@korajs/cli 0.3.2 → 0.4.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 (50) hide show
  1. package/dist/bin.cjs +385 -288
  2. package/dist/bin.cjs.map +1 -1
  3. package/dist/bin.js +25 -11
  4. package/dist/bin.js.map +1 -1
  5. package/dist/{chunk-KTSRAPSE.js → chunk-CMSX76KM.js} +108 -65
  6. package/dist/chunk-CMSX76KM.js.map +1 -0
  7. package/dist/{chunk-ZGYRDYXS.js → chunk-MVP5PDT4.js} +22 -4
  8. package/dist/chunk-MVP5PDT4.js.map +1 -0
  9. package/dist/{chunk-E7OCVRYL.js → chunk-YGVO4POI.js} +242 -215
  10. package/dist/chunk-YGVO4POI.js.map +1 -0
  11. package/dist/create.cjs +122 -66
  12. package/dist/create.cjs.map +1 -1
  13. package/dist/create.js +2 -2
  14. package/dist/index.cjs +348 -278
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +31 -26
  17. package/dist/index.d.ts +31 -26
  18. package/dist/index.js +2 -2
  19. package/package.json +2 -2
  20. package/templates/tauri-react/.env.example +7 -0
  21. package/templates/tauri-react/.github/workflows/release-desktop.yml +107 -0
  22. package/templates/tauri-react/README.md.hbs +148 -0
  23. package/templates/tauri-react/dev.ts +37 -0
  24. package/templates/tauri-react/index.html.hbs +16 -0
  25. package/templates/tauri-react/kora.config.ts +17 -0
  26. package/templates/tauri-react/package.json.hbs +44 -0
  27. package/templates/tauri-react/server.ts +23 -0
  28. package/templates/tauri-react/src/App.tsx +578 -0
  29. package/templates/tauri-react/src/AppShell.tsx +116 -0
  30. package/templates/tauri-react/src/SetupScreen.tsx +239 -0
  31. package/templates/tauri-react/src/main.tsx +9 -0
  32. package/templates/tauri-react/src/schema.ts +15 -0
  33. package/templates/tauri-react/src/sync-config.ts +103 -0
  34. package/templates/tauri-react/src/updater.ts +38 -0
  35. package/templates/tauri-react/src-tauri/Cargo.toml +19 -0
  36. package/templates/tauri-react/src-tauri/build.rs +3 -0
  37. package/templates/tauri-react/src-tauri/capabilities/default.json +12 -0
  38. package/templates/tauri-react/src-tauri/icons/128x128.png +0 -0
  39. package/templates/tauri-react/src-tauri/icons/128x128@2x.png +0 -0
  40. package/templates/tauri-react/src-tauri/icons/32x32.png +0 -0
  41. package/templates/tauri-react/src-tauri/icons/icon.icns +0 -0
  42. package/templates/tauri-react/src-tauri/icons/icon.ico +0 -0
  43. package/templates/tauri-react/src-tauri/src/lib.rs +8 -0
  44. package/templates/tauri-react/src-tauri/src/main.rs +6 -0
  45. package/templates/tauri-react/src-tauri/tauri.conf.json +44 -0
  46. package/templates/tauri-react/tsconfig.json +15 -0
  47. package/templates/tauri-react/vite.config.ts +15 -0
  48. package/dist/chunk-E7OCVRYL.js.map +0 -1
  49. package/dist/chunk-KTSRAPSE.js.map +0 -1
  50. package/dist/chunk-ZGYRDYXS.js.map +0 -1
package/dist/create.cjs CHANGED
@@ -50,6 +50,7 @@ var ProjectExistsError = class extends import_core.KoraError {
50
50
  // src/prompts/preferences.ts
51
51
  var import_conf = __toESM(require("conf"), 1);
52
52
  var DEFAULT_PREFERENCES = {
53
+ platform: "web",
53
54
  framework: "react",
54
55
  tailwind: true,
55
56
  sync: true,
@@ -151,6 +152,7 @@ function promptConfirm(message, defaultValue = false, options) {
151
152
  resolve5(false);
152
153
  return;
153
154
  }
155
+ ;
154
156
  (options?.output ?? process.stdout).write(" Please answer with y or n\n");
155
157
  ask();
156
158
  });
@@ -256,7 +258,8 @@ var TEMPLATES = [
256
258
  "react-tailwind-sync",
257
259
  "react-tailwind",
258
260
  "react-sync",
259
- "react-basic"
261
+ "react-basic",
262
+ "tauri-react"
260
263
  ];
261
264
 
