@doodle-engine/cli 0.0.20 → 0.0.22

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/dist/cli.js CHANGED
@@ -206,16 +206,28 @@ function I(t) {
206
206
  console.log(c.green("✓ No validation errors"));
207
207
  return;
208
208
  }
209
- console.log(c.red(`
209
+ console.log(
210
+ c.red(
211
+ `
210
212
  ✗ Found ${t.length} validation error${t.length === 1 ? "" : "s"}:
211
- `));
213
+ `
214
+ )
215
+ );
212
216
  for (const o of t)
213
- console.log(c.bold(o.file) + (o.line ? `:${o.line}` : "")), console.log(" " + c.red(o.message)), o.suggestion && console.log(" " + c.dim(o.suggestion)), console.log();
217
+ console.log(
218
+ c.bold(o.file) + (o.line ? `:${o.line}` : "")
219
+ ), console.log(" " + c.red(o.message)), o.suggestion && console.log(" " + c.dim(o.suggestion)), console.log();
214
220
  }
215
221
  async function q(t, o, s, r, n = Date.now().toString()) {
216
- const { shell: a, game: e } = W(s, r);
222
+ const { shell: a, game: e } = W(
223
+ s,
224
+ r
225
+ );
217
226
  async function i(g) {
218
- const _ = h(o, g.startsWith("/") ? g.slice(1) : g);
227
+ const _ = h(
228
+ o,
229
+ g.startsWith("/") ? g.slice(1) : g
230
+ );
219
231
  try {
220
232
  return (await B(_)).size;
221
233
  } catch {
@@ -223,19 +235,23 @@ async function q(t, o, s, r, n = Date.now().toString()) {
223
235
  }
224
236
  }
225
237
  const l = await Promise.all(
226
- a.map(async (g) => ({
227
- path: g,
228
- type: R(g),
229
- size: await i(g),
230
- tier: 1
231
- }))
238
+ a.map(
239
+ async (g) => ({
240
+ path: g,
241
+ type: R(g),
242
+ size: await i(g),
243
+ tier: 1
244
+ })
245
+ )
232
246
  ), d = await Promise.all(
233
- e.map(async (g) => ({
234
- path: g,
235
- type: R(g),
236
- size: await i(g),
237
- tier: 2
238
- }))
247
+ e.map(
248
+ async (g) => ({
249
+ path: g,
250
+ type: R(g),
251
+ size: await i(g),
252
+ tier: 2
253
+ })
254
+ )
239
255
  ), u = l.reduce((g, _) => g + (_.size ?? 0), 0), m = d.reduce((g, _) => g + (_.size ?? 0), 0);
240
256
  return {
241
257
  version: n,
@@ -248,7 +264,9 @@ async function q(t, o, s, r, n = Date.now().toString()) {
248
264
  const S = "🐾", X = "✨", Z = "✏️", ee = "➕";
249
265
  async function te() {
250
266
  const t = process.cwd(), o = h(t, "content");
251
- console.log(""), console.log(c.bold.magenta(` ${S} Doodle Engine Dev Server ${S}`)), console.log("");
267
+ console.log(""), console.log(
268
+ c.bold.magenta(` ${S} Doodle Engine Dev Server ${S}`)
269
+ ), console.log("");
252
270
  const s = {
253
271
  name: "doodle-content-loader",
254
272
  configureServer(n) {
@@ -257,7 +275,12 @@ async function te() {
257
275
  const m = await j(o);
258
276
  u.setHeader("Content-Type", "application/json"), u.end(JSON.stringify(m));
259
277
  } catch (m) {
260
- console.error(c.red(" Error loading content:"), m), u.statusCode = 500, u.end(JSON.stringify({ error: "Failed to load content" }));
278
+ console.error(
279
+ c.red(" Error loading content:"),
280
+ m
281
+ ), u.statusCode = 500, u.end(
282
+ JSON.stringify({ error: "Failed to load content" })
283
+ );
261
284
  }
262
285
  }), n.middlewares.use("/api/manifest", async (d, u) => {
263
286
  try {
@@ -270,7 +293,12 @@ async function te() {
270
293
  );
271
294
  u.setHeader("Content-Type", "application/json"), u.end(JSON.stringify(_));
272
295
  } catch (m) {
273
- console.error(c.red(" Error generating manifest:"), m), u.statusCode = 500, u.end(JSON.stringify({ error: "Failed to generate manifest" }));
296
+ console.error(
297
+ c.red(" Error generating manifest:"),
298
+ m
299
+ ), u.statusCode = 500, u.end(
300
+ JSON.stringify({ error: "Failed to generate manifest" })
301
+ );
274
302
  }
275
303
  });
276
304
  const a = L(o, {
@@ -288,9 +316,13 @@ async function te() {
288
316
  }, 50);
289
317
  };
290
318
  a.on("change", (d) => {
291
- l(c.yellow(` ${Z} Content changed: ${d}`));
319
+ l(
320
+ c.yellow(` ${Z} Content changed: ${d}`)
321
+ );
292
322
  }), a.on("add", (d) => {
293
- e && l(c.green(` ${ee} Content added: ${d}`));
323
+ e && l(
324
+ c.green(` ${ee} Content added: ${d}`)
325
+ );
294
326
  });
295
327
  }
296
328
  }, r = await F({
@@ -301,7 +333,9 @@ async function te() {
301
333
  open: !0
302
334
  }
303
335
  });
304
- await r.listen(), r.printUrls(), console.log(""), console.log(c.dim(` ${X} Watching content files for changes...`)), console.log("");
336
+ await r.listen(), r.printUrls(), console.log(""), console.log(
337
+ c.dim(` ${X} Watching content files for changes...`)
338
+ ), console.log("");
305
339
  }
306
340
  async function j(t) {
307
341
  const o = {
@@ -535,7 +569,10 @@ async function re() {
535
569
  n,
536
570
  Date.now().toString()
537
571
  ), l = h(a, "api");
538
- await T(l, { recursive: !0 }), await w(h(l, "content"), JSON.stringify(s)), await w(h(l, "manifest"), JSON.stringify(i)), await w(h(a, "asset-manifest.json"), JSON.stringify(i, null, 2)), console.log(c.dim("Generating service worker..."));
572
+ await T(l, { recursive: !0 }), await w(h(l, "content"), JSON.stringify(s)), await w(h(l, "manifest"), JSON.stringify(i)), await w(
573
+ h(a, "asset-manifest.json"),
574
+ JSON.stringify(i, null, 2)
575
+ ), console.log(c.dim("Generating service worker..."));
539
576
  const d = ae(i);
540
577
  await w(h(a, "sw.js"), d), console.log(""), console.log(c.green("✅ Build complete! Output in dist/")), console.log(""), console.log("To preview the build:"), console.log(c.dim(" yarn preview")), console.log("");
541
578
  } catch (a) {
@@ -597,7 +634,14 @@ async function se(t) {
597
634
  const a = h(t, "game.yaml"), e = await p(a, "utf-8");
598
635
  n = y(e);
599
636
  } catch {
600
- n = { id: "game", startLocation: "", startTime: { day: 1, hour: 8 }, startFlags: {}, startVariables: {}, startInventory: [] };
637
+ n = {
638
+ id: "game",
639
+ startLocation: "",
640
+ startTime: { day: 1, hour: 8 },
641
+ startFlags: {},
642
+ startVariables: {},
643
+ startInventory: []
644
+ };
601
645
  }
602
646
  return { registry: o, fileMap: s, config: n };
603
647
  }
@@ -667,33 +711,33 @@ dist
667
711
  *.log
668
712
  `, de = `<!doctype html>
669
713
  <html lang="en">
670
- <head>
671
- <meta charset="UTF-8" />
672
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
673
- <title>Doodle Engine Game</title>
674
- </head>
675
- <body>
676
- <div id="root"></div>
677
- <script type="module" src="/src/main.tsx"><\/script>
678
- </body>
714
+ <head>
715
+ <meta charset="UTF-8" />
716
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
717
+ <title>Doodle Engine Game</title>
718
+ </head>
719
+ <body>
720
+ <div id="root"></div>
721
+ <script type="module" src="/src/main.tsx"><\/script>
722
+ </body>
679
723
  </html>
680
724
  `, ue = `{
681
- "compilerOptions": {
682
- "target": "ES2024",
683
- "lib": ["ES2024", "DOM", "DOM.Iterable"],
684
- "module": "ESNext",
685
- "moduleResolution": "bundler",
686
- "jsx": "react-jsx",
687
- "strict": true,
688
- "skipLibCheck": true,
689
- "esModuleInterop": true,
690
- "forceConsistentCasingInFileNames": true,
691
- "resolveJsonModule": true,
692
- "isolatedModules": true,
693
- "noEmit": true,
694
- "types": ["vite/client"]
695
- },
696
- "include": ["src"]
725
+ "compilerOptions": {
726
+ "target": "ES2024",
727
+ "lib": ["ES2024", "DOM", "DOM.Iterable"],
728
+ "module": "ESNext",
729
+ "moduleResolution": "bundler",
730
+ "jsx": "react-jsx",
731
+ "strict": true,
732
+ "skipLibCheck": true,
733
+ "esModuleInterop": true,
734
+ "forceConsistentCasingInFileNames": true,
735
+ "resolveJsonModule": true,
736
+ "isolatedModules": true,
737
+ "noEmit": true,
738
+ "types": ["vite/client"]
739
+ },
740
+ "include": ["src"]
697
741
  }
698
742
  `, he = `id: bartender
699
743
  name: "@character.bartender.name"
@@ -1364,147 +1408,190 @@ stages:
1364
1408
  description: "@quest.odd_jobs.stage.talked_to_merchant"
1365
1409
  - id: complete
1366
1410
  description: "@quest.odd_jobs.stage.complete"
1367
- `, Re = `import { useEffect, useState } from 'react'
1368
- import { Engine } from '@doodle-engine/core'
1369
- import type { GameState, Snapshot } from '@doodle-engine/core'
1370
- import { GameProvider, useGame } from '@doodle-engine/react'
1411
+ `, Re = `import { useEffect, useState } from 'react';
1412
+ import { Engine } from '@doodle-engine/core';
1413
+ import type { GameState, Snapshot } from '@doodle-engine/core';
1414
+ import { GameProvider, useGame } from '@doodle-engine/react';
1371
1415
 
1372
1416
  export function App() {
1373
- const [game, setGame] = useState<{ engine: Engine; snapshot: Snapshot } | null>(null)
1374
-
1375
- useEffect(() => {
1376
- fetch('/api/content')
1377
- .then(res => res.json())
1378
- .then(data => {
1379
- const engine = new Engine(data.registry, createEmptyState())
1380
- const snapshot = engine.newGame(data.config)
1381
- setGame({ engine, snapshot })
1382
- })
1383
- }, [])
1384
-
1385
- if (!game) {
1386
- return <div className="app-bootstrap"><div className="spinner" /></div>
1387
- }
1417
+ const [game, setGame] = useState<{
1418
+ engine: Engine;
1419
+ snapshot: Snapshot;
1420
+ } | null>(null);
1421
+
1422
+ useEffect(() => {
1423
+ fetch('/api/content')
1424
+ .then((res) => res.json())
1425
+ .then((data) => {
1426
+ const engine = new Engine(data.registry, createEmptyState());
1427
+ const snapshot = engine.newGame(data.config);
1428
+ setGame({ engine, snapshot });
1429
+ });
1430
+ }, []);
1431
+
1432
+ if (!game) {
1433
+ return (
1434
+ <div className="app-bootstrap">
1435
+ <div className="spinner" />
1436
+ </div>
1437
+ );
1438
+ }
1388
1439
 
1389
- return (
1390
- <GameProvider engine={game.engine} initialSnapshot={game.snapshot} devTools={import.meta.env.DEV}>
1391
- <GameUI />
1392
- </GameProvider>
1393
- )
1440
+ return (
1441
+ <GameProvider
1442
+ engine={game.engine}
1443
+ initialSnapshot={game.snapshot}
1444
+ devTools={import.meta.env.DEV}
1445
+ >
1446
+ <GameUI />
1447
+ </GameProvider>
1448
+ );
1394
1449
  }
1395
1450
 
1396
1451
  function GameUI() {
1397
- const { snapshot, actions } = useGame()
1398
-
1399
- return (
1400
- <div style={{ padding: '2rem', fontFamily: 'sans-serif', maxWidth: '800px', margin: '0 auto' }}>
1401
- <h1>{snapshot.location.name}</h1>
1402
- <p>{snapshot.location.description}</p>
1403
-
1404
- {snapshot.dialogue && (
1405
- <div style={{ background: '#f0f0f0', padding: '1rem', borderRadius: '8px', margin: '1rem 0' }}>
1406
- <strong>{snapshot.dialogue.speakerName}:</strong>
1407
- <p>{snapshot.dialogue.text}</p>
1408
- {snapshot.choices.map(choice => (
1409
- <button
1410
- key={choice.id}
1411
- onClick={() => actions.selectChoice(choice.id)}
1412
- style={{ display: 'block', margin: '0.5rem 0', padding: '0.5rem 1rem', cursor: 'pointer' }}
1413
- >
1414
- {choice.text}
1415
- </button>
1416
- ))}
1417
- </div>
1418
- )}
1419
-
1420
- {!snapshot.dialogue && snapshot.charactersHere.length > 0 && (
1421
- <div>
1422
- <h2>Characters here</h2>
1423
- {snapshot.charactersHere.map(char => (
1424
- <button
1425
- key={char.id}
1426
- onClick={() => actions.talkTo(char.id)}
1427
- style={{ display: 'block', margin: '0.5rem 0', padding: '0.5rem 1rem', cursor: 'pointer' }}
1428
- >
1429
- Talk to {char.name}
1430
- </button>
1431
- ))}
1452
+ const { snapshot, actions } = useGame();
1453
+
1454
+ return (
1455
+ <div
1456
+ style={{
1457
+ padding: '2rem',
1458
+ fontFamily: 'sans-serif',
1459
+ maxWidth: '800px',
1460
+ margin: '0 auto',
1461
+ }}
1462
+ >
1463
+ <h1>{snapshot.location.name}</h1>
1464
+ <p>{snapshot.location.description}</p>
1465
+
1466
+ {snapshot.dialogue && (
1467
+ <div
1468
+ style={{
1469
+ background: '#f0f0f0',
1470
+ padding: '1rem',
1471
+ borderRadius: '8px',
1472
+ margin: '1rem 0',
1473
+ }}
1474
+ >
1475
+ <strong>{snapshot.dialogue.speakerName}:</strong>
1476
+ <p>{snapshot.dialogue.text}</p>
1477
+ {snapshot.choices.map((choice) => (
1478
+ <button
1479
+ key={choice.id}
1480
+ onClick={() => actions.selectChoice(choice.id)}
1481
+ style={{
1482
+ display: 'block',
1483
+ margin: '0.5rem 0',
1484
+ padding: '0.5rem 1rem',
1485
+ cursor: 'pointer',
1486
+ }}
1487
+ >
1488
+ {choice.text}
1489
+ </button>
1490
+ ))}
1491
+ </div>
1492
+ )}
1493
+
1494
+ {!snapshot.dialogue && snapshot.charactersHere.length > 0 && (
1495
+ <div>
1496
+ <h2>Characters here</h2>
1497
+ {snapshot.charactersHere.map((char) => (
1498
+ <button
1499
+ key={char.id}
1500
+ onClick={() => actions.talkTo(char.id)}
1501
+ style={{
1502
+ display: 'block',
1503
+ margin: '0.5rem 0',
1504
+ padding: '0.5rem 1rem',
1505
+ cursor: 'pointer',
1506
+ }}
1507
+ >
1508
+ Talk to {char.name}
1509
+ </button>
1510
+ ))}
1511
+ </div>
1512
+ )}
1432
1513
  </div>
1433
- )}
1434
- </div>
1435
- )
1514
+ );
1436
1515
  }
1437
1516
 
1438
1517
  function createEmptyState(): GameState {
1439
- return {
1440
- currentLocation: '',
1441
- currentTime: { day: 1, hour: 0 },
1442
- flags: {},
1443
- variables: {},
1444
- inventory: [],
1445
- questProgress: {},
1446
- unlockedJournalEntries: [],
1447
- playerNotes: [],
1448
- dialogueState: null,
1449
- characterState: {},
1450
- itemLocations: {},
1451
- mapEnabled: true,
1452
- notifications: [],
1453
- pendingSounds: [],
1454
- pendingVideo: null,
1455
- pendingInterlude: null,
1456
- currentLocale: 'en',
1457
- }
1518
+ return {
1519
+ currentLocation: '',
1520
+ currentTime: { day: 1, hour: 0 },
1521
+ flags: {},
1522
+ variables: {},
1523
+ inventory: [],
1524
+ questProgress: {},
1525
+ unlockedJournalEntries: [],
1526
+ playerNotes: [],
1527
+ dialogueState: null,
1528
+ characterState: {},
1529
+ itemLocations: {},
1530
+ mapEnabled: true,
1531
+ notifications: [],
1532
+ pendingSounds: [],
1533
+ pendingVideo: null,
1534
+ pendingInterlude: null,
1535
+ currentLocale: 'en',
1536
+ };
1458
1537
  }
1459
- `, Ae = `import { useEffect, useState } from 'react'
1460
- import type { ContentRegistry, GameConfig, AssetManifest } from '@doodle-engine/core'
1461
- import { GameShell } from '@doodle-engine/react'
1538
+ `, Ae = `import { useEffect, useState } from 'react';
1539
+ import type {
1540
+ ContentRegistry,
1541
+ GameConfig,
1542
+ AssetManifest,
1543
+ } from '@doodle-engine/core';
1544
+ import { GameShell } from '@doodle-engine/react';
1462
1545
 
1463
1546
  export function App() {
1464
- const [content, setContent] = useState<{
1465
- registry: ContentRegistry
1466
- config: GameConfig
1467
- } | null>(null)
1468
- const [manifest, setManifest] = useState<AssetManifest | null>(null)
1469
-
1470
- useEffect(() => {
1471
- Promise.all([
1472
- fetch('/api/content').then(res => res.json()),
1473
- fetch('/api/manifest').then(res => res.json()),
1474
- ]).then(([contentData, manifestData]) => {
1475
- setContent({ registry: contentData.registry, config: contentData.config })
1476
- setManifest(manifestData)
1477
- })
1478
- }, [])
1547
+ const [content, setContent] = useState<{
1548
+ registry: ContentRegistry;
1549
+ config: GameConfig;
1550
+ } | null>(null);
1551
+ const [manifest, setManifest] = useState<AssetManifest | null>(null);
1552
+
1553
+ useEffect(() => {
1554
+ Promise.all([
1555
+ fetch('/api/content').then((res) => res.json()),
1556
+ fetch('/api/manifest').then((res) => res.json()),
1557
+ ]).then(([contentData, manifestData]) => {
1558
+ setContent({
1559
+ registry: contentData.registry,
1560
+ config: contentData.config,
1561
+ });
1562
+ setManifest(manifestData);
1563
+ });
1564
+ }, []);
1565
+
1566
+ // Minimal bootstrap state while fetching manifest/content
1567
+ if (!content || !manifest) {
1568
+ return (
1569
+ <div className="app-bootstrap">
1570
+ <div className="spinner" />
1571
+ </div>
1572
+ );
1573
+ }
1479
1574
 
1480
- // Minimal bootstrap state while fetching manifest/content
1481
- if (!content || !manifest) {
1482
1575
  return (
1483
- <div className="app-bootstrap">
1484
- <div className="spinner" />
1485
- </div>
1486
- )
1487
- }
1488
-
1489
- return (
1490
- <GameShell
1491
- registry={content.registry}
1492
- config={content.config}
1493
- manifest={manifest}
1494
- title="My Doodle Game"
1495
- subtitle="A text-based adventure"
1496
- availableLocales={[{ code: 'en', label: 'English' }]}
1497
- devTools={import.meta.env.DEV}
1498
- />
1499
- )
1576
+ <GameShell
1577
+ registry={content.registry}
1578
+ config={content.config}
1579
+ manifest={manifest}
1580
+ title="My Doodle Game"
1581
+ subtitle="A text-based adventure"
1582
+ availableLocales={[{ code: 'en', label: 'English' }]}
1583
+ devTools={import.meta.env.DEV}
1584
+ />
1585
+ );
1500
1586
  }
1501
1587
  `, Se = `body {
1502
- margin: 0;
1503
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
1504
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
1505
- sans-serif;
1506
- -webkit-font-smoothing: antialiased;
1507
- -moz-osx-font-smoothing: grayscale;
1588
+ margin: 0;
1589
+ font-family:
1590
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
1591
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
1592
+ sans-serif;
1593
+ -webkit-font-smoothing: antialiased;
1594
+ -moz-osx-font-smoothing: grayscale;
1508
1595
  }
1509
1596
 
1510
1597
  /* ── Theme overrides ──────────────────────────────────────────────── */
@@ -1518,24 +1605,24 @@ export function App() {
1518
1605
  --doodle-accent: #6366f1;
1519
1606
  }
1520
1607
  */
1521
- `, je = `import { StrictMode } from 'react'
1522
- import { createRoot } from 'react-dom/client'
1523
- import '@doodle-engine/react/style.css'
1524
- import { App } from './App'
1525
- import './index.css'
1608
+ `, je = `import { StrictMode } from 'react';
1609
+ import { createRoot } from 'react-dom/client';
1610
+ import '@doodle-engine/react/style.css';
1611
+ import { App } from './App';
1612
+ import './index.css';
1526
1613
 
1527
1614
  // Register service worker in production for offline asset caching
1528
1615
  if ('serviceWorker' in navigator && import.meta.env.PROD) {
1529
- navigator.serviceWorker.register('/sw.js').catch(() => {
1530
- // SW registration failure is non-fatal
1531
- })
1616
+ navigator.serviceWorker.register('/sw.js').catch(() => {
1617
+ // SW registration failure is non-fatal
1618
+ });
1532
1619
  }
1533
1620
 
1534
1621
  createRoot(document.getElementById('root')!).render(
1535
- <StrictMode>
1536
- <App />
1537
- </StrictMode>,
1538
- )
1622
+ <StrictMode>
1623
+ <App />
1624
+ </StrictMode>
1625
+ );
1539
1626
  `, D = "🐾", xe = "🐕", H = "🦴", Ge = "✨", $ = "📁", N = "✅", qe = "🚀", x = /* @__PURE__ */ Object.assign({
1540
1627
  "./templates/_root/_gitignore": le,
1541
1628
  "./templates/_root/index.html": de,
@@ -1565,7 +1652,8 @@ createRoot(document.getElementById('root')!).render(
1565
1652
  });
1566
1653
  function He(t) {
1567
1654
  const o = t.replace("./templates/", "");
1568
- if (o === "src/App.default.tsx" || o === "src/App.custom.tsx") return null;
1655
+ if (o === "src/App.default.tsx" || o === "src/App.custom.tsx")
1656
+ return null;
1569
1657
  if (o.startsWith("_root/")) {
1570
1658
  const s = o.slice(6);
1571
1659
  return s.startsWith("_") ? "." + s.slice(1) : s;
@@ -1581,8 +1669,14 @@ async function $e(t) {
1581
1669
  message: "Use default renderer?",
1582
1670
  initial: !0
1583
1671
  });
1584
- s === void 0 && (console.log(c.yellow(`
1585
- ${H} No worries, maybe next time! Woof!`)), process.exit(0)), console.log(""), await Me(o, t, s), console.log(""), console.log(c.bold.green(` ${N} Project created successfully!`)), console.log(""), console.log(c.dim(` ${$} ${o}`)), console.log(""), console.log(c.bold(" Next steps:")), console.log(c.cyan(` cd ${t}`)), console.log(c.cyan(" npm install ") + c.dim("# or: yarn install / pnpm install")), console.log(c.cyan(" npm run dev ") + c.dim("# or: yarn dev / pnpm dev")), console.log(""), console.log(c.dim(` ${qe} Happy game making! ${D}`)), console.log("");
1672
+ s === void 0 && (console.log(
1673
+ c.yellow(`
1674
+ ${H} No worries, maybe next time! Woof!`)
1675
+ ), process.exit(0)), console.log(""), await Me(o, t, s), console.log(""), console.log(c.bold.green(` ${N} Project created successfully!`)), console.log(""), console.log(c.dim(` ${$} ${o}`)), console.log(""), console.log(c.bold(" Next steps:")), console.log(c.cyan(` cd ${t}`)), console.log(
1676
+ c.cyan(" npm install ") + c.dim("# or: yarn install / pnpm install")
1677
+ ), console.log(
1678
+ c.cyan(" npm run dev ") + c.dim("# or: yarn dev / pnpm dev")
1679
+ ), console.log(""), console.log(c.dim(` ${qe} Happy game making! ${D}`)), console.log("");
1586
1680
  }
1587
1681
  async function Me(t, o, s) {
1588
1682
  const r = [
@@ -1632,7 +1726,10 @@ async function Me(t, o, s) {
1632
1726
  vite: "^6.0.0"
1633
1727
  }
1634
1728
  };
1635
- console.log(` ${Ge} ${c.bold("Writing project files...")}`), await w(h(t, "package.json"), JSON.stringify(n, null, 2));
1729
+ console.log(` ${Ge} ${c.bold("Writing project files...")}`), await w(
1730
+ h(t, "package.json"),
1731
+ JSON.stringify(n, null, 2)
1732
+ );
1636
1733
  for (const [e, i] of Object.entries(x)) {
1637
1734
  const l = He(e);
1638
1735
  if (l === null) continue;
@@ -1640,10 +1737,18 @@ async function Me(t, o, s) {
1640
1737
  await T(U(d), { recursive: !0 }), await w(d, i);
1641
1738
  }
1642
1739
  const a = s ? "./templates/src/App.default.tsx" : "./templates/src/App.custom.tsx";
1643
- await w(h(t, "src/App.tsx"), x[a]), console.log(c.green(` ${N} Source files created`)), console.log(""), console.log(` ${H} ${c.bold("Starter content written")}`), console.log(""), console.log(c.dim(" Content includes:")), console.log(c.dim(" 2 locations (tavern, market)")), console.log(c.dim(" 2 characters (bartender, merchant)")), console.log(c.dim(" 1 item (old coin)")), console.log(c.dim(" 1 map (town with 2 locations)")), console.log(c.dim(" 1 quest (odd jobs, 3 stages)")), console.log(c.dim(" 3 journal entries")), console.log(c.dim(" 1 interlude (chapter one, auto-triggers at tavern)")), console.log(c.dim(" 5 dialogues (2 narrator intros, 2 NPC conversations, 1 skill check)")), console.log(c.dim(" English locale with all strings"));
1740
+ await w(h(t, "src/App.tsx"), x[a]), console.log(c.green(` ${N} Source files created`)), console.log(""), console.log(` ${H} ${c.bold("Starter content written")}`), console.log(""), console.log(c.dim(" Content includes:")), console.log(c.dim(" 2 locations (tavern, market)")), console.log(c.dim(" 2 characters (bartender, merchant)")), console.log(c.dim(" 1 item (old coin)")), console.log(c.dim(" 1 map (town with 2 locations)")), console.log(c.dim(" 1 quest (odd jobs, 3 stages)")), console.log(c.dim(" 3 journal entries")), console.log(
1741
+ c.dim(" 1 interlude (chapter one, auto-triggers at tavern)")
1742
+ ), console.log(
1743
+ c.dim(
1744
+ " 5 dialogues (2 narrator intros, 2 NPC conversations, 1 skill check)"
1745
+ )
1746
+ ), console.log(c.dim(" English locale with all strings"));
1644
1747
  }
1645
1748
  const v = new M();
1646
- v.name("doodle").description(c.magenta("🐾 Doodle Engine") + c.dim(" — Narrative RPG development tools")).version("0.0.1");
1749
+ v.name("doodle").description(
1750
+ c.magenta("🐾 Doodle Engine") + c.dim(" — Narrative RPG development tools")
1751
+ ).version("0.0.1");
1647
1752
  v.command("create <project-name>").description("Scaffold a new Doodle Engine game project").action(async (t) => {
1648
1753
  await $e(t);
1649
1754
  });
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,wBAAsB,KAAK,kBAoF1B"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,wBAAsB,KAAK,kBAuF1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,wBAAsB,GAAG,kBAqGxB"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,wBAAsB,GAAG,kBA0HxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4CH,wBAAsB,MAAM,CAAC,WAAW,EAAE,MAAM,iBAwC/C"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA6CH,wBAAsB,MAAM,CAAC,WAAW,EAAE,MAAM,iBAgD/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,qBAAqB,CAAA;AAEpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAErD;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,MAA8B,GACtC,OAAO,CAAC,aAAa,CAAC,CA0CxB"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,qBAAqB,CAAC;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACvC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,MAA8B,GACxC,OAAO,CAAC,aAAa,CAAC,CAoDxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"service-worker.d.ts","sourceRoot":"","sources":["../src/service-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CA8ErE"}
1
+ {"version":3,"file":"service-worker.d.ts","sourceRoot":"","sources":["../src/service-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CA8ErE"}