@korajs/cli 0.6.0 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin.cjs +2582 -202
  3. package/dist/bin.cjs.map +1 -1
  4. package/dist/bin.js +152 -96
  5. package/dist/bin.js.map +1 -1
  6. package/dist/chunk-5NI2FEQL.js +92 -0
  7. package/dist/chunk-5NI2FEQL.js.map +1 -0
  8. package/dist/chunk-6C4BHSRA.js +82 -0
  9. package/dist/chunk-6C4BHSRA.js.map +1 -0
  10. package/dist/{chunk-VLTPEATY.js → chunk-B5YS4STN.js} +9 -96
  11. package/dist/chunk-B5YS4STN.js.map +1 -0
  12. package/dist/{chunk-EEZNRI5W.js → chunk-BWTKRKNJ.js} +13 -5
  13. package/dist/{chunk-EEZNRI5W.js.map → chunk-BWTKRKNJ.js.map} +1 -1
  14. package/dist/{chunk-Q2FBCOQD.js → chunk-EOWLAAIV.js} +5 -3
  15. package/dist/{chunk-Q2FBCOQD.js.map → chunk-EOWLAAIV.js.map} +1 -1
  16. package/dist/create.cjs +8 -2
  17. package/dist/create.cjs.map +1 -1
  18. package/dist/create.js +3 -2
  19. package/dist/create.js.map +1 -1
  20. package/dist/index.js +3 -2
  21. package/dist/lab-manager-KUDII6BT.js +280 -0
  22. package/dist/lab-manager-KUDII6BT.js.map +1 -0
  23. package/dist/schema-loader-GGHECMTM.js +9 -0
  24. package/dist/schema-loader-GGHECMTM.js.map +1 -0
  25. package/dist/spectator-manager-E2LH2P54.js +142 -0
  26. package/dist/spectator-manager-E2LH2P54.js.map +1 -0
  27. package/dist/studio-server-NIFKZI4F.js +1738 -0
  28. package/dist/studio-server-NIFKZI4F.js.map +1 -0
  29. package/package.json +8 -6
  30. package/templates/react-basic/AGENTS.md +87 -0
  31. package/templates/react-sync/AGENTS.md +87 -0
  32. package/templates/react-sync/src/App.tsx +8 -0
  33. package/templates/react-sync/src/index.css +11 -0
  34. package/templates/react-tailwind/AGENTS.md +87 -0
  35. package/templates/react-tailwind-sync/AGENTS.md +87 -0
  36. package/templates/react-tailwind-sync/src/App.tsx +28 -0
  37. package/templates/svelte-basic/AGENTS.md +76 -0
  38. package/templates/svelte-basic/src/App.svelte +27 -31
  39. package/templates/svelte-basic/src/Root.svelte +4 -4
  40. package/templates/svelte-basic/src/modules/todos/useTodos.ts +1 -1
  41. package/templates/svelte-basic/vite.config.ts +1 -1
  42. package/templates/svelte-sync/AGENTS.md +76 -0
  43. package/templates/svelte-sync/src/App.svelte +31 -35
  44. package/templates/svelte-sync/src/Root.svelte +6 -6
  45. package/templates/svelte-sync/src/modules/todos/useTodos.ts +1 -1
  46. package/templates/svelte-tailwind/AGENTS.md +76 -0
  47. package/templates/svelte-tailwind/src/App.svelte +17 -21
  48. package/templates/svelte-tailwind/src/Root.svelte +4 -4
  49. package/templates/svelte-tailwind/src/modules/todos/useTodos.ts +1 -1
  50. package/templates/svelte-tailwind/vite.config.ts +2 -2
  51. package/templates/svelte-tailwind-sync/AGENTS.md +76 -0
  52. package/templates/svelte-tailwind-sync/src/App.svelte +52 -56
  53. package/templates/svelte-tailwind-sync/src/Root.svelte +6 -6
  54. package/templates/svelte-tailwind-sync/src/modules/todos/useTodos.ts +1 -1
  55. package/templates/svelte-tailwind-sync/vite.config.ts +1 -1
  56. package/templates/tauri-react/AGENTS.md +91 -0
  57. package/templates/vue-basic/AGENTS.md +84 -0
  58. package/templates/vue-basic/src/modules/todos/useTodos.ts +1 -1
  59. package/templates/vue-sync/AGENTS.md +84 -0
  60. package/templates/vue-sync/src/main.ts +5 -1
  61. package/templates/vue-sync/src/modules/todos/useTodos.ts +1 -1
  62. package/templates/vue-tailwind/AGENTS.md +84 -0
  63. package/templates/vue-tailwind/src/App.vue +1 -8
  64. package/templates/vue-tailwind/src/modules/todos/useTodos.ts +1 -1
  65. package/templates/vue-tailwind-sync/AGENTS.md +84 -0
  66. package/templates/vue-tailwind-sync/src/modules/todos/useTodos.ts +1 -1
  67. package/dist/chunk-VLTPEATY.js.map +0 -1
