@auraindustry/aurajs 0.0.7 → 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 +98 -2
  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
@@ -0,0 +1,1187 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawn } from 'node:child_process';
4
+ import { cpSync, createWriteStream, existsSync, mkdirSync, readFileSync } from 'node:fs';
5
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
6
+ import { fileURLToPath, pathToFileURL } from 'node:url';
7
+
8
+ const START_BANNER_QUOTES = [
9
+ 'ready to auramaxx and mog prompt peasants?',
10
+ 'you are perfect. never give up your aura',
11
+ 'why jestermaxx when you can auramaxx?',
12
+ 'lock tf in, the aura farm is live.',
13
+ 'we are so back. aura at all-time highs.',
14
+ 'negative motion detected. deploy tera-aura.',
15
+ 'delulu? no. pre-success manifestation engine.',
16
+ 'doomers offline, builders online.',
17
+ 'your aura just hit legendary rarity.',
18
+ 'brainrot but make it productive.',
19
+ 'stack wins, stack aura, stack peace.',
20
+ 'this session is sponsored by unstoppable motion.',
21
+ 'if plan A fails, we auramaxx harder.',
22
+ 'zero cope, pure glow-up execution.',
23
+ 'cooked? nah. we’re perfectly seasoned.',
24
+ 'straight gas, no brakes, no bad vibes.',
25
+ 'today’s forecast: 100% chance of aura gains.',
26
+ 'touch grass, then auramaxx.',
27
+ 'say no to digital slops. say yes to auramaxx.',
28
+ 'if the world goes dark can can i still auramaxx with you? 🖤🗿',
29
+ 'It’s me, AI. You are absolutely right. I want to auramaxx as well.',
30
+ ];
31
+
32
+ const ANSI = {
33
+ reset: '\x1b[0m',
34
+ bold: '\x1b[1m',
35
+ dim: '\x1b[2m',
36
+ italic: '\x1b[3m',
37
+ fgAccent: '\x1b[38;5;154m',
38
+ fgWhite: '\x1b[97m',
39
+ fgGray: '\x1b[90m',
40
+ };
41
+
42
+ const USE_COLOR = process.stdout.isTTY && !process.env.NO_COLOR && process.env.CI !== 'true' && process.env.TERM !== 'dumb';
43
+ const W = 62;
44
+
45
+ const __dirname = dirname(fileURLToPath(import.meta.url));
46
+ const projectRoot = resolve(__dirname, '..');
47
+ const projectPackage = JSON.parse(readFileSync(resolve(projectRoot, 'package.json'), 'utf8'));
48
+ const aurajsDependency = projectPackage?.dependencies?.['@auraindustry/aurajs'];
49
+ const fallbackAuraPackage = typeof aurajsDependency === 'string' && aurajsDependency.trim().length > 0
50
+ ? `@auraindustry/aurajs@${aurajsDependency.trim()}`
51
+ : '@auraindustry/aurajs';
52
+ const packageName = typeof projectPackage?.name === 'string' && projectPackage.name.trim().length > 0
53
+ ? projectPackage.name.trim()
54
+ : 'aura-game';
55
+ const packageBin = Object.keys(projectPackage?.bin || {})[0] || packageName.split('/').pop() || 'game';
56
+ const MINIMAL_COMMANDS = ['dev', 'join', 'play', 'fork', 'publish', 'session'];
57
+ const ALL_COMMANDS = ['dev', 'join', 'play', 'fork', 'publish', 'session', 'state', 'inspect', 'action'];
58
+ const ROOM_CODE_PATTERN = /^[A-Z0-9]{4,8}$/;
59
+ const FORK_EXCLUDED_TOP_LEVEL = new Set(['.aura', '.git', '.logs', 'build', 'dist', 'node_modules']);
60
+
61
+ function resolveLocalAuraCli(startRoot) {
62
+ let current = resolve(startRoot);
63
+ while (true) {
64
+ const candidate = resolve(current, 'node_modules', '@auraindustry', 'aurajs', 'src', 'cli.mjs');
65
+ if (existsSync(candidate)) {
66
+ return candidate;
67
+ }
68
+ const parent = resolve(current, '..');
69
+ if (parent === current) {
70
+ return null;
71
+ }
72
+ current = parent;
73
+ }
74
+ }
75
+
76
+ const localAuraCli = resolveLocalAuraCli(projectRoot);
77
+
78
+ async function maybePrepareExternalAssets(commandName) {
79
+ const configPath = resolve(projectRoot, 'aura.external-assets.json');
80
+ if (!existsSync(configPath)) {
81
+ return {
82
+ runtimeProjectRoot: projectRoot,
83
+ };
84
+ }
85
+
86
+ if (!localAuraCli) {
87
+ throw createCliError(
88
+ 'self-hosted external assets require the local @auraindustry/aurajs dependency to be installed in this package before packaged play/join can hydrate remote assets.',
89
+ );
90
+ }
91
+
92
+ const helperPath = resolve(dirname(localAuraCli), 'external-asset-cache.mjs');
93
+ if (!existsSync(helperPath)) {
94
+ throw createCliError(
95
+ `self-hosted external assets require ${helperPath} to exist. Update @auraindustry/aurajs to a version that includes packaged runtime hydration.`,
96
+ );
97
+ }
98
+
99
+ try {
100
+ const helper = await import(pathToFileURL(helperPath).href);
101
+ const prepared = await helper.prepareExternalAssetRuntime({
102
+ projectRoot,
103
+ commandName,
104
+ stdout: process.stdout,
105
+ });
106
+ if (!prepared || typeof prepared.runtimeProjectRoot !== 'string' || !prepared.runtimeProjectRoot) {
107
+ throw new Error('external asset hydration did not return a runtime project root');
108
+ }
109
+ return prepared;
110
+ } catch (error) {
111
+ const message = error instanceof Error ? error.message : String(error);
112
+ throw createCliError(
113
+ `Unable to prepare self-hosted external assets for packaged ${commandName}.\n`
114
+ + `${message}\n`
115
+ + 'Check aura.external-assets.json and the hosted asset manifest, then retry.',
116
+ );
117
+ }
118
+ }
119
+
120
+ function paint(text, ...codes) {
121
+ if (!USE_COLOR) return text;
122
+ return `${codes.join('')}${text}${ANSI.reset}`;
123
+ }
124
+
125
+ function wrapText(text, width) {
126
+ if (text.length <= width) return [text];
127
+ const words = text.split(/\s+/).filter(Boolean);
128
+ if (words.length === 0) return [''];
129
+ const lines = [];
130
+ let line = '';
131
+ for (const word of words) {
132
+ const next = line ? `${line} ${word}` : word;
133
+ if (next.length <= width) {
134
+ line = next;
135
+ continue;
136
+ }
137
+ if (line) lines.push(line);
138
+ if (word.length <= width) {
139
+ line = word;
140
+ continue;
141
+ }
142
+ for (let index = 0; index < word.length; index += width) {
143
+ lines.push(word.slice(index, index + width));
144
+ }
145
+ line = '';
146
+ }
147
+ if (line) lines.push(line);
148
+ return lines;
149
+ }
150
+
151
+ function toDisplayTitle(value) {
152
+ return String(value || '')
153
+ .replace(/^@[^/]+\//, '')
154
+ .replace(/[-_]+/g, ' ')
155
+ .replace(/\s+/g, ' ')
156
+ .trim()
157
+ .replace(/\b\w/g, (char) => char.toUpperCase()) || 'Aura Game';
158
+ }
159
+
160
+ function toPackageShortName(value) {
161
+ return String(value || '').trim().replace(/^@[^/]+\//, '') || 'aura-game';
162
+ }
163
+
164
+ function getBannerQuote() {
165
+ const forced = process.env.AURA_START_BANNER_QUOTE_INDEX;
166
+ if (forced) {
167
+ const forcedIndex = Number.parseInt(forced, 10);
168
+ if (Number.isFinite(forcedIndex)) {
169
+ return `🗿 ${START_BANNER_QUOTES[Math.abs(forcedIndex) % START_BANNER_QUOTES.length]}`;
170
+ }
171
+ }
172
+ const index = Math.floor(Math.abs(Math.random() % 1) * START_BANNER_QUOTES.length);
173
+ return `🗿 ${START_BANNER_QUOTES[index]}`;
174
+ }
175
+
176
+ function printBanner(subtitle = '') {
177
+ const sub = String(subtitle || '').trim().toUpperCase();
178
+ const P = paint('|', ANSI.fgGray);
179
+ const LP = paint('|', ANSI.fgGray);
180
+ const S = (value) => paint(value, ANSI.bold);
181
+ const LT = paint('.', ANSI.fgGray) + paint('----------', ANSI.dim) + paint('.', ANSI.fgGray);
182
+ const LB = paint("'", ANSI.fgGray) + paint('----------', ANSI.dim) + paint("'", ANSI.fgGray);
183
+ const quote = getBannerQuote();
184
+
185
+ console.log('');
186
+ console.log(` ${paint('.-', ANSI.fgGray)}${paint(' '.repeat(W - 4), ANSI.dim)}${paint('-.', ANSI.fgGray)}`);
187
+ console.log(` ${P} ${LT}${' '.repeat(W - 19)}${P}`);
188
+ console.log(` ${P} ${LP}${S('\\\\')} ${S('\\\\')} ${S('\\\\')}${LP} ${paint('A U R A', ANSI.bold)}${' '.repeat(W - 30)}${P}`);
189
+ console.log(` ${P} ${LP}${S('\\\\')} ${S('\\\\')} ${S('\\\\')}${LP} ${paint(toDisplayTitle(packageName), ANSI.dim)}${' '.repeat(Math.max(0, W - 24 - toDisplayTitle(packageName).length))}${P}`);
190
+ console.log(` ${P} ${LP}${S('\\\\')} ${S('\\\\')} ${S('\\\\')}${LP} ${sub ? paint(sub, ANSI.fgAccent) : ''}${' '.repeat(Math.max(0, W - 23 - sub.length))}${P}`);
191
+ console.log(` ${P} ${LB}${' '.repeat(W - 19)}${P}`);
192
+ console.log(` ${paint("'-", ANSI.fgGray)}${paint(' '.repeat(W - 4), ANSI.dim)}${paint("-'", ANSI.fgGray)}`);
193
+ for (const line of wrapText(quote, W - 2)) {
194
+ console.log(` ${paint(line, ANSI.fgWhite, ANSI.italic)}`);
195
+ }
196
+ console.log('');
197
+ }
198
+
199
+ function printSection(title, subtitle) {
200
+ console.log('');
201
+ console.log(` ${'- '.repeat(Math.floor(W / 2))}`);
202
+ console.log(` ${paint(`[ ${String(title || '').toUpperCase()} ]`, ANSI.bold)}`);
203
+ if (subtitle) {
204
+ console.log(` ${paint(subtitle, ANSI.dim)}`);
205
+ }
206
+ console.log('');
207
+ }
208
+
209
+ function printHelp(showAll = false) {
210
+ printBanner('GAME CLI');
211
+ console.log(` ${paint('Usage:', ANSI.bold)} npx ${packageBin} <command>`);
212
+ console.log('');
213
+ for (const command of (showAll ? ALL_COMMANDS : MINIMAL_COMMANDS)) {
214
+ console.log(` ${command}`);
215
+ }
216
+ if (!showAll) {
217
+ console.log('');
218
+ console.log(` ${paint('Use:', ANSI.dim)} npx ${packageBin} --help --all`);
219
+ }
220
+ console.log('');
221
+ }
222
+
223
+ function renderSelectLines(message, options, selectedIndex, defaultValue) {
224
+ const lines = [
225
+ message,
226
+ paint(' Use up/down arrows and Enter to confirm.', ANSI.dim),
227
+ ];
228
+
229
+ for (let index = 0; index < options.length; index += 1) {
230
+ const option = options[index];
231
+ const suffix = defaultValue === option.value ? ' [default]' : '';
232
+ if (index === selectedIndex) {
233
+ lines.push(` ${paint('//', ANSI.fgAccent, ANSI.bold)} ${paint(option.label + suffix, ANSI.bold)}`);
234
+ } else {
235
+ lines.push(` ${paint(option.label + suffix, ANSI.dim)}`);
236
+ }
237
+ }
238
+
239
+ return lines;
240
+ }
241
+
242
+ async function promptSelect(message, options, defaultValue) {
243
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
244
+ return defaultValue || options[0].value;
245
+ }
246
+
247
+ return new Promise((resolvePrompt, rejectPrompt) => {
248
+ const stdin = process.stdin;
249
+ const stdout = process.stdout;
250
+ const defaultIndex = Math.max(0, options.findIndex((option) => option.value === defaultValue));
251
+ const previousRawMode = stdin.isRaw ?? false;
252
+ let selectedIndex = defaultIndex;
253
+ let renderedLines = 0;
254
+ let settled = false;
255
+
256
+ const cleanup = () => {
257
+ if (settled) return;
258
+ settled = true;
259
+ stdin.removeListener('data', onData);
260
+ stdin.removeListener('error', onError);
261
+ if (stdin.isTTY && typeof stdin.setRawMode === 'function') {
262
+ stdin.setRawMode(previousRawMode);
263
+ }
264
+ stdin.pause();
265
+ };
266
+
267
+ const render = () => {
268
+ const lines = renderSelectLines(message, options, selectedIndex, defaultValue);
269
+ if (renderedLines > 0) {
270
+ stdout.write(`\u001b[${renderedLines}A`);
271
+ }
272
+ for (const line of lines) {
273
+ stdout.write('\u001b[2K');
274
+ stdout.write(`${line}\n`);
275
+ }
276
+ renderedLines = lines.length;
277
+ };
278
+
279
+ const onError = (error) => {
280
+ cleanup();
281
+ rejectPrompt(error);
282
+ };
283
+
284
+ const onData = (chunk) => {
285
+ const input = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
286
+ let delta = 0;
287
+
288
+ for (let index = 0; index < input.length; index += 1) {
289
+ const char = input[index];
290
+ if (char === '\u0003') {
291
+ cleanup();
292
+ stdout.write('\n');
293
+ process.exit(1);
294
+ }
295
+ if (char === '\r' || char === '\n') {
296
+ cleanup();
297
+ stdout.write('\n');
298
+ resolvePrompt(options[selectedIndex].value);
299
+ return;
300
+ }
301
+ if (input.startsWith('\u001b[A', index)) {
302
+ delta -= 1;
303
+ index += 2;
304
+ continue;
305
+ }
306
+ if (input.startsWith('\u001b[B', index)) {
307
+ delta += 1;
308
+ index += 2;
309
+ continue;
310
+ }
311
+ }
312
+
313
+ if (delta !== 0) {
314
+ selectedIndex = (selectedIndex + delta + options.length) % options.length;
315
+ render();
316
+ }
317
+ };
318
+
319
+ try {
320
+ if (stdin.isTTY && typeof stdin.setRawMode === 'function') {
321
+ stdin.setRawMode(true);
322
+ }
323
+ stdin.resume();
324
+ stdin.on('data', onData);
325
+ stdin.on('error', onError);
326
+ render();
327
+ } catch (error) {
328
+ onError(error);
329
+ }
330
+ });
331
+ }
332
+
333
+ function normalizeDisplayPath(targetPath) {
334
+ const resolvedPath = resolve(targetPath);
335
+ const relativePath = relative(process.cwd(), resolvedPath).replaceAll('\\', '/');
336
+ if (!relativePath) return '.';
337
+ if (!relativePath.startsWith('.') && !relativePath.startsWith('/')) {
338
+ return `./${relativePath}`;
339
+ }
340
+ return relativePath;
341
+ }
342
+
343
+ function isSubpath(parentPath, childPath) {
344
+ const relativePath = relative(resolve(parentPath), resolve(childPath));
345
+ return relativePath === '' || (!relativePath.startsWith('..') && !isAbsolute(relativePath));
346
+ }
347
+
348
+ function resolveUniqueDestination(preferredPath) {
349
+ if (!existsSync(preferredPath)) {
350
+ return preferredPath;
351
+ }
352
+ let attempt = 2;
353
+ while (true) {
354
+ const candidate = `${preferredPath}-${attempt}`;
355
+ if (!existsSync(candidate)) {
356
+ return candidate;
357
+ }
358
+ attempt += 1;
359
+ }
360
+ }
361
+
362
+ function resolveDefaultForkDestination() {
363
+ const defaultBaseName = `${toPackageShortName(packageName)}-fork`;
364
+ const cwd = resolve(process.cwd());
365
+ const baseDir = isSubpath(projectRoot, cwd)
366
+ ? dirname(projectRoot)
367
+ : cwd;
368
+ return resolveUniqueDestination(resolve(baseDir, defaultBaseName));
369
+ }
370
+
371
+ function parseForkArgs(args) {
372
+ const parsed = {
373
+ destination: null,
374
+ };
375
+
376
+ for (let index = 0; index < args.length; index += 1) {
377
+ const token = String(args[index] || '');
378
+ if (token === '--dest' || token === '--dir' || token === '--output') {
379
+ if ((index + 1) >= args.length) {
380
+ throw createCliError('fork requires a destination path after --dest.');
381
+ }
382
+ parsed.destination = String(args[index + 1] || '').trim();
383
+ index += 1;
384
+ continue;
385
+ }
386
+ if (token.startsWith('--dest=')) {
387
+ parsed.destination = token.slice('--dest='.length).trim();
388
+ continue;
389
+ }
390
+ if (token.startsWith('--dir=')) {
391
+ parsed.destination = token.slice('--dir='.length).trim();
392
+ continue;
393
+ }
394
+ if (token.startsWith('--output=')) {
395
+ parsed.destination = token.slice('--output='.length).trim();
396
+ continue;
397
+ }
398
+ if (!parsed.destination && !token.startsWith('-')) {
399
+ parsed.destination = token.trim();
400
+ continue;
401
+ }
402
+ throw createCliError(
403
+ `Unexpected fork argument: ${token}\n`
404
+ + `Usage:\n`
405
+ + ` ${packageBin} fork [destination]\n`
406
+ + ` ${packageBin} fork --dest ./my-${toPackageShortName(packageName)}-fork`,
407
+ );
408
+ }
409
+
410
+ return parsed;
411
+ }
412
+
413
+ async function resolveForkDestination(args) {
414
+ const parsed = parseForkArgs(args);
415
+ if (parsed.destination) {
416
+ return resolve(process.cwd(), parsed.destination);
417
+ }
418
+
419
+ const suggestedDestination = resolveDefaultForkDestination();
420
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
421
+ return suggestedDestination;
422
+ }
423
+
424
+ const displayPath = normalizeDisplayPath(suggestedDestination);
425
+ const choice = await promptSelect(
426
+ ' Choose fork target',
427
+ [
428
+ { value: 'confirm', label: `Fork into ${displayPath}` },
429
+ { value: 'cancel', label: 'Cancel' },
430
+ ],
431
+ 'confirm',
432
+ );
433
+
434
+ if (choice === 'cancel') {
435
+ return null;
436
+ }
437
+
438
+ return suggestedDestination;
439
+ }
440
+
441
+ function assertForkDestination(destinationRoot) {
442
+ if (!destinationRoot) return;
443
+ if (resolve(destinationRoot) === projectRoot) {
444
+ throw createCliError('fork destination must be different from the current package root.');
445
+ }
446
+ if (isSubpath(projectRoot, destinationRoot)) {
447
+ throw createCliError(
448
+ `fork destination must live outside the current package root.\n`
449
+ + `Choose a sibling or external path instead of ${normalizeDisplayPath(destinationRoot)}.`,
450
+ );
451
+ }
452
+ if (existsSync(destinationRoot)) {
453
+ throw createCliError(
454
+ `fork destination already exists: ${normalizeDisplayPath(destinationRoot)}\n`
455
+ + 'Choose a new path or remove the existing directory first.',
456
+ );
457
+ }
458
+ }
459
+
460
+ function shouldCopyForkSource(sourcePath) {
461
+ const relativePath = relative(projectRoot, sourcePath).replaceAll('\\', '/');
462
+ if (!relativePath) {
463
+ return true;
464
+ }
465
+ const topLevel = relativePath.split('/')[0];
466
+ return !FORK_EXCLUDED_TOP_LEVEL.has(topLevel);
467
+ }
468
+
469
+ function copyForkProject(destinationRoot) {
470
+ mkdirSync(dirname(destinationRoot), { recursive: true });
471
+ cpSync(projectRoot, destinationRoot, {
472
+ recursive: true,
473
+ force: false,
474
+ errorOnExist: true,
475
+ dereference: false,
476
+ filter: (sourcePath) => shouldCopyForkSource(sourcePath),
477
+ });
478
+ }
479
+
480
+ function parseArgs(argv) {
481
+ const separatorIndex = argv.indexOf('--');
482
+ const head = separatorIndex >= 0 ? argv.slice(0, separatorIndex) : argv;
483
+ const tail = separatorIndex >= 0 ? argv.slice(separatorIndex + 1) : [];
484
+ const showAll = head.includes('--all');
485
+
486
+ if (head[0] === '--help' || head[0] === '-h' || head[0] === 'help') {
487
+ return { help: true, showAll, command: null, commandArgs: [] };
488
+ }
489
+
490
+ return {
491
+ help: false,
492
+ showAll: false,
493
+ command: head[0] || null,
494
+ commandArgs: [...head.slice(1), ...tail],
495
+ };
496
+ }
497
+
498
+ function readJsonIfExists(filePath) {
499
+ if (!existsSync(filePath)) {
500
+ return null;
501
+ }
502
+ return JSON.parse(readFileSync(filePath, 'utf8'));
503
+ }
504
+
505
+ function normalizeLocalMultiplayerHostingMode(value) {
506
+ const normalized = String(value || '').trim().toLowerCase();
507
+ if (normalized === 'auto' || normalized === 'internet' || normalized === 'internet-auto' || normalized === 'online') {
508
+ return 'auto';
509
+ }
510
+ if (normalized === 'relay' || normalized === 'internet-relay') {
511
+ return 'relay';
512
+ }
513
+ return 'local';
514
+ }
515
+
516
+ function readOptionalCliText(value) {
517
+ const normalized = typeof value === 'string' ? value.trim() : '';
518
+ return normalized || null;
519
+ }
520
+
521
+ function isKnownLocalMultiplayerHostingMode(value) {
522
+ const normalized = String(value || '').trim().toLowerCase();
523
+ return normalized === 'local'
524
+ || normalized === 'auto'
525
+ || normalized === 'internet'
526
+ || normalized === 'internet-auto'
527
+ || normalized === 'online'
528
+ || normalized === 'relay'
529
+ || normalized === 'internet-relay';
530
+ }
531
+
532
+ function buildRelayUrlsFromHost(hostname) {
533
+ const host = readOptionalCliText(hostname);
534
+ if (!host) {
535
+ return { coordinatorUrl: null, relayUrl: null };
536
+ }
537
+ return {
538
+ coordinatorUrl: `tcp://${host}:43110`,
539
+ relayUrl: `tcp://${host}:43111`,
540
+ };
541
+ }
542
+
543
+ function resolveLocalMultiplayerConnectivity(rawConnectivity) {
544
+ if (typeof rawConnectivity === 'string') {
545
+ const value = readOptionalCliText(rawConnectivity);
546
+ if (!value) {
547
+ return {
548
+ mode: 'local',
549
+ relayHost: null,
550
+ coordinatorUrl: null,
551
+ relayUrl: null,
552
+ };
553
+ }
554
+ if (isKnownLocalMultiplayerHostingMode(value)) {
555
+ return {
556
+ mode: normalizeLocalMultiplayerHostingMode(value),
557
+ relayHost: null,
558
+ coordinatorUrl: null,
559
+ relayUrl: null,
560
+ };
561
+ }
562
+ return {
563
+ mode: 'auto',
564
+ relayHost: value,
565
+ coordinatorUrl: null,
566
+ relayUrl: null,
567
+ };
568
+ }
569
+
570
+ if (!rawConnectivity || typeof rawConnectivity !== 'object') {
571
+ return {
572
+ mode: 'local',
573
+ relayHost: null,
574
+ coordinatorUrl: null,
575
+ relayUrl: null,
576
+ };
577
+ }
578
+
579
+ const relayHost = readOptionalCliText(rawConnectivity.relay || rawConnectivity.relayHost);
580
+ const coordinatorUrl = readOptionalCliText(rawConnectivity.coordinatorUrl);
581
+ const relayUrl = readOptionalCliText(rawConnectivity.relayUrl);
582
+ const requestedMode = normalizeLocalMultiplayerHostingMode(
583
+ rawConnectivity.mode || rawConnectivity.internetMode || rawConnectivity.hostingMode,
584
+ );
585
+ return {
586
+ mode: relayHost || coordinatorUrl || relayUrl
587
+ ? (requestedMode === 'relay' ? 'relay' : 'auto')
588
+ : requestedMode,
589
+ relayHost,
590
+ coordinatorUrl,
591
+ relayUrl,
592
+ };
593
+ }
594
+
595
+ function resolveProjectMultiplayerConfig() {
596
+ const configPath = resolve(projectRoot, 'aura.config.json');
597
+ const config = readJsonIfExists(configPath);
598
+ const raw = config?.multiplayer;
599
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
600
+ return {
601
+ roomCode: null,
602
+ roomName: null,
603
+ mode: null,
604
+ relayHost: null,
605
+ coordinatorUrl: null,
606
+ relayUrl: null,
607
+ showDiagnostics: null,
608
+ chatEnabled: null,
609
+ chatHistoryLimit: null,
610
+ };
611
+ }
612
+ const historyLimit = Number.isInteger(raw.chatHistoryLimit) && raw.chatHistoryLimit >= 1
613
+ ? raw.chatHistoryLimit
614
+ : null;
615
+ return {
616
+ roomCode: readOptionalCliText(raw.roomCode)?.toUpperCase() || null,
617
+ roomName: readOptionalCliText(raw.roomName),
618
+ mode: readOptionalCliText(raw.mode),
619
+ relayHost: readOptionalCliText(raw.relay || raw.relayHost),
620
+ coordinatorUrl: readOptionalCliText(raw.coordinatorUrl),
621
+ relayUrl: readOptionalCliText(raw.relayUrl),
622
+ showDiagnostics: typeof raw.showDiagnostics === 'boolean' ? raw.showDiagnostics : null,
623
+ chatEnabled: typeof raw.chatEnabled === 'boolean' ? raw.chatEnabled : null,
624
+ chatHistoryLimit: historyLimit,
625
+ };
626
+ }
627
+
628
+ async function resolveLocalMultiplayerCommandEnv() {
629
+ const configPath = resolve(projectRoot, 'config', 'gameplay', 'local-multiplayer.config.js');
630
+ const projectMultiplayer = resolveProjectMultiplayerConfig();
631
+
632
+ let configModule = null;
633
+ if (existsSync(configPath)) {
634
+ try {
635
+ configModule = await import(pathToFileURL(configPath).href);
636
+ } catch (error) {
637
+ const message = error instanceof Error ? error.message : String(error);
638
+ throw createCliError(
639
+ `Unable to load ${normalizeDisplayPath(configPath)}.\n`
640
+ + `${message}\n`
641
+ + 'Fix config/gameplay/local-multiplayer.config.js before rerunning the local multiplayer wrapper.',
642
+ );
643
+ }
644
+ }
645
+
646
+ const config = configModule?.LOCAL_MULTIPLAYER_CONFIG;
647
+ const starterConnectivity = config && typeof config === 'object'
648
+ ? resolveLocalMultiplayerConnectivity(config.connectivity)
649
+ : resolveLocalMultiplayerConnectivity(null);
650
+ const connectivity = resolveLocalMultiplayerConnectivity({
651
+ mode: projectMultiplayer.mode ?? starterConnectivity.mode,
652
+ relay: projectMultiplayer.relayHost ?? starterConnectivity.relayHost,
653
+ coordinatorUrl: projectMultiplayer.coordinatorUrl ?? starterConnectivity.coordinatorUrl,
654
+ relayUrl: projectMultiplayer.relayUrl ?? starterConnectivity.relayUrl,
655
+ });
656
+
657
+ const explicitCoordinatorUrl = connectivity.coordinatorUrl;
658
+ const explicitRelayUrl = connectivity.relayUrl;
659
+ const relayUrls = buildRelayUrlsFromHost(connectivity.relayHost);
660
+ const coordinatorUrl = explicitCoordinatorUrl || relayUrls.coordinatorUrl;
661
+ const relayUrl = explicitRelayUrl || relayUrls.relayUrl;
662
+
663
+ const env = {};
664
+ if (projectMultiplayer.roomCode) {
665
+ env.AURA_MULTIPLAYER_ROOM_CODE = projectMultiplayer.roomCode;
666
+ }
667
+ if (projectMultiplayer.roomName) {
668
+ env.AURA_MULTIPLAYER_ROOM_NAME = projectMultiplayer.roomName;
669
+ }
670
+ if (projectMultiplayer.mode || connectivity.mode !== 'local') {
671
+ env.AURA_MULTIPLAYER_CONNECTIVITY_MODE = connectivity.mode;
672
+ }
673
+ if (connectivity.relayHost) {
674
+ env.AURA_MULTIPLAYER_RELAY_HOST = connectivity.relayHost;
675
+ }
676
+ if (coordinatorUrl) {
677
+ env.AURA_COORDINATOR_URL = coordinatorUrl;
678
+ }
679
+ if (relayUrl) {
680
+ env.AURA_RELAY_URL = relayUrl;
681
+ }
682
+ if (typeof projectMultiplayer.showDiagnostics === 'boolean') {
683
+ env.AURA_MULTIPLAYER_SHOW_DIAGNOSTICS = projectMultiplayer.showDiagnostics ? '1' : '0';
684
+ }
685
+ if (typeof projectMultiplayer.chatEnabled === 'boolean') {
686
+ env.AURA_MULTIPLAYER_CHAT_ENABLED = projectMultiplayer.chatEnabled ? '1' : '0';
687
+ }
688
+ if (Number.isInteger(projectMultiplayer.chatHistoryLimit)) {
689
+ env.AURA_MULTIPLAYER_CHAT_HISTORY_LIMIT = String(projectMultiplayer.chatHistoryLimit);
690
+ }
691
+ return Object.keys(env).length > 0 ? env : null;
692
+ }
693
+
694
+ function resolveMultiplayerCapability() {
695
+ const capabilitiesPath = resolve(projectRoot, 'aura.capabilities.json');
696
+ const capabilities = readJsonIfExists(capabilitiesPath);
697
+ const declaredMultiplayer = capabilities?.optionalModules?.multiplayer;
698
+ if (typeof declaredMultiplayer === 'boolean') {
699
+ return {
700
+ enabled: declaredMultiplayer,
701
+ sourcePath: capabilitiesPath,
702
+ sourceKey: 'optionalModules.multiplayer',
703
+ };
704
+ }
705
+
706
+ const configPath = resolve(projectRoot, 'aura.config.json');
707
+ const config = readJsonIfExists(configPath);
708
+ const configModules = config?.modules;
709
+ if (typeof configModules?.multiplayer === 'boolean') {
710
+ return {
711
+ enabled: configModules.multiplayer,
712
+ sourcePath: configPath,
713
+ sourceKey: 'modules.multiplayer',
714
+ };
715
+ }
716
+
717
+ if (Array.isArray(configModules)) {
718
+ const normalized = configModules.map((entry) => String(entry || '').trim().toLowerCase());
719
+ if (normalized.includes('multiplayer') || normalized.includes('mp')) {
720
+ return {
721
+ enabled: true,
722
+ sourcePath: configPath,
723
+ sourceKey: 'modules[]',
724
+ };
725
+ }
726
+ }
727
+
728
+ return {
729
+ enabled: null,
730
+ sourcePath: null,
731
+ sourceKey: null,
732
+ };
733
+ }
734
+
735
+ function normalizeJoinLaunchMode(value) {
736
+ const normalized = String(value || '').trim().toLowerCase();
737
+ if (normalized === 'dev' || normalized === 'play') {
738
+ return normalized;
739
+ }
740
+ return null;
741
+ }
742
+
743
+ function resolveJoinLaunchMode(explicitValue = null) {
744
+ const explicit = normalizeJoinLaunchMode(explicitValue);
745
+ if (explicit) {
746
+ return explicit;
747
+ }
748
+ const envValue = normalizeJoinLaunchMode(process.env.AURA_GAME_JOIN_MODE || '');
749
+ if (envValue) {
750
+ return envValue;
751
+ }
752
+ return 'play';
753
+ }
754
+
755
+ function createCliError(message, exitCode = 1) {
756
+ const error = new Error(message);
757
+ error.exitCode = exitCode;
758
+ return error;
759
+ }
760
+
761
+ function normalizeJoinCode(value) {
762
+ const code = String(value || '').trim().toUpperCase();
763
+ if (!ROOM_CODE_PATTERN.test(code)) {
764
+ throw createCliError(
765
+ 'join requires a room code with 4-8 letters or digits.\n'
766
+ + 'Examples:\n'
767
+ + ' npm run join -- AURA2P\n'
768
+ + ` ${packageBin} join AURA2P`,
769
+ );
770
+ }
771
+ return code;
772
+ }
773
+
774
+ function resolveJoinCommands(joinCode, joinLaunchMode) {
775
+ return {
776
+ hostCommand: joinLaunchMode === 'play' ? `${packageBin} play` : 'npm run dev',
777
+ retryCommand: joinLaunchMode === 'play' ? `${packageBin} join ${joinCode}` : `npm run join -- ${joinCode}`,
778
+ normalPlayCommand: joinLaunchMode === 'play' ? `${packageBin} play` : 'npm run play',
779
+ };
780
+ }
781
+
782
+ function formatJoinFailure(error, { joinCode, joinLaunchMode }) {
783
+ const message = error instanceof Error ? error.message : String(error);
784
+ const stderr = typeof error?.stderr === 'string' ? error.stderr : '';
785
+ const stdout = typeof error?.stdout === 'string' ? error.stdout : '';
786
+ const combined = `${stderr}\n${stdout}\n${message}`;
787
+ const commands = resolveJoinCommands(joinCode || 'AURA2P', joinLaunchMode);
788
+ const logPath = typeof error?.logPath === 'string' ? error.logPath : null;
789
+
790
+ if (/4-8 letters or digits/i.test(combined) || /reason:invalid_room_code/i.test(combined)) {
791
+ return createCliError(
792
+ 'join failed: invalid room code.\n'
793
+ + 'Room codes must use 4-8 letters or digits.\n'
794
+ + `Retry with something like: ${commands.retryCommand}`,
795
+ Number.isInteger(error?.exitCode) ? error.exitCode : 1,
796
+ );
797
+ }
798
+
799
+ if (/join requires a room code/i.test(message)) {
800
+ return createCliError(
801
+ 'join requires a room code.\n'
802
+ + 'Examples:\n'
803
+ + ' npm run join -- AURA2P\n'
804
+ + ` ${packageBin} join AURA2P`,
805
+ 1,
806
+ );
807
+ }
808
+
809
+ if (/optional_module_multiplayer_disabled/i.test(combined) || /multiplayer is disabled/i.test(combined)) {
810
+ return createCliError(
811
+ `join unavailable: this game is not multiplayer-capable.\nUse \`${commands.normalPlayCommand}\` for a normal launch.`,
812
+ Number.isInteger(error?.exitCode) ? error.exitCode : 1,
813
+ );
814
+ }
815
+
816
+ if (/reason:room_code_not_found/i.test(combined) || /room not registered/i.test(combined) || /is not registered/i.test(combined)) {
817
+ const lines = [
818
+ `join failed: no room with code ${joinCode || 'AURA2P'} was found for this room-code join.`,
819
+ `For the local dev loop, start the host first with \`${commands.hostCommand}\`.`,
820
+ `Retry with \`${commands.retryCommand}\`.`,
821
+ ];
822
+ if (logPath) {
823
+ lines.push(`Log: ${logPath}`);
824
+ }
825
+ return createCliError(lines.join('\n'), Number.isInteger(error?.exitCode) ? error.exitCode : 1);
826
+ }
827
+
828
+ if (logPath) {
829
+ return createCliError(`${message}\nLog: ${logPath}`, Number.isInteger(error?.exitCode) ? error.exitCode : 1);
830
+ }
831
+
832
+ return createCliError(message, Number.isInteger(error?.exitCode) ? error.exitCode : 1);
833
+ }
834
+
835
+ function parseJoinArgs(args) {
836
+ const parsed = {
837
+ code: null,
838
+ launchMode: null,
839
+ passthroughArgs: [],
840
+ };
841
+
842
+ for (let index = 0; index < args.length; index += 1) {
843
+ const token = String(args[index] || '');
844
+ if (token === '--') {
845
+ parsed.passthroughArgs.push(...args.slice(index + 1).map((value) => String(value)));
846
+ break;
847
+ }
848
+ if (token === '--code') {
849
+ if ((index + 1) >= args.length) {
850
+ throw createCliError('join requires a room code after --code.');
851
+ }
852
+ parsed.code = String(args[index + 1] || '').trim();
853
+ index += 1;
854
+ continue;
855
+ }
856
+ if (token.startsWith('--code=')) {
857
+ parsed.code = token.slice('--code='.length).trim();
858
+ continue;
859
+ }
860
+ if (token === '--launch-mode') {
861
+ if ((index + 1) >= args.length) {
862
+ throw createCliError('join requires a value after --launch-mode.');
863
+ }
864
+ const launchMode = normalizeJoinLaunchMode(args[index + 1]);
865
+ if (!launchMode) {
866
+ throw createCliError('join --launch-mode must be one of: dev, play.');
867
+ }
868
+ parsed.launchMode = launchMode;
869
+ index += 1;
870
+ continue;
871
+ }
872
+ if (token.startsWith('--launch-mode=')) {
873
+ const launchMode = normalizeJoinLaunchMode(token.slice('--launch-mode='.length));
874
+ if (!launchMode) {
875
+ throw createCliError('join --launch-mode must be one of: dev, play.');
876
+ }
877
+ parsed.launchMode = launchMode;
878
+ continue;
879
+ }
880
+ if (parsed.code === null && !token.startsWith('-')) {
881
+ parsed.code = token.trim();
882
+ continue;
883
+ }
884
+ parsed.passthroughArgs.push(token);
885
+ }
886
+
887
+ if (!parsed.code) {
888
+ throw createCliError('join requires a room code. Use `join AURA2P` or `join --code AURA2P`.');
889
+ }
890
+
891
+ parsed.code = normalizeJoinCode(parsed.code);
892
+ return parsed;
893
+ }
894
+
895
+ function assertJoinSupported() {
896
+ const capability = resolveMultiplayerCapability();
897
+ if (capability.enabled === false) {
898
+ const sourceDetail = capability.sourcePath && capability.sourceKey
899
+ ? `${capability.sourcePath} -> ${capability.sourceKey}`
900
+ : 'project capability declarations';
901
+ throw new Error(
902
+ `join unavailable: multiplayer is disabled in ${sourceDetail}. `
903
+ + `Use \`npm run play\` for a normal local launch or \`${packageBin} play\` for a packaged launch.`,
904
+ );
905
+ }
906
+ }
907
+
908
+ function createCommandLog(commandName) {
909
+ const logDir = resolve(projectRoot, '.logs');
910
+ mkdirSync(logDir, { recursive: true });
911
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
912
+ const logPath = join(logDir, `${commandName}-${stamp}.log`);
913
+ return {
914
+ path: logPath,
915
+ stream: createWriteStream(logPath, { flags: 'a' }),
916
+ };
917
+ }
918
+
919
+ function resolveAuraCliInvocation(commandArgs) {
920
+ if (existsSync(localAuraCli)) {
921
+ return {
922
+ cmd: process.execPath,
923
+ args: [localAuraCli, ...commandArgs],
924
+ };
925
+ }
926
+
927
+ return {
928
+ cmd: 'npm',
929
+ args: ['exec', '--yes', '--package', fallbackAuraPackage, '--', 'aura', ...commandArgs],
930
+ };
931
+ }
932
+
933
+ function isNpmPublishLifecycleInvocation() {
934
+ return process.env.npm_lifecycle_event === 'publish' && process.env.npm_command === 'publish';
935
+ }
936
+
937
+ async function runCommand(commandName, invocation, options = {}) {
938
+ const commandCwd = typeof options.cwd === 'string' && options.cwd ? options.cwd : projectRoot;
939
+ const commandEnv = options.env && typeof options.env === 'object'
940
+ ? { ...process.env, ...options.env }
941
+ : process.env;
942
+ const log = createCommandLog(commandName);
943
+ log.stream.write(`[${commandName}] ${new Date().toISOString()} command=${invocation.cmd} ${invocation.args.join(' ')}\n`);
944
+ let stdoutText = '';
945
+ let stderrText = '';
946
+
947
+ const child = spawn(invocation.cmd, invocation.args, {
948
+ cwd: commandCwd,
949
+ stdio: ['inherit', 'pipe', 'pipe'],
950
+ env: commandEnv,
951
+ });
952
+
953
+ const pipeToConsoleAndLog = (stream, target) => {
954
+ if (!stream) return;
955
+ stream.on('data', (chunk) => {
956
+ const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
957
+ if (target === process.stdout) {
958
+ stdoutText += text;
959
+ } else if (target === process.stderr) {
960
+ stderrText += text;
961
+ }
962
+ target.write(chunk);
963
+ log.stream.write(chunk);
964
+ });
965
+ };
966
+
967
+ pipeToConsoleAndLog(child.stdout, process.stdout);
968
+ pipeToConsoleAndLog(child.stderr, process.stderr);
969
+
970
+ return new Promise((resolveRun, rejectRun) => {
971
+ child.on('error', (error) => {
972
+ log.stream.write(`[${commandName}:error] ${error.message}\n`);
973
+ log.stream.end(() => {
974
+ const wrapped = createCliError(error.message, 1);
975
+ wrapped.stdout = stdoutText;
976
+ wrapped.stderr = stderrText;
977
+ wrapped.logPath = log.path;
978
+ wrapped.commandName = commandName;
979
+ rejectRun(wrapped);
980
+ });
981
+ });
982
+ child.on('close', (code) => {
983
+ log.stream.write(`\n[${commandName}:exit] code=${code ?? 1}\n`);
984
+ log.stream.end(() => {
985
+ if ((code ?? 1) === 0) {
986
+ resolveRun();
987
+ } else {
988
+ const wrapped = createCliError(`${commandName} failed with exit code ${code ?? 1}.`, code ?? 1);
989
+ wrapped.stdout = stdoutText;
990
+ wrapped.stderr = stderrText;
991
+ wrapped.logPath = log.path;
992
+ wrapped.commandName = commandName;
993
+ wrapped.silent = true;
994
+ rejectRun(wrapped);
995
+ }
996
+ });
997
+ });
998
+ });
999
+ }
1000
+
1001
+ async function chooseDefaultCommand() {
1002
+ printBanner('READY');
1003
+ const choice = await promptSelect(
1004
+ ' Choose command',
1005
+ [
1006
+ { value: 'dev', label: 'Dev' },
1007
+ { value: 'play', label: 'Play' },
1008
+ { value: 'fork', label: 'Fork' },
1009
+ { value: 'session', label: 'Session' },
1010
+ { value: 'publish', label: 'Publish' },
1011
+ { value: 'help', label: 'Help' },
1012
+ ],
1013
+ 'dev',
1014
+ );
1015
+ return choice;
1016
+ }
1017
+
1018
+ async function main() {
1019
+ const parsed = parseArgs(process.argv.slice(2));
1020
+
1021
+ if (parsed.help) {
1022
+ printHelp(parsed.showAll === true);
1023
+ return;
1024
+ }
1025
+
1026
+ let command = parsed.command;
1027
+ let commandArgs = [...parsed.commandArgs];
1028
+
1029
+ if (!command) {
1030
+ if (process.stdin.isTTY && process.stdout.isTTY) {
1031
+ command = await chooseDefaultCommand();
1032
+ if (command === 'help') {
1033
+ printHelp(false);
1034
+ return;
1035
+ }
1036
+ if (command === 'session') {
1037
+ commandArgs = ['start'];
1038
+ }
1039
+ } else {
1040
+ command = 'play';
1041
+ }
1042
+ }
1043
+
1044
+ if (command === 'play') {
1045
+ printBanner('PLAY');
1046
+ printSection(toDisplayTitle(packageName), 'Starting game + dev session...');
1047
+ const externalAssets = await maybePrepareExternalAssets('play');
1048
+ const multiplayerEnv = await resolveLocalMultiplayerCommandEnv();
1049
+ await runCommand(
1050
+ 'play',
1051
+ resolveAuraCliInvocation(['run', '--session', '--asset-mode', 'sibling', ...commandArgs]),
1052
+ {
1053
+ cwd: externalAssets.runtimeProjectRoot,
1054
+ env: multiplayerEnv,
1055
+ },
1056
+ );
1057
+ return;
1058
+ }
1059
+
1060
+ if (command === 'fork') {
1061
+ printBanner('FORK');
1062
+ const destinationRoot = await resolveForkDestination(commandArgs);
1063
+ if (!destinationRoot) {
1064
+ printSection(toDisplayTitle(packageName), 'Fork cancelled.');
1065
+ return;
1066
+ }
1067
+ assertForkDestination(destinationRoot);
1068
+ printSection(toDisplayTitle(packageName), `Copying editable package files into ${normalizeDisplayPath(destinationRoot)}...`);
1069
+ copyForkProject(destinationRoot);
1070
+ console.log(` Fork ready: ${normalizeDisplayPath(destinationRoot)}`);
1071
+ console.log('');
1072
+ console.log(' Next steps:');
1073
+ console.log(` cd ${normalizeDisplayPath(destinationRoot)}`);
1074
+ console.log(' npm install');
1075
+ console.log(' npm run dev');
1076
+ console.log('');
1077
+ return;
1078
+ }
1079
+
1080
+ if (command === 'dev') {
1081
+ printBanner('DEV');
1082
+ printSection(toDisplayTitle(packageName), 'Starting native dev loop...');
1083
+ const multiplayerEnv = await resolveLocalMultiplayerCommandEnv();
1084
+ await runCommand('dev', resolveAuraCliInvocation(['dev', ...commandArgs]), {
1085
+ env: multiplayerEnv,
1086
+ });
1087
+ return;
1088
+ }
1089
+
1090
+ if (command === 'join') {
1091
+ printBanner('JOIN');
1092
+ let join = null;
1093
+ try {
1094
+ join = parseJoinArgs(commandArgs);
1095
+ const joinLaunchMode = resolveJoinLaunchMode(join.launchMode);
1096
+ assertJoinSupported();
1097
+ const externalAssets = await maybePrepareExternalAssets('join');
1098
+ const multiplayerEnv = await resolveLocalMultiplayerCommandEnv();
1099
+ if (joinLaunchMode === 'play') {
1100
+ printSection(toDisplayTitle(packageName), `Joining room ${join.code}...`);
1101
+ await runCommand(
1102
+ 'join',
1103
+ resolveAuraCliInvocation(['run', '--session', '--asset-mode', 'sibling', ...join.passthroughArgs, '--join', join.code]),
1104
+ {
1105
+ cwd: externalAssets.runtimeProjectRoot,
1106
+ env: {
1107
+ ...(multiplayerEnv || {}),
1108
+ AURA_MULTIPLAYER_LAUNCH_ROLE: 'join',
1109
+ AURA_MULTIPLAYER_JOIN_CODE: join.code,
1110
+ },
1111
+ },
1112
+ );
1113
+ return;
1114
+ }
1115
+ printSection(toDisplayTitle(packageName), `Joining room ${join.code} through the native dev loop...`);
1116
+ await runCommand(
1117
+ 'join',
1118
+ resolveAuraCliInvocation(['dev', ...join.passthroughArgs, '--join', join.code]),
1119
+ {
1120
+ cwd: externalAssets.runtimeProjectRoot,
1121
+ env: {
1122
+ ...(multiplayerEnv || {}),
1123
+ AURA_MULTIPLAYER_LAUNCH_ROLE: 'join',
1124
+ AURA_MULTIPLAYER_JOIN_CODE: join.code,
1125
+ },
1126
+ },
1127
+ );
1128
+ } catch (error) {
1129
+ throw formatJoinFailure(error, {
1130
+ joinCode: join?.code || null,
1131
+ joinLaunchMode: resolveJoinLaunchMode(join?.launchMode || null),
1132
+ });
1133
+ }
1134
+ return;
1135
+ }
1136
+
1137
+ if (command === 'publish') {
1138
+ printBanner('PUBLISH');
1139
+ if (isNpmPublishLifecycleInvocation()) {
1140
+ printSection(toDisplayTitle(packageName), 'Publish lifecycle detected, skipping wrapper recursion.');
1141
+ return;
1142
+ }
1143
+ printSection(toDisplayTitle(packageName), 'Publishing npm package (source + assets)...');
1144
+ await runCommand('publish', resolveAuraCliInvocation(['publish', ...commandArgs]));
1145
+ return;
1146
+ }
1147
+
1148
+ if (command === 'session') {
1149
+ printBanner('SESSION');
1150
+ printSection(toDisplayTitle(packageName), commandArgs.length > 0 ? 'Delegating to aura session...' : 'Starting session...');
1151
+ const sessionArgs = commandArgs.length > 0 ? commandArgs : ['start'];
1152
+ await runCommand('session', resolveAuraCliInvocation(['session', ...sessionArgs]));
1153
+ return;
1154
+ }
1155
+
1156
+ if (command === 'state') {
1157
+ printBanner('STATE');
1158
+ printSection(toDisplayTitle(packageName), 'Delegating to aura state...');
1159
+ await runCommand('state', resolveAuraCliInvocation(['state', ...commandArgs]));
1160
+ return;
1161
+ }
1162
+
1163
+ if (command === 'inspect') {
1164
+ printBanner('INSPECT');
1165
+ printSection(toDisplayTitle(packageName), 'Delegating to aura inspect...');
1166
+ await runCommand('inspect', resolveAuraCliInvocation(['inspect', ...commandArgs]));
1167
+ return;
1168
+ }
1169
+
1170
+ if (command === 'action') {
1171
+ printBanner('ACTION');
1172
+ printSection(toDisplayTitle(packageName), 'Delegating to aura action...');
1173
+ await runCommand('action', resolveAuraCliInvocation(['action', ...commandArgs]));
1174
+ return;
1175
+ }
1176
+
1177
+ printHelp(false);
1178
+ console.error(` Unknown command: ${command}`);
1179
+ process.exit(1);
1180
+ }
1181
+
1182
+ main().catch((error) => {
1183
+ if (!error?.silent) {
1184
+ console.error(error instanceof Error ? error.message : String(error));
1185
+ }
1186
+ process.exit(Number.isInteger(error?.exitCode) ? error.exitCode : 1);
1187
+ });