@auraindustry/aurajs 0.1.3 → 0.1.5
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 +7 -0
- package/benchmarks/perf-thresholds.json +27 -0
- package/package.json +6 -1
- package/src/ai-guidance.mjs +302 -0
- package/src/authored-project.mjs +498 -2
- package/src/build-contract/capabilities.mjs +87 -1
- package/src/build-contract/constants.mjs +1 -0
- package/src/build-contract.mjs +2 -0
- package/src/bundler.mjs +143 -13
- package/src/cli.mjs +681 -13
- package/src/commands/packs.mjs +741 -0
- package/src/commands/project-authoring.mjs +128 -1
- package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
- package/src/conformance/cases/core-runtime-cases.mjs +6 -2
- package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
- package/src/conformance/cases/systems-and-gameplay-cases.mjs +265 -4
- package/src/conformance-mobile.mjs +166 -0
- package/src/conformance.mjs +89 -30
- package/src/evidence-bundle.mjs +242 -0
- package/src/headless-test/runtime-coordinator.mjs +186 -33
- package/src/headless-test.mjs +2 -0
- package/src/helpers/2d/index.mjs +183 -0
- package/src/helpers/index.mjs +26 -0
- package/src/helpers/starter-utils/adventure-objectives.js +102 -0
- package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
- package/src/helpers/starter-utils/animation-2d.js +337 -0
- package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
- package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
- package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
- package/src/helpers/starter-utils/avatar-3d.js +404 -0
- package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
- package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
- package/src/helpers/starter-utils/core.js +150 -0
- package/src/helpers/starter-utils/dialogue-2d.js +351 -0
- package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
- package/src/helpers/starter-utils/index.js +26 -0
- package/src/helpers/starter-utils/inventory-2d.js +268 -0
- package/src/helpers/starter-utils/journal-2d.js +267 -0
- package/src/helpers/starter-utils/platformer-3d.js +132 -0
- package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
- package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
- package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
- package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
- package/src/helpers/starter-utils/triggers.js +662 -0
- package/src/helpers/starter-utils/tween-2d.js +615 -0
- package/src/helpers/starter-utils/wave-director.js +101 -0
- package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
- package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
- package/src/mobile/android/build.mjs +606 -0
- package/src/mobile/android/host-artifact.mjs +280 -0
- package/src/mobile/ios/build.mjs +1323 -0
- package/src/mobile/ios/host-artifact.mjs +819 -0
- package/src/mobile/shared/capabilities.mjs +174 -0
- package/src/packs/catalog.mjs +259 -0
- package/src/perf-benchmark-runner.mjs +17 -12
- package/src/perf-benchmark.mjs +408 -4
- package/src/publish-command.mjs +303 -6
- package/src/replay-runtime.mjs +257 -0
- package/src/scaffold/config.mjs +2 -0
- package/src/scaffold/fs.mjs +8 -1
- package/src/scaffold/project-docs.mjs +43 -1
- package/src/scaffold.mjs +4 -0
- package/src/session-runtime.mjs +4 -3
- package/src/web-conformance.mjs +0 -36
- package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
- package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
- package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
- package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
- package/templates/create/2d-adventure/docs/design/loop.md +4 -3
- package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
- package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
- package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
- package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
- package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
- package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
- package/templates/create/3d/scenes/gameplay.scene.js +30 -3
- package/templates/create/3d/src/runtime/capabilities.js +5 -0
- package/templates/create/3d/src/runtime/materials.js +10 -0
- package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
- package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
- package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
- package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
- package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
- package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
- package/templates/create/shared/src/runtime/ui-forms.js +552 -0
- package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
- package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
- package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
- package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
- package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
- package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
- package/templates/create/shared/src/starter-utils/index.js +15 -1
- package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
- package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
- package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
- package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
- package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
- package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
- package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
- package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
- package/templates/create-bin/play.js +36 -7
- package/templates/skills/auramaxx/SKILL.md +46 -0
- package/templates/skills/auramaxx/project-requirements.md +68 -0
- package/templates/skills/auramaxx/starter-recipes.md +104 -0
- package/templates/skills/auramaxx/validation-checklist.md +49 -0
- package/templates/skills/aurajs/SKILL.md +0 -96
- package/templates/skills/aurajs/api-contract-3d.md +0 -7
- package/templates/skills/aurajs/api-contract.md +0 -7
package/src/cli.mjs
CHANGED
|
@@ -28,15 +28,24 @@ import {
|
|
|
28
28
|
MAKE_SUPPORTED_KINDS_HELP_TEXT,
|
|
29
29
|
MAKE_USAGE,
|
|
30
30
|
PREFAB_ROLE_OPTION_LIST,
|
|
31
|
+
VENDOR_USAGE,
|
|
31
32
|
cmdCheck,
|
|
32
33
|
cmdCreate,
|
|
33
34
|
cmdExplain,
|
|
34
35
|
cmdFrom,
|
|
35
36
|
cmdInit,
|
|
36
37
|
cmdMake,
|
|
38
|
+
cmdVendor,
|
|
37
39
|
} from './commands/project-authoring.mjs';
|
|
40
|
+
import { PACKS_USAGE, cmdPacks } from './commands/packs.mjs';
|
|
38
41
|
import { packageAssets } from './asset-pack.mjs';
|
|
39
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
buildRuntimeConfig,
|
|
44
|
+
readProjectCapabilityDeclaration,
|
|
45
|
+
writeBuildManifest,
|
|
46
|
+
writeCanonicalJsonFile,
|
|
47
|
+
writeWebBuildArtifacts,
|
|
48
|
+
} from './build-contract.mjs';
|
|
40
49
|
import { discoverProjectIconPath, SUPPORTED_BUILD_ICON_EXTENSIONS } from './icon-discovery.mjs';
|
|
41
50
|
import { runPublishCommand } from './publish-command.mjs';
|
|
42
51
|
import { runExternalAssetsCommand } from './self-hosted-assets.mjs';
|
|
@@ -55,6 +64,10 @@ import {
|
|
|
55
64
|
} from './headless-action.mjs';
|
|
56
65
|
import { loadConfig, ConfigError } from './config.mjs';
|
|
57
66
|
import { ensureHostBinaryAvailable, HostBinaryResolutionError } from './host-binary.mjs';
|
|
67
|
+
import { buildAndroidArtifacts, stageAndroidProject } from './mobile/android/build.mjs';
|
|
68
|
+
import { produceAndroidHostArtifact } from './mobile/android/host-artifact.mjs';
|
|
69
|
+
import { buildIosArtifacts, stageIosProject } from './mobile/ios/build.mjs';
|
|
70
|
+
import { produceIosHostArtifact } from './mobile/ios/host-artifact.mjs';
|
|
58
71
|
import { runConformanceCommand } from './conformance-runner.mjs';
|
|
59
72
|
import { buildRuntimeInspectorSnapshotReport } from './conformance.mjs';
|
|
60
73
|
import {
|
|
@@ -113,6 +126,16 @@ import {
|
|
|
113
126
|
writeSessionRegistry,
|
|
114
127
|
} from './session-client.mjs';
|
|
115
128
|
import { GAME_ACTION_REQUEST_SCHEMA_VERSION } from './game-action-runtime.mjs';
|
|
129
|
+
import {
|
|
130
|
+
captureHeadlessEvidenceBundle,
|
|
131
|
+
EvidenceBundleError,
|
|
132
|
+
serializeEvidenceManifest,
|
|
133
|
+
} from './evidence-bundle.mjs';
|
|
134
|
+
import {
|
|
135
|
+
ReplayError,
|
|
136
|
+
runHeadlessReplay,
|
|
137
|
+
serializeReplayReport,
|
|
138
|
+
} from './replay-runtime.mjs';
|
|
116
139
|
|
|
117
140
|
// ---------------------------------------------------------------------------
|
|
118
141
|
// Version
|
|
@@ -192,6 +215,35 @@ const COMMANDS = {
|
|
|
192
215
|
' - This is an authoring command on `aura`, not a generated game-wrapper verb.',
|
|
193
216
|
],
|
|
194
217
|
},
|
|
218
|
+
vendor: {
|
|
219
|
+
description: 'Vendor supported helper files into the current AuraJS project',
|
|
220
|
+
usage: VENDOR_USAGE,
|
|
221
|
+
details: [
|
|
222
|
+
' Notes:',
|
|
223
|
+
' - `aura vendor helpers` seeds the packaged starter helper copies into src/starter-utils/.',
|
|
224
|
+
' - Re-run with `--force` to overwrite local helper files and resync them to the packaged version.',
|
|
225
|
+
' - Use `--json` when you want machine-readable created/overwritten/skipped file lists.',
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
packs: {
|
|
229
|
+
description: 'List and register optional AuraJS packs and bundles',
|
|
230
|
+
usage: PACKS_USAGE,
|
|
231
|
+
details: [
|
|
232
|
+
' Subcommands:',
|
|
233
|
+
' list [--json] List known optional packs and bundles',
|
|
234
|
+
' show <id> [--json] Show one pack or bundle entry',
|
|
235
|
+
' add <id> [--source package|workspace] [--install] Register one pack or bundle in the current AuraJS project',
|
|
236
|
+
' vendor <id> [--source auto|workspace|installed|github] [--ref <git-ref>] [--force] Copy pack payloads into the project',
|
|
237
|
+
'',
|
|
238
|
+
' Notes:',
|
|
239
|
+
' - `aura packs add` writes optional package dependencies plus aura.packs.json metadata.',
|
|
240
|
+
' - `--workspace` uses local file: specs that point at pack packages in the AuraJS source checkout.',
|
|
241
|
+
' - `aura packs vendor` is the editable-content lane: it copies pack payloads into project-local folders such as content/, docs/, or assets/.',
|
|
242
|
+
' - `--source github` on vendor fetches the pack archive from its registered GitHub repo/ref and vendors from that payload.',
|
|
243
|
+
' - `--install` runs `npm install` after package.json and aura.packs.json are updated.',
|
|
244
|
+
' - Bundles expand to their member packs so AI/project introspection can see the concrete installed lanes.',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
195
247
|
explain: {
|
|
196
248
|
description: 'Explain how the current AuraJS project is wired',
|
|
197
249
|
usage: 'aura explain [--json]',
|
|
@@ -233,15 +285,17 @@ const COMMANDS = {
|
|
|
233
285
|
},
|
|
234
286
|
build: {
|
|
235
287
|
description: 'Build release artifacts (native or web)',
|
|
236
|
-
usage: 'aura build [--target <windows|mac|linux|all|web|gb|gbc|gba>] [--asset-mode <embed|sibling>]',
|
|
288
|
+
usage: 'aura build [--target <windows|mac|linux|all|web|android|ios|mobile|gb|gbc|gba>] [--asset-mode <embed|sibling>]',
|
|
237
289
|
details: [
|
|
238
290
|
' Options:',
|
|
239
|
-
' --target <windows|mac|linux|all|web|gb|gbc|gba> Build target',
|
|
291
|
+
' --target <windows|mac|linux|all|web|android|ios|mobile|gb|gbc|gba> Build target',
|
|
240
292
|
' --asset-mode <embed|sibling> Package assets in pak or sibling assets/',
|
|
241
293
|
'',
|
|
242
294
|
' Notes:',
|
|
243
295
|
' - `--target web` emits browser artifacts under `build/web` for the current browser-backed subset.',
|
|
244
296
|
' - Native targets are current host only in v1.',
|
|
297
|
+
' - `--target android|ios|mobile` produces host artifacts, stages mobile package roots, and runs Gradle/Xcode export when prerequisites are present; otherwise manifests stay reason-coded and staged.',
|
|
298
|
+
' - Mobile targets require `--asset-mode embed` in v1.',
|
|
245
299
|
' - `--target all` keeps current host output; use CI matrix for all platforms.',
|
|
246
300
|
' - Browser runtime truth today: current 2D/input/assets/storage path is supported; `aura.state` and `aura.net` remain reason-coded unsupported.',
|
|
247
301
|
' - `--target gb|gbc|gba` routes through the Aura Retro lane under `src/cli/src/retro` and writes cartridge-oriented artifacts under `build/<target>`.',
|
|
@@ -280,10 +334,14 @@ const COMMANDS = {
|
|
|
280
334
|
},
|
|
281
335
|
publish: {
|
|
282
336
|
description: 'Publish the current game package through npm',
|
|
283
|
-
usage: 'aura publish [--dry-run] [npm publish options]',
|
|
337
|
+
usage: 'aura publish [--dry-run] [--name <package>] [--version <semver>] [--yes] [npm publish options]',
|
|
284
338
|
details: [
|
|
285
339
|
' Notes:',
|
|
286
340
|
' - `aura publish` is the canonical npm-first publish lane for game projects.',
|
|
341
|
+
' - Interactive terminals can keep or update package.json name/version before publish.',
|
|
342
|
+
' - `--name <package>` sets the package name before validation and publish.',
|
|
343
|
+
' - `--version <semver>` sets the package version before validation and publish.',
|
|
344
|
+
' - `--yes` skips the prompt and uses current package metadata.',
|
|
287
345
|
' - Scoped package names default to `--access public` unless explicitly overridden.',
|
|
288
346
|
' - npm publish lifecycle recursion is skipped cleanly instead of re-entering the command.',
|
|
289
347
|
' - For oversized payloads, generate self-hosted metadata with `aura external-assets generate` after you upload assets to your own HTTPS host.',
|
|
@@ -315,6 +373,49 @@ const COMMANDS = {
|
|
|
315
373
|
},
|
|
316
374
|
clean: { description: 'Delete build artifacts', usage: 'aura clean' },
|
|
317
375
|
test: { description: 'Run game logic in headless mode', usage: 'aura test [file] [--width N] [--height N] [--frames N]' },
|
|
376
|
+
evidence: {
|
|
377
|
+
description: 'Capture one headless evidence bundle for the current authored project',
|
|
378
|
+
usage: 'aura evidence [file] [--replay <replay.json>] [--frames N] [--width N] [--height N] [--out-dir <path>] [--output <path|->]',
|
|
379
|
+
details: [
|
|
380
|
+
' Options:',
|
|
381
|
+
' --replay <replay.json> Execute one deterministic replay before capture and include replay artifacts',
|
|
382
|
+
' --frames <N> Number of lifecycle frames to execute before capture (or after replay when --replay is set)',
|
|
383
|
+
' --width <N> Override headless viewport width',
|
|
384
|
+
' --height <N> Override headless viewport height',
|
|
385
|
+
' --out-dir <path> Directory for manifest.json, summary.json, state.json, inspect.json, perf.json, and optional replay artifacts',
|
|
386
|
+
' --output <path|-> Write the manifest JSON to file (or "-" for stdout)',
|
|
387
|
+
' --compact Compact manifest JSON output (single line)',
|
|
388
|
+
' --pretty Pretty manifest JSON output (default)',
|
|
389
|
+
' --file <path> Override entry file (default: build.entry from config)',
|
|
390
|
+
'',
|
|
391
|
+
' Notes:',
|
|
392
|
+
' - This is headless-first and currently captures one combined evidence bundle per run.',
|
|
393
|
+
' - The bundle writes manifest.json, summary.json, state.json, inspect.json, and perf.json under --out-dir.',
|
|
394
|
+
' - When --replay is set, the bundle also writes replay.json and replay-report.json.',
|
|
395
|
+
],
|
|
396
|
+
},
|
|
397
|
+
replay: {
|
|
398
|
+
description: 'Run one deterministic headless replay against the current authored project',
|
|
399
|
+
usage: 'aura replay run <replay.json> [--output <path|->] [--state-output <path|->] [--file <path>] [--width N] [--height N] [--compact]',
|
|
400
|
+
details: [
|
|
401
|
+
' Subcommands:',
|
|
402
|
+
' run <replay.json> Execute one headless replay payload with deterministic input injection',
|
|
403
|
+
'',
|
|
404
|
+
' Options:',
|
|
405
|
+
' run:',
|
|
406
|
+
' --output <path|-> Write replay report JSON to file (or "-" for stdout)',
|
|
407
|
+
' --state-output <path|-> Write final canonical state payload to file (or "-" for stdout)',
|
|
408
|
+
' --file <path> Override entry file (default: build.entry from config)',
|
|
409
|
+
' --width <N> Override headless viewport width',
|
|
410
|
+
' --height <N> Override headless viewport height',
|
|
411
|
+
' --compact Compact JSON output (single line)',
|
|
412
|
+
' --pretty Pretty JSON output (default)',
|
|
413
|
+
'',
|
|
414
|
+
' Notes:',
|
|
415
|
+
' - Replay is headless-first today and uses deterministic input injection plus optional fingerprint checkpoints.',
|
|
416
|
+
' - Use `expectFingerprint` checkpoints inside the replay payload to stop on divergence.',
|
|
417
|
+
],
|
|
418
|
+
},
|
|
318
419
|
conformance: { description: 'Run API conformance suites in headless mode', usage: 'aura conformance [--mode shim|native|both] [--json]' },
|
|
319
420
|
state: {
|
|
320
421
|
description: 'Export, diff, and patch canonical game-state snapshots',
|
|
@@ -518,7 +619,16 @@ if (HAS_AURAPM_PREVIEW) {
|
|
|
518
619
|
};
|
|
519
620
|
}
|
|
520
621
|
|
|
521
|
-
const
|
|
622
|
+
const SUPPORTED_MOBILE_BUILD_TARGETS = new Set(['android', 'ios', 'mobile']);
|
|
623
|
+
const SUPPORTED_BUILD_TARGETS = new Set([
|
|
624
|
+
'windows',
|
|
625
|
+
'mac',
|
|
626
|
+
'linux',
|
|
627
|
+
'all',
|
|
628
|
+
'web',
|
|
629
|
+
...SUPPORTED_MOBILE_BUILD_TARGETS,
|
|
630
|
+
...SUPPORTED_RETRO_BUILD_TARGETS,
|
|
631
|
+
]);
|
|
522
632
|
const SUPPORTED_STATE_EXPORT_MODES = new Set(['headless', 'native', 'shim']);
|
|
523
633
|
const STATE_MUTATION_AUDIT_SCHEMA_VERSION = 'aurajs.state-mutation-audit.v1';
|
|
524
634
|
const WEB_DEV_REFRESH_SIGNAL_SCHEMA = 'aurajs.web-dev-refresh.v1';
|
|
@@ -557,6 +667,7 @@ function printHelp() {
|
|
|
557
667
|
' create Scaffold a new game project',
|
|
558
668
|
' from Convert a supported foreign project into a new AuraJS project',
|
|
559
669
|
' make Generate authored project files from templates',
|
|
670
|
+
' vendor Vendor supported helper files into the current project',
|
|
560
671
|
' explain Explain how the current project is wired',
|
|
561
672
|
' check Validate authored project wiring',
|
|
562
673
|
' play Start the game with a live dev session',
|
|
@@ -636,6 +747,10 @@ function currentPlatformTarget() {
|
|
|
636
747
|
return 'linux';
|
|
637
748
|
}
|
|
638
749
|
|
|
750
|
+
function isMobileBuildTarget(target) {
|
|
751
|
+
return SUPPORTED_MOBILE_BUILD_TARGETS.has(target);
|
|
752
|
+
}
|
|
753
|
+
|
|
639
754
|
function parseAssetMode(args) {
|
|
640
755
|
for (let i = 0; i < args.length; i += 1) {
|
|
641
756
|
if (args[i] === '--asset-mode' && args[i + 1]) {
|
|
@@ -772,6 +887,260 @@ function parseStateExportArgs(args) {
|
|
|
772
887
|
return parsed;
|
|
773
888
|
}
|
|
774
889
|
|
|
890
|
+
function parseEvidenceArgs(args) {
|
|
891
|
+
const parsed = {
|
|
892
|
+
file: null,
|
|
893
|
+
replayPath: null,
|
|
894
|
+
frames: 1,
|
|
895
|
+
width: null,
|
|
896
|
+
height: null,
|
|
897
|
+
outDir: resolve(process.cwd(), '.aura/evidence/latest'),
|
|
898
|
+
outputPath: null,
|
|
899
|
+
compact: false,
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
let positionalFileSeen = false;
|
|
903
|
+
let formattingFlag = 'pretty';
|
|
904
|
+
let framesSpecified = false;
|
|
905
|
+
|
|
906
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
907
|
+
const token = args[i];
|
|
908
|
+
|
|
909
|
+
if (token === '--frames') {
|
|
910
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--frames', 'invalid_evidence_args');
|
|
911
|
+
parsed.frames = parseNonNegativeIntegerArg(value, '--frames', 'invalid_evidence_args');
|
|
912
|
+
framesSpecified = true;
|
|
913
|
+
i += 1;
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
if (token.startsWith('--frames=')) {
|
|
917
|
+
parsed.frames = parseNonNegativeIntegerArg(token.slice('--frames='.length), '--frames', 'invalid_evidence_args');
|
|
918
|
+
framesSpecified = true;
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
if (token === '--replay') {
|
|
923
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--replay', 'invalid_evidence_args');
|
|
924
|
+
parsed.replayPath = normalizeStateCommandInputPath(value, 'replay', 'invalid_evidence_args');
|
|
925
|
+
i += 1;
|
|
926
|
+
continue;
|
|
927
|
+
}
|
|
928
|
+
if (token.startsWith('--replay=')) {
|
|
929
|
+
parsed.replayPath = normalizeStateCommandInputPath(token.slice('--replay='.length), 'replay', 'invalid_evidence_args');
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
if (token === '--width') {
|
|
934
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--width', 'invalid_evidence_args');
|
|
935
|
+
parsed.width = parsePositiveIntegerArg(value, '--width', 'invalid_evidence_args');
|
|
936
|
+
i += 1;
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
if (token.startsWith('--width=')) {
|
|
940
|
+
parsed.width = parsePositiveIntegerArg(token.slice('--width='.length), '--width', 'invalid_evidence_args');
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
if (token === '--height') {
|
|
945
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--height', 'invalid_evidence_args');
|
|
946
|
+
parsed.height = parsePositiveIntegerArg(value, '--height', 'invalid_evidence_args');
|
|
947
|
+
i += 1;
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
950
|
+
if (token.startsWith('--height=')) {
|
|
951
|
+
parsed.height = parsePositiveIntegerArg(token.slice('--height='.length), '--height', 'invalid_evidence_args');
|
|
952
|
+
continue;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
if (token === '--out-dir') {
|
|
956
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--out-dir', 'invalid_evidence_args');
|
|
957
|
+
parsed.outDir = resolve(process.cwd(), value);
|
|
958
|
+
i += 1;
|
|
959
|
+
continue;
|
|
960
|
+
}
|
|
961
|
+
if (token.startsWith('--out-dir=')) {
|
|
962
|
+
parsed.outDir = resolve(process.cwd(), token.slice('--out-dir='.length));
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
if (token === '--output' || token === '--out') {
|
|
967
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, token, 'invalid_evidence_args');
|
|
968
|
+
parsed.outputPath = normalizeStateExportOutput(value);
|
|
969
|
+
i += 1;
|
|
970
|
+
continue;
|
|
971
|
+
}
|
|
972
|
+
if (token.startsWith('--output=')) {
|
|
973
|
+
parsed.outputPath = normalizeStateExportOutput(token.slice('--output='.length));
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
if (token.startsWith('--out=')) {
|
|
977
|
+
parsed.outputPath = normalizeStateExportOutput(token.slice('--out='.length));
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
if (token === '--compact') {
|
|
982
|
+
if (formattingFlag === 'pretty') {
|
|
983
|
+
parsed.compact = true;
|
|
984
|
+
formattingFlag = 'compact';
|
|
985
|
+
continue;
|
|
986
|
+
}
|
|
987
|
+
if (formattingFlag === 'compact') {
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
throw new StateExportError('invalid_evidence_args', 'Cannot use --compact and --pretty together.');
|
|
991
|
+
}
|
|
992
|
+
if (token === '--pretty') {
|
|
993
|
+
if (formattingFlag === 'compact') {
|
|
994
|
+
throw new StateExportError('invalid_evidence_args', 'Cannot use --compact and --pretty together.');
|
|
995
|
+
}
|
|
996
|
+
parsed.compact = false;
|
|
997
|
+
formattingFlag = 'pretty';
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
if (token === '--file') {
|
|
1002
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--file', 'invalid_evidence_args');
|
|
1003
|
+
parsed.file = normalizeStateExportFile(value);
|
|
1004
|
+
i += 1;
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
if (token.startsWith('--file=')) {
|
|
1008
|
+
parsed.file = normalizeStateExportFile(token.slice('--file='.length));
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (token.startsWith('--')) {
|
|
1013
|
+
throw new StateExportError('invalid_evidence_args', `Unknown evidence option: ${token}`);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
if (positionalFileSeen) {
|
|
1017
|
+
throw new StateExportError('invalid_evidence_args', `Unexpected argument: ${token}`);
|
|
1018
|
+
}
|
|
1019
|
+
positionalFileSeen = true;
|
|
1020
|
+
parsed.file = normalizeStateExportFile(token);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
if (parsed.replayPath && framesSpecified !== true) {
|
|
1024
|
+
parsed.frames = 0;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
return parsed;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
function parseReplayRunArgs(args) {
|
|
1031
|
+
const parsed = {
|
|
1032
|
+
replayPath: null,
|
|
1033
|
+
file: null,
|
|
1034
|
+
width: null,
|
|
1035
|
+
height: null,
|
|
1036
|
+
outputPath: null,
|
|
1037
|
+
stateOutputPath: null,
|
|
1038
|
+
compact: false,
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
let formattingFlag = 'pretty';
|
|
1042
|
+
|
|
1043
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
1044
|
+
const token = args[i];
|
|
1045
|
+
|
|
1046
|
+
if (token === '--output' || token === '--out') {
|
|
1047
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, token, 'invalid_replay_args');
|
|
1048
|
+
parsed.outputPath = normalizeStateExportOutput(value);
|
|
1049
|
+
i += 1;
|
|
1050
|
+
continue;
|
|
1051
|
+
}
|
|
1052
|
+
if (token.startsWith('--output=')) {
|
|
1053
|
+
parsed.outputPath = normalizeStateExportOutput(token.slice('--output='.length));
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
if (token.startsWith('--out=')) {
|
|
1057
|
+
parsed.outputPath = normalizeStateExportOutput(token.slice('--out='.length));
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
if (token === '--state-output') {
|
|
1062
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--state-output', 'invalid_replay_args');
|
|
1063
|
+
parsed.stateOutputPath = normalizeStateExportOutput(value);
|
|
1064
|
+
i += 1;
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
if (token.startsWith('--state-output=')) {
|
|
1068
|
+
parsed.stateOutputPath = normalizeStateExportOutput(token.slice('--state-output='.length));
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
if (token === '--file') {
|
|
1073
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--file', 'invalid_replay_args');
|
|
1074
|
+
parsed.file = normalizeStateExportFile(value);
|
|
1075
|
+
i += 1;
|
|
1076
|
+
continue;
|
|
1077
|
+
}
|
|
1078
|
+
if (token.startsWith('--file=')) {
|
|
1079
|
+
parsed.file = normalizeStateExportFile(token.slice('--file='.length));
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
if (token === '--width') {
|
|
1084
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--width', 'invalid_replay_args');
|
|
1085
|
+
parsed.width = parsePositiveIntegerArg(value, '--width', 'invalid_replay_args');
|
|
1086
|
+
i += 1;
|
|
1087
|
+
continue;
|
|
1088
|
+
}
|
|
1089
|
+
if (token.startsWith('--width=')) {
|
|
1090
|
+
parsed.width = parsePositiveIntegerArg(token.slice('--width='.length), '--width', 'invalid_replay_args');
|
|
1091
|
+
continue;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
if (token === '--height') {
|
|
1095
|
+
const value = readRequiredOptionValueWithReasonCode(args, i, '--height', 'invalid_replay_args');
|
|
1096
|
+
parsed.height = parsePositiveIntegerArg(value, '--height', 'invalid_replay_args');
|
|
1097
|
+
i += 1;
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
if (token.startsWith('--height=')) {
|
|
1101
|
+
parsed.height = parsePositiveIntegerArg(token.slice('--height='.length), '--height', 'invalid_replay_args');
|
|
1102
|
+
continue;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
if (token === '--compact') {
|
|
1106
|
+
if (formattingFlag === 'pretty') {
|
|
1107
|
+
parsed.compact = true;
|
|
1108
|
+
formattingFlag = 'compact';
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
if (formattingFlag === 'compact') {
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1114
|
+
throw new StateExportError('invalid_replay_args', 'Cannot use --compact and --pretty together.');
|
|
1115
|
+
}
|
|
1116
|
+
if (token === '--pretty') {
|
|
1117
|
+
if (formattingFlag === 'compact') {
|
|
1118
|
+
throw new StateExportError('invalid_replay_args', 'Cannot use --compact and --pretty together.');
|
|
1119
|
+
}
|
|
1120
|
+
parsed.compact = false;
|
|
1121
|
+
formattingFlag = 'pretty';
|
|
1122
|
+
continue;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
if (token.startsWith('--')) {
|
|
1126
|
+
throw new StateExportError('invalid_replay_args', `Unknown replay option: ${token}`);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
if (parsed.replayPath === null) {
|
|
1130
|
+
parsed.replayPath = normalizeStateCommandInputPath(token, 'replay', 'invalid_replay_args');
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
throw new StateExportError('invalid_replay_args', `Unexpected argument: ${token}`);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
if (!parsed.replayPath) {
|
|
1138
|
+
throw new StateExportError('invalid_replay_args', 'Replay run requires a replay JSON path.');
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
return parsed;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
775
1144
|
function parseStateDiffArgs(args) {
|
|
776
1145
|
const parsed = {
|
|
777
1146
|
beforePath: null,
|
|
@@ -2757,10 +3126,7 @@ function parseDevArgs(args) {
|
|
|
2757
3126
|
|
|
2758
3127
|
function normalizeDevTarget(value) {
|
|
2759
3128
|
const normalized = String(value || '').trim().toLowerCase();
|
|
2760
|
-
if (normalized === 'macos' || normalized === 'darwin' || normalized === 'mac') return 'mac';
|
|
2761
|
-
if (normalized === 'win' || normalized === 'win32' || normalized === 'windows') return 'windows';
|
|
2762
3129
|
if (normalized === 'browser' || normalized === 'web') return 'web';
|
|
2763
|
-
if (normalized === 'linux') return 'linux';
|
|
2764
3130
|
throw new StateExportError(
|
|
2765
3131
|
'invalid_dev_args',
|
|
2766
3132
|
`Unsupported dev target "${value}". Supported values: web.`,
|
|
@@ -3438,6 +3804,96 @@ function resolveBuildIdentity(config) {
|
|
|
3438
3804
|
};
|
|
3439
3805
|
}
|
|
3440
3806
|
|
|
3807
|
+
function sanitizeMobileIdentifierFragment(value, fallback = 'game') {
|
|
3808
|
+
const normalized = String(value || '')
|
|
3809
|
+
.trim()
|
|
3810
|
+
.toLowerCase()
|
|
3811
|
+
.replace(/[^a-z0-9]+/g, '');
|
|
3812
|
+
return normalized.length > 0 ? normalized : fallback;
|
|
3813
|
+
}
|
|
3814
|
+
|
|
3815
|
+
function resolveAndroidBuildIdentity(identity) {
|
|
3816
|
+
const slug = sanitizeExecutableBaseName(identity.executableBaseName || 'game').toLowerCase();
|
|
3817
|
+
return {
|
|
3818
|
+
name: identity.name,
|
|
3819
|
+
slug,
|
|
3820
|
+
applicationId: process.env.AURA_ANDROID_APPLICATION_ID
|
|
3821
|
+
|| `dev.aurajs.${sanitizeMobileIdentifierFragment(slug)}`,
|
|
3822
|
+
versionCode: Number.parseInt(process.env.AURA_ANDROID_VERSION_CODE || '1', 10) || 1,
|
|
3823
|
+
versionName: process.env.AURA_ANDROID_VERSION_NAME || identity.version,
|
|
3824
|
+
};
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3827
|
+
function resolveIosBuildIdentity(identity) {
|
|
3828
|
+
const slug = sanitizeExecutableBaseName(identity.executableBaseName || 'game').toLowerCase();
|
|
3829
|
+
return {
|
|
3830
|
+
appName: identity.name,
|
|
3831
|
+
bundleId: process.env.AURA_IOS_BUNDLE_ID
|
|
3832
|
+
|| `com.aurajs.${sanitizeMobileIdentifierFragment(slug)}`,
|
|
3833
|
+
version: identity.version,
|
|
3834
|
+
buildNumber: process.env.AURA_IOS_BUILD_NUMBER || '1',
|
|
3835
|
+
};
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
function buildMobileSourceArtifacts({
|
|
3839
|
+
projectRoot,
|
|
3840
|
+
outDir,
|
|
3841
|
+
entryFile,
|
|
3842
|
+
identity,
|
|
3843
|
+
modules,
|
|
3844
|
+
windowConfig,
|
|
3845
|
+
}) {
|
|
3846
|
+
const sourceOutRoot = resolve(projectRoot, outDir, '.mobile-source');
|
|
3847
|
+
const bundle = runBuildStage('bundle', () => bundleProject({
|
|
3848
|
+
projectRoot,
|
|
3849
|
+
mode: 'build',
|
|
3850
|
+
entryFile,
|
|
3851
|
+
outFile: resolve(sourceOutRoot, 'js/game.bundle.js'),
|
|
3852
|
+
}));
|
|
3853
|
+
const assets = runBuildStage('asset-pack', () => packageAssets({
|
|
3854
|
+
projectRoot,
|
|
3855
|
+
outRoot: sourceOutRoot,
|
|
3856
|
+
mode: 'embed',
|
|
3857
|
+
}));
|
|
3858
|
+
const buildManifestPath = runBuildStage('build-contract', () => writeBuildManifest({
|
|
3859
|
+
outRoot: sourceOutRoot,
|
|
3860
|
+
bundlePath: bundle.outFile,
|
|
3861
|
+
assetsManifestPath: assets.manifestPath,
|
|
3862
|
+
executablePath: null,
|
|
3863
|
+
assetMode: assets.mode,
|
|
3864
|
+
identity: {
|
|
3865
|
+
name: identity.name,
|
|
3866
|
+
version: identity.version,
|
|
3867
|
+
windowTitle: identity.name,
|
|
3868
|
+
executableBaseName: identity.executableBaseName,
|
|
3869
|
+
executableFileName: null,
|
|
3870
|
+
},
|
|
3871
|
+
icon: null,
|
|
3872
|
+
}));
|
|
3873
|
+
const runtimeConfigPath = runBuildStage('runtime-config', () => {
|
|
3874
|
+
const capabilityDeclaration = readProjectCapabilityDeclaration({
|
|
3875
|
+
projectRoot,
|
|
3876
|
+
modules: modules || {},
|
|
3877
|
+
});
|
|
3878
|
+
const runtimeConfig = buildRuntimeConfig({
|
|
3879
|
+
windowConfig: windowConfig || {},
|
|
3880
|
+
modules: modules || {},
|
|
3881
|
+
capabilityDeclaration,
|
|
3882
|
+
});
|
|
3883
|
+
const outPath = resolve(sourceOutRoot, 'runtime-config.json');
|
|
3884
|
+
writeCanonicalJsonFile(outPath, runtimeConfig);
|
|
3885
|
+
return outPath;
|
|
3886
|
+
});
|
|
3887
|
+
|
|
3888
|
+
return {
|
|
3889
|
+
outRoot: sourceOutRoot,
|
|
3890
|
+
bundle,
|
|
3891
|
+
assets,
|
|
3892
|
+
buildManifestPath,
|
|
3893
|
+
runtimeConfigPath,
|
|
3894
|
+
};
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3441
3897
|
function resolveBuildIcon({ projectRoot, targetOutRoot, iconPath, assetDir = 'assets' }) {
|
|
3442
3898
|
const configuredPath = typeof iconPath === 'string' && iconPath.trim().length > 0
|
|
3443
3899
|
? iconPath.trim()
|
|
@@ -4221,7 +4677,7 @@ async function cmdDevNative(devArgs = {}) {
|
|
|
4221
4677
|
|
|
4222
4678
|
async function cmdDev(args) {
|
|
4223
4679
|
const parsed = parseDevArgs(args);
|
|
4224
|
-
const target = parsed.target
|
|
4680
|
+
const target = parsed.target;
|
|
4225
4681
|
if (target === 'web') {
|
|
4226
4682
|
if (parsed.restoreKind || parsed.session !== null || parsed.sessionName || parsed.runtimeArgs.length > 0) {
|
|
4227
4683
|
throw new StateExportError(
|
|
@@ -4238,7 +4694,7 @@ async function cmdDev(args) {
|
|
|
4238
4694
|
async function cmdBuild(args, options = {}) {
|
|
4239
4695
|
const target = parseTarget(args);
|
|
4240
4696
|
if (target && !SUPPORTED_BUILD_TARGETS.has(target)) {
|
|
4241
|
-
throw new Error(`Unsupported --target "${target}". Supported values: windows, mac, linux, all, web, gb, gbc, gba.`);
|
|
4697
|
+
throw new Error(`Unsupported --target "${target}". Supported values: windows, mac, linux, all, web, android, ios, mobile, gb, gbc, gba.`);
|
|
4242
4698
|
}
|
|
4243
4699
|
|
|
4244
4700
|
const requestedTarget = target || currentPlatformTarget();
|
|
@@ -4247,6 +4703,8 @@ async function cmdBuild(args, options = {}) {
|
|
|
4247
4703
|
const entryFile = options.entryFile || config.build.entry;
|
|
4248
4704
|
const logOutput = options.log !== false;
|
|
4249
4705
|
const identity = resolveBuildIdentity(config);
|
|
4706
|
+
const cliAssetMode = parseAssetMode(args);
|
|
4707
|
+
const selectedAssetMode = args.some((a) => a === '--asset-mode') ? cliAssetMode : config.build.assetMode;
|
|
4250
4708
|
if (isRetroBuildTarget(requestedTarget)) {
|
|
4251
4709
|
return buildRetroProject({
|
|
4252
4710
|
projectRoot,
|
|
@@ -4304,6 +4762,136 @@ async function cmdBuild(args, options = {}) {
|
|
|
4304
4762
|
loaderPath: webContract.loaderPath,
|
|
4305
4763
|
};
|
|
4306
4764
|
}
|
|
4765
|
+
if (isMobileBuildTarget(requestedTarget)) {
|
|
4766
|
+
if (selectedAssetMode !== 'embed') {
|
|
4767
|
+
throw new Error('Mobile builds require `--asset-mode embed` in v1.');
|
|
4768
|
+
}
|
|
4769
|
+
|
|
4770
|
+
const mobileSource = buildMobileSourceArtifacts({
|
|
4771
|
+
projectRoot,
|
|
4772
|
+
outDir: config.build.outDir,
|
|
4773
|
+
entryFile,
|
|
4774
|
+
identity,
|
|
4775
|
+
modules: config.modules,
|
|
4776
|
+
windowConfig: config.window,
|
|
4777
|
+
});
|
|
4778
|
+
|
|
4779
|
+
const androidRequested = requestedTarget === 'android' || requestedTarget === 'mobile';
|
|
4780
|
+
const iosRequested = requestedTarget === 'ios' || requestedTarget === 'mobile';
|
|
4781
|
+
|
|
4782
|
+
const androidHostArtifact = androidRequested
|
|
4783
|
+
? runBuildStage('android-host-artifact', () => produceAndroidHostArtifact({
|
|
4784
|
+
sourceLibraryPath: process.env.AURA_ANDROID_NATIVE_HOST_LIBRARY || null,
|
|
4785
|
+
env: process.env,
|
|
4786
|
+
}))
|
|
4787
|
+
: null;
|
|
4788
|
+
const androidStage = androidRequested
|
|
4789
|
+
? runBuildStage('android-stage', () => stageAndroidProject({
|
|
4790
|
+
projectRoot,
|
|
4791
|
+
outRoot: resolve(projectRoot, config.build.outDir, 'android'),
|
|
4792
|
+
bundlePath: mobileSource.bundle.outFile,
|
|
4793
|
+
assetsPackPath: mobileSource.assets.packPath,
|
|
4794
|
+
sourceBuildManifestPath: mobileSource.buildManifestPath,
|
|
4795
|
+
runtimeConfigPath: mobileSource.runtimeConfigPath,
|
|
4796
|
+
nativeHostLibraryPath: androidHostArtifact?.ok ? androidHostArtifact.distArtifactPath : null,
|
|
4797
|
+
identity: resolveAndroidBuildIdentity(identity),
|
|
4798
|
+
}))
|
|
4799
|
+
: null;
|
|
4800
|
+
const androidBuild = androidRequested
|
|
4801
|
+
? runBuildStage('android-build', () => buildAndroidArtifacts({
|
|
4802
|
+
outRoot: androidStage.outRoot,
|
|
4803
|
+
manifestPath: androidStage.manifestPath,
|
|
4804
|
+
env: process.env,
|
|
4805
|
+
}))
|
|
4806
|
+
: null;
|
|
4807
|
+
const iosHostArtifact = iosRequested
|
|
4808
|
+
? runBuildStage('ios-host-artifact', () => produceIosHostArtifact({
|
|
4809
|
+
hostFrameworkPath: process.env.AURA_IOS_HOST_FRAMEWORK_PATH || null,
|
|
4810
|
+
environment: process.env,
|
|
4811
|
+
}))
|
|
4812
|
+
: null;
|
|
4813
|
+
const iosStage = iosRequested
|
|
4814
|
+
? runBuildStage('ios-stage', () => stageIosProject({
|
|
4815
|
+
projectRoot,
|
|
4816
|
+
outRoot: resolve(projectRoot, config.build.outDir, 'ios'),
|
|
4817
|
+
sourceBuildRoot: mobileSource.outRoot,
|
|
4818
|
+
buildManifestPath: mobileSource.buildManifestPath,
|
|
4819
|
+
assetsManifestPath: mobileSource.assets.manifestPath,
|
|
4820
|
+
bundlePath: mobileSource.bundle.outFile,
|
|
4821
|
+
hostFrameworkPath: iosHostArtifact?.ok ? iosHostArtifact.artifactPath : null,
|
|
4822
|
+
identity: resolveIosBuildIdentity(identity),
|
|
4823
|
+
}))
|
|
4824
|
+
: null;
|
|
4825
|
+
const iosBuild = iosRequested
|
|
4826
|
+
? runBuildStage('ios-build', () => buildIosArtifacts({
|
|
4827
|
+
outRoot: iosStage.outRoot,
|
|
4828
|
+
manifestPath: iosStage.manifestPath,
|
|
4829
|
+
environment: process.env,
|
|
4830
|
+
}))
|
|
4831
|
+
: null;
|
|
4832
|
+
|
|
4833
|
+
if (logOutput) {
|
|
4834
|
+
console.log('\n aura build: complete.');
|
|
4835
|
+
console.log(` Game: ${identity.name}`);
|
|
4836
|
+
console.log(` Version: ${identity.version}`);
|
|
4837
|
+
console.log(` Time: ${mobileSource.bundle.elapsedMs}ms`);
|
|
4838
|
+
console.log(` Assets: ${mobileSource.assets.assetCount} (${mobileSource.assets.mode})`);
|
|
4839
|
+
console.log(
|
|
4840
|
+
` Asset updates: copied=${mobileSource.assets.incremental.copied} skipped=${mobileSource.assets.incremental.skipped} removed=${mobileSource.assets.incremental.removed}`,
|
|
4841
|
+
);
|
|
4842
|
+
console.log(` Output target: ${requestedTarget}`);
|
|
4843
|
+
if (androidStage) {
|
|
4844
|
+
const androidToolchain = androidStage.toolchain.ready
|
|
4845
|
+
? 'ready'
|
|
4846
|
+
: (androidStage.toolchain.reasonCodes.join(', ') || 'missing');
|
|
4847
|
+
console.log(` Android stage: ${resolve(projectRoot, config.build.outDir, 'android')}`);
|
|
4848
|
+
console.log(` Android host artifact: ${androidHostArtifact?.reasonCode || 'not_requested'}`);
|
|
4849
|
+
console.log(` Android toolchain: ${androidToolchain}`);
|
|
4850
|
+
console.log(` Android build: ${androidBuild?.reasonCode || 'not_run'}`);
|
|
4851
|
+
}
|
|
4852
|
+
if (iosStage) {
|
|
4853
|
+
const iosToolchain = iosStage.toolchain.reasonCode;
|
|
4854
|
+
console.log(` iOS stage: ${resolve(projectRoot, config.build.outDir, 'ios')}`);
|
|
4855
|
+
console.log(` iOS host artifact: ${iosHostArtifact?.reasonCode || 'not_requested'}`);
|
|
4856
|
+
console.log(` iOS toolchain: ${iosToolchain}`);
|
|
4857
|
+
console.log(` iOS build: ${iosBuild?.reasonCode || 'not_run'}`);
|
|
4858
|
+
}
|
|
4859
|
+
console.log(' Note: mobile in v1 produces host artifacts, stages package roots, and runs Gradle/Xcode export when prerequisites are present; otherwise manifests stay reason-coded and staged.');
|
|
4860
|
+
console.log('');
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
return {
|
|
4864
|
+
projectRoot,
|
|
4865
|
+
config,
|
|
4866
|
+
requestedTarget,
|
|
4867
|
+
platformTarget: currentPlatformTarget(),
|
|
4868
|
+
effectiveTarget: requestedTarget,
|
|
4869
|
+
targetKind: 'mobile',
|
|
4870
|
+
targetOutRoot: resolve(projectRoot, config.build.outDir),
|
|
4871
|
+
executablePath: null,
|
|
4872
|
+
launchExecutablePath: null,
|
|
4873
|
+
bundlePath: mobileSource.bundle.outFile,
|
|
4874
|
+
assetsManifestPath: mobileSource.assets.manifestPath,
|
|
4875
|
+
buildManifestPath: mobileSource.buildManifestPath,
|
|
4876
|
+
assetMode: mobileSource.assets.mode,
|
|
4877
|
+
identity,
|
|
4878
|
+
icon: null,
|
|
4879
|
+
androidBuildManifestPath: androidStage?.manifestPath || null,
|
|
4880
|
+
iosBuildManifestPath: iosStage?.manifestPath || null,
|
|
4881
|
+
mobileBuilds: {
|
|
4882
|
+
android: androidRequested ? {
|
|
4883
|
+
hostArtifact: androidHostArtifact,
|
|
4884
|
+
stage: androidStage,
|
|
4885
|
+
export: androidBuild,
|
|
4886
|
+
} : null,
|
|
4887
|
+
ios: iosRequested ? {
|
|
4888
|
+
hostArtifact: iosHostArtifact,
|
|
4889
|
+
stage: iosStage,
|
|
4890
|
+
export: iosBuild,
|
|
4891
|
+
} : null,
|
|
4892
|
+
},
|
|
4893
|
+
};
|
|
4894
|
+
}
|
|
4307
4895
|
|
|
4308
4896
|
const platformTarget = currentPlatformTarget();
|
|
4309
4897
|
const effectiveTarget = platformTarget;
|
|
@@ -4311,8 +4899,7 @@ async function cmdBuild(args, options = {}) {
|
|
|
4311
4899
|
const executableFileName = executableNameForPlatform(effectiveTarget, identity.executableBaseName);
|
|
4312
4900
|
|
|
4313
4901
|
// CLI --asset-mode flag overrides config if provided.
|
|
4314
|
-
const
|
|
4315
|
-
const assetMode = args.some((a) => a === '--asset-mode') ? cliAssetMode : config.build.assetMode;
|
|
4902
|
+
const assetMode = selectedAssetMode;
|
|
4316
4903
|
|
|
4317
4904
|
const result = runBuildStage('bundle', () => bundleProject({
|
|
4318
4905
|
projectRoot,
|
|
@@ -4700,6 +5287,9 @@ async function cmdRun(args) {
|
|
|
4700
5287
|
if (built.targetKind === 'retro') {
|
|
4701
5288
|
throw new Error('aura run does not support Aura Retro targets. Use `aura build --target <gb|gbc|gba>` and the generated preview/toolchain outputs instead.');
|
|
4702
5289
|
}
|
|
5290
|
+
if (built.targetKind === 'mobile') {
|
|
5291
|
+
throw new Error('aura run does not support mobile package targets. Use `aura build --target android|ios|mobile` and continue with the staged mobile package lane.');
|
|
5292
|
+
}
|
|
4703
5293
|
if (built.effectiveTarget === 'web') {
|
|
4704
5294
|
throw new Error('aura run does not support --target web. Serve build/web in a browser and use the web loader contract.');
|
|
4705
5295
|
}
|
|
@@ -4901,6 +5491,74 @@ async function cmdTest(args) {
|
|
|
4901
5491
|
console.log('');
|
|
4902
5492
|
}
|
|
4903
5493
|
|
|
5494
|
+
async function cmdEvidence(args) {
|
|
5495
|
+
const projectRoot = process.cwd();
|
|
5496
|
+
const parsed = parseEvidenceArgs(args);
|
|
5497
|
+
const config = await loadConfig({ projectRoot, mode: 'build' });
|
|
5498
|
+
const replayPayload = parsed.replayPath
|
|
5499
|
+
? readJsonInputFile(parsed.replayPath, 'replay payload', 'replay_input')
|
|
5500
|
+
: null;
|
|
5501
|
+
const result = await captureHeadlessEvidenceBundle({
|
|
5502
|
+
projectRoot,
|
|
5503
|
+
file: parsed.file || config.build.entry,
|
|
5504
|
+
frames: parsed.frames,
|
|
5505
|
+
width: parsed.width ?? config.window.width,
|
|
5506
|
+
height: parsed.height ?? config.window.height,
|
|
5507
|
+
outDir: parsed.outDir,
|
|
5508
|
+
replayPayload,
|
|
5509
|
+
});
|
|
5510
|
+
|
|
5511
|
+
const manifestText = serializeEvidenceManifest(result.manifest, parsed.compact);
|
|
5512
|
+
writeStateJsonOutput(parsed.outputPath, manifestText, 'evidence_output_write_failed');
|
|
5513
|
+
}
|
|
5514
|
+
|
|
5515
|
+
async function cmdReplayRun(args) {
|
|
5516
|
+
const projectRoot = process.cwd();
|
|
5517
|
+
const parsed = parseReplayRunArgs(args);
|
|
5518
|
+
const config = await loadConfig({ projectRoot, mode: 'build' });
|
|
5519
|
+
const payload = readJsonInputFile(parsed.replayPath, 'replay payload', 'replay_input');
|
|
5520
|
+
const result = await runHeadlessReplay({
|
|
5521
|
+
projectRoot,
|
|
5522
|
+
file: parsed.file || config.build.entry,
|
|
5523
|
+
width: parsed.width ?? config.window.width,
|
|
5524
|
+
height: parsed.height ?? config.window.height,
|
|
5525
|
+
payload,
|
|
5526
|
+
});
|
|
5527
|
+
|
|
5528
|
+
if (parsed.stateOutputPath !== null) {
|
|
5529
|
+
writeStateJsonOutput(
|
|
5530
|
+
parsed.stateOutputPath,
|
|
5531
|
+
serializeCanonicalStatePayload(result.finalState, parsed.compact),
|
|
5532
|
+
'replay_state_output_write_failed',
|
|
5533
|
+
);
|
|
5534
|
+
}
|
|
5535
|
+
writeStateJsonOutput(
|
|
5536
|
+
parsed.outputPath,
|
|
5537
|
+
serializeReplayReport(result.report, parsed.compact),
|
|
5538
|
+
'replay_output_write_failed',
|
|
5539
|
+
);
|
|
5540
|
+
}
|
|
5541
|
+
|
|
5542
|
+
async function cmdReplay(args) {
|
|
5543
|
+
const subcommand = args[0];
|
|
5544
|
+
if (!subcommand) {
|
|
5545
|
+
throw new StateExportError(
|
|
5546
|
+
'replay_subcommand_required',
|
|
5547
|
+
'Missing replay subcommand. Usage: aura replay run <replay.json> [options]',
|
|
5548
|
+
);
|
|
5549
|
+
}
|
|
5550
|
+
|
|
5551
|
+
if (subcommand === 'run') {
|
|
5552
|
+
await cmdReplayRun(args.slice(1));
|
|
5553
|
+
return;
|
|
5554
|
+
}
|
|
5555
|
+
|
|
5556
|
+
throw new StateExportError(
|
|
5557
|
+
'replay_subcommand_unsupported',
|
|
5558
|
+
`Unknown replay subcommand "${subcommand}". Supported subcommands: run.`,
|
|
5559
|
+
);
|
|
5560
|
+
}
|
|
5561
|
+
|
|
4904
5562
|
async function runStateExportPayload(parsed) {
|
|
4905
5563
|
const projectRoot = process.cwd();
|
|
4906
5564
|
const config = await loadConfig({ projectRoot, mode: 'build' });
|
|
@@ -6257,6 +6915,8 @@ const HANDLERS = {
|
|
|
6257
6915
|
create: (args) => cmdCreate(args, { error }),
|
|
6258
6916
|
from: (args) => cmdFrom(args, { error }),
|
|
6259
6917
|
make: (args) => cmdMake(args, { error }),
|
|
6918
|
+
vendor: (args) => cmdVendor(args, { error }),
|
|
6919
|
+
packs: (args) => cmdPacks(args, { error }),
|
|
6260
6920
|
explain: (args) => cmdExplain(args, { error }),
|
|
6261
6921
|
check: (args) => cmdCheck(args, { error }),
|
|
6262
6922
|
dev: cmdDev,
|
|
@@ -6268,6 +6928,8 @@ const HANDLERS = {
|
|
|
6268
6928
|
'external-assets': cmdExternalAssets,
|
|
6269
6929
|
clean: cmdClean,
|
|
6270
6930
|
test: cmdTest,
|
|
6931
|
+
evidence: cmdEvidence,
|
|
6932
|
+
replay: cmdReplay,
|
|
6271
6933
|
conformance: cmdConformance,
|
|
6272
6934
|
state: cmdState,
|
|
6273
6935
|
inspect: cmdInspect,
|
|
@@ -6291,7 +6953,7 @@ async function main() {
|
|
|
6291
6953
|
process.exit(0);
|
|
6292
6954
|
}
|
|
6293
6955
|
|
|
6294
|
-
if (argv
|
|
6956
|
+
if (argv[0] === '--version' || argv[0] === '-v') {
|
|
6295
6957
|
console.log(VERSION);
|
|
6296
6958
|
process.exit(0);
|
|
6297
6959
|
}
|
|
@@ -6335,6 +6997,12 @@ async function main() {
|
|
|
6335
6997
|
if (err instanceof StateArtifactError) {
|
|
6336
6998
|
error(`${err.message} (reasonCode=${err.reasonCode})`, 6);
|
|
6337
6999
|
}
|
|
7000
|
+
if (err instanceof EvidenceBundleError) {
|
|
7001
|
+
error(`${err.message} (reasonCode=${err.reasonCode})`, 6);
|
|
7002
|
+
}
|
|
7003
|
+
if (err instanceof ReplayError) {
|
|
7004
|
+
error(`${err.message} (reasonCode=${err.reasonCode})`, 6);
|
|
7005
|
+
}
|
|
6338
7006
|
if (err instanceof HeadlessTestError) {
|
|
6339
7007
|
if (Array.isArray(err.details?.failures) && err.details.failures.length > 0) {
|
|
6340
7008
|
console.error('\n aura test failures:');
|