package/dist/bin.js CHANGED
@@ -1,25 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createCommand
4
- } from "./chunk-EEZNRI5W.js";
4
+ } from "./chunk-BWTKRKNJ.js";
5
5
  import {
6
6
  deployCommand,
7
7
  generateTypes
8
- } from "./chunk-Q2FBCOQD.js";
8
+ } from "./chunk-EOWLAAIV.js";
9
9
  import {
10
10
  DevServerError,
11
11
  InvalidProjectError,
12
12
  SchemaNotFoundError,
13
13
  createLogger,
14
+ promptConfirm
15
+ } from "./chunk-B5YS4STN.js";
16
+ import {
17
+ loadSchemaDefinition
18
+ } from "./chunk-6C4BHSRA.js";
19
+ import {
14
20
  findProjectRoot,
15
21
  findSchemaFile,
16
22
  hasTsxInstalled,
17
- promptConfirm,
18
23
  resolveProjectBinaryEntryPoint
19
- } from "./chunk-VLTPEATY.js";
24
+ } from "./chunk-5NI2FEQL.js";
20
25
 
21
26
  // src/bin.ts
22
- import { defineCommand as defineCommand9, runMain } from "citty";
27
+ import { defineCommand as defineCommand10, runMain } from "citty";
23
28
 
24
29
  // src/commands/backup/backup-command.ts
25
30
  import { readFile, writeFile } from "fs/promises";
@@ -247,7 +252,7 @@ async function loadTypeScriptConfig(configPath, projectRoot) {
247
252
  }
248
253
  }
