@auraindustry/aurajs 0.1.1 → 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.
Files changed (144) hide show
  1. package/README.md +7 -0
  2. package/benchmarks/perf-thresholds.json +27 -0
  3. package/package.json +6 -1
  4. package/src/ai-guidance.mjs +302 -0
  5. package/src/asset-pack.mjs +2 -1
  6. package/src/authored-project.mjs +498 -2
  7. package/src/authored-runtime.mjs +14 -0
  8. package/src/bin-integrity.mjs +33 -26
  9. package/src/build-contract/capabilities.mjs +87 -1
  10. package/src/build-contract/constants.mjs +1 -0
  11. package/src/build-contract.mjs +2 -0
  12. package/src/bundler.mjs +143 -13
  13. package/src/cli.mjs +681 -13
  14. package/src/commands/packs.mjs +741 -0
  15. package/src/commands/project-authoring.mjs +128 -1
  16. package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
  17. package/src/conformance/cases/core-runtime-cases.mjs +6 -2
  18. package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
  19. package/src/conformance/cases/systems-and-gameplay-cases.mjs +1126 -10
  20. package/src/conformance-mobile.mjs +166 -0
  21. package/src/conformance.mjs +89 -30
  22. package/src/evidence-bundle.mjs +242 -0
  23. package/src/external-package-surface.mjs +1 -1
  24. package/src/headless-test/runtime-coordinator.mjs +186 -33
  25. package/src/headless-test.mjs +2 -0
  26. package/src/helpers/2d/index.mjs +183 -0
  27. package/src/helpers/index.mjs +26 -0
  28. package/src/helpers/starter-utils/adventure-objectives.js +102 -0
  29. package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
  30. package/src/helpers/starter-utils/animation-2d.js +337 -0
  31. package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
  32. package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
  33. package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
  34. package/src/helpers/starter-utils/avatar-3d.js +404 -0
  35. package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
  36. package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
  37. package/src/helpers/starter-utils/core.js +150 -0
  38. package/src/helpers/starter-utils/dialogue-2d.js +351 -0
  39. package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
  40. package/src/helpers/starter-utils/index.js +26 -0
  41. package/src/helpers/starter-utils/inventory-2d.js +268 -0
  42. package/src/helpers/starter-utils/journal-2d.js +267 -0
  43. package/src/helpers/starter-utils/platformer-3d.js +132 -0
  44. package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
  45. package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
  46. package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
  47. package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
  48. package/src/helpers/starter-utils/triggers.js +662 -0
  49. package/src/helpers/starter-utils/tween-2d.js +615 -0
  50. package/src/helpers/starter-utils/wave-director.js +101 -0
  51. package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
  52. package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
  53. package/src/mobile/android/build.mjs +606 -0
  54. package/src/mobile/android/host-artifact.mjs +280 -0
  55. package/src/mobile/ios/build.mjs +1323 -0
  56. package/src/mobile/ios/host-artifact.mjs +819 -0
  57. package/src/mobile/shared/capabilities.mjs +174 -0
  58. package/src/package-integrity.mjs +18 -4
  59. package/src/packs/catalog.mjs +259 -0
  60. package/src/perf-benchmark-runner.mjs +17 -12
  61. package/src/perf-benchmark.mjs +408 -4
  62. package/src/publish-command.mjs +434 -17
  63. package/src/publish-validation.mjs +22 -11
  64. package/src/replay-runtime.mjs +257 -0
  65. package/src/scaffold/config.mjs +2 -0
  66. package/src/scaffold/fs.mjs +8 -1
  67. package/src/scaffold/project-docs.mjs +101 -41
  68. package/src/scaffold.mjs +4 -0
  69. package/src/session-runtime.mjs +4 -3
  70. package/src/web-conformance.mjs +0 -36
  71. package/templates/create/2d/src/runtime/app.js +4 -0
  72. package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
  73. package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
  74. package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
  75. package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
  76. package/templates/create/2d-adventure/docs/design/loop.md +4 -3
  77. package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
  78. package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
  79. package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
  80. package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
  81. package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
  82. package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
  83. package/templates/create/2d-survivor/src/runtime/app.js +4 -0
  84. package/templates/create/3d/scenes/gameplay.scene.js +30 -3
  85. package/templates/create/3d/src/runtime/app.js +4 -0
  86. package/templates/create/3d/src/runtime/capabilities.js +5 -0
  87. package/templates/create/3d/src/runtime/materials.js +10 -0
  88. package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
  89. package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
  90. package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
  91. package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
  92. package/templates/create/3d-collectathon/src/runtime/app.js +4 -0
  93. package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
  94. package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
  95. package/templates/create/blank/assets/splash/aurajs-gg-wordmark.webp +0 -0
  96. package/templates/create/blank/assets/splash/bg.webp +0 -0
  97. package/templates/create/blank/assets/splash/boot-loop.wav +0 -0
  98. package/templates/create/blank/assets/splash/boot-sting.wav +0 -0
  99. package/templates/create/blank/assets/splash/logo-mascot-sheet.webp +0 -0
  100. package/templates/create/blank/assets/splash/logoholo.webp +0 -0
  101. package/templates/create/blank/src/main.js +5 -1
  102. package/templates/create/blank/src/runtime/splash.js +305 -0
  103. package/templates/create/local-multiplayer/scenes/gameplay.scene.js +186 -12
  104. package/templates/create/local-multiplayer/src/runtime/capabilities.js +8 -1
  105. package/templates/create/shared/assets/splash/aurajs-gg-wordmark.webp +0 -0
  106. package/templates/create/shared/assets/splash/bg.webp +0 -0
  107. package/templates/create/shared/assets/splash/boot-loop.wav +0 -0
  108. package/templates/create/shared/assets/splash/boot-sting.wav +0 -0
  109. package/templates/create/shared/assets/splash/logo-mascot-sheet.webp +0 -0
  110. package/templates/create/shared/assets/splash/logoholo.webp +0 -0
  111. package/templates/create/shared/src/runtime/splash.js +305 -0
  112. package/templates/create/shared/src/runtime/ui-forms.js +552 -0
  113. package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
  114. package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
  115. package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
  116. package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
  117. package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
  118. package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
  119. package/templates/create/shared/src/starter-utils/index.js +15 -1
  120. package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
  121. package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
  122. package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
  123. package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
  124. package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
  125. package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
  126. package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
  127. package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
  128. package/templates/create/video-cutscene/src/runtime/app.js +4 -0
  129. package/templates/create-bin/play.js +148 -7
  130. package/templates/skills/auramaxx/SKILL.md +46 -0
  131. package/templates/skills/auramaxx/project-requirements.md +68 -0
  132. package/templates/skills/auramaxx/starter-recipes.md +104 -0
  133. package/templates/skills/auramaxx/validation-checklist.md +49 -0
  134. package/templates/starter/assets/splash/aurajs-gg-wordmark.webp +0 -0
  135. package/templates/starter/assets/splash/bg.webp +0 -0
  136. package/templates/starter/assets/splash/boot-loop.wav +0 -0
  137. package/templates/starter/assets/splash/boot-sting.wav +0 -0
  138. package/templates/starter/assets/splash/logo-mascot-sheet.webp +0 -0
  139. package/templates/starter/assets/splash/logoholo.webp +0 -0
  140. package/templates/starter/src/main.js +4 -0
  141. package/templates/starter/src/runtime/splash.js +305 -0
  142. package/templates/skills/aurajs/SKILL.md +0 -96
  143. package/templates/skills/aurajs/api-contract-3d.md +0 -7
  144. package/templates/skills/aurajs/api-contract.md +0 -7
