@stacksolo/cli 0.1.3 → 0.1.4
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/index.js +138 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -877,25 +877,28 @@ async function scaffoldTemplates(cwd, projectType, uiFramework) {
|
|
|
877
877
|
}
|
|
878
878
|
async function scaffoldFunctionApi(cwd, name) {
|
|
879
879
|
const dir = path.join(cwd, name);
|
|
880
|
-
|
|
880
|
+
const srcDir = path.join(dir, "src");
|
|
881
|
+
await fs.mkdir(srcDir, { recursive: true });
|
|
881
882
|
await fs.writeFile(
|
|
882
883
|
path.join(dir, "package.json"),
|
|
883
884
|
JSON.stringify(
|
|
884
885
|
{
|
|
885
886
|
name,
|
|
886
887
|
version: "1.0.0",
|
|
887
|
-
main: "index.js",
|
|
888
|
+
main: "dist/index.js",
|
|
888
889
|
type: "module",
|
|
889
890
|
scripts: {
|
|
890
|
-
|
|
891
|
-
build: "
|
|
891
|
+
dev: "tsup src/index.ts --format esm --target node20 --watch --onSuccess 'functions-framework --source=dist --target=handler'",
|
|
892
|
+
build: "tsup src/index.ts --format esm --target node20",
|
|
893
|
+
start: "functions-framework --source=dist --target=handler"
|
|
892
894
|
},
|
|
893
895
|
dependencies: {
|
|
894
896
|
"@google-cloud/functions-framework": "^3.3.0"
|
|
895
897
|
},
|
|
896
898
|
devDependencies: {
|
|
897
899
|
typescript: "^5.0.0",
|
|
898
|
-
"@types/node": "^20.0.0"
|
|
900
|
+
"@types/node": "^20.0.0",
|
|
901
|
+
tsup: "^8.0.0"
|
|
899
902
|
}
|
|
900
903
|
},
|
|
901
904
|
null,
|
|
@@ -903,15 +906,21 @@ async function scaffoldFunctionApi(cwd, name) {
|
|
|
903
906
|
) + "\n"
|
|
904
907
|
);
|
|
905
908
|
await fs.writeFile(
|
|
906
|
-
path.join(
|
|
907
|
-
|
|
909
|
+
path.join(srcDir, "index.ts"),
|
|
910
|
+
`/**
|
|
911
|
+
* ${name} HTTP function
|
|
912
|
+
* Generated by: stacksolo init
|
|
913
|
+
*/
|
|
914
|
+
|
|
915
|
+
import type { Request, Response } from '@google-cloud/functions-framework';
|
|
908
916
|
|
|
909
|
-
|
|
917
|
+
export function handler(req: Request, res: Response): void {
|
|
910
918
|
const { method, path } = req;
|
|
911
919
|
|
|
912
920
|
// Health check
|
|
913
921
|
if (path === '/health') {
|
|
914
|
-
|
|
922
|
+
res.json({ status: 'ok' });
|
|
923
|
+
return;
|
|
915
924
|
}
|
|
916
925
|
|
|
917
926
|
// Your API routes here
|
|
@@ -920,7 +929,7 @@ functions.http('handler', (req, res) => {
|
|
|
920
929
|
method,
|
|
921
930
|
path,
|
|
922
931
|
});
|
|
923
|
-
}
|
|
932
|
+
}
|
|
924
933
|
`
|
|
925
934
|
);
|
|
926
935
|
await fs.writeFile(
|
|
@@ -930,19 +939,31 @@ functions.http('handler', (req, res) => {
|
|
|
930
939
|
compilerOptions: {
|
|
931
940
|
target: "ES2022",
|
|
932
941
|
module: "ESNext",
|
|
933
|
-
moduleResolution: "
|
|
942
|
+
moduleResolution: "bundler",
|
|
934
943
|
esModuleInterop: true,
|
|
935
944
|
strict: true,
|
|
945
|
+
skipLibCheck: true,
|
|
936
946
|
outDir: "dist",
|
|
947
|
+
rootDir: "src",
|
|
937
948
|
declaration: true
|
|
938
949
|
},
|
|
939
|
-
include: ["
|
|
950
|
+
include: ["src/**/*"],
|
|
951
|
+
exclude: ["node_modules", "dist"]
|
|
940
952
|
},
|
|
941
953
|
null,
|
|
942
954
|
2
|
|
943
955
|
) + "\n"
|
|
944
956
|
);
|
|
945
|
-
|
|
957
|
+
await fs.writeFile(
|
|
958
|
+
path.join(dir, ".gitignore"),
|
|
959
|
+
`node_modules/
|
|
960
|
+
dist/
|
|
961
|
+
*.log
|
|
962
|
+
.env
|
|
963
|
+
.env.local
|
|
964
|
+
`
|
|
965
|
+
);
|
|
966
|
+
return [`${name}/package.json`, `${name}/src/index.ts`, `${name}/tsconfig.json`, `${name}/.gitignore`];
|
|
946
967
|
}
|
|
947
968
|
async function scaffoldContainerApi(cwd, name) {
|
|
948
969
|
const dir = path.join(cwd, name);
|
|
@@ -1027,25 +1048,28 @@ CMD ["node", "index.js"]
|
|
|
1027
1048
|
}
|
|
1028
1049
|
async function scaffoldFunctionCron(cwd, name) {
|
|
1029
1050
|
const dir = path.join(cwd, name);
|
|
1030
|
-
|
|
1051
|
+
const srcDir = path.join(dir, "src");
|
|
1052
|
+
await fs.mkdir(srcDir, { recursive: true });
|
|
1031
1053
|
await fs.writeFile(
|
|
1032
1054
|
path.join(dir, "package.json"),
|
|
1033
1055
|
JSON.stringify(
|
|
1034
1056
|
{
|
|
1035
1057
|
name,
|
|
1036
1058
|
version: "1.0.0",
|
|
1037
|
-
main: "index.js",
|
|
1059
|
+
main: "dist/index.js",
|
|
1038
1060
|
type: "module",
|
|
1039
1061
|
scripts: {
|
|
1040
|
-
|
|
1041
|
-
build: "
|
|
1062
|
+
dev: "tsup src/index.ts --format esm --target node20 --watch --onSuccess 'functions-framework --source=dist --target=handler'",
|
|
1063
|
+
build: "tsup src/index.ts --format esm --target node20",
|
|
1064
|
+
start: "functions-framework --source=dist --target=handler"
|
|
1042
1065
|
},
|
|
1043
1066
|
dependencies: {
|
|
1044
1067
|
"@google-cloud/functions-framework": "^3.3.0"
|
|
1045
1068
|
},
|
|
1046
1069
|
devDependencies: {
|
|
1047
1070
|
typescript: "^5.0.0",
|
|
1048
|
-
"@types/node": "^20.0.0"
|
|
1071
|
+
"@types/node": "^20.0.0",
|
|
1072
|
+
tsup: "^8.0.0"
|
|
1049
1073
|
}
|
|
1050
1074
|
},
|
|
1051
1075
|
null,
|
|
@@ -1053,17 +1077,22 @@ async function scaffoldFunctionCron(cwd, name) {
|
|
|
1053
1077
|
) + "\n"
|
|
1054
1078
|
);
|
|
1055
1079
|
await fs.writeFile(
|
|
1056
|
-
path.join(
|
|
1057
|
-
|
|
1080
|
+
path.join(srcDir, "index.ts"),
|
|
1081
|
+
`/**
|
|
1082
|
+
* ${name} Cron function
|
|
1083
|
+
* Generated by: stacksolo init
|
|
1084
|
+
*/
|
|
1085
|
+
|
|
1086
|
+
import type { Request, Response } from '@google-cloud/functions-framework';
|
|
1058
1087
|
|
|
1059
|
-
|
|
1088
|
+
export function handler(req: Request, res: Response): void {
|
|
1060
1089
|
console.log('Cron triggered:', new Date().toISOString());
|
|
1061
1090
|
|
|
1062
1091
|
// Your scheduled job logic here
|
|
1063
1092
|
|
|
1064
1093
|
console.log('Job complete');
|
|
1065
1094
|
res.json({ status: 'ok' });
|
|
1066
|
-
}
|
|
1095
|
+
}
|
|
1067
1096
|
`
|
|
1068
1097
|
);
|
|
1069
1098
|
await fs.writeFile(
|
|
@@ -1073,19 +1102,31 @@ functions.http('handler', (req, res) => {
|
|
|
1073
1102
|
compilerOptions: {
|
|
1074
1103
|
target: "ES2022",
|
|
1075
1104
|
module: "ESNext",
|
|
1076
|
-
moduleResolution: "
|
|
1105
|
+
moduleResolution: "bundler",
|
|
1077
1106
|
esModuleInterop: true,
|
|
1078
1107
|
strict: true,
|
|
1108
|
+
skipLibCheck: true,
|
|
1079
1109
|
outDir: "dist",
|
|
1110
|
+
rootDir: "src",
|
|
1080
1111
|
declaration: true
|
|
1081
1112
|
},
|
|
1082
|
-
include: ["
|
|
1113
|
+
include: ["src/**/*"],
|
|
1114
|
+
exclude: ["node_modules", "dist"]
|
|
1083
1115
|
},
|
|
1084
1116
|
null,
|
|
1085
1117
|
2
|
|
1086
1118
|
) + "\n"
|
|
1087
1119
|
);
|
|
1088
|
-
|
|
1120
|
+
await fs.writeFile(
|
|
1121
|
+
path.join(dir, ".gitignore"),
|
|
1122
|
+
`node_modules/
|
|
1123
|
+
dist/
|
|
1124
|
+
*.log
|
|
1125
|
+
.env
|
|
1126
|
+
.env.local
|
|
1127
|
+
`
|
|
1128
|
+
);
|
|
1129
|
+
return [`${name}/package.json`, `${name}/src/index.ts`, `${name}/tsconfig.json`, `${name}/.gitignore`];
|
|
1089
1130
|
}
|
|
1090
1131
|
async function scaffoldStaticWeb(cwd, name) {
|
|
1091
1132
|
const dir = path.join(cwd, name);
|
|
@@ -15552,6 +15593,9 @@ function generateConfigMap(options) {
|
|
|
15552
15593
|
} else {
|
|
15553
15594
|
data.PUBSUB_EMULATOR_HOST = "pubsub-emulator:8085";
|
|
15554
15595
|
}
|
|
15596
|
+
if (options.kernelUrl) {
|
|
15597
|
+
data.KERNEL_URL = options.kernelUrl;
|
|
15598
|
+
}
|
|
15555
15599
|
if (options.additionalEnv) {
|
|
15556
15600
|
Object.assign(data, options.additionalEnv);
|
|
15557
15601
|
}
|
|
@@ -15660,9 +15704,31 @@ function generateFunctionManifests(options) {
|
|
|
15660
15704
|
const functionName = sanitizeName(options.function.name);
|
|
15661
15705
|
const runtimeConfig = getRuntimeConfig(options.function.runtime, options.function.entryPoint);
|
|
15662
15706
|
const isPython = isPythonRuntime(options.function.runtime);
|
|
15663
|
-
const installCmd = isPython ? "pip install -r requirements.txt 2>/dev/null || true && pip install functions-framework" : "npm install";
|
|
15664
15707
|
const runCmd = isPython ? runtimeConfig.command.join(" ") : "npm run dev 2>/dev/null || " + runtimeConfig.command.join(" ");
|
|
15665
|
-
const containerCommand =
|
|
15708
|
+
const containerCommand = isPython ? [
|
|
15709
|
+
"sh",
|
|
15710
|
+
"-c",
|
|
15711
|
+
[
|
|
15712
|
+
"cp -r /source/* /app/ 2>/dev/null || true",
|
|
15713
|
+
"cd /app",
|
|
15714
|
+
"pip install -r requirements.txt 2>/dev/null || true",
|
|
15715
|
+
"pip install functions-framework",
|
|
15716
|
+
runCmd
|
|
15717
|
+
].join(" && ")
|
|
15718
|
+
] : [
|
|
15719
|
+
"sh",
|
|
15720
|
+
"-c",
|
|
15721
|
+
[
|
|
15722
|
+
// Copy source files to /app, excluding node_modules (macOS binaries don't work in Linux)
|
|
15723
|
+
"cd /source",
|
|
15724
|
+
"find . -maxdepth 1 ! -name node_modules ! -name . -exec cp -r {} /app/ \\;",
|
|
15725
|
+
"cd /app",
|
|
15726
|
+
// Always install fresh for Linux platform
|
|
15727
|
+
"npm install",
|
|
15728
|
+
// Run the dev server
|
|
15729
|
+
runCmd
|
|
15730
|
+
].join(" && ")
|
|
15731
|
+
];
|
|
15666
15732
|
const labels = {
|
|
15667
15733
|
"app.kubernetes.io/name": functionName,
|
|
15668
15734
|
"app.kubernetes.io/component": "function",
|
|
@@ -15711,16 +15777,21 @@ function generateFunctionManifests(options) {
|
|
|
15711
15777
|
volumeMounts: [
|
|
15712
15778
|
{
|
|
15713
15779
|
name: "source",
|
|
15780
|
+
mountPath: "/source",
|
|
15781
|
+
readOnly: true
|
|
15782
|
+
},
|
|
15783
|
+
{
|
|
15784
|
+
name: "workdir",
|
|
15714
15785
|
mountPath: "/app"
|
|
15715
15786
|
}
|
|
15716
15787
|
],
|
|
15717
15788
|
workingDir: "/app",
|
|
15718
15789
|
resources: {
|
|
15719
15790
|
limits: {
|
|
15720
|
-
memory: options.function.memory || "
|
|
15791
|
+
memory: options.function.memory || "512Mi"
|
|
15721
15792
|
},
|
|
15722
15793
|
requests: {
|
|
15723
|
-
memory: "
|
|
15794
|
+
memory: "256Mi"
|
|
15724
15795
|
}
|
|
15725
15796
|
}
|
|
15726
15797
|
}
|
|
@@ -15732,6 +15803,10 @@ function generateFunctionManifests(options) {
|
|
|
15732
15803
|
path: options.sourceDir,
|
|
15733
15804
|
type: "DirectoryOrCreate"
|
|
15734
15805
|
}
|
|
15806
|
+
},
|
|
15807
|
+
{
|
|
15808
|
+
name: "workdir",
|
|
15809
|
+
emptyDir: {}
|
|
15735
15810
|
}
|
|
15736
15811
|
]
|
|
15737
15812
|
}
|
|
@@ -15817,7 +15892,21 @@ function generateUIManifests(options) {
|
|
|
15817
15892
|
{
|
|
15818
15893
|
name: uiName,
|
|
15819
15894
|
image: "node:20-slim",
|
|
15820
|
-
|
|
15895
|
+
// Copy source (excluding node_modules) to working directory, then install fresh Linux deps
|
|
15896
|
+
command: [
|
|
15897
|
+
"sh",
|
|
15898
|
+
"-c",
|
|
15899
|
+
[
|
|
15900
|
+
// Copy source files to /app, excluding node_modules (macOS binaries don't work in Linux)
|
|
15901
|
+
"cd /source",
|
|
15902
|
+
"find . -maxdepth 1 ! -name node_modules ! -name . -exec cp -r {} /app/ \\;",
|
|
15903
|
+
"cd /app",
|
|
15904
|
+
// Always install fresh for Linux platform
|
|
15905
|
+
"npm install",
|
|
15906
|
+
// Run the dev server
|
|
15907
|
+
frameworkConfig.command.join(" ")
|
|
15908
|
+
].join(" && ")
|
|
15909
|
+
],
|
|
15821
15910
|
ports: [
|
|
15822
15911
|
{
|
|
15823
15912
|
containerPort: options.port,
|
|
@@ -15832,16 +15921,21 @@ function generateUIManifests(options) {
|
|
|
15832
15921
|
volumeMounts: [
|
|
15833
15922
|
{
|
|
15834
15923
|
name: "source",
|
|
15924
|
+
mountPath: "/source",
|
|
15925
|
+
readOnly: true
|
|
15926
|
+
},
|
|
15927
|
+
{
|
|
15928
|
+
name: "workdir",
|
|
15835
15929
|
mountPath: "/app"
|
|
15836
15930
|
}
|
|
15837
15931
|
],
|
|
15838
15932
|
workingDir: "/app",
|
|
15839
15933
|
resources: {
|
|
15840
15934
|
limits: {
|
|
15841
|
-
memory: "
|
|
15935
|
+
memory: "1Gi"
|
|
15842
15936
|
},
|
|
15843
15937
|
requests: {
|
|
15844
|
-
memory: "
|
|
15938
|
+
memory: "512Mi"
|
|
15845
15939
|
}
|
|
15846
15940
|
}
|
|
15847
15941
|
}
|
|
@@ -15853,6 +15947,10 @@ function generateUIManifests(options) {
|
|
|
15853
15947
|
path: options.sourceDir,
|
|
15854
15948
|
type: "DirectoryOrCreate"
|
|
15855
15949
|
}
|
|
15950
|
+
},
|
|
15951
|
+
{
|
|
15952
|
+
name: "workdir",
|
|
15953
|
+
emptyDir: {}
|
|
15856
15954
|
}
|
|
15857
15955
|
]
|
|
15858
15956
|
}
|
|
@@ -16569,7 +16667,7 @@ function generateNginxConfig(routes, servicePortMap) {
|
|
|
16569
16667
|
const basePath = route.path.replace(/\/?\*$/, "");
|
|
16570
16668
|
return `
|
|
16571
16669
|
location ${basePath}/ {
|
|
16572
|
-
proxy_pass ${upstream}
|
|
16670
|
+
proxy_pass ${upstream};
|
|
16573
16671
|
proxy_http_version 1.1;
|
|
16574
16672
|
proxy_set_header Upgrade $http_upgrade;
|
|
16575
16673
|
proxy_set_header Connection 'upgrade';
|
|
@@ -16687,8 +16785,14 @@ function generateK8sManifests(options) {
|
|
|
16687
16785
|
const projectName = config.project.name;
|
|
16688
16786
|
const portAllocator = createPortAllocator();
|
|
16689
16787
|
const servicePortMap = {};
|
|
16788
|
+
let kernelUrl;
|
|
16789
|
+
if (config.project.kernel) {
|
|
16790
|
+
kernelUrl = `http://${config.project.kernel.name}:8090`;
|
|
16791
|
+
} else if (config.project.gcpKernel) {
|
|
16792
|
+
kernelUrl = `http://${config.project.gcpKernel.name}:8080`;
|
|
16793
|
+
}
|
|
16690
16794
|
manifests.push(generateNamespace(projectName));
|
|
16691
|
-
manifests.push(generateConfigMap({ projectName }));
|
|
16795
|
+
manifests.push(generateConfigMap({ projectName, kernelUrl }));
|
|
16692
16796
|
if (includeEmulators) {
|
|
16693
16797
|
manifests.push(generateFirebaseEmulator({ projectName }));
|
|
16694
16798
|
manifests.push(generatePubSubEmulator({ projectName }));
|