Skip to content

Commit

Permalink
EvalTS (end to end type safety) (hyperbrew#53)
Browse files Browse the repository at this point in the history
* evalTS start

* getSequenceLengthInFrames added to ppro utils

* disable sourcemap temporarily

* build config working

* cleanup

* remove sourcemapping

* cleanup and add to all templates

* cleanup
  • Loading branch information
justintaylor-dev authored Feb 9, 2023
1 parent 81cc56b commit 816b546
Show file tree
Hide file tree
Showing 18 changed files with 281 additions and 2 deletions.
8 changes: 8 additions & 0 deletions cep.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ const config: CEP_Config = {
name: "PPRO",
version: "[0.0,99.9]",
},
{
name: "ILST",
version: "[0.0,99.9]",
},
{
name: "PHXS",
version: "[0.0,99.9]",
},
{
name: "FLPR",
version: "[0.0,99.9]",
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"scripts": {
"dev": "vite",
"watch": "tsc && vite build --watch true",
"build": "rimraf dist/* && tsc && vite build --watch false",
"build": "rimraf dist/* && tsc -p \"tsconfig-build.json\" && vite build --watch false",
"zxp": "rimraf dist/* && tsc && cross-env ZXP_PACKAGE=true vite build --watch false",
"zip": "rimraf dist/* && tsc && cross-env ZIP_PACKAGE=true vite build --watch false",
"serve": "cross-env SERVE_PANEL=true vite preview",
Expand All @@ -14,6 +14,7 @@
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"source-map-js": "^1.0.2",
"vue": "^3.2.45"
},
"devDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions src/js/lib/es-types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type Scripts = {
[key: string]: (a: any, ...ags: any) => any;
};
80 changes: 80 additions & 0 deletions src/js/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import CSInterface from "../lib/csinterface";
import Vulcan, { VulcanMessage } from "../lib/vulcan";
import { ns } from "../../shared/shared";
import { fs } from "./node";

export const csi = new CSInterface();
export const vulcan = new Vulcan();
Expand All @@ -13,6 +14,17 @@ export const openLinkInBrowser = (url: string) => {
}
};

/**
* @function EvalES
* Evaluates a string in ExtendScript scoped to the project's namespace
* Optionally, pass true to the isGlobal param to avoid scoping
*
* @param script The script as a string to be evaluated
* @param isGlobal Optional. Defaults to false,
*
* @return String Result.
*/

