@korajs/cli 0.4.0 → 0.5.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 (103) hide show
  1. package/dist/bin.cjs +1609 -643
  2. package/dist/bin.cjs.map +1 -1
  3. package/dist/bin.js +1086 -139
  4. package/dist/bin.js.map +1 -1
  5. package/dist/{chunk-CMSX76KM.js → chunk-3WNFM3QB.js} +103 -96
  6. package/dist/chunk-3WNFM3QB.js.map +1 -0
  7. package/dist/{chunk-MVP5PDT4.js → chunk-PSRM56B7.js} +2 -2
  8. package/dist/{chunk-YGVO4POI.js → chunk-SOTZIWIF.js} +27 -15
  9. package/dist/chunk-SOTZIWIF.js.map +1 -0
  10. package/dist/create.cjs +54 -47
  11. package/dist/create.cjs.map +1 -1
  12. package/dist/create.js +2 -2
  13. package/dist/index.cjs +78 -59
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +5 -3
  16. package/dist/index.d.ts +5 -3
  17. package/dist/index.js +2 -2
  18. package/package.json +9 -3
  19. package/templates/react-basic/README.md.hbs +10 -1
  20. package/templates/react-basic/src/App.tsx +112 -126
  21. package/templates/react-basic/src/index.css +165 -159
  22. package/templates/react-basic/src/kora-worker.ts +0 -1
  23. package/templates/react-basic/src/main.tsx +12 -12
  24. package/templates/react-basic/src/modules/todos/todo.mutations.ts +25 -0
  25. package/templates/react-basic/src/modules/todos/todo.queries.ts +5 -0
  26. package/templates/react-basic/src/modules/todos/todo.schema.ts +10 -0
  27. package/templates/react-basic/src/modules/todos/useTodos.ts +31 -0
  28. package/templates/react-basic/src/schema.ts +6 -12
  29. package/templates/react-basic/src/vite-env.d.ts +17 -0
  30. package/templates/react-basic/{tsconfig.json → tsconfig.json.hbs} +1 -2
  31. package/templates/react-basic/vite.config.ts +57 -50
  32. package/templates/react-sync/.env.example +19 -0
  33. package/templates/react-sync/README.md.hbs +43 -1
  34. package/templates/react-sync/package.json.hbs +3 -0
  35. package/templates/react-sync/server.ts +90 -26
  36. package/templates/react-sync/src/App.tsx +132 -130
  37. package/templates/react-sync/src/auth.ts +25 -0
  38. package/templates/react-sync/src/index.css +212 -165
  39. package/templates/react-sync/src/kora-worker.ts +0 -1
  40. package/templates/react-sync/src/main.tsx +34 -18
  41. package/templates/react-sync/src/modules/todos/todo.mutations.ts +25 -0
  42. package/templates/react-sync/src/modules/todos/todo.queries.ts +5 -0
  43. package/templates/react-sync/src/modules/todos/todo.schema.ts +10 -0
  44. package/templates/react-sync/src/modules/todos/useTodos.ts +31 -0
  45. package/templates/react-sync/src/schema.ts +6 -12
  46. package/templates/react-sync/src/vite-env.d.ts +17 -0
  47. package/templates/react-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
  48. package/templates/react-sync/vite.config.ts +67 -60
  49. package/templates/react-tailwind/README.md.hbs +10 -1
  50. package/templates/react-tailwind/src/App.tsx +186 -197
  51. package/templates/react-tailwind/src/index.css +3 -3
  52. package/templates/react-tailwind/src/kora-worker.ts +0 -1
  53. package/templates/react-tailwind/src/main.tsx +19 -12
  54. package/templates/react-tailwind/src/modules/todos/todo.mutations.ts +25 -0
  55. package/templates/react-tailwind/src/modules/todos/todo.queries.ts +5 -0
  56. package/templates/react-tailwind/src/modules/todos/todo.schema.ts +10 -0
  57. package/templates/react-tailwind/src/modules/todos/useTodos.ts +31 -0
  58. package/templates/react-tailwind/src/schema.ts +6 -12
  59. package/templates/react-tailwind/src/vite-env.d.ts +17 -0
  60. package/templates/react-tailwind/{tsconfig.json → tsconfig.json.hbs} +1 -2
  61. package/templates/react-tailwind/vite.config.ts +57 -50
  62. package/templates/react-tailwind-sync/.env.example +19 -0
  63. package/templates/react-tailwind-sync/README.md.hbs +43 -1
  64. package/templates/react-tailwind-sync/package.json.hbs +3 -0
  65. package/templates/react-tailwind-sync/server.ts +90 -26
  66. package/templates/react-tailwind-sync/src/App.tsx +246 -222
  67. package/templates/react-tailwind-sync/src/auth.ts +25 -0
  68. package/templates/react-tailwind-sync/src/index.css +3 -3
  69. package/templates/react-tailwind-sync/src/kora-worker.ts +0 -1
  70. package/templates/react-tailwind-sync/src/main.tsx +48 -18
  71. package/templates/react-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
  72. package/templates/react-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
  73. package/templates/react-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
  74. package/templates/react-tailwind-sync/src/modules/todos/useTodos.ts +31 -0
  75. package/templates/react-tailwind-sync/src/schema.ts +6 -12
  76. package/templates/react-tailwind-sync/src/vite-env.d.ts +17 -0
  77. package/templates/react-tailwind-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
  78. package/templates/react-tailwind-sync/vite.config.ts +67 -60
  79. package/templates/tauri-react/.env.example +20 -0
  80. package/templates/tauri-react/README.md.hbs +36 -1
  81. package/templates/tauri-react/dev.ts +11 -11
  82. package/templates/tauri-react/package.json.hbs +2 -0
  83. package/templates/tauri-react/server.ts +86 -12
  84. package/templates/tauri-react/src/App.tsx +769 -544
  85. package/templates/tauri-react/src/AppShell.tsx +125 -83
  86. package/templates/tauri-react/src/SetupScreen.tsx +257 -208
  87. package/templates/tauri-react/src/auth.ts +45 -0
  88. package/templates/tauri-react/src/main.tsx +3 -3
  89. package/templates/tauri-react/src/modules/todos/todo.mutations.ts +25 -0
  90. package/templates/tauri-react/src/modules/todos/todo.queries.ts +5 -0
  91. package/templates/tauri-react/src/modules/todos/todo.schema.ts +10 -0
  92. package/templates/tauri-react/src/modules/todos/useTodos.ts +31 -0
  93. package/templates/tauri-react/src/schema.ts +6 -12
  94. package/templates/tauri-react/src/sync-config.ts +47 -47
  95. package/templates/tauri-react/src/updater.ts +15 -15
  96. package/templates/tauri-react/src/vite-env.d.ts +17 -0
  97. package/templates/tauri-react/src-tauri/tauri.conf.json +1 -1
  98. package/templates/tauri-react/tsconfig.json.hbs +14 -0
  99. package/templates/tauri-react/vite.config.ts +9 -9
  100. package/dist/chunk-CMSX76KM.js.map +0 -1
  101. package/dist/chunk-YGVO4POI.js.map +0 -1
  102. package/templates/tauri-react/tsconfig.json +0 -15
  103. /package/dist/{chunk-MVP5PDT4.js.map → chunk-PSRM56B7.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -279,6 +279,7 @@ function toPascalCase(name) {
279
279
  }
280
280
 
281
281
  // src/commands/deploy/deploy-command.ts
282
+ var import_node_fs2 = require("fs");
282
283
  var import_node_path12 = require("path");
283
284
  var import_citty = require("citty");
284
285
 
@@ -778,13 +779,13 @@ var AwsEcsAdapter = class {
778
779
  projectRoot: config.projectRoot,
779
780
  deployDirectory
780
781
  });
