afterpresets 0.2.0 → 0.3.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 (114) hide show
  1. package/README.md +6 -4
  2. package/native-runtime/CMakeLists.txt +82 -0
  3. package/native-runtime/README.md +40 -0
  4. package/native-runtime/THIRD_PARTY_NOTICES.md +14 -0
  5. package/native-runtime/include/ap_native.h +223 -0
  6. package/native-runtime/src/apply.cpp +199 -0
  7. package/native-runtime/src/crypto.cpp +225 -0
  8. package/native-runtime/src/crypto.hpp +51 -0
  9. package/native-runtime/src/dialog.cpp +62 -0
  10. package/native-runtime/src/dialog.hpp +35 -0
  11. package/native-runtime/src/engine.cpp +909 -0
  12. package/native-runtime/src/engine.hpp +232 -0
  13. package/native-runtime/src/fsutil.cpp +291 -0
  14. package/native-runtime/src/fsutil.hpp +57 -0
  15. package/native-runtime/src/json.cpp +326 -0
  16. package/native-runtime/src/json.hpp +70 -0
  17. package/native-runtime/src/platform.hpp +83 -0
  18. package/native-runtime/src/platform_common.cpp +60 -0
  19. package/native-runtime/src/platform_mac.mm +314 -0
  20. package/native-runtime/src/platform_win.cpp +277 -0
  21. package/native-runtime/src/runtime.cpp +473 -0
  22. package/native-runtime/src/util.cpp +169 -0
  23. package/native-runtime/src/util.hpp +32 -0
  24. package/native-runtime/src/zip.cpp +243 -0
  25. package/native-runtime/src/zip.hpp +58 -0
  26. package/native-runtime/third_party/monocypher/LICENCE.md +167 -0
  27. package/native-runtime/third_party/monocypher/monocypher-ed25519.c +500 -0
  28. package/native-runtime/third_party/monocypher/monocypher-ed25519.h +140 -0
  29. package/native-runtime/third_party/monocypher/monocypher.c +2956 -0
  30. package/native-runtime/third_party/monocypher/monocypher.h +321 -0
  31. package/native-runtime/third_party/tinf/LICENSE +22 -0
  32. package/native-runtime/third_party/tinf/crc32.c +57 -0
  33. package/native-runtime/third_party/tinf/tinf.h +140 -0
  34. package/native-runtime/third_party/tinf/tinflate.c +636 -0
  35. package/native-runtime/vendor-files.json +39 -0
  36. package/package.json +6 -3
  37. package/runtime/docs/cep/host.md +8 -0
  38. package/runtime/docs/common/README.md +1 -1
  39. package/runtime/docs/native/README.md +44 -0
  40. package/runtime/docs/native/debugging.md +140 -0
  41. package/runtime/docs/native/rules.md +402 -0
  42. package/runtime/docs/native/testing.md +154 -0
  43. package/runtime/package.json +1 -1
  44. package/runtime/scripts/ae-sdk-docs/config.js +102 -0
  45. package/runtime/scripts/ae-sdk-docs/convert.js +430 -0
  46. package/runtime/scripts/ae-sdk-docs/index.js +314 -0
  47. package/runtime/scripts/ae-sdk-docs/source.js +205 -0
  48. package/runtime/scripts/ae-sdk-docs/split.js +170 -0
  49. package/runtime/scripts/ae-sdk-docs.js +72 -0
  50. package/runtime/src/host.js +1 -1
  51. package/src/api/error-messages.js +1 -1
  52. package/src/check/check.js +3 -3
  53. package/src/check/native.js +14 -0
  54. package/src/check/pricing.js +1 -1
  55. package/src/cli.js +2 -2
  56. package/src/commands/build.js +8 -2
  57. package/src/commands/check.js +10 -2
  58. package/src/commands/dev.js +9 -2
  59. package/src/commands/docs.js +5 -1
  60. package/src/commands/init.js +10 -7
  61. package/src/commands/push.js +5 -2
  62. package/src/commands/sdk.js +14 -0
  63. package/src/commands/testers.js +1 -1
  64. package/src/commands/upgrade.js +2 -2
  65. package/src/commands/whoami.js +1 -1
  66. package/src/dev/bridge.js +8 -0
  67. package/src/dev/native.js +3 -0
  68. package/src/dev/session.js +4 -3
  69. package/src/mcp/extendscript.js +9 -8
  70. package/src/mcp/host-target.js +1 -0
  71. package/src/mcp/panels.js +1 -1
  72. package/src/mcp/png.js +1 -0
  73. package/src/mcp/server.js +2 -2
  74. package/src/mcp/tools/capture.js +3 -0
  75. package/src/mcp/tools/host.js +1 -1
  76. package/src/mcp/tools/native.js +6 -0
  77. package/src/mcp/tools/project.js +48 -32
  78. package/src/mcp/tools/releases.js +23 -20
  79. package/src/native/build.js +27 -0
  80. package/src/native/cmake/CMakeLists.txt +88 -0
  81. package/src/native/cmake/zig-windows.cmake +19 -0
  82. package/src/native/effect.js +3 -0
  83. package/src/native/install.js +8 -0
  84. package/src/native/installers.js +4 -0
  85. package/src/native/pipl.js +20 -0
  86. package/src/native/restart.js +2 -0
  87. package/src/native/sdk.js +8 -0
  88. package/src/project/docs.js +3 -3
  89. package/src/project/project.js +2 -2
  90. package/src/project/template.js +5 -4
  91. package/src/prompt.js +1 -1
  92. package/src/release/native.js +3 -0
  93. package/src/release/publish.js +1 -1
  94. package/src/system/run-command.js +1 -1
  95. package/src/targets.js +1 -1
  96. package/template/cep/AGENTS.md +99 -164
  97. package/template/cep/README.md +7 -2
  98. package/template/cep/docs/code_guide.md +67 -0
  99. package/template/cep/docs/initial_setup.md +58 -12
  100. package/template/cep/docs/release_checklist.md +24 -0
  101. package/template/hosts/AGENTS.two-apps.md +12 -0
  102. package/template/native/.mcp.json +8 -0
  103. package/template/native/AGENTS.md +105 -0
  104. package/template/native/README.md +71 -0
  105. package/template/native/docs/code_guide.md +72 -0
  106. package/template/native/docs/initial_setup.md +179 -0
  107. package/template/native/docs/release_checklist.md +24 -0
  108. package/template/native/effect.json +16 -0
  109. package/template/native/gitignore +8 -0
  110. package/template/native/package.json +14 -0
  111. package/template/native/src/Effect.cpp +224 -0
  112. package/template/native/src/License.cpp +95 -0
  113. package/template/native/src/License.h +29 -0
  114. package/template/native/src/Render.h +68 -0