262
265
  // src/utils/fs-helpers.ts
@@ -454,12 +457,16 @@ async function findNearestAncestorWithEntry(startDir, entryName) {
454
457
 
455
458
  // src/commands/create/options.ts
456
459
  function determineTemplateFromSelections(input) {
460
+ if (input.platform === "desktop-tauri") return "tauri-react";
457
461
  const shouldSync = input.sync && input.db !== "none";
458
462
  if (input.tailwind && shouldSync) return "react-tailwind-sync";
459
463
  if (input.tailwind && !shouldSync) return "react-tailwind";
460
464
  if (!input.tailwind && shouldSync) return "react-sync";
461
465
  return "react-basic";
462
466
  }
467
+ function isPlatformValue(value) {
468
+ return value === "web" || value === "desktop-tauri";
469
+ }
463
470
  function isFrameworkValue(value) {
464
471
  return value === "react" || value === "vue" || value === "svelte" || value === "solid";
465
472
  }
@@ -494,83 +501,110 @@ async function resolveCreatePreferencesFlow(params) {
494
501
  usedStoredPreferences = true;
495
502
  }
496
503
  }
497
- if (flags.framework !== void 0) {
498
- if (!isFrameworkValue(flags.framework)) {
504
+ if (flags.platform !== void 0) {
505
+ if (!isPlatformValue(flags.platform)) {
499
506
  throw new Error(
500
- `Invalid --framework value "${flags.framework}". Expected one of: react, vue, svelte, solid.`
507
+ `Invalid --platform value "${flags.platform}". Expected one of: web, desktop-tauri.`
501
508
  );
502
509
  }
503
- effective.framework = flags.framework;
510
+ effective.platform = flags.platform;
504
511
  } else if (!flags.useDefaults && !usedStoredPreferences) {
505
- effective.framework = await prompts.select("UI framework:", [
506
- { label: "React", value: "react" },
507
- { label: "Vue (coming soon)", value: "vue", disabled: true },
508
- { label: "Svelte (coming soon)", value: "svelte", disabled: true },
509
- { label: "Solid (coming soon)", value: "solid", disabled: true }
512
+ effective.platform = await prompts.select("Platform:", [
513
+ { label: "Web (browser)", value: "web" },
514
+ { label: "Desktop (Tauri \u2014 native SQLite)", value: "desktop-tauri" }
510
515
  ]);
511
516
  }
512
- if (flags.auth !== void 0) {
513
- if (!isAuthValue(flags.auth)) {
514
- throw new Error(
515
- `Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
516
- );
517
+ const isTauri = effective.platform === "desktop-tauri";
518
+ if (isTauri) {
519
+ effective.framework = "react";
520
+ effective.tailwind = false;
521
+ effective.sync = true;
522
+ effective.db = "sqlite";
523
+ effective.dbProvider = "none";
524
+ effective.auth = "none";
525
+ } else {
526
+ if (flags.framework !== void 0) {
527
+ if (!isFrameworkValue(flags.framework)) {
528
+ throw new Error(
529
+ `Invalid --framework value "${flags.framework}". Expected one of: react, vue, svelte, solid.`
530
+ );
531
+ }
532
+ effective.framework = flags.framework;
533
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
534
+ effective.framework = await prompts.select("UI framework:", [
535
+ { label: "React", value: "react" },
536
+ { label: "Vue (coming soon)", value: "vue", disabled: true },
537
+ { label: "Svelte (coming soon)", value: "svelte", disabled: true },
538
+ { label: "Solid (coming soon)", value: "solid", disabled: true }
539
+ ]);
517
540
  }
518
- effective.auth = flags.auth;
519
- } else if (!flags.useDefaults && !usedStoredPreferences) {
520
- effective.auth = await prompts.select("Authentication:", [
521
- { label: "None", value: "none" },
522
- { label: "Email + Password (coming soon)", value: "email-password", disabled: true },
523
- { label: "OAuth (coming soon)", value: "oauth", disabled: true }
524
- ]);
525
- }
526
- if (flags.tailwind !== void 0) {
527
- effective.tailwind = flags.tailwind;
528
- } else if (!flags.useDefaults && !usedStoredPreferences) {
529
- effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
530
- }
531
- if (flags.sync !== void 0) {
532
- effective.sync = flags.sync;
533
- } else if (!flags.useDefaults && !usedStoredPreferences) {
534
- effective.sync = await prompts.confirm("Enable multi-device sync?", true);
535
- }
536
- if (flags.db !== void 0) {
537
- if (!isDatabaseValue(flags.db)) {
538
- throw new Error(`Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`);
541
+ if (flags.auth !== void 0) {
542
+ if (!isAuthValue(flags.auth)) {
543
+ throw new Error(
544
+ `Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
545
+ );
546
+ }
547
+ effective.auth = flags.auth;
548
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
549
+ effective.auth = await prompts.select("Authentication:", [
550
+ { label: "None", value: "none" },
551
+ { label: "Email + Password (coming soon)", value: "email-password", disabled: true },
552
+ { label: "OAuth (coming soon)", value: "oauth", disabled: true }
553
+ ]);
539
554
  }
540
- effective.db = flags.db;
541
- } else if (!effective.sync) {
542
- effective.db = "none";
543
- } else if (!flags.useDefaults && !usedStoredPreferences) {
544
- effective.db = await prompts.select("Server-side database:", [
545
- { label: "SQLite (zero-config)", value: "sqlite" },
546
- { label: "PostgreSQL (production-scale)", value: "postgres" }
547
- ]);
548
- }
549
- if (effective.db !== "postgres") {
550
- effective.dbProvider = "none";
551
- } else if (flags.dbProvider !== void 0) {
552
- if (!isDatabaseProviderValue(flags.dbProvider)) {
553
- throw new Error(
554
- `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
555
- );
555
+ if (flags.tailwind !== void 0) {
556
+ effective.tailwind = flags.tailwind;
557
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
558
+ effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
559
+ }
560
+ if (flags.sync !== void 0) {
561
+ effective.sync = flags.sync;
562
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
563
+ effective.sync = await prompts.confirm("Enable multi-device sync?", true);
564
+ }
565
+ if (flags.db !== void 0) {
566
+ if (!isDatabaseValue(flags.db)) {
567
+ throw new Error(
568
+ `Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
569
+ );
570
+ }
571
+ effective.db = flags.db;
572
+ } else if (!effective.sync) {
573
+ effective.db = "none";
574
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
575
+ effective.db = await prompts.select("Server-side database:", [
576
+ { label: "SQLite (zero-config)", value: "sqlite" },
577
+ { label: "PostgreSQL (production-scale)", value: "postgres" }
578
+ ]);
579
+ }
580
+ if (effective.db !== "postgres") {
581
+ effective.dbProvider = "none";
582
+ } else if (flags.dbProvider !== void 0) {
583
+ if (!isDatabaseProviderValue(flags.dbProvider)) {
584
+ throw new Error(
585
+ `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
586
+ );
587
+ }
588
+ effective.dbProvider = flags.dbProvider;
589
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
590
+ effective.dbProvider = await prompts.select("Database provider:", [
591
+ { label: "Local Postgres", value: "local" },
592
+ { label: "Supabase", value: "supabase" },
593
+ { label: "Neon", value: "neon" },
594
+ { label: "Railway", value: "railway" },
595
+ { label: "Vercel Postgres", value: "vercel-postgres" },
596
+ { label: "Custom connection string", value: "custom" }
597
+ ]);
556
598
  }
557
- effective.dbProvider = flags.dbProvider;
558
- } else if (!flags.useDefaults && !usedStoredPreferences) {
559
- effective.dbProvider = await prompts.select("Database provider:", [
560
- { label: "Local Postgres", value: "local" },
561
- { label: "Supabase", value: "supabase" },
562
- { label: "Neon", value: "neon" },
563
- { label: "Railway", value: "railway" },
564
- { label: "Vercel Postgres", value: "vercel-postgres" },
565
- { label: "Custom connection string", value: "custom" }
566
- ]);
567
599
  }
568
600
  const template = determineTemplateFromSelections({
601
+ platform: effective.platform,
569
602
  tailwind: effective.tailwind,
570
603
  sync: effective.sync,
571
604
  db: effective.db
572
605
  });
573
606
  return {
607
+ platform: effective.platform,
574
608
  framework: effective.framework,
575
609
  auth: effective.auth,
576
610
  db: effective.db,
@@ -586,6 +620,7 @@ function shouldSavePreferences(flags) {
586
620
  }
587
621
  function saveResolvedPreferences(store, resolution) {
588
622
  store.saveCreatePreferences({
623
+ platform: resolution.platform,
589
624
  framework: resolution.framework,
590
625
  tailwind: resolution.tailwind,
591
626
  sync: resolution.sync,
@@ -596,12 +631,15 @@ function saveResolvedPreferences(store, resolution) {
596
631
  });
597
632
  }
598
633
  function hasExplicitPreferenceFlags(flags) {
599
- return flags.framework !== void 0 || flags.auth !== void 0 || flags.db !== void 0 || flags.dbProvider !== void 0 || flags.tailwind !== void 0 || flags.sync !== void 0;
634
+ return flags.platform !== void 0 || flags.framework !== void 0 || flags.auth !== void 0 || flags.db !== void 0 || flags.dbProvider !== void 0 || flags.tailwind !== void 0 || flags.sync !== void 0;
600
635
  }
601
636
  function promptSupportsRichOptions() {
602
637
  return typeof process !== "undefined" && process.stdin.isTTY && process.stdout.isTTY;
603
638
  }
604
639
  function formatStoredPreferenceLabel(preferences) {
640
+ if (preferences.platform === "desktop-tauri") {
641
+ return `Use previous settings (tauri-desktop + ${preferences.packageManager})`;
642
+ }
605
643
  const syncLabel = preferences.sync ? `sync/${preferences.db}` : "local-only";
606
644
  const styleLabel = preferences.tailwind ? "tailwind" : "css";
607
645
  return `Use previous settings (${preferences.framework} + ${styleLabel} + ${syncLabel} + ${preferences.packageManager})`;
@@ -703,7 +741,7 @@ async function applySyncProviderPreset(options) {
703
741
  await (0, import_promises3.writeFile)(readmePath, readmeTemplate, "utf-8");
704
742
  }
705
743
  function isSyncTemplate(template) {
706
- return template === "react-sync" || template === "react-tailwind-sync";
744
+ return template === "react-sync" || template === "react-tailwind-sync" || template === "tauri-react";
707
745
  }
708
746
  function getProviderDisplayName(provider) {
709
747
  switch (provider) {
@@ -819,6 +857,18 @@ function createCompatibilityLayerPlan(templateName) {
819
857
  authLayer
820
858
  ]
821
859
  };
860
+ case "tauri-react":
861
+ return {
862
+ compatibilityTarget: templateName,
863
+ layers: [
864
+ { category: "base", name: "tauri", sourceTemplate: "tauri-react" },
865
+ uiLayer,
866
+ { category: "style", name: "plain", sourceTemplate: null },
867
+ { category: "sync", name: "enabled", sourceTemplate: null },
868
+ { category: "db", name: "tauri-sqlite", sourceTemplate: null },
869
+ authLayer
870
+ ]
871
+ };
822
872
  }
823
873
  }
824
874
  async function composeTemplateLayers(plan, targetDir, context) {
@@ -875,9 +925,13 @@ var createCommand = (0, import_citty.defineCommand)({
875
925
  description: "Project directory name",
876
926
  required: false
877
927
  },
928
+ platform: {
929
+ type: "string",
930
+ description: "Target platform (web, desktop-tauri)"
931
+ },
878
932
  template: {
879
933
  type: "string",
880
- description: "Project template (react-tailwind-sync, react-tailwind, react-sync, react-basic)"
934
+ description: "Project template (react-tailwind-sync, react-tailwind, react-sync, react-basic, tauri-react)"
881
935
  },
882
936
  pm: {
883
937
  type: "string",
@@ -948,6 +1002,7 @@ var createCommand = (0, import_citty.defineCommand)({
948
1002
  return;
949
1003
  }
950
1004
  const preferenceFlags = {
1005
+ platform: typeof args.platform === "string" ? args.platform : void 0,
951
1006
  framework: typeof args.framework === "string" ? args.framework : void 0,
952
1007
  auth: typeof args.auth === "string" ? args.auth : void 0,
953
1008
  db: typeof args.db === "string" ? args.db : void 0,
@@ -1055,6 +1110,7 @@ var createCommand = (0, import_citty.defineCommand)({
1055
1110
  logger.success("Project scaffolded");
1056
1111
  if (shouldSavePreferences(preferenceFlags)) {
1057
1112
  saveResolvedPreferences(preferenceStore, {
1113
+ platform: selection.platform,
1058
1114
  framework: selection.framework,
1059
1115
  auth: selection.auth,
1060
1116
  db: selection.db,
@@ -1106,7 +1162,7 @@ function isValidPackageManager(value) {
1106
1162
  return PACKAGE_MANAGERS.includes(value);
1107
1163
  }
1108
1164
  function isSyncTemplate2(template) {
1109
- return template === "react-sync" || template === "react-tailwind-sync";
1165
+ return template === "react-sync" || template === "react-tailwind-sync" || template === "tauri-react";
1110
1166
  }
1111
1167
  function formatDbProviderForLog(dbProvider) {
1112
1168
  switch (dbProvider) {