@korajs/cli 0.3.4 → 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 (104) hide show
  1. package/dist/bin.cjs +1839 -829
  2. package/dist/bin.cjs.map +1 -1
  3. package/dist/bin.js +1107 -146
  4. package/dist/bin.js.map +1 -1
  5. package/dist/{chunk-HNVCNPER.js → chunk-3WNFM3QB.js} +107 -97
  6. package/dist/chunk-3WNFM3QB.js.map +1 -0
  7. package/dist/{chunk-ULTO5NFA.js → chunk-PSRM56B7.js} +2 -2
  8. package/dist/chunk-PSRM56B7.js.map +1 -0
  9. package/dist/{chunk-MIMLCXSX.js → chunk-SOTZIWIF.js} +267 -228
  10. package/dist/chunk-SOTZIWIF.js.map +1 -0
  11. package/dist/create.cjs +58 -48
  12. package/dist/create.cjs.map +1 -1
  13. package/dist/create.js +2 -2
  14. package/dist/index.cjs +322 -273
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +31 -29
  17. package/dist/index.d.ts +31 -29
  18. package/dist/index.js +2 -2
  19. package/package.json +9 -3
  20. package/templates/react-basic/README.md.hbs +10 -1
  21. package/templates/react-basic/src/App.tsx +112 -126
  22. package/templates/react-basic/src/index.css +165 -159
  23. package/templates/react-basic/src/kora-worker.ts +0 -1
  24. package/templates/react-basic/src/main.tsx +12 -12
  25. package/templates/react-basic/src/modules/todos/todo.mutations.ts +25 -0
  26. package/templates/react-basic/src/modules/todos/todo.queries.ts +5 -0
  27. package/templates/react-basic/src/modules/todos/todo.schema.ts +10 -0
  28. package/templates/react-basic/src/modules/todos/useTodos.ts +31 -0
  29. package/templates/react-basic/src/schema.ts +6 -12
  30. package/templates/react-basic/src/vite-env.d.ts +17 -0
  31. package/templates/react-basic/{tsconfig.json → tsconfig.json.hbs} +1 -2
  32. package/templates/react-basic/vite.config.ts +57 -50
  33. package/templates/react-sync/.env.example +19 -0
  34. package/templates/react-sync/README.md.hbs +43 -1
  35. package/templates/react-sync/package.json.hbs +3 -0
  36. package/templates/react-sync/server.ts +90 -26
  37. package/templates/react-sync/src/App.tsx +132 -130
  38. package/templates/react-sync/src/auth.ts +25 -0
  39. package/templates/react-sync/src/index.css +212 -165
  40. package/templates/react-sync/src/kora-worker.ts +0 -1
  41. package/templates/react-sync/src/main.tsx +34 -18
  42. package/templates/react-sync/src/modules/todos/todo.mutations.ts +25 -0
  43. package/templates/react-sync/src/modules/todos/todo.queries.ts +5 -0
  44. package/templates/react-sync/src/modules/todos/todo.schema.ts +10 -0
  45. package/templates/react-sync/src/modules/todos/useTodos.ts +31 -0
  46. package/templates/react-sync/src/schema.ts +6 -12
  47. package/templates/react-sync/src/vite-env.d.ts +17 -0
  48. package/templates/react-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
  49. package/templates/react-sync/vite.config.ts +67 -60
  50. package/templates/react-tailwind/README.md.hbs +10 -1
  51. package/templates/react-tailwind/src/App.tsx +186 -197
  52. package/templates/react-tailwind/src/index.css +3 -3
  53. package/templates/react-tailwind/src/kora-worker.ts +0 -1
  54. package/templates/react-tailwind/src/main.tsx +19 -12
  55. package/templates/react-tailwind/src/modules/todos/todo.mutations.ts +25 -0
  56. package/templates/react-tailwind/src/modules/todos/todo.queries.ts +5 -0
  57. package/templates/react-tailwind/src/modules/todos/todo.schema.ts +10 -0
  58. package/templates/react-tailwind/src/modules/todos/useTodos.ts +31 -0
  59. package/templates/react-tailwind/src/schema.ts +6 -12
  60. package/templates/react-tailwind/src/vite-env.d.ts +17 -0
  61. package/templates/react-tailwind/{tsconfig.json → tsconfig.json.hbs} +1 -2
  62. package/templates/react-tailwind/vite.config.ts +57 -50
  63. package/templates/react-tailwind-sync/.env.example +19 -0
  64. package/templates/react-tailwind-sync/README.md.hbs +43 -1
  65. package/templates/react-tailwind-sync/package.json.hbs +3 -0
  66. package/templates/react-tailwind-sync/server.ts +90 -26
  67. package/templates/react-tailwind-sync/src/App.tsx +246 -222
  68. package/templates/react-tailwind-sync/src/auth.ts +25 -0
  69. package/templates/react-tailwind-sync/src/index.css +3 -3
  70. package/templates/react-tailwind-sync/src/kora-worker.ts +0 -1
  71. package/templates/react-tailwind-sync/src/main.tsx +48 -18
  72. package/templates/react-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
  73. package/templates/react-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
  74. package/templates/react-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
  75. package/templates/react-tailwind-sync/src/modules/todos/useTodos.ts +31 -0
  76. package/templates/react-tailwind-sync/src/schema.ts +6 -12
  77. package/templates/react-tailwind-sync/src/vite-env.d.ts +17 -0
  78. package/templates/react-tailwind-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
  79. package/templates/react-tailwind-sync/vite.config.ts +67 -60
  80. package/templates/tauri-react/.env.example +20 -0
  81. package/templates/tauri-react/README.md.hbs +36 -1
  82. package/templates/tauri-react/dev.ts +11 -11
  83. package/templates/tauri-react/package.json.hbs +2 -0
  84. package/templates/tauri-react/server.ts +86 -12
  85. package/templates/tauri-react/src/App.tsx +769 -544
  86. package/templates/tauri-react/src/AppShell.tsx +125 -83
  87. package/templates/tauri-react/src/SetupScreen.tsx +257 -208
  88. package/templates/tauri-react/src/auth.ts +45 -0
  89. package/templates/tauri-react/src/main.tsx +3 -3
  90. package/templates/tauri-react/src/modules/todos/todo.mutations.ts +25 -0
  91. package/templates/tauri-react/src/modules/todos/todo.queries.ts +5 -0
  92. package/templates/tauri-react/src/modules/todos/todo.schema.ts +10 -0
  93. package/templates/tauri-react/src/modules/todos/useTodos.ts +31 -0
  94. package/templates/tauri-react/src/schema.ts +6 -12
  95. package/templates/tauri-react/src/sync-config.ts +47 -47
  96. package/templates/tauri-react/src/updater.ts +15 -15
  97. package/templates/tauri-react/src/vite-env.d.ts +17 -0
  98. package/templates/tauri-react/src-tauri/tauri.conf.json +2 -2
  99. package/templates/tauri-react/tsconfig.json.hbs +14 -0
  100. package/templates/tauri-react/vite.config.ts +9 -9
  101. package/dist/chunk-HNVCNPER.js.map +0 -1
  102. package/dist/chunk-MIMLCXSX.js.map +0 -1
  103. package/dist/chunk-ULTO5NFA.js.map +0 -1
  104. package/templates/tauri-react/tsconfig.json +0 -15
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
 