export const evalES = (script: string, isGlobal = false): Promise<string> => {
return new Promise(function (resolve, reject) {
const pre = isGlobal
Expand All @@ -28,6 +40,74 @@ export const evalES = (script: string, isGlobal = false): Promise<string> => {
});
};

import type { Scripts } from "@esTypes/index";

type ArgTypes<F extends Function> = F extends (...args: infer A) => any
? A
: never;
type ReturnType<F extends Function> = F extends (...args: infer A) => infer B
? B
: never;

/**
* @description End-to-end type-safe ExtendScript evaluation with error handling
* Call ExtendScript functions from CEP with type-safe parameters and return types.
* Any ExtendScript errors are captured and logged to the CEP console for tracing
*
* @param functionName The name of the function to be evaluated.
* @param args the list of arguments taken by the function.
*
* @example
* evalTS("helloStr", "test").then((res) => {
* // Do stuff
* });
*
* @return Promise resolving to function native return type.
*/

export const evalTS = <
Key extends string & keyof Scripts,
Func extends Function & Scripts[Key]
>(
functionName: Key,
...args: ArgTypes<Func>
): Promise<ReturnType<Func>> => {
return new Promise(function (resolve, reject) {
const formattedArgs = args.map((arg) => {
if (typeof arg === "object") {
return JSON.stringify(arg);
} else if (typeof arg == "string") {
return `"${arg}"`;
} else {
return arg;
}
});
csi.evalScript(
`try{
var host = typeof $ !== 'undefined' ? $ : window;
var res = host["${ns}"].${functionName}(${formattedArgs.join(",")});
JSON.stringify(res);
}catch(e){
e.fileName = new File(e.fileName).fsName;
JSON.stringify(e);
}`,
(res: string) => {
try {
const parsed = JSON.parse(res);
if (parsed.name === "ReferenceError") {
console.error("REFERENCE ERROR");
reject(parsed);
} else {
resolve(parsed);
}
} catch (error) {
reject(res);
}
}
);
});
};

export const evalFile = (file: string) => {
return evalES(
"typeof $ !== 'undefined' ? $.evalFile(\"" +
Expand Down
24 changes: 24 additions & 0 deletions src/js/main/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
evalFile,
openLinkInBrowser,
subscribeBackgroundColor,
evalTS,
} from "../lib/utils";

import reactLogo from "../assets/react.svg";
Expand All @@ -23,10 +24,32 @@ const Main = () => {
const [bgColor, setBgColor] = useState("#282c34");
const [count, setCount] = useState(0);

//* Demonstration of Traditional string eval-based ExtendScript Interaction
const jsxTest = () => {
console.log(evalES(`helloWorld("${csi.getApplicationID()}")`));
};

//* Demonstration of End-to-End Type-safe ExtendScript Interaction
const jsxTestTS = () => {
evalTS("helloStr", "test").then((res) => {
console.log(res);
});
evalTS("helloNum", 1000).then((res) => {
console.log(typeof res, res);
});
evalTS("helloArrayStr", ["ddddd", "aaaaaa", "zzzzzzz"]).then((res) => {
console.log(typeof res, res);
});
evalTS("helloObj", { height: 90, width: 100 }).then((res) => {
console.log(typeof res, res);
console.log(res.x);
console.log(res.y);
});
evalTS("helloError", "test").catch((e) => {
console.log("there was an error", e);
});
};

const nodeTest = () => {
alert(
`Node.js ${process.version}\nPlatform: ${
Expand Down Expand Up @@ -86,6 +109,7 @@ const Main = () => {
<button onClick={jsxTest}>
<img className="icon-button" src={adobe} />
</button>
<button onClick={jsxTestTS}>Ts</button>
</div>
<p>
Edit <code>main.tsx</code> and save to test HMR updates.
Expand Down
24 changes: 24 additions & 0 deletions src/js/template-react/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
evalFile,
openLinkInBrowser,
subscribeBackgroundColor,
evalTS,
} from "../lib/utils";

import reactLogo from "../assets/react.svg";
Expand All @@ -23,10 +24,32 @@ const Main = () => {
const [bgColor, setBgColor] = useState("#282c34");
const [count, setCount] = useState(0);

//* Demonstration of Traditional string eval-based ExtendScript Interaction
const jsxTest = () => {
console.log(evalES(`helloWorld("${csi.getApplicationID()}")`));
};

//* Demonstration of End-to-End Type-safe ExtendScript Interaction
const jsxTestTS = () => {
evalTS("helloStr", "test").then((res) => {
console.log(res);
});
evalTS("helloNum", 1000).then((res) => {
console.log(typeof res, res);
});
evalTS("helloArrayStr", ["ddddd", "aaaaaa", "zzzzzzz"]).then((res) => {
console.log(typeof res, res);
});
evalTS("helloObj", { height: 90, width: 100 }).then((res) => {
console.log(typeof res, res);
console.log(res.x);
console.log(res.y);
});
evalTS("helloError", "test").catch((e) => {
console.log("there was an error", e);
});
};

const nodeTest = () => {
alert(
`Node.js ${process.version}\nPlatform: ${
Expand Down Expand Up @@ -86,6 +109,7 @@ const Main = () => {
<button onClick={jsxTest}>
<img className="icon-button" src={adobe} />
</button>
<button onClick={jsxTestTS}>Ts</button>
</div>
<p>
Edit <code>main.tsx</code> and save to test HMR updates.
Expand Down
24 changes: 24 additions & 0 deletions src/js/template-svelte/main.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
csi,
evalES,
evalFile,
evalTS,
openLinkInBrowser,
subscribeBackgroundColor,
} from "../lib/utils";
Expand All @@ -24,10 +25,32 @@
let count: number = 0;
let backgroundColor: string = "#282c34";
//* Demonstration of Traditional string eval-based ExtendScript Interaction
const jsxTest = () => {
console.log(evalES(`helloWorld("${csi.getApplicationID()}")`));
};
//* Demonstration of End-to-End Type-safe ExtendScript Interaction
const jsxTestTS = () => {
evalTS("helloStr", "test").then((res) => {
console.log(res);
});
evalTS("helloNum", 1000).then((res) => {
console.log(typeof res, res);
});
evalTS("helloArrayStr", ["ddddd", "aaaaaa", "zzzzzzz"]).then((res) => {
console.log(typeof res, res);
});
evalTS("helloObj", { height: 90, width: 100 }).then((res) => {
console.log(typeof res, res);
console.log(res.x);
console.log(res.y);
});
evalTS("helloError", "test").catch((e) => {
console.log("there was an error", e);
});
};
const nodeTest = () => {
alert(
`Node.js ${process.version}\nPlatform: ${
Expand Down Expand Up @@ -85,6 +108,7 @@
<button on:click={jsxTest}>
<img class="icon-button" src={adobe} alt="" />
</button>
<button on:click={jsxTestTS}>Ts</button>
</div>

<p>Edit <code>main.svelte</code> and save to test HMR updates.</p>
Expand Down
24 changes: 24 additions & 0 deletions src/js/template-vue/main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
csi,
evalES,
evalFile,
evalTS,
openLinkInBrowser,
subscribeBackgroundColor,
} from "../lib/utils";
Expand All @@ -13,10 +14,32 @@ import "../index.scss";
const count = ref(0);
const backgroundColor = ref("#282c34");
//* Demonstration of Traditional string eval-based ExtendScript Interaction
const jsxTest = () => {
console.log(evalES(`helloWorld("${csi.getApplicationID()}")`));
};
//* Demonstration of End-to-End Type-safe ExtendScript Interaction
const jsxTestTS = () => {
evalTS("helloStr", "test").then((res) => {
console.log(res);
});
evalTS("helloNum", 1000).then((res) => {
console.log(typeof res, res);
});
evalTS("helloArrayStr", ["ddddd", "aaaaaa", "zzzzzzz"]).then((res) => {
console.log(typeof res, res);
});
evalTS("helloObj", { height: 90, width: 100 }).then((res) => {
console.log(typeof res, res);
console.log(res.x);
console.log(res.y);
});
evalTS("helloError", "test").catch((e) => {
console.log("there was an error", e);
});
};
const nodeTest = () => {
alert(
`Node.js ${process.version}\nPlatform: ${
Expand Down Expand Up @@ -74,6 +97,7 @@ onMounted(() => {
<button @click="jsxTest">
<img class="icon-button" src="../assets/adobe.svg" />
</button>
<button @click="jsxTestTS">Ts</button>
</div>

<p>Edit <code>main.vue</code> and save to test HMR updates.</p>
Expand Down
9 changes: 9 additions & 0 deletions src/jsx/aeft/aeft.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import {
helloError,
helloStr,
helloNum,
helloArrayStr,
helloObj,
} from "../utils/samples";
export { helloError, helloStr, helloNum, helloArrayStr, helloObj };

export const helloWorld = () => {
alert("Hello from After Effects!");
app.project.activeItem;
Expand Down
9 changes: 9 additions & 0 deletions src/jsx/ilst/ilst.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import {
helloError,
helloStr,
helloNum,
helloArrayStr,
helloObj,
} from "../utils/samples";
export { helloError, helloStr, helloNum, helloArrayStr, helloObj };

export const helloWorld = () => {
alert("Hello from Illustrator");
app.activeDocument.path;
Expand Down
6 changes: 6 additions & 0 deletions src/jsx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ switch (BridgeTalk.appName) {
//@ts-ignore
const host = typeof $ !== "undefined" ? $ : window;
host[ns] = main;

export type Scripts = typeof aeft &
typeof ilst &
typeof anim &
typeof ppro &
typeof phxs;
9 changes: 9 additions & 0 deletions src/jsx/phxs/phxs.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import {
helloError,
helloStr,
helloNum,
helloArrayStr,
helloObj,
} from "../utils/samples";
export { helloError, helloStr, helloNum, helloArrayStr, helloObj };

export const helloWorld = () => {
app.activeDocument;
alert("Hello from Photoshop");
Expand Down
8 changes: 8 additions & 0 deletions src/jsx/ppro/ppro-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ export const deleteItem = (item: ProjectItem) => {
tmpBin.deleteBin();
}
};

export const getSequenceLengthInFrames = (seq: Sequence) => {
const settings = seq.getSettings();
const end = seq.end;
const fps = settings.videoFrameRate.ticks;
const frames = parseInt(end) / parseInt(fps);
return frames;
};
Loading

0 comments on commit 816b546

Please sign in to comment.