@auraindustry/aurajs 0.0.7 → 0.1.1

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 +98 -2
  2. package/benchmarks/perf-thresholds.json +54 -0
  3. package/package.json +4 -7
  4. package/src/asset-pack.mjs +8 -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 +4840 -1512
  17. package/src/commands/project-authoring.mjs +454 -0
  18. package/src/config.mjs +44 -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 +439 -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 +41 -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 +16 -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 +472 -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 +65 -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 +1192 -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
@@ -0,0 +1,708 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ import { assertProjectBinIntegrity, DEFAULT_AURAJS_PACKAGE_ROOT } from './bin-integrity.mjs';
7
+ import { BUILD_MANIFEST_SCHEMA } from './build-contract.mjs';
8
+ import { loadConfig } from './config.mjs';
9
+ import {
10
+ ASSET_MANIFEST_SCHEMA,
11
+ evaluateExternalAssetPolicy,
12
+ } from './external-asset-policy.mjs';
13
+ import {
14
+ inspectPublishPackFiles,
15
+ preparePublishPackageSurface,
16
+ SELF_HOSTED_PACKAGE_SURFACE_MODE,
17
+ } from './external-package-surface.mjs';
18
+ import {
19
+ PACKAGE_INTEGRITY_MANIFEST_PATH,
20
+ PACKAGE_INTEGRITY_PUBLISH_FILES,
21
+ PACKAGE_INTEGRITY_SIGNATURE_PATH,
22
+ writeSignedPackageIntegrityArtifacts,
23
+ } from './package-integrity.mjs';
24
+ import {
25
+ PUBLISH_ENV_EXAMPLE_PATH,
26
+ PUBLISH_SOURCE_ENV_PATH,
27
+ resolvePublishEnvExampleSurface,
28
+ } from './publish-env-example.mjs';
29
+
30
+ export const PUBLISH_REPORT_SCHEMA = 'aurajs.publish-report.v1';
31
+ const CLI_ENTRY_PATH = fileURLToPath(new URL('./cli.mjs', import.meta.url));
32
+ const AURAJS_PACKAGE_VERSION = JSON.parse(readFileSync(resolve(DEFAULT_AURAJS_PACKAGE_ROOT, 'package.json'), 'utf8')).version;
33
+
34
+ export class PublishValidationError extends Error {
35
+ constructor(reasonCode, message, details = {}) {
36
+ super(message);
37
+ this.name = 'PublishValidationError';
38
+ this.reasonCode = typeof reasonCode === 'string' && reasonCode.length > 0
39
+ ? reasonCode
40
+ : 'publish_validation_failed';
41
+ this.details = details && typeof details === 'object' ? details : {};
42
+ this.reportPath = null;
43
+ this.report = null;
44
+ }
45
+ }
46
+
47
+ function nowIso() {
48
+ return new Date().toISOString();
49
+ }
50
+
51
+ function resolveNpmCommand() {
52
+ return process.platform === 'win32' ? 'npm.cmd' : 'npm';
53
+ }
54
+
55
+ function currentPlatformTarget() {
56
+ if (process.platform === 'win32') return 'windows';
57
+ if (process.platform === 'darwin') return 'mac';
58
+ return 'linux';
59
+ }
60
+
61
+ function pipeChildStream(stream, target, sink) {
62
+ if (!stream) return;
63
+ stream.on('data', (chunk) => {
64
+ const text = String(chunk);
65
+ sink.push(text);
66
+ target?.write?.(chunk);
67
+ });
68
+ }
69
+
70
+ function runChildProcess(command, args, {
71
+ cwd,
72
+ env,
73
+ stdout = process.stdout,
74
+ stderr = process.stderr,
75
+ failureReasonCode,
76
+ failureMessage,
77
+ } = {}) {
78
+ return new Promise((resolveRun, rejectRun) => {
79
+ const stdoutChunks = [];
80
+ const stderrChunks = [];
81
+ const child = spawn(command, args, {
82
+ cwd,
83
+ env,
84
+ stdio: ['ignore', 'pipe', 'pipe'],
85
+ });
86
+
87
+ pipeChildStream(child.stdout, stdout, stdoutChunks);
88
+ pipeChildStream(child.stderr, stderr, stderrChunks);
89
+
90
+ child.on('error', (error) => {
91
+ rejectRun(new PublishValidationError(
92
+ failureReasonCode,
93
+ `${failureMessage}: ${error.message}`,
94
+ {
95
+ command,
96
+ args,
97
+ cwd,
98
+ },
99
+ ));
100
+ });
101
+
102
+ child.on('close', (code, signal) => {
103
+ if ((code ?? 1) === 0) {
104
+ resolveRun({
105
+ ok: true,
106
+ code: 0,
107
+ signal: signal ?? null,
108
+ stdout: stdoutChunks.join(''),
109
+ stderr: stderrChunks.join(''),
110
+ });
111
+ return;
112
+ }
113
+
114
+ rejectRun(new PublishValidationError(
115
+ failureReasonCode,
116
+ signal
117
+ ? `${failureMessage}: process exited by signal ${signal}.`
118
+ : `${failureMessage}: process exited with code ${code ?? 1}.`,
119
+ {
120
+ command,
121
+ args,
122
+ cwd,
123
+ code: code ?? 1,
124
+ signal: signal ?? null,
125
+ stdout: stdoutChunks.join(''),
126
+ stderr: stderrChunks.join(''),
127
+ },
128
+ ));
129
+ });
130
+ });
131
+ }
132
+
133
+ function readProjectPackage(projectRoot) {
134
+ const packagePath = resolve(projectRoot, 'package.json');
135
+ if (!existsSync(packagePath)) {
136
+ throw new PublishValidationError(
137
+ 'publish_package_json_missing',
138
+ 'aura publish requires a package.json in the current project root.',
139
+ { packagePath },
140
+ );
141
+ }
142
+
143
+ let projectPackage;
144
+ try {
145
+ projectPackage = JSON.parse(readFileSync(packagePath, 'utf8'));
146
+ } catch (error) {
147
+ throw new PublishValidationError(
148
+ 'publish_package_json_invalid',
149
+ `Failed to read package.json for aura publish: ${error.message}`,
150
+ { packagePath },
151
+ );
152
+ }
153
+
154
+ const packageName = typeof projectPackage?.name === 'string' && projectPackage.name.trim().length > 0
155
+ ? projectPackage.name.trim()
156
+ : null;
157
+ if (!packageName) {
158
+ throw new PublishValidationError(
159
+ 'publish_package_name_missing',
160
+ 'aura publish requires package.json -> name to be set.',
161
+ { packagePath },
162
+ );
163
+ }
164
+
165
+ const packageVersion = typeof projectPackage?.version === 'string' && projectPackage.version.trim().length > 0
166
+ ? projectPackage.version.trim()
167
+ : null;
168
+ if (!packageVersion) {
169
+ throw new PublishValidationError(
170
+ 'publish_package_version_missing',
171
+ 'aura publish requires package.json -> version to be set.',
172
+ { packagePath },
173
+ );
174
+ }
175
+
176
+ return {
177
+ packagePath,
178
+ projectPackage,
179
+ packageName,
180
+ packageVersion,
181
+ };
182
+ }
183
+
184
+ function normalizeBinEntries(projectPackage, packageName) {
185
+ if (typeof projectPackage?.bin === 'string' && projectPackage.bin.trim().length > 0) {
186
+ return [{
187
+ name: packageName.split('/').pop() || packageName,
188
+ relativePath: normalizeRelativePath(projectPackage.bin.trim()),
189
+ }];
190
+ }
191
+
192
+ const entries = Object.entries(projectPackage?.bin || {})
193
+ .filter(([, value]) => typeof value === 'string' && value.trim().length > 0)
194
+ .map(([name, value]) => ({
195
+ name,
196
+ relativePath: normalizeRelativePath(value.trim()),
197
+ }));
198
+
199
+ if (entries.length === 0) {
200
+ throw new PublishValidationError(
201
+ 'publish_bin_missing',
202
+ 'aura publish requires package.json -> bin to point at the generated wrapper entrypoint.',
203
+ {},
204
+ );
205
+ }
206
+
207
+ return entries;
208
+ }
209
+
210
+ function normalizeRelativePath(pathLike) {
211
+ return String(pathLike || '')
212
+ .trim()
213
+ .replace(/^[.][\\/]/, '')
214
+ .replaceAll('\\', '/');
215
+ }
216
+
217
+ function assertRequiredFileExists(projectRoot, relativePath, reasonCode, message) {
218
+ const absolutePath = resolve(projectRoot, relativePath);
219
+ if (!existsSync(absolutePath)) {
220
+ throw new PublishValidationError(reasonCode, message, {
221
+ path: relativePath,
222
+ absolutePath,
223
+ });
224
+ }
225
+ return absolutePath;
226
+ }
227
+
228
+ function createBaseReport({ projectRoot, packageName, packageVersion }) {
229
+ const normalizedPackageName = typeof packageName === 'string' && packageName.length > 0
230
+ ? packageName
231
+ : null;
232
+ return {
233
+ schema: PUBLISH_REPORT_SCHEMA,
234
+ generatedAt: nowIso(),
235
+ projectRoot,
236
+ package: {
237
+ name: normalizedPackageName,
238
+ version: packageVersion,
239
+ scope: normalizedPackageName
240
+ ? (normalizedPackageName.startsWith('@') ? 'scoped' : 'unscoped')
241
+ : null,
242
+ },
243
+ summary: {
244
+ pass: false,
245
+ reasonCode: null,
246
+ },
247
+ validation: {
248
+ metadata: {},
249
+ binIntegrity: {},
250
+ packageIntegrity: {},
251
+ build: {},
252
+ assets: {},
253
+ pack: {},
254
+ },
255
+ };
256
+ }
257
+
258
+ function writePublishReport(projectRoot, report) {
259
+ const reportRoot = resolve(projectRoot, '.aura', 'publish');
260
+ mkdirSync(reportRoot, { recursive: true });
261
+ const reportPath = join(reportRoot, 'publish-report.json');
262
+ writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
263
+ return reportPath;
264
+ }
265
+
266
+ function normalizePackFiles(entry) {
267
+ if (!entry || typeof entry !== 'object' || !Array.isArray(entry.files)) {
268
+ throw new PublishValidationError(
269
+ 'publish_pack_json_invalid',
270
+ 'npm pack --json --dry-run did not return a files payload.',
271
+ { entry },
272
+ );
273
+ }
274
+ return entry.files
275
+ .filter((file) => file && typeof file.path === 'string')
276
+ .map((file) => ({
277
+ path: file.path,
278
+ size: Number.isFinite(file.size) ? file.size : null,
279
+ mode: Number.isFinite(file.mode) ? file.mode : null,
280
+ }));
281
+ }
282
+
283
+ function validatePackRequiredFiles(packFiles, requiredPaths) {
284
+ const packagedPaths = new Set(packFiles.map((entry) => entry.path));
285
+ const missing = requiredPaths.filter((filePath) => !packagedPaths.has(filePath));
286
+ if (missing.length > 0) {
287
+ throw new PublishValidationError(
288
+ 'publish_required_file_missing',
289
+ `npm pack payload is missing required publish files: ${missing.join(', ')}`,
290
+ { missing },
291
+ );
292
+ }
293
+ }
294
+
295
+ async function defaultBuildProject({ projectRoot, env, stdout, stderr }) {
296
+ return runChildProcess(
297
+ process.execPath,
298
+ [CLI_ENTRY_PATH, 'build'],
299
+ {
300
+ cwd: projectRoot,
301
+ env,
302
+ stdout,
303
+ stderr,
304
+ failureReasonCode: 'publish_build_failed',
305
+ failureMessage: 'aura publish validation build failed',
306
+ },
307
+ );
308
+ }
309
+
310
+ async function defaultRunPackDryRun({ projectRoot, packRoot, env }) {
311
+ const pack = await runChildProcess(
312
+ resolveNpmCommand(),
313
+ ['pack', '--json', '--dry-run', '--ignore-scripts'],
314
+ {
315
+ cwd: packRoot || projectRoot,
316
+ env,
317
+ stdout: null,
318
+ stderr: null,
319
+ failureReasonCode: 'publish_pack_dry_run_failed',
320
+ failureMessage: 'aura publish pack dry-run failed',
321
+ },
322
+ );
323
+
324
+ let payload;
325
+ try {
326
+ payload = JSON.parse(pack.stdout || '[]');
327
+ } catch (error) {
328
+ throw new PublishValidationError(
329
+ 'publish_pack_json_invalid',
330
+ `Failed to parse npm pack --json output: ${error.message}`,
331
+ { stdout: pack.stdout },
332
+ );
333
+ }
334
+
335
+ if (!Array.isArray(payload) || payload.length === 0 || !payload[0]) {
336
+ throw new PublishValidationError(
337
+ 'publish_pack_json_invalid',
338
+ 'npm pack --json --dry-run returned no package payload.',
339
+ { payload },
340
+ );
341
+ }
342
+
343
+ return payload[0];
344
+ }
345
+
346
+ export async function validatePublishProject(
347
+ {
348
+ projectRoot = process.cwd(),
349
+ env = process.env,
350
+ stdout = process.stdout,
351
+ stderr = process.stderr,
352
+ buildProject = defaultBuildProject,
353
+ runPackDryRun = defaultRunPackDryRun,
354
+ } = {},
355
+ ) {
356
+ let packageSurface = null;
357
+ const report = createBaseReport({
358
+ projectRoot,
359
+ packageName: null,
360
+ packageVersion: null,
361
+ });
362
+
363
+ try {
364
+ const { packageName, packageVersion, projectPackage } = readProjectPackage(projectRoot);
365
+ report.package.name = packageName;
366
+ report.package.version = packageVersion;
367
+ report.package.scope = packageName.startsWith('@') ? 'scoped' : 'unscoped';
368
+ const config = await loadConfig({ projectRoot, mode: 'build' });
369
+ const binEntries = normalizeBinEntries(projectPackage, packageName);
370
+ const envExampleSurface = resolvePublishEnvExampleSurface({ projectRoot });
371
+ const requiredProjectFiles = [
372
+ 'README.md',
373
+ 'aura.config.json',
374
+ 'aura.capabilities.json',
375
+ 'src/main.js',
376
+ ...binEntries.map((entry) => entry.relativePath),
377
+ ];
378
+
379
+ report.validation.metadata = {
380
+ reasonCode: 'publish_metadata_ok',
381
+ bin: binEntries,
382
+ requiredProjectFiles,
383
+ publishConfig: projectPackage?.publishConfig || null,
384
+ environment: envExampleSurface.metadata,
385
+ };
386
+
387
+ for (const binEntry of binEntries) {
388
+ assertRequiredFileExists(
389
+ projectRoot,
390
+ binEntry.relativePath,
391
+ 'publish_bin_target_missing',
392
+ `aura publish requires bin target "${binEntry.relativePath}" to exist.`,
393
+ );
394
+ }
395
+ for (const requiredFile of requiredProjectFiles) {
396
+ assertRequiredFileExists(
397
+ projectRoot,
398
+ requiredFile,
399
+ 'publish_required_project_file_missing',
400
+ `aura publish requires "${requiredFile}" to exist before publishing.`,
401
+ );
402
+ }
403
+
404
+ const binIntegrity = assertProjectBinIntegrity({
405
+ projectRoot,
406
+ projectPackage,
407
+ packageName,
408
+ aurajsPackageRoot: DEFAULT_AURAJS_PACKAGE_ROOT,
409
+ expectedAurajsVersion: AURAJS_PACKAGE_VERSION,
410
+ enforceExactAurajsDependency: true,
411
+ });
412
+ report.validation.binIntegrity = {
413
+ reasonCode: 'publish_bin_integrity_ok',
414
+ ...binIntegrity,
415
+ };
416
+
417
+ stdout?.write('\n aura publish: validating project build contract...\n');
418
+ await buildProject({ projectRoot, env, stdout, stderr });
419
+
420
+ const buildTarget = currentPlatformTarget();
421
+ const buildRoot = resolve(projectRoot, config.build.outDir, buildTarget);
422
+ const buildManifestPath = resolve(buildRoot, 'build-manifest.json');
423
+ assertRequiredFileExists(
424
+ projectRoot,
425
+ join(config.build.outDir, buildTarget, 'build-manifest.json'),
426
+ 'publish_build_manifest_missing',
427
+ 'aura publish validation requires build-manifest.json to be emitted by aura build.',
428
+ );
429
+
430
+ let buildManifest;
431
+ try {
432
+ buildManifest = JSON.parse(readFileSync(buildManifestPath, 'utf8'));
433
+ } catch (error) {
434
+ throw new PublishValidationError(
435
+ 'publish_build_manifest_invalid',
436
+ `Failed to parse build manifest emitted during publish validation: ${error.message}`,
437
+ { buildManifestPath },
438
+ );
439
+ }
440
+
441
+ if (buildManifest.schema !== BUILD_MANIFEST_SCHEMA) {
442
+ throw new PublishValidationError(
443
+ 'publish_build_manifest_schema_invalid',
444
+ `Publish validation expected ${BUILD_MANIFEST_SCHEMA}, got ${buildManifest?.schema || '<missing>'}.`,
445
+ { buildManifestPath, schema: buildManifest?.schema || null },
446
+ );
447
+ }
448
+
449
+ const bundleRelativePath = String(buildManifest.entrypoint || '');
450
+ const assetsManifestRelativePath = String(buildManifest.assetsManifest || '');
451
+ if (!bundleRelativePath) {
452
+ throw new PublishValidationError(
453
+ 'publish_bundle_missing',
454
+ 'Publish validation build manifest is missing the bundled entrypoint path.',
455
+ { buildManifestPath },
456
+ );
457
+ }
458
+ if (!assetsManifestRelativePath) {
459
+ throw new PublishValidationError(
460
+ 'publish_assets_manifest_missing',
461
+ 'Publish validation build manifest is missing the assets manifest path.',
462
+ { buildManifestPath },
463
+ );
464
+ }
465
+
466
+ const bundlePath = resolve(buildRoot, bundleRelativePath);
467
+ const assetsManifestPath = resolve(buildRoot, assetsManifestRelativePath);
468
+ assertRequiredFileExists(
469
+ buildRoot,
470
+ bundleRelativePath,
471
+ 'publish_bundle_missing',
472
+ 'Publish validation could not find the built JS bundle referenced by build-manifest.json.',
473
+ );
474
+ assertRequiredFileExists(
475
+ buildRoot,
476
+ assetsManifestRelativePath,
477
+ 'publish_assets_manifest_missing',
478
+ 'Publish validation could not find the assets manifest referenced by build-manifest.json.',
479
+ );
480
+
481
+ let assetsManifest;
482
+ try {
483
+ assetsManifest = JSON.parse(readFileSync(assetsManifestPath, 'utf8'));
484
+ } catch (error) {
485
+ throw new PublishValidationError(
486
+ 'publish_assets_manifest_invalid',
487
+ `Failed to parse assets manifest emitted during publish validation: ${error.message}`,
488
+ { assetsManifestPath },
489
+ );
490
+ }
491
+
492
+ if (assetsManifest?.schema !== ASSET_MANIFEST_SCHEMA) {
493
+ throw new PublishValidationError(
494
+ 'publish_assets_manifest_schema_invalid',
495
+ `Publish validation expected ${ASSET_MANIFEST_SCHEMA}, got ${assetsManifest?.schema || '<missing>'}.`,
496
+ {
497
+ assetsManifestPath,
498
+ schema: assetsManifest?.schema || null,
499
+ },
500
+ );
501
+ }
502
+
503
+ if (config.identity?.icon) {
504
+ if (buildManifest.icon?.status !== 'copied') {
505
+ throw new PublishValidationError(
506
+ 'publish_icon_validation_failed',
507
+ 'Publish validation expected the configured identity.icon to be copied into build output.',
508
+ {
509
+ configuredIcon: config.identity.icon,
510
+ icon: buildManifest.icon || null,
511
+ },
512
+ );
513
+ }
514
+ }
515
+
516
+ report.validation.build = {
517
+ reasonCode: 'publish_build_ok',
518
+ buildTarget,
519
+ buildRoot,
520
+ buildManifestPath,
521
+ bundlePath,
522
+ assetsManifestPath,
523
+ identity: buildManifest.identity || null,
524
+ icon: buildManifest.icon || null,
525
+ };
526
+ const buildMetadata = {
527
+ buildTarget,
528
+ buildRoot,
529
+ identity: buildManifest.identity || null,
530
+ icon: buildManifest.icon || null,
531
+ };
532
+
533
+ let assetThresholdRecord;
534
+ try {
535
+ assetThresholdRecord = evaluateExternalAssetPolicy({
536
+ projectRoot,
537
+ buildRoot,
538
+ assetsManifestPath,
539
+ assetsManifest,
540
+ assetDir: config.build.assetDir,
541
+ env,
542
+ });
543
+ } catch (error) {
544
+ throw new PublishValidationError(
545
+ 'publish_asset_threshold_invalid',
546
+ error?.message || 'Assets manifest or publish threshold configuration is invalid.',
547
+ {},
548
+ );
549
+ }
550
+
551
+ try {
552
+ packageSurface = preparePublishPackageSurface({
553
+ projectRoot,
554
+ projectPackage,
555
+ assetDir: config.build.assetDir,
556
+ assetPolicy: assetThresholdRecord,
557
+ generatedFilePaths: PACKAGE_INTEGRITY_PUBLISH_FILES,
558
+ generatedFiles: envExampleSurface.generatedFiles,
559
+ excludedFilePaths: envExampleSurface.excludedFilePaths,
560
+ });
561
+ } catch (error) {
562
+ throw new PublishValidationError(
563
+ 'publish_external_assets_surface_invalid',
564
+ error?.message || 'Failed to stage the self-hosted external asset publish surface.',
565
+ {},
566
+ );
567
+ }
568
+
569
+ const packageIntegrity = writeSignedPackageIntegrityArtifacts({
570
+ packageRoot: packageSurface.publishRoot,
571
+ signerProjectRoot: projectRoot,
572
+ buildMetadata,
573
+ });
574
+ report.validation.packageIntegrity = {
575
+ reasonCode: 'publish_package_integrity_ok',
576
+ manifestPath: packageIntegrity.manifestPath,
577
+ signaturePath: packageIntegrity.signaturePath,
578
+ schema: packageIntegrity.schema,
579
+ fileCount: packageIntegrity.fileCount,
580
+ signerFingerprint: packageIntegrity.signerFingerprint,
581
+ publishedMetadata: packageIntegrity.publishedMetadata,
582
+ };
583
+
584
+ assetThresholdRecord.packageSurfaceMode = packageSurface.mode;
585
+ assetThresholdRecord.assetPackaging = packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE
586
+ ? 'self_hosted'
587
+ : 'embedded';
588
+ report.validation.assets = assetThresholdRecord;
589
+ if (assetThresholdRecord.blocked) {
590
+ throw new PublishValidationError(
591
+ 'publish_asset_threshold_exceeded',
592
+ `AuraJS asset payload is ${assetThresholdRecord.assetBytes} bytes, above the npm-first threshold of ${assetThresholdRecord.thresholdBytes} bytes. Self-host the heavy assets on a public HTTPS base URL (for example Cloudflare R2 or S3), generate the external asset config, then publish the slim package.`,
593
+ assetThresholdRecord,
594
+ );
595
+ }
596
+
597
+ const packEntry = await runPackDryRun({
598
+ projectRoot,
599
+ packRoot: packageSurface.publishRoot,
600
+ env,
601
+ });
602
+ const packFiles = normalizePackFiles(packEntry);
603
+ const packInspection = inspectPublishPackFiles(packFiles, {
604
+ assetDir: packageSurface.assetDir,
605
+ externalAssetsConfigPath: packageSurface.externalAssetsConfigPath,
606
+ });
607
+ const requiredPackFiles = [
608
+ 'package.json',
609
+ 'README.md',
610
+ 'aura.config.json',
611
+ 'aura.capabilities.json',
612
+ ...binEntries.map((entry) => entry.relativePath),
613
+ 'src/main.js',
614
+ ...(packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE
615
+ ? [packageSurface.externalAssetsConfigPath]
616
+ : []),
617
+ ...PACKAGE_INTEGRITY_PUBLISH_FILES,
618
+ ...(envExampleSurface.metadata.generatedExample ? [PUBLISH_ENV_EXAMPLE_PATH] : []),
619
+ ];
620
+ validatePackRequiredFiles(packFiles, requiredPackFiles);
621
+
622
+ if (packFiles.some((entry) => entry.path === PUBLISH_SOURCE_ENV_PATH)) {
623
+ throw new PublishValidationError(
624
+ 'publish_env_file_included',
625
+ '.env must not be included in the published npm package. AuraJS generates .env.example instead.',
626
+ {},
627
+ );
628
+ }
629
+
630
+ if (packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE && packInspection.includesAssetPayload) {
631
+ throw new PublishValidationError(
632
+ 'publish_external_assets_payload_included',
633
+ `Self-hosted external asset packages must omit ${packageSurface.assetDir}/ from the npm tarball.`,
634
+ {
635
+ assetDir: packageSurface.assetDir,
636
+ },
637
+ );
638
+ }
639
+
640
+ if (packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE && !packInspection.includesExternalAssetsConfig) {
641
+ throw new PublishValidationError(
642
+ 'publish_external_assets_config_missing_from_pack',
643
+ `${packageSurface.externalAssetsConfigPath} must be present in the slim npm tarball for self-hosted assets.`,
644
+ {
645
+ configPath: packageSurface.externalAssetsConfigPath,
646
+ },
647
+ );
648
+ }
649
+
650
+ report.validation.pack = {
651
+ reasonCode: 'publish_pack_dry_run_ok',
652
+ filename: typeof packEntry.filename === 'string' ? packEntry.filename : null,
653
+ size: Number.isFinite(packEntry.size) ? packEntry.size : null,
654
+ unpackedSize: Number.isFinite(packEntry.unpackedSize) ? packEntry.unpackedSize : null,
655
+ surfaceMode: packageSurface.mode,
656
+ assetDir: packageSurface.assetDir,
657
+ externalAssetsConfigPath: packageSurface.externalAssetsConfigPath,
658
+ assetPayloadIncluded: packInspection.includesAssetPayload,
659
+ externalAssetsConfigIncluded: packInspection.includesExternalAssetsConfig,
660
+ manifestIncluded: packFiles.some((entry) => entry.path === PACKAGE_INTEGRITY_MANIFEST_PATH),
661
+ signatureIncluded: packFiles.some((entry) => entry.path === PACKAGE_INTEGRITY_SIGNATURE_PATH),
662
+ envExampleIncluded: packFiles.some((entry) => entry.path === PUBLISH_ENV_EXAMPLE_PATH),
663
+ sourceEnvIncluded: packFiles.some((entry) => entry.path === PUBLISH_SOURCE_ENV_PATH),
664
+ files: packFiles,
665
+ };
666
+
667
+ report.summary = {
668
+ pass: true,
669
+ reasonCode: 'publish_validation_ok',
670
+ };
671
+
672
+ const reportPath = writePublishReport(projectRoot, report);
673
+ return {
674
+ ok: true,
675
+ packageName: report.package.name,
676
+ packageVersion: report.package.version,
677
+ report,
678
+ reportPath,
679
+ };
680
+ } catch (error) {
681
+ const normalized = error instanceof PublishValidationError
682
+ ? error
683
+ : new PublishValidationError(
684
+ typeof error?.reasonCode === 'string' && error.reasonCode.length > 0
685
+ ? error.reasonCode
686
+ : 'publish_validation_failed',
687
+ error?.message || 'Publish validation failed.',
688
+ error?.details && typeof error.details === 'object' ? error.details : {},
689
+ );
690
+
691
+ report.summary = {
692
+ pass: false,
693
+ reasonCode: normalized.reasonCode,
694
+ };
695
+ report.failure = {
696
+ reasonCode: normalized.reasonCode,
697
+ message: normalized.message,
698
+ details: normalized.details,
699
+ };
700
+
701
+ const reportPath = writePublishReport(projectRoot, report);
702
+ normalized.reportPath = reportPath;
703
+ normalized.report = report;
704
+ throw normalized;
705
+ } finally {
706
+ packageSurface?.cleanup?.();
707
+ }
708
+ }