@@ -350,6 +351,7 @@ function promptConfirm(message, defaultValue = false, options) {
350
351
  resolve3(false);
351
352
  return;
352
353
  }
354
+ ;
353
355
  (options?.output ?? process.stdout).write(" Please answer with y or n\n");
354
356
  ask();
355
357
  });
@@ -542,7 +544,15 @@ function createLogger(options) {
542
544
  }
543
545
 
544
546
  // src/commands/deploy/adapters/adapter.ts
545
- var DEPLOY_PLATFORMS = ["fly", "railway", "aws-ecs", "aws-lightsail", "render", "docker", "kora-cloud"];
547
+ var DEPLOY_PLATFORMS = [
548
+ "fly",
549
+ "railway",
550
+ "aws-ecs",
551
+ "aws-lightsail",
552
+ "render",
553
+ "docker",
554
+ "kora-cloud"
555
+ ];
546
556
  function isDeployPlatform(value) {
547
557
  return DEPLOY_PLATFORMS.includes(value);
548
558
  }
@@ -553,8 +563,8 @@ var import_node_path4 = require("path");
553
563
 
554
564
  // src/commands/deploy/builder/client-builder.ts
555
565
  var import_node_child_process = require("child_process");
556
- var import_promises2 = require("fs/promises");
557
566
  var import_node_fs = require("fs");
567
+ var import_promises2 = require("fs/promises");
558
568
  var import_node_path2 = require("path");