781
- const client = await buildClient({
782
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
782
783
  projectRoot: config.projectRoot,
783
784
  outDir: (0, import_node_path4.join)(deployDirectory, "dist"),
784
785
  mode: "production"
785
786
  });
786
787
  return {
787
- clientDirectory: client.outDir,
788
+ clientDirectory: client?.outDir ?? null,
788
789
  serverBundlePath: (0, import_node_path4.join)(deployDirectory, "server-bundled.js"),
789
790
  deployDirectory
790
791
  };
@@ -1129,13 +1130,13 @@ var AwsLightsailAdapter = class {
1129
1130
  projectRoot: config.projectRoot,
1130
1131
  deployDirectory
1131
1132
  });
1132
- const client = await buildClient({
1133
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
1133
1134
  projectRoot: config.projectRoot,
1134
1135
  outDir: (0, import_node_path5.join)(deployDirectory, "dist"),
1135
1136
  mode: "production"
1136
1137
  });
1137
1138
  return {
1138
- clientDirectory: client.outDir,
1139
+ clientDirectory: client?.outDir ?? null,
1139
1140
  serverBundlePath: (0, import_node_path5.join)(deployDirectory, "server-bundled.js"),
1140
1141
  deployDirectory
1141
1142
  };
@@ -1465,7 +1466,7 @@ function generateFlyToml(options) {
1465
1466
  ' interval = "30s"',
1466
1467
  ' method = "GET"',
1467
1468
  ' timeout = "5s"',
1468
- ' path = "/"',
1469
+ ' path = "/health"',
1469
1470
  ""
1470
1471
  ].join("\n");
