@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/bin.cjs CHANGED
@@ -88,6 +88,7 @@ var DevServerError = class extends import_core.KoraError {
88
88
  // src/prompts/preferences.ts
89
89
  var import_conf = __toESM(require("conf"), 1);
90
90
  var DEFAULT_PREFERENCES = {
91
+ platform: "web",
91
92
  framework: "react",
92
93
  tailwind: true,
93
94
  sync: true,
@@ -189,6 +190,7 @@ function promptConfirm(message, defaultValue = false, options) {
189
190
  resolve9(false);
190
191
  return;
191
192
  }
193
+ ;
192
194
  (options?.output ?? process.stdout).write(" Please answer with y or n\n");
193
195
  ask();
194
196
  });
@@ -294,7 +296,8 @@ var TEMPLATES = [
294
296
  "react-tailwind-sync",
295
297
  "react-tailwind",
296
298
  "react-sync",
297
- "react-basic"
299
+ "react-basic",
300
+ "tauri-react"
298
301
  ];
299
302
 
300
303
  // src/utils/fs-helpers.ts
@@ -562,12 +565,16 @@ async function findNearestAncestorWithEntry(startDir, entryName) {
562
565
 
563
566
  // src/commands/create/options.ts
564
567
  function determineTemplateFromSelections(input) {
568
+ if (input.platform === "desktop-tauri") return "tauri-react";
565
569
  const shouldSync = input.sync && input.db !== "none";
566
570
  if (input.tailwind && shouldSync) return "react-tailwind-sync";
567
571
  if (input.tailwind && !shouldSync) return "react-tailwind";
568
572
  if (!input.tailwind && shouldSync) return "react-sync";
569
573
  return "react-basic";
570
574
  }
575
+ function isPlatformValue(value) {
576
+ return value === "web" || value === "desktop-tauri";
577
+ }
571
578
  function isFrameworkValue(value) {
572
579
  return value === "react" || value === "vue" || value === "svelte" || value === "solid";
573
580
  }
@@ -602,83 +609,110 @@ async function resolveCreatePreferencesFlow(params) {
602
609
  usedStoredPreferences = true;
603
610
  }
604
611
  }