559
569
  async function buildClient(options) {
560
570
  const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
@@ -712,37 +722,46 @@ var AwsEcsAdapter = class {
712
722
  };
713
723
  const region = config.region ?? "us-east-1";
714
724
  const repoName = `kora/${config.appName}`;
715
- const createRepo = await this.runner.run("aws", [
716
- "ecr",
717
- "create-repository",
718
- "--repository-name",
719
- repoName,
720
- "--region",
721
- region,
722
- "--image-scanning-configuration",
723
- "scanOnPush=true"
724
- ], config.projectRoot);
725
+ const createRepo = await this.runner.run(
726
+ "aws",
727
+ [
728
+ "ecr",
729
+ "create-repository",
730
+ "--repository-name",
731
+ repoName,
732
+ "--region",
733
+ region,
734
+ "--image-scanning-configuration",
735
+ "scanOnPush=true"
736
+ ],
737
+ config.projectRoot
738
+ );
725
739
  if (createRepo.exitCode !== 0 && !createRepo.stderr.includes("RepositoryAlreadyExistsException")) {
726
740
  throw new Error(`Failed to create ECR repository: ${createRepo.stderr}`);
727
741
  }
728
- const identity = await this.runner.run("aws", ["sts", "get-caller-identity", "--query", "Account", "--output", "text"], config.projectRoot);
742
+ const identity = await this.runner.run(
743
+ "aws",
744
+ ["sts", "get-caller-identity", "--query", "Account", "--output", "text"],
745
+ config.projectRoot
746
+ );
729
747
  const accountId = identity.stdout.trim();
730
- await this.runner.run("aws", [
731
- "ecs",
732
- "create-cluster",
733
- "--cluster-name",
734
- config.appName,
735
- "--region",
736
- region
737
- ], config.projectRoot);
738
- await this.runner.run("aws", [
739
- "logs",
740
- "create-log-group",
741
- "--log-group-name",
742
- `/ecs/${config.appName}`,
743
- "--region",
744
- region
745
- ], config.projectRoot);
748
+ await this.runner.run(
749
+ "aws",
750
+ ["ecs", "create-cluster", "--cluster-name", config.appName, "--region", region],
751
+ config.projectRoot
752
+ );
753
+ await this.runner.run(
754
+ "aws",
755
+ [
756
+ "logs",
757
+ "create-log-group",
758
+ "--log-group-name",
759
+ `/ecs/${config.appName}`,
760
+ "--region",
761
+ region
762
+ ],
763
+ config.projectRoot
764
+ );
746
765
  return {
747
766
  applicationId: `${accountId}.dkr.ecr.${region}.amazonaws.com/${repoName}`,
748
767
  databaseId: null,
@@ -760,13 +779,13 @@ var AwsEcsAdapter = class {
760
779
  projectRoot: config.projectRoot,
761
780
  deployDirectory
762
781
  });
763
- const client = await buildClient({
782
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
764
783
  projectRoot: config.projectRoot,
765
784
  outDir: (0, import_node_path4.join)(deployDirectory, "dist"),
766
785
  mode: "production"
767
786
  });
768
787
  return {
769
- clientDirectory: client.outDir,
788
+ clientDirectory: client?.outDir ?? null,
770
789
  serverBundlePath: (0, import_node_path4.join)(deployDirectory, "server-bundled.js"),
771
790
  deployDirectory
772
791
  };
@@ -775,50 +794,42 @@ var AwsEcsAdapter = class {
775
794
  const context = this.requireContext();
776
795
  const region = context.region ?? "us-east-1";
777
796
  const repoName = `kora/${context.appName}`;
778
- const loginPassword = await this.runner.run("aws", [
779
- "ecr",
780
- "get-login-password",
781
- "--region",
782
- region
783
- ], context.projectRoot);
797
+ const loginPassword = await this.runner.run(
798
+ "aws",
799
+ ["ecr", "get-login-password", "--region", region],
800
+ context.projectRoot
801
+ );
784
802
  if (loginPassword.exitCode !== 0) {
785
803
  throw new Error(`ECR login failed: ${loginPassword.stderr}`);
786
804
  }
787
- const identity = await this.runner.run("aws", [
788
- "sts",
789
- "get-caller-identity",
790
- "--query",
791
- "Account",
792
- "--output",
793
- "text"
794
- ], context.projectRoot);
805
+ const identity = await this.runner.run(
806
+ "aws",
807
+ ["sts", "get-caller-identity", "--query", "Account", "--output", "text"],
808
+ context.projectRoot
809
+ );
795
810
  const accountId = identity.stdout.trim();
796
811
  const ecrUri = `${accountId}.dkr.ecr.${region}.amazonaws.com`;
797
812
  const imageUri = `${ecrUri}/${repoName}:latest`;
798
- const dockerLogin = await this.runner.run("docker", [
799
- "login",
800
- "--username",
801
- "AWS",
802
- "--password-stdin",
803
- ecrUri
804
- ], artifacts.deployDirectory);
813
+ const dockerLogin = await this.runner.run(
814
+ "docker",
815
+ ["login", "--username", "AWS", "--password-stdin", ecrUri],
816
+ artifacts.deployDirectory
817
+ );
805
818
  this.logger.step("Building Docker image...");
806
- const dockerBuild = await this.runner.run("docker", [
807
- "build",
808
- "--platform",
809
- "linux/amd64",
810
- "-t",
811
- imageUri,
812
- "."
813
- ], artifacts.deployDirectory);
819
+ const dockerBuild = await this.runner.run(
820
+ "docker",
821
+ ["build", "--platform", "linux/amd64", "-t", imageUri, "."],
822
+ artifacts.deployDirectory
823
+ );
814
824
  if (dockerBuild.exitCode !== 0) {
815
825
  throw new Error(`Docker build failed: ${dockerBuild.stderr}`);
816
826
  }
817
827
  this.logger.step("Pushing image to ECR...");
818
- const dockerPush = await this.runner.run("docker", [
819
- "push",
820
- imageUri
821
- ], artifacts.deployDirectory);
828
+ const dockerPush = await this.runner.run(
829
+ "docker",
830
+ ["push", imageUri],
831
+ artifacts.deployDirectory
832
+ );
822
833
  if (dockerPush.exitCode !== 0) {
823
834
  throw new Error(`Docker push failed: ${dockerPush.stderr}`);
824
835
  }
@@ -829,52 +840,55 @@ var AwsEcsAdapter = class {
829
840
  cpu: "256",
830
841
  memory: "512",
831
842
  executionRoleArn: `arn:aws:iam::${accountId}:role/ecsTaskExecutionRole`,
832
- containerDefinitions: [{
833
- name: context.appName,
834
- image: imageUri,
835
- essential: true,
836
- portMappings: [{ containerPort: 3001, protocol: "tcp" }],
837
- logConfiguration: {
838
- logDriver: "awslogs",
839
- options: {
840
- "awslogs-group": `/ecs/${context.appName}`,
841
- "awslogs-region": region,
842
- "awslogs-stream-prefix": "ecs"
843
+ containerDefinitions: [
844
+ {
845
+ name: context.appName,
846
+ image: imageUri,
847
+ essential: true,
848
+ portMappings: [{ containerPort: 3001, protocol: "tcp" }],
849
+ logConfiguration: {
850
+ logDriver: "awslogs",
851
+ options: {
852
+ "awslogs-group": `/ecs/${context.appName}`,
853
+ "awslogs-region": region,
854
+ "awslogs-stream-prefix": "ecs"
855
+ }
856
+ },
857
+ healthCheck: {
858
+ command: ["CMD-SHELL", "curl -f http://localhost:3001/health || exit 1"],
859
+ interval: 30,
860
+ timeout: 5,
861
+ retries: 3,
862
+ startPeriod: 60
843
863
  }
844
- },
845
- healthCheck: {
846
- command: ["CMD-SHELL", "curl -f http://localhost:3001/health || exit 1"],
847
- interval: 30,
848
- timeout: 5,
849
- retries: 3,
850
- startPeriod: 60
851
864
  }
852
- }]
865
+ ]
853
866
  });
854
- const registerTask = await this.runner.run("aws", [
855
- "ecs",
856
- "register-task-definition",
857
- "--cli-input-json",
858
- taskDef,
859
- "--region",
860
- region
861
- ], context.projectRoot);
867
+ const registerTask = await this.runner.run(
868
+ "aws",
869
+ ["ecs", "register-task-definition", "--cli-input-json", taskDef, "--region", region],
870
+ context.projectRoot
871
+ );
862
872
  if (registerTask.exitCode !== 0) {
863
873
  throw new Error(`Task definition registration failed: ${registerTask.stderr}`);
864
874
  }
865
- const updateService = await this.runner.run("aws", [
866
- "ecs",
867
- "update-service",
868
- "--cluster",
869
- context.appName,
870
- "--service",
871
- context.appName,
872
- "--task-definition",
873
- context.appName,
874
- "--force-new-deployment",
875
- "--region",
876
- region
877
- ], context.projectRoot);
875
+ const updateService = await this.runner.run(
876
+ "aws",
877
+ [
878
+ "ecs",
879
+ "update-service",
880
+ "--cluster",
881
+ context.appName,
882
+ "--service",
883
+ context.appName,
884
+ "--task-definition",
885
+ context.appName,
886
+ "--force-new-deployment",
887
+ "--region",
888
+ region
889
+ ],
890
+ context.projectRoot
891
+ );
878
892
  const deploymentId = (/* @__PURE__ */ new Date()).toISOString();
879
893
  if (updateService.exitCode !== 0) {
880
894
  this.logger.step("Service not found, creating new service...");
@@ -899,19 +913,23 @@ var AwsEcsAdapter = class {
899
913
  async rollback(deploymentId) {
900
914
  const context = this.requireContext();
901
915
  const region = context.region ?? "us-east-1";
902
- const result = await this.runner.run("aws", [
903
- "ecs",
904
- "update-service",
905
- "--cluster",
906
- context.appName,
907
- "--service",
908
- context.appName,
909
- "--task-definition",
910
- `${context.appName}:${deploymentId}`,
911
- "--force-new-deployment",
912
- "--region",
913
- region
914
- ], context.projectRoot);
916
+ const result = await this.runner.run(
917
+ "aws",
918
+ [
919
+ "ecs",
920
+ "update-service",
921
+ "--cluster",
922
+ context.appName,
923
+ "--service",
924
+ context.appName,
925
+ "--task-definition",
926
+ `${context.appName}:${deploymentId}`,
927
+ "--force-new-deployment",
928
+ "--region",
929
+ region
930
+ ],
931
+ context.projectRoot
932
+ );
915
933
  if (result.exitCode !== 0) {
916
934
  throw new Error(`ECS rollback failed: ${result.stderr}`);
917
935
  }
@@ -954,16 +972,20 @@ var AwsEcsAdapter = class {
954
972
  async status() {
955
973
  const context = this.requireContext();
956
974
  const region = context.region ?? "us-east-1";
957
- const result = await this.runner.run("aws", [
958
- "ecs",
959
- "describe-services",
960
- "--cluster",
961
- context.appName,
962
- "--services",
963
- context.appName,
964
- "--region",
965
- region
966
- ], context.projectRoot);
975
+ const result = await this.runner.run(
976
+ "aws",
977
+ [
978
+ "ecs",
979
+ "describe-services",
980
+ "--cluster",
981
+ context.appName,
982
+ "--services",
983
+ context.appName,
984
+ "--region",
985
+ region
986
+ ],
987
+ context.projectRoot
988
+ );
967
989
  if (result.exitCode !== 0) {
968
990
  return { state: "failed", message: result.stderr };
969
991
  }
@@ -1072,18 +1094,22 @@ var AwsLightsailAdapter = class {
1072
1094
  };
1073
1095
  const region = config.region ?? "us-east-1";
1074
1096
  const serviceName = sanitizeLightsailName(config.appName);
1075
- const createService = await this.runner.run("aws", [
1076
- "lightsail",
1077
- "create-container-service",
1078
- "--service-name",
1079
- serviceName,
1080
- "--power",
1081
- "nano",
1082
- "--scale",
1083
- "1",
1084
- "--region",
1085
- region
1086
- ], config.projectRoot);
1097
+ const createService = await this.runner.run(
1098
+ "aws",
1099
+ [
1100
+ "lightsail",
1101
+ "create-container-service",
1102
+ "--service-name",
1103
+ serviceName,
1104
+ "--power",
1105
+ "nano",
1106
+ "--scale",
1107
+ "1",
1108
+ "--region",
1109
+ region
1110
+ ],
1111
+ config.projectRoot
1112
+ );
1087
1113
  if (createService.exitCode !== 0 && !createService.stderr.includes("already exists")) {
1088
1114
  throw new Error(`Failed to create Lightsail container service: ${createService.stderr}`);
1089
1115
  }
@@ -1104,13 +1130,13 @@ var AwsLightsailAdapter = class {
1104
1130
  projectRoot: config.projectRoot,
1105
1131
  deployDirectory
1106
1132
  });
1107
- const client = await buildClient({
1133
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
1108
1134
  projectRoot: config.projectRoot,
1109
1135
  outDir: (0, import_node_path5.join)(deployDirectory, "dist"),
1110
1136
  mode: "production"
1111
1137
  });
1112
1138
  return {
1113
- clientDirectory: client.outDir,
1139
+ clientDirectory: client?.outDir ?? null,
1114
1140
  serverBundlePath: (0, import_node_path5.join)(deployDirectory, "server-bundled.js"),
1115
1141
  deployDirectory
1116
1142
  };
@@ -1121,30 +1147,31 @@ var AwsLightsailAdapter = class {
1121
1147
  const serviceName = sanitizeLightsailName(context.appName);
1122
1148
  const imageTag = `${serviceName}:latest`;
1123
1149
  this.logger.step("Building Docker image...");
1124
- const dockerBuild = await this.runner.run("docker", [
1125
- "build",
1126
- "--platform",
1127
- "linux/amd64",
1128
- "-t",
1129
- imageTag,
1130
- "."
1131
- ], artifacts.deployDirectory);
1150
+ const dockerBuild = await this.runner.run(
1151
+ "docker",
1152
+ ["build", "--platform", "linux/amd64", "-t", imageTag, "."],
1153
+ artifacts.deployDirectory
1154
+ );
1132
1155
  if (dockerBuild.exitCode !== 0) {
1133
1156
  throw new Error(`Docker build failed: ${dockerBuild.stderr}`);
1134
1157
  }
1135
1158
  this.logger.step("Pushing image to Lightsail...");
1136
- const pushImage = await this.runner.run("aws", [
1137
- "lightsail",
1138
- "push-container-image",
1139
- "--service-name",
1140
- serviceName,
1141
- "--label",
1142
- "latest",
1143
- "--image",
1144
- imageTag,
1145
- "--region",
1146
- region
1147
- ], artifacts.deployDirectory);
1159
+ const pushImage = await this.runner.run(
1160
+ "aws",
1161
+ [
1162
+ "lightsail",
1163
+ "push-container-image",
1164
+ "--service-name",
1165
+ serviceName,
1166
+ "--label",
1167
+ "latest",
1168
+ "--image",
1169
+ imageTag,
1170
+ "--region",
1171
+ region
1172
+ ],
1173
+ artifacts.deployDirectory
1174
+ );
1148
1175
  if (pushImage.exitCode !== 0) {
1149
1176
  throw new Error(`Lightsail image push failed: ${pushImage.stderr}`);
1150
1177
  }
@@ -1175,29 +1202,30 @@ var AwsLightsailAdapter = class {
1175
1202
  unhealthyThreshold: 3
1176
1203
  }
1177
1204
  });
1178
- const createDeploy = await this.runner.run("aws", [
1179
- "lightsail",
1180
- "create-container-service-deployment",
1181
- "--service-name",
1182
- serviceName,
1183
- "--containers",
1184
- containers,
1185
- "--public-endpoint",
1186
- publicEndpoint,
1187
- "--region",
1188
- region
1189
- ], context.projectRoot);
1205
+ const createDeploy = await this.runner.run(
1206
+ "aws",
1207
+ [
1208
+ "lightsail",
1209
+ "create-container-service-deployment",
1210
+ "--service-name",
1211
+ serviceName,
1212
+ "--containers",
1213
+ containers,
1214
+ "--public-endpoint",
1215
+ publicEndpoint,
1216
+ "--region",
1217
+ region
1218
+ ],
1219
+ context.projectRoot
1220
+ );
1190
1221
  if (createDeploy.exitCode !== 0) {
1191
1222
  throw new Error(`Lightsail deployment failed: ${createDeploy.stderr}`);
1192
1223
  }
1193
- const serviceInfo = await this.runner.run("aws", [
1194
- "lightsail",
1195
- "get-container-services",
1196
- "--service-name",
1197
- serviceName,
1198
- "--region",
1199
- region
1200
- ], context.projectRoot);
1224
+ const serviceInfo = await this.runner.run(
1225
+ "aws",
1226
+ ["lightsail", "get-container-services", "--service-name", serviceName, "--region", region],
1227
+ context.projectRoot
1228
+ );
1201
1229
  const rawUrl = parseLightsailUrl(serviceInfo.stdout) ?? `https://${serviceName}.${region}.cs.amazonlightsail.com`;
1202
1230
  const serviceUrl = rawUrl.replace(/\/+$/, "");
1203
1231
  const deploymentId = (/* @__PURE__ */ new Date()).toISOString();
@@ -1211,14 +1239,18 @@ var AwsLightsailAdapter = class {
1211
1239
  const context = this.requireContext();
1212
1240
  const region = context.region ?? "us-east-1";
1213
1241
  const serviceName = sanitizeLightsailName(context.appName);
1214
- const deployments = await this.runner.run("aws", [
1215
- "lightsail",
1216
- "get-container-service-deployments",
1217
- "--service-name",
1218
- serviceName,
1219
- "--region",
1220
- region
1221
- ], context.projectRoot);
1242
+ const deployments = await this.runner.run(
1243
+ "aws",
1244
+ [
1245
+ "lightsail",
1246
+ "get-container-service-deployments",
1247
+ "--service-name",
1248
+ serviceName,
1249
+ "--region",
1250
+ region
1251
+ ],
1252
+ context.projectRoot
1253
+ );
1222
1254
  if (deployments.exitCode !== 0) {
1223
1255
  throw new Error(`Lightsail rollback failed: ${deployments.stderr}`);
1224
1256
  }
@@ -1226,18 +1258,22 @@ var AwsLightsailAdapter = class {
1226
1258
  if (!previousDeployment) {
1227
1259
  throw new Error("No previous deployment found to rollback to.");
1228
1260
  }
1229
- const redeploy = await this.runner.run("aws", [
1230
- "lightsail",
1231
- "create-container-service-deployment",
1232
- "--service-name",
1233
- serviceName,
1234
- "--containers",
1235
- JSON.stringify(previousDeployment.containers),
1236
- "--public-endpoint",
1237
- JSON.stringify(previousDeployment.publicEndpoint),
1238
- "--region",
1239
- region
1240
- ], context.projectRoot);
1261
+ const redeploy = await this.runner.run(
1262
+ "aws",
1263
+ [
1264
+ "lightsail",
1265
+ "create-container-service-deployment",
1266
+ "--service-name",
1267
+ serviceName,
1268
+ "--containers",
1269
+ JSON.stringify(previousDeployment.containers),
1270
+ "--public-endpoint",
1271
+ JSON.stringify(previousDeployment.publicEndpoint),
1272
+ "--region",
1273
+ region
1274
+ ],
1275
+ context.projectRoot
1276
+ );
1241
1277
  if (redeploy.exitCode !== 0) {
1242
1278
  throw new Error(`Lightsail rollback deployment failed: ${redeploy.stderr}`);
1243
1279
  }
@@ -1284,14 +1320,11 @@ var AwsLightsailAdapter = class {
1284
1320
  const context = this.requireContext();
1285
1321
  const region = context.region ?? "us-east-1";
1286
1322
  const serviceName = sanitizeLightsailName(context.appName);
1287
- const result = await this.runner.run("aws", [
1288
- "lightsail",
1289
- "get-container-services",
1290
- "--service-name",
1291
- serviceName,
1292
- "--region",
1293
- region
1294
- ], context.projectRoot);
1323
+ const result = await this.runner.run(
1324
+ "aws",
1325
+ ["lightsail", "get-container-services", "--service-name", serviceName, "--region", region],
1326
+ context.projectRoot
1327
+ );
1295
1328
  if (result.exitCode !== 0) {
1296
1329
  return { state: "failed", message: result.stderr };
1297
1330
  }
@@ -1356,12 +1389,7 @@ ${error.message}` });
1356
1389
  });
1357
1390
  }
1358
1391
  };
1359
- var PASSTHROUGH_ENV_VARS = [
1360
- "DATABASE_URL",
1361
- "AUTH_SECRET",
1362
- "PUBLIC_URL",
1363
- "NODE_ENV"
1364
- ];
1392
+ var PASSTHROUGH_ENV_VARS = ["DATABASE_URL", "AUTH_SECRET", "PUBLIC_URL", "NODE_ENV"];
1365
1393
  function sanitizeLightsailName(name) {
1366
1394
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-{2,}/g, "-").replace(/^-|-$/g, "").slice(0, 255) || "kora-app";
1367
1395
  }
@@ -1438,7 +1466,7 @@ function generateFlyToml(options) {
1438
1466
  ' interval = "30s"',
1439
1467
  ' method = "GET"',
1440
1468
  ' timeout = "5s"',
1441
- ' path = "/"',
1469
+ ' path = "/health"',
1442
1470
  ""
1443
1471
  ].join("\n");
1444
1472
  }
@@ -1548,13 +1576,13 @@ var FlyAdapter = class {
1548
1576
  projectRoot: config.projectRoot,
1549
1577
  deployDirectory
1550
1578
  });
1551
- const client = await buildClient({
1579
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
1552
1580
  projectRoot: config.projectRoot,
1553
1581
  outDir: (0, import_node_path7.join)(deployDirectory, "dist"),
1554
1582
  mode: "production"
1555
1583
  });
1556
1584
  return {
1557
- clientDirectory: client.outDir,
1585
+ clientDirectory: client?.outDir ?? null,
1558
1586
  serverBundlePath: (0, import_node_path7.join)(deployDirectory, "server-bundled.js"),
1559
1587
  deployDirectory
1560
1588
  };
@@ -1906,13 +1934,13 @@ var RailwayAdapter = class {
1906
1934
  projectRoot: config.projectRoot,
1907
1935
  deployDirectory
1908
1936
  });
1909
- const client = await buildClient({
1937
+ const client = config.deployTarget === "sync-server" ? null : await buildClient({
1910
1938
  projectRoot: config.projectRoot,
1911
1939
  outDir: (0, import_node_path9.join)(deployDirectory, "dist"),
1912
1940
  mode: "production"
1913
1941
  });
1914
1942
  return {
1915
- clientDirectory: client.outDir,
1943
+ clientDirectory: client?.outDir ?? null,
1916
1944
  serverBundlePath: (0, import_node_path9.join)(deployDirectory, "server-bundled.js"),
1917
1945
  deployDirectory
1918
1946
  };
@@ -2204,7 +2232,7 @@ var GENERATED_HEADER3 = "# Generated by kora deploy \u2014 do not edit manually"
2204
2232
  function generateDockerfile(options = {}) {
2205
2233
  const nodeVersion = options.nodeVersion ?? "20-alpine";
2206
2234
  const port = options.port ?? 3e3;
2207
- const clientDirectory = options.clientDirectory ?? "dist";
2235
+ const clientDirectory = options.clientDirectory === void 0 ? "dist" : options.clientDirectory;
2208
2236
  const serverBundleFile = options.serverBundleFile ?? "server-bundled.js";
2209
2237
  const hasNativeDeps = options.nativeDependencies && Object.keys(options.nativeDependencies).length > 0;
2210
2238
  const lines = [
@@ -2224,7 +2252,9 @@ function generateDockerfile(options = {}) {
2224
2252
  lines.push("RUN npm install --omit=dev");
2225
2253
  lines.push("");
2226
2254
  }
2227
- lines.push(`COPY ${clientDirectory} ./dist`);
2255
+ if (clientDirectory !== null) {
2256
+ lines.push(`COPY ${clientDirectory} ./dist`);
2257
+ }
2228
2258
  lines.push(`COPY ${serverBundleFile} ./server-bundled.js`);
2229
2259
  lines.push("");
2230
2260
  lines.push(`EXPOSE ${String(port)}`);
@@ -2240,7 +2270,8 @@ function generateDeployPackageJson(nativeDependencies) {
2240
2270
  type: "module",
2241
2271
  dependencies: nativeDependencies
2242
2272
  };
2243
- return JSON.stringify(pkg, null, 2) + "\n";
2273
+ return `${JSON.stringify(pkg, null, 2)}
2274
+ `;
2244
2275
  }
2245
2276
  function generateDockerIgnore() {
2246
2277
  return [
@@ -2548,12 +2579,14 @@ var deployCommand = (0, import_citty.defineCommand)({
2548
2579
  const region = resolveRegion(args.region, existingState?.region, confirmMode);
2549
2580
  const deployDirectory = resolveDeployDirectory(projectRoot);
2550
2581
  const environment = args.prod === true ? "production" : "preview";
2582
+ const deployTarget = detectDeployTarget(projectRoot);
2551
2583
  const config = {
2552
2584
  projectRoot,
2553
2585
  appName,
2554
2586
  region,
2555
2587
  environment,
2556
- confirm: confirmMode
2588
+ confirm: confirmMode,
2589
+ deployTarget
2557
2590
  };
2558
2591
  const adapter = createDeployAdapter(platform);
2559
2592
  configureAdapterContext(adapter, {
@@ -2565,14 +2598,18 @@ var deployCommand = (0, import_citty.defineCommand)({
2565
2598
  logger.info(
2566
2599
  `Deploying to ${platform} (${appName}${region ? `, ${region}` : ""}, ${environment})`
2567
2600
  );
2601
+ if (deployTarget === "sync-server") {
2602
+ logger.step("Detected Tauri project. Deploying the sync server only.");
2603
+ }
2568
2604
  if (confirmMode) {
2569
2605
  logger.step("Running in --confirm mode (non-interactive, fail-fast).");
2570
2606
  }
2571
2607
  await writeDockerfileArtifact(deployDirectory, {
2608
+ clientDirectory: deployTarget === "sync-server" ? null : void 0,
2572
2609
  nativeDependencies: {
2573
2610
  "better-sqlite3": "^11.0.0",
2574
2611
  "drizzle-orm": "^0.45.2",
2575
- "postgres": "^3.4.0"
2612
+ postgres: "^3.4.0"
2576
2613
  }
2577
2614
  });
2578
2615
  await writeDockerIgnoreArtifact(deployDirectory);
@@ -2707,6 +2744,9 @@ function configureAdapterContext(adapter, context) {
2707
2744
  adapter.setContext(context);
2708
2745
  }
2709
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
+ }
2710
2750
  function hasContextSetter(adapter) {
2711
2751
  return typeof adapter.setContext === "function";
2712
2752
  }
@@ -2835,10 +2875,49 @@ async function resolveCreatePreferencesFlow(params) {
2835
2875
  if (isTauri) {
2836
2876
  effective.framework = "react";
2837
2877
  effective.tailwind = false;
2838
- effective.sync = true;
2839
- effective.db = "sqlite";
2840
- effective.dbProvider = "none";
2841
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
+ }
2842
2921
  } else {
2843
2922
  if (flags.framework !== void 0) {
2844
2923
  if (!isFrameworkValue(flags.framework)) {
@@ -2881,7 +2960,9 @@ async function resolveCreatePreferencesFlow(params) {
2881
2960
  }
2882
2961
  if (flags.db !== void 0) {
2883
2962
  if (!isDatabaseValue(flags.db)) {
2884
- throw new Error(`Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`);
2963
+ throw new Error(
2964
+ `Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
2965
+ );
2885
2966
  }
2886
2967
  effective.db = flags.db;
2887
2968
  } else if (!effective.sync) {
@@ -2972,63 +3053,31 @@ async function applySyncProviderPreset(options) {
2972
3053
  }
2973
3054
  const providerName = getProviderDisplayName(options.dbProvider);
2974
3055
  const providerConnectionString = getProviderConnectionStringExample(options.dbProvider);
2975
- const serverPath = (0, import_node_path13.join)(options.targetDir, "server.ts");
2976
3056
  const envPath = (0, import_node_path13.join)(options.targetDir, ".env.example");
2977
3057
  const readmePath = (0, import_node_path13.join)(options.targetDir, "README.md");
2978
- const serverTemplate = [
2979
- "import { createPostgresServerStore, createProductionServer } from '@korajs/server'",
2980
- "",
2981
- `// PostgreSQL provider preset: ${providerName}`,
2982
- "// Ensure DATABASE_URL is set in your environment.",
2983
- "",
2984
- "async function start(): Promise<void> {",
2985
- " const connectionString = process.env.DATABASE_URL || ''",
2986
- " if (connectionString.length === 0) {",
2987
- " throw new Error('DATABASE_URL is required for PostgreSQL sync server store.')",
2988
- " }",
2989
- "",
2990
- " const store = await createPostgresServerStore({ connectionString })",
2991
- " const server = createProductionServer({",
2992
- " store,",
2993
- " port: Number(process.env.PORT) || 3001,",
2994
- " staticDir: './dist',",
2995
- " syncPath: '/kora-sync',",
2996
- " })",
2997
- "",
2998
- " const url = await server.start()",
2999
- " console.log(`Kora app running at ${url}`)",
3000
- "}",
3001
- "",
3002
- "void start()",
3003
- ""
3004
- ].join("\n");
3005
- const envTemplate = [
3006
- "# Kora Sync Server",
3007
- "# WebSocket URL for the sync server (used by the client)",
3008
- "VITE_SYNC_URL=ws://localhost:3001",
3009
- "",
3010
- "# Sync server port",
3011
- "PORT=3001",
3012
- "",
3013
- `# PostgreSQL connection string (${providerName})`,
3014
- `# Example: ${providerConnectionString}`,
3015
- "DATABASE_URL=",
3016
- ""
3017
- ].join("\n");
3018
3058
  const existingReadme = await (0, import_promises9.readFile)(readmePath, "utf-8");
3059
+ const existingEnv = await (0, import_promises9.readFile)(envPath, "utf-8");
3019
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");
3020
3067
  const readmeSuffix = [
3021
3068
  "",
3022
3069
  "## PostgreSQL Provider Preset",
3023
3070
  "",
3024
3071
  `Selected DB provider: ${options.dbProvider}`,
3025
3072
  "",
3026
- "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.",
3027
3076
  ""
3028
3077
  ].join("\n");
3029
3078
  const readmeTemplate = `${trimmedReadme}${readmeSuffix}`;
3030
- await (0, import_promises9.writeFile)(serverPath, serverTemplate, "utf-8");
3031
- await (0, import_promises9.writeFile)(envPath, envTemplate, "utf-8");
3079
+ await (0, import_promises9.writeFile)(envPath, `${trimmedEnv}${envSuffix}
3080
+ `, "utf-8");
3032
3081
  await (0, import_promises9.writeFile)(readmePath, readmeTemplate, "utf-8");
3033
3082
  }
3034
3083
  function isSyncTemplate(template) {