1471
1472
  }
@@ -1575,13 +1576,13 @@ var FlyAdapter = class {
1575
1576
  projectRoot: config.projectRoot,
1576
1577
  deployDirectory
1577
1578
  });
1578
- const client = await buildClient({
1579
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
1579
1580
  projectRoot: config.projectRoot,
1580
1581
  outDir: (0, import_node_path7.join)(deployDirectory, "dist"),
1581
1582
  mode: "production"
1582
1583
  });
1583
1584
  return {
1584
- clientDirectory: client.outDir,
1585
+ clientDirectory: client?.outDir ?? null,
1585
1586
  serverBundlePath: (0, import_node_path7.join)(deployDirectory, "server-bundled.js"),
1586
1587
  deployDirectory
1587
1588
  };
@@ -1933,13 +1934,13 @@ var RailwayAdapter = class {
1933
1934
  projectRoot: config.projectRoot,
1934
1935
  deployDirectory
1935
1936
  });
1936
- const client = await buildClient({
1937
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
1937
1938
  projectRoot: config.projectRoot,
1938
1939
  outDir: (0, import_node_path9.join)(deployDirectory, "dist"),
1939
1940
  mode: "production"
1940
1941
  });
1941
1942
  return {
1942
- clientDirectory: client.outDir,
1943
+ clientDirectory: client?.outDir ?? null,
1943
1944
  serverBundlePath: (0, import_node_path9.join)(deployDirectory, "server-bundled.js"),
1944
1945
  deployDirectory
1945
1946
  };