@@ -1,14 +1,21 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { existsSync, readFileSync } from 'node:fs';
3
- import { resolve } from 'node:path';
2
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { basename, join, resolve } from 'node:path';
4
5
 
5
6
  import { preparePublishPackageSurface } from './external-package-surface.mjs';
6
7
  import {
7
8
  PACKAGE_INTEGRITY_PUBLISH_FILES,
8
9
  writeSignedPackageIntegrityArtifacts,
9
10
  } from './package-integrity.mjs';
11
+ import { canPromptInteractively, promptInput, promptSelect } from './terminal-ui.mjs';
10
12
  import { resolvePublishEnvExampleSurface } from './publish-env-example.mjs';
11
13
  import { validatePublishProject } from './publish-validation.mjs';
14
+ import { formatBytes } from './external-asset-policy.mjs';
15
+
16
+ const SEMVER_RE = /^v?(\d+)\.(\d+)\.(\d+)(-[0-9A-Za-z-.]+)?$/;
17
+ const SCOPED_PACKAGE_RE = /^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/;
18
+ const UNSCOPED_PACKAGE_RE = /^[a-z0-9][a-z0-9._-]*$/;
12
19
 
13
20
  export function isNpmPublishLifecycleInvocation(env = process.env) {
14
21
  return env.npm_lifecycle_event === 'publish' && env.npm_command === 'publish';
@@ -18,7 +25,237 @@ export function hasOption(commandArgs, optionName) {
18
25
  return commandArgs.some((arg) => arg === optionName || arg.startsWith(`${optionName}=`));
19
26
  }
20
27
 
21
- export function readProjectPackage(projectRoot = process.cwd()) {
28
+ function stripOption(commandArgs, optionName) {
29
+ const nextArgs = [];
30
+ for (let index = 0; index < commandArgs.length; index += 1) {
31
+ const current = commandArgs[index];
32
+ if (current === optionName) {
33
+ index += 1;
34
+ continue;
35
+ }
36
+ if (current.startsWith(`${optionName}=`)) {
37
+ continue;
38
+ }
39
+ nextArgs.push(current);
40
+ }
41
+ return nextArgs;
42
+ }
43
+
44
+ function sanitizePackageSlug(value) {
45
+ const compact = String(value || '')
46
+ .trim()
47
+ .toLowerCase()
48
+ .replace(/^@[^/]+\//, '')
49
+ .replace(/\s+/g, '-')
50
+ .replace(/[^a-z0-9._-]/g, '-')
51
+ .replace(/-+/g, '-')
52
+ .replace(/^[-._]+|[-._]+$/g, '');
53
+ if (!compact) {
54
+ throw new Error(`Cannot derive package slug from "${value}".`);
55
+ }
56
+ return compact;
57
+ }
58
+
59
+ function buildDefaultPackageName(projectRoot) {
60
+ return `@aurajs/${sanitizePackageSlug(basename(projectRoot))}`;
61
+ }
62
+
63
+ function ensureScopedPackageName(value) {
64
+ const trimmed = String(value || '').trim();
65
+ if (!trimmed) {
66
+ throw new Error('Package name cannot be empty.');
67
+ }
68
+ if (/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(trimmed)) {
69
+ return `@${trimmed}`;
70
+ }
71
+ return trimmed;
72
+ }
73
+
74
+ function isValidPackageName(value) {
75
+ const normalized = String(value || '').trim();
76
+ if (!normalized) {
77
+ return false;
78
+ }
79
+ try {
80
+ const candidate = ensureScopedPackageName(normalized);
81
+ return SCOPED_PACKAGE_RE.test(candidate) || UNSCOPED_PACKAGE_RE.test(candidate);
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
86
+
87
+ function validatePackageName(value) {
88
+ const normalized = ensureScopedPackageName(value);
89
+ if (!SCOPED_PACKAGE_RE.test(normalized) && !UNSCOPED_PACKAGE_RE.test(normalized)) {
90
+ throw new Error(`Invalid npm package name "${value}".`);
91
+ }
92
+ }
93
+
94
+ function normalizeVersion(value) {
95
+ return String(value || '').trim().replace(/^v/i, '');
96
+ }
97
+
98
+ function isValidVersion(value) {
99
+ return SEMVER_RE.test(String(value || '').trim());
100
+ }
101
+
102
+ function validateVersion(value) {
103
+ if (!isValidVersion(value)) {
104
+ throw new Error(`Invalid version "${value}". Expected semver like 1.2.3 or 1.2.3-beta.1.`);
105
+ }
106
+ }
107
+
108
+ function bumpVersion(currentVersion, bumpKind) {
109
+ const match = normalizeVersion(currentVersion).match(SEMVER_RE);
110
+ if (!match) {
111
+ throw new Error(`Current version "${currentVersion}" is not valid semver.`);
112
+ }
113
+ const major = Number.parseInt(match[1], 10);
114
+ const minor = Number.parseInt(match[2], 10);
115
+ const patch = Number.parseInt(match[3], 10);
116
+ const prerelease = match[4] || '';
117
+
118
+ if (bumpKind === 'major') return `${major + 1}.0.0${prerelease}`;
119
+ if (bumpKind === 'minor') return `${major}.${minor + 1}.0${prerelease}`;
120
+ return `${major}.${minor}.${patch + 1}${prerelease}`;
121
+ }
122
+
123
+ function extractInternalPublishOptions(commandArgs) {
124
+ const sanitizedArgs = [];
125
+ let explicitName = null;
126
+ let explicitVersion = null;
127
+ let yes = false;
128
+
129
+ for (let index = 0; index < commandArgs.length; index += 1) {
130
+ const current = commandArgs[index];
131
+ if (current === '--yes' || current === '-y') {
132
+ yes = true;
133
+ continue;
134
+ }
135
+ if (current === '--name') {
136
+ explicitName = commandArgs[index + 1] || '';
137
+ index += 1;
138
+ continue;
139
+ }
140
+ if (current.startsWith('--name=')) {
141
+ explicitName = current.slice('--name='.length);
142
+ continue;
143
+ }
144
+ if (current === '--version') {
145
+ explicitVersion = commandArgs[index + 1] || '';
146
+ index += 1;
147
+ continue;
148
+ }
149
+ if (current.startsWith('--version=')) {
150
+ explicitVersion = current.slice('--version='.length);
151
+ continue;
152
+ }
153
+ sanitizedArgs.push(current);
154
+ }
155
+
156
+ return {
157
+ sanitizedArgs,
158
+ explicitName,
159
+ explicitVersion,
160
+ yes,
161
+ };
162
+ }
163
+
164
+ export function extractPublishToken(commandArgs, env = process.env) {
165
+ let explicitToken = null;
166
+
167
+ for (let index = 0; index < commandArgs.length; index += 1) {
168
+ const current = commandArgs[index];
169
+ if (current === '--token') {
170
+ explicitToken = commandArgs[index + 1] || '';
171
+ break;
172
+ }
173
+ if (current.startsWith('--token=')) {
174
+ explicitToken = current.slice('--token='.length);
175
+ break;
176
+ }
177
+ }
178
+
179
+ const envToken = typeof env.NODE_AUTH_TOKEN === 'string' && env.NODE_AUTH_TOKEN.trim().length > 0
180
+ ? env.NODE_AUTH_TOKEN.trim()
181
+ : null;
182
+ const normalizedToken = typeof explicitToken === 'string' && explicitToken.trim().length > 0
183
+ ? explicitToken.trim()
184
+ : envToken;
185
+
186
+ return {
187
+ publishArgs: stripOption(commandArgs, '--token'),
188
+ publishEnv: normalizedToken
189
+ ? {
190
+ ...env,
191
+ NODE_AUTH_TOKEN: normalizedToken,
192
+ }
193
+ : env,
194
+ publishToken: normalizedToken,
195
+ };
196
+ }
197
+
198
+ function normalizeRegistryUrl(registryValue) {
199
+ const normalizedValue = String(registryValue || '').trim();
200
+ if (!normalizedValue) {
201
+ return 'https://registry.npmjs.org/';
202
+ }
203
+
204
+ try {
205
+ const registryUrl = new URL(normalizedValue);
206
+ if (!registryUrl.pathname.endsWith('/')) {
207
+ registryUrl.pathname = `${registryUrl.pathname}/`;
208
+ }
209
+ return registryUrl.toString();
210
+ } catch {
211
+ return 'https://registry.npmjs.org/';
212
+ }
213
+ }
214
+
215
+ function buildRegistryAuthLine(token, registryUrl) {
216
+ const parsedUrl = new URL(registryUrl);
217
+ const registryPath = parsedUrl.pathname === '/' ? '' : parsedUrl.pathname.replace(/\/$/, '');
218
+ return `//${parsedUrl.host}${registryPath}/:_authToken=${token}`;
219
+ }
220
+
221
+ function createPublishTokenEnv(token, env = process.env) {
222
+ if (!token) {
223
+ return {
224
+ env,
225
+ cleanup() {},
226
+ };
227
+ }
228
+
229
+ const registryUrl = normalizeRegistryUrl(env.npm_config_registry || env.NPM_CONFIG_REGISTRY);
230
+ const userConfigDir = mkdtempSync(join(tmpdir(), 'aurajs-npm-auth-'));
231
+ const userConfigPath = join(userConfigDir, '.npmrc');
232
+ writeFileSync(
233
+ userConfigPath,
234
+ [
235
+ `registry=${registryUrl}`,
236
+ 'always-auth=true',
237
+ buildRegistryAuthLine(token, registryUrl),
238
+ '',
239
+ ].join('\n'),
240
+ 'utf8',
241
+ );
242
+
243
+ return {
244
+ env: {
245
+ ...env,
246
+ NODE_AUTH_TOKEN: token,
247
+ NPM_CONFIG_USERCONFIG: userConfigPath,
248
+ npm_config_userconfig: userConfigPath,
249
+ NPM_CONFIG_REGISTRY: registryUrl,
250
+ npm_config_registry: registryUrl,
251
+ },
252
+ cleanup() {
253
+ rmSync(userConfigDir, { recursive: true, force: true });
254
+ },
255
+ };
256
+ }
257
+
258
+ function readProjectPackageManifest(projectRoot = process.cwd()) {
22
259
  const packagePath = resolve(projectRoot, 'package.json');
23
260
  if (!existsSync(packagePath)) {
24
261
  throw new Error('aura publish requires a package.json in the current project root.');
@@ -34,9 +271,6 @@ export function readProjectPackage(projectRoot = process.cwd()) {
34
271
  const packageName = typeof projectPackage?.name === 'string' && projectPackage.name.trim().length > 0
35
272
  ? projectPackage.name.trim()
36
273
  : null;
37
- if (!packageName) {
38
- throw new Error('aura publish requires package.json -> name to be set.');
39
- }
40
274
 
41
275
  return {
42
276
  packagePath,
@@ -45,9 +279,162 @@ export function readProjectPackage(projectRoot = process.cwd()) {
45
279
  };
46
280
  }
47
281
 
282
+ export function readProjectPackage(projectRoot = process.cwd()) {
283
+ const projectPackage = readProjectPackageManifest(projectRoot);
284
+ if (!projectPackage.packageName) {
285
+ throw new Error('aura publish requires package.json -> name to be set.');
286
+ }
287
+ return projectPackage;
288
+ }
289
+
290
+ async function resolvePublishPackageName(
291
+ commandArgs,
292
+ {
293
+ projectRoot = process.cwd(),
294
+ canPromptInteractivelyImpl = canPromptInteractively,
295
+ promptInputImpl = promptInput,
296
+ } = {},
297
+ ) {
298
+ const { packagePath, projectPackage, packageName: currentPackageName } = readProjectPackageManifest(projectRoot);
299
+ const { sanitizedArgs, explicitName, yes } = extractInternalPublishOptions(commandArgs);
300
+ const defaultPackageName = buildDefaultPackageName(projectRoot);
301
+ const currentValidPackageName = currentPackageName && isValidPackageName(currentPackageName)
302
+ ? ensureScopedPackageName(currentPackageName)
303
+ : null;
304
+
305
+ let targetPackageName = currentPackageName;
306
+
307
+ if (explicitName !== null) {
308
+ targetPackageName = ensureScopedPackageName(explicitName);
309
+ validatePackageName(targetPackageName);
310
+ } else if (yes) {
311
+ targetPackageName = currentPackageName || defaultPackageName;
312
+ validatePackageName(targetPackageName);
313
+ } else if (canPromptInteractivelyImpl()) {
314
+ const fallbackPackageName = currentValidPackageName || defaultPackageName;
315
+ const fallbackDisplay = fallbackPackageName.startsWith('@')
316
+ ? fallbackPackageName.slice(1)
317
+ : fallbackPackageName;
318
+ const input = await promptInputImpl(` Package name (default: ${fallbackDisplay})`);
319
+ targetPackageName = ensureScopedPackageName(input || fallbackPackageName);
320
+ validatePackageName(targetPackageName);
321
+ }
322
+
323
+ if (targetPackageName && projectPackage.name !== targetPackageName) {
324
+ projectPackage.name = targetPackageName;
325
+ writeFileSync(packagePath, `${JSON.stringify(projectPackage, null, 2)}\n`, 'utf8');
326
+ }
327
+
328
+ return {
329
+ publishArgs: sanitizedArgs,
330
+ packageName: targetPackageName,
331
+ };
332
+ }
333
+
334
+ async function resolvePublishVersion(
335
+ commandArgs,
336
+ {
337
+ projectRoot = process.cwd(),
338
+ canPromptInteractivelyImpl = canPromptInteractively,
339
+ promptSelectImpl = promptSelect,
340
+ promptInputImpl = promptInput,
341
+ } = {},
342
+ ) {
343
+ const { packagePath, projectPackage } = readProjectPackage(projectRoot);
344
+ const { sanitizedArgs, explicitVersion, yes } = extractInternalPublishOptions(commandArgs);
345
+ const packageVersion = typeof projectPackage?.version === 'string' && projectPackage.version.trim().length > 0
346
+ ? normalizeVersion(projectPackage.version)
347
+ : null;
348
+ const currentVersion = isValidVersion(packageVersion || '') ? packageVersion : null;
349
+
350
+ let targetVersion = packageVersion;
351
+
352
+ if (explicitVersion !== null) {
353
+ const normalized = normalizeVersion(explicitVersion);
354
+ validateVersion(normalized);
355
+ targetVersion = normalized;
356
+ } else if (yes) {
357
+ if (packageVersion) {
358
+ validateVersion(packageVersion);
359
+ targetVersion = packageVersion;
360
+ } else {
361
+ targetVersion = '0.1.0';
362
+ }
363
+ } else if (canPromptInteractivelyImpl()) {
364
+ if (currentVersion) {
365
+ const choice = await promptSelectImpl(
366
+ ' Version selection',
367
+ [
368
+ { value: 'current', label: `Current (${currentVersion})`, aliases: ['c', 'keep'] },
369
+ { value: 'bump', label: 'Bump version', aliases: ['b'] },
370
+ { value: 'custom', label: 'Custom version', aliases: ['x'] },
371
+ ],
372
+ 'current',
373
+ );
374
+
375
+ if (choice === 'bump') {
376
+ const bumpKind = await promptSelectImpl(
377
+ ' Bump type',
378
+ [
379
+ { value: 'patch', label: `Patch (${bumpVersion(currentVersion, 'patch')})`, aliases: ['p'] },
380
+ { value: 'minor', label: `Minor (${bumpVersion(currentVersion, 'minor')})`, aliases: ['m'] },
381
+ { value: 'major', label: `Major (${bumpVersion(currentVersion, 'major')})`, aliases: ['M'] },
382
+ ],
383
+ 'patch',
384
+ );
385
+ targetVersion = bumpVersion(currentVersion, bumpKind);
386
+ } else if (choice === 'custom') {
387
+ while (true) {
388
+ const input = normalizeVersion(await promptInputImpl(' Custom version (semver)'));
389
+ if (!input) {
390
+ console.error(' Version is required.');
391
+ continue;
392
+ }
393
+ if (!isValidVersion(input)) {
394
+ console.error(' Invalid version format. Use semver like 1.2.3 or 1.2.3-beta.1');
395
+ continue;
396
+ }
397
+ targetVersion = input;
398
+ break;
399
+ }
400
+ }
401
+ } else {
402
+ const defaultVersion = packageVersion ? '' : '0.1.0';
403
+ const promptLabel = defaultVersion
404
+ ? ` Package version (semver, default: ${defaultVersion})`
405
+ : ' Package version (semver)';
406
+ while (true) {
407
+ const input = normalizeVersion(await promptInputImpl(promptLabel));
408
+ const candidate = input || defaultVersion;
409
+ if (!candidate) {
410
+ console.error(' Version is required.');
411
+ continue;
412
+ }
413
+ if (!isValidVersion(candidate)) {
414
+ console.error(' Invalid version format. Use semver like 1.2.3 or 1.2.3-beta.1');
415
+ continue;
416
+ }
417
+ targetVersion = candidate;
418
+ break;
419
+ }
420
+ }
421
+ }
422
+
423
+ if (targetVersion && projectPackage.version !== targetVersion) {
424
+ projectPackage.version = targetVersion;
425
+ writeFileSync(packagePath, `${JSON.stringify(projectPackage, null, 2)}\n`, 'utf8');
426
+ }
427
+
428
+ return {
429
+ publishArgs: sanitizedArgs,
430
+ packageVersion: targetVersion,
431
+ };
432
+ }
433
+
48
434
  export function buildPublishArgs(commandArgs, { packageName } = {}) {
49
- const publishArgs = ['publish', ...commandArgs];
50
- if (String(packageName || '').startsWith('@') && !hasOption(commandArgs, '--access')) {
435
+ const sanitizedArgs = stripOption(commandArgs, '--token');
436
+ const publishArgs = ['publish', ...sanitizedArgs];
437
+ if (String(packageName || '').startsWith('@') && !hasOption(sanitizedArgs, '--access')) {
51
438
  publishArgs.push('--access', 'public');
52
439
  }
53
440
  return publishArgs;
@@ -68,13 +455,10 @@ function spawnPublish(commandArgs, { projectRoot, env, stdout, stderr }) {
68
455
  return new Promise((resolveRun, rejectRun) => {
69
456
  const child = spawn(resolveNpmCommand(), commandArgs, {
70
457
  cwd: projectRoot,
71
- stdio: ['ignore', 'pipe', 'pipe'],
458
+ stdio: 'inherit',
72
459
  env,
73
460
  });
74
461
 
75
- pipeChildStream(child.stdout, stdout);
76
- pipeChildStream(child.stderr, stderr);
77
-
78
462
  child.on('error', (error) => {
79
463
  rejectRun(error);
80
464
  });
@@ -107,6 +491,9 @@ export async function runPublishCommand(
107
491
  stdout = process.stdout,
108
492
  stderr = process.stderr,
109
493
  validateProject = validatePublishProject,
494
+ canPromptInteractivelyImpl = canPromptInteractively,
495
+ promptSelectImpl = promptSelect,
496
+ promptInputImpl = promptInput,
110
497
  } = {},
111
498
  ) {
112
499
  if (isNpmPublishLifecycleInvocation(env)) {
@@ -121,6 +508,19 @@ export async function runPublishCommand(
121
508
  };
122
509
  }
123
510
 
511
+ await resolvePublishPackageName(commandArgs, {
512
+ projectRoot,
513
+ canPromptInteractivelyImpl,
514
+ promptInputImpl,
515
+ });
516
+
517
+ const publishVersionResolution = await resolvePublishVersion(commandArgs, {
518
+ projectRoot,
519
+ canPromptInteractivelyImpl,
520
+ promptSelectImpl,
521
+ promptInputImpl,
522
+ });
523
+
124
524
  let validation;
125
525
  try {
126
526
  validation = await validateProject({
@@ -134,9 +534,13 @@ export async function runPublishCommand(
134
534
  const assetBytes = Number.isFinite(error?.details?.assetBytes) ? error.details.assetBytes : null;
135
535
  const thresholdBytes = Number.isFinite(error?.details?.thresholdBytes) ? error.details.thresholdBytes : null;
136
536
  if (assetBytes !== null && thresholdBytes !== null) {
137
- stdout?.write(` Asset payload: ${assetBytes} bytes (threshold ${thresholdBytes})\n`);
537
+ stdout?.write(` Asset payload: ${formatBytes(assetBytes)} (${assetBytes} bytes)\n`);
538
+ stdout?.write(` Threshold: ${formatBytes(thresholdBytes)} (${thresholdBytes} bytes)\n`);
138
539
  }
139
- stdout?.write(' Next step: upload the heavy assets to a public HTTPS host like Cloudflare R2 or S3, generate the external asset config, then retry publish.\n');
540
+ stdout?.write(' This package is too large for npm-first publish.\n');
541
+ stdout?.write(' Self-host for now: upload the heavy assets to your own public HTTPS host, then generate the external asset config.\n');
542
+ stdout?.write(' Command: auramaxx external-assets generate --public-base-url https://cdn.example.com/my-game\n');
543
+ stdout?.write(' Docs: https://www.aurajs.gg/docs/publishing-and-large-assets\n');
140
544
  }
141
545
  if (error?.reportPath) {
142
546
  stdout?.write(` Validation report: ${error.reportPath}\n\n`);
@@ -146,8 +550,13 @@ export async function runPublishCommand(
146
550
 
147
551
  const packageName = validation.packageName;
148
552
  const { projectPackage } = readProjectPackage(projectRoot);
149
- const publishArgs = buildPublishArgs(commandArgs, { packageName });
150
- const dryRun = hasOption(commandArgs, '--dry-run');
553
+ const { publishArgs: sanitizedCommandArgs, publishEnv, publishToken } = extractPublishToken(
554
+ publishVersionResolution.publishArgs,
555
+ env,
556
+ );
557
+ const publishArgs = buildPublishArgs(sanitizedCommandArgs, { packageName });
558
+ const publishTokenEnv = createPublishTokenEnv(publishToken, publishEnv);
559
+ const dryRun = hasOption(sanitizedCommandArgs, '--dry-run');
151
560
  const envExampleSurface = resolvePublishEnvExampleSurface({ projectRoot });
152
561
  const packageSurface = preparePublishPackageSurface({
153
562
  projectRoot,
@@ -162,9 +571,15 @@ export async function runPublishCommand(
162
571
  packageRoot: packageSurface.publishRoot,
163
572
  signerProjectRoot: projectRoot,
164
573
  buildMetadata: validation?.report?.validation?.build || null,
574
+ includedRelativePaths: Array.isArray(validation?.report?.validation?.pack?.files)
575
+ ? validation.report.validation.pack.files.map((entry) => entry?.path).filter(Boolean)
576
+ : null,
165
577
  });
166
578
  stdout?.write(`\n aura publish: ${dryRun ? 'dry-run' : 'npm-first publish'}\n`);
167
579
  stdout?.write(` Package: ${packageName}\n`);
580
+ if (publishVersionResolution.packageVersion) {
581
+ stdout?.write(` Version: ${publishVersionResolution.packageVersion}\n`);
582
+ }
168
583
  stdout?.write(` Validation report: ${validation.reportPath}\n`);
169
584
  if (Number.isFinite(validation?.report?.validation?.assets?.assetBytes)) {
170
585
  const assets = validation.report.validation.assets;
@@ -176,11 +591,12 @@ export async function runPublishCommand(
176
591
  try {
177
592
  await spawnPublish(publishArgs, {
178
593
  projectRoot: packageSurface.publishRoot,
179
- env,
594
+ env: publishTokenEnv.env,
180
595
  stdout,
181
596
  stderr,
182
597
  });
183
598
  } finally {
599
+ publishTokenEnv.cleanup();
184
600
  packageSurface.cleanup();
185
601
  }
186
602
 
@@ -189,6 +605,7 @@ export async function runPublishCommand(
189
605
  skipped: false,
190
606
  reasonCode: dryRun ? 'publish_dry_run_ok' : 'publish_ok',
191
607
  packageName,
608
+ packageVersion: publishVersionResolution.packageVersion || validation.packageVersion || null,
192
609
  reportPath: validation.reportPath,
193
610
  publishArgs,
194
611
  };
@@ -401,12 +401,16 @@ export async function validatePublishProject(
401
401
  );
402
402
  }
403
403
 
404
+ const expectedAurajsVersion = typeof projectPackage?.dependencies?.['@auraindustry/aurajs'] === 'string'
405
+ ? projectPackage.dependencies['@auraindustry/aurajs'].trim()
406
+ : null;
407
+
404
408
  const binIntegrity = assertProjectBinIntegrity({
405
409
  projectRoot,
406
410
  projectPackage,
407
411
  packageName,
408
412
  aurajsPackageRoot: DEFAULT_AURAJS_PACKAGE_ROOT,
409
- expectedAurajsVersion: AURAJS_PACKAGE_VERSION,
413
+ expectedAurajsVersion,
410
414
  enforceExactAurajsDependency: true,
411
415
  });
412
416
  report.validation.binIntegrity = {
@@ -566,20 +570,11 @@ export async function validatePublishProject(
566
570
  );
567
571
  }
568
572
 
569
- const packageIntegrity = writeSignedPackageIntegrityArtifacts({
573
+ let packageIntegrity = writeSignedPackageIntegrityArtifacts({
570
574
  packageRoot: packageSurface.publishRoot,
571
575
  signerProjectRoot: projectRoot,
572
576
  buildMetadata,
573
577
  });
574
- report.validation.packageIntegrity = {
575
- reasonCode: 'publish_package_integrity_ok',
576
- manifestPath: packageIntegrity.manifestPath,
577
- signaturePath: packageIntegrity.signaturePath,
578
- schema: packageIntegrity.schema,
579
- fileCount: packageIntegrity.fileCount,
580
- signerFingerprint: packageIntegrity.signerFingerprint,
581
- publishedMetadata: packageIntegrity.publishedMetadata,
582
- };
583
578
 
584
579
  assetThresholdRecord.packageSurfaceMode = packageSurface.mode;
585
580
  assetThresholdRecord.assetPackaging = packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE
@@ -664,6 +659,22 @@ export async function validatePublishProject(
664
659
  files: packFiles,
665
660
  };
666
661
 
662
+ packageIntegrity = writeSignedPackageIntegrityArtifacts({
663
+ packageRoot: packageSurface.publishRoot,
664
+ signerProjectRoot: projectRoot,
665
+ buildMetadata,
666
+ includedRelativePaths: packFiles.map((entry) => entry.path),
667
+ });
668
+ report.validation.packageIntegrity = {
669
+ reasonCode: 'publish_package_integrity_ok',
670
+ manifestPath: packageIntegrity.manifestPath,
671
+ signaturePath: packageIntegrity.signaturePath,
672
+ schema: packageIntegrity.schema,
673
+ fileCount: packageIntegrity.fileCount,
674
+ signerFingerprint: packageIntegrity.signerFingerprint,
675
+ publishedMetadata: packageIntegrity.publishedMetadata,
676
+ };
677
+
667
678
  report.summary = {
668
679
  pass: true,
669
680
  reasonCode: 'publish_validation_ok',