249
254
  async function runCommand(command, args, cwd) {
250
- return await new Promise((resolve6, reject) => {
255
+ return await new Promise((resolve7, reject) => {
251
256
  const child = spawn(command, args, {
252
257
  cwd,
253
258
  stdio: ["ignore", "pipe", "pipe"],
@@ -266,7 +271,7 @@ async function runCommand(command, args, cwd) {
266
271
  });
267
272
  child.on("exit", (code) => {
268
273
  if (code === 0) {
269
- resolve6(stdout.trim());
274
+ resolve7(stdout.trim());
270
275
  return;
271
276
  }
272
277
  reject(new Error(`Failed to load kora config (exit ${code ?? "unknown"}): ${stderr.trim()}`));
@@ -284,79 +289,6 @@ function toConfigObject(mod) {
284
289
  return value;
285
290
  }
286
291
 
287
- // src/commands/migrate/schema-loader.ts
288
- import { spawn as spawn2 } from "child_process";
289
- import { extname as extname2 } from "path";
290
- import { pathToFileURL as pathToFileURL2 } from "url";
291
- async function loadSchemaDefinition(schemaPath, projectRoot) {
292
- const ext = extname2(schemaPath);
293
- const moduleValue = ext === ".ts" || ext === ".mts" || ext === ".cts" ? await loadTypeScriptModule(schemaPath, projectRoot) : await import(`${pathToFileURL2(schemaPath).href}?t=${Date.now()}-${Math.random()}`);
294
- return extractSchema(moduleValue);
295
- }
296
- function extractSchema(value) {
297
- if (typeof value !== "object" || value === null) {
298
- throw new Error("Schema module must export an object.");
299
- }
300
- const moduleRecord = value;
301
- const candidate = moduleRecord.default ?? moduleRecord;
302
- if (!isSchemaDefinition(candidate)) {
303
- throw new Error("Schema module must export a valid SchemaDefinition as default export.");
304
- }
305
- return candidate;
306
- }
307
- function isSchemaDefinition(value) {
308
- if (typeof value !== "object" || value === null) return false;
309
- const object = value;
310
- return typeof object.version === "number" && typeof object.collections === "object" && object.collections !== null && typeof object.relations === "object" && object.relations !== null;
311
- }
312
- async function loadTypeScriptModule(schemaPath, projectRoot) {
313
- if (!await hasTsxInstalled(projectRoot)) {
314
- throw new Error(
315
- `Schema file is TypeScript (${schemaPath}) but local "tsx" was not found. Install tsx in the project.`
316
- );
317
- }
318
- const script = "const modulePath = process.argv[process.argv.length - 1];import('node:url').then(u => import(u.pathToFileURL(modulePath).href)).then(mod => { const v = mod.default ?? mod; process.stdout.write(JSON.stringify(v)) }).catch(e => { process.stderr.write(String(e)); process.exit(1) })";
319
- const output = await runCommand2(
320
- process.execPath,
321
- ["--import", "tsx", "--eval", script, schemaPath],
322
- projectRoot
323
- );
324
- try {
325
- return JSON.parse(output);
326
- } catch {
327
- throw new Error(`Failed to parse schema module output for ${schemaPath}`);
328
- }
329
- }
330
- async function runCommand2(command, args, cwd) {
331
- return await new Promise((resolve6, reject) => {
332
- const child = spawn2(command, args, {
333
- cwd,
334
- stdio: ["ignore", "pipe", "pipe"],
335
- env: process.env
336
- });
337
- let stdout = "";
338
- let stderr = "";
339
- child.stdout?.on("data", (chunk) => {
340
- stdout += chunk.toString("utf-8");
341
- });
342
- child.stderr?.on("data", (chunk) => {
343
- stderr += chunk.toString("utf-8");
344
- });
345
- child.on("error", (error) => {
346
- reject(error);
347
- });
348
- child.on("exit", (code) => {
349
- if (code === 0) {
350
- resolve6(stdout.trim());
351
- return;
352
- }
353
- reject(
354
- new Error(`Failed to load TypeScript schema (exit ${code ?? "unknown"}): ${stderr.trim()}`)
355
- );
356
- });
357
- });
358
- }
359
-
360
292
  // src/commands/compact/compact-command.ts
361
293
  var compactCommand = defineCommand2({
362
294
  meta: {
@@ -448,8 +380,8 @@ var ProcessManager = class {
448
380
  let resolveExit;
449
381
  const runningProcess = {
450
382
  child,
451
- exitPromise: new Promise((resolve6) => {
452
- resolveExit = resolve6;
383
+ exitPromise: new Promise((resolve7) => {
384
+ resolveExit = resolve7;
453
385
  }),
454
386
  stdoutBuffer: "",
455
387
  stderrBuffer: ""
@@ -516,13 +448,13 @@ var ProcessManager = class {
516
448
  }
517
449
  };
518
450
  function delay(ms) {
519
- return new Promise((resolve6) => {
520
- setTimeout(resolve6, ms);
451
+ return new Promise((resolve7) => {
452
+ setTimeout(resolve7, ms);
521
453
  });
522
454
  }
523
455
 
524
456
  // src/commands/dev/schema-watcher.ts
525
- import { spawn as spawn3 } from "child_process";
457
+ import { spawn as spawn2 } from "child_process";
526
458
  import { watch } from "fs";
527
459
  import { join as join3 } from "path";
528
460
  var SchemaWatcher = class {
@@ -579,8 +511,8 @@ var SchemaWatcher = class {
579
511
  }
580
512
  };
581
513
  async function spawnCommand(command, args, cwd) {
582
- await new Promise((resolve6, reject) => {
583
- const child = spawn3(command, args, {
514
+ await new Promise((resolve7, reject) => {
515
+ const child = spawn2(command, args, {
584
516
  cwd,
585
517
  stdio: ["ignore", "pipe", "pipe"],
586
518
  env: process.env
@@ -596,7 +528,7 @@ async function spawnCommand(command, args, cwd) {
596
528
  });
597
529
  child.on("exit", (code) => {
598
530
  if (code === 0) {
599
- resolve6();
531
+ resolve7();
600
532
  return;
601
533
  }
602
534
  reject(new Error(`Type generation exited with code ${code ?? "unknown"}.`));
@@ -706,8 +638,8 @@ var devCommand = defineCommand3({
706
638
  let schemaWatcher = null;
707
639
  let shuttingDown = false;
708
640
  let resolveFinished;
709
- const finished = new Promise((resolve6) => {
710
- resolveFinished = resolve6;
641
+ const finished = new Promise((resolve7) => {
642
+ resolveFinished = resolve7;
711
643
  });
712
644
  const onManagedProcessExit = () => {
713
645
  if (!processManager.hasRunning() && !shuttingDown) {
@@ -1324,7 +1256,7 @@ var generateCommand = defineCommand5({
1324
1256
  }
1325
1257
  logger.step(`Reading schema from ${schemaPath}...`);
1326
1258
  const schemaModule = await import(schemaPath);
1327
- const schema = extractSchema2(schemaModule);
1259
+ const schema = extractSchema(schemaModule);
1328
1260
  if (!schema) {
1329
1261
  logger.error("Schema file must export a SchemaDefinition as the default export.");
1330
1262
  process.exitCode = 1;
@@ -1395,14 +1327,14 @@ var generateCommand = defineCommand5({
1395
1327
  })
1396
1328
  }
1397
1329
  });
1398
- function extractSchema2(mod) {
1330
+ function extractSchema(mod) {
1399
1331
  if (typeof mod !== "object" || mod === null) return null;
1400
1332
  const record = mod;
1401
1333
  const candidate = record.default ?? record;
1402
- if (isSchemaDefinition2(candidate)) return candidate;
1334
+ if (isSchemaDefinition(candidate)) return candidate;
1403
1335
  return null;
1404
1336
  }
1405
- function isSchemaDefinition2(value) {
1337
+ function isSchemaDefinition(value) {
1406
1338
  if (typeof value !== "object" || value === null) return false;
1407
1339
  const obj = value;
1408
1340
  return typeof obj.version === "number" && typeof obj.collections === "object" && obj.collections !== null;
@@ -2570,8 +2502,131 @@ function printStatus(status, url, logger) {
2570
2502
  }
2571
2503
  }
2572
2504
 
2505
+ // src/commands/studio/studio-command.ts
2506
+ import { existsSync } from "fs";
2507
+ import { resolve as resolve6 } from "path";
2508
+ import { defineCommand as defineCommand9 } from "citty";
2509
+ var studioCommand = defineCommand9({
2510
+ meta: {
2511
+ name: "studio",
2512
+ description: "Kora Studio: visualize records, operations, and sync \u2014 or run the sync lab"
2513
+ },
2514
+ args: {
2515
+ db: {
2516
+ type: "string",
2517
+ description: "Path to a Kora SQLite database file (file mode, read-only)"
2518
+ },
2519
+ lab: {
2520
+ type: "boolean",
2521
+ description: "Start the interactive multi-device sync laboratory"
2522
+ },
2523
+ connect: {
2524
+ type: "string",
2525
+ description: "Spectator mode: WebSocket URL of a live Kora sync server (read-only replica)"
2526
+ },
2527
+ token: {
2528
+ type: "string",
2529
+ description: "Spectator mode: bearer token for the sync auth handshake"
2530
+ },
2531
+ devices: {
2532
+ type: "string",
2533
+ description: "Lab mode: number of initial devices (default 2)"
2534
+ },
2535
+ schema: {
2536
+ type: "string",
2537
+ description: "Lab mode: path to a schema file (defaults to a built-in demo schema)"
2538
+ },
2539
+ port: {
2540
+ type: "string",
2541
+ description: "Port for the Studio UI (default 4321, 0 for a random free port)"
2542
+ }
2543
+ },
2544
+ async run({ args }) {
2545
+ const logger = createLogger();
2546
+ const port = args.port !== void 0 ? Number.parseInt(args.port, 10) : 4321;
2547
+ if (Number.isNaN(port) || port < 0 || port > 65535) {
2548
+ throw new Error(`Invalid port "${args.port}"`);
2549
+ }
2550
+ const { startStudioServer } = await import("./studio-server-NIFKZI4F.js");
2551
+ if (typeof args.connect === "string") {
2552
+ if (typeof args.schema !== "string") {
2553
+ throw new Error(
2554
+ "Spectator mode needs your schema to materialize records: kora studio --connect wss://\u2026 --schema ./kora/schema.ts"
2555
+ );
2556
+ }
2557
+ const { loadSchemaDefinition: loadSchemaDefinition2 } = await import("./schema-loader-GGHECMTM.js");
2558
+ const schema = await loadSchemaDefinition2(resolve6(process.cwd(), args.schema), process.cwd());
2559
+ const { SpectatorManager } = await import("./spectator-manager-E2LH2P54.js");
2560
+ const spectator = new SpectatorManager({
2561
+ url: args.connect,
2562
+ schema,
2563
+ ...typeof args.token === "string" ? { token: args.token } : {}
2564
+ });
2565
+ await spectator.start();
2566
+ const server2 = await startStudioServer({ port, spectator });
2567
+ logger.banner();
2568
+ logger.success(`Kora Studio SPECTATOR running at ${server2.url}`);
2569
+ logger.step(`Watching ${args.connect} (read-only replica \u2014 nothing is ever pushed)`);
2570
+ logger.step("Press Ctrl+C to stop.");
2571
+ const shutdown2 = async () => {
2572
+ await server2.close();
2573
+ await spectator.close();
2574
+ process.exit(0);
2575
+ };
2576
+ process.on("SIGINT", () => void shutdown2());
2577
+ process.on("SIGTERM", () => void shutdown2());
2578
+ return;
2579
+ }
2580
+ if (args.lab) {
2581
+ const { LabManager, defaultLabSchema } = await import("./lab-manager-KUDII6BT.js");
2582
+ let schema = defaultLabSchema();
2583
+ if (typeof args.schema === "string") {
2584
+ const { loadSchemaDefinition: loadSchemaDefinition2 } = await import("./schema-loader-GGHECMTM.js");
2585
+ schema = await loadSchemaDefinition2(resolve6(process.cwd(), args.schema), process.cwd());
2586
+ }
2587
+ const initialDevices = args.devices !== void 0 ? Math.max(1, Number.parseInt(args.devices, 10) || 2) : 2;
2588
+ const lab = new LabManager(schema);
2589
+ await lab.start(initialDevices);
2590
+ const server2 = await startStudioServer({ port, lab });
2591
+ logger.banner();
2592
+ logger.success(`Kora Studio LAB running at ${server2.url}`);
2593
+ logger.step(`${initialDevices} device(s) started against an in-process sync server.`);
2594
+ logger.step("Everything in the lab is throwaway \u2014 experiment freely.");
2595
+ logger.step("Press Ctrl+C to stop.");
2596
+ const shutdown2 = async () => {
2597
+ await server2.close();
2598
+ await lab.close();
2599
+ process.exit(0);
2600
+ };
2601
+ process.on("SIGINT", () => void shutdown2());
2602
+ process.on("SIGTERM", () => void shutdown2());
2603
+ return;
2604
+ }
2605
+ if (typeof args.db !== "string") {
2606
+ throw new Error(
2607
+ "Pass --db <path> to inspect a database, --lab for the sync laboratory, or --connect <wss url> for live spectator mode."
2608
+ );
2609
+ }
2610
+ const dbPath = resolve6(process.cwd(), args.db);
2611
+ if (!existsSync(dbPath)) {
2612
+ throw new Error(`Database file not found: ${dbPath}`);
2613
+ }
2614
+ const server = await startStudioServer({ port, dbPath });
2615
+ logger.banner();
2616
+ logger.success(`Kora Studio running at ${server.url}`);
2617
+ logger.step(`Database: ${dbPath} (read-only)`);
2618
+ logger.step("Press Ctrl+C to stop.");
2619
+ const shutdown = async () => {
2620
+ await server.close();
2621
+ process.exit(0);
2622
+ };
2623
+ process.on("SIGINT", () => void shutdown());
2624
+ process.on("SIGTERM", () => void shutdown());
2625
+ }
2626
+ });
2627
+
2573
2628
  // src/bin.ts
2574
- var main = defineCommand9({
2629
+ var main = defineCommand10({
2575
2630
  meta: {
2576
2631
  name: "kora",
2577
2632
  description: "Kora.js \u2014 Offline-first application framework"
@@ -2586,7 +2641,8 @@ var main = defineCommand9({
2586
2641
  generate: generateCommand,
2587
2642
  logs: logsCommand,
2588
2643
  migrate: migrateCommand,
2589
- status: statusCommand
2644
+ status: statusCommand,
2645
+ studio: studioCommand
2590
2646
  }
2591
2647
  });
2592
2648
  runMain(main);