@@ -2231,7 +2232,7 @@ var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually"
2231
2232
  function generateDockerfile(options = {}) {
2232
2233
  const nodeVersion = options.nodeVersion ?? "20-alpine";
2233
2234
  const port = options.port ?? 3e3;
2234
- const clientDirectory = options.clientDirectory ?? "dist";
2235
+ const clientDirectory = options.clientDirectory === void 0 ? "dist" : options.clientDirectory;
2235
2236
  const serverBundleFile = options.serverBundleFile ?? "server-bundled.js";
2236
2237
  const hasNativeDeps = options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0;
2237
2238
  const lines = [
@@ -2251,7 +2252,9 @@ function generateDockerfile(options = {}) {
2251
2252
  lines.push("RUN npm install --omit=dev");
2252
2253
  lines.push("");
2253
2254
  }
2254
- lines.push(`COPY ${clientDirectory} ./dist`);
2255
+ if (clientDirectory !== null) {
2256
+ lines.push(`COPY ${clientDirectory} ./dist`);
2257
+ }
2255
2258
  lines.push(`COPY ${serverBundleFile} ./server-bundled.js`);
2256
2259
  lines.push("");
2257
2260
  lines.push(`EXPOSE ${String(port)}`);
@@ -2576,12 +2579,14 @@ var deployCommand = (0, import_citty.defineCommand)({
2576
2579
  const region = resolveRegion(args.region, existingState?.region, confirmMode);
2577
2580
  const deployDirectory = resolveDeployDirectory(projectRoot);
2578
2581
  const environment = args.prod === true ? "production" : "preview";
2582
+ const deployTarget = detectDeployTarget(projectRoot);
2579
2583
  const config = {
2580
2584
  projectRoot,
2581
2585
  appName,
2582
2586
  region,
2583
2587
  environment,
2584
- confirm: confirmMode
2588
+ confirm: confirmMode,
2589
+ deployTarget
2585
2590
  };
2586
2591
  const adapter = createDeployAdapter(platform);
2587
2592
  configureAdapterContext(adapter, {
@@ -2593,10 +2598,14 @@ var deployCommand = (0, import_citty.defineCommand)({
2593
2598
  logger.info(
2594
2599
  `Deploying to ${platform} (${appName}${region ? `, ${region}` : ""}, ${environment})`
2595
2600
  );
2601
+ if (deployTarget === "sync-server") {
2602
+ logger.step("Detected Tauri project. Deploying the sync server only.");
2603
+ }
2596
2604
  if (confirmMode) {
2597
2605
  logger.step("Running in --confirm mode (non-interactive, fail-fast).");
2598
2606
  }
2599
2607
  await writeDockerfileArtifact(deployDirectory, {
2608
+ clientDirectory: deployTarget === "sync-server" ? null : void 0,
2600
2609
  nativeDependencies: {
2601
2610
  "better-sqlite3": "^11.0.0",
2602
2611
  "drizzle-orm": "^0.45.2",
@@ -2735,6 +2744,9 @@ function configureAdapterContext(adapter, context) {
2735
2744
  adapter.setContext(context);
2736
2745
  }
2737
2746
  }
2747
+ function detectDeployTarget(projectRoot) {
2748
+ return (0, import_node_fs2.existsSync)((0, import_node_path12.join)(projectRoot, "src-tauri")) ? "sync-server" : "full-stack";
2749
+ }
2738
2750
  function hasContextSetter(adapter) {
2739
2751
  return typeof adapter.setContext === "function";
2740
2752
  }
@@ -2863,10 +2875,49 @@ async function resolveCreatePreferencesFlow(params) {
2863
2875
  if (isTauri) {
2864
2876
  effective.framework = "react";
2865
2877
  effective.tailwind = false;
2866
- effective.sync = true;
2867
- effective.db = "sqlite";
2868
- effective.dbProvider = "none";
2869
2878
  effective.auth = "none";
2879
+ if (flags.sync !== void 0) {
2880
+ effective.sync = flags.sync;
2881
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
2882
+ effective.sync = await prompts.confirm("Enable multi-device sync?", true);
2883
+ }
2884
+ if (flags.db !== void 0) {
2885
+ if (!isDatabaseValue(flags.db)) {
2886
+ throw new Error(
2887
+ `Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
2888
+ );
2889
+ }
2890
+ effective.db = flags.db;
2891
+ } else if (!effective.sync) {
2892
+ effective.db = "none";
2893
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
2894
+ effective.db = await prompts.select("Sync server database:", [
2895
+ { label: "SQLite (zero-config; local, LAN, small teams)", value: "sqlite" },
2896
+ { label: "PostgreSQL (production-scale)", value: "postgres" }
2897
+ ]);
2898
+ }
2899
+ if (effective.db === "none") {
2900
+ effective.sync = false;
2901
+ }
2902
+ if (effective.db !== "postgres") {
2903
+ effective.dbProvider = "none";
2904
+ } else if (flags.dbProvider !== void 0) {
2905
+ if (!isDatabaseProviderValue(flags.dbProvider)) {
2906
+ throw new Error(
2907
+ `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
2908
+ );
2909
+ }
2910
+ effective.dbProvider = flags.dbProvider;
2911
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
2912
+ effective.dbProvider = await prompts.select("Database provider:", [
2913
+ { label: "Local Postgres", value: "local" },
2914
+ { label: "Supabase", value: "supabase" },
2915
+ { label: "Neon", value: "neon" },
2916
+ { label: "Railway", value: "railway" },
2917
+ { label: "Vercel Postgres", value: "vercel-postgres" },
2918
+ { label: "Custom connection string", value: "custom" }
2919
+ ]);
2920
+ }
2870
2921
  } else {
2871
2922
  if (flags.framework !== void 0) {
2872
2923
  if (!isFrameworkValue(flags.framework)) {
@@ -3002,63 +3053,31 @@ async function applySyncProviderPreset(options) {
3002
3053
  }
3003
3054
  const providerName = getProviderDisplayName(options.dbProvider);
3004
3055
  const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
3005
- const serverPath = (0, import_node_path13.join)(options.targetDir, "server.ts");
3006
3056
  const envPath = (0, import_node_path13.join)(options.targetDir, ".env.example");
3007
3057
  const readmePath = (0, import_node_path13.join)(options.targetDir, "README.md");
3008
- const serverTemplate = [
3009
- "import { createPostgresServerStore, createProductionServer } from '@korajs/server'",
3010
- "",
3011
- `// PostgreSQL provider preset: ${providerName}`,
3012
- "// Ensure DATABASE_URL is set in your environment.",
3013
- "",
3014
- "async function start(): Promise<void> {",
3015
- " const connectionString = process.env.DATABASE_URL || ''",
3016
- " if (connectionString.length === 0) {",
3017
- " throw new Error('DATABASE_URL is required for PostgreSQL sync server store.')",
3018
- " }",
3019
- "",
3020
- " const store = await createPostgresServerStore({ connectionString })",
3021
- " const server = createProductionServer({",
3022
- " store,",
3023
- " port: Number(process.env.PORT) || 3001,",
3024
- " staticDir: './dist',",
3025
- " syncPath: '/kora-sync',",
3026
- " })",
3027
- "",
3028
- " const url = await server.start()",
3029
- " console.log(`Kora app running at ${url}`)",
3030
- "}",
3031
- "",
3032
- "void start()",
3033
- ""
3034
- ].join("\n");
3035
- const envTemplate = [
3036
- "# Kora Sync Server",
3037
- "# WebSocket URL for the sync server (used by the client)",
3038
- "VITE_SYNC_URL=ws://localhost:3001",
3039
- "",
3040
- "# Sync server port",
3041
- "PORT=3001",
3042
- "",
3043
- `# PostgreSQL connection string (${providerName})`,
3044
- `# Example: ${providerConnectionString}`,
3045
- "DATABASE_URL=",
3046
- ""
3047
- ].join("\n");
3048
3058
  const existingReadme = await (0, import_promises9.readFile)(readmePath, "utf-8");
3059
+ const existingEnv = await (0, import_promises9.readFile)(envPath, "utf-8");
3049
3060
  const trimmedReadme = existingReadme.trimEnd();
3061
+ const trimmedEnv = existingEnv.trimEnd();
3062
+ const envSuffix = [
3063
+ "",
3064
+ `# PostgreSQL provider preset: ${providerName}`,
3065
+ `# Example: ${providerConnectionString}`
3066
+ ].join("\n");
3050
3067
  const readmeSuffix = [
3051
3068
  "",
3052
3069
  "## PostgreSQL Provider Preset",
3053
3070
  "",
3054
3071
  `Selected DB provider: ${options.dbProvider}`,
3055
3072
  "",
3056
- "This scaffold uses `createPostgresServerStore` in `server.ts` and reads `DATABASE_URL` from the environment. See `.env.example` for provider-specific examples.",
3073
+ "This scaffold keeps one sync server entrypoint. When `DATABASE_URL` is set, `server.ts` uses PostgreSQL. When it is empty, the same server uses SQLite at `KORA_SERVER_DB`.",
3074
+ "",
3075
+ "The generated server uses `createPostgresServerStore` automatically when `DATABASE_URL` is present.",
3057
3076
  ""
3058
3077
  ].join("\n");
3059
3078
  const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
3060
- await (0, import_promises9.writeFile)(serverPath, serverTemplate, "utf-8");
3061
- await (0, import_promises9.writeFile)(envPath, envTemplate, "utf-8");
3079
+ await (0, import_promises9.writeFile)(envPath, `${trimmedEnv}${envSuffix}
3080
+ `, "utf-8");
3062
3081
  await (0, import_promises9.writeFile)(readmePath, readmeTemplate, "utf-8");
3063
3082
  }
3064
3083
  function isSyncTemplate(template) {