afterpresets 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +20 -2
  3. package/bin/ap.js +2 -0
  4. package/package.json +39 -4
  5. package/runtime/docs/cep/host-after-effects.md +57 -0
  6. package/runtime/docs/cep/host-premiere.md +84 -0
  7. package/runtime/docs/cep/host.md +128 -0
  8. package/runtime/docs/common/README.md +65 -0
  9. package/runtime/docs/common/assets.md +88 -0
  10. package/runtime/docs/common/boot.md +103 -0
  11. package/runtime/docs/common/licensing.md +261 -0
  12. package/runtime/docs/common/panels.md +114 -0
  13. package/runtime/docs/common/storage.md +82 -0
  14. package/runtime/docs/common/updates.md +251 -0
  15. package/runtime/package.json +5 -0
  16. package/runtime/runtime-files.json +14 -0
  17. package/runtime/src/boot.js +1 -0
  18. package/runtime/src/computer-id.js +1 -0
  19. package/runtime/src/core.js +1 -0
  20. package/runtime/src/events.js +1 -0
  21. package/runtime/src/host.js +1 -0
  22. package/runtime/src/license.js +1 -0
  23. package/runtime/src/panels.js +1 -0
  24. package/runtime/src/storage.js +1 -0
  25. package/runtime/src/updates.js +1 -0
  26. package/runtime/src/vendor/CSInterface.js +1 -0
  27. package/runtime/src/vendor/json2.jsx +506 -0
  28. package/runtime/src/zip.js +1 -0
  29. package/src/api/client.js +1 -0
  30. package/src/api/error-messages.js +1 -0
  31. package/src/api/session.js +1 -0
  32. package/src/args.js +1 -0
  33. package/src/auth/credentials.js +2 -0
  34. package/src/auth/logout.js +1 -0
  35. package/src/build/assets.js +1 -0
  36. package/src/build/build.js +9 -0
  37. package/src/build/bundle.js +5 -0
  38. package/src/build/html.js +4 -0
  39. package/src/build/jsx.js +3 -0
  40. package/src/build/jsxbin.js +1 -0
  41. package/src/build/runtime.js +4 -0
  42. package/src/check/check.js +3 -0
  43. package/src/check/extendscript-globals.d.ts +6 -0
  44. package/src/check/pricing.js +1 -0
  45. package/src/check/types.js +3 -0
  46. package/src/cli.js +5 -0
  47. package/src/commands/add.js +11 -0
  48. package/src/commands/build.js +6 -0
  49. package/src/commands/check.js +13 -0
  50. package/src/commands/config.js +7 -0
  51. package/src/commands/dev.js +6 -0
  52. package/src/commands/docs.js +1 -0
  53. package/src/commands/init.js +12 -0
  54. package/src/commands/login.js +3 -0
  55. package/src/commands/logout.js +1 -0
  56. package/src/commands/mcp.js +7 -0
  57. package/src/commands/push.js +7 -0
  58. package/src/commands/releases.js +5 -0
  59. package/src/commands/testers.js +1 -0
  60. package/src/commands/upgrade.js +2 -0
  61. package/src/commands/whoami.js +1 -0
  62. package/src/config.js +1 -0
  63. package/src/context.js +1 -0
  64. package/src/dev/cep-link.js +1 -0
  65. package/src/dev/debug-file.js +10 -0
  66. package/src/dev/debug-mode.js +1 -0
  67. package/src/dev/session.js +4 -0
  68. package/src/errors.js +1 -0
  69. package/src/mcp/capture.js +1 -0
  70. package/src/mcp/extendscript.js +9 -0
  71. package/src/mcp/panels.js +1 -0
  72. package/src/mcp/protocol.js +4 -0
  73. package/src/mcp/redact.js +1 -0
  74. package/src/mcp/server.js +2 -0
  75. package/src/mcp/snapshot.js +2 -0
  76. package/src/mcp/tools/account.js +3 -0
  77. package/src/mcp/tools/host.js +1 -0
  78. package/src/mcp/tools/panel.js +7 -0
  79. package/src/mcp/tools/project.js +40 -0
  80. package/src/mcp/tools/releases.js +29 -0
  81. package/src/output.js +6 -0
  82. package/src/project/add-panel.js +11 -0
  83. package/src/project/docs.js +3 -0
  84. package/src/project/manifest.js +6 -0
  85. package/src/project/panels.js +1 -0
  86. package/src/project/project.js +2 -0
  87. package/src/project/semver.js +1 -0
  88. package/src/project/template.js +4 -0
  89. package/src/prompt.js +1 -0
  90. package/src/release/installers.js +4 -0
  91. package/src/release/package.js +1 -0
  92. package/src/release/publish.js +1 -0
  93. package/src/system/run-command.js +1 -0
  94. package/src/system/update-check.js +2 -0
  95. package/src/targets.js +1 -0
  96. package/src/user-config.js +2 -0
  97. package/template/cep/.mcp.json +8 -0
  98. package/template/cep/AGENTS.md +169 -0
  99. package/template/cep/README.md +78 -0
  100. package/template/cep/docs/initial_setup.md +69 -0
  101. package/template/cep/gitignore +12 -0
  102. package/template/cep/package.json +14 -0
  103. package/template/cep/src/features/home/home.css +67 -0
  104. package/template/cep/src/features/home/home.html +23 -0
  105. package/template/cep/src/features/home/home.js +40 -0
  106. package/template/cep/src/features/license-screen/license-screen.css +80 -0
  107. package/template/cep/src/features/license-screen/license-screen.html +72 -0
  108. package/template/cep/src/features/license-screen/license-screen.js +60 -0
  109. package/template/cep/src/features/update-screen/update-screen.css +173 -0
  110. package/template/cep/src/features/update-screen/update-screen.html +57 -0
  111. package/template/cep/src/features/update-screen/update-screen.js +196 -0
  112. package/template/cep/src/panels/main/index.html +21 -0
  113. package/template/cep/src/panels/main/main.js +39 -0
  114. package/template/cep/src/shared/lib/dom.js +29 -0
  115. package/template/cep/src/shared/lib/host-theme.js +17 -0
  116. package/template/cep/src/shared/lib/markdown.js +109 -0
  117. package/template/cep/src/shared/lib/view.js +82 -0
  118. package/template/cep/src/shared/ui/base.css +60 -0
  119. package/template/cep/src/shared/ui/button.css +61 -0
  120. package/template/cep/src/shared/ui/card.css +22 -0
  121. package/template/cep/src/shared/ui/field.css +25 -0
  122. package/template/cep/src/shared/ui/index.css +7 -0
  123. package/template/cep/src/shared/ui/tokens.css +21 -0
  124. package/template/hosts/aeft/AGENTS.host.md +10 -0
  125. package/template/hosts/aeft/jsx/aeft/home.jsx +16 -0
  126. package/template/hosts/ppro/AGENTS.host.md +15 -0
  127. package/template/hosts/ppro/jsx/ppro/home.jsx +20 -0
  128. package/vendor/afterpresets-additions/AfterEffects.d.ts +291 -0
  129. package/vendor/afterpresets-additions/Premiere.d.ts +179 -0
  130. package/vendor/types-for-adobe/AfterEffects/26.0/index.d.ts +3403 -0
  131. package/vendor/types-for-adobe/LICENSE.md +21 -0
  132. package/vendor/types-for-adobe/Premiere/24.0/index.d.ts +2567 -0
  133. package/vendor/types-for-adobe/README.md +13 -0
  134. package/vendor/types-for-adobe/shared/JavaScript.d.ts +2761 -0
  135. package/vendor/types-for-adobe/shared/PlugPlugExternalObject.d.ts +91 -0
  136. package/vendor/types-for-adobe/shared/ScriptUI.d.ts +3012 -0
  137. package/vendor/types-for-adobe/shared/XMPScript.d.ts +72 -0
  138. package/vendor/types-for-adobe/shared/global.d.ts +152 -0
