@auraindustry/aurajs 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auraindustry/aurajs",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Write games in JavaScript, build native binaries.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -276,6 +276,9 @@ function collectAssets(assetsRoot) {
276
276
  function walkDir(dir, out) {
277
277
  const items = readdirSync(dir).sort((a, b) => a.localeCompare(b));
278
278
  for (const item of items) {
279
+ if (item === '.gitkeep' || item === '.DS_Store') {
280
+ continue;
281
+ }
279
282
  const full = join(dir, item);
280
283
  const stat = statSync(full);
281
284
  if (stat.isDirectory()) {
package/src/cli.mjs CHANGED
@@ -4553,6 +4553,11 @@ function printForegroundSessionReady(commandLabel, record, {
4553
4553
  reattached = false,
4554
4554
  includeWorkflowHints = false,
4555
4555
  } = {}) {
4556
+ if (commandLabel === 'aura run') {
4557
+ printRunLaunchBanner();
4558
+ return;
4559
+ }
4560
+
4556
4561
  const readiness = reattached ? 'dev session reattached' : 'dev session ready';
4557
4562
  console.log(
4558
4563
  ` ${commandLabel}: ${readiness} `
@@ -4570,6 +4575,18 @@ function printForegroundSessionReady(commandLabel, record, {
4570
4575
  console.log('');
4571
4576
  }
4572
4577
 
4578
+ function printRunLaunchBanner() {
4579
+ console.log('');
4580
+ console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ');
4581
+ console.log(' [ AURAJS ]');
4582
+ console.log(' Docs: https://www.aurajs.gg/docs');
4583
+ console.log('');
4584
+ console.log(' To create your own game:');
4585
+ console.log(' npm install -g auramaxx');
4586
+ console.log(' auramaxx create my-game');
4587
+ console.log('');
4588
+ }
4589
+
4573
4590
  function logForegroundSessionRegistryHygiene(commandLabel, report) {
4574
4591
  if (!report || typeof report !== 'object') {
4575
4592
  return;
@@ -4689,8 +4706,6 @@ async function cmdRun(args) {
4689
4706
  const launchContract = built.buildManifestPath;
4690
4707
  const launchExecutablePath = built.launchExecutablePath || built.executablePath;
4691
4708
 
4692
- console.log('\n aura run: launching native host.\n');
4693
-
4694
4709
  const launchEnv = {
4695
4710
  ...process.env,
4696
4711
  AURA_MODE: 'release',
@@ -221,6 +221,8 @@ export async function cmdInit(args, { error } = {}) {
221
221
  const dest = resolve(process.cwd(), name);
222
222
 
223
223
  try {
224
+ printBanner('CREATE');
225
+ printSection('AuraJS Create', `Scaffolding ${name}...`);
224
226
  const result = scaffold(name, dest);
225
227
  console.log(`\n Created "${name}" at ${dest}`);
226
228
  console.log('');
@@ -232,6 +234,13 @@ export async function cmdInit(args, { error } = {}) {
232
234
  console.log(` cd ${name}`);
233
235
  console.log(' aura dev');
234
236
  console.log('');
237
+ console.log(' Docs:');
238
+ console.log(' https://www.aurajs.gg/docs');
239
+ console.log('');
240
+ console.log(' Agent skills:');
241
+ console.log(' cd <your-codebase>');
242
+ console.log(' npx -y skills add Aura-Industry/auramaxx');
243
+ console.log('');
235
244
  } catch (err) {
236
245
  handleProjectAuthoringError(error, err);
237
246
  }
@@ -251,6 +260,8 @@ export async function cmdCreate(args, { error } = {}) {
251
260
  const dest = resolve(process.cwd(), name);
252
261
 
253
262
  try {
263
+ printBanner('CREATE');
264
+ printSection('AuraJS Create', `Scaffolding ${name}...`);
254
265
  const result = scaffoldGame({
255
266
  name,
256
267
  dest,
@@ -287,9 +298,18 @@ export async function cmdCreate(args, { error } = {}) {
287
298
  console.log(' npm run build:gbc');
288
299
  } else {
289
300
  console.log(' npm run dev');
301
+ console.log('');
302
+ console.log(' Optional packaged local run:');
290
303
  console.log(' npm run play');
291
304
  }
292
305
  console.log('');
306
+ console.log(' Docs:');
307
+ console.log(' https://www.aurajs.gg/docs');
308
+ console.log('');
309
+ console.log(' Agent skills:');
310
+ console.log(' cd <your-codebase>');
311
+ console.log(' npx -y skills add Aura-Industry/auramaxx');
312
+ console.log('');
293
313
  } catch (err) {
294
314
  handleProjectAuthoringError(error, err);
295
315
  }
package/src/config.mjs CHANGED
@@ -175,6 +175,7 @@ const SCHEMA = {
175
175
  relay: { type: 'string', default: null, validate: nonEmptyString },
176
176
  coordinatorUrl: { type: 'string', default: null, validate: nonEmptyString },
177
177
  relayUrl: { type: 'string', default: null, validate: nonEmptyString },
178
+ launcherBaseUrl: { type: 'string', default: null, validate: absoluteHttpUrl },
178
179
  showDiagnostics: { type: 'boolean', default: false },
179
180
  chatEnabled: { type: 'boolean', default: false },
180
181
  chatHistoryLimit: { type: 'number', default: 6, validate: positiveInteger },
@@ -234,6 +235,22 @@ function nonEmptyString(value, path) {
234
235
  return null;
235
236
  }
236
237
 
238
+ function absoluteHttpUrl(value, path) {
239
+ const normalized = String(value || '').trim();
240
+ if (normalized.length === 0) {
241
+ return `${path} must be a non-empty string`;
242
+ }
243
+ try {
244
+ const parsed = new URL(normalized);
245
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
246
+ return `${path} must use http:// or https://, got: ${JSON.stringify(value)}`;
247
+ }
248
+ return null;
249
+ } catch {
250
+ return `${path} must be an absolute http:// or https:// URL, got: ${JSON.stringify(value)}`;
251
+ }
252
+ }
253
+
237
254
  function multiplayerRoomCode(value, path) {
238
255
  const normalized = String(value || '').trim();
239
256
  if (!/^[A-Za-z0-9]{4,8}$/.test(normalized)) {
@@ -13,6 +13,7 @@ export function renderProjectReadme({ name, projectTitle, template, templateMeta
13
13
 
14
14
  const optionalCommands = [
15
15
  'npm run build',
16
+ '# packaged local launch sanity check',
16
17
  'npm run play',
17
18
  templateMetadata?.optionalModules?.multiplayer === true ? 'npm run join -- AURA2P' : null,
18
19
  'npm run publish',
@@ -109,7 +110,7 @@ If any are unavailable at runtime, fail fast and capture the reason code before
109
110
  ## Build + Share
110
111
 
111
112
  1. \`npm run build\` to emit native/web artifacts.
112
- 1. \`npm run play\` to launch through the generated game CLI wrapper.
113
+ 1. \`npm run play\` to sanity-check the packaged local wrapper path.
113
114
  ${templateMetadata?.optionalModules?.multiplayer === true ? '1. `npm run join -- AURA2P` to join a room-code multiplayer session through the generated wrapper.\n' : ''}1. \`npm run session -- start\` to open a persistent local developer session.
114
115
  1. \`npm run publish\` once metadata and binaries are ready.
115
116
  1. If you are not publishing under \`@aurajs\`, update \`package.json -> name\` first.
@@ -26,13 +26,13 @@ export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
26
26
  examples: ['examples/web-render-2d-proof'],
27
27
  }),
28
28
  Object.freeze({
29
- id: 'web-partial-pokemon-style-example',
29
+ id: 'web-partial-auramon-example',
30
30
  bucket: 'partial',
31
31
  expectation: 'partial',
32
- title: 'pokemon-style runs on the current browser-backed subset',
32
+ title: 'auramon runs on the current browser-backed subset',
33
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'],
34
+ testName: 'web loader browser smoke: auramon runs on the supported 2d subset with input and resize evidence',
35
+ examples: ['examples/auramon'],
36
36
  }),
37
37
  Object.freeze({
38
38
  id: 'web-supported-starter-3d-example',
@@ -33,6 +33,7 @@
33
33
  "relay": null,
34
34
  "coordinatorUrl": null,
35
35
  "relayUrl": null,
36
+ "launcherBaseUrl": null,
36
37
  "showDiagnostics": true,
37
38
  "chatEnabled": true,
38
39
  "chatHistoryLimit": 6
@@ -11,4 +11,6 @@ multiplayer. The default template keeps hosting local-first, while the authored
11
11
  project config can promote the same `npm run dev` + `npm run join -- CODE`
12
12
  flow to internet-backed hosting by setting `aura.config.json -> multiplayer.relay`
13
13
  or the `AURA_MULTIPLAYER_RELAY_HOST` env var. Direct host/port joins and LAN
14
- discovery still stay outside this starter.
14
+ discovery still stay outside this starter. If you also set
15
+ `aura.config.json -> multiplayer.launcherBaseUrl`, the host HUD can surface one
16
+ shareable launcher join page instead of only room-code shell instructions.
@@ -52,6 +52,11 @@ function readAuraEnvBoolean(name) {
52
52
  return null;
53
53
  }
54
54
 
55
+ function normalizeLauncherBaseUrl(value) {
56
+ const normalized = String(value || '').trim().replace(/\/+$/, '');
57
+ return normalized || null;
58
+ }
59
+
55
60
  function isKnownConnectivityMode(value) {
56
61
  const normalized = String(value || '').trim().toLowerCase();
57
62
  return normalized === 'local'
@@ -134,9 +139,16 @@ function resolveDiagnosticsConfig() {
134
139
  };
135
140
  }
136
141
 
142
+ function resolveLauncherConfig() {
143
+ return {
144
+ baseUrl: normalizeLauncherBaseUrl(readAuraEnv('AURA_MULTIPLAYER_LAUNCHER_BASE_URL')),
145
+ };
146
+ }
147
+
137
148
  const ROOM_CONFIG = resolveRoomConfig();
138
149
  const CONNECTIVITY_CONFIG = resolveConnectivityConfig();
139
150
  const DIAGNOSTICS_CONFIG = resolveDiagnosticsConfig();
151
+ const LAUNCHER_CONFIG = resolveLauncherConfig();
140
152
  const LAUNCH_JOIN_CODE = (() => {
141
153
  const value = readAuraEnv('AURA_MULTIPLAYER_JOIN_CODE');
142
154
  return value ? value.toUpperCase() : null;
@@ -233,6 +245,7 @@ function readInput() {
233
245
  }
234
246
 
235
247
  function currentStatusLine(sceneState, roomCode) {
248
+ const shareLink = currentLauncherJoinLink(sceneState);
236
249
  if (sceneState.role === 'pending') {
237
250
  if (launchedViaExplicitJoin()) {
238
251
  return `Joining room code ${roomCode}...`;
@@ -240,6 +253,9 @@ function currentStatusLine(sceneState, roomCode) {
240
253
  return 'Checking for a room-code match before hosting this room...';
241
254
  }
242
255
  if (sceneState.role === 'host') {
256
+ if (shareLink) {
257
+ return `Share launcher link: ${displayShareLink(shareLink)}`;
258
+ }
243
259
  if (usesInternetBackedHosting()) {
244
260
  return `Share this room code anywhere: npm run join -- ${roomCode}`;
245
261
  }
@@ -251,6 +267,17 @@ function currentStatusLine(sceneState, roomCode) {
251
267
  return 'Joined through the local-first room-code multiplayer flow.';
252
268
  }
253
269
 
270
+ function currentLauncherJoinLink(sceneState) {
271
+ if (!usesInternetBackedHosting() || !LAUNCHER_CONFIG.baseUrl) {
272
+ return null;
273
+ }
274
+ return `${LAUNCHER_CONFIG.baseUrl}/join/${encodeURIComponent(currentRoomCode(sceneState))}`;
275
+ }
276
+
277
+ function displayShareLink(link) {
278
+ return String(link || '').replace(/^https?:\/\//, '');
279
+ }
280
+
254
281
  export function createGameplayScene(context = {}) {
255
282
  const appState = context.appState && typeof context.appState === 'object'
256
283
  ? context.appState
@@ -272,6 +299,7 @@ export function createGameplayScene(context = {}) {
272
299
  function syncHud() {
273
300
  const roomInfo = currentRoomInfo(sceneState);
274
301
  const roomCode = currentRoomCode(sceneState);
302
+ const shareLink = currentLauncherJoinLink(sceneState);
275
303
  const diagnostics = DIAGNOSTICS_CONFIG.enabled
276
304
  ? {
277
305
  mode: roomInfo?.requestedMode || CONNECTIVITY_CONFIG.mode,
@@ -290,6 +318,7 @@ export function createGameplayScene(context = {}) {
290
318
  playerCount: Number(aura.multiplayer.getPlayerCount?.() || 0),
291
319
  connected: aura.multiplayer.isConnected() === true,
292
320
  showControlsHint: multiplayerUi.showControlsHint !== false,
321
+ shareLink: shareLink ? displayShareLink(shareLink) : null,
293
322
  statusLine: currentStatusLine(sceneState, roomCode),
294
323
  diagnostics,
295
324
  });
@@ -434,7 +463,7 @@ export function createGameplayScene(context = {}) {
434
463
  notes: [
435
464
  'Keep the room-code multiplayer dev loop starter-owned here instead of splitting it between src/main.js and layout-generated files.',
436
465
  'Use appState.session for durable room/session summary, appState.ui for HUD presentation state, and keep connection-side details scene-local.',
437
- 'aura.config.json -> multiplayer is the project-level source of truth for room code, room name, diagnostics, and relay defaults.',
466
+ 'aura.config.json -> multiplayer is the project-level source of truth for room code, room name, diagnostics, relay defaults, and optional launcher join pages.',
438
467
  'config/gameplay/local-multiplayer.config.js stays focused on local gameplay tuning like port, player speed, bounds, and fallback timing.',
439
468
  ],
440
469
  };
@@ -23,6 +23,7 @@ export function drawLocalMultiplayerHud({
23
23
  playerCount = 0,
24
24
  connected = false,
25
25
  showControlsHint = true,
26
+ shareLink = null,
26
27
  statusLine = '',
27
28
  diagnostics = null,
28
29
  } = {}) {
@@ -47,13 +48,17 @@ export function drawLocalMultiplayerHud({
47
48
  aura.draw2d.text(`Reason: ${diagnostics.lastReasonCode || '-'}`, LOCAL_MULTIPLAYER_CONFIG.width - 248, 122, 11, aura.rgb(0.82, 0.9, 0.86));
48
49
  }
49
50
 
50
- aura.draw2d.text(
51
- 'Room-code multiplayer. Put room + relay defaults in aura.config.json -> multiplayer.',
52
- 18,
53
- LOCAL_MULTIPLAYER_CONFIG.height - 28,
54
- 10,
55
- aura.rgb(0.76, 0.82, 0.92),
56
- );
51
+ if (shareLink) {
52
+ aura.draw2d.text(`Join link: ${shareLink}`, 18, LOCAL_MULTIPLAYER_CONFIG.height - 28, 10, aura.rgb(0.76, 0.82, 0.92));
53
+ } else {
54
+ aura.draw2d.text(
55
+ 'Room-code multiplayer. Put room + relay defaults in aura.config.json -> multiplayer.',
56
+ 18,
57
+ LOCAL_MULTIPLAYER_CONFIG.height - 28,
58
+ 10,
59
+ aura.rgb(0.76, 0.82, 0.92),
60
+ );
61
+ }
57
62
  aura.draw2d.text(`Connected: ${connected}`, LOCAL_MULTIPLAYER_CONFIG.width - 166, 16, 11, aura.rgb(0.82, 0.9, 0.86));
58
63
  }
59
64
 
@@ -604,6 +604,7 @@ function resolveProjectMultiplayerConfig() {
604
604
  relayHost: null,
605
605
  coordinatorUrl: null,
606
606
  relayUrl: null,
607
+ launcherBaseUrl: null,
607
608
  showDiagnostics: null,
608
609
  chatEnabled: null,
609
610
  chatHistoryLimit: null,
@@ -619,6 +620,7 @@ function resolveProjectMultiplayerConfig() {
619
620
  relayHost: readOptionalCliText(raw.relay || raw.relayHost),
620
621
  coordinatorUrl: readOptionalCliText(raw.coordinatorUrl),
621
622
  relayUrl: readOptionalCliText(raw.relayUrl),
623
+ launcherBaseUrl: readOptionalCliText(raw.launcherBaseUrl || raw.launcherUrl),
622
624
  showDiagnostics: typeof raw.showDiagnostics === 'boolean' ? raw.showDiagnostics : null,
623
625
  chatEnabled: typeof raw.chatEnabled === 'boolean' ? raw.chatEnabled : null,
624
626
  chatHistoryLimit: historyLimit,
@@ -679,6 +681,9 @@ async function resolveLocalMultiplayerCommandEnv() {
679
681
  if (relayUrl) {
680
682
  env.AURA_RELAY_URL = relayUrl;
681
683
  }
684
+ if (projectMultiplayer.launcherBaseUrl) {
685
+ env.AURA_MULTIPLAYER_LAUNCHER_BASE_URL = projectMultiplayer.launcherBaseUrl;
686
+ }
682
687
  if (typeof projectMultiplayer.showDiagnostics === 'boolean') {
683
688
  env.AURA_MULTIPLAYER_SHOW_DIAGNOSTICS = projectMultiplayer.showDiagnostics ? '1' : '0';
684
689
  }
@@ -900,7 +905,7 @@ function assertJoinSupported() {
900
905
  : 'project capability declarations';
901
906
  throw new Error(
902
907
  `join unavailable: multiplayer is disabled in ${sourceDetail}. `
903
- + `Use \`npm run play\` for a normal local launch or \`${packageBin} play\` for a packaged launch.`,
908
+ + `Use \`npm run dev\` for the local authoring loop, \`npm run play\` for a packaged local launch, or \`${packageBin} play\` for an installed package launch.`,
904
909
  );
905
910
  }
906
911
  }
@@ -1043,7 +1048,7 @@ async function main() {
1043
1048
 
1044
1049
  if (command === 'play') {
1045
1050
  printBanner('PLAY');
1046
- printSection(toDisplayTitle(packageName), 'Starting game + dev session...');
1051
+ printSection(toDisplayTitle(packageName), 'Starting packaged local game session...');
1047
1052
  const externalAssets = await maybePrepareExternalAssets('play');
1048
1053
  const multiplayerEnv = await resolveLocalMultiplayerCommandEnv();
1049
1054
  await runCommand(