@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.
- package/dist/bin.cjs +1839 -829
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1107 -146
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-HNVCNPER.js → chunk-3WNFM3QB.js} +107 -97
- package/dist/chunk-3WNFM3QB.js.map +1 -0
- package/dist/{chunk-ULTO5NFA.js → chunk-PSRM56B7.js} +2 -2
- package/dist/chunk-PSRM56B7.js.map +1 -0
- package/dist/{chunk-MIMLCXSX.js → chunk-SOTZIWIF.js} +267 -228
- package/dist/chunk-SOTZIWIF.js.map +1 -0
- package/dist/create.cjs +58 -48
- package/dist/create.cjs.map +1 -1
- package/dist/create.js +2 -2
- package/dist/index.cjs +322 -273
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -29
- package/dist/index.d.ts +31 -29
- package/dist/index.js +2 -2
- package/package.json +9 -3
- package/templates/react-basic/README.md.hbs +10 -1
- package/templates/react-basic/src/App.tsx +112 -126
- package/templates/react-basic/src/index.css +165 -159
- package/templates/react-basic/src/kora-worker.ts +0 -1
- package/templates/react-basic/src/main.tsx +12 -12
- package/templates/react-basic/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-basic/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-basic/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-basic/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-basic/src/schema.ts +6 -12
- package/templates/react-basic/src/vite-env.d.ts +17 -0
- package/templates/react-basic/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-basic/vite.config.ts +57 -50
- package/templates/react-sync/.env.example +19 -0
- package/templates/react-sync/README.md.hbs +43 -1
- package/templates/react-sync/package.json.hbs +3 -0
- package/templates/react-sync/server.ts +90 -26
- package/templates/react-sync/src/App.tsx +132 -130
- package/templates/react-sync/src/auth.ts +25 -0
- package/templates/react-sync/src/index.css +212 -165
- package/templates/react-sync/src/kora-worker.ts +0 -1
- package/templates/react-sync/src/main.tsx +34 -18
- package/templates/react-sync/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-sync/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-sync/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-sync/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-sync/src/schema.ts +6 -12
- package/templates/react-sync/src/vite-env.d.ts +17 -0
- package/templates/react-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-sync/vite.config.ts +67 -60
- package/templates/react-tailwind/README.md.hbs +10 -1
- package/templates/react-tailwind/src/App.tsx +186 -197
- package/templates/react-tailwind/src/index.css +3 -3
- package/templates/react-tailwind/src/kora-worker.ts +0 -1
- package/templates/react-tailwind/src/main.tsx +19 -12
- package/templates/react-tailwind/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-tailwind/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-tailwind/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-tailwind/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-tailwind/src/schema.ts +6 -12
- package/templates/react-tailwind/src/vite-env.d.ts +17 -0
- package/templates/react-tailwind/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-tailwind/vite.config.ts +57 -50
- package/templates/react-tailwind-sync/.env.example +19 -0
- package/templates/react-tailwind-sync/README.md.hbs +43 -1
- package/templates/react-tailwind-sync/package.json.hbs +3 -0
- package/templates/react-tailwind-sync/server.ts +90 -26
- package/templates/react-tailwind-sync/src/App.tsx +246 -222
- package/templates/react-tailwind-sync/src/auth.ts +25 -0
- package/templates/react-tailwind-sync/src/index.css +3 -3
- package/templates/react-tailwind-sync/src/kora-worker.ts +0 -1
- package/templates/react-tailwind-sync/src/main.tsx +48 -18
- package/templates/react-tailwind-sync/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/react-tailwind-sync/src/modules/todos/todo.queries.ts +5 -0
- package/templates/react-tailwind-sync/src/modules/todos/todo.schema.ts +10 -0
- package/templates/react-tailwind-sync/src/modules/todos/useTodos.ts +31 -0
- package/templates/react-tailwind-sync/src/schema.ts +6 -12
- package/templates/react-tailwind-sync/src/vite-env.d.ts +17 -0
- package/templates/react-tailwind-sync/{tsconfig.json → tsconfig.json.hbs} +1 -2
- package/templates/react-tailwind-sync/vite.config.ts +67 -60
- package/templates/tauri-react/.env.example +20 -0
- package/templates/tauri-react/README.md.hbs +36 -1
- package/templates/tauri-react/dev.ts +11 -11
- package/templates/tauri-react/package.json.hbs +2 -0
- package/templates/tauri-react/server.ts +86 -12
- package/templates/tauri-react/src/App.tsx +769 -544
- package/templates/tauri-react/src/AppShell.tsx +125 -83
- package/templates/tauri-react/src/SetupScreen.tsx +257 -208
- package/templates/tauri-react/src/auth.ts +45 -0
- package/templates/tauri-react/src/main.tsx +3 -3
- package/templates/tauri-react/src/modules/todos/todo.mutations.ts +25 -0
- package/templates/tauri-react/src/modules/todos/todo.queries.ts +5 -0
- package/templates/tauri-react/src/modules/todos/todo.schema.ts +10 -0
- package/templates/tauri-react/src/modules/todos/useTodos.ts +31 -0
- package/templates/tauri-react/src/schema.ts +6 -12
- package/templates/tauri-react/src/sync-config.ts +47 -47
- package/templates/tauri-react/src/updater.ts +15 -15
- package/templates/tauri-react/src/vite-env.d.ts +17 -0
- package/templates/tauri-react/src-tauri/tauri.conf.json +2 -2
- package/templates/tauri-react/tsconfig.json.hbs +14 -0
- package/templates/tauri-react/vite.config.ts +9 -9
- package/dist/chunk-HNVCNPER.js.map +0 -1
- package/dist/chunk-MIMLCXSX.js.map +0 -1
- package/dist/chunk-ULTO5NFA.js.map +0 -1
- 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 = [
|
|
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(
|
|
716
|
-
"
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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(
|
|
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(
|
|
731
|
-
"
|
|
732
|
-
"create-cluster",
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
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
|
|
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(
|
|
779
|
-
"
|
|
780
|
-
"get-login-password",
|
|
781
|
-
|
|
782
|
-
|
|
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(
|
|
788
|
-
"
|
|
789
|
-
"get-caller-identity",
|
|
790
|
-
|
|
791
|
-
|
|
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(
|
|
799
|
-
"
|
|
800
|
-
"--username",
|
|
801
|
-
|
|
802
|
-
|
|
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(
|
|
807
|
-
"
|
|
808
|
-
"--platform",
|
|
809
|
-
|
|
810
|
-
|
|
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(
|
|
819
|
-
"
|
|
820
|
-
imageUri
|
|
821
|
-
|
|
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
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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(
|
|
855
|
-
"
|
|
856
|
-
"register-task-definition",
|
|
857
|
-
|
|
858
|
-
|
|
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(
|
|
866
|
-
"
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
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(
|
|
903
|
-
"
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
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(
|
|
958
|
-
"
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
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(
|
|
1076
|
-
"
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
|
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(
|
|
1125
|
-
"
|
|
1126
|
-
"--platform",
|
|
1127
|
-
|
|
1128
|
-
|
|
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(
|
|
1137
|
-
"
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
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(
|
|
1179
|
-
"
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
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(
|
|
1194
|
-
"
|
|
1195
|
-
"get-container-services",
|
|
1196
|
-
|
|
1197
|
-
|
|
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(
|
|
1215
|
-
"
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
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(
|
|
1230
|
-
"
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
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(
|
|
1288
|
-
"
|
|
1289
|
-
"get-container-services",
|
|
1290
|
-
|
|
1291
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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(
|
|
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
|
|
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)(
|
|
3031
|
-
|
|
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) {
|