package/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ AfterPresets CLI and Runtime License
2
+
3
+ Copyright (c) AfterPresets. All rights reserved.
4
+
5
+ This package ("the Software") contains the AfterPresets command-line tool and
6
+ the AfterPresets runtime.
7
+
8
+ You may install and use the Software only to create, test, build and publish
9
+ Adobe After Effects extensions that are distributed through AfterPresets
10
+ (afterpresets.com), and you may include the runtime in those extensions as
11
+ the Software's build process does.
12
+
13
+ You may not, except as the law expressly allows:
14
+ - modify, decompile, deobfuscate or reverse engineer the runtime, or remove,
15
+ disable or work around its licensing, signing or update checks;
16
+ - copy or redistribute the Software, or the runtime outside an extension
17
+ built with the Software;
18
+ - use the Software to build or distribute extensions outside AfterPresets.
19
+
20
+ Use of AfterPresets services is also governed by the AfterPresets Terms of
21
+ Service at https://afterpresets.com.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED. IN NO EVENT SHALL AFTERPRESETS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25
+ OTHER LIABILITY ARISING FROM THE SOFTWARE OR ITS USE.
package/README.md CHANGED
@@ -1,3 +1,21 @@
1
- # Temporary Holding Version
1
+ # AfterPresets CLI
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Make Adobe After Effects extensions with an AI agent, and sell them on
4
+ [AfterPresets](https://afterpresets.com) with licensing, signed auto-updates
5
+ and checkout handled.
6
+
7
+ You do not need to write code. Open an empty folder in your agent (the Code
8
+ tab of the Claude desktop app, Claude Code, Codex, Cursor...) and follow the
9
+ **[Quickstart](https://docs.afterpresets.com/get-started/quickstart/)**.
10
+
11
+ ```sh
12
+ npx afterpresets login
13
+ npx afterpresets init my-extension
14
+ ```
15
+
16
+ Inside a project, `ap dev` puts the extension into After Effects and reloads
17
+ it on every save, `ap push` publishes a release, and `ap upgrade` updates
18
+ this package. Every project includes `AGENTS.md` and an MCP server
19
+ (`ap mcp`) so your agent can see, click and test the live panel.
20
+
21
+ Docs: https://docs.afterpresets.com
package/bin/ap.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ "use strict";const{main:r}=require("../src/cli"),{createContext:s}=require("../src/context");r(process.argv.slice(2),s()).then(e=>{process.exitCode=e});
package/package.json CHANGED
@@ -1,6 +1,41 @@
1
1
  {
2
2
  "name": "afterpresets",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Create, develop, and publish Adobe CEP extensions on AfterPresets.",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "homepage": "https://docs.afterpresets.com",
7
+ "keywords": [
8
+ "after effects",
9
+ "adobe",
10
+ "cep",
11
+ "extension",
12
+ "afterpresets",
13
+ "mcp"
14
+ ],
15
+ "bin": {
16
+ "ap": "bin/ap.js",
17
+ "afterpresets": "bin/ap.js"
18
+ },
19
+ "files": [
20
+ "bin",
21
+ "src",
22
+ "runtime",
23
+ "template",
24
+ "vendor",
25
+ "LICENSE"
26
+ ],
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
30
+ "dependencies": {
31
+ "adm-zip": "0.5.16",
32
+ "chokidar": "3.6.0",
33
+ "esbuild": "0.25.12",
34
+ "jsxbin": "2.3.0",
35
+ "playwright-core": "1.64.1",
36
+ "typescript": "5.9.3"
37
+ },
38
+ "afterpresets": {
39
+ "runtimeVersion": "0.4.0"
40
+ }
41
+ }
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: After Effects ExtendScript
3
+ description: "Rules for ExtendScript in After Effects (jsx/aeft/): undo groups, the active composition, 1-based collections, and the version range."
4
+ ---
5
+
6
+ # After Effects ExtendScript
7
+
8
+ Read [host.md](host.md) first: it explains `AP.host.eval` and how `jsx/` is
9
+ loaded. This page is about code that runs in After Effects. Put code that only
10
+ makes sense in After Effects in `jsx/aeft/`.
11
+
12
+ ## Undo
13
+
14
+ Wrap every change in one undo group so the user undoes the whole action with
15
+ one Ctrl/Cmd+Z, and close it in `finally`:
16
+
17
+ ```js
18
+ app.beginUndoGroup("Rename layers");
19
+ try {
20
+ /* changes */
21
+ } finally {
22
+ app.endUndoGroup();
23
+ }
24
+ ```
25
+
26
+ The MCP `host_eval` tool already wraps each call in an undo group named
27
+ "AfterPresets MCP".
28
+
29
+ ## The active composition
30
+
31
+ `app.project.activeItem` is often null or not a composition (a footage item, a
32
+ folder, or nothing selected). Check before using it:
33
+
34
+ ```js
35
+ var comp = app.project.activeItem;
36
+ if (!comp || !(comp instanceof CompItem)) {
37
+ return JSON.stringify({ ok: false, message: "Open or select a composition first." });
38
+ }
39
+ ```
40
+
41
+ ## Collections and times
42
+
43
+ - Collections are 1-based: `comp.layer(1)`, `app.project.item(1)`,
44
+ `comp.selectedLayers[0]` (a plain array, 0-based).
45
+ - Times are seconds (floating point). `comp.frameDuration` is one frame.
46
+
47
+ ## Versions
48
+
49
+ The extension's range is `hosts[].minVersion` in afterpresets.json (default
50
+ 17.0, After Effects 2020). Check `parseFloat(app.version)` before using newer
51
+ APIs and return `{ ok: false, message }` when they are missing.
52
+
53
+ ## Type hints
54
+
55
+ `ap check --types` checks `jsx/` against the After Effects 26.0 declarations
56
+ from types-for-adobe and lists likely mistakes. Hints can be wrong; confirm
57
+ with the MCP `host_eval` tool before changing working code.
@@ -0,0 +1,84 @@
1
+ ---
2
+ title: Premiere Pro ExtendScript
3
+ description: "Rules for ExtendScript in Premiere Pro (jsx/ppro/): no undo groups, times in ticks, 0-based track and clip collections, no QE DOM, and the version range."
4
+ ---
5
+
6
+ # Premiere Pro ExtendScript
7
+
8
+ Read [host.md](host.md) first: it explains `AP.host.eval` and how `jsx/` is
9
+ loaded. This page is about code that runs in Premiere Pro. Put code that only
10
+ makes sense in Premiere Pro in `jsx/ppro/`.
11
+
12
+ ## No undo groups
13
+
14
+ Premiere Pro's ExtendScript has no `beginUndoGroup`. Every change a script
15
+ makes (a clip moved, a marker added, a property set) is its own step in
16
+ Edit → Undo. Keep scripted edits small, do the checks before the first change,
17
+ and tell the user how many undo steps an action adds. The MCP `host_eval`
18
+ tool cannot group them either.
19
+
20
+ ## The active sequence
21
+
22
+ `app.project.activeSequence` is null when no sequence is open. Check it:
23
+
24
+ ```js
25
+ function myTool_sequenceInfo() {
26
+ var sequence = app.project.activeSequence;
27
+ if (!sequence) return JSON.stringify({ ok: false, message: "Open a sequence first." });
28
+ var clips = 0;
29
+ for (var i = 0; i < sequence.videoTracks.numTracks; i++) {
30
+ clips += sequence.videoTracks[i].clips.numItems;
31
+ }
32
+ return JSON.stringify({ ok: true, name: sequence.name, videoClips: clips });
33
+ }
34
+ ```
35
+
36
+ ## Collections
37
+
38
+ Tracks, clips, sequences and project items are 0-based collections with a
39
+ count property: `sequence.videoTracks[0]` with `numTracks`,
40
+ `track.clips[0]` with `numItems`, `app.project.sequences[0]` with
41
+ `numSequences`, `app.project.rootItem.children[0]` with `numItems`. Use a
42
+ `for` loop; they are not arrays.
43
+
44
+ ## Times are ticks
45
+
46
+ Premiere measures time in ticks: **254016000000 ticks per second**. A `Time`
47
+ object has `.seconds` (a number) and `.ticks` (a string). Create one with
48
+ `new Time()` and set either:
49
+
50
+ ```js
51
+ var t = new Time();
52
+ t.seconds = 2.5;
53
+ app.project.activeSequence.setPlayerPosition(t.ticks); // move the playhead to 2.5 s
54
+ var startSeconds = clip.start.seconds; // read a clip's start
55
+ ```
56
+
57
+ Frame-accurate maths: convert with the sequence's timebase
58
+ (`sequence.timebase`, ticks per frame, a string) instead of rounding seconds.
59
+
60
+ ## Things not to use
61
+
62
+ - **The QE DOM** (`app.enableQE()`, `qe.*`): undocumented, unsupported, and
63
+ it changes between versions. Do not ship code that needs it.
64
+ - Dialogs (`alert`, `confirm`, `File.openDialog`) block Premiere Pro while
65
+ open; the panel can show its own UI instead.
66
+
67
+ ## Projects
68
+
69
+ - `app.project` is the active project. Premiere Pro can have several projects
70
+ open (`app.projects`, `numProjects`).
71
+ - Save with `app.project.save()`. The MCP `host_scratch_project` tool creates a
72
+ new project in the temp folder and leaves the user's project open.
73
+
74
+ ## Versions
75
+
76
+ The extension's range is `hosts[].minVersion` in afterpresets.json (default
77
+ 14.0, Premiere Pro 2020). Check `app.version` before using newer APIs and
78
+ return `{ ok: false, message }` when they are missing.
79
+
80
+ ## Type hints
81
+
82
+ `ap check --types` checks `jsx/` against the Premiere Pro 24.0 declarations
83
+ from types-for-adobe (the newest set; newer APIs may be missing) and lists
84
+ likely mistakes. Hints can be wrong; confirm with the MCP `host_eval` tool.
@@ -0,0 +1,128 @@
1
+ ---
2
+ title: Calling the app (ExtendScript)
3
+ description: Call ExtendScript functions in After Effects or Premiere Pro from a panel with AP.host.eval, write jsx/ functions in ES3 that return JSON, keep app-only code in jsx/aeft/ and jsx/ppro/, and handle host errors.
4
+ ---
5
+
6
+ # Calling the app (ExtendScript)
7
+
8
+ Panel code runs in a browser. Anything that touches the app (the project, its
9
+ compositions or sequences, layers or clips, files through `File`/`Folder`) runs
10
+ in ExtendScript, in `jsx/`. `AP.host.eval` connects the two. It works the same
11
+ in After Effects and Premiere Pro. What you can do in each app:
12
+
13
+ - [host-after-effects.md](host-after-effects.md): After Effects
14
+ - [host-premiere.md](host-premiere.md): Premiere Pro
15
+
16
+ ## Where JSX lives
17
+
18
+ Put ExtendScript in `jsx/`, one file per feature (for example
19
+ `jsx/layers.jsx`; subfolders are fine). Every `.jsx` file there is loaded into
20
+ the app once, before your app starts, and its functions are shared by
21
+ all panels. Call one from panel code with `ctx.host.eval("fnName", [args], cb)`.
22
+
23
+ Two folders are special (afterpresets.json `hosts` lists the apps):
24
+
25
+ | Folder | Loaded in |
26
+ |---|---|
27
+ | `jsx/aeft/` | After Effects only |
28
+ | `jsx/ppro/` | Premiere Pro only |
29
+ | everything else in `jsx/` | every app the extension targets |
30
+
31
+ An extension for both apps can define the same function in `jsx/aeft/` and
32
+ `jsx/ppro/` (for example `myTool_activeItemName`) and call it from shared panel
33
+ code; each app loads its own version. `ap check` warns about a folder for an
34
+ app the project does not target.
35
+
36
+ - There is no list to keep: the CLI joins every `.jsx` file in alphabetical
37
+ path order, with JSON support (json2) first, embeds the result in every
38
+ panel's `main.js` (readable in `ap dev`, compiled to JSXBIN for releases),
39
+ and the runtime evaluates it as soon as `AP.boot` runs, before `start`.
40
+ Every `AP.host.eval` waits for that load.
41
+ - Order only matters for code that runs at the top level of a file while it
42
+ loads (not inside a function). Keep files to function declarations.
43
+
44
+ ## Writing a JSX function
45
+
46
+ ExtendScript is **ES3**: `var` only, no `let`/`const`, no arrow functions, no
47
+ `Array.prototype.forEach`/`map`/`indexOf`, no `trim()`, no template strings.
48
+ `JSON` is always available (the CLI adds json2).
49
+
50
+ Rules:
51
+
52
+ 1. Declare a named top-level function. Avoid generic names; prefix them
53
+ (`myTool_addNull`), because every extension shares one ExtendScript engine.
54
+ 2. Take JSON-compatible arguments (strings, numbers, booleans, arrays, plain
55
+ objects).
56
+ 3. Return `JSON.stringify(...)`. Return a result object such as `{ ok: true, ... }`
57
+ or `{ ok: false, message: "..." }` for expected problems.
58
+ 4. Undo: in After Effects wrap changes in one undo group; Premiere Pro has
59
+ none (every change is its own undo step). See the app pages.
60
+
61
+ ```js
62
+ /* jsx/aeft/layers.jsx (After Effects) */
63
+ function myTool_addNull(name) {
64
+ var comp = app.project.activeItem;
65
+ if (!comp || !(comp instanceof CompItem)) {
66
+ return JSON.stringify({ ok: false, message: "Select a composition first." });
67
+ }
68
+ app.beginUndoGroup("Add null");
69
+ try {
70
+ var layer = comp.layers.addNull();
71
+ layer.name = name;
72
+ return JSON.stringify({ ok: true, index: layer.index });
73
+ } finally {
74
+ app.endUndoGroup();
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Calling it from the panel
80
+
81
+ ```js
82
+ AP.host.eval("myTool_addNull", ["Controller"], function (result) {
83
+ if (!result || result.error) {
84
+ showError(result ? result.error : "No answer from the app.");
85
+ return;
86
+ }
87
+ if (!result.ok) {
88
+ showMessage(result.message);
89
+ return;
90
+ }
91
+ showMessage("Added layer " + result.index);
92
+ });
93
+ ```
94
+
95
+ `AP.host.eval(fnName, args, cb)`:
96
+
97
+ - `fnName` is a function name or dotted path (`"myTool.addNull"`). Anything else
98
+ is refused with `{ error }`.
99
+ - `args` is an array. Each value is passed as a JSON literal, so quotes,
100
+ newlines, and code in strings are safe. `undefined` becomes `null`.
101
+ - `cb(result)` receives the parsed JSON your function returned, `null` when it
102
+ returned nothing, or `{ error: "message" }` when anything failed.
103
+
104
+ Never build ExtendScript source by joining strings with user input. Always pass
105
+ values through `args`.
106
+
107
+ ## Errors
108
+
109
+ | `result` | Cause |
110
+ |---|---|
111
+ | `{ error: "<message>" }` | Your function threw; the message is the thrown error's message. |
112
+ | `{ error: "...is undefined" }` or similar | The function does not exist: check the name, that its file is in `jsx/` and ends in `.jsx`, and that it is not in another app's folder (`jsx/aeft/`, `jsx/ppro/`). |
113
+ | `{ error: "The host returned a non-JSON result.", raw }` | Your function returned a plain string. Return `JSON.stringify(...)`. |
114
+ | `{ error: "The host script failed to run." }` | ExtendScript syntax error or an ES5+ feature in `jsx/`. |
115
+ | `{ error: "Could not load host script: ..." }` | The embedded JSX failed to load. Read the message; usually a syntax error. "This extension has no host script for X" means the build has no code for the running app (afterpresets.json `hosts`). |
116
+
117
+ The JSX loads once per page. During `ap dev` every save rebuilds and reloads
118
+ the open panels, which loads the new JSX too; after an update,
119
+ `AP.updates.reload()` does the same. The new functions replace the old ones.
120
+ Functions removed from the new code stay defined in the app until it
121
+ restarts, so never rely on a function being absent.
122
+
123
+ ## Testing
124
+
125
+ Call the function from the live panel and check the result and the project
126
+ state. Use a disposable project (the MCP `host_scratch_project` tool) for
127
+ anything that changes the project. With the MCP tools, `host_eval` runs in the
128
+ app that runs the connected panel.
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: AfterPresets runtime reference
3
+ description: What the AfterPresets runtime does, and which reference file to read before you use any AP.* API.
4
+ ---
5
+
6
+ # AfterPresets runtime reference
7
+
8
+ These files are for the AI coding agent that builds an After Effects or Premiere
9
+ Pro extension with AfterPresets. They describe the `AP.*` API that every panel gets.
10
+
11
+ ## What the runtime does
12
+
13
+ The runtime is a small script that the AfterPresets CLI puts in front of each
14
+ panel's JavaScript. It is logic only. It draws nothing: your project owns every
15
+ screen, style, and word the user sees.
16
+
17
+ It gives you:
18
+
19
+ - `AP.boot` to start the panel.
20
+ - Licensing, off by default. Paid extensions must turn it on.
21
+ - Signed updates with changelogs.
22
+ - `AP.host.eval` to call ExtendScript functions in the app (After Effects or Premiere Pro).
23
+ - `AP.panels` and `AP.events` for extensions with more than one panel.
24
+ - `AP.paths` to find the images, videos and other files you ship.
25
+ - `AP.storage` to save settings and other small data on this computer.
26
+
27
+ Do not edit the runtime and do not copy it into your source files. The CLI
28
+ adds it for you. `ap docs` refreshes this folder from the installed runtime.
29
+
30
+ ## The rule
31
+
32
+ **Read the relevant file below before you write or change code that uses
33
+ `AP.*`.** Do not guess option names, statuses, or callback shapes. If a file
34
+ and your memory disagree, the file wins.
35
+
36
+ ## Files
37
+
38
+ | File | Read it before you |
39
+ |---|---|
40
+ | [boot.md](boot.md) | call `AP.boot`, use `ctx`, or change when the app starts |
41
+ | [licensing.md](licensing.md) | turn licensing on, write `renderLicense`, or change the license screen |
42
+ | [updates.md](updates.md) | change update options or the update screen, or show a changelog |
43
+ | [host.md](host.md) | call the app from the panel or write `jsx/` code |
44
+ | [host-after-effects.md](host-after-effects.md) | write ExtendScript for After Effects (`jsx/aeft/`) |
45
+ | [host-premiere.md](host-premiere.md) | write ExtendScript for Premiere Pro (`jsx/ppro/`) |
46
+ | [panels.md](panels.md) | add a panel or modal, open/close panels, or send data between panels |
47
+ | [assets.md](assets.md) | add images, fonts, videos or other files, or import a file into the app |
48
+ | [storage.md](storage.md) | save settings, recent items or any other data between launches |
49
+
50
+ ## Commands you will use
51
+
52
+ ```sh
53
+ ap dev # build, link into the app, rebuild on change
54
+ ap check # static checks; also run by ap dev and ap push
55
+ ap add panel settings --type modal
56
+ ap push # publish a release (asks for version bump and changelog)
57
+ ap docs # refresh docs/afterpresets/ from the runtime
58
+ ```
59
+
60
+ ## Compatibility
61
+
62
+ Panels run in Adobe CEP 10 or later (After Effects 2020+, Premiere Pro 2020+). Its browser is old
63
+ (Chromium 74 in CEP 10). Write plain ES5 in panel code: `var`, `function`, no
64
+ arrow functions, no `let`/`const`, no `class`, no template strings, no
65
+ `fetch`-only features. ExtendScript in `jsx/` is ES3 (see [host.md](host.md)).
@@ -0,0 +1,88 @@
1
+ ---
2
+ title: Media and other files
3
+ description: Where to put images, fonts, videos, presets and other files your extension ships, and how to use them from HTML, CSS, JavaScript and ExtendScript.
4
+ ---
5
+
6
+ # Media and other files
7
+
8
+ Put files your extension ships in these folders at the **project root**
9
+ (next to `afterpresets.json`):
10
+
11
+ ```
12
+ assets/ fonts/ icons/ images/ media/
13
+ ```
14
+
15
+ They are copied into the build unchanged, at the same place: `media/intro.mp4`
16
+ in the project is `media/intro.mp4` inside the installed extension. Other
17
+ folders are not shipped. To choose your own list, set it in
18
+ `afterpresets.json` (this replaces the defaults):
19
+
20
+ ```json
21
+ "assets": ["media", "presets", "fonts"]
22
+ ```
23
+
24
+ These files are **not** obfuscated or hidden. Anything the buyer installs, they
25
+ can open. Keep secrets out of them. The whole release must stay under 200 MB.
26
+
27
+ ## From HTML and CSS
28
+
29
+ Write paths relative to the file you are in, as usual. They must point into
30
+ an asset folder; the build rewrites them for the installed extension and fails
31
+ on a missing file.
32
+
33
+ ```html
34
+ <!-- src/panels/main/index.html -->
35
+ <img src="../../../images/logo.png" alt="">
36
+ ```
37
+
38
+ ```css
39
+ /* src/features/home/home.css */
40
+ .hero { background-image: url(../../../images/hero.jpg); }
41
+ @font-face { font-family: "Brand"; src: url(../../../fonts/Brand.woff2); }
42
+ ```
43
+
44
+ ## From JavaScript
45
+
46
+ Use `AP.paths`; never build paths by hand.
47
+
48
+ | Call | Returns |
49
+ |---|---|
50
+ | `AP.paths.asset("media/intro.mp4")` | Absolute path of a shipped file. Relative path with `/`; `..` and absolute paths throw. |
51
+ | `AP.paths.extension()` | Absolute path of the installed extension folder. |
52
+ | `AP.paths.data()` | A writable folder for your own files. It survives updates. Never write into the extension folder: updates replace it. For settings use `AP.storage`; see [storage.md](storage.md). |
53
+
54
+ ## From ExtendScript (importing into the app)
55
+
56
+ ExtendScript cannot see the panel's folders by itself. Pass the absolute path
57
+ from the panel:
58
+
59
+ ```js
60
+ // panel
61
+ ctx.host.eval("importClip", [AP.paths.asset("media/intro.mp4")], function (result) {
62
+ if (result && result.error) { /* show result.error */ }
63
+ });
64
+ ```
65
+
66
+ ```js
67
+ // After Effects: jsx/aeft/media.jsx (loaded automatically, like every .jsx file in jsx/)
68
+ function importClip(path) {
69
+ var file = new File(path);
70
+ if (!file.exists) return JSON.stringify({ error: "Missing file: " + path });
71
+ var item = app.project.importFile(new ImportOptions(file));
72
+ return JSON.stringify({ ok: true, name: item.name });
73
+ }
74
+ ```
75
+
76
+ ```js
77
+ // Premiere Pro: jsx/ppro/media.jsx
78
+ function importClip(path) {
79
+ var file = new File(path);
80
+ if (!file.exists) return JSON.stringify({ error: "Missing file: " + path });
81
+ // importFiles(paths, suppressUI, targetBin, importAsNumberedStills)
82
+ var ok = app.project.importFiles([file.fsName], true, app.project.getInsertionBin(), false);
83
+ return JSON.stringify({ ok: ok === true, name: file.name });
84
+ }
85
+ ```
86
+
87
+ Both files define the same function name: an extension for both apps calls
88
+ `importClip` and each app loads its own version.
@@ -0,0 +1,103 @@
1
+ ---
2
+ title: AP.boot
3
+ description: Start a panel with AP.boot. Options, the ctx object passed to start, and the boot lifecycle.
4
+ ---
5
+
6
+ # AP.boot
7
+
8
+ Every panel calls `AP.boot` exactly once, from its `src/panels/<id>/main.js`
9
+ code. `ap check` fails when a panel never calls it.
10
+
11
+ ```js
12
+ AP.boot({
13
+ start: function (ctx) {
14
+ // Build your UI here.
15
+ },
16
+ license: false, // default. true, or { offlineGraceDays, checkInBackground }
17
+ renderLicense: function (api, root) {}, // required when license is on
18
+ updates: { check: "auto", mode: "background" } // defaults
19
+ });
20
+ ```
21
+
22
+ ## Options
23
+
24
+ | Option | Type | Default | Meaning |
25
+ |---|---|---|---|
26
+ | `start` | `function (ctx)` | required | Your app. Called once, when the panel may run. |
27
+ | `license` | `false`, `true`, or `{ offlineGraceDays, checkInBackground }` | `false` | Turns licensing on. See [licensing.md](licensing.md). |
28
+ | `renderLicense` | `function (api, root)` | none | Draws the license screen. Required when `license` is on. |
29
+ | `updates.check` | `"auto"` or `"manual"` | `"auto"` | `"auto"` checks at start and every 6 hours. See [updates.md](updates.md). |
30
+ | `updates.mode` | `"background"`, `"prompt"` or `"silent"` | `"background"` | What happens when an update is found. `"background"` installs it without asking, then your update screen offers **Reload now** (`AP.updates.reload()`). `"prompt"` waits for your Install button. `"silent"` installs and shows nothing. See [updates.md](updates.md). |
31
+
32
+ Unknown values are replaced by the default with a console warning. If
33
+ `license` is on and `renderLicense` is missing, `AP.boot` logs an error and
34
+ throws; the panel stays empty.
35
+
36
+ ## ctx
37
+
38
+ `start(ctx)` receives:
39
+
40
+ ```js
41
+ ctx = {
42
+ product: { bundleId: "com.afterpresets.seller.tool", version: "1.2.0" },
43
+ panel: { id: "main" }, // this panel's id from afterpresets.json
44
+ license: AP.license, // license api; status is "disabled" when licensing is off
45
+ updates: AP.updates, // see updates.md
46
+ host: AP.host // see host.md
47
+ };
48
+ ```
49
+
50
+ The same objects are also available as globals (`AP.license`, `AP.updates`,
51
+ `AP.host`, `AP.panels`, `AP.events`) for code that runs outside `start`.
52
+
53
+ ## Lifecycle
54
+
55
+ 1. The page loads. The runtime is already defined; nothing has run yet.
56
+ 2. Your entry code calls `AP.boot(options)`.
57
+ 3. When the DOM is ready:
58
+ - **License off:** `AP.license.state.status` is `"disabled"` and `start(ctx)`
59
+ runs immediately.
60
+ - **License on:** the runtime adds an empty `<div id="ap-license-root">` to
61
+ `<body>`, calls `renderLicense(api, root)`, and validates the license.
62
+ `start(ctx)` runs once the status becomes `active` or `offline_grace`.
63
+ It never runs for any other status.
64
+ 4. After `start`, if `updates.check` is `"auto"`, the runtime checks for updates
65
+ now and every 6 hours. In the default `"background"` mode a found update is
66
+ installed right away and `AP.updates.onInstalled` fires; the panel keeps
67
+ running the old version until `AP.updates.reload()` or the next launch.
68
+
69
+ `start` runs at most once per panel load. If the license later becomes invalid
70
+ (for example the buyer signs out), the license root is shown again over your
71
+ app; `start` is not called a second time.
72
+
73
+ ## Example: a free extension
74
+
75
+ ```js
76
+ AP.boot({
77
+ start: function (ctx) {
78
+ var app = document.getElementById("app");
79
+ app.textContent = "Hello from " + ctx.product.bundleId + " (" + ctx.panel.id + ")";
80
+ }
81
+ });
82
+ ```
83
+
84
+ ## Example: a paid extension
85
+
86
+ ```js
87
+ AP.boot({
88
+ start: function (ctx) {
89
+ renderHome(document.getElementById("app"), ctx); // imported from src/features/home/home.js
90
+ },
91
+ license: true,
92
+ renderLicense: renderLicense, // imported; see licensing.md
93
+ updates: { check: "auto", mode: "background" }
94
+ });
95
+ ```
96
+
97
+ ## Mistakes to avoid
98
+
99
+ - Do not build app UI before `start` runs. Put it inside `start`.
100
+ - Do not call `start` yourself, and do not call `AP.boot` twice (the second call
101
+ is ignored with a warning).
102
+ - Do not wrap `AP.boot` in `try/catch` to hide the missing-`renderLicense`
103
+ error. Fix the options instead.