@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.
- package/dist/bin.cjs +385 -288
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +25 -11
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-KTSRAPSE.js → chunk-CMSX76KM.js} +108 -65
- package/dist/chunk-CMSX76KM.js.map +1 -0
- package/dist/{chunk-ZGYRDYXS.js → chunk-MVP5PDT4.js} +22 -4
- package/dist/chunk-MVP5PDT4.js.map +1 -0
- package/dist/{chunk-E7OCVRYL.js → chunk-YGVO4POI.js} +242 -215
- package/dist/chunk-YGVO4POI.js.map +1 -0
- package/dist/create.cjs +122 -66
- package/dist/create.cjs.map +1 -1
- package/dist/create.js +2 -2
- package/dist/index.cjs +348 -278
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -26
- package/dist/index.d.ts +31 -26
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/templates/tauri-react/.env.example +7 -0
- package/templates/tauri-react/.github/workflows/release-desktop.yml +107 -0
- package/templates/tauri-react/README.md.hbs +148 -0
- package/templates/tauri-react/dev.ts +37 -0
- package/templates/tauri-react/index.html.hbs +16 -0
- package/templates/tauri-react/kora.config.ts +17 -0
- package/templates/tauri-react/package.json.hbs +44 -0
- package/templates/tauri-react/server.ts +23 -0
- package/templates/tauri-react/src/App.tsx +578 -0
- package/templates/tauri-react/src/AppShell.tsx +116 -0
- package/templates/tauri-react/src/SetupScreen.tsx +239 -0
- package/templates/tauri-react/src/main.tsx +9 -0
- package/templates/tauri-react/src/schema.ts +15 -0
- package/templates/tauri-react/src/sync-config.ts +103 -0
- package/templates/tauri-react/src/updater.ts +38 -0
- package/templates/tauri-react/src-tauri/Cargo.toml +19 -0
- package/templates/tauri-react/src-tauri/build.rs +3 -0
- package/templates/tauri-react/src-tauri/capabilities/default.json +12 -0
- package/templates/tauri-react/src-tauri/icons/128x128.png +0 -0
- package/templates/tauri-react/src-tauri/icons/128x128@2x.png +0 -0
- package/templates/tauri-react/src-tauri/icons/32x32.png +0 -0
- package/templates/tauri-react/src-tauri/icons/icon.icns +0 -0
- package/templates/tauri-react/src-tauri/icons/icon.ico +0 -0
- package/templates/tauri-react/src-tauri/src/lib.rs +8 -0
- package/templates/tauri-react/src-tauri/src/main.rs +6 -0
- package/templates/tauri-react/src-tauri/tauri.conf.json +44 -0
- package/templates/tauri-react/tsconfig.json +15 -0
- package/templates/tauri-react/vite.config.ts +15 -0
- package/dist/chunk-E7OCVRYL.js.map +0 -1
- package/dist/chunk-KTSRAPSE.js.map +0 -1
- package/dist/chunk-ZGYRDYXS.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -91,7 +91,8 @@ var TEMPLATES = [
|
|
|
91
91
|
"react-tailwind-sync",
|
|
92
92
|
"react-tailwind",
|
|
93
93
|
"react-sync",
|
|
94
|
-
"react-basic"
|
|
94
|
+
"react-basic",
|
|
95
|
+
"tauri-react"
|
|
95
96
|
];
|
|
96
97
|
var TEMPLATE_INFO = [
|
|
97
98
|
{
|
|
@@ -113,6 +114,11 @@ var TEMPLATE_INFO = [
|
|
|
113
114
|
name: "react-basic",
|
|
114
115
|
label: "React + CSS (local-only)",
|
|
115
116
|
description: "Clean CSS app \u2014 no sync server"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "tauri-react",
|
|
120
|
+
label: "Tauri Desktop (native SQLite)",
|
|
121
|
+
description: "Desktop app with native SQLite \u2014 no WASM, includes sync server"
|
|
116
122
|
}
|
|
117
123
|
];
|
|
118
124
|
|
|
@@ -344,6 +350,7 @@ function promptConfirm(message, defaultValue = false, options) {
|
|
|
344
350
|
resolve3(false);
|
|
345
351
|
return;
|
|
346
352
|
}
|
|
353
|
+
;
|
|
347
354
|
(options?.output ?? process.stdout).write(" Please answer with y or n\n");
|
|
348
355
|
ask();
|
|
349
356
|
});
|
|
@@ -536,7 +543,15 @@ function createLogger(options) {
|
|
|
536
543
|
}
|
|
537
544
|
|
|
538
545
|
// src/commands/deploy/adapters/adapter.ts
|
|
539
|
-
var DEPLOY_PLATFORMS = [
|
|
546
|
+
var DEPLOY_PLATFORMS = [
|
|
547
|
+
"fly",
|
|
548
|
+
"railway",
|
|
549
|
+
"aws-ecs",
|
|
550
|
+
"aws-lightsail",
|
|
551
|
+
"render",
|
|
552
|
+
"docker",
|
|
553
|
+
"kora-cloud"
|
|
554
|
+
];
|
|
540
555
|
function isDeployPlatform(value) {
|
|
541
556
|
return DEPLOY_PLATFORMS.includes(value);
|
|
542
557
|
}
|
|
@@ -547,8 +562,8 @@ var import_node_path4 = require("path");
|
|
|
547
562
|
|
|
548
563
|
// src/commands/deploy/builder/client-builder.ts
|
|
549
564
|
var import_node_child_process = require("child_process");
|
|
550
|
-
var import_promises2 = require("fs/promises");
|
|
551
565
|
var import_node_fs = require("fs");
|
|
566
|
+
var import_promises2 = require("fs/promises");
|
|
552
567
|
var import_node_path2 = require("path");
|
|
553
568
|
async function buildClient(options) {
|
|
554
569
|
const viteEntryPoint = await resolveProjectBinaryEntryPoint(options.projectRoot, "vite", "vite");
|
|
@@ -706,37 +721,46 @@ var AwsEcsAdapter = class {
|
|
|
706
721
|
};
|
|
707
722
|
const region = config.region ?? "us-east-1";
|
|
708
723
|
const repoName = `kora/${config.appName}`;
|
|
709
|
-
const createRepo = await this.runner.run(
|
|
710
|
-
"
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
724
|
+
const createRepo = await this.runner.run(
|
|
725
|
+
"aws",
|
|
726
|
+
[
|
|
727
|
+
"ecr",
|
|
728
|
+
"create-repository",
|
|
729
|
+
"--repository-name",
|
|
730
|
+
repoName,
|
|
731
|
+
"--region",
|
|
732
|
+
region,
|
|
733
|
+
"--image-scanning-configuration",
|
|
734
|
+
"scanOnPush=true"
|
|
735
|
+
],
|
|
736
|
+
config.projectRoot
|
|
737
|
+
);
|
|
719
738
|
if (createRepo.exitCode !== 0 && !createRepo.stderr.includes("RepositoryAlreadyExistsException")) {
|
|
720
739
|
throw new Error(`Failed to create ECR repository: ${createRepo.stderr}`);
|
|
721
740
|
}
|
|
722
|
-
const identity = await this.runner.run(
|
|
741
|
+
const identity = await this.runner.run(
|
|
742
|
+
"aws",
|
|
743
|
+
["sts", "get-caller-identity", "--query", "Account", "--output", "text"],
|
|
744
|
+
config.projectRoot
|
|
745
|
+
);
|
|
723
746
|
const accountId = identity.stdout.trim();
|
|
724
|
-
await this.runner.run(
|
|
725
|
-
"
|
|
726
|
-
"create-cluster",
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
747
|
+
await this.runner.run(
|
|
748
|
+
"aws",
|
|
749
|
+
["ecs", "create-cluster", "--cluster-name", config.appName, "--region", region],
|
|
750
|
+
config.projectRoot
|
|
751
|
+
);
|
|
752
|
+
await this.runner.run(
|
|
753
|
+
"aws",
|
|
754
|
+
[
|
|
755
|
+
"logs",
|
|
756
|
+
"create-log-group",
|
|
757
|
+
"--log-group-name",
|
|
758
|
+
`/ecs/${config.appName}`,
|
|
759
|
+
"--region",
|
|
760
|
+
region
|
|
761
|
+
],
|
|
762
|
+
config.projectRoot
|
|
763
|
+
);
|
|
740
764
|
return {
|
|
741
765
|
applicationId: `${accountId}.dkr.ecr.${region}.amazonaws.com/${repoName}`,
|
|
742
766
|
databaseId: null,
|
|
@@ -769,50 +793,42 @@ var AwsEcsAdapter = class {
|
|
|
769
793
|
const context = this.requireContext();
|
|
770
794
|
const region = context.region ?? "us-east-1";
|
|
771
795
|
const repoName = `kora/${context.appName}`;
|
|
772
|
-
const loginPassword = await this.runner.run(
|
|
773
|
-
"
|
|
774
|
-
"get-login-password",
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
], context.projectRoot);
|
|
796
|
+
const loginPassword = await this.runner.run(
|
|
797
|
+
"aws",
|
|
798
|
+
["ecr", "get-login-password", "--region", region],
|
|
799
|
+
context.projectRoot
|
|
800
|
+
);
|
|
778
801
|
if (loginPassword.exitCode !== 0) {
|
|
779
802
|
throw new Error(`ECR login failed: ${loginPassword.stderr}`);
|
|
780
803
|
}
|
|
781
|
-
const identity = await this.runner.run(
|
|
782
|
-
"
|
|
783
|
-
"get-caller-identity",
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
"--output",
|
|
787
|
-
"text"
|
|
788
|
-
], context.projectRoot);
|
|
804
|
+
const identity = await this.runner.run(
|
|
805
|
+
"aws",
|
|
806
|
+
["sts", "get-caller-identity", "--query", "Account", "--output", "text"],
|
|
807
|
+
context.projectRoot
|
|
808
|
+
);
|
|
789
809
|
const accountId = identity.stdout.trim();
|
|
790
810
|
const ecrUri = `${accountId}.dkr.ecr.${region}.amazonaws.com`;
|
|
791
811
|
const imageUri = `${ecrUri}/${repoName}:latest`;
|
|
792
|
-
const dockerLogin = await this.runner.run(
|
|
793
|
-
"
|
|
794
|
-
"--username",
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
ecrUri
|
|
798
|
-
], artifacts.deployDirectory);
|
|
812
|
+
const dockerLogin = await this.runner.run(
|
|
813
|
+
"docker",
|
|
814
|
+
["login", "--username", "AWS", "--password-stdin", ecrUri],
|
|
815
|
+
artifacts.deployDirectory
|
|
816
|
+
);
|
|
799
817
|
this.logger.step("Building Docker image...");
|
|
800
|
-
const dockerBuild = await this.runner.run(
|
|
801
|
-
"
|
|
802
|
-
"--platform",
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
imageUri,
|
|
806
|
-
"."
|
|
807
|
-
], artifacts.deployDirectory);
|
|
818
|
+
const dockerBuild = await this.runner.run(
|
|
819
|
+
"docker",
|
|
820
|
+
["build", "--platform", "linux/amd64", "-t", imageUri, "."],
|
|
821
|
+
artifacts.deployDirectory
|
|
822
|
+
);
|
|
808
823
|
if (dockerBuild.exitCode !== 0) {
|
|
809
824
|
throw new Error(`Docker build failed: ${dockerBuild.stderr}`);
|
|
810
825
|
}
|
|
811
826
|
this.logger.step("Pushing image to ECR...");
|
|
812
|
-
const dockerPush = await this.runner.run(
|
|
813
|
-
"
|
|
814
|
-
imageUri
|
|
815
|
-
|
|
827
|
+
const dockerPush = await this.runner.run(
|
|
828
|
+
"docker",
|
|
829
|
+
["push", imageUri],
|
|
830
|
+
artifacts.deployDirectory
|
|
831
|
+
);
|
|
816
832
|
if (dockerPush.exitCode !== 0) {
|
|
817
833
|
throw new Error(`Docker push failed: ${dockerPush.stderr}`);
|
|
818
834
|
}
|
|
@@ -823,52 +839,55 @@ var AwsEcsAdapter = class {
|
|
|
823
839
|
cpu: "256",
|
|
824
840
|
memory: "512",
|
|
825
841
|
executionRoleArn: `arn:aws:iam::${accountId}:role/ecsTaskExecutionRole`,
|
|
826
|
-
containerDefinitions: [
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
842
|
+
containerDefinitions: [
|
|
843
|
+
{
|
|
844
|
+
name: context.appName,
|
|
845
|
+
image: imageUri,
|
|
846
|
+
essential: true,
|
|
847
|
+
portMappings: [{ containerPort: 3001, protocol: "tcp" }],
|
|
848
|
+
logConfiguration: {
|
|
849
|
+
logDriver: "awslogs",
|
|
850
|
+
options: {
|
|
851
|
+
"awslogs-group": `/ecs/${context.appName}`,
|
|
852
|
+
"awslogs-region": region,
|
|
853
|
+
"awslogs-stream-prefix": "ecs"
|
|
854
|
+
}
|
|
855
|
+
},
|
|
856
|
+
healthCheck: {
|
|
857
|
+
command: ["CMD-SHELL", "curl -f http://localhost:3001/health || exit 1"],
|
|
858
|
+
interval: 30,
|
|
859
|
+
timeout: 5,
|
|
860
|
+
retries: 3,
|
|
861
|
+
startPeriod: 60
|
|
837
862
|
}
|
|
838
|
-
},
|
|
839
|
-
healthCheck: {
|
|
840
|
-
command: ["CMD-SHELL", "curl -f http://localhost:3001/health || exit 1"],
|
|
841
|
-
interval: 30,
|
|
842
|
-
timeout: 5,
|
|
843
|
-
retries: 3,
|
|
844
|
-
startPeriod: 60
|
|
845
863
|
}
|
|
846
|
-
|
|
864
|
+
]
|
|
847
865
|
});
|
|
848
|
-
const registerTask = await this.runner.run(
|
|
849
|
-
"
|
|
850
|
-
"register-task-definition",
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
"--region",
|
|
854
|
-
region
|
|
855
|
-
], context.projectRoot);
|
|
866
|
+
const registerTask = await this.runner.run(
|
|
867
|
+
"aws",
|
|
868
|
+
["ecs", "register-task-definition", "--cli-input-json", taskDef, "--region", region],
|
|
869
|
+
context.projectRoot
|
|
870
|
+
);
|
|
856
871
|
if (registerTask.exitCode !== 0) {
|
|
857
872
|
throw new Error(`Task definition registration failed: ${registerTask.stderr}`);
|
|
858
873
|
}
|
|
859
|
-
const updateService = await this.runner.run(
|
|
860
|
-
"
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
874
|
+
const updateService = await this.runner.run(
|
|
875
|
+
"aws",
|
|
876
|
+
[
|
|
877
|
+
"ecs",
|
|
878
|
+
"update-service",
|
|
879
|
+
"--cluster",
|
|
880
|
+
context.appName,
|
|
881
|
+
"--service",
|
|
882
|
+
context.appName,
|
|
883
|
+
"--task-definition",
|
|
884
|
+
context.appName,
|
|
885
|
+
"--force-new-deployment",
|
|
886
|
+
"--region",
|
|
887
|
+
region
|
|
888
|
+
],
|
|
889
|
+
context.projectRoot
|
|
890
|
+
);
|
|
872
891
|
const deploymentId = (/* @__PURE__ */ new Date()).toISOString();
|
|
873
892
|
if (updateService.exitCode !== 0) {
|
|
874
893
|
this.logger.step("Service not found, creating new service...");
|
|
@@ -893,19 +912,23 @@ var AwsEcsAdapter = class {
|
|
|
893
912
|
async rollback(deploymentId) {
|
|
894
913
|
const context = this.requireContext();
|
|
895
914
|
const region = context.region ?? "us-east-1";
|
|
896
|
-
const result = await this.runner.run(
|
|
897
|
-
"
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
915
|
+
const result = await this.runner.run(
|
|
916
|
+
"aws",
|
|
917
|
+
[
|
|
918
|
+
"ecs",
|
|
919
|
+
"update-service",
|
|
920
|
+
"--cluster",
|
|
921
|
+
context.appName,
|
|
922
|
+
"--service",
|
|
923
|
+
context.appName,
|
|
924
|
+
"--task-definition",
|
|
925
|
+
`${context.appName}:${deploymentId}`,
|
|
926
|
+
"--force-new-deployment",
|
|
927
|
+
"--region",
|
|
928
|
+
region
|
|
929
|
+
],
|
|
930
|
+
context.projectRoot
|
|
931
|
+
);
|
|
909
932
|
if (result.exitCode !== 0) {
|
|
910
933
|
throw new Error(`ECS rollback failed: ${result.stderr}`);
|
|
911
934
|
}
|
|
@@ -948,16 +971,20 @@ var AwsEcsAdapter = class {
|
|
|
948
971
|
async status() {
|
|
949
972
|
const context = this.requireContext();
|
|
950
973
|
const region = context.region ?? "us-east-1";
|
|
951
|
-
const result = await this.runner.run(
|
|
952
|
-
"
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
974
|
+
const result = await this.runner.run(
|
|
975
|
+
"aws",
|
|
976
|
+
[
|
|
977
|
+
"ecs",
|
|
978
|
+
"describe-services",
|
|
979
|
+
"--cluster",
|
|
980
|
+
context.appName,
|
|
981
|
+
"--services",
|
|
982
|
+
context.appName,
|
|
983
|
+
"--region",
|
|
984
|
+
region
|
|
985
|
+
],
|
|
986
|
+
context.projectRoot
|
|
987
|
+
);
|
|
961
988
|
if (result.exitCode !== 0) {
|
|
962
989
|
return { state: "failed", message: result.stderr };
|
|
963
990
|
}
|
|
@@ -1066,18 +1093,22 @@ var AwsLightsailAdapter = class {
|
|
|
1066
1093
|
};
|
|
1067
1094
|
const region = config.region ?? "us-east-1";
|
|
1068
1095
|
const serviceName = sanitizeLightsailName(config.appName);
|
|
1069
|
-
const createService = await this.runner.run(
|
|
1070
|
-
"
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1096
|
+
const createService = await this.runner.run(
|
|
1097
|
+
"aws",
|
|
1098
|
+
[
|
|
1099
|
+
"lightsail",
|
|
1100
|
+
"create-container-service",
|
|
1101
|
+
"--service-name",
|
|
1102
|
+
serviceName,
|
|
1103
|
+
"--power",
|
|
1104
|
+
"nano",
|
|
1105
|
+
"--scale",
|
|
1106
|
+
"1",
|
|
1107
|
+
"--region",
|
|
1108
|
+
region
|
|
1109
|
+
],
|
|
1110
|
+
config.projectRoot
|
|
1111
|
+
);
|
|
1081
1112
|
if (createService.exitCode !== 0 && !createService.stderr.includes("already exists")) {
|
|
1082
1113
|
throw new Error(`Failed to create Lightsail container service: ${createService.stderr}`);
|
|
1083
1114
|
}
|
|
@@ -1115,30 +1146,31 @@ var AwsLightsailAdapter = class {
|
|
|
1115
1146
|
const serviceName = sanitizeLightsailName(context.appName);
|
|
1116
1147
|
const imageTag = `${serviceName}:latest`;
|
|
1117
1148
|
this.logger.step("Building Docker image...");
|
|
1118
|
-
const dockerBuild = await this.runner.run(
|
|
1119
|
-
"
|
|
1120
|
-
"--platform",
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
imageTag,
|
|
1124
|
-
"."
|
|
1125
|
-
], artifacts.deployDirectory);
|
|
1149
|
+
const dockerBuild = await this.runner.run(
|
|
1150
|
+
"docker",
|
|
1151
|
+
["build", "--platform", "linux/amd64", "-t", imageTag, "."],
|
|
1152
|
+
artifacts.deployDirectory
|
|
1153
|
+
);
|
|
1126
1154
|
if (dockerBuild.exitCode !== 0) {
|
|
1127
1155
|
throw new Error(`Docker build failed: ${dockerBuild.stderr}`);
|
|
1128
1156
|
}
|
|
1129
1157
|
this.logger.step("Pushing image to Lightsail...");
|
|
1130
|
-
const pushImage = await this.runner.run(
|
|
1131
|
-
"
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1158
|
+
const pushImage = await this.runner.run(
|
|
1159
|
+
"aws",
|
|
1160
|
+
[
|
|
1161
|
+
"lightsail",
|
|
1162
|
+
"push-container-image",
|
|
1163
|
+
"--service-name",
|
|
1164
|
+
serviceName,
|
|
1165
|
+
"--label",
|
|
1166
|
+
"latest",
|
|
1167
|
+
"--image",
|
|
1168
|
+
imageTag,
|
|
1169
|
+
"--region",
|
|
1170
|
+
region
|
|
1171
|
+
],
|
|
1172
|
+
artifacts.deployDirectory
|
|
1173
|
+
);
|
|
1142
1174
|
if (pushImage.exitCode !== 0) {
|
|
1143
1175
|
throw new Error(`Lightsail image push failed: ${pushImage.stderr}`);
|
|
1144
1176
|
}
|
|
@@ -1169,29 +1201,30 @@ var AwsLightsailAdapter = class {
|
|
|
1169
1201
|
unhealthyThreshold: 3
|
|
1170
1202
|
}
|
|
1171
1203
|
});
|
|
1172
|
-
const createDeploy = await this.runner.run(
|
|
1173
|
-
"
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1204
|
+
const createDeploy = await this.runner.run(
|
|
1205
|
+
"aws",
|
|
1206
|
+
[
|
|
1207
|
+
"lightsail",
|
|
1208
|
+
"create-container-service-deployment",
|
|
1209
|
+
"--service-name",
|
|
1210
|
+
serviceName,
|
|
1211
|
+
"--containers",
|
|
1212
|
+
containers,
|
|
1213
|
+
"--public-endpoint",
|
|
1214
|
+
publicEndpoint,
|
|
1215
|
+
"--region",
|
|
1216
|
+
region
|
|
1217
|
+
],
|
|
1218
|
+
context.projectRoot
|
|
1219
|
+
);
|
|
1184
1220
|
if (createDeploy.exitCode !== 0) {
|
|
1185
1221
|
throw new Error(`Lightsail deployment failed: ${createDeploy.stderr}`);
|
|
1186
1222
|
}
|
|
1187
|
-
const serviceInfo = await this.runner.run(
|
|
1188
|
-
"
|
|
1189
|
-
"get-container-services",
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
"--region",
|
|
1193
|
-
region
|
|
1194
|
-
], context.projectRoot);
|
|
1223
|
+
const serviceInfo = await this.runner.run(
|
|
1224
|
+
"aws",
|
|
1225
|
+
["lightsail", "get-container-services", "--service-name", serviceName, "--region", region],
|
|
1226
|
+
context.projectRoot
|
|
1227
|
+
);
|
|
1195
1228
|
const rawUrl = parseLightsailUrl(serviceInfo.stdout) ?? `https://${serviceName}.${region}.cs.amazonlightsail.com`;
|
|
1196
1229
|
const serviceUrl = rawUrl.replace(/\/+$/, "");
|
|
1197
1230
|
const deploymentId = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1205,14 +1238,18 @@ var AwsLightsailAdapter = class {
|
|
|
1205
1238
|
const context = this.requireContext();
|
|
1206
1239
|
const region = context.region ?? "us-east-1";
|
|
1207
1240
|
const serviceName = sanitizeLightsailName(context.appName);
|
|
1208
|
-
const deployments = await this.runner.run(
|
|
1209
|
-
"
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1241
|
+
const deployments = await this.runner.run(
|
|
1242
|
+
"aws",
|
|
1243
|
+
[
|
|
1244
|
+
"lightsail",
|
|
1245
|
+
"get-container-service-deployments",
|
|
1246
|
+
"--service-name",
|
|
1247
|
+
serviceName,
|
|
1248
|
+
"--region",
|
|
1249
|
+
region
|
|
1250
|
+
],
|
|
1251
|
+
context.projectRoot
|
|
1252
|
+
);
|
|
1216
1253
|
if (deployments.exitCode !== 0) {
|
|
1217
1254
|
throw new Error(`Lightsail rollback failed: ${deployments.stderr}`);
|
|
1218
1255
|
}
|
|
@@ -1220,18 +1257,22 @@ var AwsLightsailAdapter = class {
|
|
|
1220
1257
|
if (!previousDeployment) {
|
|
1221
1258
|
throw new Error("No previous deployment found to rollback to.");
|
|
1222
1259
|
}
|
|
1223
|
-
const redeploy = await this.runner.run(
|
|
1224
|
-
"
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1260
|
+
const redeploy = await this.runner.run(
|
|
1261
|
+
"aws",
|
|
1262
|
+
[
|
|
1263
|
+
"lightsail",
|
|
1264
|
+
"create-container-service-deployment",
|
|
1265
|
+
"--service-name",
|
|
1266
|
+
serviceName,
|
|
1267
|
+
"--containers",
|
|
1268
|
+
JSON.stringify(previousDeployment.containers),
|
|
1269
|
+
"--public-endpoint",
|
|
1270
|
+
JSON.stringify(previousDeployment.publicEndpoint),
|
|
1271
|
+
"--region",
|
|
1272
|
+
region
|
|
1273
|
+
],
|
|
1274
|
+
context.projectRoot
|
|
1275
|
+
);
|
|
1235
1276
|
if (redeploy.exitCode !== 0) {
|
|
1236
1277
|
throw new Error(`Lightsail rollback deployment failed: ${redeploy.stderr}`);
|
|
1237
1278
|
}
|
|
@@ -1278,14 +1319,11 @@ var AwsLightsailAdapter = class {
|
|
|
1278
1319
|
const context = this.requireContext();
|
|
1279
1320
|
const region = context.region ?? "us-east-1";
|
|
1280
1321
|
const serviceName = sanitizeLightsailName(context.appName);
|
|
1281
|
-
const result = await this.runner.run(
|
|
1282
|
-
"
|
|
1283
|
-
"get-container-services",
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
"--region",
|
|
1287
|
-
region
|
|
1288
|
-
], context.projectRoot);
|
|
1322
|
+
const result = await this.runner.run(
|
|
1323
|
+
"aws",
|
|
1324
|
+
["lightsail", "get-container-services", "--service-name", serviceName, "--region", region],
|
|
1325
|
+
context.projectRoot
|
|
1326
|
+
);
|
|
1289
1327
|
if (result.exitCode !== 0) {
|
|
1290
1328
|
return { state: "failed", message: result.stderr };
|
|
1291
1329
|
}
|
|
@@ -1350,12 +1388,7 @@ ${error.message}` });
|
|
|
1350
1388
|
});
|
|
1351
1389
|
}
|
|
1352
1390
|
};
|
|
1353
|
-
var PASSTHROUGH_ENV_VARS = [
|
|
1354
|
-
"DATABASE_URL",
|
|
1355
|
-
"AUTH_SECRET",
|
|
1356
|
-
"PUBLIC_URL",
|
|
1357
|
-
"NODE_ENV"
|
|
1358
|
-
];
|
|
1391
|
+
var PASSTHROUGH_ENV_VARS = ["DATABASE_URL", "AUTH_SECRET", "PUBLIC_URL", "NODE_ENV"];
|
|
1359
1392
|
function sanitizeLightsailName(name) {
|
|
1360
1393
|
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-{2,}/g, "-").replace(/^-|-$/g, "").slice(0, 255) || "kora-app";
|
|
1361
1394
|
}
|
|
@@ -2234,7 +2267,8 @@ function generateDeployPackageJson(nativeDependencies) {
|
|
|
2234
2267
|
type: "module",
|
|
2235
2268
|
dependencies: nativeDependencies
|
|
2236
2269
|
};
|
|
2237
|
-
return JSON.stringify(pkg, null, 2)
|
|
2270
|
+
return `${JSON.stringify(pkg, null, 2)}
|
|
2271
|
+
`;
|
|
2238
2272
|
}
|
|
2239
2273
|
function generateDockerIgnore() {
|
|
2240
2274
|
return [
|
|
@@ -2566,7 +2600,7 @@ var deployCommand = (0, import_citty.defineCommand)({
|
|
|
2566
2600
|
nativeDependencies: {
|
|
2567
2601
|
"better-sqlite3": "^11.0.0",
|
|
2568
2602
|
"drizzle-orm": "^0.45.2",
|
|
2569
|
-
|
|
2603
|
+
postgres: "^3.4.0"
|
|
2570
2604
|
}
|
|
2571
2605
|
});
|
|
2572
2606
|
await writeDockerIgnoreArtifact(deployDirectory);
|
|
@@ -2731,12 +2765,16 @@ function validateProjectName(name) {
|
|
|
2731
2765
|
|
|
2732
2766
|
// src/commands/create/options.ts
|
|
2733
2767
|
function determineTemplateFromSelections(input) {
|
|
2768
|
+
if (input.platform === "desktop-tauri") return "tauri-react";
|
|
2734
2769
|
const shouldSync = input.sync && input.db !== "none";
|
|
2735
2770
|
if (input.tailwind && shouldSync) return "react-tailwind-sync";
|
|
2736
2771
|
if (input.tailwind && !shouldSync) return "react-tailwind";
|
|
2737
2772
|
if (!input.tailwind && shouldSync) return "react-sync";
|
|
2738
2773
|
return "react-basic";
|
|
2739
2774
|
}
|
|
2775
|
+
function isPlatformValue(value) {
|
|
2776
|
+
return value === "web" || value === "desktop-tauri";
|
|
2777
|
+
}
|
|
2740
2778
|
function isFrameworkValue(value) {
|
|
2741
2779
|
return value === "react" || value === "vue" || value === "svelte" || value === "solid";
|
|
2742
2780
|
}
|
|
@@ -2753,6 +2791,7 @@ function isDatabaseProviderValue(value) {
|
|
|
2753
2791
|
// src/prompts/preferences.ts
|
|
2754
2792
|
var import_conf = __toESM(require("conf"), 1);
|
|
2755
2793
|
var DEFAULT_PREFERENCES = {
|
|
2794
|
+
platform: "web",
|
|
2756
2795
|
framework: "react",
|
|
2757
2796
|
tailwind: true,
|
|
2758
2797
|
sync: true,
|
|
@@ -2807,83 +2846,110 @@ async function resolveCreatePreferencesFlow(params) {
|
|
|
2807
2846
|
usedStoredPreferences = true;
|
|
2808
2847
|
}
|
|
2809
2848
|
}
|
|
2810
|
-
if (flags.
|
|
2811
|
-
if (!
|
|
2849
|
+
if (flags.platform !== void 0) {
|
|
2850
|
+
if (!isPlatformValue(flags.platform)) {
|
|
2812
2851
|
throw new Error(
|
|
2813
|
-
`Invalid --
|
|
2852
|
+
`Invalid --platform value "${flags.platform}". Expected one of: web, desktop-tauri.`
|
|
2814
2853
|
);
|
|
2815
2854
|
}
|
|
2816
|
-
effective.
|
|
2817
|
-
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2818
|
-
effective.framework = await prompts.select("UI framework:", [
|
|
2819
|
-
{ label: "React", value: "react" },
|
|
2820
|
-
{ label: "Vue (coming soon)", value: "vue", disabled: true },
|
|
2821
|
-
{ label: "Svelte (coming soon)", value: "svelte", disabled: true },
|
|
2822
|
-
{ label: "Solid (coming soon)", value: "solid", disabled: true }
|
|
2823
|
-
]);
|
|
2824
|
-
}
|
|
2825
|
-
if (flags.auth !== void 0) {
|
|
2826
|
-
if (!isAuthValue(flags.auth)) {
|
|
2827
|
-
throw new Error(
|
|
2828
|
-
`Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
|
|
2829
|
-
);
|
|
2830
|
-
}
|
|
2831
|
-
effective.auth = flags.auth;
|
|
2832
|
-
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2833
|
-
effective.auth = await prompts.select("Authentication:", [
|
|
2834
|
-
{ label: "None", value: "none" },
|
|
2835
|
-
{ label: "Email + Password (coming soon)", value: "email-password", disabled: true },
|
|
2836
|
-
{ label: "OAuth (coming soon)", value: "oauth", disabled: true }
|
|
2837
|
-
]);
|
|
2838
|
-
}
|
|
2839
|
-
if (flags.tailwind !== void 0) {
|
|
2840
|
-
effective.tailwind = flags.tailwind;
|
|
2841
|
-
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2842
|
-
effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
|
|
2843
|
-
}
|
|
2844
|
-
if (flags.sync !== void 0) {
|
|
2845
|
-
effective.sync = flags.sync;
|
|
2846
|
-
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2847
|
-
effective.sync = await prompts.confirm("Enable multi-device sync?", true);
|
|
2848
|
-
}
|
|
2849
|
-
if (flags.db !== void 0) {
|
|
2850
|
-
if (!isDatabaseValue(flags.db)) {
|
|
2851
|
-
throw new Error(`Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`);
|
|
2852
|
-
}
|
|
2853
|
-
effective.db = flags.db;
|
|
2854
|
-
} else if (!effective.sync) {
|
|
2855
|
-
effective.db = "none";
|
|
2855
|
+
effective.platform = flags.platform;
|
|
2856
2856
|
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2857
|
-
effective.
|
|
2858
|
-
{ label: "
|
|
2859
|
-
{ label: "
|
|
2857
|
+
effective.platform = await prompts.select("Platform:", [
|
|
2858
|
+
{ label: "Web (browser)", value: "web" },
|
|
2859
|
+
{ label: "Desktop (Tauri \u2014 native SQLite)", value: "desktop-tauri" }
|
|
2860
2860
|
]);
|
|
2861
2861
|
}
|
|
2862
|
-
|
|
2862
|
+
const isTauri = effective.platform === "desktop-tauri";
|
|
2863
|
+
if (isTauri) {
|
|
2864
|
+
effective.framework = "react";
|
|
2865
|
+
effective.tailwind = false;
|
|
2866
|
+
effective.sync = true;
|
|
2867
|
+
effective.db = "sqlite";
|
|
2863
2868
|
effective.dbProvider = "none";
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
+
effective.auth = "none";
|
|
2870
|
+
} else {
|
|
2871
|
+
if (flags.framework !== void 0) {
|
|
2872
|
+
if (!isFrameworkValue(flags.framework)) {
|
|
2873
|
+
throw new Error(
|
|
2874
|
+
`Invalid --framework value "${flags.framework}". Expected one of: react, vue, svelte, solid.`
|
|
2875
|
+
);
|
|
2876
|
+
}
|
|
2877
|
+
effective.framework = flags.framework;
|
|
2878
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2879
|
+
effective.framework = await prompts.select("UI framework:", [
|
|
2880
|
+
{ label: "React", value: "react" },
|
|
2881
|
+
{ label: "Vue (coming soon)", value: "vue", disabled: true },
|
|
2882
|
+
{ label: "Svelte (coming soon)", value: "svelte", disabled: true },
|
|
2883
|
+
{ label: "Solid (coming soon)", value: "solid", disabled: true }
|
|
2884
|
+
]);
|
|
2885
|
+
}
|
|
2886
|
+
if (flags.auth !== void 0) {
|
|
2887
|
+
if (!isAuthValue(flags.auth)) {
|
|
2888
|
+
throw new Error(
|
|
2889
|
+
`Invalid --auth value "${flags.auth}". Expected one of: none, email-password, oauth.`
|
|
2890
|
+
);
|
|
2891
|
+
}
|
|
2892
|
+
effective.auth = flags.auth;
|
|
2893
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2894
|
+
effective.auth = await prompts.select("Authentication:", [
|
|
2895
|
+
{ label: "None", value: "none" },
|
|
2896
|
+
{ label: "Email + Password (coming soon)", value: "email-password", disabled: true },
|
|
2897
|
+
{ label: "OAuth (coming soon)", value: "oauth", disabled: true }
|
|
2898
|
+
]);
|
|
2899
|
+
}
|
|
2900
|
+
if (flags.tailwind !== void 0) {
|
|
2901
|
+
effective.tailwind = flags.tailwind;
|
|
2902
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2903
|
+
effective.tailwind = await prompts.confirm("Use Tailwind CSS?", true);
|
|
2904
|
+
}
|
|
2905
|
+
if (flags.sync !== void 0) {
|
|
2906
|
+
effective.sync = flags.sync;
|
|
2907
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2908
|
+
effective.sync = await prompts.confirm("Enable multi-device sync?", true);
|
|
2909
|
+
}
|
|
2910
|
+
if (flags.db !== void 0) {
|
|
2911
|
+
if (!isDatabaseValue(flags.db)) {
|
|
2912
|
+
throw new Error(
|
|
2913
|
+
`Invalid --db value "${flags.db}". Expected one of: none, sqlite, postgres.`
|
|
2914
|
+
);
|
|
2915
|
+
}
|
|
2916
|
+
effective.db = flags.db;
|
|
2917
|
+
} else if (!effective.sync) {
|
|
2918
|
+
effective.db = "none";
|
|
2919
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2920
|
+
effective.db = await prompts.select("Server-side database:", [
|
|
2921
|
+
{ label: "SQLite (zero-config)", value: "sqlite" },
|
|
2922
|
+
{ label: "PostgreSQL (production-scale)", value: "postgres" }
|
|
2923
|
+
]);
|
|
2924
|
+
}
|
|
2925
|
+
if (effective.db !== "postgres") {
|
|
2926
|
+
effective.dbProvider = "none";
|
|
2927
|
+
} else if (flags.dbProvider !== void 0) {
|
|
2928
|
+
if (!isDatabaseProviderValue(flags.dbProvider)) {
|
|
2929
|
+
throw new Error(
|
|
2930
|
+
`Invalid --db-provider value "${flags.dbProvider}". Expected one of: none, local, supabase, neon, railway, vercel-postgres, custom.`
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
effective.dbProvider = flags.dbProvider;
|
|
2934
|
+
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2935
|
+
effective.dbProvider = await prompts.select("Database provider:", [
|
|
2936
|
+
{ label: "Local Postgres", value: "local" },
|
|
2937
|
+
{ label: "Supabase", value: "supabase" },
|
|
2938
|
+
{ label: "Neon", value: "neon" },
|
|
2939
|
+
{ label: "Railway", value: "railway" },
|
|
2940
|
+
{ label: "Vercel Postgres", value: "vercel-postgres" },
|
|
2941
|
+
{ label: "Custom connection string", value: "custom" }
|
|
2942
|
+
]);
|
|
2869
2943
|
}
|
|
2870
|
-
effective.dbProvider = flags.dbProvider;
|
|
2871
|
-
} else if (!flags.useDefaults && !usedStoredPreferences) {
|
|
2872
|
-
effective.dbProvider = await prompts.select("Database provider:", [
|
|
2873
|
-
{ label: "Local Postgres", value: "local" },
|
|
2874
|
-
{ label: "Supabase", value: "supabase" },
|
|
2875
|
-
{ label: "Neon", value: "neon" },
|
|
2876
|
-
{ label: "Railway", value: "railway" },
|
|
2877
|
-
{ label: "Vercel Postgres", value: "vercel-postgres" },
|
|
2878
|
-
{ label: "Custom connection string", value: "custom" }
|
|
2879
|
-
]);
|
|
2880
2944
|
}
|
|
2881
2945
|
const template = determineTemplateFromSelections({
|
|
2946
|
+
platform: effective.platform,
|
|
2882
2947
|
tailwind: effective.tailwind,
|
|
2883
2948
|
sync: effective.sync,
|
|
2884
2949
|
db: effective.db
|
|
2885
2950
|
});
|
|
2886
2951
|
return {
|
|
2952
|
+
platform: effective.platform,
|
|
2887
2953
|
framework: effective.framework,
|
|
2888
2954
|
auth: effective.auth,
|
|
2889
2955
|
db: effective.db,
|
|
@@ -2899,6 +2965,7 @@ function shouldSavePreferences(flags) {
|
|
|
2899
2965
|
}
|
|
2900
2966
|
function saveResolvedPreferences(store, resolution) {
|
|
2901
2967
|
store.saveCreatePreferences({
|
|
2968
|
+
platform: resolution.platform,
|
|
2902
2969
|
framework: resolution.framework,
|
|
2903
2970
|
tailwind: resolution.tailwind,
|
|
2904
2971
|
sync: resolution.sync,
|
|
@@ -2909,12 +2976,15 @@ function saveResolvedPreferences(store, resolution) {
|
|
|
2909
2976
|
});
|
|
2910
2977
|
}
|
|
2911
2978
|
function hasExplicitPreferenceFlags(flags) {
|
|
2912
|
-
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;
|
|
2979
|
+
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;
|
|
2913
2980
|
}
|
|
2914
2981
|
function promptSupportsRichOptions() {
|
|
2915
2982
|
return typeof process !== "undefined" && process.stdin.isTTY && process.stdout.isTTY;
|
|
2916
2983
|
}
|
|
2917
2984
|
function formatStoredPreferenceLabel(preferences) {
|
|
2985
|
+
if (preferences.platform === "desktop-tauri") {
|
|
2986
|
+
return `Use previous settings (tauri-desktop + ${preferences.packageManager})`;
|
|
2987
|
+
}
|
|
2918
2988
|
const syncLabel = preferences.sync ? `sync/${preferences.db}` : "local-only";
|
|
2919
2989
|
const styleLabel = preferences.tailwind ? "tailwind" : "css";
|
|
2920
2990
|
return `Use previous settings (${preferences.framework} + ${styleLabel} + ${syncLabel} + ${preferences.packageManager})`;
|
|
@@ -2992,7 +3062,7 @@ async function applySyncProviderPreset(options) {
|
|
|
2992
3062
|
await (0, import_promises9.writeFile)(readmePath, readmeTemplate, "utf-8");
|
|
2993
3063
|
}
|
|
2994
3064
|
function isSyncTemplate(template) {
|
|
2995
|
-
return template === "react-sync" || template === "react-tailwind-sync";
|
|
3065
|
+
return template === "react-sync" || template === "react-tailwind-sync" || template === "tauri-react";
|
|
2996
3066
|
}
|
|
2997
3067
|
function getProviderDisplayName(provider) {
|
|
2998
3068
|
switch (provider) {
|