@auraindustry/aurajs 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -7
- package/benchmarks/perf-thresholds.json +54 -0
- package/package.json +4 -7
- package/src/asset-pack.mjs +5 -1
- package/src/authored-project.mjs +1449 -0
- package/src/authored-runtime.mjs +2016 -0
- package/src/authoring/avatar-animation-graph.mjs +648 -0
- package/src/bin-integrity.mjs +272 -0
- package/src/build-contract/assets.mjs +130 -0
- package/src/build-contract/capabilities.mjs +116 -0
- package/src/build-contract/constants.mjs +6 -0
- package/src/build-contract/helpers.mjs +44 -0
- package/src/build-contract/web-templates.mjs +5993 -0
- package/src/build-contract.mjs +27 -2910
- package/src/bundler.mjs +188 -55
- package/src/cli.mjs +4825 -1512
- package/src/commands/project-authoring.mjs +434 -0
- package/src/config.mjs +27 -0
- package/src/conformance/cases/app-and-ui-runtime-cases.mjs +3309 -0
- package/src/conformance/cases/core-runtime-cases.mjs +1431 -0
- package/src/conformance/cases/index.mjs +11 -0
- package/src/conformance/cases/scene3d-and-media-cases.mjs +2094 -0
- package/src/conformance/cases/systems-and-gameplay-cases.mjs +1776 -0
- package/src/conformance/shared.mjs +27 -0
- package/src/conformance-runner.mjs +25 -13
- package/src/conformance.mjs +619 -4020
- package/src/cutscene.mjs +362 -5
- package/src/dev-cli-action.mjs +249 -0
- package/src/dev-cli-inspect.mjs +92 -0
- package/src/dev-cli-state.mjs +80 -0
- package/src/external-asset-cache.mjs +587 -0
- package/src/external-asset-policy.mjs +217 -0
- package/src/external-package-surface.mjs +206 -0
- package/src/game-action-runtime.mjs +869 -0
- package/src/game-state-runtime.mjs +206 -6
- package/src/headless-action.mjs +186 -0
- package/src/headless-test/runtime-animation.mjs +1173 -0
- package/src/headless-test/runtime-coordinator.mjs +1514 -0
- package/src/headless-test/runtime-primitives.mjs +320 -0
- package/src/headless-test/runtime-world.mjs +2253 -0
- package/src/headless-test.mjs +392 -4298
- package/src/host-binary.mjs +342 -14
- package/src/icon-discovery.mjs +64 -0
- package/src/make-catalog.mjs +109 -0
- package/src/make.mjs +197 -0
- package/src/package-integrity.mjs +586 -0
- package/src/perf-benchmark.mjs +353 -0
- package/src/postinstall.mjs +5 -5
- package/src/prefabs/index.mjs +34 -0
- package/src/prefabs/scene-serialization.mjs +184 -0
- package/src/project-importer.mjs +620 -0
- package/src/project-registry.mjs +24 -0
- package/src/publish-command.mjs +195 -0
- package/src/publish-env-example.mjs +83 -0
- package/src/publish-validation.mjs +708 -0
- package/src/retro/assets/compile.mjs +232 -0
- package/src/retro/backend-gba/authoring.mjs +1029 -0
- package/src/retro/backend-gba/rom.mjs +363 -0
- package/src/retro/backend-gbc/rom.mjs +85 -0
- package/src/retro/build.mjs +278 -0
- package/src/retro/cli/commands.mjs +292 -0
- package/src/retro/cli/templates.mjs +84 -0
- package/src/retro/diagnostics/catalog.mjs +110 -0
- package/src/retro/diagnostics/emit.mjs +72 -0
- package/src/retro/emulator/case-overlay.mjs +64 -0
- package/src/retro/emulator/discovery.mjs +158 -0
- package/src/retro/emulator/macos-case-overlay.swift +220 -0
- package/src/retro/emulator/profiles.mjs +146 -0
- package/src/retro/emulator/runner.mjs +289 -0
- package/src/retro/frontend/load-project.mjs +98 -0
- package/src/retro/index.mjs +30 -0
- package/src/retro/ir/build-ir.mjs +108 -0
- package/src/retro/runtime-gba/contract.mjs +151 -0
- package/src/retro/runtime-gbc/contract.mjs +117 -0
- package/src/retro/shared/span.mjs +26 -0
- package/src/retro/shared/targets.mjs +64 -0
- package/src/retro/validator/check-project.mjs +114 -0
- package/src/runtime-hotspot-audit.mjs +707 -0
- package/src/scaffold/config.mjs +1000 -0
- package/src/scaffold/fs.mjs +56 -0
- package/src/scaffold/layout.mjs +318 -0
- package/src/scaffold/project-docs.mjs +438 -0
- package/src/scaffold.mjs +93 -596
- package/src/scene-composition/index.mjs +326 -0
- package/src/scene-composition/runtime.mjs +751 -0
- package/src/self-hosted-assets.mjs +604 -0
- package/src/session-client.mjs +750 -0
- package/src/session-native-launcher.mjs +74 -0
- package/src/session-protocol.mjs +75 -0
- package/src/session-runtime.mjs +321 -0
- package/src/session-server.mjs +360 -0
- package/src/shader-kits/index.mjs +773 -0
- package/src/starter-content-registry.mjs +292 -0
- package/src/state-artifacts.mjs +662 -24
- package/src/state-dev-reload.mjs +99 -2
- package/src/terminal-ui.mjs +245 -0
- package/src/web-conformance.mjs +219 -0
- package/templates/create/2d/config/gameplay/shooter.config.js +26 -0
- package/templates/create/2d/content/gameplay/waves.json +26 -0
- package/templates/create/2d/content/registries/.gitkeep +1 -0
- package/templates/create/2d/docs/design/.gitkeep +1 -0
- package/templates/create/2d/docs/design/loop.md +5 -0
- package/templates/create/2d/prefabs/enemies.prefab.js +90 -0
- package/templates/create/2d/prefabs/enemy-basic.prefab.js +18 -0
- package/templates/create/2d/prefabs/player.prefab.js +36 -0
- package/templates/create/2d/prefabs/projectiles.prefab.js +35 -0
- package/templates/create/2d/scenes/boot.scene.js +12 -0
- package/templates/create/2d/scenes/gameplay.scene.js +230 -0
- package/templates/create/2d/scenes/menu.scene.js +9 -0
- package/templates/create/2d/src/main.js +6 -185
- package/templates/create/2d/src/runtime/app.js +49 -0
- package/templates/create/2d/src/runtime/capabilities.js +35 -0
- package/templates/create/2d/ui/hud.screen.js +40 -0
- package/templates/create/2d/ui/pause.screen.js +149 -0
- package/templates/create/2d/ui/settings.screen.js +347 -0
- package/templates/create/2d/ui/title.screen.js +13 -0
- package/templates/create/2d-adventure/aura.config.json +28 -0
- package/templates/create/2d-adventure/config/gameplay/adventure.config.js +14 -0
- package/templates/create/2d-adventure/content/gameplay/world.js +46 -0
- package/templates/create/2d-adventure/content/registries/.gitkeep +1 -0
- package/templates/create/2d-adventure/docs/design/loop.md +5 -0
- package/templates/create/2d-adventure/prefabs/player.prefab.js +54 -0
- package/templates/create/2d-adventure/prefabs/relic.prefab.js +38 -0
- package/templates/create/2d-adventure/prefabs/world.prefab.js +125 -0
- package/templates/create/2d-adventure/scenes/gameplay.scene.js +256 -0
- package/templates/create/2d-adventure/src/runtime/capabilities.js +34 -0
- package/templates/create/2d-adventure/ui/hud.screen.js +60 -0
- package/templates/create/2d-survivor/config/gameplay/survivor.config.js +33 -0
- package/templates/create/2d-survivor/content/gameplay/spawn-zones.json +29 -0
- package/templates/create/2d-survivor/content/registries/.gitkeep +1 -0
- package/templates/create/2d-survivor/docs/design/.gitkeep +1 -0
- package/templates/create/2d-survivor/docs/design/loop.md +5 -0
- package/templates/create/2d-survivor/prefabs/enemies.prefab.js +178 -0
- package/templates/create/2d-survivor/prefabs/enemy-swarm.prefab.js +18 -0
- package/templates/create/2d-survivor/prefabs/player.prefab.js +42 -0
- package/templates/create/2d-survivor/prefabs/projectiles.prefab.js +56 -0
- package/templates/create/2d-survivor/scenes/boot.scene.js +12 -0
- package/templates/create/2d-survivor/scenes/gameplay.scene.js +314 -0
- package/templates/create/2d-survivor/scenes/menu.scene.js +9 -0
- package/templates/create/2d-survivor/src/main.js +5 -332
- package/templates/create/2d-survivor/src/runtime/app.js +49 -0
- package/templates/create/2d-survivor/src/runtime/capabilities.js +35 -0
- package/templates/create/2d-survivor/ui/hud.screen.js +45 -0
- package/templates/create/2d-survivor/ui/title.screen.js +13 -0
- package/templates/create/3d/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d/config/gameplay/.gitkeep +1 -0
- package/templates/create/3d/content/gameplay/checkpoints.json +33 -0
- package/templates/create/3d/content/gameplay/course.js +40 -0
- package/templates/create/3d/content/registries/.gitkeep +1 -0
- package/templates/create/3d/docs/design/.gitkeep +1 -0
- package/templates/create/3d/docs/design/loop.md +5 -0
- package/templates/create/3d/prefabs/checkpoint.prefab.js +15 -0
- package/templates/create/3d/prefabs/player.prefab.js +204 -0
- package/templates/create/3d/prefabs/world.prefab.js +112 -0
- package/templates/create/3d/scenes/boot.scene.js +12 -0
- package/templates/create/3d/scenes/checkpoint.scene.js +9 -0
- package/templates/create/3d/scenes/gameplay.scene.js +292 -0
- package/templates/create/3d/src/main.js +6 -295
- package/templates/create/3d/src/runtime/app.js +49 -0
- package/templates/create/3d/src/runtime/capabilities.js +53 -0
- package/templates/create/3d/src/runtime/materials.js +34 -0
- package/templates/create/3d/src/runtime/state.js +39 -0
- package/templates/create/3d/ui/hud.screen.js +75 -0
- package/templates/create/3d/ui/pause.screen.js +166 -0
- package/templates/create/3d/ui/settings.screen.js +387 -0
- package/templates/create/3d-adventure/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d-adventure/aura.config.json +28 -0
- package/templates/create/3d-adventure/config/gameplay/adventure.config.js +9 -0
- package/templates/create/3d-adventure/content/gameplay/course.js +62 -0
- package/templates/create/3d-adventure/content/registries/.gitkeep +1 -0
- package/templates/create/3d-adventure/docs/design/loop.md +5 -0
- package/templates/create/3d-adventure/prefabs/player.prefab.js +168 -0
- package/templates/create/3d-adventure/prefabs/relic.prefab.js +35 -0
- package/templates/create/3d-adventure/prefabs/world.prefab.js +119 -0
- package/templates/create/3d-adventure/scenes/gameplay.scene.js +358 -0
- package/templates/create/3d-adventure/src/runtime/capabilities.js +56 -0
- package/templates/create/3d-adventure/src/runtime/materials.js +39 -0
- package/templates/create/3d-adventure/src/runtime/state.js +31 -0
- package/templates/create/3d-adventure/ui/hud.screen.js +70 -0
- package/templates/create/3d-adventure/ui/pause.screen.js +437 -0
- package/templates/create/3d-collectathon/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d-collectathon/config/gameplay/.gitkeep +1 -0
- package/templates/create/3d-collectathon/content/gameplay/collectibles.json +26 -0
- package/templates/create/3d-collectathon/content/gameplay/course.js +46 -0
- package/templates/create/3d-collectathon/content/registries/.gitkeep +1 -0
- package/templates/create/3d-collectathon/docs/design/.gitkeep +1 -0
- package/templates/create/3d-collectathon/docs/design/loop.md +5 -0
- package/templates/create/3d-collectathon/prefabs/collectible.prefab.js +15 -0
- package/templates/create/3d-collectathon/prefabs/player.prefab.js +207 -0
- package/templates/create/3d-collectathon/prefabs/world.prefab.js +112 -0
- package/templates/create/3d-collectathon/scenes/boot.scene.js +12 -0
- package/templates/create/3d-collectathon/scenes/checkpoint.scene.js +9 -0
- package/templates/create/3d-collectathon/scenes/gameplay.scene.js +200 -0
- package/templates/create/3d-collectathon/src/main.js +5 -355
- package/templates/create/3d-collectathon/src/runtime/app.js +49 -0
- package/templates/create/3d-collectathon/src/runtime/capabilities.js +53 -0
- package/templates/create/3d-collectathon/src/runtime/materials.js +34 -0
- package/templates/create/3d-collectathon/src/runtime/state.js +27 -0
- package/templates/create/3d-collectathon/ui/hud.screen.js +66 -0
- package/templates/create/3d-collectathon/ui/pause.screen.js +13 -0
- package/templates/create/blank/config/gameplay/.gitkeep +1 -0
- package/templates/create/blank/content/gameplay/.gitkeep +1 -0
- package/templates/create/blank/content/registries/.gitkeep +1 -0
- package/templates/create/blank/docs/design/.gitkeep +1 -0
- package/templates/create/blank/docs/design/loop.md +5 -0
- package/templates/create/blank/prefabs/.gitkeep +1 -0
- package/templates/create/blank/scenes/.gitkeep +1 -0
- package/templates/create/blank/src/runtime/.gitkeep +1 -0
- package/templates/create/blank/ui/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/audio/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/fonts/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/sprites/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/starter/README.md +11 -0
- package/templates/create/deckbuilder-2d/assets/ui/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/aura.config.json +28 -0
- package/templates/create/deckbuilder-2d/config/gameplay/deckbuilder.config.js +26 -0
- package/templates/create/deckbuilder-2d/content/cards/guard.card.js +19 -0
- package/templates/create/deckbuilder-2d/content/cards/spark.card.js +20 -0
- package/templates/create/deckbuilder-2d/content/cards/starter.deck.js +69 -0
- package/templates/create/deckbuilder-2d/content/cards/strike.card.js +19 -0
- package/templates/create/deckbuilder-2d/content/cards/survey.card.js +20 -0
- package/templates/create/deckbuilder-2d/content/encounters/training-battle.encounter.js +14 -0
- package/templates/create/deckbuilder-2d/content/encounters/training-battle.js +65 -0
- package/templates/create/deckbuilder-2d/content/enemies/training-automaton.enemy.js +48 -0
- package/templates/create/deckbuilder-2d/content/gameplay/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/content/registries/cards.registry.js +26 -0
- package/templates/create/deckbuilder-2d/content/registries/encounters.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/registries/enemies.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/registries/relics.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/relics/ember-charm.relic.js +18 -0
- package/templates/create/deckbuilder-2d/docs/design/loop.md +12 -0
- package/templates/create/deckbuilder-2d/prefabs/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/scenes/boot.scene.js +84 -0
- package/templates/create/deckbuilder-2d/scenes/gameplay.scene.js +641 -0
- package/templates/create/deckbuilder-2d/src/components/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/src/main.js +17 -0
- package/templates/create/deckbuilder-2d/src/runtime/capabilities.js +22 -0
- package/templates/create/deckbuilder-2d/src/shared/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/src/systems/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/tests/smoke/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/ui/hud.screen.js +80 -0
- package/templates/create/deckbuilder-2d/ui/pause.screen.js +146 -0
- package/templates/create/deckbuilder-2d/ui/settings.screen.js +342 -0
- package/templates/create/local-multiplayer/aura.config.json +40 -0
- package/templates/create/local-multiplayer/config/gameplay/local-multiplayer.config.js +26 -0
- package/templates/create/local-multiplayer/content/gameplay/room-layout.js +13 -0
- package/templates/create/local-multiplayer/content/registries/.gitkeep +1 -0
- package/templates/create/local-multiplayer/docs/design/loop.md +14 -0
- package/templates/create/local-multiplayer/prefabs/player.prefab.js +99 -0
- package/templates/create/local-multiplayer/scenes/boot.scene.js +12 -0
- package/templates/create/local-multiplayer/scenes/gameplay.scene.js +443 -0
- package/templates/create/local-multiplayer/src/main.js +17 -0
- package/templates/create/local-multiplayer/src/runtime/capabilities.js +28 -0
- package/templates/create/local-multiplayer/ui/hud.screen.js +60 -0
- package/templates/create/shared/src/runtime/project-inspector.js +105 -0
- package/templates/create/shared/src/runtime/scene-flow.js +290 -0
- package/templates/create/shared/src/runtime/screen-shell.js +222 -0
- package/templates/create/shared/src/runtime/ui-forms.js +209 -0
- package/templates/create/shared/src/runtime/ui-settings.js +237 -0
- package/templates/create/shared/src/runtime/ui-theme.js +352 -0
- package/templates/create/shared/src/starter-utils/adventure-objectives.js +102 -0
- package/templates/create/shared/src/starter-utils/animation-2d.js +337 -0
- package/templates/create/shared/src/starter-utils/avatar-3d.js +404 -0
- package/templates/create/shared/src/starter-utils/combat-feedback-2d.js +320 -0
- package/templates/create/shared/src/starter-utils/core.js +39 -3
- package/templates/create/shared/src/starter-utils/index.js +8 -2
- package/templates/create/shared/src/starter-utils/platformer-3d.js +34 -3
- package/templates/create/shared/src/starter-utils/triggers.js +662 -0
- package/templates/create/shared/src/starter-utils/tween-2d.js +615 -0
- package/templates/create/video-cutscene/assets/video/.gitkeep +0 -0
- package/templates/create/video-cutscene/aura.config.json +28 -0
- package/templates/create/video-cutscene/config/gameplay/.gitkeep +0 -0
- package/templates/create/video-cutscene/content/gameplay/.gitkeep +0 -0
- package/templates/create/video-cutscene/content/registries/.gitkeep +0 -0
- package/templates/create/video-cutscene/docs/design/loop.md +22 -0
- package/templates/create/video-cutscene/prefabs/.gitkeep +0 -0
- package/templates/create/video-cutscene/scenes/boot.scene.js +11 -0
- package/templates/create/video-cutscene/scenes/cutscene.scene.js +113 -0
- package/templates/create/video-cutscene/scenes/gameplay.scene.js +50 -0
- package/templates/create/video-cutscene/src/main.js +17 -0
- package/templates/create/video-cutscene/src/runtime/app.js +52 -0
- package/templates/create/video-cutscene/src/runtime/capabilities.js +35 -0
- package/templates/create/video-cutscene/src/runtime/state.js +13 -0
- package/templates/create/video-cutscene/ui/.gitkeep +0 -0
- package/templates/create-bin/play.js +1187 -0
- package/templates/make/README.md +46 -0
- package/templates/make/catalog.json +51 -0
- package/templates/make/component/files/{{MAKE_NAME}}.component.js +20 -0
- package/templates/make/component/manifest.json +9 -0
- package/templates/make/data/files/{{MAKE_NAME}}.json +14 -0
- package/templates/make/data/manifest.json +9 -0
- package/templates/make/material/files/{{MAKE_NAME}}.material.json +17 -0
- package/templates/make/material/manifest.json +9 -0
- package/templates/make/prefab/files/{{MAKE_NAME}}.prefab.js +20 -0
- package/templates/make/prefab/manifest.json +9 -0
- package/templates/make/scene/files/{{MAKE_NAME}}.scene.js +31 -0
- package/templates/make/scene/manifest.json +9 -0
- package/templates/make/shader/files/{{MAKE_NAME}}.shader.js +23 -0
- package/templates/make/shader/manifest.json +9 -0
- package/templates/make/system/files/{{MAKE_NAME}}.system.js +15 -0
- package/templates/make/system/manifest.json +9 -0
- package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.js +16 -0
- package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.json +23 -0
- package/templates/make/ui-screen/manifest.json +10 -0
- package/templates/make-starters/deckbuilder-2d/card/files/{{MAKE_NAME}}.card.js +22 -0
- package/templates/make-starters/deckbuilder-2d/card/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/catalog.json +34 -0
- package/templates/make-starters/deckbuilder-2d/encounter/files/{{MAKE_NAME}}.encounter.js +18 -0
- package/templates/make-starters/deckbuilder-2d/encounter/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/enemy/files/{{MAKE_NAME}}.enemy.js +28 -0
- package/templates/make-starters/deckbuilder-2d/enemy/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/relic/files/{{MAKE_NAME}}.relic.js +23 -0
- package/templates/make-starters/deckbuilder-2d/relic/manifest.json +9 -0
- package/templates/retro/platformer/README.md +10 -0
- package/templates/retro/platformer/assets/retro/assets.json +91 -0
- package/templates/retro/platformer/aura.config.json +7 -0
- package/templates/retro/platformer/package.json +5 -0
- package/templates/retro/platformer/src/main.js +40 -0
- package/templates/retro/puzzle-grid/README.md +10 -0
- package/templates/retro/puzzle-grid/assets/retro/assets.json +90 -0
- package/templates/retro/puzzle-grid/aura.config.json +7 -0
- package/templates/retro/puzzle-grid/package.json +5 -0
- package/templates/retro/puzzle-grid/src/main.js +29 -0
- package/templates/retro/tactics-grid/README.md +10 -0
- package/templates/retro/tactics-grid/assets/retro/assets.json +90 -0
- package/templates/retro/tactics-grid/aura.config.json +7 -0
- package/templates/retro/tactics-grid/package.json +5 -0
- package/templates/retro/tactics-grid/src/main.js +35 -0
- package/templates/retro/topdown-adventure/README.md +10 -0
- package/templates/retro/topdown-adventure/assets/retro/assets.json +95 -0
- package/templates/retro/topdown-adventure/aura.config.json +7 -0
- package/templates/retro/topdown-adventure/package.json +5 -0
- package/templates/retro/topdown-adventure/src/main.js +29 -0
- package/templates/skills/aurajs/SKILL.md +61 -5
package/src/state-dev-reload.mjs
CHANGED
|
@@ -19,6 +19,9 @@ export function prepareDevStateRestoreEntry({
|
|
|
19
19
|
projectRoot: resolvedProjectRoot,
|
|
20
20
|
kind: artifactKind,
|
|
21
21
|
name: artifactName,
|
|
22
|
+
exportDefaults: {
|
|
23
|
+
mode: 'native',
|
|
24
|
+
},
|
|
22
25
|
});
|
|
23
26
|
|
|
24
27
|
if (artifact.envelope.stateSchemaVersion !== GAME_STATE_SCHEMA_VERSION) {
|
|
@@ -54,14 +57,82 @@ export function prepareDevStateRestoreEntry({
|
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
59
|
|
|
60
|
+
export function prepareDevStateRestorePayloadEntry({
|
|
61
|
+
projectRoot,
|
|
62
|
+
entryFile,
|
|
63
|
+
payload,
|
|
64
|
+
reasonCode = 'dev_live_state_restore',
|
|
65
|
+
label = 'live',
|
|
66
|
+
}) {
|
|
67
|
+
const resolvedProjectRoot = resolve(projectRoot || process.cwd());
|
|
68
|
+
const resolvedEntryFile = resolve(resolvedProjectRoot, entryFile || 'src/main.js');
|
|
69
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
70
|
+
throw new Error('Live dev-state restore payload must be an object.');
|
|
71
|
+
}
|
|
72
|
+
if (payload.schemaVersion !== GAME_STATE_SCHEMA_VERSION) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Live dev-state restore payload uses schema "${payload.schemaVersion}", expected "${GAME_STATE_SCHEMA_VERSION}".`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const generatedDir = resolve(resolvedProjectRoot, 'src', '.aurajs-generated');
|
|
79
|
+
mkdirSync(generatedDir, { recursive: true });
|
|
80
|
+
|
|
81
|
+
const safeLabel = String(label || 'live')
|
|
82
|
+
.trim()
|
|
83
|
+
.replace(/[^a-zA-Z0-9._-]+/g, '-')
|
|
84
|
+
.replace(/-+/g, '-')
|
|
85
|
+
.replace(/^[-._]+|[-._]+$/g, '')
|
|
86
|
+
.slice(0, 48) || 'live';
|
|
87
|
+
const generatedFile = resolve(generatedDir, `dev-state-restore-${safeLabel}.js`);
|
|
88
|
+
const relativeImport = normalizeImportSpecifier(dirname(generatedFile), resolvedEntryFile);
|
|
89
|
+
const wrapperSource = buildDevStateRestoreWrapperSource({
|
|
90
|
+
entryImport: relativeImport,
|
|
91
|
+
payload,
|
|
92
|
+
artifact: {
|
|
93
|
+
kind: 'live-session',
|
|
94
|
+
artifactVersion: null,
|
|
95
|
+
name: safeLabel,
|
|
96
|
+
path: relative(resolvedProjectRoot, generatedFile).split(sep).join('/'),
|
|
97
|
+
stateSchemaVersion: GAME_STATE_SCHEMA_VERSION,
|
|
98
|
+
payloadFingerprint: payload?.export?.fingerprint || null,
|
|
99
|
+
migration: null,
|
|
100
|
+
reasonCode,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const previous = tryReadFile(generatedFile);
|
|
105
|
+
if (previous !== wrapperSource) {
|
|
106
|
+
writeFileSync(generatedFile, wrapperSource, 'utf8');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
entryFile: relative(resolvedProjectRoot, generatedFile).split(sep).join('/'),
|
|
111
|
+
wrapperPath: generatedFile,
|
|
112
|
+
artifact: {
|
|
113
|
+
kind: 'live-session',
|
|
114
|
+
artifactVersion: null,
|
|
115
|
+
name: safeLabel,
|
|
116
|
+
path: relative(resolvedProjectRoot, generatedFile).split(sep).join('/'),
|
|
117
|
+
stateSchemaVersion: GAME_STATE_SCHEMA_VERSION,
|
|
118
|
+
payloadFingerprint: payload?.export?.fingerprint || null,
|
|
119
|
+
migration: null,
|
|
120
|
+
reasonCode,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
57
125
|
export function buildDevStateRestoreWrapperSource({ entryImport, payload, artifact }) {
|
|
58
126
|
const bootstrapSource = buildStateRestoreRuntimeBootstrapSource();
|
|
59
127
|
const metadata = {
|
|
60
128
|
kind: artifact.kind,
|
|
129
|
+
artifactVersion: artifact.artifactVersion ?? null,
|
|
61
130
|
name: artifact.name,
|
|
62
131
|
path: artifact.path,
|
|
63
132
|
stateSchemaVersion: artifact.stateSchemaVersion,
|
|
64
133
|
payloadFingerprint: artifact.payloadFingerprint,
|
|
134
|
+
migration: artifact.migration || null,
|
|
135
|
+
reasonCode: artifact.reasonCode || null,
|
|
65
136
|
};
|
|
66
137
|
|
|
67
138
|
return [
|
|
@@ -76,26 +147,52 @@ export function buildDevStateRestoreWrapperSource({ entryImport, payload, artifa
|
|
|
76
147
|
' if (!stateNs || typeof stateNs.apply !== "function") {',
|
|
77
148
|
' throw new Error("[aurajs] dev restore failed: aura.state.apply is unavailable");',
|
|
78
149
|
' }',
|
|
150
|
+
' if (aura && typeof aura === "object") {',
|
|
151
|
+
' aura.__aurajsPendingDevRestore = { ...__aurajsRestoreMeta };',
|
|
152
|
+
' }',
|
|
79
153
|
' const result = stateNs.apply(__aurajsRestorePayload);',
|
|
80
154
|
' if (!result || result.ok !== true) {',
|
|
81
155
|
' const reasonCode = result && typeof result.reasonCode === "string"',
|
|
82
156
|
' ? result.reasonCode',
|
|
83
157
|
' : "state_apply_failed";',
|
|
158
|
+
' if (aura && typeof aura === "object") {',
|
|
159
|
+
' aura.__aurajsDevRestore = {',
|
|
160
|
+
' kind: __aurajsRestoreMeta.kind,',
|
|
161
|
+
' artifactVersion: __aurajsRestoreMeta.artifactVersion || null,',
|
|
162
|
+
' name: __aurajsRestoreMeta.name,',
|
|
163
|
+
' path: __aurajsRestoreMeta.path,',
|
|
164
|
+
' stateSchemaVersion: __aurajsRestoreMeta.stateSchemaVersion || null,',
|
|
165
|
+
' reasonCode,',
|
|
166
|
+
' detail: result && typeof result === "object" ? result.detail || null : null,',
|
|
167
|
+
' payloadFingerprint: __aurajsRestoreMeta.payloadFingerprint || null,',
|
|
168
|
+
' migration: __aurajsRestoreMeta.migration || null,',
|
|
169
|
+
' continuity: result && typeof result === "object" ? result.continuity || null : null,',
|
|
170
|
+
' ok: false,',
|
|
171
|
+
' };',
|
|
172
|
+
' delete aura.__aurajsPendingDevRestore;',
|
|
173
|
+
' }',
|
|
84
174
|
' throw new Error(`[aurajs] dev restore failed (${__aurajsRestoreMeta.kind}:${__aurajsRestoreMeta.name}): ${reasonCode}`);',
|
|
85
175
|
' }',
|
|
86
|
-
|
|
87
|
-
|
|
176
|
+
' return result;',
|
|
177
|
+
'}',
|
|
88
178
|
'aura.setup = function (...args) {',
|
|
89
179
|
' const setupResult = __aurajsOriginalSetup ? __aurajsOriginalSetup.apply(this, args) : undefined;',
|
|
90
180
|
' const restoreResult = __aurajsApplyRestorePayload();',
|
|
91
181
|
' if (aura && typeof aura === "object") {',
|
|
92
182
|
' aura.__aurajsDevRestore = {',
|
|
93
183
|
' kind: __aurajsRestoreMeta.kind,',
|
|
184
|
+
' artifactVersion: __aurajsRestoreMeta.artifactVersion || null,',
|
|
94
185
|
' name: __aurajsRestoreMeta.name,',
|
|
95
186
|
' path: __aurajsRestoreMeta.path,',
|
|
187
|
+
' stateSchemaVersion: __aurajsRestoreMeta.stateSchemaVersion || null,',
|
|
96
188
|
' reasonCode: restoreResult.reasonCode || null,',
|
|
189
|
+
' detail: restoreResult.detail || null,',
|
|
97
190
|
' payloadFingerprint: __aurajsRestoreMeta.payloadFingerprint || null,',
|
|
191
|
+
' migration: __aurajsRestoreMeta.migration || null,',
|
|
192
|
+
' continuity: restoreResult.continuity || null,',
|
|
193
|
+
' ok: restoreResult.ok === true,',
|
|
98
194
|
' };',
|
|
195
|
+
' delete aura.__aurajsPendingDevRestore;',
|
|
99
196
|
' }',
|
|
100
197
|
' return setupResult;',
|
|
101
198
|
'};',
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import readline from 'node:readline';
|
|
2
|
+
|
|
3
|
+
const START_BANNER_QUOTES = [
|
|
4
|
+
'ready to auramaxx and mog prompt peasants?',
|
|
5
|
+
'you are perfect. never give up your aura',
|
|
6
|
+
'why jestermaxx when you can auramaxx?',
|
|
7
|
+
'lock tf in, the aura farm is live.',
|
|
8
|
+
'we are so back. aura at all-time highs.',
|
|
9
|
+
'negative motion detected. deploy tera-aura.',
|
|
10
|
+
'delulu? no. pre-success manifestation engine.',
|
|
11
|
+
'doomers offline, builders online.',
|
|
12
|
+
'your aura just hit legendary rarity.',
|
|
13
|
+
'brainrot but make it productive.',
|
|
14
|
+
'stack wins, stack aura, stack peace.',
|
|
15
|
+
'this session is sponsored by unstoppable motion.',
|
|
16
|
+
'if plan A fails, we auramaxx harder.',
|
|
17
|
+
'zero cope, pure glow-up execution.',
|
|
18
|
+
'cooked? nah. we are perfectly seasoned.',
|
|
19
|
+
'straight gas, no brakes, no bad vibes.',
|
|
20
|
+
'today forecast: 100% chance of aura gains.',
|
|
21
|
+
'touch grass, then auramaxx.',
|
|
22
|
+
'say no to digital slops. say yes to auramaxx.',
|
|
23
|
+
'if the world goes dark can i still auramaxx with you?',
|
|
24
|
+
'its me, AI. you are absolutely right. i want to auramaxx as well.',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export const ANSI = {
|
|
28
|
+
reset: '\x1b[0m',
|
|
29
|
+
bold: '\x1b[1m',
|
|
30
|
+
dim: '\x1b[2m',
|
|
31
|
+
italic: '\x1b[3m',
|
|
32
|
+
fgAccent: '\x1b[38;5;154m',
|
|
33
|
+
fgWhite: '\x1b[97m',
|
|
34
|
+
fgGray: '\x1b[90m',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const USE_COLOR = process.stdout.isTTY
|
|
38
|
+
&& !process.env.NO_COLOR
|
|
39
|
+
&& process.env.CI !== 'true'
|
|
40
|
+
&& process.env.TERM !== 'dumb';
|
|
41
|
+
const BANNER_WIDTH = 62;
|
|
42
|
+
|
|
43
|
+
function wrapText(text, width) {
|
|
44
|
+
if (text.length <= width) return [text];
|
|
45
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
46
|
+
if (words.length === 0) return [''];
|
|
47
|
+
const lines = [];
|
|
48
|
+
let line = '';
|
|
49
|
+
for (const word of words) {
|
|
50
|
+
const next = line ? `${line} ${word}` : word;
|
|
51
|
+
if (next.length <= width) {
|
|
52
|
+
line = next;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (line) lines.push(line);
|
|
56
|
+
if (word.length <= width) {
|
|
57
|
+
line = word;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
for (let index = 0; index < word.length; index += width) {
|
|
61
|
+
lines.push(word.slice(index, index + width));
|
|
62
|
+
}
|
|
63
|
+
line = '';
|
|
64
|
+
}
|
|
65
|
+
if (line) lines.push(line);
|
|
66
|
+
return lines;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getBannerQuote() {
|
|
70
|
+
const forced = process.env.AURA_START_BANNER_QUOTE_INDEX;
|
|
71
|
+
if (forced) {
|
|
72
|
+
const forcedIndex = Number.parseInt(forced, 10);
|
|
73
|
+
if (Number.isFinite(forcedIndex)) {
|
|
74
|
+
return START_BANNER_QUOTES[Math.abs(forcedIndex) % START_BANNER_QUOTES.length];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return START_BANNER_QUOTES[Math.floor(Math.random() * START_BANNER_QUOTES.length)];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function paint(text, ...codes) {
|
|
81
|
+
if (!USE_COLOR) return text;
|
|
82
|
+
return `${codes.join('')}${text}${ANSI.reset}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function canPromptInteractively() {
|
|
86
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY && typeof process.stdin.setRawMode === 'function');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function printBanner(subtitle = '') {
|
|
90
|
+
const sub = String(subtitle || '').trim().toUpperCase();
|
|
91
|
+
const pipe = paint('|', ANSI.fgGray);
|
|
92
|
+
const logoPipe = paint('|', ANSI.fgGray);
|
|
93
|
+
const stripe = (value) => paint(value, ANSI.bold);
|
|
94
|
+
const logoTop = paint('.', ANSI.fgGray) + paint('----------', ANSI.dim) + paint('.', ANSI.fgGray);
|
|
95
|
+
const logoBottom = paint("'", ANSI.fgGray) + paint('----------', ANSI.dim) + paint("'", ANSI.fgGray);
|
|
96
|
+
|
|
97
|
+
console.log('');
|
|
98
|
+
console.log(` ${paint('.-', ANSI.fgGray)}${paint(' '.repeat(BANNER_WIDTH - 4), ANSI.dim)}${paint('-.', ANSI.fgGray)}`);
|
|
99
|
+
console.log(` ${pipe} ${logoTop}${' '.repeat(BANNER_WIDTH - 19)}${pipe}`);
|
|
100
|
+
console.log(` ${pipe} ${logoPipe}${stripe('\\\\')} ${stripe('\\\\')} ${stripe('\\\\')}${logoPipe} ${paint('A U R A', ANSI.bold)}${' '.repeat(BANNER_WIDTH - 30)}${pipe}`);
|
|
101
|
+
console.log(` ${pipe} ${logoPipe}${stripe('\\\\')} ${stripe('\\\\')} ${stripe('\\\\')}${logoPipe} ${paint('A U R A J S', ANSI.dim)}${' '.repeat(BANNER_WIDTH - 35)}${pipe}`);
|
|
102
|
+
console.log(` ${pipe} ${logoPipe}${stripe('\\\\')} ${stripe('\\\\')} ${stripe('\\\\')}${logoPipe} ${sub ? paint(sub, ANSI.fgAccent) : ''}${' '.repeat(Math.max(0, BANNER_WIDTH - 23 - sub.length))}${pipe}`);
|
|
103
|
+
console.log(` ${pipe} ${logoBottom}${' '.repeat(BANNER_WIDTH - 19)}${pipe}`);
|
|
104
|
+
console.log(` ${paint("'-", ANSI.fgGray)}${paint(' '.repeat(BANNER_WIDTH - 4), ANSI.dim)}${paint("-'", ANSI.fgGray)}`);
|
|
105
|
+
for (const line of wrapText(getBannerQuote(), BANNER_WIDTH - 2)) {
|
|
106
|
+
console.log(` ${paint(line, ANSI.fgWhite, ANSI.italic)}`);
|
|
107
|
+
}
|
|
108
|
+
console.log('');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function printSection(title, subtitle = '') {
|
|
112
|
+
console.log('');
|
|
113
|
+
console.log(` ${'- '.repeat(Math.floor(BANNER_WIDTH / 2))}`);
|
|
114
|
+
console.log(` ${paint(`[ ${String(title || '').toUpperCase()} ]`, ANSI.bold)}`);
|
|
115
|
+
if (subtitle) {
|
|
116
|
+
console.log(` ${paint(subtitle, ANSI.dim)}`);
|
|
117
|
+
}
|
|
118
|
+
console.log('');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function renderSelectLines(message, options, selectedIndex, defaultValue) {
|
|
122
|
+
const lines = [
|
|
123
|
+
message,
|
|
124
|
+
paint(' Use up/down arrows and Enter to confirm.', ANSI.dim),
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
128
|
+
const option = options[index];
|
|
129
|
+
const suffix = defaultValue === option.value ? ' [default]' : '';
|
|
130
|
+
if (index === selectedIndex) {
|
|
131
|
+
lines.push(` ${paint('//', ANSI.fgAccent, ANSI.bold)} ${paint(option.label + suffix, ANSI.bold)}`);
|
|
132
|
+
} else {
|
|
133
|
+
lines.push(` ${paint(option.label + suffix, ANSI.dim)}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return lines;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function promptSelect(message, options, defaultValue) {
|
|
141
|
+
if (!Array.isArray(options) || options.length === 0) {
|
|
142
|
+
throw new Error('promptSelect requires at least one option.');
|
|
143
|
+
}
|
|
144
|
+
if (!canPromptInteractively()) {
|
|
145
|
+
return defaultValue || options[0].value;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return new Promise((resolvePrompt, rejectPrompt) => {
|
|
149
|
+
const stdin = process.stdin;
|
|
150
|
+
const stdout = process.stdout;
|
|
151
|
+
const defaultIndex = Math.max(0, options.findIndex((option) => option.value === defaultValue));
|
|
152
|
+
const previousRawMode = stdin.isRaw ?? false;
|
|
153
|
+
let selectedIndex = defaultIndex;
|
|
154
|
+
let renderedLines = 0;
|
|
155
|
+
let settled = false;
|
|
156
|
+
|
|
157
|
+
const cleanup = () => {
|
|
158
|
+
if (settled) return;
|
|
159
|
+
settled = true;
|
|
160
|
+
stdin.removeListener('data', onData);
|
|
161
|
+
stdin.removeListener('error', onError);
|
|
162
|
+
if (stdin.isTTY && typeof stdin.setRawMode === 'function') {
|
|
163
|
+
stdin.setRawMode(previousRawMode);
|
|
164
|
+
}
|
|
165
|
+
stdin.pause();
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const render = () => {
|
|
169
|
+
const lines = renderSelectLines(message, options, selectedIndex, defaultValue);
|
|
170
|
+
if (renderedLines > 0) {
|
|
171
|
+
stdout.write(`\u001b[${renderedLines}A`);
|
|
172
|
+
}
|
|
173
|
+
for (const line of lines) {
|
|
174
|
+
stdout.write('\u001b[2K');
|
|
175
|
+
stdout.write(`${line}\n`);
|
|
176
|
+
}
|
|
177
|
+
renderedLines = lines.length;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const onError = (error) => {
|
|
181
|
+
cleanup();
|
|
182
|
+
rejectPrompt(error);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const onData = (chunk) => {
|
|
186
|
+
const input = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
|
|
187
|
+
let delta = 0;
|
|
188
|
+
|
|
189
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
190
|
+
const char = input[index];
|
|
191
|
+
if (char === '\u0003') {
|
|
192
|
+
cleanup();
|
|
193
|
+
stdout.write('\n');
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
if (char === '\r' || char === '\n') {
|
|
197
|
+
cleanup();
|
|
198
|
+
stdout.write('\n');
|
|
199
|
+
resolvePrompt(options[selectedIndex].value);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (input.startsWith('\u001b[A', index)) {
|
|
203
|
+
delta -= 1;
|
|
204
|
+
index += 2;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (input.startsWith('\u001b[B', index)) {
|
|
208
|
+
delta += 1;
|
|
209
|
+
index += 2;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (delta !== 0) {
|
|
215
|
+
selectedIndex = (selectedIndex + delta + options.length) % options.length;
|
|
216
|
+
render();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
if (stdin.isTTY && typeof stdin.setRawMode === 'function') {
|
|
222
|
+
stdin.setRawMode(true);
|
|
223
|
+
}
|
|
224
|
+
stdin.resume();
|
|
225
|
+
stdin.on('data', onData);
|
|
226
|
+
stdin.on('error', onError);
|
|
227
|
+
render();
|
|
228
|
+
} catch (error) {
|
|
229
|
+
onError(error);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export async function promptInput(label) {
|
|
235
|
+
return new Promise((resolve) => {
|
|
236
|
+
const rl = readline.createInterface({
|
|
237
|
+
input: process.stdin,
|
|
238
|
+
output: process.stdout,
|
|
239
|
+
});
|
|
240
|
+
rl.question(`${label}: `, (answer) => {
|
|
241
|
+
rl.close();
|
|
242
|
+
resolve(String(answer || '').trim());
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
const repoRoot = resolve(fileURLToPath(new URL('../../../../..', import.meta.url)));
|
|
7
|
+
const DEFAULT_TEST_FILE = './packages/aurascript/src/cli/test/build-contract.test.mjs';
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
|
|
10
|
+
Object.freeze({
|
|
11
|
+
id: 'web-supported-browser-surface-2d',
|
|
12
|
+
bucket: 'supported',
|
|
13
|
+
expectation: 'supported',
|
|
14
|
+
title: 'browser loader installs the committed 2d surface',
|
|
15
|
+
file: DEFAULT_TEST_FILE,
|
|
16
|
+
testName: 'web loader installs browser-backed aura surface for 2d examples',
|
|
17
|
+
examples: [],
|
|
18
|
+
}),
|
|
19
|
+
Object.freeze({
|
|
20
|
+
id: 'web-supported-render-2d-proof-example',
|
|
21
|
+
bucket: 'supported',
|
|
22
|
+
expectation: 'supported',
|
|
23
|
+
title: 'web-render-2d-proof runs on the committed advanced draw2d browser floor',
|
|
24
|
+
file: DEFAULT_TEST_FILE,
|
|
25
|
+
testName: 'web loader browser smoke: web-render-2d-proof runs on the committed advanced draw2d browser floor',
|
|
26
|
+
examples: ['examples/web-render-2d-proof'],
|
|
27
|
+
}),
|
|
28
|
+
Object.freeze({
|
|
29
|
+
id: 'web-partial-pokemon-style-example',
|
|
30
|
+
bucket: 'partial',
|
|
31
|
+
expectation: 'partial',
|
|
32
|
+
title: 'pokemon-style runs on the current browser-backed subset',
|
|
33
|
+
file: DEFAULT_TEST_FILE,
|
|
34
|
+
testName: 'web loader browser smoke: pokemon-style runs on the supported 2d subset with input and resize evidence',
|
|
35
|
+
examples: ['examples/pokemon-style'],
|
|
36
|
+
}),
|
|
37
|
+
Object.freeze({
|
|
38
|
+
id: 'web-supported-starter-3d-example',
|
|
39
|
+
bucket: 'supported',
|
|
40
|
+
expectation: 'supported',
|
|
41
|
+
title: 'starter-3d runs on the committed browser 3d floor',
|
|
42
|
+
file: DEFAULT_TEST_FILE,
|
|
43
|
+
testName: 'web loader browser smoke: starter-3d runs on the committed browser 3d floor',
|
|
44
|
+
examples: ['examples/starter-3d'],
|
|
45
|
+
}),
|
|
46
|
+
Object.freeze({
|
|
47
|
+
id: 'web-unsupported-multiplayer-examples',
|
|
48
|
+
bucket: 'unsupported',
|
|
49
|
+
expectation: 'unsupported',
|
|
50
|
+
title: 'multiplayer examples fail before setup with stable capability diagnostics',
|
|
51
|
+
file: DEFAULT_TEST_FILE,
|
|
52
|
+
testName: 'web loader browser smoke: multiplayer examples fail before setup with stable capability diagnostics',
|
|
53
|
+
examples: ['examples/multiplayer-room-client', 'examples/multiplayer-room-host'],
|
|
54
|
+
}),
|
|
55
|
+
Object.freeze({
|
|
56
|
+
id: 'web-unsupported-advanced-3d-example',
|
|
57
|
+
bucket: 'unsupported',
|
|
58
|
+
expectation: 'unsupported',
|
|
59
|
+
title: 'advanced 3d examples outside the committed browser floor fail before setup with stable capability diagnostics',
|
|
60
|
+
file: DEFAULT_TEST_FILE,
|
|
61
|
+
testName: 'web loader browser smoke: advanced 3d examples still fail before setup with stable capability diagnostics',
|
|
62
|
+
examples: ['examples/custom-shader-material-proof'],
|
|
63
|
+
}),
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
export class WebConformanceSuiteError extends Error {
|
|
67
|
+
constructor(message, details = {}) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = 'WebConformanceSuiteError';
|
|
70
|
+
this.details = details;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function escapeRegExp(value) {
|
|
75
|
+
return String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function tailLines(value, maxLines = 20) {
|
|
79
|
+
const text = String(value || '').trim();
|
|
80
|
+
if (!text) return '';
|
|
81
|
+
return text.split(/\r?\n/).slice(-maxLines).join('\n');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function summarizeBucket(cases, bucket) {
|
|
85
|
+
const matches = cases.filter((entry) => entry.bucket === bucket);
|
|
86
|
+
return {
|
|
87
|
+
total: matches.length,
|
|
88
|
+
passed: matches.filter((entry) => entry.status === 'passed').length,
|
|
89
|
+
failed: matches.filter((entry) => entry.status === 'failed').length,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function runWebSmokeCase({ cwd, caseDef }) {
|
|
94
|
+
const args = [
|
|
95
|
+
'--test',
|
|
96
|
+
'--test-name-pattern',
|
|
97
|
+
`^${escapeRegExp(caseDef.testName)}$`,
|
|
98
|
+
caseDef.file,
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
102
|
+
const child = spawn(process.execPath, args, {
|
|
103
|
+
cwd,
|
|
104
|
+
env: process.env,
|
|
105
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
let stdout = '';
|
|
109
|
+
let stderr = '';
|
|
110
|
+
|
|
111
|
+
child.stdout.setEncoding('utf8');
|
|
112
|
+
child.stderr.setEncoding('utf8');
|
|
113
|
+
child.stdout.on('data', (chunk) => {
|
|
114
|
+
stdout += chunk;
|
|
115
|
+
});
|
|
116
|
+
child.stderr.on('data', (chunk) => {
|
|
117
|
+
stderr += chunk;
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
child.on('error', (error) => {
|
|
121
|
+
rejectPromise(error);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
child.on('close', (code, signal) => {
|
|
125
|
+
resolvePromise({
|
|
126
|
+
code: Number.isInteger(code) ? code : 1,
|
|
127
|
+
signal: signal || null,
|
|
128
|
+
stdout,
|
|
129
|
+
stderr,
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function runWebConformanceSuite(options = {}) {
|
|
136
|
+
const startedAt = Date.now();
|
|
137
|
+
const cwd = resolve(options.cwd || repoRoot);
|
|
138
|
+
const reportPath = resolve(options.reportPath || cwd, '.aura/web-conformance/report.json');
|
|
139
|
+
const cases = Array.isArray(options.cases) && options.cases.length > 0
|
|
140
|
+
? options.cases
|
|
141
|
+
: DEFAULT_WEB_SMOKE_CASES;
|
|
142
|
+
const runner = typeof options.runner === 'function' ? options.runner : runWebSmokeCase;
|
|
143
|
+
const results = [];
|
|
144
|
+
|
|
145
|
+
mkdirSync(dirname(reportPath), { recursive: true });
|
|
146
|
+
|
|
147
|
+
for (const caseDef of cases) {
|
|
148
|
+
const caseStartedAt = Date.now();
|
|
149
|
+
const execution = await runner({ cwd, caseDef });
|
|
150
|
+
const durationMs = Date.now() - caseStartedAt;
|
|
151
|
+
const passed = execution.code === 0;
|
|
152
|
+
|
|
153
|
+
results.push({
|
|
154
|
+
id: caseDef.id,
|
|
155
|
+
title: caseDef.title,
|
|
156
|
+
bucket: caseDef.bucket,
|
|
157
|
+
expectation: caseDef.expectation,
|
|
158
|
+
file: caseDef.file,
|
|
159
|
+
testName: caseDef.testName,
|
|
160
|
+
examples: Array.isArray(caseDef.examples) ? caseDef.examples : [],
|
|
161
|
+
status: passed ? 'passed' : 'failed',
|
|
162
|
+
durationMs,
|
|
163
|
+
stdoutTail: tailLines(execution.stdout),
|
|
164
|
+
stderrTail: tailLines(execution.stderr),
|
|
165
|
+
error: passed
|
|
166
|
+
? null
|
|
167
|
+
: {
|
|
168
|
+
message: `Web smoke case failed: ${caseDef.id}`,
|
|
169
|
+
exitCode: execution.code,
|
|
170
|
+
signal: execution.signal,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const durationMs = Date.now() - startedAt;
|
|
176
|
+
const summary = {
|
|
177
|
+
total: results.length,
|
|
178
|
+
passed: results.filter((entry) => entry.status === 'passed').length,
|
|
179
|
+
failed: results.filter((entry) => entry.status === 'failed').length,
|
|
180
|
+
durationMs,
|
|
181
|
+
byMode: {
|
|
182
|
+
web: {
|
|
183
|
+
total: results.length,
|
|
184
|
+
passed: results.filter((entry) => entry.status === 'passed').length,
|
|
185
|
+
failed: results.filter((entry) => entry.status === 'failed').length,
|
|
186
|
+
durationMs,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
byBucket: {
|
|
190
|
+
supported: summarizeBucket(results, 'supported'),
|
|
191
|
+
partial: summarizeBucket(results, 'partial'),
|
|
192
|
+
unsupported: summarizeBucket(results, 'unsupported'),
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const report = {
|
|
197
|
+
schemaVersion: 'aurajs.web-conformance-report.v1',
|
|
198
|
+
generatedAt: new Date().toISOString(),
|
|
199
|
+
mode: 'web',
|
|
200
|
+
cwd,
|
|
201
|
+
reportPath,
|
|
202
|
+
summary,
|
|
203
|
+
cases: results,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
|
|
207
|
+
|
|
208
|
+
if (summary.failed > 0) {
|
|
209
|
+
throw new WebConformanceSuiteError(
|
|
210
|
+
`Web conformance failed for ${summary.failed}/${summary.total} browser smoke cases.`,
|
|
211
|
+
{
|
|
212
|
+
reportPath,
|
|
213
|
+
failedCases: results.filter((entry) => entry.status === 'failed'),
|
|
214
|
+
},
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return report;
|
|
219
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const SHOOTER_CONFIG = Object.freeze({
|
|
2
|
+
playerWidth: 34,
|
|
3
|
+
playerHeight: 26,
|
|
4
|
+
playerSpeed: 420,
|
|
5
|
+
bulletWidth: 6,
|
|
6
|
+
bulletHeight: 14,
|
|
7
|
+
bulletSpeed: 640,
|
|
8
|
+
shootCooldownSeconds: 0.14,
|
|
9
|
+
playerStartOffsetY: 70,
|
|
10
|
+
betweenWaveDelaySeconds: 1.0,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const SHOOTER_WAVES = Object.freeze([
|
|
14
|
+
Object.freeze({ maxSpawns: 9, spawnEvery: 0.62, archetype: 'scout', speedScale: 1.0 }),
|
|
15
|
+
Object.freeze({ maxSpawns: 10, spawnEvery: 0.56, archetype: 'striker', speedScale: 1.06 }),
|
|
16
|
+
Object.freeze({ maxSpawns: 8, spawnEvery: 0.74, archetype: 'tank', speedScale: 1.02 }),
|
|
17
|
+
Object.freeze({ maxSpawns: 12, spawnEvery: 0.48, archetype: null, speedScale: 1.12 }),
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
export const SHOOTER_TEXT = Object.freeze({
|
|
21
|
+
started: '{{PROJECT_TITLE}} started (2D shooter template)',
|
|
22
|
+
controls: 'Move: Arrows/WASD Fire: Space/Z',
|
|
23
|
+
gameOverTitle: 'GAME OVER',
|
|
24
|
+
gameOverPrompt: 'Press Enter to restart',
|
|
25
|
+
waveDone: 'Done',
|
|
26
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "aurajs.wave-plan.v1",
|
|
3
|
+
"waves": [
|
|
4
|
+
{
|
|
5
|
+
"id": "intro",
|
|
6
|
+
"maxSpawns": 9,
|
|
7
|
+
"spawnEvery": 0.62,
|
|
8
|
+
"archetype": "scout",
|
|
9
|
+
"speedScale": 1
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "pressure",
|
|
13
|
+
"maxSpawns": 10,
|
|
14
|
+
"spawnEvery": 0.56,
|
|
15
|
+
"archetype": "striker",
|
|
16
|
+
"speedScale": 1.06
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "anchor",
|
|
20
|
+
"maxSpawns": 8,
|
|
21
|
+
"spawnEvery": 0.74,
|
|
22
|
+
"archetype": "tank",
|
|
23
|
+
"speedScale": 1.02
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# 2D Shooter Loop
|
|
2
|
+
|
|
3
|
+
1. Survive the wave set, clear the arena, and keep the score-and-lives loop readable.
|
|
4
|
+
1. Keep tuning in `config/gameplay/shooter.config.js`, authored wave payloads in `content/gameplay/waves.json`, and reusable combat pieces in `prefabs/`.
|
|
5
|
+
1. Extend from here with enemy families, weapon rules, and HUD beats before layering on heavier meta systems.
|