605
- if (flags.framework !== void 0) {
606
- if (!isFrameworkValue(flags.framework)) {
607
- throw new Error(
608
- `Invalid --framework value "${flags.framework}". Expected one of: react, vue, svelte, solid.`
609
- );
610
- }
611
- effective.framework = flags.framework;
612
- } else if (!flags.useDefaults && !usedStoredPreferences) {
613
- effective.framework = await prompts.select("UI framework:", [
614
- { label: "React", value: "react" },
615
- { label: "Vue (coming soon)", value: "vue", disabled: true },
616
- { label: "Svelte (coming soon)", value: "svelte", disabled: true },
617
- { label: "Solid (coming soon)", value: "solid", disabled: true }
618
- ]);
619
- }
620
- if (flags.auth !== void 0) {
621
- if (!isAuthValue(flags.auth)) {
612
+ if (flags.platform !== void 0) {
613
+ if (!isPlatformValue(flags.platform)) {
622
614
  throw new Error(
623
- `Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
615
+ `Invalid --platform value "${flags.platform}". Expected one of: web, desktop-tauri.`
624
616
  );
625
617
  }
626
- effective.auth = flags.auth;
627
- } else if (!flags.useDefaults && !usedStoredPreferences) {
628
- effective.auth = await prompts.select("Authentication:", [
629
- { label: "None", value: "none" },
630
- { label: "Email + Password (coming soon)", value: "email-password", disabled: true },
631
- { label: "OAuth (coming soon)", value: "oauth", disabled: true }
632
- ]);
633
- }
634
- if (flags.tailwind !== void 0) {
635
- effective.tailwind = flags.tailwind;
636
- } else if (!flags.useDefaults && !usedStoredPreferences) {
637
- effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
638
- }
639
- if (flags.sync !== void 0) {
640
- effective.sync = flags.sync;
641
- } else if (!flags.useDefaults && !usedStoredPreferences) {
642
- effective.sync = await prompts.confirm("Enable multi-device sync?", true);
643
- }
644
- if (flags.db !== void 0) {
645
- if (!isDatabaseValue(flags.db)) {
646
- throw new Error(`Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`);
647
- }
648
- effective.db = flags.db;
649
- } else if (!effective.sync) {
650
- effective.db = "none";
618
+ effective.platform = flags.platform;
651
619
  } else if (!flags.useDefaults && !usedStoredPreferences) {
652
- effective.db = await prompts.select("Server-side database:", [
653
- { label: "SQLite (zero-config)", value: "sqlite" },
654
- { label: "PostgreSQL (production-scale)", value: "postgres" }
620
+ effective.platform = await prompts.select("Platform:", [
621
+ { label: "Web (browser)", value: "web" },
622
+ { label: "Desktop (Tauri \u2014 native SQLite)", value: "desktop-tauri" }
655
623
  ]);
656
624
  }
657
- if (effective.db !== "postgres") {
625
+ const isTauri = effective.platform === "desktop-tauri";
626
+ if (isTauri) {
627
+ effective.framework = "react";
628
+ effective.tailwind = false;
629
+ effective.sync = true;
630
+ effective.db = "sqlite";
658
631
  effective.dbProvider = "none";
659
- } else if (flags.dbProvider !== void 0) {
660
- if (!isDatabaseProviderValue(flags.dbProvider)) {
661
- throw new Error(
662
- `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
663
- );
632
+ effective.auth = "none";
633
+ } else {
634
+ if (flags.framework !== void 0) {
635
+ if (!isFrameworkValue(flags.framework)) {
636
+ throw new Error(
637
+ `Invalid --framework value "${flags.framework}". Expected one of: react, vue, svelte, solid.`
638
+ );
639
+ }
640
+ effective.framework = flags.framework;
641
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
642
+ effective.framework = await prompts.select("UI framework:", [
643
+ { label: "React", value: "react" },
644
+ { label: "Vue (coming soon)", value: "vue", disabled: true },
645
+ { label: "Svelte (coming soon)", value: "svelte", disabled: true },
646
+ { label: "Solid (coming soon)", value: "solid", disabled: true }
647
+ ]);
648
+ }
649
+ if (flags.auth !== void 0) {
650
+ if (!isAuthValue(flags.auth)) {
651
+ throw new Error(
652
+ `Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
653
+ );
654
+ }
655
+ effective.auth = flags.auth;
656
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
657
+ effective.auth = await prompts.select("Authentication:", [
658
+ { label: "None", value: "none" },
659
+ { label: "Email + Password (coming soon)", value: "email-password", disabled: true },
660
+ { label: "OAuth (coming soon)", value: "oauth", disabled: true }
661
+ ]);
662
+ }
663
+ if (flags.tailwind !== void 0) {
664
+ effective.tailwind = flags.tailwind;
665
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
666
+ effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
667
+ }
668
+ if (flags.sync !== void 0) {
669
+ effective.sync = flags.sync;
670
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
671
+ effective.sync = await prompts.confirm("Enable multi-device sync?", true);
672
+ }
673
+ if (flags.db !== void 0) {
674
+ if (!isDatabaseValue(flags.db)) {
675
+ throw new Error(
676
+ `Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
677
+ );
678
+ }
679
+ effective.db = flags.db;
680
+ } else if (!effective.sync) {
681
+ effective.db = "none";
682
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
683
+ effective.db = await prompts.select("Server-side database:", [
684
+ { label: "SQLite (zero-config)", value: "sqlite" },
685
+ { label: "PostgreSQL (production-scale)", value: "postgres" }
686
+ ]);
687
+ }
688
+ if (effective.db !== "postgres") {
689
+ effective.dbProvider = "none";
690
+ } else if (flags.dbProvider !== void 0) {
691
+ if (!isDatabaseProviderValue(flags.dbProvider)) {
692
+ throw new Error(
693
+ `Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
694
+ );
695
+ }
696
+ effective.dbProvider = flags.dbProvider;
697
+ } else if (!flags.useDefaults && !usedStoredPreferences) {
698
+ effective.dbProvider = await prompts.select("Database provider:", [
699
+ { label: "Local Postgres", value: "local" },
700
+ { label: "Supabase", value: "supabase" },
701
+ { label: "Neon", value: "neon" },
702
+ { label: "Railway", value: "railway" },
703
+ { label: "Vercel Postgres", value: "vercel-postgres" },
704
+ { label: "Custom connection string", value: "custom" }
705
+ ]);
664
706
  }
665
- effective.dbProvider = flags.dbProvider;
666
- } else if (!flags.useDefaults && !usedStoredPreferences) {
667
- effective.dbProvider = await prompts.select("Database provider:", [
668
- { label: "Local Postgres", value: "local" },
669
- { label: "Supabase", value: "supabase" },
670
- { label: "Neon", value: "neon" },
671
- { label: "Railway", value: "railway" },
672
- { label: "Vercel Postgres", value: "vercel-postgres" },
673
- { label: "Custom connection string", value: "custom" }
674
- ]);
675
707
  }
676
708
  const template = determineTemplateFromSelections({
709
+ platform: effective.platform,
677
710
  tailwind: effective.tailwind,
678
711
  sync: effective.sync,
679
712
  db: effective.db
680
713
  });
681
714
  return {
715
+ platform: effective.platform,
682
716
  framework: effective.framework,
683
717
  auth: effective.auth,
684
718
  db: effective.db,
@@ -694,6 +728,7 @@ function shouldSavePreferences(flags) {
694
728
  }
695
729
  function saveResolvedPreferences(store, resolution) {
696
730
  store.saveCreatePreferences({
731
+ platform: resolution.platform,
697
732
  framework: resolution.framework,
698
733
  tailwind: resolution.tailwind,
699
734
  sync: resolution.sync,
@@ -704,12 +739,15 @@ function saveResolvedPreferences(store, resolution) {
704
739
  });
705
740
  }
706
741
  function hasExplicitPreferenceFlags(flags) {
707
- 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;
742
+ 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;
708
743
  }
709
744
  function promptSupportsRichOptions() {
710
745
  return typeof process !== "undefined" && process.stdin.isTTY && process.stdout.isTTY;
711
746
  }
712
747
  function formatStoredPreferenceLabel(preferences) {
748
+ if (preferences.platform === "desktop-tauri") {
749
+ return `Use previous settings (tauri-desktop + ${preferences.packageManager})`;
750
+ }
713
751
  const syncLabel = preferences.sync ? `sync/${preferences.db}` : "local-only";
714
752
  const styleLabel = preferences.tailwind ? "tailwind" : "css";
715
753
  return `Use previous settings (${preferences.framework} + ${styleLabel} + ${syncLabel} + ${preferences.packageManager})`;
@@ -811,7 +849,7 @@ async function applySyncProviderPreset(options) {
811
849
  await (0, import_promises3.writeFile)(readmePath, readmeTemplate, "utf-8");
812
850
  }
813
851
  function isSyncTemplate(template) {
814
- return template === "react-sync" || template === "react-tailwind-sync";
852
+ return template === "react-sync" || template === "react-tailwind-sync" || template === "tauri-react";
815
853
  }
816
854
  function getProviderDisplayName(provider) {
817
855
  switch (provider) {
@@ -927,6 +965,18 @@ function createCompatibilityLayerPlan(templateName) {
927
965
  authLayer
928
966
  ]
929
967
  };
968
+ case "tauri-react":
969
+ return {
970
+ compatibilityTarget: templateName,
971
+ layers: [
972
+ { category: "base", name: "tauri", sourceTemplate: "tauri-react" },
973
+ uiLayer,
974
+ { category: "style", name: "plain", sourceTemplate: null },
975
+ { category: "sync", name: "enabled", sourceTemplate: null },
976
+ { category: "db", name: "tauri-sqlite", sourceTemplate: null },
977
+ authLayer
978
+ ]
979
+ };
930
980
  }
931
981
  }
932
982
  async function composeTemplateLayers(plan, targetDir, context) {
@@ -983,9 +1033,13 @@ var createCommand = (0, import_citty.defineCommand)({
983
1033
  description: "Project directory name",
984
1034
  required: false
985
1035
  },
1036
+ platform: {
1037
+ type: "string",
1038
+ description: "Target platform (web, desktop-tauri)"
1039
+ },
986
1040
  template: {
987
1041
  type: "string",
988
- description: "Project template (react-tailwind-sync, react-tailwind, react-sync, react-basic)"
1042
+ description: "Project template (react-tailwind-sync, react-tailwind, react-sync, react-basic, tauri-react)"
989
1043
  },
990
1044
  pm: {
991
1045
  type: "string",
@@ -1056,6 +1110,7 @@ var createCommand = (0, import_citty.defineCommand)({
1056
1110
  return;
1057
1111
  }
1058
1112
  const preferenceFlags = {
1113
+ platform: typeof args.platform === "string" ? args.platform : void 0,
1059
1114
  framework: typeof args.framework === "string" ? args.framework : void 0,
1060
1115
  auth: typeof args.auth === "string" ? args.auth : void 0,
1061
1116
  db: typeof args.db === "string" ? args.db : void 0,
@@ -1163,6 +1218,7 @@ var createCommand = (0, import_citty.defineCommand)({
1163
1218
  logger.success("Project scaffolded");
1164
1219
  if (shouldSavePreferences(preferenceFlags)) {
1165
1220
  saveResolvedPreferences(preferenceStore, {
1221
+ platform: selection.platform,
1166
1222
  framework: selection.framework,
1167
1223
  auth: selection.auth,
1168
1224
  db: selection.db,
@@ -1214,7 +1270,7 @@ function isValidPackageManager(value) {
1214
1270
  return PACKAGE_MANAGERS.includes(value);
1215
1271
  }
1216
1272
  function isSyncTemplate2(template) {
1217
- return template === "react-sync" || template === "react-tailwind-sync";
1273
+ return template === "react-sync" || template === "react-tailwind-sync" || template === "tauri-react";
1218
1274
  }
1219
1275
  function formatDbProviderForLog(dbProvider) {
1220
1276
  switch (dbProvider) {
@@ -1299,7 +1355,15 @@ var import_node_path16 = require("path");
1299
1355
  var import_citty2 = require("citty");
1300
1356
 
1301
1357
  // src/commands/deploy/adapters/adapter.ts
1302
- var DEPLOY_PLATFORMS = ["fly", "railway", "aws-ecs", "aws-lightsail", "render", "docker", "kora-cloud"];
1358
+ var DEPLOY_PLATFORMS = [
1359
+ "fly",
1360
+ "railway",
1361
+ "aws-ecs",
1362
+ "aws-lightsail",
1363
+ "render",
1364
+ "docker",
1365
+ "kora-cloud"
1366
+ ];
1303
1367
  function isDeployPlatform(value) {
1304
1368
  return DEPLOY_PLATFORMS.includes(value);
1305
1369
  }
@@ -1310,8 +1374,8 @@ var import_node_path8 = require("path");
1310
1374
 
1311
1375
  // src/commands/deploy/builder/client-builder.ts
1312
1376
  var import_node_child_process3 = require("child_process");
1313
- var import_promises5 = require("fs/promises");
1314
1377
  var import_node_fs3 = require("fs");
1378
+ var import_promises5 = require("fs/promises");
1315
1379
  var import_node_path6 = require("path");
1316
1380
  async function buildClient(options) {
1317
1381
  const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
@@ -1469,37 +1533,46 @@ var AwsEcsAdapter = class {
1469
1533
  };
1470
1534
  const region = config.region ?? "us-east-1";
1471
1535
  const repoName = `kora/${config.appName}`;
1472
- const createRepo = await this.runner.run("aws", [
1473
- "ecr",
1474
- "create-repository",
1475
- "--repository-name",
1476
- repoName,
1477
- "--region",
1478
- region,
1479
- "--image-scanning-configuration",
1480
- "scanOnPush=true"
1481
- ], config.projectRoot);
1536
+ const createRepo = await this.runner.run(
1537
+ "aws",
1538
+ [
1539
+ "ecr",
1540
+ "create-repository",
1541
+ "--repository-name",
1542
+ repoName,
1543
+ "--region",
1544
+ region,
1545
+ "--image-scanning-configuration",
1546
+ "scanOnPush=true"
1547
+ ],
1548
+ config.projectRoot
1549
+ );
1482
1550
  if (createRepo.exitCode !== 0 && !createRepo.stderr.includes("RepositoryAlreadyExistsException")) {
1483
1551
  throw new Error(`Failed to create ECR repository: ${createRepo.stderr}`);
1484
1552
  }
1485
- const identity = await this.runner.run("aws", ["sts", "get-caller-identity", "--query", "Account", "--output", "text"], config.projectRoot);
1553
+ const identity = await this.runner.run(
1554
+ "aws",
1555
+ ["sts", "get-caller-identity", "--query", "Account", "--output", "text"],
1556
+ config.projectRoot
1557
+ );
1486
1558
  const accountId = identity.stdout.trim();
1487
- await this.runner.run("aws", [
1488
- "ecs",
1489
- "create-cluster",
1490
- "--cluster-name",
1491
- config.appName,
1492
- "--region",
1493
- region
1494
- ], config.projectRoot);
1495
- await this.runner.run("aws", [
1496
- "logs",
1497
- "create-log-group",
1498
- "--log-group-name",
1499
- `/ecs/${config.appName}`,
1500
- "--region",
1501
- region
1502
- ], config.projectRoot);
1559
+ await this.runner.run(
1560
+ "aws",
1561
+ ["ecs", "create-cluster", "--cluster-name", config.appName, "--region", region],
1562
+ config.projectRoot
1563
+ );
1564
+ await this.runner.run(
1565
+ "aws",
1566
+ [
1567
+ "logs",
1568
+ "create-log-group",
1569
+ "--log-group-name",
1570
+ `/ecs/${config.appName}`,
1571
+ "--region",
1572
+ region
1573
+ ],
1574
+ config.projectRoot
1575
+ );
1503
1576
  return {
1504
1577
  applicationId: `${accountId}.dkr.ecr.${region}.amazonaws.com/${repoName}`,
1505
1578
  databaseId: null,
@@ -1532,50 +1605,42 @@ var AwsEcsAdapter = class {
1532
1605
  const context = this.requireContext();
1533
1606
  const region = context.region ?? "us-east-1";
1534
1607
  const repoName = `kora/${context.appName}`;
1535
- const loginPassword = await this.runner.run("aws", [
1536
- "ecr",
1537
- "get-login-password",
1538
- "--region",
1539
- region
1540
- ], context.projectRoot);
1608
+ const loginPassword = await this.runner.run(
1609
+ "aws",
1610
+ ["ecr", "get-login-password", "--region", region],
1611
+ context.projectRoot
1612
+ );
1541
1613
  if (loginPassword.exitCode !== 0) {
1542
1614
  throw new Error(`ECR login failed: ${loginPassword.stderr}`);
1543
1615
  }
1544
- const identity = await this.runner.run("aws", [
1545
- "sts",
1546
- "get-caller-identity",
1547
- "--query",
1548
- "Account",
1549
- "--output",
1550
- "text"
1551
- ], context.projectRoot);
1616
+ const identity = await this.runner.run(
1617
+ "aws",
1618
+ ["sts", "get-caller-identity", "--query", "Account", "--output", "text"],
1619
+ context.projectRoot
1620
+ );
1552
1621
  const accountId = identity.stdout.trim();
1553
1622
  const ecrUri = `${accountId}.dkr.ecr.${region}.amazonaws.com`;
1554
1623
  const imageUri = `${ecrUri}/${repoName}:latest`;
1555
- const dockerLogin = await this.runner.run("docker", [
1556
- "login",
1557
- "--username",
1558
- "AWS",
1559
- "--password-stdin",
1560
- ecrUri
1561
- ], artifacts.deployDirectory);
1624
+ const dockerLogin = await this.runner.run(
1625
+ "docker",
1626
+ ["login", "--username", "AWS", "--password-stdin", ecrUri],
1627
+ artifacts.deployDirectory
1628
+ );
1562
1629
  this.logger.step("Building Docker image...");
1563
- const dockerBuild = await this.runner.run("docker", [
1564
- "build",
1565
- "--platform",
1566
- "linux/amd64",
1567
- "-t",
1568
- imageUri,
1569
- "."
1570
- ], artifacts.deployDirectory);
1630
+ const dockerBuild = await this.runner.run(
1631
+ "docker",
1632
+ ["build", "--platform", "linux/amd64", "-t", imageUri, "."],
1633
+ artifacts.deployDirectory
1634
+ );
1571
1635
  if (dockerBuild.exitCode !== 0) {
1572
1636
  throw new Error(`Docker build failed: ${dockerBuild.stderr}`);
1573
1637
  }
1574
1638
  this.logger.step("Pushing image to ECR...");
1575
- const dockerPush = await this.runner.run("docker", [
1576
- "push",
1577
- imageUri
1578
- ], artifacts.deployDirectory);
1639
+ const dockerPush = await this.runner.run(
1640
+ "docker",
1641
+ ["push", imageUri],
1642
+ artifacts.deployDirectory
1643
+ );
1579
1644
  if (dockerPush.exitCode !== 0) {
1580
1645
  throw new Error(`Docker push failed: ${dockerPush.stderr}`);
1581
1646
  }
@@ -1586,52 +1651,55 @@ var AwsEcsAdapter = class {
1586
1651
  cpu: "256",
1587
1652
  memory: "512",
1588
1653
  executionRoleArn: `arn:aws:iam::${accountId}:role/ecsTaskExecutionRole`,
1589
- containerDefinitions: [{
1590
- name: context.appName,
1591
- image: imageUri,
1592
- essential: true,
1593
- portMappings: [{ containerPort: 3001, protocol: "tcp" }],
1594
- logConfiguration: {
1595
- logDriver: "awslogs",
1596
- options: {
1597
- "awslogs-group": `/ecs/${context.appName}`,
1598
- "awslogs-region": region,
1599
- "awslogs-stream-prefix": "ecs"
1654
+ containerDefinitions: [
1655
+ {
1656
+ name: context.appName,
1657
+ image: imageUri,
1658
+ essential: true,
1659
+ portMappings: [{ containerPort: 3001, protocol: "tcp" }],
1660
+ logConfiguration: {
1661
+ logDriver: "awslogs",
1662
+ options: {
1663
+ "awslogs-group": `/ecs/${context.appName}`,
1664
+ "awslogs-region": region,
1665
+ "awslogs-stream-prefix": "ecs"
1666
+ }
1667
+ },
1668
+ healthCheck: {
1669
+ command: ["CMD-SHELL", "curl -f http://localhost:3001/health || exit 1"],
1670
+ interval: 30,
1671
+ timeout: 5,
1672
+ retries: 3,
1673
+ startPeriod: 60
1600
1674
  }
1601
- },
1602
- healthCheck: {
1603
- command: ["CMD-SHELL", "curl -f http://localhost:3001/health || exit 1"],
1604
- interval: 30,
1605
- timeout: 5,
1606
- retries: 3,
1607
- startPeriod: 60
1608
1675
  }
1609
- }]
1676
+ ]
1610
1677
  });
1611
- const registerTask = await this.runner.run("aws", [
1612
- "ecs",
1613
- "register-task-definition",
1614
- "--cli-input-json",
1615
- taskDef,
1616
- "--region",
1617
- region
1618
- ], context.projectRoot);
1678
+ const registerTask = await this.runner.run(
1679
+ "aws",
1680
+ ["ecs", "register-task-definition", "--cli-input-json", taskDef, "--region", region],
1681
+ context.projectRoot
1682
+ );
1619
1683
  if (registerTask.exitCode !== 0) {
1620
1684
  throw new Error(`Task definition registration failed: ${registerTask.stderr}`);
1621
1685
  }
1622
- const updateService = await this.runner.run("aws", [
1623
- "ecs",
1624
- "update-service",
1625
- "--cluster",
1626
- context.appName,
1627
- "--service",
1628
- context.appName,
1629
- "--task-definition",
1630
- context.appName,
1631
- "--force-new-deployment",
1632
- "--region",
1633
- region
1634
- ], context.projectRoot);
1686
+ const updateService = await this.runner.run(
1687
+ "aws",
1688
+ [
1689
+ "ecs",
1690
+ "update-service",
1691
+ "--cluster",
1692
+ context.appName,
1693
+ "--service",
1694
+ context.appName,
1695
+ "--task-definition",
1696
+ context.appName,
1697
+ "--force-new-deployment",
1698
+ "--region",
1699
+ region
1700
+ ],
1701
+ context.projectRoot
1702
+ );
1635
1703
  const deploymentId = (/* @__PURE__ */ new Date()).toISOString();
1636
1704
  if (updateService.exitCode !== 0) {
1637
1705
  this.logger.step("Service not found, creating new service...");
@@ -1656,19 +1724,23 @@ var AwsEcsAdapter = class {
1656
1724
  async rollback(deploymentId) {
1657
1725
  const context = this.requireContext();
1658
1726
  const region = context.region ?? "us-east-1";
1659
- const result = await this.runner.run("aws", [
1660
- "ecs",
1661
- "update-service",
1662
- "--cluster",
1663
- context.appName,
1664
- "--service",
1665
- context.appName,
1666
- "--task-definition",
1667
- `${context.appName}:${deploymentId}`,
1668
- "--force-new-deployment",
1669
- "--region",
1670
- region
1671
- ], context.projectRoot);
1727
+ const result = await this.runner.run(
1728
+ "aws",
1729
+ [
1730
+ "ecs",
1731
+ "update-service",
1732
+ "--cluster",
1733
+ context.appName,
1734
+ "--service",
1735
+ context.appName,
1736
+ "--task-definition",
1737
+ `${context.appName}:${deploymentId}`,
1738
+ "--force-new-deployment",
1739
+ "--region",
1740
+ region
1741
+ ],
1742
+ context.projectRoot
1743
+ );
1672
1744
  if (result.exitCode !== 0) {
1673
1745
  throw new Error(`ECS rollback failed: ${result.stderr}`);
1674
1746
  }
@@ -1711,16 +1783,20 @@ var AwsEcsAdapter = class {
1711
1783
  async status() {
1712
1784
  const context = this.requireContext();
1713
1785
  const region = context.region ?? "us-east-1";
1714
- const result = await this.runner.run("aws", [
1715
- "ecs",
1716
- "describe-services",
1717
- "--cluster",
1718
- context.appName,
1719
- "--services",
1720
- context.appName,
1721
- "--region",
1722
- region
1723
- ], context.projectRoot);
1786
+ const result = await this.runner.run(
1787
+ "aws",
1788
+ [
1789
+ "ecs",
1790
+ "describe-services",
1791
+ "--cluster",
1792
+ context.appName,
1793
+ "--services",
1794
+ context.appName,
1795
+ "--region",
1796
+ region
1797
+ ],
1798
+ context.projectRoot
1799
+ );
1724
1800
  if (result.exitCode !== 0) {
1725
1801
  return { state: "failed", message: result.stderr };
1726
1802
  }
@@ -1829,18 +1905,22 @@ var AwsLightsailAdapter = class {
1829
1905
  };
1830
1906
  const region = config.region ?? "us-east-1";
1831
1907
  const serviceName = sanitizeLightsailName(config.appName);
1832
- const createService = await this.runner.run("aws", [
1833
- "lightsail",
1834
- "create-container-service",
1835
- "--service-name",
1836
- serviceName,
1837
- "--power",
1838
- "nano",
1839
- "--scale",
1840
- "1",
1841
- "--region",
1842
- region
1843
- ], config.projectRoot);
1908
+ const createService = await this.runner.run(
1909
+ "aws",
1910
+ [
1911
+ "lightsail",
1912
+ "create-container-service",
1913
+ "--service-name",
1914
+ serviceName,
1915
+ "--power",
1916
+ "nano",
1917
+ "--scale",
1918
+ "1",
1919
+ "--region",
1920
+ region
1921
+ ],
1922
+ config.projectRoot
1923
+ );
1844
1924
  if (createService.exitCode !== 0 && !createService.stderr.includes("already exists")) {
1845
1925
  throw new Error(`Failed to create Lightsail container service: ${createService.stderr}`);
1846
1926
  }
@@ -1878,30 +1958,31 @@ var AwsLightsailAdapter = class {
1878
1958
  const serviceName = sanitizeLightsailName(context.appName);
1879
1959
  const imageTag = `${serviceName}:latest`;
1880
1960
  this.logger.step("Building Docker image...");
1881
- const dockerBuild = await this.runner.run("docker", [
1882
- "build",
1883
- "--platform",
1884
- "linux/amd64",
1885
- "-t",
1886
- imageTag,
1887
- "."
1888
- ], artifacts.deployDirectory);
1961
+ const dockerBuild = await this.runner.run(
1962
+ "docker",
1963
+ ["build", "--platform", "linux/amd64", "-t", imageTag, "."],
1964
+ artifacts.deployDirectory
1965
+ );
1889
1966
  if (dockerBuild.exitCode !== 0) {
1890
1967
  throw new Error(`Docker build failed: ${dockerBuild.stderr}`);
1891
1968
  }
1892
1969
  this.logger.step("Pushing image to Lightsail...");
1893
- const pushImage = await this.runner.run("aws", [
1894
- "lightsail",
1895
- "push-container-image",
1896
- "--service-name",
1897
- serviceName,
1898
- "--label",
1899
- "latest",
1900
- "--image",
1901
- imageTag,
1902
- "--region",
1903
- region
1904
- ], artifacts.deployDirectory);
1970
+ const pushImage = await this.runner.run(
1971
+ "aws",
1972
+ [
1973
+ "lightsail",
1974
+ "push-container-image",
1975
+ "--service-name",
1976
+ serviceName,
1977
+ "--label",
1978
+ "latest",
1979
+ "--image",
1980
+ imageTag,
1981
+ "--region",
1982
+ region
1983
+ ],
1984
+ artifacts.deployDirectory
1985
+ );
1905
1986
  if (pushImage.exitCode !== 0) {
1906
1987
  throw new Error(`Lightsail image push failed: ${pushImage.stderr}`);
1907
1988
  }
@@ -1932,29 +2013,30 @@ var AwsLightsailAdapter = class {
1932
2013
  unhealthyThreshold: 3
1933
2014
  }
1934
2015
  });
1935
- const createDeploy = await this.runner.run("aws", [
1936
- "lightsail",
1937
- "create-container-service-deployment",
1938
- "--service-name",
1939
- serviceName,
1940
- "--containers",
1941
- containers,
1942
- "--public-endpoint",
1943
- publicEndpoint,
1944
- "--region",
1945
- region
1946
- ], context.projectRoot);
2016
+ const createDeploy = await this.runner.run(
2017
+ "aws",
2018
+ [
2019
+ "lightsail",
2020
+ "create-container-service-deployment",
2021
+ "--service-name",
2022
+ serviceName,
2023
+ "--containers",
2024
+ containers,
2025
+ "--public-endpoint",
2026
+ publicEndpoint,
2027
+ "--region",
2028
+ region
2029
+ ],
2030
+ context.projectRoot
2031
+ );
1947
2032
  if (createDeploy.exitCode !== 0) {
1948
2033
  throw new Error(`Lightsail deployment failed: ${createDeploy.stderr}`);
1949
2034
  }
1950
- const serviceInfo = await this.runner.run("aws", [
1951
- "lightsail",
1952
- "get-container-services",
1953
- "--service-name",
1954
- serviceName,
1955
- "--region",
1956
- region
1957
- ], context.projectRoot);
2035
+ const serviceInfo = await this.runner.run(
2036
+ "aws",
2037
+ ["lightsail", "get-container-services", "--service-name", serviceName, "--region", region],
2038
+ context.projectRoot
2039
+ );
1958
2040
  const rawUrl = parseLightsailUrl(serviceInfo.stdout) ?? `https://${serviceName}.${region}.cs.amazonlightsail.com`;
1959
2041
  const serviceUrl = rawUrl.replace(/\/+$/, "");
1960
2042
  const deploymentId = (/* @__PURE__ */ new Date()).toISOString();
@@ -1968,14 +2050,18 @@ var AwsLightsailAdapter = class {
1968
2050
  const context = this.requireContext();
1969
2051
  const region = context.region ?? "us-east-1";
1970
2052
  const serviceName = sanitizeLightsailName(context.appName);
1971
- const deployments = await this.runner.run("aws", [
1972
- "lightsail",
1973
- "get-container-service-deployments",
1974
- "--service-name",
1975
- serviceName,
1976
- "--region",
1977
- region
1978
- ], context.projectRoot);
2053
+ const deployments = await this.runner.run(
2054
+ "aws",
2055
+ [
2056
+ "lightsail",
2057
+ "get-container-service-deployments",
2058
+ "--service-name",
2059
+ serviceName,
2060
+ "--region",
2061
+ region
2062
+ ],
2063
+ context.projectRoot
2064
+ );
1979
2065
  if (deployments.exitCode !== 0) {
1980
2066
  throw new Error(`Lightsail rollback failed: ${deployments.stderr}`);
1981
2067
  }
@@ -1983,18 +2069,22 @@ var AwsLightsailAdapter = class {
1983
2069
  if (!previousDeployment) {
1984
2070
  throw new Error("No previous deployment found to rollback to.");
1985
2071
  }
1986
- const redeploy = await this.runner.run("aws", [
1987
- "lightsail",
1988
- "create-container-service-deployment",
1989
- "--service-name",
1990
- serviceName,
1991
- "--containers",
1992
- JSON.stringify(previousDeployment.containers),
1993
- "--public-endpoint",
1994
- JSON.stringify(previousDeployment.publicEndpoint),
1995
- "--region",
1996
- region
1997
- ], context.projectRoot);
2072
+ const redeploy = await this.runner.run(
2073
+ "aws",
2074
+ [
2075
+ "lightsail",
2076
+ "create-container-service-deployment",
2077
+ "--service-name",
2078
+ serviceName,
2079
+ "--containers",
2080
+ JSON.stringify(previousDeployment.containers),
2081
+ "--public-endpoint",
2082
+ JSON.stringify(previousDeployment.publicEndpoint),
2083
+ "--region",
2084
+ region
2085
+ ],
2086
+ context.projectRoot
2087
+ );
1998
2088
  if (redeploy.exitCode !== 0) {
1999
2089
  throw new Error(`Lightsail rollback deployment failed: ${redeploy.stderr}`);
2000
2090
  }
@@ -2041,14 +2131,11 @@ var AwsLightsailAdapter = class {
2041
2131
  const context = this.requireContext();
2042
2132
  const region = context.region ?? "us-east-1";
2043
2133
  const serviceName = sanitizeLightsailName(context.appName);
2044
- const result = await this.runner.run("aws", [
2045
- "lightsail",
2046
- "get-container-services",
2047
- "--service-name",
2048
- serviceName,
2049
- "--region",
2050
- region
2051
- ], context.projectRoot);
2134
+ const result = await this.runner.run(
2135
+ "aws",
2136
+ ["lightsail", "get-container-services", "--service-name", serviceName, "--region", region],
2137
+ context.projectRoot
2138
+ );
2052
2139
  if (result.exitCode !== 0) {
2053
2140
  return { state: "failed", message: result.stderr };
2054
2141
  }
@@ -2113,12 +2200,7 @@ ${error.message}` });
2113
2200
  });
2114
2201
  }
2115
2202
  };
2116
- var PASSTHROUGH_ENV_VARS = [
2117
- "DATABASE_URL",
2118
- "AUTH_SECRET",
2119
- "PUBLIC_URL",
2120
- "NODE_ENV"
2121
- ];
2203
+ var PASSTHROUGH_ENV_VARS = ["DATABASE_URL", "AUTH_SECRET", "PUBLIC_URL", "NODE_ENV"];
2122
2204
  function sanitizeLightsailName(name) {
2123
2205
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-{2,}/g, "-").replace(/^-|-$/g, "").slice(0, 255) || "kora-app";
2124
2206
  }
@@ -2997,7 +3079,8 @@ function generateDeployPackageJson(nativeDependencies) {
2997
3079
  type: "module",
2998
3080
  dependencies: nativeDependencies
2999
3081
  };
3000
- return JSON.stringify(pkg, null, 2) + "\n";
3082
+ return `${JSON.stringify(pkg, null, 2)}
3083
+ `;
3001
3084
  }
3002
3085
  function generateDockerIgnore() {
3003
3086
  return [
@@ -3329,7 +3412,7 @@ var deployCommand = (0, import_citty2.defineCommand)({
3329
3412
  nativeDependencies: {
3330
3413
  "better-sqlite3": "^11.0.0",
3331
3414
  "drizzle-orm": "^0.45.2",
3332
- "postgres": "^3.4.0"
3415
+ postgres: "^3.4.0"
3333
3416
  }
3334
3417
  });
3335
3418
  await writeDockerIgnoreArtifact(deployDirectory);
@@ -3683,7 +3766,14 @@ var SchemaWatcher = class {
3683
3766
  this.watcher = null;
3684
3767
  }
3685
3768
  async regenerate() {
3686
- const koraBinJs = (0, import_node_path18.join)(this.config.projectRoot, "node_modules", "@korajs", "cli", "dist", "bin.js");
3769
+ const koraBinJs = (0, import_node_path18.join)(
3770
+ this.config.projectRoot,
3771
+ "node_modules",
3772
+ "@korajs",
3773
+ "cli",
3774
+ "dist",
3775
+ "bin.js"
3776
+ );
3687
3777
  const hasTsx = await hasTsxInstalled(this.config.projectRoot);
3688
3778
  const command = process.execPath;
3689
3779
  const args = hasTsx ? ["--import", "tsx", koraBinJs, "generate", "types", "--schema", this.config.schemaPath] : [koraBinJs, "generate", "types", "--schema", this.config.schemaPath];
@@ -3819,7 +3909,9 @@ var devCommand = (0, import_citty3.defineCommand)({
3819
3909
  if (await fileExists2(candidate)) {
3820
3910
  configuredSchemaPath = candidate;
3821
3911
  } else {
3822
- logger.warn(`Configured schema file not found: ${candidate}. Falling back to auto-detection.`);
3912
+ logger.warn(
3913
+ `Configured schema file not found: ${candidate}. Falling back to auto-detection.`
3914
+ );
3823
3915
  }
3824
3916
  }
3825
3917
  const schemaPath = configuredSchemaPath ?? await findSchemaFile(projectRoot);
@@ -3973,7 +4065,8 @@ function isPostgresEnvRequested(config) {
3973
4065
  const sync = config?.dev?.sync;
3974
4066
  if (typeof sync !== "object" || sync === null) return false;
3975
4067
  if (sync.store === "postgres") return true;
3976
- if (typeof sync.store === "object" && sync.store !== null && sync.store.type === "postgres") return true;
4068
+ if (typeof sync.store === "object" && sync.store !== null && sync.store.type === "postgres")
4069
+ return true;
3977
4070
  return false;
3978
4071
  }
3979
4072
  var MANAGED_SYNC_BOOTSTRAP_SCRIPT = `
@@ -4294,7 +4387,8 @@ function isBreakingChange(change) {
4294
4387
  if (change.type === "field-changed") {
4295
4388
  if (change.before.kind !== change.after.kind) return true;
4296
4389
  if (change.before.itemKind !== change.after.itemKind) return true;
4297
- if (serializeEnum(change.before.enumValues) !== serializeEnum(change.after.enumValues)) return true;
4390
+ if (serializeEnum(change.before.enumValues) !== serializeEnum(change.after.enumValues))
4391
+ return true;
4298
4392
  if (change.before.required !== change.after.required && change.after.required) return true;
4299
4393
  return false;
4300
4394
  }
@@ -4678,9 +4772,7 @@ async function runSqliteMigration(path, statements, migrationId, fromVersion, to
4678
4772
  async function loadSqliteDriver(projectRoot) {
4679
4773
  try {
4680
4774
  const { createRequire } = await import("module");
4681
- const requireFrom = createRequire(
4682
- projectRoot ? `${projectRoot}/package.json` : import_meta3.url
4683
- );
4775
+ const requireFrom = createRequire(projectRoot ? `${projectRoot}/package.json` : import_meta3.url);
4684
4776
  const Database = requireFrom("better-sqlite3");
4685
4777
  return {
4686
4778
  open(path) {
@@ -4958,7 +5050,12 @@ var migrateCommand = (0, import_citty5.defineCommand)({
4958
5050
  return;
4959
5051
  }
4960
5052
  await (0, import_promises15.mkdir)(outputDir, { recursive: true });
4961
- const migrationPath = await writeMigrationFile(outputDir, diff.fromVersion, diff.toVersion, generated);
5053
+ const migrationPath = await writeMigrationFile(
5054
+ outputDir,
5055
+ diff.fromVersion,
5056
+ diff.toVersion,
5057
+ generated
5058
+ );
4962
5059
  await writeSchemaSnapshot(snapshotFile, currentSchema);
4963
5060
  logger.blank();
4964
5061
  logger.success(`Generated migration: ${migrationPath}`);