@@ -0,0 +1,88 @@
1
+ # AfterPresets native effect build. Lives in the CLI package (so `ap upgrade`
2
+ # updates it) and is driven by `ap build` (packages/cli/src/native/build.js);
3
+ # projects contain no CMake files. Inputs (all set by build.js):
4
+ #
5
+ # AP_PROJECT_ROOT the seller's project (src/*.cpp|*.c|*.mm; optional native.cmake)
6
+ # AP_GEN_DIR files generated from effect.json (headers, PiPL, Info.plist, PkgInfo)
7
+ # AP_SDK_ROOT ~/.afterpresets/sdk/<version> (Adobe's SDK, never in the project)
8
+ # AP_NATIVE_DIR the ap_native runtime (packages/native-runtime)
9
+ # AP_BUNDLE_NAME executable / bundle name
10
+ # AP_RELEASE ON for release builds (stripped, no debug info)
11
+ cmake_minimum_required(VERSION 3.20)
12
+ if(APPLE AND NOT CMAKE_OSX_ARCHITECTURES)
13
+ set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "")
14
+ endif()
15
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "")
16
+ project(ap_effect LANGUAGES C CXX)
17
+
18
+ foreach(v AP_PROJECT_ROOT AP_GEN_DIR AP_SDK_ROOT AP_NATIVE_DIR AP_BUNDLE_NAME)
19
+ if(NOT ${v})
20
+ message(FATAL_ERROR "${v} is not set: run `ap build`, not cmake directly.")
21
+ endif()
22
+ endforeach()
23
+
24
+ set(CMAKE_CXX_STANDARD 17)
25
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
26
+ set(CMAKE_CXX_VISIBILITY_PRESET hidden) # export only EffectMain + PluginDataEntryFunction2
27
+ set(CMAKE_C_VISIBILITY_PRESET hidden)
28
+ set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
29
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
30
+
31
+ add_subdirectory(${AP_NATIVE_DIR} ap_native)
32
+
33
+ set(SDK_EX ${AP_SDK_ROOT}/Examples)
34
+ file(GLOB_RECURSE AP_SOURCES CONFIGURE_DEPENDS
35
+ ${AP_PROJECT_ROOT}/src/*.cpp ${AP_PROJECT_ROOT}/src/*.c)
36
+ if(APPLE)
37
+ enable_language(OBJCXX)
38
+ file(GLOB_RECURSE AP_MM CONFIGURE_DEPENDS ${AP_PROJECT_ROOT}/src/*.mm)
39
+ list(APPEND AP_SOURCES ${AP_MM})
40
+ endif()
41
+ # The SDK's suite helpers, compiled from the cache (never copied into the project).
42
+ list(APPEND AP_SOURCES ${SDK_EX}/Util/AEGP_SuiteHandler.cpp ${SDK_EX}/Util/MissingSuiteError.cpp)
43
+
44
+ set(NAME ${AP_BUNDLE_NAME})
45
+ if(APPLE)
46
+ set_source_files_properties(${AP_GEN_DIR}/${NAME}.rsrc PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
47
+ add_library(${NAME} MODULE ${AP_SOURCES} ${AP_GEN_DIR}/${NAME}.rsrc)
48
+ set_target_properties(${NAME} PROPERTIES
49
+ BUNDLE TRUE
50
+ BUNDLE_EXTENSION plugin
51
+ MACOSX_BUNDLE_INFO_PLIST ${AP_GEN_DIR}/Info.plist)
52
+ target_link_options(${NAME} PRIVATE -Wl,-dead_strip)
53
+ if(AP_RELEASE)
54
+ target_link_options(${NAME} PRIVATE -Wl,-x)
55
+ endif()
56
+ add_custom_command(TARGET ${NAME} POST_BUILD
57
+ COMMAND ${CMAKE_COMMAND} -E copy ${AP_GEN_DIR}/PkgInfo $<TARGET_BUNDLE_CONTENT_DIR:${NAME}>/PkgInfo
58
+ COMMAND codesign --force --sign - --timestamp=none $<TARGET_BUNDLE_DIR:${NAME}>
59
+ COMMENT "PkgInfo + ad-hoc signature")
60
+ elseif(WIN32)
61
+ # pipl.rc names pipl.bin relatively; both live in AP_GEN_DIR.
62
+ add_library(${NAME} MODULE ${AP_SOURCES} ${AP_GEN_DIR}/pipl.rc)
63
+ set_source_files_properties(${AP_GEN_DIR}/pipl.rc PROPERTIES OBJECT_DEPENDS ${AP_GEN_DIR}/pipl.bin)
64
+ set_target_properties(${NAME} PROPERTIES SUFFIX ".aex" PREFIX "")
65
+ # The SDK headers pick their Windows branch from these (as Adobe's Visual Studio projects define them).
66
+ target_compile_definitions(${NAME} PRIVATE _WINDOWS MSWindows WIN32)
67
+ if(AP_RELEASE)
68
+ target_link_options(${NAME} PRIVATE -s)
69
+ endif()
70
+ else()
71
+ message(FATAL_ERROR "After Effects effects build for macOS or Windows only.")
72
+ endif()
73
+
74
+ target_include_directories(${NAME} PRIVATE
75
+ ${AP_PROJECT_ROOT}/src
76
+ ${AP_GEN_DIR}
77
+ ${SDK_EX}/Headers
78
+ ${SDK_EX}/Headers/SP
79
+ ${SDK_EX}/Util
80
+ ${SDK_EX}/Resources)
81
+ target_link_libraries(${NAME} PRIVATE ap_native)
82
+ # Warnings in the seller's code (build.js reports only those under the project).
83
+ target_compile_options(${NAME} PRIVATE -Wall -Wno-unused-parameter -Wno-missing-braces)
84
+
85
+ # Optional per-project additions (extra libraries, defines). Runs last.
86
+ if(EXISTS ${AP_PROJECT_ROOT}/native.cmake)
87
+ include(${AP_PROJECT_ROOT}/native.cmake)
88
+ endif()
@@ -0,0 +1,19 @@
1
+ # Builds the Windows .aex with Zig (x86_64-windows-gnu, links the UCRT; only
2
+ # the C ABI crosses into After Effects, so the MSVC C++ ABI is not needed), on
3
+ # macOS (cross-compiling) and on Windows (no Visual Studio). build.js writes the
4
+ # zig-* wrappers into AP_ZIG_WRAPPERS: sh scripts on macOS, .cmd files on
5
+ # Windows (AP_ZIG_EXT=.cmd).
6
+ set(CMAKE_SYSTEM_NAME Windows)
7
+ set(CMAKE_SYSTEM_PROCESSOR x86_64)
8
+ if(NOT AP_ZIG_WRAPPERS)
9
+ set(AP_ZIG_WRAPPERS $ENV{AP_ZIG_WRAPPERS})
10
+ endif()
11
+ if(NOT DEFINED AP_ZIG_EXT)
12
+ set(AP_ZIG_EXT "$ENV{AP_ZIG_EXT}")
13
+ endif()
14
+ set(CMAKE_C_COMPILER ${AP_ZIG_WRAPPERS}/zig-cc${AP_ZIG_EXT})
15
+ set(CMAKE_CXX_COMPILER ${AP_ZIG_WRAPPERS}/zig-c++${AP_ZIG_EXT})
16
+ set(CMAKE_RC_COMPILER ${AP_ZIG_WRAPPERS}/zig-rc${AP_ZIG_EXT})
17
+ set(CMAKE_AR ${AP_ZIG_WRAPPERS}/zig-ar${AP_ZIG_EXT})
18
+ set(CMAKE_RANLIB ${AP_ZIG_WRAPPERS}/zig-ranlib${AP_ZIG_EXT})
19
+ set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES AP_ZIG_WRAPPERS AP_ZIG_EXT)
@@ -0,0 +1,3 @@
1
+ "use strict";const h={NON_PARAM_VARY:4,WORKS_IN_PLACE:8192,I_DO_DIALOG:32,USE_OUTPUT_EXTENT:64,PIX_INDEPENDENT:1024,I_EXPAND_BUFFER:512,I_HAVE_EXTERNAL_DEPENDENCIES:16777216,SEND_UPDATE_PARAMS_UI:67108864,DEEP_COLOR_AWARE:33554432},p={SUPPORTS_QUERY_DYNAMIC_FLAGS:1,I_USE_3D_CAMERA:2,I_USE_3D_LIGHTS:4,PARAM_GROUP_START_COLLAPSED_FLAG:8,SUPPORTS_SMART_RENDER:1024,FLOAT_COLOR_AWARE:4096,I_USE_COLORSPACE_ENUMERATION:8192,REVEALS_ZERO_ALPHA:128,I_MIX_GUID_DEPENDENCIES:1<<21,SUPPORTS_GET_FLATTENED_SEQUENCE_DATA:1<<23,SUPPORTS_THREADED_RENDERING:1<<27},A=["DEEP_COLOR_AWARE","PIX_INDEPENDENT","I_DO_DIALOG","SEND_UPDATE_PARAMS_UI"],y=["SUPPORTS_SMART_RENDER","FLOAT_COLOR_AWARE","SUPPORTS_THREADED_RENDERING","I_MIX_GUID_DEPENDENCIES"],E=["slider","angle","color","point","checkbox","popup"],_=["background","notify","manual","off"],g=31,m=9e3,P=9001,x=["input","license","count"];class l extends Error{constructor(e){super("effect.json has "+e.length+" problem"+(e.length===1?"":"s")+`:
2
+ - `+e.join(`
3
+ - `)),this.name="EffectError",this.problems=e}}const O=t=>Buffer.byteLength(String(t),"utf8"),f=t=>typeof t=="number"&&Number.isFinite(t);function S(t){const e=require("crypto"),i=String(t||""),u=i.split(".").pop().replace(/[^A-Za-z0-9]/g,""),c=e.createHash("sha256").update(i).digest("hex").slice(0,6);return("AP "+u.slice(0,20)+" "+c).trim()}function T(t){return{EFFECT_NAME:String(t&&t.name||"My Effect").replace(/[^\x20-\x7E]/g,"").trim().slice(0,g)||"My Effect",MATCH_NAME:S(t&&t.bundleId)}}function D(t){const e=/^#([0-9a-fA-F]{6})$/.exec(String(t||""));if(!e)return null;const i=parseInt(e[1],16);return[i>>16&255,i>>8&255,i&255]}function o(t,e,i,{required:u,max:c=g,noPipe:n}={}){if(i==null||i===""){u&&t.push(e+" is required.");return}if(typeof i!="string")return t.push(e+" must be text.");O(i)>c&&t.push(e+" is "+O(i)+" bytes; the limit is "+c+" (After Effects truncates longer names)."),/[\u0000-\u001f"\\]/.test(i)&&t.push(e+" must not contain quotes, backslashes or control characters."),n&&i.indexOf("|")!==-1&&t.push(e+' must not contain "|".')}function b(t,e){if(e===void 0||e===!0)return{enabled:!0,offlineGraceDays:0,checkInBackground:!0};if(e===!1)return{enabled:!1,offlineGraceDays:0,checkInBackground:!0};if(!e||typeof e!="object"||Array.isArray(e))return t.push('"license" must be true, false or { "offlineGraceDays": 0-30, "checkInBackground": true }.'),{enabled:!0,offlineGraceDays:0,checkInBackground:!0};const i=e.offlineGraceDays===void 0?0:e.offlineGraceDays;return(!Number.isInteger(i)||i<0||i>30)&&t.push('"license.offlineGraceDays" must be a whole number from 0 to 30.'),e.checkInBackground!==void 0&&typeof e.checkInBackground!="boolean"&&t.push('"license.checkInBackground" must be true or false.'),{enabled:!0,offlineGraceDays:Number.isInteger(i)?i:0,checkInBackground:e.checkInBackground!==!1}}function R(t,e,i,u,c){if(i===void 0)return c.slice();if(!Array.isArray(i))return t.push('"'+e+'" must be a list of flag names, e.g. '+JSON.stringify(c)+"."),c.slice();const n=[];return i.forEach(s=>{Object.prototype.hasOwnProperty.call(u,s)?n.indexOf(s)===-1&&n.push(s):t.push('"'+e+'": unknown flag '+JSON.stringify(s)+". Known: "+Object.keys(u).join(", ")+".")}),n}function M(t,e,i,u){const c="params["+i+"]";if(!e||typeof e!="object"||Array.isArray(e))return t.push(c+" must be an object."),null;const n={key:e.key,id:e.id,type:e.type,name:e.name},s=c+(typeof e.key=="string"?' ("'+e.key+'")':"");if(typeof e.key!="string"||!/^[a-z][a-z0-9_]{0,30}$/.test(e.key)?t.push(s+': "key" must be lower-case letters, digits and _ (starting with a letter), e.g. "amount".'):x.indexOf(e.key)!==-1?t.push(s+': "key" '+JSON.stringify(e.key)+" is reserved."):u.keys.has(e.key)?t.push(s+': "key" is used twice.'):u.keys.add(e.key),!Number.isInteger(e.id)||e.id<1||e.id>m?t.push(s+': "id" must be a whole number from 1 to '+m+". Give every param its own id and never change or reuse it: saved projects find params by id."):u.ids.has(e.id)?t.push(s+': "id" '+e.id+" is used twice."):u.ids.add(e.id),o(t,s+' "name"',e.name,{required:!0}),E.indexOf(e.type)===-1)return t.push(s+': "type" must be one of '+E.join(", ")+"."),n;const a=e.default;switch(e.type){case"slider":{["min","max"].forEach(r=>!f(e[r])&&t.push(s+': slider needs a numeric "'+r+'".')),n.min=e.min,n.max=e.max,n.sliderMin=e.sliderMin===void 0?e.min:e.sliderMin,n.sliderMax=e.sliderMax===void 0?e.max:e.sliderMax,n.default=a===void 0?e.min:a,n.precision=e.precision===void 0?1:e.precision,n.display=e.display||"none",f(n.min)&&f(n.max)&&(n.min>=n.max&&t.push(s+': "min" must be less than "max".'),(!f(n.sliderMin)||!f(n.sliderMax)||n.sliderMin<n.min||n.sliderMax>n.max||n.sliderMin>=n.sliderMax)&&t.push(s+': "sliderMin"/"sliderMax" must lie within min..max, sliderMin < sliderMax.'),(!f(n.default)||n.default<n.min||n.default>n.max)&&t.push(s+': "default" must be a number within min..max.')),(!Number.isInteger(n.precision)||n.precision<0||n.precision>6)&&t.push(s+': "precision" must be 0-6 (decimal places).'),["none","percent","pixels"].indexOf(n.display)===-1&&t.push(s+': "display" must be "none", "percent" or "pixels".');break}case"angle":n.default=a===void 0?0:a,f(n.default)||t.push(s+': angle "default" must be a number of degrees.');break;case"color":n.default=a===void 0?"#FFFFFF":a,n.rgb=D(n.default),n.rgb||t.push(s+': color "default" must look like "#FF8800".');break;case"point":n.default=a===void 0?[50,50]:a,(!Array.isArray(n.default)||n.default.length!==2||!n.default.every(f))&&t.push(s+': point "default" must be [x, y] in percent of the layer, e.g. [50, 50].');break;case"checkbox":n.default=a===void 0?!1:a,n.label=e.label===void 0?"":e.label,typeof n.default!="boolean"&&t.push(s+': checkbox "default" must be true or false.'),o(t,s+' "label"',n.label,{max:31});break;case"popup":n.choices=e.choices,!Array.isArray(e.choices)||e.choices.length<1||e.choices.length>64?(t.push(s+': popup needs "choices": a list of 1-64 names.'),n.choices=[]):(e.choices.forEach((r,d)=>o(t,s+" choice "+(d+1),r,{required:!0,max:63,noPipe:!0})),new Set(e.choices).size!==e.choices.length&&t.push(s+": popup choices must be unique.")),n.default=a===void 0?n.choices[0]:a,n.defaultIndex=n.choices.indexOf(n.default)+1,n.defaultIndex<1&&t.push(s+': popup "default" must be one of the choices.');break}return n}function N(t){const e=[];if(!t||typeof t!="object"||Array.isArray(t))throw new l(["effect.json must be a JSON object."]);o(e,'"name"',t.name,{required:!0}),o(e,'"matchName"',t.matchName,{required:!0}),o(e,'"category"',t.category,{required:!0}),o(e,'"description"',t.description,{max:255}),t.supportUrl!==void 0&&t.supportUrl!==""&&!/^https:\/\/[^\s"\\]{3,200}$/.test(String(t.supportUrl))&&e.push('"supportUrl" must be an https:// address.');const i=b(e,t.license),u=t.updates===void 0?"background":t.updates;_.indexOf(u)===-1&&e.push('"updates" must be one of '+_.join(", ")+".");const c=R(e,"outFlags",t.outFlags,h,A),n=R(e,"outFlags2",t.outFlags2,p,y);c.indexOf("SEND_UPDATE_PARAMS_UI")===-1&&e.push('"outFlags" must include SEND_UPDATE_PARAMS_UI (the license/update status line needs it).'),c.indexOf("I_DO_DIALOG")===-1&&e.push('"outFlags" must include I_DO_DIALOG (buyers sign in from the Options button).'),i.enabled&&n.indexOf("I_MIX_GUID_DEPENDENCIES")===-1&&e.push('"outFlags2" must include I_MIX_GUID_DEPENDENCIES when licensing is on (otherwise After Effects can show a cached watermarked frame after sign-in).'),n.indexOf("FLOAT_COLOR_AWARE")!==-1&&c.indexOf("DEEP_COLOR_AWARE")===-1&&e.push("FLOAT_COLOR_AWARE needs DEEP_COLOR_AWARE in outFlags."),n.indexOf("FLOAT_COLOR_AWARE")!==-1&&n.indexOf("SUPPORTS_SMART_RENDER")===-1&&e.push("FLOAT_COLOR_AWARE (32 bpc) needs SUPPORTS_SMART_RENDER.");const s={keys:new Set,ids:new Set};let a=[];t.params!==void 0&&!Array.isArray(t.params)?e.push('"params" must be a list.'):a=(t.params||[]).map((d,k)=>M(e,d,k,s)).filter(Boolean),a.length>60&&e.push("Too many params ("+a.length+"); keep it under 60.");const r=new Set(["$schema","name","matchName","category","description","supportUrl","license","updates","params","outFlags","outFlags2"]);if(Object.keys(t).forEach(d=>!r.has(d)&&e.push("Unknown field "+JSON.stringify(d)+".")),e.length)throw new l(e);return{name:t.name,matchName:t.matchName,category:t.category,description:t.description||"",supportUrl:t.supportUrl||"",license:i,updates:u,params:a,outFlags:c,outFlags2:n,outFlagsValue:I(c,h),outFlags2Value:I(n,p)}}function I(t,e){return t.reduce((i,u)=>(i|e[u])>>>0,0)}function U(t){const e=require("fs"),u=require("path").join(t,"effect.json");let c;try{c=e.readFileSync(u,"utf8")}catch{throw new l(["effect.json is missing in "+t+"."])}c.charCodeAt(0)===65279&&(c=c.slice(1));let n;try{n=JSON.parse(c)}catch(s){throw new l(["effect.json is not valid JSON: "+s.message])}return N(n)}function F(t,e){if(!t)return[];const i=[];return t.matchName!==e.matchName&&i.push('matchName changed from "'+t.matchName+'" to "'+e.matchName+'". After Effects identifies the effect by it in every saved project: change it back.'),t.params.forEach(u=>{const c=e.params.find(n=>n.id===u.id);c?c.type!==u.type&&i.push("param id "+u.id+" changed type from "+u.type+" to "+c.type+". Give the new param a new id instead."):i.push("param id "+u.id+' ("'+u.name+'") was removed. Keep it (you may hide it in code) so saved projects still open with their keyframes.')}),i}module.exports={OUT_FLAGS:h,OUT_FLAGS2:p,DEFAULT_OUT_FLAGS:A,DEFAULT_OUT_FLAGS2:y,PARAM_TYPES:E,UPDATE_MODES:_,MAX_PARAM_ID:m,LICENSE_PARAM_ID:P,EffectError:l,defaultMatchName:S,templateValues:T,validateEffect:N,loadEffect:U,compatibilityProblems:F,hexColor:D};
@@ -0,0 +1,8 @@
1
+ "use strict";const $=require("crypto"),o=require("fs"),j=require("os"),u=require("path"),P="/Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore",O="Adobe\\Common\\Plug-ins\\7.0\\MediaCore",I="AfterPresets Dev",T=".ap-dev.json",J=/^com\.afterpresets\.[a-z0-9]{1,64}\.[a-z0-9-]{2,40}$/,h=e=>e.platform==="win32";function b(e,t){const r=e.env||{};if(r[t]!==void 0)return r[t];const a=Object.keys(r).find(n=>n.toLowerCase()===t.toLowerCase());return a?r[a]:void 0}function k(e){return h(e)?".aex":".plugin"}function p(e){const t=e.env&&e.env.AP_NATIVE_DEV_ROOT;return t?u.resolve(t):h(e)?u.win32.join(b(e,"ProgramFiles")||"C:\\Program Files",O,I):u.join(P,I)}function v(e){return"'"+String(e).replace(/'/g,"'\\''")+"'"}function L(e){const t=e.env&&e.env.USER||j.userInfo().username;if(!/^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$/.test(t))throw new Error("Unexpected user name: "+t);return t}function W(e){const t=b(e,"USERNAME")||j.userInfo().username,r=b(e,"USERDOMAIN")||"",a=/["/\\[\]:;|=,+*?<>\x00-\x1f]/;if(!t||a.test(t)||a.test(r)||t.length>104||r.length>64)throw new Error("Unexpected user name: "+(r?r+"\\":"")+t);return r?r+"\\"+t:t}function F(e){try{if(!o.statSync(e).isDirectory())return!1;const t=u.join(e,".ap-write-test-"+process.pid+"-"+A());return o.writeFileSync(t,""),o.unlinkSync(t),!0}catch{return!1}}function D(e){return"'"+String(e).replace(/'/g,"''")+"'"}function w(e){const t=p(e);return h(e)?"New-Item -ItemType Directory -Force -Path "+D(t)+" | Out-Null; icacls "+D(t)+" /grant "+D(W(e)+":(OI)(CI)M"):"sudo mkdir -p "+v(t)+" && sudo chown "+L(e)+":staff "+v(t)}function E(e){return h(e)?"in PowerShell opened as administrator (Start menu > type PowerShell > right-click Windows PowerShell > Run as administrator)":"in Terminal"}async function _(e){if(h(e))return{ok:!1,message:"AfterPresets does not ask for administrator rights on Windows. The user can run this once "+E(e)+`:
2
+ `+w(e)};const t=p(e),r=L(e),a="mkdir -p "+v(t)+" && chown "+r+":staff "+v(t),n="do shell script "+JSON.stringify(a)+' with prompt "AfterPresets needs to create the After Effects dev plug-in folder once." with administrator privileges',s=await e.runCommand("/usr/bin/osascript",["-e",n],{quiet:!0});if(s.code===0&&F(t))return{ok:!0,message:"Created "+t+" (owned by "+r+")."};const l=/-128|User cancel/i.test(s.stderr||"");return{ok:!1,cancelled:l,message:(l?"The administrator prompt was cancelled.":"Could not create the dev folder: "+String(s.stderr||"").trim())+`
3
+ The user can run this in Terminal instead:
4
+ `+w(e)}}function N(e){const t=p(e);if(F(t))return{ready:!0,root:t,message:t+" is ready."};const r=o.existsSync(t),a=h(e)?" It needs an administrator once (later installs need nothing). Ask the user to run this one line "+E(e)+`, then build again:
5
+ `:` It needs an administrator once (later installs need nothing). Ask the user to approve the macOS password prompt (installDev with { askAdmin: true }), or to run in Terminal:
6
+ `;return{ready:!1,root:t,command:w(e),where:E(e),message:(r?t+" exists but is not writable by you.":t+" does not exist yet.")+a+w(e)}}function C(e){if(!J.test(String(e||"")))throw new Error("Invalid bundle ID: "+e)}function A(){return $.randomBytes(4).toString("hex")}const Q=/\.ap-(old|staging)-[0-9a-f]+$/;function Z(e,t,r){const a=u.dirname(t),n=r?t+".ap-staging-"+A():u.join(a,".staging-"+A()+"-"+u.basename(t));o.cpSync(e,n,{recursive:!0,verbatimSymlinks:!0});let s=null;if(o.existsSync(t)||R(t)){s=r?t+".ap-old-"+A():u.join(a,".old-"+A()+"-"+u.basename(t));try{o.renameSync(t,s)}catch(l){throw o.rmSync(n,{recursive:!0,force:!0}),r&&/^(EPERM|EBUSY|EACCES)$/.test(l.code)?new Error("Could not replace "+t+": After Effects (or another program) is using it. Quit After Effects, then build again."):l}}try{o.renameSync(n,t)}catch(l){throw s&&o.renameSync(s,t),o.rmSync(n,{recursive:!0,force:!0}),l}if(s)try{o.rmSync(s,{recursive:!0,force:!0})}catch(l){if(!r)throw l}}function G(e){for(const t of o.readdirSync(e))if(Q.test(t))try{o.rmSync(u.join(e,t),{recursive:!0,force:!0})}catch{}}function R(e){try{return o.lstatSync(e).isSymbolicLink()}catch{return!1}}function H(e){try{return JSON.parse(o.readFileSync(u.join(e,T),"utf8"))}catch{return null}}async function X(e,t,r){const a=r||{},n=t&&t.build&&t.build.artifacts?t.build:t&&t.artifacts?t:t&&t.build?t.build:null;n&&!n.artifacts&&n.artefacts&&(n.artifacts=n.artefacts),t&&t.askAdmin&&(a.askAdmin=!0);const s=h(e);if(e.platform!=="darwin"&&!s&&!(e.env&&e.env.AP_NATIVE_DEV_ROOT))return{ok:!1,message:"Dev installs run on macOS and Windows."};const l=n&&n.artifacts&&(s?n.artifacts.win:n.artifacts.mac);if(!l)return{ok:!1,message:"No "+(s?"Windows (.aex)":"macOS (.plugin)")+" build to install: run the dev build first."};C(n.bundleId);let d=N(e);if(!d.ready&&a.askAdmin&&!s){const m=await _(e);if(!m.ok)return{ok:!1,needsAdmin:!0,command:w(e),where:E(e),message:m.message};d=N(e)}if(!d.ready)return{ok:!1,needsAdmin:!0,command:d.command,where:d.where,message:d.message};const i=u.join(d.root,n.bundleId);R(i)&&o.unlinkSync(i),o.mkdirSync(i,{recursive:!0});const c=u.basename(l),f=u.join(i,c);s&&G(i);try{Z(l,f,s)}catch(m){return{ok:!1,message:m.message}}const S=k(e);for(const m of o.readdirSync(i))if(!(m===c||!m.toLowerCase().endsWith(S))){if(!s){o.rmSync(u.join(i,m),{recursive:!0,force:!0});continue}try{o.rmSync(u.join(i,m),{force:!0})}catch{try{o.renameSync(u.join(i,m),u.join(i,m+".ap-old-"+A()))}catch{}}}s||await e.runCommand("/usr/bin/xattr",["-dr","com.apple.quarantine",f],{quiet:!0});const y={bundleId:n.bundleId,name:n.name,version:n.version,buildId:n.buildId,matchName:n.matchName,installedAt:new Date(e.now()).toISOString()};o.writeFileSync(u.join(i,T),JSON.stringify(y,null,2)+`
7
+ `);const g=await z(e,{bundleId:n.bundleId});return{ok:!0,path:f,buildId:n.buildId,restartNeeded:g.restartNeeded,aeRunning:g.aeRunning,message:"Installed "+c+" into "+i+"."+(g.restartNeeded?" After Effects started before this build was installed: restart it to load this one.":g.aeRunning?"":" Start After Effects to load it.")}}async function Y(e,t){C(t);const r=u.join(p(e),t);if(R(r))return o.unlinkSync(r),{ok:!0,removed:!0,message:"Removed the link "+r+"."};if(!o.existsSync(r))return{ok:!0,removed:!1,message:"Nothing installed at "+r+"."};try{o.rmSync(r,{recursive:!0,force:!0})}catch(a){return{ok:!1,removed:!1,message:"Could not remove "+r+": "+a.message}}return{ok:!0,removed:!0,message:"Removed "+r+". After Effects drops the effect at its next start."}}function q(e){for(const t of String(e||"").split(/\r?\n/)){const r=/^"([^"]+)","(\d+)"/.exec(t.trim());if(r&&r[1].toLowerCase()==="afterfx.exe")return Number(r[2])}return 0}async function K(e){const t=u.win32.join(b(e,"SystemRoot")||"C:\\Windows","System32"),r=await e.runCommand(u.win32.join(t,"tasklist.exe"),["/FI","IMAGENAME eq AfterFX.exe","/FO","CSV","/NH"],{quiet:!0,shell:!1}),a=r.code===0?q(r.stdout):0;if(!a)return{running:!1,pid:0,startedAt:null};const n=await e.runCommand(u.win32.join(t,"WindowsPowerShell","v1.0","powershell.exe"),["-NoProfile","-NonInteractive","-Command","(Get-Process -Id "+a+").StartTime.ToUniversalTime().ToString('o')"],{quiet:!0,shell:!1}),s=Date.parse(String(n.stdout||"").trim());return{running:!0,pid:a,startedAt:n.code===0&&Number.isFinite(s)?s:null}}async function M(e){if(h(e))return K(e);const t=await e.runCommand("/usr/bin/pgrep",["-x","After Effects"],{quiet:!0}),r=t.code===0?Number(String(t.stdout).trim().split(`
8
+ `)[0]):0;if(!r)return{running:!1,pid:0,startedAt:null};const a=await e.runCommand("/bin/ps",["-o","lstart=","-p",String(r)],{quiet:!0}),n=Date.parse(String(a.stdout||"").trim());return{running:!0,pid:r,startedAt:Number.isFinite(n)?n:null}}function U(e,t){if(h(e)){const r=b(e,"LOCALAPPDATA")||u.join(e.homeDir,"AppData","Local");return u.join(r,"AfterPresets","Logs",t+".log")}return u.join(e.homeDir,"Library","Logs","AfterPresets",t+".log")}function B(e,t,r){const a=U(e,t);let n;try{const i=o.openSync(a,"r"),c=o.fstatSync(i).size,f=Math.min(c,256*1024),S=Buffer.alloc(f);o.readSync(i,S,0,f,c-f),o.closeSync(i),n=S.toString("utf8")}catch{return null}const s=new RegExp("^(\\S+).*?start "+t.replace(/[.]/g,"\\.")+" \\S+ build=([A-Za-z0-9_-]+)","gm");let l,d=null;for(;l=s.exec(n);){const i=Date.parse(l[1]);r&&(!Number.isFinite(i)||i<r-1e3)||(d=l[2])}return d}function V(e){return h(e)?"ask the user to save their work and restart After Effects (it is not restarted automatically on Windows).":"restart it."}async function z(e,t){const r=t||{},a=r.bundleId||r.settings&&r.settings.bundleId||r.project&&r.project.settings&&r.project.settings.bundleId;C(a);const n=u.join(p(e),a),s=H(n),l=k(e),d=o.existsSync(n)?o.readdirSync(n).find(g=>g.toLowerCase().endsWith(l)&&!g.startsWith(".")):null,i=await M(e),c=i.running?B(e,a,i.startedAt):null;let f=!1,S="";if(i.running&&s&&d){const g=Date.parse(s.installedAt);c&&i.startedAt&&g<i.startedAt?(f=c!==s.buildId,S="build ID"):i.startedAt&&(f=g>i.startedAt,S="install time",c===s.buildId&&(f=!1))}let y;return d?i.running?f&&c?y="RESTART NEEDED: After Effects is running build "+c+"; build "+(s&&s.buildId)+" was installed after it started. After Effects loads plugins only at launch: "+V(e):f?y="RESTART NEEDED: After Effects has not loaded this plugin yet (build "+(s&&s.buildId)+" was installed after it started). After Effects loads plugins only at launch: "+V(e):c?y="After Effects is running build "+c+".":y="After Effects started after build "+(s&&s.buildId)+" was installed; it loads that build when the effect is first used.":y="Installed (build "+(s&&s.buildId)+"). After Effects is not running; it loads this build when it starts.":y="Not installed in "+n+".",{installed:!!d,path:d?u.join(n,d):null,buildId:s?s.buildId:null,aeRunning:i.running,aePid:i.pid||null,aeStartedAt:i.startedAt?new Date(i.startedAt).toISOString():null,loadedBuildId:c,restartNeeded:f,decidedBy:S||null,message:y}}module.exports={MEDIACORE_MAC:P,MEDIACORE_WIN_SUBPATH:O,pluginExt:k,logPath:U,parseTasklist:q,windowsUser:W,adminWhere:E,DEV_FOLDER:I,devRoot:p,devRootStatus:N,adminCommand:w,setupDevRootWithAdminDialog:_,installDev:X,uninstallDev:Y,devStatus:z,afterEffectsProcess:M,loadedBuildFromLog:B};
@@ -0,0 +1,4 @@
1
+ "use strict";const l=/^com\.afterpresets\.[a-z0-9]{1,64}\.[a-z0-9-]{2,40}$/,c=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,u=/^\d{1,6}\.\d{1,6}\.\d{1,6}$/,a="/Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore/AfterPresets",f="Adobe\\Common\\Plug-ins\\7.0\\MediaCore\\AfterPresets";function d(n,e){return String(n||"").replace(/[^A-Za-z0-9 ._-]/g,"").replace(/\s+/g," ").trim().slice(0,80)||e}function o(n){const e=n||{};if(!l.test(String(e.bundleId||"")))throw new Error("Invalid bundle ID for installer: "+e.bundleId);const t=e.bundleName||String(e.pluginName||"").replace(/\.plugin$/i,"");if(!c.test(t))throw new Error("Invalid plug-in name for installer: "+t);const s=e.version===void 0?"":String(e.version);if(s&&!u.test(s))throw new Error("Invalid version for installer: "+s);const r=Array.isArray(e.oses)&&e.oses.length?["mac","win"].filter(i=>e.oses.indexOf(i)!==-1):["mac","win"];if(!r.length)throw new Error("Invalid operating systems for installer: "+e.oses);return{bundleId:e.bundleId,bundleName:t,version:s,display:d(e.name,t),listingUrl:e.listingUrl,oses:r}}function p(n){const e=o(n),t=e.bundleName+".plugin";return["#!/bin/bash","# Installs "+e.display+" for After Effects (AfterPresets).","set -u",'SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"','ROOT="${AP_INSTALL_ROOT:-'+a+'}"','DEST="$ROOT/'+e.bundleId+'"','SRC="$SCRIPT_DIR/'+t+'"','ME="$(id -un)"',"",'fail() { echo ""; echo "Install failed: $1"; echo ""; read -r -p "Press Enter to close..." _; exit 1; }',"",'echo ""','echo "Installing '+e.display+(e.version?" "+e.version:"")+'..."','echo ""','[ -d "$SRC" ] || fail "'+t+' is missing. Unzip the whole download, then run this script from the unzipped folder."',"","# First install: create the AfterPresets folder once with administrator approval and","# make it yours, so updates install later without a password.",'mkdir -p "$ROOT" 2>/dev/null',"needs_admin=0",'if [ ! -d "$ROOT" ] || [ ! -w "$ROOT" ]; then needs_admin=1; fi','if [ -e "$DEST" ] && [ ! -w "$DEST" ]; then needs_admin=1; fi','if [ "$needs_admin" = 1 ] && [ -n "${AP_INSTALL_ROOT:-}" ]; then fail "$ROOT is not writable (test root: no admin prompt)."; fi','if [ "$needs_admin" = 1 ]; then',' echo "macOS will ask for your password once to create the AfterPresets plug-in folder."',` /usr/bin/osascript - "$ROOT" "$ME" <<'APPLESCRIPT' >/dev/null || fail "Administrator approval was not given."`,"on run argv"," set r to quoted form of (item 1 of argv)"," set u to quoted form of (item 2 of argv)",' do shell script "mkdir -p " & r & " && chown -R " & u & ":staff " & r & " && chmod 755 " & r with prompt "Install an After Effects plug-in from AfterPresets." with administrator privileges',"end run","APPLESCRIPT","fi",'[ -w "$ROOT" ] || fail "$ROOT is not writable."',"",'if [ -L "$DEST" ]; then rm -f "$DEST"; fi','mkdir -p "$DEST" || fail "Could not create $DEST."','STAGE="$DEST/.installing-$$"','rm -rf "$STAGE"','mkdir -p "$STAGE" && /usr/bin/ditto "$SRC" "$STAGE/'+t+'" || { rm -rf "$STAGE"; fail "Could not copy the plug-in."; }','/usr/bin/xattr -dr com.apple.quarantine "$STAGE/'+t+'" 2>/dev/null','if [ -L "$DEST/'+t+'" ]; then rm -f "$DEST/'+t+'"; fi','if [ -e "$DEST/'+t+'" ]; then mv "$DEST/'+t+'" "$STAGE/old.plugin" || { rm -rf "$STAGE"; fail "Could not replace the old version."; }; fi','mv "$STAGE/'+t+'" "$DEST/'+t+'" || { [ -e "$STAGE/old.plugin" ] && mv "$STAGE/old.plugin" "$DEST/'+t+'"; rm -rf "$STAGE"; fail "Could not install the plug-in."; }','rm -rf "$STAGE"',"",'echo ""','echo "Done! Installed into $DEST"','if /usr/bin/pgrep -x "After Effects" >/dev/null 2>&1; then',' echo "Restart After Effects to load '+e.display+'."',"else",` echo "Start After Effects and find it in Effect > the effect's category."`,"fi",'echo ""','read -r -p "Press Enter to close..." _',""].join(`
2
+ `)}function h(n){const e=o(n),t=e.bundleName+".aex";return["@echo off","setlocal",'set "SCRIPT_DIR=%~dp0"','set "ROOT=%ProgramFiles%\\'+f+'"','set "DEST=%ROOT%\\'+e.bundleId+'"',"","rem Ask for administrator rights (UAC) once; remember who started the install.","net session >nul 2>&1","if errorlevel 1 ("," echo Windows will ask for permission to install the plug-in.",` powershell -NoProfile -ExecutionPolicy Bypass -Command "Start-Process -FilePath '%~f0' -ArgumentList ('\\"' + $env:USERDOMAIN + '\\' + $env:USERNAME + '\\"') -Verb RunAs"`," exit /b",")",'set "INSTALL_USER=%~1"','if "%INSTALL_USER%"=="" set "INSTALL_USER=%USERDOMAIN%\\%USERNAME%"',"","echo.","echo Installing "+e.display+(e.version?" "+e.version:"")+"...","echo.",'if not exist "%SCRIPT_DIR%'+t+'" ('," echo "+t+" is missing. Unzip the whole download, then run this script from the unzipped folder."," goto fail",")","",'if not exist "%ROOT%" mkdir "%ROOT%"',"rem Let the buyer's account update the plug-in later without a prompt.",'icacls "%ROOT%" /grant "%INSTALL_USER%":(OI)(CI)M >nul',"rem A junction or link in the way is removed, never followed.",'fsutil reparsepoint query "%DEST%" >nul 2>&1 && rmdir "%DEST%"','if not exist "%DEST%" mkdir "%DEST%"','copy /Y "%SCRIPT_DIR%'+t+'" "%DEST%\\'+t+'.new" >nul || goto fail','move /Y "%DEST%\\'+t+'.new" "%DEST%\\'+t+'" >nul',"if errorlevel 1 (",' del /Q "%DEST%\\'+t+'.new" >nul 2>&1'," echo After Effects is using the old version. Quit After Effects and run this installer again."," goto fail",")",`powershell -NoProfile -Command "Unblock-File -LiteralPath '%DEST%\\`+t+`'" >nul 2>&1`,"","echo.","echo Done! Installed into %DEST%","echo Restart After Effects to load "+e.display+".","echo.","pause","exit /b 0","",":fail","echo.","echo Install failed.","pause","exit /b 1",""].join(`\r
3
+ `)}function m(n){const e=o(n),t=e.oses.indexOf("mac")!==-1,s=e.oses.indexOf("win")!==-1,r=e.display+(e.version?" "+e.version:"")+" - After Effects plugin",i=[r,"=".repeat(Math.min(78,r.length)),"","This plugin is published on AfterPresets by an independent developer.","AfterPresets does not review plugin code.","","Install","-------",""];return t&&i.push("macOS:",' 1. Double-click "mac-install.command".'," 2. If macOS blocks it, right-click the file -> Open, then click Open."," Still blocked? System Settings -> Privacy & Security, scroll down,",' click "Open Anyway" next to mac-install.command, and run it again.'," 3. macOS asks for your password once (the first install only).",""),s&&i.push("Windows:",' 1. Double-click "windows-install.bat" and allow it to make changes'," (Windows asks for permission once, the first install only).",' 2. If Windows warns about the file, click "More info" and "Run anyway"',' (or "Run").',""),i.push("Then restart After Effects.","","Sign in","-------","","Apply the effect to a layer (Effect menu -> "+e.display+"). In the Effect",'Controls panel click "Options" next to the effect name (or the Status',"button). Your browser opens: sign in to AfterPresets and approve. Without","a license the effect renders with a watermark.","","Updates install themselves; when one is ready the effect's status line",'says "Update: restart AE". Restart After Effects to use it.'),e.listingUrl&&i.push("","Plugin page: "+String(e.listingUrl).replace(/[\r\n]/g,"")),i.push("","Bundle ID: "+e.bundleId,""),i.join(`
4
+ `)}module.exports={BUNDLE_ID_PATTERN:l,MAC_VENDOR_ROOT:a,WIN_VENDOR_SUBPATH:f,displayName:d,macInstallCommand:p,windowsInstallBat:h,readmeText:m};
@@ -0,0 +1,20 @@
1
+ "use strict";const I=require("fs"),C=require("path"),{LICENSE_PARAM_ID:T}=require("./effect"),F=16e3,S={major:13,minor:28};function D(n){const e=String(n&&n.name||"").replace(/[^A-Za-z0-9]/g,""),t=String(n&&n.bundleId||"").split(".").pop().replace(/[^A-Za-z0-9]/g,"");return((/^[A-Za-z]/.test(e)?e:"")||(/^[A-Za-z]/.test(t)?t:"")||"Effect").slice(0,40)}function B(n){const e=/^(\d+)\.(\d+)\.(\d+)/.exec(String(n||"0.0.0")),t=Math.min(127,Number(e?e[1]:0)),r=Math.min(15,Number(e?e[2]:0)),s=Math.min(15,Number(e?e[3]:0)),f=3,u=1;return{value:((t>>3&15)<<26|(t&7)<<19|(r&15)<<15|(s&15)<<11|(f&3)<<9|u&511)>>>0,major:t,minor:r,bug:s,stage:f,build:u}}function U(n,{win:e,specVersion:t,version:r,entryPoint:s}){const f=t||S,u=s||"EffectMain",c=_=>Buffer.from([_&255]),a=_=>{const i=Buffer.alloc(2);return e?i.writeUInt16LE(_):i.writeUInt16BE(_),i},o=_=>{const i=Buffer.alloc(4);return e?i.writeUInt32LE(_>>>0):i.writeUInt32BE(_>>>0),i},p=_=>{const i=Buffer.from(_,"latin1");return e?Buffer.from(i).reverse():i},m=_=>_%4?4-_%4:0,P=_=>{const i=Buffer.concat([c(Buffer.byteLength(_)),Buffer.from(_,"utf8")]);return e?Buffer.concat([i,Buffer.alloc(m(i.length))]):i},L=_=>{const i=Buffer.concat([Buffer.from(_,"utf8"),Buffer.alloc(1)]);return e?Buffer.concat([i,Buffer.alloc(m(i.length))]):i},g=[],d=(_,i)=>g.push([_,i]);d("kind",p("eFKT")),d("name",P(n.name)),d("catg",P(n.category)),e?d("8664",L(u)):(d("ma64",P(u)),d("mi64",P(u))),d("ePVR",Buffer.concat([a(2),a(0)])),d("eSVR",Buffer.concat([a(f.major),a(f.minor)])),d("eVER",o(B(r).value)),d("eINF",e?o(0):a(0)),d("eGLO",o(n.outFlagsValue)),d("eGL2",o(n.outFlags2Value)),d("eMNA",P(n.matchName)),d("aeFL",o(0)),n.supportUrl&&d("eURL",P(n.supportUrl));const A=[];e&&A.push(Buffer.from([1,0])),A.push(o(0)),A.push(o(g.length));for(const[_,i]of g)A.push(p("8BIM"),p(_),o(0),o(i.length),i),e||A.push(Buffer.alloc(m(i.length)));return Buffer.concat(A)}function V(n,e){let t=0;const r=()=>{const c=e?n.readUInt32LE(t):n.readUInt32BE(t);return t+=4,c},s=()=>{const c=n.subarray(t,t+4);return t+=4,(e?Buffer.from(c).reverse():c).toString("latin1")};if(e){if(n[0]!==1||n[1]!==0)throw new Error("Windows PiPL must start with 01 00");t=2}if(r()!==0)throw new Error("unknown PiPL version");const f=r(),u={};for(let c=0;c<f;c++){const a=s(),o=s();r();const p=r();if(a!=="8BIM")throw new Error("unexpected vendor "+a);u[o]=n.subarray(t,t+p),t+=p,!e&&p%4&&(t+=4-p%4)}return u}function N(n,e,t){const s=Buffer.concat([Buffer.alloc(4),t]);s.writeUInt32BE(t.length,0);const f=256+s.length,u=28,c=u+2+8+12,a=Buffer.alloc(c);a.writeUInt16BE(u,24),a.writeUInt16BE(c,26),a.writeUInt16BE(0,28),a.write(n,30,"latin1"),a.writeUInt16BE(0,34),a.writeUInt16BE(10,36),a.writeInt16BE(e,38),a.writeUInt16BE(65535,40),a.writeUInt32BE(0,42),a.writeUInt32BE(0,46);const o=Buffer.alloc(16);o.writeUInt32BE(256,0),o.writeUInt32BE(f,4),o.writeUInt32BE(s.length,8),o.writeUInt32BE(a.length,12),o.copy(a,0);const p=Buffer.alloc(256);return o.copy(p,0),Buffer.concat([p,s,a])}function b(n,e){const t=n.readUInt32BE(0),r=n.readUInt32BE(4),s=r+n.readUInt16BE(r+24),f=n.readUInt16BE(s)+1;for(let u=0;u<f;u++){const c=s+2+u*8;if(n.toString("latin1",c,c+4)!==e)continue;const a=s+n.readUInt16BE(c+6),o=n.readUInt32BE(a+4)&16777215,p=n.readUInt32BE(t+o);return n.subarray(t+o+4,t+o+4+p)}return null}function l(n){let e='"';for(const t of Buffer.from(String(n),"utf8"))t>=32&&t<127&&t!==34&&t!==92&&t!==63?e+=String.fromCharCode(t):e+="\\"+t.toString(8).padStart(3,"0");return e+'"'}const h=n=>n.toUpperCase(),E=n=>{const e=String(n);return/[.eE]/.test(e)?e:e+".0"},k={off:"AP_UPDATES_OFF",manual:"AP_UPDATES_MANUAL",notify:"AP_UPDATES_NOTIFY",background:"AP_UPDATES_BACKGROUND"};function O(n,e){const t=e.settings,r=B(t.version),s=e.specVersion||S;return["// Generated by `ap build` from effect.json and afterpresets.json. Do not edit:","// change effect.json instead (the PiPL resource is generated from the same data).","#pragma once","","#define AP_EFFECT_NAME "+l(n.name),"#define AP_MATCH_NAME "+l(n.matchName),"#define AP_CATEGORY "+l(n.category),"#define AP_DESCRIPTION "+l(n.description),"#define AP_SUPPORT_URL "+l(n.supportUrl),"#define AP_BUNDLE_ID "+l(t.bundleId),"#define AP_VERSION "+l(t.version),"#define AP_VERSION_STRING AP_VERSION","#define AP_VERSION_MAJOR "+r.major,"#define AP_VERSION_MINOR "+r.minor,"#define AP_VERSION_BUG "+r.bug,"#define AP_VERSION_BUILD "+r.build,"#define AP_EFFECT_VERSION "+r.value+"u /* PF_VERSION("+[r.major,r.minor,r.bug,"PF_Stage_RELEASE",r.build].join(", ")+") */","#define AP_SPEC_VERSION_MAJOR "+s.major,"#define AP_SPEC_VERSION_MINOR "+s.minor,"#define AP_OUT_FLAGS "+n.outFlagsValue+"u /* "+n.outFlags.join(" | ")+" */","#define AP_OUT_FLAGS2 "+n.outFlags2Value+"u /* "+n.outFlags2.join(" | ")+" */","","// AfterPresets runtime (ap_native)","#define AP_DEV_BUILD "+(e.mode==="release"?0:1),"#define AP_BUILD_ID "+l(e.buildId||""),"#define AP_API_BASE "+l(e.apiBase||"https://api.afterpresets.com"),"#define AP_PUBLIC_KEY "+l(e.publicKey||""),"#define AP_PRODUCT_URL "+l(e.productUrl||""),"#define AP_MANAGE_DEVICES_URL "+l(e.manageDevicesUrl||""),"#define AP_LICENSE_ENABLED "+(n.license.enabled?1:0),"#define AP_OFFLINE_GRACE_DAYS "+n.license.offlineGraceDays,"#define AP_CHECK_IN_BACKGROUND "+(n.license.checkInBackground?1:0),"#define AP_UPDATE_MODE "+k[n.updates],""].join(`
2
+ `)}function M(n){const e="AP_ID_"+h(n.key),t=l(n.name);switch(n.type){case"slider":{const r={none:"PF_ValueDisplayFlag_NONE",percent:"PF_ValueDisplayFlag_PERCENT",pixels:"PF_ValueDisplayFlag_PIXEL"}[n.display];return"PF_ADD_FLOAT_SLIDERX("+[t,E(n.min),E(n.max),E(n.sliderMin),E(n.sliderMax),E(n.default),n.precision,r,0,e].join(", ")+");"}case"angle":return"PF_ADD_ANGLE("+[t,E(n.default),e].join(", ")+");";case"color":return"PF_ADD_COLOR("+[t,n.rgb[0],n.rgb[1],n.rgb[2],e].join(", ")+");";case"point":return"PF_ADD_POINT("+[t,E(n.default[0]),E(n.default[1]),"FALSE",e].join(", ")+");";case"checkbox":return"PF_ADD_CHECKBOX("+[t,l(n.label),n.default?"TRUE":"FALSE",0,e].join(", ")+");";case"popup":return"PF_ADD_POPUP("+[t,n.choices.length,n.defaultIndex,l(n.choices.join("|")),e].join(", ")+");"}throw new Error("unknown param type "+n.type)}function y(n){const e=[];e.push("// Generated by `ap build` from effect.json. Do not edit: change effect.json."),e.push("// Include after AE_Effect.h, AE_EffectVers.h, AE_Macros.h and Param_Utils.h."),e.push("#pragma once"),e.push('#include "ap_effect_config.h"'),e.push(""),e.push("// Parameter indices (params[AP_PARAM_X] in render calls). Index 0 is the input layer."),e.push("enum {"),e.push(" AP_PARAM_INPUT = 0,"),n.params.forEach(r=>e.push(" AP_PARAM_"+h(r.key)+",")),e.push(" AP_PARAM_LICENSE, // the AfterPresets status button, added last by ap_add_params"),e.push(" AP_PARAM_COUNT"),e.push("};"),e.push(""),e.push("// Permanent parameter ids from effect.json (saved projects match params by id)."),e.push("enum {"),n.params.forEach(r=>e.push(" AP_ID_"+h(r.key)+" = "+r.id+",")),e.push(" AP_ID_LICENSE = "+T),e.push("};");const t=n.params.filter(r=>r.type==="popup");return t.length&&(e.push(""),e.push("// Popup values (1-based, as After Effects reports them in u.pd.value)."),t.forEach(r=>{e.push("enum {"),r.choices.forEach((s,f)=>{const u=String(s).toUpperCase().replace(/[^A-Z0-9]+/g,"_").replace(/^_|_$/g,"")||"CHOICE";e.push(" AP_"+h(r.key)+"_"+u+"_"+(f+1)+" = "+(f+1)+",")}),e.push(" AP_"+h(r.key)+"_COUNT = "+r.choices.length),e.push("};")})),e.push(""),e.push("// The PiPL carries the same numbers: if a flag name drifts from the SDK, the build fails here."),e.push("static_assert(AP_OUT_FLAGS == (0"+n.outFlags.map(r=>" | PF_OutFlag_"+r).join("")+'), "effect.json outFlags do not match the SDK");'),e.push("static_assert(AP_OUT_FLAGS2 == (0"+n.outFlags2.map(r=>" | PF_OutFlag2_"+r).join("")+'), "effect.json outFlags2 do not match the SDK");'),e.push('static_assert(AP_EFFECT_VERSION == PF_VERSION(AP_VERSION_MAJOR, AP_VERSION_MINOR, AP_VERSION_BUG, PF_Stage_RELEASE, AP_VERSION_BUILD), "version encoding");'),e.push(""),e.push("// Adds every parameter from effect.json, then the status button. Call from PF_Cmd_PARAMS_SETUP."),e.push(`// licenseLabel: the button's caption (for example "Sign in").`),e.push("static inline PF_Err ap_add_params(PF_InData *in_data, PF_OutData *out_data, const char *statusName, const char *licenseLabel) {"),e.push(" PF_ParamDef def;"),n.params.forEach(r=>{e.push(" AEFX_CLR_STRUCT(def);"),e.push(" "+M(r))}),e.push(" AEFX_CLR_STRUCT(def);"),e.push(" PF_ADD_BUTTON(statusName, licenseLabel, 0, PF_ParamFlag_SUPERVISE | PF_ParamFlag_CANNOT_TIME_VARY, AP_ID_LICENSE);"),e.push(" out_data->num_params = AP_PARAM_COUNT;"),e.push(" return PF_Err_NONE;"),e.push("}"),e.push(""),e.join(`
3
+ `)}function R(n,e){const t=s=>String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),r=t(e.version);return`<?xml version="1.0" encoding="UTF-8"?>
4
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
5
+ <plist version="1.0">
6
+ <dict>
7
+ <key>CFBundleDevelopmentRegion</key><string>en</string>
8
+ <key>CFBundleExecutable</key><string>${t(n)}</string>
9
+ <key>CFBundleIdentifier</key><string>${t(e.bundleId)}</string>
10
+ <key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
11
+ <key>CFBundleName</key><string>${t(n)}</string>
12
+ <key>CFBundlePackageType</key><string>eFKT</string>
13
+ <key>CFBundleSignature</key><string>FXTC</string>
14
+ <key>CFBundleShortVersionString</key><string>${r}</string>
15
+ <key>CFBundleVersion</key><string>${r}</string>
16
+ <key>LSMinimumSystemVersion</key><string>12.0</string>
17
+ </dict>
18
+ </plist>
19
+ `}function j(n,e,t){const r=t.bundleName||D(t.settings);I.mkdirSync(e,{recursive:!0});const s={"ap_effect_config.h":O(n,t),"ap_effect_params.h":y(n),[r+".rsrc"]:N("PiPL",F,U(n,{win:!1,specVersion:t.specVersion,version:t.settings.version})),"pipl.bin":U(n,{win:!0,specVersion:t.specVersion,version:t.settings.version}),"pipl.rc":F+` PiPL DISCARDABLE "pipl.bin"
20
+ `,PkgInfo:"eFKTFXTC","Info.plist":R(r,t.settings)},f=[];return Object.keys(s).forEach(u=>{const c=C.join(e,u),a=Buffer.isBuffer(s[u])?s[u]:Buffer.from(s[u]);let o=!1;try{o=I.readFileSync(c).equals(a)}catch{o=!1}o||I.writeFileSync(c,a),f.push(c)}),{name:r,files:f}}module.exports={PIPL_RESOURCE_ID:F,DEFAULT_SPEC_VERSION:S,bundleName:D,effectVersion:B,buildPipl:U,parsePipl:V,buildRsrc:N,readRsrc:b,cString:l,configHeader:O,paramsHeader:y,infoPlist:R,generate:j};
@@ -0,0 +1,2 @@
1
+ "use strict";const{afterEffectsProcess:u}=require("./install");async function m(e,t){const r=await e.runCommand("/bin/ps",["-o","comm=","-p",String(t)],{quiet:!0}),n=String(r.stdout||"").trim(),s=/^(.*?\.app)\/Contents\/MacOS\//.exec(n);return s?s[1]:null}function w(){return"(function(){var p=app.project;return (p.dirty?'1':'0')+'\\n'+p.numItems+'\\n'+(p.file?p.file.fsName:'');})();"}function g(e){if(typeof e!="string")return{ok:!1,reason:"After Effects returned no project state."};const t=e.split(`
2
+ `);return t.length!==3||t[0]!=="0"&&t[0]!=="1"||!/^\d+$/.test(t[1])?{ok:!1,reason:"After Effects returned an unexpected project state."}:{ok:!0,dirty:t[0]==="1",numItems:Number(t[1]),file:t[2]||null}}async function c(e){if(typeof e!="function")return{ok:!1,reason:"no connection to After Effects (the dev bridge) to check the open project."};let t;try{t=await e(w())}catch(r){return{ok:!1,reason:"After Effects did not answer through the dev bridge ("+r.message+"); a dialog may be open."}}return!t||t.ok===!1?{ok:!1,reason:"After Effects did not answer through the dev bridge"+(t&&t.error?" ("+t.error+")":"")+"; a dialog may be open."}:g(t.result!==void 0?t.result:t.value)}function y(e,t){const r=t||{};return!e||e.ok!==!0||typeof e.dirty!="boolean"||typeof e.numItems!="number"?{safe:!1,reason:e&&e.reason||"the open project's state is unknown."}:r.scratch?{safe:!0,discard:!0,reason:"it is a scratch project made by the tools"}:e.numItems===0?{safe:!0,discard:!0,reason:"the project is empty"}:e.file?e.dirty?{safe:!1,reason:"the open project has unsaved changes."}:{safe:!0,discard:!1,reason:"the project is saved"}:{safe:!1,reason:"the open project has never been saved and has "+e.numItems+" item(s)."}}async function k(e,t,r,n){const s=e.now();for(;;){if(await t())return!0;if(e.now()-s>=r)return!1;await e.sleep(n)}}async function v(e,t){const r=t||{},n=f=>({restarted:!1,askUser:!0,reason:f,message:"Did not restart After Effects: "+f.replace(/\.$/,"")+". Ask the user to save their work and restart After Effects (File > Save, then quit and reopen it)."});if(e.platform==="win32")return{restarted:!1,askUser:!0,reason:"After Effects is not restarted automatically on Windows.",message:"After Effects is not restarted automatically on Windows. Ask the user to save their work and restart After Effects (File > Save, then quit and reopen it); it loads the new build at launch."};if(e.platform!=="darwin")return n("automatic restarts are macOS-only.");const s=e.now(),d=await u(e);if(!d.running)return{restarted:!1,askUser:!1,notRunning:!0,message:"After Effects is not running; it loads the new build when it starts."};const a=typeof r.evalScript=="function"?r.evalScript:null;if(!a)return n("no connection to After Effects (the dev bridge) to quit it safely.");const l=await m(e,d.pid);if(!l)return n("could not find the After Effects application.");const A=r.state||await c(a),o=y(A,r);if(!o.safe)return n(o.reason);const E=(o.discard?"app.project.close(CloseOptions.DO_NOT_SAVE_CHANGES);":"")+"app.quit();";try{await a("app.scheduleTask("+JSON.stringify(E)+", 500, false);'ok';")}catch{}const p=r.quitTimeoutMs||9e4;if(!await k(e,async()=>!(await u(e)).running,p,1e3))return n("After Effects did not quit within "+Math.round(p/1e3)+" s (it may be showing a dialog). It was not forced to quit.");const h=await e.runCommand("/usr/bin/open",["-a",l],{quiet:!0});if(h.code!==0)return n("After Effects quit but could not be started again ("+String(h.stderr||"").trim()+").");const b=await k(e,async()=>(await u(e)).running?r.waitForBridge?!!await r.waitForBridge():(await c(a)).ok:!1,r.launchTimeoutMs||24e4,2e3),i=Math.round((e.now()-s)/1e3);return b?{restarted:!0,askUser:!1,message:"Restarted After Effects ("+o.reason+") in "+i+" s; it loaded the new build.",seconds:i}:{restarted:!1,askUser:!0,reason:"not answering after launch",message:"After Effects was restarted but does not answer yet. It may be showing a dialog (for example a crash/Safe Mode prompt or a sign-in screen): ask the user what it shows.",seconds:i}}module.exports={restartAfterEffects:v,quitDecision:y,projectState:c,stateScript:w,parseState:g,afterEffectsAppPath:m};
@@ -0,0 +1,8 @@
1
+ "use strict";const k=require("crypto"),l=require("fs"),d=require("path"),{configDir:J}=require("../config"),w="https://developer.adobe.com/console/servicesandapis/ae",N="ap-sdk.json",D={major:13,minor:27},O=[{version:"27.0.0",os:"mac",spec:{major:13,minor:29},zipSha256:"7146a6b6bbb77404a6cab8d1aafe53a8554394af4648bbdde49a9e82f7cb8232",headersSha256:"92ed450fa5085afb3f3c74498a4fbbf9343e3b2ee65314e3c4043f773ccf0838",tested:!0}],R=["Examples/Headers/AE_Effect.h","Examples/Headers/AE_EffectVers.h","Examples/Headers/AE_EffectCB.h","Examples/Headers/AE_EffectSuites.h","Examples/Headers/AE_EffectCBSuites.h","Examples/Headers/AE_Macros.h","Examples/Headers/AEConfig.h","Examples/Headers/SP/SPBasic.h","Examples/Util/entry.h","Examples/Util/Param_Utils.h","Examples/Util/AEGP_SuiteHandler.h"],y={entries:1e4,totalBytes:400*1024*1024,fileBytes:100*1024*1024};function H(e){const t=/[_ -](mac|macos|osx|win|windows|win64)(?:[_ .-]|$)/i.exec(String(e||""));return t?/^win/i.test(t[1])?"win":"mac":null}function A(e){return e&&e.platform==="win32"?"%USERPROFILE%\\Downloads":"~/Downloads"}function G(e){return e&&e.platform==="win32"?"%USERPROFILE%\\.afterpresets\\sdk\\":"~/.afterpresets/sdk/"}function X(){return w}function _(e){return d.join(J(e),"sdk")}function M(e,t){const s=String(e).split(".").map(Number),n=String(t).split(".").map(Number);for(let r=0;r<3;r++){const f=(s[r]||0)-(n[r]||0);if(f)return f}return 0}function g(e){let t;try{t=l.readFileSync(d.join(e,"Examples/Headers/AE_EffectVers.h"),"utf8")}catch{return null}const s=/#define\s+PF_PLUG_IN_VERSION\s+(\d+)/.exec(t),n=/#define\s+PF_PLUG_IN_SUBVERS\s+(\d+)/.exec(t);return s&&n?{major:Number(s[1]),minor:Number(n[1])}:null}function x(e){const t=d.join(e,"Examples","Headers"),s=[];return(function n(r,f){for(const i of l.readdirSync(r,{withFileTypes:!0})){if(i.name===".DS_Store")continue;const c=d.join(r,i.name),a=f?f+"/"+i.name:i.name;i.isDirectory()?n(c,a):i.isFile()&&s.push(a+"\0"+k.createHash("sha256").update(l.readFileSync(c)).digest("hex")+`
2
+ `)}})(t,""),s.sort(),k.createHash("sha256").update(s.join("")).digest("hex")}function Z(e){return k.createHash("sha256").update(l.readFileSync(e)).digest("hex")}function v(e){return R.filter(t=>!l.existsSync(d.join(e,t)))}function U(e){try{return JSON.parse(l.readFileSync(d.join(e,N),"utf8"))}catch{return null}}function B(e){return{version:e.version,root:e.root,headersDir:d.join(e.root,"Examples","Headers"),utilDir:d.join(e.root,"Examples","Util"),specVersion:e.specVersion,verified:!!e.verified,tested:!!e.tested}}function b(e,t){const s=t||{},n=_(e),r=e.env&&e.env.AP_AE_SDK_DIR;if(r){const o=d.resolve(r),m=v(o);if(m.length)return{found:!1,sdk:null,versions:[],cacheDir:n,message:"AP_AE_SDK_DIR ("+o+") is not an After Effects SDK folder: "+m[0]+" is missing."};const u=B({version:"custom",root:o,specVersion:g(o),verified:!1});return{found:!0,sdk:u,versions:[u],cacheDir:n,message:"Using the After Effects SDK at "+o+" (AP_AE_SDK_DIR)."}}let f=[];try{f=l.readdirSync(n)}catch{f=[]}const i=f.filter(o=>/^\d+\.\d+(\.\d+)?$/.test(o)).map(o=>{const m=d.join(n,o),u=U(m);return!u||v(m).length?null:B({version:o,root:m,specVersion:u.specVersion||g(m),verified:u.verified,tested:u.tested})}).filter(Boolean).sort((o,m)=>M(m.version,o.version)),c=s.version?i.find(o=>o.version===s.version)||null:i[0]||null;let a;return c?a="After Effects SDK "+c.version+" is installed ("+c.root+").":s.version&&i.length?a="After Effects SDK "+s.version+" is not installed; installed: "+i.map(o=>o.version).join(", ")+".":a=j(e),{found:!!c,sdk:c,versions:i,cacheDir:n,message:a}}function j(e){const t=!!(e&&e.platform==="win32");return`The After Effects SDK is not installed. Ask the user to download it once (it needs a free Adobe ID, so you cannot download it yourself):
3
+ 1. Open `+w+` and sign in.
4
+ `+(t?` 2. Download "After Effects SDK" for Windows (a file like AfterEffectsSDK_27.0.0_win.zip lands in Downloads).
5
+ `:` 2. Download "After Effects SDK" for macOS (a file like AfterEffectsSDK_27.0.0_mac.zip lands in Downloads).
6
+ `)+" 3. Run `ap sdk install` (it finds the download in "+A(e)+" and unpacks it into "+G(e)+")."}function K(e){const t=r=>l.existsSync(d.join(r,"Examples","Headers","AE_Effect.h"));if(t(e))return e;let s=[];try{s=l.readdirSync(e,{withFileTypes:!0})}catch{return null}const n=s.filter(r=>r.isDirectory()&&!r.isSymbolicLink()&&r.name!=="__MACOSX").map(r=>d.join(e,r.name)).filter(t);return n.length===1?n[0]:null}function z(e){const t=d.join(e.homeDir,"Downloads");let s=[];try{s=l.readdirSync(t,{withFileTypes:!0})}catch{return null}const n=[];for(const r of s){if(!/^AfterEffectsSDK/i.test(r.name))continue;const f=d.join(t,r.name);let i;try{i=l.lstatSync(f)}catch{continue}i.isSymbolicLink()||(i.isFile()&&/\.zip$/i.test(r.name)?n.push({path:f,kind:"zip",mtime:i.mtimeMs}):i.isDirectory()&&K(f)&&n.push({path:f,kind:"dir",mtime:i.mtimeMs}))}return n.sort((r,f)=>f.mtime-r.mtime),n[0]||null}async function Q(e,t){const s=t||{},n=s.timeoutMs===void 0?600*1e3:s.timeoutMs,r=s.intervalMs||2e3,f=e.now();for(;;){const i=z(e);if(i&&i.kind==="dir")return i;if(i&&i.kind==="zip"){const c=l.statSync(i.path).size;if(await e.sleep(Math.min(r,1e3)),l.existsSync(i.path)&&l.statSync(i.path).size===c&&c>0)return i}if(e.now()-f>=n)return null;await e.sleep(r)}}function L(e){if(typeof e!="string"||!e||e.indexOf("\0")!==-1)throw new Error("empty or invalid name");if(e=e.replace(/\\/g,"/"),e.startsWith("/")||/^[A-Za-z]:/.test(e))throw new Error("absolute path "+JSON.stringify(e));const t=e.split("/").filter(s=>s!==""&&s!==".");if(t.some(s=>s===".."))throw new Error("'..' in "+JSON.stringify(e));return t.join("/")}function Y(e){const t=e.header&&e.header.attr;return typeof t=="number"&&(t>>>16&61440)===40960}function V(e){const t=e.split("/");return t[0]==="__MACOSX"||t[t.length-1]===".DS_Store"||t.some(s=>s.startsWith("._"))}function W(e,t,s){const n=d.resolve(e,t);if(n!==e&&!n.startsWith(e+d.sep))throw new Error("path escapes the folder: "+t);l.mkdirSync(d.dirname(n),{recursive:!0}),l.writeFileSync(n,s,{mode:420})}function ee(e,t){const s=require("adm-zip");let n;try{n=new s(e)}catch(a){throw new Error("could not read the zip ("+a.message+")")}const r=n.getEntries();if(r.length>y.entries)throw new Error("too many files ("+r.length+")");let f=0;const i=[];for(const a of r){const o=L(a.entryName);if(!o||V(o))continue;if(Y(a))throw new Error("it contains a symbolic link ("+o+"); a real SDK zip has none");if(a.isDirectory)continue;const m=a.header.size;if(m>y.fileBytes)throw new Error(o+" is too large");if(f+=m,f>y.totalBytes)throw new Error("it unpacks to more than "+y.totalBytes/1048576+" MB");i.push({entry:a,rel:o})}const c=ne(i.map(a=>a.rel));for(const a of i){if(c&&!a.rel.startsWith(c+"/"))continue;const o=a.entry.getData();if(o.length!==a.entry.header.size)throw new Error(a.rel+" is damaged");W(t,c?a.rel.slice(c.length+1):a.rel,o)}}function te(e,t){let s=0,n=0,r=0;return(function f(i,c){for(const a of l.readdirSync(i,{withFileTypes:!0})){const o=c?c+"/"+a.name:a.name;if(V(o))continue;const m=d.join(i,a.name),u=l.lstatSync(m);if(u.isSymbolicLink()){s++;continue}if(u.isDirectory())f(m,o);else if(u.isFile()){if(r++,n+=u.size,r>y.entries||n>y.totalBytes)throw new Error("the folder is too large to be the SDK");W(t,o,l.readFileSync(m))}}})(e,""),s}function ne(e){const t=e.filter(s=>s==="Examples/Headers/AE_Effect.h"||s.endsWith("/Examples/Headers/AE_Effect.h"));return t.length===1?t[0].slice(0,-28).replace(/\/$/,""):se(e)}function se(e){if(!e.length)return"";const t=e[0].split("/")[0];return e.every(s=>s.split("/")[0]===t&&s.indexOf("/")!==-1)&&e.some(s=>s.startsWith(t+"/Examples/"))?t:""}async function C(e,t,s){const n=e.platform==="win32"?10:1;for(let r=1;;r++)try{l.renameSync(t,s);return}catch(f){if(r>=n||!/^(EPERM|EBUSY|EACCES)$/.test(f.code))throw f;await(e.sleep?e.sleep(300*r):new Promise(i=>setTimeout(i,300*r)))}}function T(e){l.rmSync(e,{recursive:!0,force:!0})}async function re(e,t){const s=t||{};let n=s.zipPath?d.resolve(e.cwd||process.cwd(),s.zipPath):null,r;if(n){let o;try{o=l.statSync(n)}catch{return{ok:!1,message:"No file at "+n+"."}}r=o.isDirectory()?"dir":"zip"}else{const o=z(e);if(!o)return{ok:!1,message:"No AfterEffectsSDK zip or folder found in "+A(e)+`.
7
+ `+j(e)};n=o.path,r=o.kind}const f=d.basename(n);r==="dir"&&(n=K(n)||n);const i=_(e);l.mkdirSync(i,{recursive:!0});const c=l.mkdtempSync(d.join(i,".staging-")),a=[];try{const o=r==="zip"?Z(n):null;try{if(r==="zip")ee(n,c);else{const p=te(n,c);p&&a.push(p+" symbolic link(s) in the folder were skipped.")}}catch(p){return{ok:!1,message:d.basename(n)+" was not installed: "+p.message+"."}}const m=v(c);if(m.length)return{ok:!1,message:d.basename(n)+" is not the After Effects SDK ("+m[0]+' is missing). Download "After Effects SDK" from '+w+"."};const u=g(c);if(!u)return{ok:!1,message:"Could not read the API version from AE_EffectVers.h in "+d.basename(n)+"."};if(u.major<D.major||u.major===D.major&&u.minor<D.minor)return{ok:!1,message:"This SDK is too old (API "+u.major+"."+u.minor+"). Download the current After Effects SDK from "+w+"."};const I=x(c),E=O.find(p=>o&&p.zipSha256===o||p.headersSha256===I),P=/AfterEffectsSDK[_ -]?v?(\d+\.\d+(?:\.\d+)?)/i.exec(f)||/AfterEffectsSDK[_ -]?v?(\d+\.\d+(?:\.\d+)?)/i.exec(d.basename(n)),F=E?E.os:H(f);let h=E?E.version:P?P[1]:null;if(h&&/^\d+\.\d+$/.test(h)&&(h+=".0"),!h)return{ok:!1,message:"Could not tell which SDK version "+d.basename(n)+" is. Keep Adobe's file name (AfterEffectsSDK_<version>_"+(e.platform==="win32"?"win":"mac")+".zip) and try again."};E||a.push("SDK "+h+(F==="win"?" (Windows download)":"")+" is not in AfterPresets' tested list yet (its download is unverified); it has the right structure and API version, so it should work. Report problems with `ap` feedback.");const S=d.join(i,h);if(l.existsSync(S)&&U(S)&&!s.force){const p=b(e,{version:h}).sdk;return Object.assign({ok:!0,alreadyInstalled:!0,warnings:a,message:"After Effects SDK "+h+" is already installed ("+S+")."},p||{version:h,root:S})}const $={version:h,specVersion:u,source:f,os:F||null,zipSha256:o,headersSha256:I,verified:!!E,tested:!!(E&&E.tested),installedAt:new Date(e.now?e.now():Date.now()).toISOString()};if(l.writeFileSync(d.join(c,N),JSON.stringify($,null,2)+`
8
+ `),l.existsSync(S)){const p=S+".old-"+process.pid;await C(e,S,p),T(p)}await C(e,c,S);const q=b(e,{version:h}).sdk;return Object.assign({ok:!0,alreadyInstalled:!1,warnings:a,message:"Installed After Effects SDK "+h+" (API "+u.major+"."+u.minor+") into "+S+"."},q)}finally{l.existsSync(c)&&T(c)}}module.exports={SDK_DOWNLOAD_URL:w,KNOWN_SDKS:O,REQUIRED_FILES:R,MIN_SPEC:D,sdkDownloadUrl:X,sdkOsFromName:H,sdkRootIn:K,downloadsLabel:A,cacheRoot:_,findSdk:b,installSdk:re,findDownloadedSdk:z,waitForDownloadedSdk:Q,notInstalledMessage:j,readSpecVersion:g,headersDigest:x,safeEntryName:L,compareVersions:M};
@@ -1,3 +1,3 @@
1
- "use strict";const a=require("fs"),t=require("path"),{CliError:l}=require("../errors"),{projectTargets:h}=require("../targets"),p=t.join("docs","afterpresets");function f(s,i){if(!a.existsSync(s))return[];const o=[];return a.readdirSync(s,{withFileTypes:!0}).forEach(e=>{const n=i?i+"/"+e.name:e.name;e.isDirectory()?o.push.apply(o,f(t.join(s,e.name),n)):e.isFile()&&/\.md$/i.test(e.name)&&o.push(n)}),o.sort()}const d=/^host-.+\.md$/;function j(s,i){const o=i.platform,e=h(i).map(c=>c.docsPage).filter(Boolean),n=[];return["common",o].forEach(c=>{f(t.join(s,c),"").forEach(u=>{const r=t.posix.basename(u);if(!(d.test(r)&&e.indexOf(r)===-1)){if(n.some(m=>m.name===r))throw new l("The runtime docs have two files named "+r+".");n.push({name:r,from:t.join(s,c,u.split("/").join(t.sep))})}})}),n}function y(s,i){return s.split(`
2
- `).filter(o=>(o.match(/\]\((host-[^)#\s]+\.md)/g)||[]).every(n=>i.indexOf(n.slice(2))!==-1)).join(`
3
- `)}function w(s,i,o){const e=t.join(s,"docs"),n=j(e,o);if(!n.length)throw new l("The installed @afterpresets/runtime has no docs/*.md files ("+e+").",{hint:"Update the CLI with `ap upgrade`."});const c=t.join(i,p);a.rmSync(c,{recursive:!0,force:!0});const u=n.map(r=>r.name);return n.forEach(r=>{const m=t.join(c,r.name.split("/").join(t.sep));a.mkdirSync(t.dirname(m),{recursive:!0}),a.writeFileSync(m,y(a.readFileSync(r.from,"utf8"),u))}),{target:c,files:u.sort()}}module.exports={PROJECT_DOCS_DIR:p,syncRuntimeDocs:w,markdownFiles:f};
1
+ "use strict";const i=require("fs"),e=require("path"),{CliError:y}=require("../errors"),{projectTargets:D}=require("../targets"),{configDir:k}=require("../config"),p=e.join("docs","afterpresets");function h(n,r){if(!i.existsSync(n))return[];const t=[];return i.readdirSync(n,{withFileTypes:!0}).forEach(s=>{if(s.name.charAt(0)===".")return;const o=r?r+"/"+s.name:s.name;s.isDirectory()?t.push.apply(t,h(e.join(n,s.name),o)):s.isFile()&&/\.md$/i.test(s.name)&&t.push(o)}),t.sort()}const w=/^host-.+\.md$/;function v(n,r){const t=r.platform,s=D(r).map(u=>u.docsPage).filter(Boolean),o=[];return(t==="native"?["native"]:["common",t]).forEach(u=>{h(e.join(n,u),"").forEach(c=>{const a=e.posix.basename(c);if(!(w.test(a)&&s.indexOf(a)===-1)){if(o.some(f=>f.name===a))throw new y("The runtime docs have two files named "+a+".");o.push({name:a,from:e.join(n,u,c.split("/").join(e.sep))})}})}),o}function A(n,r){return n.split(`
2
+ `).filter(t=>(t.match(/\]\((host-[^)#\s]+\.md)/g)||[]).every(o=>r.indexOf(o.slice(2))!==-1)).join(`
3
+ `)}function T(n,r,t){const s=e.join(n,"docs"),o=v(s,t);if(!o.length)throw new y("The installed @afterpresets/runtime has no docs/*.md files ("+s+").",{hint:"Update the CLI with `ap upgrade`."});const u=e.join(r,p);x(u,t.platform==="native"?[m]:[]);const c=o.map(a=>a.name);return o.forEach(a=>{const f=e.join(u,a.name.split("/").join(e.sep));i.mkdirSync(e.dirname(f),{recursive:!0}),i.writeFileSync(f,A(i.readFileSync(a.from,"utf8"),c))}),{target:u,files:c.sort()}}function x(n,r){if(!r.length||!i.existsSync(n)){i.rmSync(n,{recursive:!0,force:!0});return}i.readdirSync(n).forEach(t=>{r.indexOf(t)===-1&&i.rmSync(e.join(n,t),{recursive:!0,force:!0})})}const m="sdk";function N(n){const r=e.join(n,"scripts","ae-sdk-docs");if(!i.existsSync(e.join(r,"index.js")))return null;const t=require(e.join(r,"index.js")),s=require(e.join(r,"config.js"));return{generate:t.generate,manifestName:t.MANIFEST,version:t.GENERATOR_VERSION,pin:s.PIN}}function O(n){try{return JSON.parse(i.readFileSync(n,"utf8"))}catch{return null}}async function I(n,r,t,s,o){o=o||{};const u=e.join(t,p),c=e.join(u,m),a=e.posix.join(p.split(e.sep).join("/"),m)+"/";if(!s||s.platform!=="native")return{status:"skipped",dir:c,files:[],message:"Not a native project."};const f=r?N(r):null;if(!f)return{status:"skipped",dir:c,files:[],message:"This CLI has no SDK guide generator, so "+a+" was not made.",hint:"Update the CLI with `ap upgrade`."};const g=O(e.join(c,f.manifestName)),S=()=>h(c,"").map(d=>m+"/"+d);if(!o.force&&g&&g.commit===f.pin.commit&&g.generator===f.version&&i.existsSync(e.join(c,"README.md")))return{status:"current",dir:c,files:S(),message:"The After Effects SDK guide in "+a+" is up to date."};i.mkdirSync(u,{recursive:!0});const j=i.mkdtempSync(e.join(u,".sdk-"));try{const d=o.cacheDir||e.join(k(n),"cache"),l=await f.generate({out:j,cacheDir:d,fetch:o.fetch,quiet:!0});return i.rmSync(c,{recursive:!0,force:!0}),i.renameSync(j,c),{status:"generated",dir:c,files:S(),message:"Converted Adobe's After Effects SDK guide into "+a+" ("+l.files.length+" files, ~"+Math.round(l.totalTokens/1e3)+"k tokens)."}}catch(d){i.rmSync(j,{recursive:!0,force:!0});const l=i.existsSync(e.join(c,"README.md")),E=/fetch failed|ENOTFOUND|EAI_AGAIN|ECONN|ETIMEDOUT|network|Download failed/i.test(String(d&&d.message+" "+(d.cause&&d.cause.code)));return{status:"failed",dir:c,files:l?S():[],message:(E?"Could not download Adobe's After Effects SDK guide (no internet connection?)":"Could not convert Adobe's After Effects SDK guide: "+d.message)+(l?". The older copy in "+a+" is kept.":". "+a+" is missing until it works."),hint:"Connect to the internet and run `ap docs` again. It is downloaded once per computer, then works offline."}}}module.exports={PROJECT_DOCS_DIR:p,SDK_DIR:m,syncRuntimeDocs:T,ensureSdkDocs:I,markdownFiles:h};
@@ -1,2 +1,2 @@
1
- "use strict";const f=require("fs"),p=require("path"),m=require("./semver"),{normalizePanels:g}=require("./panels"),{CliError:s}=require("../errors"),l=require("../targets"),r="afterpresets.json";function h(e){let t=p.resolve(e);for(;;){if(f.existsSync(p.join(t,r)))return t;const n=p.dirname(t);if(n===t)return null;t=n}}function u(e){try{return JSON.parse(f.readFileSync(p.join(e,r),"utf8"))}catch(t){throw new s(r+" is not valid JSON: "+t.message)}}function j(e,t){const n=t&&typeof t=="object"?t:{},o=l.targetFor(e,n.app);if(!o){const a=l.TARGETS.filter(c=>c.platform===e).map(c=>JSON.stringify(c.host));throw new s(r+": "+JSON.stringify(n.app)+" is not a "+e.toUpperCase()+" host. Use "+a.join(" or ")+".")}const i=String(n.minVersion||o.minVersion||"");if(!/^\d+(\.\d+){0,2}$/.test(i))throw new s(r+": minVersion of "+o.host+' must look like "'+(o.minVersion||"25.6.0")+'"; got '+JSON.stringify(i)+".");return{app:o.host,minVersion:i}}function d(e){const t=e.platform;if(!l.PLATFORMS[t])throw new s(r+': "platform" must be "cep" or "uxp"; got '+JSON.stringify(t)+".");const n=e.hosts;if(!Array.isArray(n)||!n.length)throw new s(r+': "hosts" must list at least one app, e.g. [{ "app": "AEFT" }].');if(t==="uxp"&&n.length!==1)throw new s(r+": a UXP plugin runs in exactly one app.");const o=[];return n.forEach(i=>{const a=j(t,i);o.some(c=>c.app===a.app)||o.push(a)}),{platform:t,hosts:o}}function y(e){const t=h(e.cwd);if(!t)throw new s("No "+r+" found in this folder or its parents.",{hint:"Run this inside a project created with `ap init <dir>`."});const n=u(t);if(!n.bundleId)throw new s(r+" has no bundleId.");if(!m.isValid(n.version))throw new s(r+' has an invalid "version": '+JSON.stringify(n.version)+".",{hint:'Use MAJOR.MINOR.PATCH, for example "0.1.0". `ap push` bumps it for you.'});const o=d(n),i=Object.assign({},n,{platform:o.platform,hosts:o.hosts,name:n.name||n.bundleId}),a=g(i);return{root:t,settings:i,panels:a,version:n.version}}function w(e,t){f.writeFileSync(p.join(e,r),JSON.stringify(t,null,2)+`
2
- `)}function O(e,t){const n=u(e);return Object.assign(n,t),w(e,n),n}module.exports={PROJECT_FILE:r,findProjectRoot:h,readProjectFile:u,normalizeTarget:d,loadProject:y,writeProjectFile:w,updateProjectFile:O};
1
+ "use strict";const f=require("fs"),p=require("path"),m=require("./semver"),{normalizePanels:v}=require("./panels"),{CliError:i}=require("../errors"),u=require("../targets"),o="afterpresets.json";function h(e){let t=p.resolve(e);for(;;){if(f.existsSync(p.join(t,o)))return t;const n=p.dirname(t);if(n===t)return null;t=n}}function l(e){try{return JSON.parse(f.readFileSync(p.join(e,o),"utf8").replace(/^\ufeff/,""))}catch(t){throw new i(o+" is not valid JSON: "+t.message)}}function w(e){return!!e&&e.platform==="native"}function j(e,t){const n=typeof t=="string"&&e==="native"?{app:t}:t&&typeof t=="object"?t:{},r=u.targetFor(e,n.app);if(!r){const a=u.TARGETS.filter(c=>c.platform===e).map(c=>JSON.stringify(c.host));throw new i(o+": "+JSON.stringify(n.app)+" is not a "+e.toUpperCase()+" host. Use "+a.join(" or ")+".")}const s=String(n.minVersion||r.minVersion||"");if(!/^\d+(\.\d+){0,2}$/.test(s))throw new i(o+": minVersion of "+r.host+' must look like "'+(r.minVersion||"25.6.0")+'"; got '+JSON.stringify(s)+".");return{app:r.host,minVersion:s}}function d(e){const t=e.platform;if(!u.PLATFORMS[t])throw new i(o+': "platform" must be "cep", "uxp" or "native"; got '+JSON.stringify(t)+".");const n=e.hosts;if(!Array.isArray(n)||!n.length)throw new i(o+': "hosts" must list at least one app, e.g. [{ "app": "AEFT" }].');if(t==="uxp"&&n.length!==1)throw new i(o+": a UXP plugin runs in exactly one app.");if(t==="native"&&n.length!==1)throw new i(o+': a native effect plugin targets one app: "hosts": ["AEFT"].');const r=[];return n.forEach(s=>{const a=j(t,s);r.some(c=>c.app===a.app)||r.push(a)}),{platform:t,hosts:r}}function O(e){const t=h(e.cwd);if(!t)throw new i("No "+o+" found in this folder or its parents.",{hint:"Run this inside a project created with `ap init <dir>`."});const n=l(t);if(!n.bundleId)throw new i(o+" has no bundleId.");if(!m.isValid(n.version))throw new i(o+' has an invalid "version": '+JSON.stringify(n.version)+".",{hint:'Use MAJOR.MINOR.PATCH, for example "0.1.0". `ap push` bumps it for you.'});const r=d(n),s=Object.assign({},n,{platform:r.platform,hosts:r.hosts,name:n.name||n.bundleId}),a=w(s)?[]:v(s);return{root:t,settings:s,panels:a,version:n.version}}function g(e,t){f.writeFileSync(p.join(e,o),JSON.stringify(t,null,2)+`
2
+ `)}function S(e,t){const n=l(e);return Object.assign(n,t),g(e,n),n}module.exports={PROJECT_FILE:o,isNative:w,findProjectRoot:h,readProjectFile:l,normalizeTarget:d,loadProject:O,writeProjectFile:g,updateProjectFile:S};
@@ -1,4 +1,5 @@
1
- "use strict";const i=require("fs"),r=require("path"),f=r.join(__dirname,"..","..","template"),x="AGENTS.host.md",_=[".md",".json",".xml",".html",".js",".jsx",".css",".txt",""],T={gitignore:".gitignore"};function y(e,t){return Object.keys(t).reduce((o,s)=>o.split("__"+s+"__").join(t[s]),e)}function S(e,t,o,s){const m=o||f,a=[];return(function j(c,n){i.mkdirSync(n,{recursive:!0}),i.readdirSync(c,{withFileTypes:!0}).forEach(p=>{if(p.name===".DS_Store"||s&&s.indexOf(p.name)!==-1)return;const h=r.join(c,p.name),l=r.join(n,T[p.name]||p.name);if(p.isDirectory())return j(h,l);const u=r.extname(p.name).toLowerCase();if(_.indexOf(u)!==-1){const d=u===".xml"||u===".html"?N(t):t,O=u===".json"||u===".js"||u===".jsx"?D(t):d;i.writeFileSync(l,y(i.readFileSync(h,"utf8"),O))}else i.copyFileSync(h,l);a.push(l)})})(m,e),a}function N(e){const t={};return Object.keys(e).forEach(o=>{t[o]=String(e[o]).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}),t}function D(e){const t={};return Object.keys(e).forEach(o=>{t[o]=JSON.stringify(String(e[o])).slice(1,-1)}),t}function E(e,t){const o=t||f,s=[];e.forEach(n=>s.indexOf(n.appName)===-1&&s.push(n.appName));const m=[];e.forEach(n=>n.homeItem&&m.indexOf(n.homeItem)===-1&&m.push(n.homeItem));const a=e.filter(n=>n.jsxDir).map(n=>"jsx/"+n.jsxDir+"/home.jsx"),j=e.map(n=>r.join(o,"hosts",n.jsxDir||n.key,x)).filter(n=>i.existsSync(n)).map(n=>i.readFileSync(n,"utf8").trim()+`
2
- `),c=e.length===1?e[0].hostEvalUndo||"":e.map(n=>"in "+n.appName+", "+(n.hostEvalUndo||"")).join("; ");return{APP_NAME:s.join(" or "),APP_NAMES:s.join(" and "),HOME_ITEM:m.join(" or "),HOME_JSX:a.map(n=>"`"+n+"`").join(" and "),HOME_JSX_ROWS:e.filter(n=>n.jsxDir).map(n=>"| `jsx/"+n.jsxDir+"/home.jsx` | Starter example ("+n.appName+"): reads the active "+n.homeItem+" |").join(`
3
- `),HOST_EVAL_UNDO:c,HOST_NOTES:j.join(`
4
- `)}}function A(e,t,o,s){const m=s||f,a=o[0].platform,j=Object.assign({},E(o,m),t),c=S(e,j,r.join(m,a));return o.forEach(n=>{const p=r.join(m,"hosts",n.jsxDir||n.key);i.existsSync(p)&&c.push.apply(c,S(e,j,p,[x]))}),c}function I(e,t,o,s){const m=r.join(s||f,"hosts",o.jsxDir||o.key);if(!i.existsSync(m))return[];const a=i.mkdtempSync(r.join(require("os").tmpdir(),"ap-host-"));try{const j=Object.assign({},E([o],s),t);return S(a,j,m,[x]).map(c=>r.relative(a,c)).filter(c=>{const n=r.join(e,c);return i.existsSync(n)?!1:(i.mkdirSync(r.dirname(n),{recursive:!0}),i.copyFileSync(r.join(a,c),n),!0)})}finally{i.rmSync(a,{recursive:!0,force:!0})}}module.exports={TEMPLATE_DIR:f,copyTemplate:S,copyProjectTemplate:A,copyHostStarter:I,hostValues:E,fill:y};
1
+ "use strict";const s=require("fs"),r=require("path"),j=r.join(__dirname,"..","..","template"),x="AGENTS.host.md",N="AGENTS.two-apps.md",D=[".md",".json",".xml",".html",".js",".jsx",".css",".txt",""],A=[".c",".cc",".cpp",".h",".hpp",".mm",".cmake",".rc",".plist"],I={gitignore:".gitignore"};function y(e,t){return Object.keys(t).reduce((o,i)=>o.split("__"+i+"__").join(t[i]),e)}function S(e,t,o,i){const m=o||j,a=[];return(function f(c,n){s.mkdirSync(n,{recursive:!0}),s.readdirSync(c,{withFileTypes:!0}).forEach(p=>{if(p.name===".DS_Store"||i&&i.indexOf(p.name)!==-1)return;const h=r.join(c,p.name),u=r.join(n,I[p.name]||p.name);if(p.isDirectory())return f(h,u);const l=r.extname(p.name).toLowerCase(),d=A.indexOf(l)!==-1||p.name==="CMakeLists.txt";if(d||D.indexOf(l)!==-1){const _=l===".xml"||l===".html"||l===".plist"?F(t):t,T=d&&l!==".plist"||l===".json"||l===".js"||l===".jsx"?O(t):_;s.writeFileSync(u,y(s.readFileSync(h,"utf8"),T))}else s.copyFileSync(h,u);a.push(u)})})(m,e),a}function F(e){const t={};return Object.keys(e).forEach(o=>{t[o]=String(e[o]).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}),t}function O(e){const t={};return Object.keys(e).forEach(o=>{t[o]=JSON.stringify(String(e[o])).slice(1,-1)}),t}function E(e,t){const o=t||j,i=[];e.forEach(n=>i.indexOf(n.appName)===-1&&i.push(n.appName));const m=[];e.forEach(n=>n.homeItem&&m.indexOf(n.homeItem)===-1&&m.push(n.homeItem));const a=e.filter(n=>n.jsxDir).map(n=>"jsx/"+n.jsxDir+"/home.jsx"),f=e.filter(n=>n.platform!=="native").map(n=>r.join(o,"hosts",n.jsxDir||n.key,x)).filter(n=>s.existsSync(n)).map(n=>s.readFileSync(n,"utf8").trim()+`
2
+ `);f.length>1&&f.push(s.readFileSync(r.join(o,"hosts",N),"utf8").trim()+`
3
+ `);const c=e.length===1?e[0].hostEvalUndo||"":e.map(n=>"in "+n.appName+", "+(n.hostEvalUndo||"")).join("; ");return{APP_NAME:i.join(" or "),APP_NAMES:i.join(" and "),HOME_ITEM:m.join(" or "),HOME_JSX:a.map(n=>"`"+n+"`").join(" and "),HOME_JSX_ROWS:e.filter(n=>n.jsxDir).map(n=>"| `jsx/"+n.jsxDir+"/home.jsx` | Starter example ("+n.appName+"): reads the active "+n.homeItem+" |").join(`
4
+ `),HOST_EVAL_UNDO:c,HOST_NOTES:f.join(`
5
+ `)}}function M(e,t,o,i){const m=i||j,a=o[0].platform,f=Object.assign({},E(o,m),t),c=S(e,f,r.join(m,a));return a==="native"||o.forEach(n=>{const p=r.join(m,"hosts",n.jsxDir||n.key);s.existsSync(p)&&c.push.apply(c,S(e,f,p,[x]))}),c}function P(e,t,o,i){const m=r.join(i||j,"hosts",o.jsxDir||o.key);if(!s.existsSync(m))return[];const a=s.mkdtempSync(r.join(require("os").tmpdir(),"ap-host-"));try{const f=Object.assign({},E([o],i),t);return S(a,f,m,[x]).map(c=>r.relative(a,c)).filter(c=>{const n=r.join(e,c);return s.existsSync(n)?!1:(s.mkdirSync(r.dirname(n),{recursive:!0}),s.copyFileSync(r.join(a,c),n),!0)})}finally{s.rmSync(a,{recursive:!0,force:!0})}}module.exports={TEMPLATE_DIR:j,copyTemplate:S,copyProjectTemplate:M,copyHostStarter:P,hostValues:E,fill:y};
package/src/prompt.js CHANGED
@@ -1 +1 @@
1
- "use strict";const b=require("readline"),{UsageError:v}=require("./errors");function y(n,a){function t(e,l){const u=l||{};return new Promise(c=>{const o=b.createInterface({input:n,output:a});let f=null,d=!1;if(u.live&&a.isTTY){const s=u.live.linesUp||1;f=(r,i)=>{d||i&&(i.name==="return"||i.name==="enter")||setImmediate(()=>{d||a.write("\x1B7\x1B["+s+"A\r\x1B[2K"+u.live.render(o.line)+"\x1B8")})},n.on("keypress",f)}o.question(e,s=>{d=!0,f&&n.removeListener("keypress",f),o.close(),c(s)}),u.prefill&&o.write(String(u.prefill))})}return{question:t}}function h(n,a,t){const e=n.out.style;n.out.log(""),n.out.log(e.cyan("?")+" "+e.bold(a)),[].concat(t||[]).forEach(l=>n.out.log(" "+(typeof l=="string"?e.dim(l):l.plain)))}function w(n){return" "+n.out.style.magenta("\u203A")+" "}async function m(n,a,t){const e=t||{};if(!n.prompt)throw new v("Missing input: "+a,e.flagHint||"Run in an interactive terminal or pass the value as a flag.");const l=e.default!==void 0&&e.default!==null&&e.default!=="",u=[].concat(e.help||[]);e.live&&u.push(e.live(l?String(e.default):"")),h(n,a,u);const c=e.live?{linesUp:1,render:o=>" "+n.out.style.dim(e.live(String(o||"").trim()))}:void 0;for(let o=0;o<5;o++){const f=l&&!e.choices?e.default:void 0,d=f!==void 0||c?{prefill:f,live:c}:void 0;let s=String(await n.prompt.question(w(n),d)).trim();!s&&l&&(s=String(e.default));const r=e.validate?e.validate(s):s?null:"A value is required.";if(!r)return s;n.out.log(" "+n.out.style.yellow(r))}throw new v("Too many invalid answers for: "+a)}async function S(n,a,t,e,l){return m(n,a,{default:e,choices:t,help:t.join(" or ")+" \xB7 Enter picks "+e,flagHint:l,validate:u=>t.indexOf(u)===-1?"Type one of: "+t.join(", ")+".":null})}async function q(n,a,t,e){const l=e||{},u=n.out.style,c=t.map((r,i)=>{const p=String(i+1)+" "+r.label+(r.note?" \xB7 "+r.note:"");return{plain:r.disabled?u.dim(p):p}}),o=t.filter(r=>!r.disabled),f=Math.max(0,t.indexOf(o.find(r=>r.value===l.default)||o[0])),d=await m(n,a,{default:String(f+1),choices:t.map((r,i)=>String(i+1)),help:c.concat(["Type a number \xB7 Enter picks "+(f+1)]),flagHint:l.flagHint,validate:r=>{const i=s(r);return i?i.disabled?i.label+" is "+(i.note||"not available")+".":null:"Type a number from 1 to "+t.length+"."}});return s(d).value;function s(r){const i=Number(r);if(Number.isInteger(i)&&i>=1&&i<=t.length)return t[i-1];const p=l.match?l.match(r):null;return t.find(g=>g.value===p||g.value===r)||null}}module.exports={createPrompt:y,ask:m,choose:S,select:q};
1
+ "use strict";const b=require("readline"),{UsageError:g}=require("./errors");function h(n,s){function i(e,l){const o=l||{};return new Promise(d=>{const a=b.createInterface({input:n,output:s});let f=null,c=!1;if(o.live&&s.isTTY){const u=o.live.linesUp||1;f=(t,r)=>{c||r&&(r.name==="return"||r.name==="enter")||setImmediate(()=>{c||s.write("\x1B7\x1B["+u+"A\r\x1B[2K"+o.live.render(a.line)+"\x1B8")})},n.on("keypress",f)}a.question(e,u=>{c=!0,f&&n.removeListener("keypress",f),a.close(),d(u)}),o.prefill&&a.write(String(o.prefill))})}return{question:i}}function y(n,s,i){const e=n.out.style;n.out.log(""),n.out.log(e.cyan("?")+" "+e.bold(s)),[].concat(i||[]).forEach(l=>n.out.log(" "+(typeof l=="string"?e.dim(l):l.plain)))}function w(n){return" "+n.out.style.magenta("\u203A")+" "}async function v(n,s,i){const e=i||{};if(!n.prompt)throw new g("Missing input: "+s,e.flagHint||"Run in an interactive terminal or pass the value as a flag.");const l=e.default!==void 0&&e.default!==null&&e.default!=="",o=[].concat(e.help||[]);e.live&&o.push(e.live(l?String(e.default):"")),y(n,s,o);const d=e.live?{linesUp:1,render:a=>" "+n.out.style.dim(e.live(String(a||"").trim()))}:void 0;for(let a=0;a<5;a++){const f=l&&!e.choices?e.default:void 0,c=f!==void 0||d?{prefill:f,live:d}:void 0;let u=String(await n.prompt.question(w(n),c)).trim();!u&&l&&(u=String(e.default));const t=e.validate?e.validate(u):u?null:"A value is required.";if(!t)return u;n.out.log(" "+n.out.style.yellow(t))}throw new g("Too many invalid answers for: "+s)}async function S(n,s,i,e){const l=e||{},o=n.out.style,d=i.map((t,r)=>{const p=" "+t.label+(t.note?" \xB7 "+t.note:"");return{plain:t.disabled?o.dim(String(r+1)+p):o.cyan(String(r+1))+p}}),a=i.filter(t=>!t.disabled),f=Math.max(0,i.indexOf(a.find(t=>t.value===l.default)||a[0])),c=await v(n,s,{default:String(f+1),choices:i.map((t,r)=>String(r+1)),help:d.concat(["Type a number \xB7 Enter picks "+(f+1)]),flagHint:l.flagHint,validate:t=>{const r=u(t);return r?r.disabled?r.label+" is "+(r.note||"not available")+".":null:"Type a number from 1 to "+i.length+"."}});return u(c).value;function u(t){const r=Number(t);if(Number.isInteger(r)&&r>=1&&r<=i.length)return i[r-1];const p=l.match?l.match(t):null;return i.find(m=>m.value===p||m.value===t)||null}}module.exports={createPrompt:h,ask:v,select:S};
@@ -0,0 +1,3 @@
1
+ "use strict";const P=require("crypto"),h=require("fs"),y=require("path"),q=require("adm-zip"),O=require("../config"),{readCredentials:L}=require("../auth/credentials"),S=require("../dev/native"),{CliError:u}=require("../errors"),F=788,U={".DS_Store":!0,__MACOSX:!0},W=/\.dSYM$/i;function N(e,n,c,a){const i=e.addFile(n,c,"",a);i.header.made=F}function _(e){const n=e||{},c=a=>(a&&typeof a=="object"?a.path||a.bundle||a.file:a)||null;return{mac:c(n.mac||n.macPlugin||n.plugin),win:c(n.win||n.winAex||n.aex)}}const x={mac:"macOS",win:"Windows"},A=["mac","win"];function k(e){return e.platform==="darwin"?A.slice():e.platform==="win32"?["win"]:[]}function B(e,n){const c=k(e);if(n==null||n===""||n===!0){if(!c.length)throw new u("Native effect plugins are built on macOS (both versions) or Windows (the Windows version).");return c}const a=(Array.isArray(n)?n:String(n).split(",")).map(t=>String(t).trim().toLowerCase()).filter(Boolean),i={mac:"mac",macos:"mac",osx:"mac",darwin:"mac",win:"win",windows:"win",win32:"win",win64:"win"},o=[];if(a.forEach(t=>{const r=i[t];if(!r)throw new u("Unknown --os value "+JSON.stringify(t)+".",{hint:"Use --os mac, --os win or --os mac,win."});o.indexOf(r)===-1&&o.push(r)}),!o.length)throw new u("--os names no operating system.",{hint:"Use --os mac, --os win or --os mac,win."});const s=o.filter(t=>c.indexOf(t)===-1);if(s.length)throw new u("This computer cannot build the "+s.map(t=>x[t]).join(" and ")+" version.",{hint:s.indexOf("mac")!==-1?"The macOS version (.plugin) is built on a Mac. On Windows, releases hold the Windows version only: drop --os or use --os win.":void 0});return A.filter(t=>o.indexOf(t)!==-1)}function E(e){return A.filter(n=>e.indexOf(n)!==-1).map(n=>x[n]).join(" and ")}function C(e,n){const c=e&&Array.isArray(e.operatingSystems)?e.operatingSystems:null,a={macos:"mac",mac:"mac",windows:"win",win:"win"},i=(c||n||[]).map(s=>a[String(s).toLowerCase()]).filter(Boolean);return i.length?" ("+E(i)+(i.indexOf("mac")!==-1&&i.indexOf("win")!==-1?"":" only")+")":""}async function D(e,n,c,a){const i=a||{},o=B(e,i.os);i.checked||await require("../commands/build").runGate(e,n);const s=O.apiBase(e,L(e));s!==O.DEFAULT_API_BASE&&e.out.warn("This build talks to "+s+" (AP_API_BASE, `ap config`, or your login), not production.");const t=O.signingPublicKey(e);if(!t)throw new u("No release signing public key is configured.",{hint:"Set AP_SIGNING_PUBLIC_KEY or run `ap config set signing-public-key <file-or-pem>`."});const r=S.vendorNativeRuntime(e,n.root),p=await S.sdkStatus(e);if(!p.ok)throw new u(p.message,{hint:p.next});const g=c||n.version,d=await S.buildNativeSafe(e,n,{mode:"release",targets:o,version:g,apiBase:s,publicKey:t,webBase:O.webBase(e),productUrl:n.settings.listingUrl||null,nativeRuntimeDir:r.dir,sdk:p.raw});if(!d.ok){const f=d.errors.slice(0,20).map(b=>" "+S.formatDiagnostic(b));throw new u("The release build failed: "+d.error+(f.length?`
2
+ `+f.join(`
3
+ `):""),{hint:d.hint||void 0})}const w=_(d.artefacts),l={};if(o.forEach(f=>l[f]=w[f]),l.mac!==void 0&&(!l.mac||!h.existsSync(l.mac)))throw new u("The build did not produce the macOS plugin (.plugin).");if(l.win!==void 0&&(!l.win||!h.existsSync(l.win)))throw new u("The build did not produce the Windows plugin (.aex).");return{version:g,runtimeVersion:r.version||"0.0.0",oses:o,artefacts:l,warnings:d.warnings,outDir:y.dirname(l.mac||l.win)}}function T(e){const n=[];return(function c(a,i){h.readdirSync(a,{withFileTypes:!0}).sort((o,s)=>o.name<s.name?-1:o.name>s.name?1:0).forEach(o=>{if(U[o.name]||W.test(o.name)||/^\._/.test(o.name))return;const s=y.join(a,o.name),t=i+"/"+o.name,r=h.lstatSync(s);if(r.isSymbolicLink())throw new u("The plugin bundle contains a symbolic link ("+t+"); releases cannot.");r.isDirectory()?c(s,t):r.isFile()&&n.push({rel:t,full:s,mode:r.mode&73?493:420})})})(e,y.basename(e)),n}function R(e,n,c){const a=S.nativeLib(e,"installers"),i=n||{};if(!i.mac&&!i.win)throw new u("Nothing to package: the build produced neither the macOS (.plugin) nor the Windows (.aex) plugin.");const o=m=>String(m).split(/[\\/]/).filter(Boolean).pop(),s=i.mac?o(i.mac):null,t=i.win?o(i.win):null,r=s?s.replace(/\.plugin$/i,""):t.replace(/\.aex$/i,"");if(!/^[A-Za-z0-9_-]+$/.test(r)||s&&!/\.plugin$/i.test(s)||t&&t!==r+".aex")throw new u(i.mac&&i.win?"The macOS and Windows builds must be <Name>.plugin and <Name>.aex; got "+s+" and "+t+".":"The build must be <Name>."+(i.mac?"plugin":"aex")+" (letters, digits, - and _); got "+(s||t)+".");const g=A.filter(m=>i[m]),d=new q,w=[];i.mac&&T(i.mac).forEach(m=>{N(d,m.rel,h.readFileSync(m.full),m.mode),w.push(m.rel)}),i.win&&(N(d,t,h.readFileSync(i.win),420),w.push(t));const l=Object.assign({bundleName:r,pluginName:s||r+".plugin",aexName:t||r+".aex"},c,{oses:g}),f=[];i.mac&&f.push(["mac-install.command",a.macInstallCommand(l),493]),i.win&&f.push(["windows-install.bat",a.windowsInstallBat(l),420]),f.push(["readme.txt",a.readmeText(l),420]),f.forEach(([m,v,I])=>{N(d,m,Buffer.from(String(v),"utf8"),I),w.push(m)});const b=d.toBuffer();return{buffer:b,sha256:P.createHash("sha256").update(b).digest("hex"),sizeBytes:b.length,entries:w,oses:g}}function K(e,n){return y.join(e.root,"dist",e.settings.bundleId+"-"+n+".zip")}module.exports={releaseArtefacts:_,buildableOses:k,resolveReleaseOses:B,osesLabel:E,publishedOsSuffix:C,buildNativeRelease:D,bundleFiles:T,assembleNativeZip:R,nativeZipPath:K};
@@ -1 +1 @@
1
- "use strict";const{hostAppNames:A,targetFor:w}=require("../targets"),U=require("../config"),q=require("../project/semver"),{updateProjectFile:v}=require("../project/project"),{productPath:P}=require("../api/session"),{assembleBuyerZip:N,obfuscateBuild:x,uploadZip:z}=require("./package"),{checkedProductionBuild:C,runGate:M}=require("../commands/build"),{CliError:c}=require("../errors"),V=["test","production"],I=["patch","minor","major"],y=5e3;function L(s){return!s||!s.trim()?"A changelog is required.":s.length>y?"Keep the changelog under "+y+" characters.":null}function d(s){return s>=1048576?(s/1048576).toFixed(1)+" MB":Math.max(1,Math.round(s/1024))+" KB"}function D(s,i){if(!i||!Array.isArray(i.hosts))throw new c("AfterPresets did not return this extension's apps.");const e=s.settings,r=i.platform;if(r!==e.platform)throw new c("afterpresets.json says "+e.platform.toUpperCase()+" but this extension is registered as "+r.toUpperCase()+". The platform cannot change.");const t=e.hosts.map(n=>n.app).filter(n=>i.hosts.indexOf(n)===-1);if(t.length){const n=t.map(l=>(w(r,l)||{appName:l}).appName),a=t.map(l=>(w(r,l)||{jsxDir:l.toLowerCase()}).jsxDir);throw new c("afterpresets.json targets "+n.join(" and ")+", which this extension is not registered for on AfterPresets.",{hint:"Run `ap add host "+a.join("` and `ap add host ")+"` so the listing shows it too."})}const u=i.hosts.filter(n=>!e.hosts.some(a=>a.app===n));return u.length?u.map(n=>(w(r,n)||{appName:n}).appName):null}async function E(s,i,e){const r=await i.get(P(e.settings.bundleId)),t=D(e,r.product||null);t&&s.out.warn("AfterPresets lists this extension for "+t.join(" and ")+", but afterpresets.json does not target it, so this release will not run there."),await M(s,e,r.product||null);const u=(r.releases||[]).map(a=>a.version),n=q.max([e.version].concat(u));return{details:r,base:n}}async function T(s){const i=await s.get("/v1/api/developer/me"),e=i.pushes;if(e&&e.limit!==null&&e.limit!==void 0&&e.used>=e.limit)throw new c("You have used all "+e.limit+" production pushes for this month. Push to the test channel, or upgrade your plan for more. (push_quota_exceeded)");return i}async function _(s,i,e,r){const t=s.out,u=e.settings.bundleId,{details:n,version:a,channel:l,changeLog:k}=r,m=await t.task("Building",()=>C(s,e,a,{checked:!0}),h=>"Built "+a+t.style.dim(" (runtime "+h.runtimeVersion+")")),f=P(u);await t.task("Obfuscating panel scripts on AfterPresets",()=>x(i,f,m.outDir,e.panels),h=>"Obfuscated "+h.files+" panel script"+(h.files===1?"":"s")+t.style.dim(" ("+d(h.bytesIn)+" sent; media stays on this computer)"));const B=n.product&&n.product.listingUrl||e.settings.listingUrl||null,o=await t.task("Packaging the installer ZIP",()=>N(m.outDir,{bundleId:u,name:e.settings.name||u,version:a,listingUrl:B,appNames:A(e.settings)}),h=>"Packaged "+d(h.sizeBytes)+t.style.dim(" sha256 "+h.sha256.slice(0,12)+"\u2026"));if(o.sizeBytes>U.MAX_BUNDLE_BYTES)throw new c("The bundle is "+d(o.sizeBytes)+"; the limit is 200 MB.");const{upload:p}=await i.post(f+"/releases",{version:a,channel:l,changeLog:k,runtimeVersion:m.runtimeVersion,sha256:o.sha256,sizeBytes:o.sizeBytes});if(!p||!p.url||!p.id)throw new c("The API did not return an upload URL.");await t.task("Uploading "+d(o.sizeBytes),()=>z(s,p,o.buffer),"Uploaded "+d(o.sizeBytes));const b=await t.task("Verifying and signing",()=>i.post(f+"/releases/uploads/"+encodeURIComponent(p.id)+"/complete",{}),"Verified and signed");v(e.root,{version:a});const g=b.release||{};return{release:g,version:g.version||a,channel:l,sha256:g.sha256||o.sha256,sizeBytes:o.sizeBytes,listingUrl:B,runtimeVersion:m.runtimeVersion}}module.exports={CHANNELS:V,BUMPS:I,MAX_CHANGELOG:y,validateChangelog:L,kb:d,preparePush:E,checkPushQuota:T,runPush:_};
1
+ "use strict";const{hostAppNames:q,targetFor:b}=require("../targets"),A=require("../config"),I=require("../project/semver"),{updateProjectFile:V}=require("../project/project"),{productPath:v}=require("../api/session"),{assembleBuyerZip:E,obfuscateBuild:L,uploadZip:N}=require("./package"),{checkedProductionBuild:C,runGate:M}=require("../commands/build"),{CliError:m}=require("../errors"),R=["test","production"],T=["patch","minor","major"],U=5e3;function _(s){return!s||!s.trim()?"A changelog is required.":s.length>U?"Keep the changelog under "+U+" characters.":null}function p(s){return s>=1048576?(s/1048576).toFixed(1)+" MB":Math.max(1,Math.round(s/1024))+" KB"}function D(s,i){if(!i||!Array.isArray(i.hosts))throw new m("AfterPresets did not return this extension's apps.");const e=s.settings,r=i.platform;if(r!==e.platform)throw new m("afterpresets.json says "+e.platform.toUpperCase()+" but this extension is registered as "+r.toUpperCase()+". The platform cannot change.");const t=e.hosts.map(a=>a.app).filter(a=>i.hosts.indexOf(a)===-1);if(t.length){const a=t.map(d=>(b(r,d)||{appName:d}).appName),n=t.map(d=>(b(r,d)||{jsxDir:d.toLowerCase()}).jsxDir);throw new m("afterpresets.json targets "+a.join(" and ")+", which this extension is not registered for on AfterPresets.",{hint:"Run `ap add host "+n.join("` and `ap add host ")+"` so the listing shows it too."})}const l=i.hosts.filter(a=>!e.hosts.some(n=>n.app===a));return l.length?l.map(a=>(b(r,a)||{appName:a}).appName):null}async function O(s,i,e){const r=await i.get(v(e.settings.bundleId)),t=D(e,r.product||null);t&&s.out.warn("AfterPresets lists this extension for "+t.join(" and ")+", but afterpresets.json does not target it, so this release will not run there."),await M(s,e,r.product||null);const l=(r.releases||[]).map(n=>n.version),a=I.max([e.version].concat(l));return{details:r,base:a}}async function S(s){const i=await s.get("/v1/api/developer/me"),e=i.pushes;if(e&&e.limit!==null&&e.limit!==void 0&&e.used>=e.limit)throw new m("You have used all "+e.limit+" production pushes for this month. Push to the test channel, or upgrade your plan for more. (push_quota_exceeded)");return i}async function Z(s,i,e,r){if(e.settings.platform==="native")return x(s,i,e,r);const t=s.out,l=e.settings.bundleId,{details:a,version:n,channel:d,changeLog:k}=r,h=await t.task("Building",()=>C(s,e,n,{checked:!0}),f=>"Built "+n+t.style.dim(" (runtime "+f.runtimeVersion+")")),y=v(l);await t.task("Obfuscating panel scripts on AfterPresets",()=>L(i,y,h.outDir,e.panels),f=>"Obfuscated "+f.files+" panel script"+(f.files===1?"":"s")+t.style.dim(" ("+p(f.bytesIn)+" sent; media stays on this computer)"));const w=a.product&&a.product.listingUrl||e.settings.listingUrl||null,u=await t.task("Packaging the installer ZIP",()=>E(h.outDir,{bundleId:l,name:e.settings.name||l,version:n,listingUrl:w,appNames:q(e.settings)}),f=>"Packaged "+p(f.sizeBytes)+t.style.dim(" sha256 "+f.sha256.slice(0,12)+"\u2026"));if(u.sizeBytes>A.MAX_BUNDLE_BYTES)throw new m("The bundle is "+p(u.sizeBytes)+"; the limit is 200 MB.");const{upload:o}=await i.post(y+"/releases",{version:n,channel:d,changeLog:k,runtimeVersion:h.runtimeVersion,sha256:u.sha256,sizeBytes:u.sizeBytes});if(!o||!o.url||!o.id)throw new m("The API did not return an upload URL.");await t.task("Uploading "+p(u.sizeBytes),()=>N(s,o,u.buffer),"Uploaded "+p(u.sizeBytes));const B=await t.task("Verifying and signing",()=>i.post(y+"/releases/uploads/"+encodeURIComponent(o.id)+"/complete",{}),"Verified and signed");V(e.root,{version:n});const g=B.release||{};return{release:g,version:g.version||n,channel:d,sha256:g.sha256||u.sha256,sizeBytes:u.sizeBytes,listingUrl:w,runtimeVersion:h.runtimeVersion}}async function x(s,i,e,r){const t=s.out,l=e.settings.bundleId,{details:a,version:n,channel:d,changeLog:k}=r,h=require("./native"),y=r.oses||h.resolveReleaseOses(s),w=await t.task("Building for "+h.osesLabel(y),()=>h.buildNativeRelease(s,e,n,{checked:!0,os:y}),c=>"Built "+n+h.publishedOsSuffix(null,c.oses)+t.style.dim(" (ap_native "+c.runtimeVersion+")"));w.warnings.forEach(c=>t.warn(c));const u=a.product&&a.product.listingUrl||e.settings.listingUrl||null,o=await t.task("Packaging the installer ZIP",()=>h.assembleNativeZip(s,w.artefacts,{bundleId:l,name:e.settings.name||l,version:n,listingUrl:u}),c=>"Packaged "+p(c.sizeBytes)+t.style.dim(" sha256 "+c.sha256.slice(0,12)+"\u2026"));if(o.sizeBytes>A.MAX_BUNDLE_BYTES)throw new m("The release is "+p(o.sizeBytes)+"; the limit is 200 MB.");const B=v(l),{upload:g}=await i.post(B+"/releases",{version:n,channel:d,changeLog:k,runtimeVersion:w.runtimeVersion,sha256:o.sha256,sizeBytes:o.sizeBytes});if(!g||!g.url||!g.id)throw new m("The API did not return an upload URL.");await t.task("Uploading "+p(o.sizeBytes),()=>N(s,g,o.buffer),"Uploaded "+p(o.sizeBytes));const f=await t.task("Verifying and signing",()=>i.post(B+"/releases/uploads/"+encodeURIComponent(g.id)+"/complete",{}),"Verified and signed"),z={version:n};try{const c=require("../dev/native").nativeLib(s,"effect").loadEffect(e.root);z.releasedEffect=require("../check/native").releasedEffectRecord(c,n)}catch(c){t.warn("Could not record the released effect identity: "+c.message)}V(e.root,z);const P=f.release||{};return{release:P,version:P.version||n,channel:d,sha256:P.sha256||o.sha256,sizeBytes:o.sizeBytes,listingUrl:u,runtimeVersion:w.runtimeVersion}}module.exports={CHANNELS:R,BUMPS:T,MAX_CHANGELOG:U,validateChangelog:_,kb:p,preparePush:O,checkPushQuota:S,runPush:Z};
@@ -1 +1 @@
1
- "use strict";const a=require("child_process");function l(s,c,n){const t=n||{};return new Promise(o=>{let r;try{r=a.spawn(s,c,{cwd:t.cwd,stdio:t.quiet?["ignore","pipe","pipe"]:"inherit",shell:process.platform==="win32"&&t.shell!==!1})}catch(e){o({code:1,stdout:"",stderr:e.message});return}let d="",i="";r.stdout&&r.stdout.on("data",e=>d+=e),r.stderr&&r.stderr.on("data",e=>i+=e),r.on("error",e=>o({code:1,stdout:d,stderr:e.message})),r.on("close",e=>o({code:e===null?1:e,stdout:d,stderr:i}))})}function p(s,c){const n=c||process.platform;let t="xdg-open",o=[s];n==="darwin"&&(t="open"),n==="win32"&&(t="cmd",o=["/c","start",'""',s.replace(/&/g,"^&")]);try{const r=a.spawn(t,o,{stdio:"ignore",detached:!0});return r.on("error",()=>{}),r.unref(),!0}catch{return!1}}module.exports={runCommand:l,openBrowser:p};
1
+ "use strict";const a=require("child_process");function p(r,e){if(e.shell===!1)return!1;if(e.shell===!0)return!0;const s=String(r).split(/[\\/]/).pop();return/^(npm|npx|pnpm|yarn|corepack)$/i.test(s)||/\.(cmd|bat)$/i.test(s)}function u(r){const e=String(r);return e===""||/[\s"&|<>^()%!]/.test(e)?'"'+e.replace(/"/g,'""')+'"':e}function d(r,e,s,o){return o!=="win32"?{command:r,args:e,shell:!1}:p(r,s)?{command:u(r),args:(e||[]).map(u),shell:!0}:{command:r,args:e,shell:!1}}function f(r,e,s){const o=s||{};return new Promise(i=>{let n;try{const t=d(r,e,o,process.platform);n=a.spawn(t.command,t.args,{cwd:o.cwd,stdio:o.quiet?["ignore","pipe","pipe"]:"inherit",shell:t.shell})}catch(t){i({code:1,stdout:"",stderr:t.message});return}let l="",c="";n.stdout&&n.stdout.on("data",t=>l+=t),n.stderr&&n.stderr.on("data",t=>c+=t),n.on("error",t=>i({code:1,stdout:l,stderr:t.message})),n.on("close",t=>i({code:t===null?1:t,stdout:l,stderr:c}))})}function h(r,e){const s=e||process.platform;let o="xdg-open",i=[r];s==="darwin"&&(o="open"),s==="win32"&&(o="cmd",i=["/c","start",'""',r.replace(/&/g,"^&")]);try{const n=a.spawn(o,i,{stdio:"ignore",detached:!0});return n.on("error",()=>{}),n.unref(),!0}catch{return!1}}module.exports={runCommand:f,openBrowser:h,spawnPlan:d};
package/src/targets.js CHANGED
@@ -1 +1 @@
1
- "use strict";const p=[{host:"AEFT",platform:"cep",app:"aftereffects",key:"aeft",appName:"After Effects",minVersion:"17.0",available:!0,jsxDir:"aeft",types:"AfterEffects/26.0",typesLabel:"After Effects 26.0",typesAdditions:"AfterEffects.d.ts",docsPage:"host-after-effects.md",homeItem:"composition",hostEvalUndo:"each call is one undo step"},{host:"PPRO",platform:"cep",app:"premierepro",key:"ppro",appName:"Premiere Pro",minVersion:"14.0",available:!0,jsxDir:"ppro",types:"Premiere/24.0",typesLabel:"Premiere Pro 24.0",typesAdditions:"Premiere.d.ts",docsPage:"host-premiere.md",homeItem:"sequence",hostEvalUndo:"Premiere has no undo groups: every change a call makes is its own undo step"},{host:"premierepro",platform:"uxp",app:"premierepro",key:"ppro",appName:"Premiere Pro",minVersion:"25.6.0",available:!1},{host:"aftereffects",platform:"uxp",app:"aftereffects",key:"aeft",appName:"After Effects",minVersion:null,available:!1}],n={cep:{name:"CEP panel",label:"CEP"},uxp:{name:"UXP plugin",label:"UXP"}},o={aeft:"aftereffects",ae:"aftereffects",aftereffects:"aftereffects","after-effects":"aftereffects",ppro:"premierepro",pr:"premierepro",premiere:"premierepro",premierepro:"premierepro","premiere-pro":"premierepro"};function f(r,e){return p.find(t=>t.platform===r&&t.host===e)||null}function i(r){const e=p.find(t=>t.platform==="cep"&&t.app===r);return e?e.host:null}function m(r){const e=String(r||"").trim().toLowerCase().replace(/\s+/g,"-");return o[e]||o[e.replace(/-/g,"")]||null}function c(r){const e=p.find(t=>t.app===r);return e?e.appName:r}function s(r){return(r.hosts||[]).map(e=>f(r.platform,e.app)).filter(Boolean)}function l(r,e){const t=[];return s(r).forEach(a=>{t.indexOf(a.appName)===-1&&t.push(a.appName)}),t.length?t.join(e||" or "):"After Effects"}module.exports={TARGETS:p,PLATFORMS:n,targetFor:f,cepHostCode:i,parseApp:m,appNameOf:c,projectTargets:s,hostAppNames:l};
1
+ "use strict";const a=[{host:"AEFT",platform:"cep",app:"aftereffects",key:"aeft",appName:"After Effects",minVersion:"17.0",available:!0,jsxDir:"aeft",types:"AfterEffects/26.0",typesLabel:"After Effects 26.0",typesAdditions:"AfterEffects.d.ts",docsPage:"host-after-effects.md",homeItem:"composition",hostEvalUndo:"each call is one undo step"},{host:"PPRO",platform:"cep",app:"premierepro",key:"ppro",appName:"Premiere Pro",minVersion:"14.0",available:!0,jsxDir:"ppro",types:"Premiere/24.0",typesLabel:"Premiere Pro 24.0",typesAdditions:"Premiere.d.ts",docsPage:"host-premiere.md",homeItem:"sequence",hostEvalUndo:"Premiere has no undo groups: every change a call makes is its own undo step"},{host:"premierepro",platform:"uxp",app:"premierepro",key:"ppro",appName:"Premiere Pro",minVersion:"25.6.0",available:!1},{host:"aftereffects",platform:"uxp",app:"aftereffects",key:"aeft",appName:"After Effects",minVersion:null,available:!1},{host:"AEFT",platform:"native",app:"aftereffects",key:"aeft",appName:"After Effects",minVersion:"23.0",available:!0},{host:"PPRO",platform:"native",app:"premierepro",key:"ppro",appName:"Premiere Pro",minVersion:null,available:!1}],n={cep:{name:"CEP panel",label:"CEP"},uxp:{name:"UXP plugin",label:"UXP"},native:{name:"After Effects plugin",label:"native C++"}},o={aeft:"aftereffects",ae:"aftereffects",aftereffects:"aftereffects","after-effects":"aftereffects",ppro:"premierepro",pr:"premierepro",premiere:"premierepro",premierepro:"premierepro","premiere-pro":"premierepro"};function f(r,e){return a.find(t=>t.platform===r&&t.host===e)||null}function i(r){const e=a.find(t=>t.platform==="cep"&&t.app===r);return e?e.host:null}function m(r){const e=String(r||"").trim().toLowerCase().replace(/\s+/g,"-");return o[e]||o[e.replace(/-/g,"")]||null}function l(r){const e=a.find(t=>t.app===r);return e?e.appName:r}function s(r){return(r.hosts||[]).map(e=>f(r.platform,e.app)).filter(Boolean)}function c(r,e){const t=[];return s(r).forEach(p=>{t.indexOf(p.appName)===-1&&t.push(p.appName)}),t.length?t.join(e||" or "):"After Effects"}module.exports={TARGETS:a,PLATFORMS:n,targetFor:f,cepHostCode:i,parseApp:m,appNameOf:l,projectTargets:s,hostAppNames:c};