@auraindustry/aurajs 0.0.6 → 0.1.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 (334) hide show
  1. package/README.md +103 -7
  2. package/benchmarks/perf-thresholds.json +54 -0
  3. package/package.json +4 -7
  4. package/src/asset-pack.mjs +5 -1
  5. package/src/authored-project.mjs +1449 -0
  6. package/src/authored-runtime.mjs +2016 -0
  7. package/src/authoring/avatar-animation-graph.mjs +648 -0
  8. package/src/bin-integrity.mjs +272 -0
  9. package/src/build-contract/assets.mjs +130 -0
  10. package/src/build-contract/capabilities.mjs +116 -0
  11. package/src/build-contract/constants.mjs +6 -0
  12. package/src/build-contract/helpers.mjs +44 -0
  13. package/src/build-contract/web-templates.mjs +5993 -0
  14. package/src/build-contract.mjs +27 -2910
  15. package/src/bundler.mjs +188 -55
  16. package/src/cli.mjs +4825 -1512
  17. package/src/commands/project-authoring.mjs +434 -0
  18. package/src/config.mjs +27 -0
  19. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +3309 -0
  20. package/src/conformance/cases/core-runtime-cases.mjs +1431 -0
  21. package/src/conformance/cases/index.mjs +11 -0
  22. package/src/conformance/cases/scene3d-and-media-cases.mjs +2094 -0
  23. package/src/conformance/cases/systems-and-gameplay-cases.mjs +1776 -0
  24. package/src/conformance/shared.mjs +27 -0
  25. package/src/conformance-runner.mjs +25 -13
  26. package/src/conformance.mjs +619 -4020
  27. package/src/cutscene.mjs +362 -5
  28. package/src/dev-cli-action.mjs +249 -0
  29. package/src/dev-cli-inspect.mjs +92 -0
  30. package/src/dev-cli-state.mjs +80 -0
  31. package/src/external-asset-cache.mjs +587 -0
  32. package/src/external-asset-policy.mjs +217 -0
  33. package/src/external-package-surface.mjs +206 -0
  34. package/src/game-action-runtime.mjs +869 -0
  35. package/src/game-state-runtime.mjs +206 -6
  36. package/src/headless-action.mjs +186 -0
  37. package/src/headless-test/runtime-animation.mjs +1173 -0
  38. package/src/headless-test/runtime-coordinator.mjs +1514 -0
  39. package/src/headless-test/runtime-primitives.mjs +320 -0
  40. package/src/headless-test/runtime-world.mjs +2253 -0
  41. package/src/headless-test.mjs +392 -4298
  42. package/src/host-binary.mjs +342 -14
  43. package/src/icon-discovery.mjs +64 -0
  44. package/src/make-catalog.mjs +109 -0
  45. package/src/make.mjs +197 -0
  46. package/src/package-integrity.mjs +586 -0
  47. package/src/perf-benchmark.mjs +353 -0
  48. package/src/postinstall.mjs +5 -5
  49. package/src/prefabs/index.mjs +34 -0
  50. package/src/prefabs/scene-serialization.mjs +184 -0
  51. package/src/project-importer.mjs +620 -0
  52. package/src/project-registry.mjs +24 -0
  53. package/src/publish-command.mjs +195 -0
  54. package/src/publish-env-example.mjs +83 -0
  55. package/src/publish-validation.mjs +708 -0
  56. package/src/retro/assets/compile.mjs +232 -0
  57. package/src/retro/backend-gba/authoring.mjs +1029 -0
  58. package/src/retro/backend-gba/rom.mjs +363 -0
  59. package/src/retro/backend-gbc/rom.mjs +85 -0
  60. package/src/retro/build.mjs +278 -0
  61. package/src/retro/cli/commands.mjs +292 -0
  62. package/src/retro/cli/templates.mjs +84 -0
  63. package/src/retro/diagnostics/catalog.mjs +110 -0
  64. package/src/retro/diagnostics/emit.mjs +72 -0
  65. package/src/retro/emulator/case-overlay.mjs +64 -0
  66. package/src/retro/emulator/discovery.mjs +158 -0
  67. package/src/retro/emulator/macos-case-overlay.swift +220 -0
  68. package/src/retro/emulator/profiles.mjs +146 -0
  69. package/src/retro/emulator/runner.mjs +289 -0
  70. package/src/retro/frontend/load-project.mjs +98 -0
  71. package/src/retro/index.mjs +30 -0
  72. package/src/retro/ir/build-ir.mjs +108 -0
  73. package/src/retro/runtime-gba/contract.mjs +151 -0
  74. package/src/retro/runtime-gbc/contract.mjs +117 -0
  75. package/src/retro/shared/span.mjs +26 -0
  76. package/src/retro/shared/targets.mjs +64 -0
  77. package/src/retro/validator/check-project.mjs +114 -0
  78. package/src/runtime-hotspot-audit.mjs +707 -0
  79. package/src/scaffold/config.mjs +1000 -0
  80. package/src/scaffold/fs.mjs +56 -0
  81. package/src/scaffold/layout.mjs +318 -0
  82. package/src/scaffold/project-docs.mjs +438 -0
  83. package/src/scaffold.mjs +93 -596
  84. package/src/scene-composition/index.mjs +326 -0
  85. package/src/scene-composition/runtime.mjs +751 -0
  86. package/src/self-hosted-assets.mjs +604 -0
  87. package/src/session-client.mjs +750 -0
  88. package/src/session-native-launcher.mjs +74 -0
  89. package/src/session-protocol.mjs +75 -0
  90. package/src/session-runtime.mjs +321 -0
  91. package/src/session-server.mjs +360 -0
  92. package/src/shader-kits/index.mjs +773 -0
  93. package/src/starter-content-registry.mjs +292 -0
  94. package/src/state-artifacts.mjs +662 -24
  95. package/src/state-dev-reload.mjs +99 -2
  96. package/src/terminal-ui.mjs +245 -0
  97. package/src/web-conformance.mjs +219 -0
  98. package/templates/create/2d/config/gameplay/shooter.config.js +26 -0
  99. package/templates/create/2d/content/gameplay/waves.json +26 -0
  100. package/templates/create/2d/content/registries/.gitkeep +1 -0
  101. package/templates/create/2d/docs/design/.gitkeep +1 -0
  102. package/templates/create/2d/docs/design/loop.md +5 -0
  103. package/templates/create/2d/prefabs/enemies.prefab.js +90 -0
  104. package/templates/create/2d/prefabs/enemy-basic.prefab.js +18 -0
  105. package/templates/create/2d/prefabs/player.prefab.js +36 -0
  106. package/templates/create/2d/prefabs/projectiles.prefab.js +35 -0
  107. package/templates/create/2d/scenes/boot.scene.js +12 -0
  108. package/templates/create/2d/scenes/gameplay.scene.js +230 -0
  109. package/templates/create/2d/scenes/menu.scene.js +9 -0
  110. package/templates/create/2d/src/main.js +6 -185
  111. package/templates/create/2d/src/runtime/app.js +49 -0
  112. package/templates/create/2d/src/runtime/capabilities.js +35 -0
  113. package/templates/create/2d/ui/hud.screen.js +40 -0
  114. package/templates/create/2d/ui/pause.screen.js +149 -0
  115. package/templates/create/2d/ui/settings.screen.js +347 -0
  116. package/templates/create/2d/ui/title.screen.js +13 -0
  117. package/templates/create/2d-adventure/aura.config.json +28 -0
  118. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +14 -0
  119. package/templates/create/2d-adventure/content/gameplay/world.js +46 -0
  120. package/templates/create/2d-adventure/content/registries/.gitkeep +1 -0
  121. package/templates/create/2d-adventure/docs/design/loop.md +5 -0
  122. package/templates/create/2d-adventure/prefabs/player.prefab.js +54 -0
  123. package/templates/create/2d-adventure/prefabs/relic.prefab.js +38 -0
  124. package/templates/create/2d-adventure/prefabs/world.prefab.js +125 -0
  125. package/templates/create/2d-adventure/scenes/gameplay.scene.js +256 -0
  126. package/templates/create/2d-adventure/src/runtime/capabilities.js +34 -0
  127. package/templates/create/2d-adventure/ui/hud.screen.js +60 -0
  128. package/templates/create/2d-survivor/config/gameplay/survivor.config.js +33 -0
  129. package/templates/create/2d-survivor/content/gameplay/spawn-zones.json +29 -0
  130. package/templates/create/2d-survivor/content/registries/.gitkeep +1 -0
  131. package/templates/create/2d-survivor/docs/design/.gitkeep +1 -0
  132. package/templates/create/2d-survivor/docs/design/loop.md +5 -0
  133. package/templates/create/2d-survivor/prefabs/enemies.prefab.js +178 -0
  134. package/templates/create/2d-survivor/prefabs/enemy-swarm.prefab.js +18 -0
  135. package/templates/create/2d-survivor/prefabs/player.prefab.js +42 -0
  136. package/templates/create/2d-survivor/prefabs/projectiles.prefab.js +56 -0
  137. package/templates/create/2d-survivor/scenes/boot.scene.js +12 -0
  138. package/templates/create/2d-survivor/scenes/gameplay.scene.js +314 -0
  139. package/templates/create/2d-survivor/scenes/menu.scene.js +9 -0
  140. package/templates/create/2d-survivor/src/main.js +5 -332
  141. package/templates/create/2d-survivor/src/runtime/app.js +49 -0
  142. package/templates/create/2d-survivor/src/runtime/capabilities.js +35 -0
  143. package/templates/create/2d-survivor/ui/hud.screen.js +45 -0
  144. package/templates/create/2d-survivor/ui/title.screen.js +13 -0
  145. package/templates/create/3d/assets/models/starter-avatar.gltf +184 -0
  146. package/templates/create/3d/config/gameplay/.gitkeep +1 -0
  147. package/templates/create/3d/content/gameplay/checkpoints.json +33 -0
  148. package/templates/create/3d/content/gameplay/course.js +40 -0
  149. package/templates/create/3d/content/registries/.gitkeep +1 -0
  150. package/templates/create/3d/docs/design/.gitkeep +1 -0
  151. package/templates/create/3d/docs/design/loop.md +5 -0
  152. package/templates/create/3d/prefabs/checkpoint.prefab.js +15 -0
  153. package/templates/create/3d/prefabs/player.prefab.js +204 -0
  154. package/templates/create/3d/prefabs/world.prefab.js +112 -0
  155. package/templates/create/3d/scenes/boot.scene.js +12 -0
  156. package/templates/create/3d/scenes/checkpoint.scene.js +9 -0
  157. package/templates/create/3d/scenes/gameplay.scene.js +292 -0
  158. package/templates/create/3d/src/main.js +6 -295
  159. package/templates/create/3d/src/runtime/app.js +49 -0
  160. package/templates/create/3d/src/runtime/capabilities.js +53 -0
  161. package/templates/create/3d/src/runtime/materials.js +34 -0
  162. package/templates/create/3d/src/runtime/state.js +39 -0
  163. package/templates/create/3d/ui/hud.screen.js +75 -0
  164. package/templates/create/3d/ui/pause.screen.js +166 -0
  165. package/templates/create/3d/ui/settings.screen.js +387 -0
  166. package/templates/create/3d-adventure/assets/models/starter-avatar.gltf +184 -0
  167. package/templates/create/3d-adventure/aura.config.json +28 -0
  168. package/templates/create/3d-adventure/config/gameplay/adventure.config.js +9 -0
  169. package/templates/create/3d-adventure/content/gameplay/course.js +62 -0
  170. package/templates/create/3d-adventure/content/registries/.gitkeep +1 -0
  171. package/templates/create/3d-adventure/docs/design/loop.md +5 -0
  172. package/templates/create/3d-adventure/prefabs/player.prefab.js +168 -0
  173. package/templates/create/3d-adventure/prefabs/relic.prefab.js +35 -0
  174. package/templates/create/3d-adventure/prefabs/world.prefab.js +119 -0
  175. package/templates/create/3d-adventure/scenes/gameplay.scene.js +358 -0
  176. package/templates/create/3d-adventure/src/runtime/capabilities.js +56 -0
  177. package/templates/create/3d-adventure/src/runtime/materials.js +39 -0
  178. package/templates/create/3d-adventure/src/runtime/state.js +31 -0
  179. package/templates/create/3d-adventure/ui/hud.screen.js +70 -0
  180. package/templates/create/3d-adventure/ui/pause.screen.js +437 -0
  181. package/templates/create/3d-collectathon/assets/models/starter-avatar.gltf +184 -0
  182. package/templates/create/3d-collectathon/config/gameplay/.gitkeep +1 -0
  183. package/templates/create/3d-collectathon/content/gameplay/collectibles.json +26 -0
  184. package/templates/create/3d-collectathon/content/gameplay/course.js +46 -0
  185. package/templates/create/3d-collectathon/content/registries/.gitkeep +1 -0
  186. package/templates/create/3d-collectathon/docs/design/.gitkeep +1 -0
  187. package/templates/create/3d-collectathon/docs/design/loop.md +5 -0
  188. package/templates/create/3d-collectathon/prefabs/collectible.prefab.js +15 -0
  189. package/templates/create/3d-collectathon/prefabs/player.prefab.js +207 -0
  190. package/templates/create/3d-collectathon/prefabs/world.prefab.js +112 -0
  191. package/templates/create/3d-collectathon/scenes/boot.scene.js +12 -0
  192. package/templates/create/3d-collectathon/scenes/checkpoint.scene.js +9 -0
  193. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +200 -0
  194. package/templates/create/3d-collectathon/src/main.js +5 -355
  195. package/templates/create/3d-collectathon/src/runtime/app.js +49 -0
  196. package/templates/create/3d-collectathon/src/runtime/capabilities.js +53 -0
  197. package/templates/create/3d-collectathon/src/runtime/materials.js +34 -0
  198. package/templates/create/3d-collectathon/src/runtime/state.js +27 -0
  199. package/templates/create/3d-collectathon/ui/hud.screen.js +66 -0
  200. package/templates/create/3d-collectathon/ui/pause.screen.js +13 -0
  201. package/templates/create/blank/config/gameplay/.gitkeep +1 -0
  202. package/templates/create/blank/content/gameplay/.gitkeep +1 -0
  203. package/templates/create/blank/content/registries/.gitkeep +1 -0
  204. package/templates/create/blank/docs/design/.gitkeep +1 -0
  205. package/templates/create/blank/docs/design/loop.md +5 -0
  206. package/templates/create/blank/prefabs/.gitkeep +1 -0
  207. package/templates/create/blank/scenes/.gitkeep +1 -0
  208. package/templates/create/blank/src/runtime/.gitkeep +1 -0
  209. package/templates/create/blank/ui/.gitkeep +1 -0
  210. package/templates/create/deckbuilder-2d/assets/audio/.gitkeep +1 -0
  211. package/templates/create/deckbuilder-2d/assets/fonts/.gitkeep +1 -0
  212. package/templates/create/deckbuilder-2d/assets/sprites/.gitkeep +1 -0
  213. package/templates/create/deckbuilder-2d/assets/starter/README.md +11 -0
  214. package/templates/create/deckbuilder-2d/assets/ui/.gitkeep +1 -0
  215. package/templates/create/deckbuilder-2d/aura.config.json +28 -0
  216. package/templates/create/deckbuilder-2d/config/gameplay/deckbuilder.config.js +26 -0
  217. package/templates/create/deckbuilder-2d/content/cards/guard.card.js +19 -0
  218. package/templates/create/deckbuilder-2d/content/cards/spark.card.js +20 -0
  219. package/templates/create/deckbuilder-2d/content/cards/starter.deck.js +69 -0
  220. package/templates/create/deckbuilder-2d/content/cards/strike.card.js +19 -0
  221. package/templates/create/deckbuilder-2d/content/cards/survey.card.js +20 -0
  222. package/templates/create/deckbuilder-2d/content/encounters/training-battle.encounter.js +14 -0
  223. package/templates/create/deckbuilder-2d/content/encounters/training-battle.js +65 -0
  224. package/templates/create/deckbuilder-2d/content/enemies/training-automaton.enemy.js +48 -0
  225. package/templates/create/deckbuilder-2d/content/gameplay/.gitkeep +1 -0
  226. package/templates/create/deckbuilder-2d/content/registries/cards.registry.js +26 -0
  227. package/templates/create/deckbuilder-2d/content/registries/encounters.registry.js +20 -0
  228. package/templates/create/deckbuilder-2d/content/registries/enemies.registry.js +20 -0
  229. package/templates/create/deckbuilder-2d/content/registries/relics.registry.js +20 -0
  230. package/templates/create/deckbuilder-2d/content/relics/ember-charm.relic.js +18 -0
  231. package/templates/create/deckbuilder-2d/docs/design/loop.md +12 -0
  232. package/templates/create/deckbuilder-2d/prefabs/.gitkeep +1 -0
  233. package/templates/create/deckbuilder-2d/scenes/boot.scene.js +84 -0
  234. package/templates/create/deckbuilder-2d/scenes/gameplay.scene.js +641 -0
  235. package/templates/create/deckbuilder-2d/src/components/.gitkeep +1 -0
  236. package/templates/create/deckbuilder-2d/src/main.js +17 -0
  237. package/templates/create/deckbuilder-2d/src/runtime/capabilities.js +22 -0
  238. package/templates/create/deckbuilder-2d/src/shared/.gitkeep +1 -0
  239. package/templates/create/deckbuilder-2d/src/systems/.gitkeep +1 -0
  240. package/templates/create/deckbuilder-2d/tests/smoke/.gitkeep +1 -0
  241. package/templates/create/deckbuilder-2d/ui/hud.screen.js +80 -0
  242. package/templates/create/deckbuilder-2d/ui/pause.screen.js +146 -0
  243. package/templates/create/deckbuilder-2d/ui/settings.screen.js +342 -0
  244. package/templates/create/local-multiplayer/aura.config.json +40 -0
  245. package/templates/create/local-multiplayer/config/gameplay/local-multiplayer.config.js +26 -0
  246. package/templates/create/local-multiplayer/content/gameplay/room-layout.js +13 -0
  247. package/templates/create/local-multiplayer/content/registries/.gitkeep +1 -0
  248. package/templates/create/local-multiplayer/docs/design/loop.md +14 -0
  249. package/templates/create/local-multiplayer/prefabs/player.prefab.js +99 -0
  250. package/templates/create/local-multiplayer/scenes/boot.scene.js +12 -0
  251. package/templates/create/local-multiplayer/scenes/gameplay.scene.js +443 -0
  252. package/templates/create/local-multiplayer/src/main.js +17 -0
  253. package/templates/create/local-multiplayer/src/runtime/capabilities.js +28 -0
  254. package/templates/create/local-multiplayer/ui/hud.screen.js +60 -0
  255. package/templates/create/shared/src/runtime/project-inspector.js +105 -0
  256. package/templates/create/shared/src/runtime/scene-flow.js +290 -0
  257. package/templates/create/shared/src/runtime/screen-shell.js +222 -0
  258. package/templates/create/shared/src/runtime/ui-forms.js +209 -0
  259. package/templates/create/shared/src/runtime/ui-settings.js +237 -0
  260. package/templates/create/shared/src/runtime/ui-theme.js +352 -0
  261. package/templates/create/shared/src/starter-utils/adventure-objectives.js +102 -0
  262. package/templates/create/shared/src/starter-utils/animation-2d.js +337 -0
  263. package/templates/create/shared/src/starter-utils/avatar-3d.js +404 -0
  264. package/templates/create/shared/src/starter-utils/combat-feedback-2d.js +320 -0
  265. package/templates/create/shared/src/starter-utils/core.js +39 -3
  266. package/templates/create/shared/src/starter-utils/index.js +8 -2
  267. package/templates/create/shared/src/starter-utils/platformer-3d.js +34 -3
  268. package/templates/create/shared/src/starter-utils/triggers.js +662 -0
  269. package/templates/create/shared/src/starter-utils/tween-2d.js +615 -0
  270. package/templates/create/video-cutscene/assets/video/.gitkeep +0 -0
  271. package/templates/create/video-cutscene/aura.config.json +28 -0
  272. package/templates/create/video-cutscene/config/gameplay/.gitkeep +0 -0
  273. package/templates/create/video-cutscene/content/gameplay/.gitkeep +0 -0
  274. package/templates/create/video-cutscene/content/registries/.gitkeep +0 -0
  275. package/templates/create/video-cutscene/docs/design/loop.md +22 -0
  276. package/templates/create/video-cutscene/prefabs/.gitkeep +0 -0
  277. package/templates/create/video-cutscene/scenes/boot.scene.js +11 -0
  278. package/templates/create/video-cutscene/scenes/cutscene.scene.js +113 -0
  279. package/templates/create/video-cutscene/scenes/gameplay.scene.js +50 -0
  280. package/templates/create/video-cutscene/src/main.js +17 -0
  281. package/templates/create/video-cutscene/src/runtime/app.js +52 -0
  282. package/templates/create/video-cutscene/src/runtime/capabilities.js +35 -0
  283. package/templates/create/video-cutscene/src/runtime/state.js +13 -0
  284. package/templates/create/video-cutscene/ui/.gitkeep +0 -0
  285. package/templates/create-bin/play.js +1187 -0
  286. package/templates/make/README.md +46 -0
  287. package/templates/make/catalog.json +51 -0
  288. package/templates/make/component/files/{{MAKE_NAME}}.component.js +20 -0
  289. package/templates/make/component/manifest.json +9 -0
  290. package/templates/make/data/files/{{MAKE_NAME}}.json +14 -0
  291. package/templates/make/data/manifest.json +9 -0
  292. package/templates/make/material/files/{{MAKE_NAME}}.material.json +17 -0
  293. package/templates/make/material/manifest.json +9 -0
  294. package/templates/make/prefab/files/{{MAKE_NAME}}.prefab.js +20 -0
  295. package/templates/make/prefab/manifest.json +9 -0
  296. package/templates/make/scene/files/{{MAKE_NAME}}.scene.js +31 -0
  297. package/templates/make/scene/manifest.json +9 -0
  298. package/templates/make/shader/files/{{MAKE_NAME}}.shader.js +23 -0
  299. package/templates/make/shader/manifest.json +9 -0
  300. package/templates/make/system/files/{{MAKE_NAME}}.system.js +15 -0
  301. package/templates/make/system/manifest.json +9 -0
  302. package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.js +16 -0
  303. package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.json +23 -0
  304. package/templates/make/ui-screen/manifest.json +10 -0
  305. package/templates/make-starters/deckbuilder-2d/card/files/{{MAKE_NAME}}.card.js +22 -0
  306. package/templates/make-starters/deckbuilder-2d/card/manifest.json +9 -0
  307. package/templates/make-starters/deckbuilder-2d/catalog.json +34 -0
  308. package/templates/make-starters/deckbuilder-2d/encounter/files/{{MAKE_NAME}}.encounter.js +18 -0
  309. package/templates/make-starters/deckbuilder-2d/encounter/manifest.json +9 -0
  310. package/templates/make-starters/deckbuilder-2d/enemy/files/{{MAKE_NAME}}.enemy.js +28 -0
  311. package/templates/make-starters/deckbuilder-2d/enemy/manifest.json +9 -0
  312. package/templates/make-starters/deckbuilder-2d/relic/files/{{MAKE_NAME}}.relic.js +23 -0
  313. package/templates/make-starters/deckbuilder-2d/relic/manifest.json +9 -0
  314. package/templates/retro/platformer/README.md +10 -0
  315. package/templates/retro/platformer/assets/retro/assets.json +91 -0
  316. package/templates/retro/platformer/aura.config.json +7 -0
  317. package/templates/retro/platformer/package.json +5 -0
  318. package/templates/retro/platformer/src/main.js +40 -0
  319. package/templates/retro/puzzle-grid/README.md +10 -0
  320. package/templates/retro/puzzle-grid/assets/retro/assets.json +90 -0
  321. package/templates/retro/puzzle-grid/aura.config.json +7 -0
  322. package/templates/retro/puzzle-grid/package.json +5 -0
  323. package/templates/retro/puzzle-grid/src/main.js +29 -0
  324. package/templates/retro/tactics-grid/README.md +10 -0
  325. package/templates/retro/tactics-grid/assets/retro/assets.json +90 -0
  326. package/templates/retro/tactics-grid/aura.config.json +7 -0
  327. package/templates/retro/tactics-grid/package.json +5 -0
  328. package/templates/retro/tactics-grid/src/main.js +35 -0
  329. package/templates/retro/topdown-adventure/README.md +10 -0
  330. package/templates/retro/topdown-adventure/assets/retro/assets.json +95 -0
  331. package/templates/retro/topdown-adventure/aura.config.json +7 -0
  332. package/templates/retro/topdown-adventure/package.json +5 -0
  333. package/templates/retro/topdown-adventure/src/main.js +29 -0
  334. package/templates/skills/aurajs/SKILL.md +61 -5
@@ -1,20 +1,24 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { basename, dirname, join, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
3
4
  import {
4
5
  accessSync,
5
6
  existsSync,
6
7
  readFileSync,
7
8
  mkdirSync,
8
9
  copyFileSync,
10
+ chmodSync,
9
11
  statSync,
10
12
  writeFileSync,
11
13
  unlinkSync,
14
+ renameSync,
12
15
  constants as fsConstants,
13
16
  } from 'node:fs';
14
17
  import { createHash } from 'node:crypto';
15
18
  import { homedir } from 'node:os';
16
19
 
17
20
  const requireFromHere = createRequire(import.meta.url);
21
+ const CLI_PACKAGE_JSON_URL = new URL('../package.json', import.meta.url);
18
22
 
19
23
  const HOST_PACKAGE_SPECS = Object.freeze([
20
24
  Object.freeze({
@@ -51,6 +55,14 @@ function readJsonFile(path) {
51
55
  return JSON.parse(readFileSync(path, 'utf8'));
52
56
  }
53
57
 
58
+ function defaultCliPackageVersion() {
59
+ try {
60
+ return readJsonFile(CLI_PACKAGE_JSON_URL).version || null;
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
54
66
  function findPackageRootFromResolvedFile(resolvedFile, packageName, readPackageJson) {
55
67
  let cursor = dirname(resolvedFile);
56
68
  while (true) {
@@ -84,6 +96,10 @@ function defaultCacheRoot() {
84
96
  return process.env.AURAJS_HOST_CACHE_DIR || join(homedir(), '.cache', 'aurajs', 'host-binaries');
85
97
  }
86
98
 
99
+ function defaultReleaseBaseUrl() {
100
+ return process.env.AURAJS_HOST_RELEASE_BASE_URL || 'https://raw.githubusercontent.com/Aura-Industry';
101
+ }
102
+
87
103
  function resolveOverrideHostBinaryPath({
88
104
  platform = process.platform,
89
105
  arch = process.arch,
@@ -119,15 +135,21 @@ function safeUnlink(path) {
119
135
  } catch {}
120
136
  }
121
137
 
122
- function resolveCacheInfo(spec, binaryPath, packageRoot, packageVersion, cacheRoot) {
123
- const binaryStats = statSync(binaryPath);
138
+ function resolveCachePaths(spec, packageVersion, cacheRoot, binaryRelativePath = spec.binaryRelativePath) {
124
139
  const cacheDir = resolve(cacheRoot, spec.target, packageVersion || 'unknown');
125
- const cachedBinaryPath = resolve(cacheDir, basename(binaryPath));
140
+ const cachedBinaryPath = resolve(cacheDir, basename(binaryRelativePath));
126
141
  const manifestPath = resolve(cacheDir, 'manifest.json');
127
142
  return {
128
143
  cacheDir,
129
144
  cachedBinaryPath,
130
145
  manifestPath,
146
+ };
147
+ }
148
+
149
+ function resolveCacheInfo(spec, binaryPath, packageRoot, packageVersion, cacheRoot) {
150
+ const binaryStats = statSync(binaryPath);
151
+ return {
152
+ ...resolveCachePaths(spec, packageVersion, cacheRoot, binaryPath),
131
153
  sourceStat: {
132
154
  size: binaryStats.size,
133
155
  mtimeMs: binaryStats.mtimeMs,
@@ -138,6 +160,83 @@ function resolveCacheInfo(spec, binaryPath, packageRoot, packageVersion, cacheRo
138
160
  };
139
161
  }
140
162
 
163
+ function readValidCachedBinary({ spec, packageVersion, cacheRoot }) {
164
+ const cache = resolveCachePaths(spec, packageVersion, cacheRoot);
165
+ if (!existsSync(cache.cachedBinaryPath) || !existsSync(cache.manifestPath)) {
166
+ return null;
167
+ }
168
+
169
+ try {
170
+ const manifest = readJsonFile(cache.manifestPath);
171
+ const cachedStats = statSync(cache.cachedBinaryPath);
172
+ const cachedHash = hashFile(cache.cachedBinaryPath);
173
+ const versionMatches = manifest?.packageVersion == null || manifest.packageVersion === (packageVersion || 'unknown');
174
+ if (
175
+ manifest?.packageName !== spec.packageName
176
+ || manifest?.target !== spec.target
177
+ || manifest?.sha256 !== cachedHash
178
+ || manifest?.size !== cachedStats.size
179
+ || !versionMatches
180
+ ) {
181
+ return null;
182
+ }
183
+
184
+ return {
185
+ ...cache,
186
+ manifest,
187
+ cachedStats,
188
+ cachedHash,
189
+ };
190
+ } catch {
191
+ return null;
192
+ }
193
+ }
194
+
195
+ function ensureCachedBinaryExecutable(path, platform) {
196
+ if (platform === 'win32') return;
197
+ try {
198
+ chmodSync(path, 0o755);
199
+ } catch {}
200
+ }
201
+
202
+ function formatReleaseRepo(spec) {
203
+ return `Aura-Industry/aurajs-${spec.target}`;
204
+ }
205
+
206
+ function buildReleaseSource(spec, packageVersion) {
207
+ const tag = `v${packageVersion}`;
208
+ const baseUrl = defaultReleaseBaseUrl().replace(/\/+$/, '');
209
+ const repo = formatReleaseRepo(spec);
210
+ const rootUrl = `${baseUrl}/aurajs-${spec.target}/${tag}`;
211
+ return {
212
+ repo,
213
+ tag,
214
+ rootUrl,
215
+ packageJsonUrl: `${rootUrl}/package.json`,
216
+ };
217
+ }
218
+
219
+ async function fetchText(url, fetchImpl) {
220
+ const response = await fetchImpl(url);
221
+ if (!response?.ok) {
222
+ throw new Error(`HTTP ${response?.status ?? 'ERR'} for ${url}`);
223
+ }
224
+ return response.text();
225
+ }
226
+
227
+ async function fetchBytes(url, fetchImpl) {
228
+ const response = await fetchImpl(url);
229
+ if (!response?.ok) {
230
+ throw new Error(`HTTP ${response?.status ?? 'ERR'} for ${url}`);
231
+ }
232
+ const buffer = await response.arrayBuffer();
233
+ return Buffer.from(buffer);
234
+ }
235
+
236
+ function writeCachedBinaryManifest(manifestPath, manifest) {
237
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
238
+ }
239
+
141
240
  export class HostBinaryResolutionError extends Error {
142
241
  constructor(message, { code = 'AURA_HOST_BINARY_ERROR', platform, arch, packageName, cause } = {}) {
143
242
  super(message, cause ? { cause } : undefined);
@@ -202,22 +301,43 @@ export function resolveAndCacheHostBinary({
202
301
  platform = process.platform,
203
302
  arch = process.arch,
204
303
  cacheRoot = defaultCacheRoot(),
205
- packageJsonVersion,
304
+ packageJsonVersion = defaultCliPackageVersion(),
206
305
  resolvePackageRoot,
207
306
  } = {}) {
208
- const resolved = resolveHostBinaryPath({ platform, arch, resolvePackageRoot });
209
-
210
- if (resolved.override) {
307
+ const override = resolveOverrideHostBinaryPath({ platform, arch });
308
+ if (override) {
211
309
  return {
212
- ...resolved,
213
- cacheDir: dirname(resolved.binaryPath),
214
- cachedBinaryPath: resolved.binaryPath,
310
+ ...override,
311
+ cacheDir: dirname(override.binaryPath),
312
+ cachedBinaryPath: override.binaryPath,
215
313
  manifestPath: null,
216
314
  cacheStatus: 'override',
217
315
  diagnostics: ['Using AURAJS_HOST_BINARY_PATH override; cache step skipped.'],
218
316
  };
219
317
  }
220
318
 
319
+ const spec = getHostPackageSpec({ platform, arch });
320
+ const versionedCacheHit = packageJsonVersion
321
+ ? readValidCachedBinary({ spec, packageVersion: packageJsonVersion, cacheRoot })
322
+ : null;
323
+ if (versionedCacheHit) {
324
+ ensureCachedBinaryExecutable(versionedCacheHit.cachedBinaryPath, platform);
325
+ return {
326
+ ...spec,
327
+ packageRoot: versionedCacheHit.manifest?.packageRoot || null,
328
+ cacheDir: versionedCacheHit.cacheDir,
329
+ cachedBinaryPath: versionedCacheHit.cachedBinaryPath,
330
+ manifestPath: versionedCacheHit.manifestPath,
331
+ cacheStatus: 'hit',
332
+ binaryPath: versionedCacheHit.cachedBinaryPath,
333
+ diagnostics: [],
334
+ packageVersion: versionedCacheHit.manifest?.packageVersion || packageJsonVersion || null,
335
+ release: versionedCacheHit.manifest?.release || null,
336
+ };
337
+ }
338
+
339
+ const resolved = resolveHostBinaryPath({ platform, arch, resolvePackageRoot });
340
+
221
341
  let packageVersion = packageJsonVersion;
222
342
  try {
223
343
  const packageJson = readJsonFile(resolve(resolved.packageRoot, 'package.json'));
@@ -237,6 +357,7 @@ export function resolveAndCacheHostBinary({
237
357
  const sourceHash = hashFile(cache.sourceBinaryPath);
238
358
  const manifest = {
239
359
  packageName: resolved.packageName,
360
+ packageVersion: packageVersion || 'unknown',
240
361
  target: resolved.target,
241
362
  sourceBinaryPath: cache.sourceBinaryPath,
242
363
  packageRoot: cache.packageRoot,
@@ -266,7 +387,8 @@ export function resolveAndCacheHostBinary({
266
387
  if (!cacheHit) {
267
388
  safeUnlink(cache.cachedBinaryPath);
268
389
  copyFileSync(cache.sourceBinaryPath, cache.cachedBinaryPath);
269
- writeFileSync(cache.manifestPath, JSON.stringify(manifest, null, 2));
390
+ ensureCachedBinaryExecutable(cache.cachedBinaryPath, platform);
391
+ writeCachedBinaryManifest(cache.manifestPath, manifest);
270
392
  }
271
393
 
272
394
  return {
@@ -276,10 +398,181 @@ export function resolveAndCacheHostBinary({
276
398
  manifestPath: cache.manifestPath,
277
399
  cacheStatus: cacheHit ? 'hit' : 'refreshed',
278
400
  binaryPath: cache.cachedBinaryPath,
401
+ packageVersion,
279
402
  diagnostics: cacheHit
280
403
  ? []
281
- : ['Host binary cache was missing/stale/corrupt and has been refreshed from optionalDependencies.'],
404
+ : ['Host binary cache was missing/stale/corrupt and has been refreshed from a packaged host binary.'],
405
+ };
406
+ }
407
+
408
+ export async function downloadAndCacheHostBinary({
409
+ platform = process.platform,
410
+ arch = process.arch,
411
+ cacheRoot = defaultCacheRoot(),
412
+ packageJsonVersion = defaultCliPackageVersion(),
413
+ fetchImpl = globalThis.fetch,
414
+ } = {}) {
415
+ if (!packageJsonVersion) {
416
+ throw new HostBinaryResolutionError(
417
+ 'Host binary download requires an explicit CLI package version.',
418
+ { code: 'AURA_HOST_VERSION_REQUIRED', platform, arch },
419
+ );
420
+ }
421
+
422
+ if (typeof fetchImpl !== 'function') {
423
+ throw new HostBinaryResolutionError(
424
+ 'Global fetch is unavailable; cannot download the host binary.',
425
+ { code: 'AURA_HOST_DOWNLOAD_UNAVAILABLE', platform, arch },
426
+ );
427
+ }
428
+
429
+ const override = resolveOverrideHostBinaryPath({ platform, arch });
430
+ if (override) {
431
+ return {
432
+ ...override,
433
+ cacheDir: dirname(override.binaryPath),
434
+ cachedBinaryPath: override.binaryPath,
435
+ manifestPath: null,
436
+ cacheStatus: 'override',
437
+ diagnostics: ['Using AURAJS_HOST_BINARY_PATH override; cache step skipped.'],
438
+ };
439
+ }
440
+
441
+ const spec = getHostPackageSpec({ platform, arch });
442
+ const source = buildReleaseSource(spec, packageJsonVersion);
443
+ let remotePackage;
444
+
445
+ try {
446
+ remotePackage = JSON.parse(await fetchText(source.packageJsonUrl, fetchImpl));
447
+ } catch (cause) {
448
+ throw new HostBinaryResolutionError(
449
+ `Failed to load host package metadata for ${spec.packageName}@${packageJsonVersion} from ${source.repo} (${source.tag}).`,
450
+ { code: 'AURA_HOST_DOWNLOAD_METADATA_FAILED', platform, arch, packageName: spec.packageName, cause },
451
+ );
452
+ }
453
+
454
+ if (remotePackage?.name !== spec.packageName) {
455
+ throw new HostBinaryResolutionError(
456
+ `Downloaded host package metadata does not match expected package "${spec.packageName}".`,
457
+ { code: 'AURA_HOST_DOWNLOAD_METADATA_INVALID', platform, arch, packageName: spec.packageName },
458
+ );
459
+ }
460
+ if (remotePackage?.version !== packageJsonVersion) {
461
+ throw new HostBinaryResolutionError(
462
+ `Downloaded host package version mismatch for "${spec.packageName}": expected ${packageJsonVersion}, received ${remotePackage?.version || 'unknown'}.`,
463
+ { code: 'AURA_HOST_VERSION_MISMATCH', platform, arch, packageName: spec.packageName },
464
+ );
465
+ }
466
+
467
+ const remoteBinaryPath = remotePackage?.aurajsHost?.binaryPath;
468
+ const checksumAlgorithm = remotePackage?.aurajsHost?.checksumAlgorithm;
469
+ const checksum = remotePackage?.aurajsHost?.checksum;
470
+ if (typeof remoteBinaryPath !== 'string' || remoteBinaryPath.length === 0) {
471
+ throw new HostBinaryResolutionError(
472
+ `Downloaded host package metadata for "${spec.packageName}" is missing aurajsHost.binaryPath.`,
473
+ { code: 'AURA_HOST_DOWNLOAD_METADATA_INVALID', platform, arch, packageName: spec.packageName },
474
+ );
475
+ }
476
+ if (checksumAlgorithm !== 'sha256' || typeof checksum !== 'string' || checksum.length === 0) {
477
+ throw new HostBinaryResolutionError(
478
+ `Downloaded host package metadata for "${spec.packageName}" is missing a valid SHA256 checksum.`,
479
+ { code: 'AURA_HOST_DOWNLOAD_METADATA_INVALID', platform, arch, packageName: spec.packageName },
480
+ );
481
+ }
482
+
483
+ const binaryUrl = `${source.rootUrl}/${remoteBinaryPath}`;
484
+ let binaryBuffer;
485
+ try {
486
+ binaryBuffer = await fetchBytes(binaryUrl, fetchImpl);
487
+ } catch (cause) {
488
+ throw new HostBinaryResolutionError(
489
+ `Failed to download host binary for ${spec.packageName}@${packageJsonVersion} from ${source.repo} (${source.tag}).`,
490
+ { code: 'AURA_HOST_DOWNLOAD_BINARY_FAILED', platform, arch, packageName: spec.packageName, cause },
491
+ );
492
+ }
493
+
494
+ const binaryHash = createHash('sha256').update(binaryBuffer).digest('hex');
495
+ if (binaryHash !== checksum) {
496
+ throw new HostBinaryResolutionError(
497
+ `Downloaded host binary checksum mismatch for ${spec.packageName}@${packageJsonVersion}.`,
498
+ { code: 'AURA_HOST_CHECKSUM_MISMATCH', platform, arch, packageName: spec.packageName },
499
+ );
500
+ }
501
+
502
+ const cache = resolveCachePaths(spec, packageJsonVersion, cacheRoot, remoteBinaryPath);
503
+ mkdirSync(cache.cacheDir, { recursive: true });
504
+
505
+ const tempBinaryPath = `${cache.cachedBinaryPath}.download-${process.pid}-${Date.now()}`;
506
+ safeUnlink(tempBinaryPath);
507
+ safeUnlink(cache.cachedBinaryPath);
508
+
509
+ try {
510
+ writeFileSync(tempBinaryPath, binaryBuffer);
511
+ ensureCachedBinaryExecutable(tempBinaryPath, platform);
512
+ renameSync(tempBinaryPath, cache.cachedBinaryPath);
513
+ } finally {
514
+ safeUnlink(tempBinaryPath);
515
+ }
516
+
517
+ const manifest = {
518
+ packageName: spec.packageName,
519
+ packageVersion: packageJsonVersion,
520
+ target: spec.target,
521
+ sourceBinaryPath: binaryUrl,
522
+ packageRoot: null,
523
+ size: binaryBuffer.length,
524
+ mtimeMs: Date.now(),
525
+ mode: platform === 'win32' ? null : 0o755,
526
+ sha256: binaryHash,
527
+ release: {
528
+ repo: source.repo,
529
+ tag: source.tag,
530
+ packageJsonUrl: source.packageJsonUrl,
531
+ binaryUrl,
532
+ },
282
533
  };
534
+ writeCachedBinaryManifest(cache.manifestPath, manifest);
535
+
536
+ return {
537
+ ...spec,
538
+ packageRoot: null,
539
+ binaryPath: cache.cachedBinaryPath,
540
+ cacheDir: cache.cacheDir,
541
+ cachedBinaryPath: cache.cachedBinaryPath,
542
+ manifestPath: cache.manifestPath,
543
+ cacheStatus: 'downloaded',
544
+ packageVersion: packageJsonVersion,
545
+ diagnostics: [`Downloaded host binary from ${source.repo}@${source.tag}.`],
546
+ release: manifest.release,
547
+ };
548
+ }
549
+
550
+ export async function ensureHostBinaryAvailable(options = {}) {
551
+ try {
552
+ const defaultSearchFrom = dirname(fileURLToPath(CLI_PACKAGE_JSON_URL));
553
+ return resolveGateHostBinary({
554
+ platform: options.platform,
555
+ arch: options.arch,
556
+ searchFrom: options.searchFrom || defaultSearchFrom,
557
+ cacheRoot: options.cacheRoot,
558
+ resolveCachedBinary: (cachedOptions) => resolveAndCacheHostBinary({
559
+ ...options,
560
+ ...cachedOptions,
561
+ }),
562
+ resolvePackagedBinary: (packagedOptions) => resolveHostBinaryPath({
563
+ ...options,
564
+ ...packagedOptions,
565
+ }),
566
+ });
567
+ } catch (error) {
568
+ if (!(error instanceof HostBinaryResolutionError)) {
569
+ throw error;
570
+ }
571
+ if (!options?.packageJsonVersion) {
572
+ throw error;
573
+ }
574
+ return downloadAndCacheHostBinary(options);
575
+ }
283
576
  }
284
577
 
285
578
  function findInstalledPackageRoot(packageName, { requireResolve, readPackageJson }) {
@@ -295,7 +588,7 @@ function findInstalledPackageRoot(packageName, { requireResolve, readPackageJson
295
588
  resolvedEntrypoint = requireResolve(packageName);
296
589
  } catch (cause) {
297
590
  throw new HostBinaryResolutionError(
298
- `Missing host package "${packageName}". Run "npm install" to install optional platform binaries.`,
591
+ `Missing packaged host binary "${packageName}". Run "npm install" to restore packaged binaries, or let AuraJS download the host on first run.`,
299
592
  { code: 'AURA_HOST_PACKAGE_MISSING', packageName, cause },
300
593
  );
301
594
  }
@@ -365,6 +658,23 @@ export function resolveGateHostBinary({
365
658
  const repoRoot = findRepoRootWithRustHost(searchFrom);
366
659
  const localCandidates = repoRoot ? resolveLocalHostBinaryCandidates(repoRoot, binaryName) : [];
367
660
  const checkedCandidates = localCandidates.map((candidate) => candidate.path);
661
+ const override = resolveOverrideHostBinaryPath({ platform, arch });
662
+
663
+ if (override) {
664
+ return {
665
+ ...override,
666
+ source: 'override',
667
+ reasonCode: 'host_binary_override_selected',
668
+ diagnostics: ['Using AURAJS_HOST_BINARY_PATH override; local build/package resolution skipped.'],
669
+ localBuild: {
670
+ repoRoot,
671
+ checked: checkedCandidates,
672
+ },
673
+ resolvedAt: new Date().toISOString(),
674
+ };
675
+ }
676
+
677
+ const availableLocalCandidates = [];
368
678
 
369
679
  for (const candidate of localCandidates) {
370
680
  if (!existsSync(candidate.path)) continue;
@@ -372,9 +682,27 @@ export function resolveGateHostBinary({
372
682
  diagnostics.push(`[host_binary_local_non_executable] Detected local ${candidate.kind} host binary but it is not executable: ${candidate.path}`);
373
683
  continue;
374
684
  }
685
+ availableLocalCandidates.push({
686
+ ...candidate,
687
+ mtimeMs: statSync(candidate.path).mtimeMs,
688
+ });
689
+ }
690
+
691
+ if (availableLocalCandidates.length > 0) {
692
+ availableLocalCandidates.sort((a, b) => {
693
+ if (a.kind !== b.kind) {
694
+ return a.kind === 'release' ? -1 : 1;
695
+ }
696
+ if (b.mtimeMs !== a.mtimeMs) {
697
+ return b.mtimeMs - a.mtimeMs;
698
+ }
699
+ return 0;
700
+ });
701
+
702
+ const candidate = availableLocalCandidates[0];
375
703
  if (candidate.kind === 'debug') {
376
704
  diagnostics.push(
377
- `[host_binary_local_debug_fallback] Selected local debug host because release host is unavailable or not executable: ${candidate.path}`,
705
+ `[host_binary_local_debug_fallback] Selected newer local debug host: ${candidate.path}`,
378
706
  );
379
707
  }
380
708
 
@@ -0,0 +1,64 @@
1
+ import { existsSync, readdirSync } from 'node:fs';
2
+ import { basename, extname, join, relative, resolve } from 'node:path';
3
+
4
+ export const SUPPORTED_BUILD_ICON_EXTENSIONS = Object.freeze(['.png', '.jpg', '.jpeg', '.ico', '.icns']);
5
+
6
+ function compareCandidates(a, b) {
7
+ if (a.exactBaseName !== b.exactBaseName) {
8
+ return a.exactBaseName ? -1 : 1;
9
+ }
10
+ if (a.extensionRank !== b.extensionRank) {
11
+ return a.extensionRank - b.extensionRank;
12
+ }
13
+ if (a.depth !== b.depth) {
14
+ return a.depth - b.depth;
15
+ }
16
+ return a.relativePath.localeCompare(b.relativePath);
17
+ }
18
+
19
+ function walk(dirPath, visit) {
20
+ for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
21
+ const fullPath = join(dirPath, entry.name);
22
+ if (entry.isDirectory()) {
23
+ walk(fullPath, visit);
24
+ continue;
25
+ }
26
+ if (entry.isFile()) {
27
+ visit(fullPath);
28
+ }
29
+ }
30
+ }
31
+
32
+ export function discoverProjectIconPath({ projectRoot, assetDir = 'assets' } = {}) {
33
+ const normalizedAssetDir = String(assetDir || 'assets').trim() || 'assets';
34
+ const assetRoot = resolve(projectRoot, normalizedAssetDir);
35
+ if (!existsSync(assetRoot)) {
36
+ return null;
37
+ }
38
+
39
+ const candidates = [];
40
+ walk(assetRoot, (fullPath) => {
41
+ const extension = extname(fullPath).toLowerCase();
42
+ const extensionRank = SUPPORTED_BUILD_ICON_EXTENSIONS.indexOf(extension);
43
+ if (extensionRank === -1) {
44
+ return;
45
+ }
46
+ const fileBaseName = basename(fullPath, extension).toLowerCase();
47
+ if (!fileBaseName.startsWith('logo')) {
48
+ return;
49
+ }
50
+ const relativePath = relative(projectRoot, fullPath).split('\\').join('/');
51
+ candidates.push({
52
+ relativePath,
53
+ exactBaseName: fileBaseName === 'logo',
54
+ extensionRank,
55
+ depth: relativePath.split('/').length,
56
+ });
57
+ });
58
+
59
+ if (candidates.length === 0) {
60
+ return null;
61
+ }
62
+ candidates.sort(compareCandidates);
63
+ return candidates[0].relativePath;
64
+ }
@@ -0,0 +1,109 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const CLI_SRC_DIR = dirname(fileURLToPath(import.meta.url));
6
+ const CORE_MAKE_TEMPLATE_DIR = resolve(CLI_SRC_DIR, '../templates/make');
7
+ const CORE_MAKE_CATALOG_PATH = resolve(CORE_MAKE_TEMPLATE_DIR, 'catalog.json');
8
+ const STARTER_MAKE_TEMPLATE_DIR = resolve(CLI_SRC_DIR, '../templates/make-starters');
9
+
10
+ function readJsonFile(path) {
11
+ return JSON.parse(readFileSync(path, 'utf8'));
12
+ }
13
+
14
+ function normalizeCatalogRows(source, { owner, scope, manifestDir }) {
15
+ const kinds = Array.isArray(source?.kinds) ? source.kinds : [];
16
+ return kinds.map((entry) => {
17
+ const id = String(entry?.id || '').trim();
18
+ const manifest = String(entry?.manifest || '').trim();
19
+ if (!id || !manifest) {
20
+ throw new Error(`Invalid make catalog entry for owner "${owner}".`);
21
+ }
22
+ return {
23
+ id,
24
+ owner,
25
+ scope,
26
+ manifestPath: resolve(manifestDir, manifest),
27
+ outputRoot: typeof entry?.outputRoot === 'string' && entry.outputRoot.trim().length > 0
28
+ ? entry.outputRoot.trim()
29
+ : null,
30
+ registerAs: typeof entry?.registerAs === 'string' && entry.registerAs.trim().length > 0
31
+ ? entry.registerAs.trim()
32
+ : null,
33
+ defaultRole: typeof entry?.defaultRole === 'string' && entry.defaultRole.trim().length > 0
34
+ ? entry.defaultRole.trim()
35
+ : null,
36
+ starterContentFamily: typeof entry?.starterContentFamily === 'string' && entry.starterContentFamily.trim().length > 0
37
+ ? entry.starterContentFamily.trim()
38
+ : null,
39
+ starterContentRegistry: typeof entry?.starterContentRegistry === 'string' && entry.starterContentRegistry.trim().length > 0
40
+ ? entry.starterContentRegistry.trim()
41
+ : null,
42
+ };
43
+ });
44
+ }
45
+
46
+ function loadProjectTemplate(projectRoot) {
47
+ if (!projectRoot) return 'blank';
48
+ const capabilitiesPath = resolve(projectRoot, 'aura.capabilities.json');
49
+ if (!existsSync(capabilitiesPath)) return 'blank';
50
+ try {
51
+ const capabilities = readJsonFile(capabilitiesPath);
52
+ if (typeof capabilities?.template === 'string' && capabilities.template.trim().length > 0) {
53
+ return capabilities.template.trim();
54
+ }
55
+ } catch {}
56
+ return 'blank';
57
+ }
58
+
59
+ export function loadCoreMakeCatalog() {
60
+ const catalog = readJsonFile(CORE_MAKE_CATALOG_PATH);
61
+ return normalizeCatalogRows(catalog, {
62
+ owner: 'core',
63
+ scope: 'core',
64
+ manifestDir: CORE_MAKE_TEMPLATE_DIR,
65
+ });
66
+ }
67
+
68
+ export function loadStarterMakeCatalog(template, options = {}) {
69
+ const normalizedTemplate = String(template || '').trim() || 'blank';
70
+ const starterCatalogRoot = resolve(options.catalogRoot || STARTER_MAKE_TEMPLATE_DIR);
71
+ const catalogPath = resolve(starterCatalogRoot, normalizedTemplate, 'catalog.json');
72
+ if (!existsSync(catalogPath)) return [];
73
+ const catalog = readJsonFile(catalogPath);
74
+ return normalizeCatalogRows(catalog, {
75
+ owner: `starter:${normalizedTemplate}`,
76
+ scope: normalizedTemplate,
77
+ manifestDir: dirname(catalogPath),
78
+ });
79
+ }
80
+
81
+ export function loadMakeCatalog(options = {}) {
82
+ const projectRoot = options.projectRoot ? resolve(options.projectRoot) : null;
83
+ const template = options.template || loadProjectTemplate(projectRoot);
84
+ const coreEntries = loadCoreMakeCatalog();
85
+ const starterEntries = loadStarterMakeCatalog(template, options);
86
+ const merged = new Map();
87
+
88
+ for (const entry of [...coreEntries, ...starterEntries]) {
89
+ if (merged.has(entry.id)) {
90
+ throw new Error(`Duplicate make kind "${entry.id}" in merged make catalog.`);
91
+ }
92
+ merged.set(entry.id, entry);
93
+ }
94
+
95
+ return [...merged.values()];
96
+ }
97
+
98
+ export function listMakeKinds(options = {}) {
99
+ return loadMakeCatalog(options).map((entry) => entry.id);
100
+ }
101
+
102
+ export function listCoreMakeKinds() {
103
+ return loadCoreMakeCatalog().map((entry) => entry.id);
104
+ }
105
+
106
+ export function resolveMakeKind(kind, options = {}) {
107
+ const normalizedKind = String(kind || '').trim();
108
+ return loadMakeCatalog(options).find((entry) => entry.id === normalizedKind) || null;
109
+ }