slskit-cli 1.0.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/CHANGELOG.md +61 -0
- package/COMMAND.md +636 -0
- package/LICENSE +21 -0
- package/NOTICE.md +22 -0
- package/README.md +168 -0
- package/bin/slskit.js +3 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +25 -0
- package/dist/commands/base-command.d.ts +5 -0
- package/dist/commands/base-command.js +29 -0
- package/dist/commands/configure/action.d.ts +2 -0
- package/dist/commands/configure/action.js +120 -0
- package/dist/commands/configure/aws-cli.d.ts +16 -0
- package/dist/commands/configure/aws-cli.js +135 -0
- package/dist/commands/configure/index.d.ts +2 -0
- package/dist/commands/configure/index.js +20 -0
- package/dist/commands/configure/prompts.d.ts +8 -0
- package/dist/commands/configure/prompts.js +117 -0
- package/dist/commands/configure/types.d.ts +24 -0
- package/dist/commands/configure/types.js +6 -0
- package/dist/commands/deploy/action.d.ts +2 -0
- package/dist/commands/deploy/action.js +115 -0
- package/dist/commands/deploy/index.d.ts +2 -0
- package/dist/commands/deploy/index.js +23 -0
- package/dist/commands/deploy/sam-deploy.d.ts +10 -0
- package/dist/commands/deploy/sam-deploy.js +127 -0
- package/dist/commands/deploy/scope.d.ts +9 -0
- package/dist/commands/deploy/scope.js +34 -0
- package/dist/commands/deploy/types.d.ts +20 -0
- package/dist/commands/deploy/types.js +2 -0
- package/dist/commands/env/action.d.ts +11 -0
- package/dist/commands/env/action.js +274 -0
- package/dist/commands/env/dotenv.d.ts +6 -0
- package/dist/commands/env/dotenv.js +99 -0
- package/dist/commands/env/index.d.ts +2 -0
- package/dist/commands/env/index.js +76 -0
- package/dist/commands/env/keys.d.ts +8 -0
- package/dist/commands/env/keys.js +41 -0
- package/dist/commands/env/parameters.d.ts +7 -0
- package/dist/commands/env/parameters.js +63 -0
- package/dist/commands/env/templates.d.ts +3 -0
- package/dist/commands/env/templates.js +65 -0
- package/dist/commands/env/types.d.ts +21 -0
- package/dist/commands/env/types.js +2 -0
- package/dist/commands/function/action.d.ts +2 -0
- package/dist/commands/function/action.js +71 -0
- package/dist/commands/function/generator.d.ts +8 -0
- package/dist/commands/function/generator.js +58 -0
- package/dist/commands/function/index.d.ts +2 -0
- package/dist/commands/function/index.js +26 -0
- package/dist/commands/function/manifest.d.ts +5 -0
- package/dist/commands/function/manifest.js +57 -0
- package/dist/commands/function/prompts.d.ts +18 -0
- package/dist/commands/function/prompts.js +196 -0
- package/dist/commands/function/tooling.d.ts +2 -0
- package/dist/commands/function/tooling.js +43 -0
- package/dist/commands/function/types.d.ts +52 -0
- package/dist/commands/function/types.js +2 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +19 -0
- package/dist/commands/init/action.d.ts +2 -0
- package/dist/commands/init/action.js +36 -0
- package/dist/commands/init/content.d.ts +2 -0
- package/dist/commands/init/content.js +97 -0
- package/dist/commands/init/index.d.ts +2 -0
- package/dist/commands/init/index.js +30 -0
- package/dist/commands/init/manifest.d.ts +6 -0
- package/dist/commands/init/manifest.js +147 -0
- package/dist/commands/init/prompts.d.ts +6 -0
- package/dist/commands/init/prompts.js +155 -0
- package/dist/commands/init/scaffold.d.ts +7 -0
- package/dist/commands/init/scaffold.js +85 -0
- package/dist/commands/init/templates/helpers.d.ts +9 -0
- package/dist/commands/init/templates/helpers.js +42 -0
- package/dist/commands/init/templates/node.d.ts +4 -0
- package/dist/commands/init/templates/node.js +99 -0
- package/dist/commands/init/templates/project.d.ts +8 -0
- package/dist/commands/init/templates/project.js +239 -0
- package/dist/commands/init/templates/python.d.ts +4 -0
- package/dist/commands/init/templates/python.js +65 -0
- package/dist/commands/init/templates/sam.d.ts +4 -0
- package/dist/commands/init/templates/sam.js +369 -0
- package/dist/commands/init/templates/shared-code.d.ts +6 -0
- package/dist/commands/init/templates/shared-code.js +159 -0
- package/dist/commands/init/types.d.ts +47 -0
- package/dist/commands/init/types.js +75 -0
- package/dist/commands/rm/action.d.ts +2 -0
- package/dist/commands/rm/action.js +89 -0
- package/dist/commands/rm/index.d.ts +2 -0
- package/dist/commands/rm/index.js +25 -0
- package/dist/commands/rm/plan.d.ts +19 -0
- package/dist/commands/rm/plan.js +78 -0
- package/dist/commands/rm/prompts.d.ts +4 -0
- package/dist/commands/rm/prompts.js +107 -0
- package/dist/commands/rm/types.d.ts +7 -0
- package/dist/commands/rm/types.js +2 -0
- package/dist/commands/run/action.d.ts +2 -0
- package/dist/commands/run/action.js +171 -0
- package/dist/commands/run/index.d.ts +2 -0
- package/dist/commands/run/index.js +21 -0
- package/dist/commands/run/local-template.d.ts +7 -0
- package/dist/commands/run/local-template.js +51 -0
- package/dist/commands/run/manifest.d.ts +2 -0
- package/dist/commands/run/manifest.js +20 -0
- package/dist/commands/run/resources.d.ts +20 -0
- package/dist/commands/run/resources.js +93 -0
- package/dist/commands/run/sam-cli.d.ts +10 -0
- package/dist/commands/run/sam-cli.js +183 -0
- package/dist/commands/run/types.d.ts +18 -0
- package/dist/commands/run/types.js +2 -0
- package/dist/commands/run/watch.d.ts +11 -0
- package/dist/commands/run/watch.js +131 -0
- package/dist/core/context.d.ts +15 -0
- package/dist/core/context.js +41 -0
- package/dist/core/credentials.d.ts +10 -0
- package/dist/core/credentials.js +22 -0
- package/dist/core/environments.d.ts +46 -0
- package/dist/core/environments.js +161 -0
- package/dist/core/errors.d.ts +4 -0
- package/dist/core/errors.js +11 -0
- package/dist/core/flags-docs.d.ts +2 -0
- package/dist/core/flags-docs.js +63 -0
- package/dist/core/is-ci.d.ts +4 -0
- package/dist/core/is-ci.js +16 -0
- package/dist/core/logger.d.ts +4 -0
- package/dist/core/logger.js +19 -0
- package/dist/core/run.d.ts +1 -0
- package/dist/core/run.js +27 -0
- package/dist/core/scope.d.ts +33 -0
- package/dist/core/scope.js +108 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +9 -0
- package/dist/program.d.ts +2 -0
- package/dist/program.js +26 -0
- package/package.json +110 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.nodeService = nodeService;
|
|
4
|
+
exports.standaloneNodeService = standaloneNodeService;
|
|
5
|
+
exports.nodeHandler = nodeHandler;
|
|
6
|
+
const helpers_js_1 = require("./helpers.js");
|
|
7
|
+
function nodeSharedImports(answers) {
|
|
8
|
+
const loggerFrom = answers.layer
|
|
9
|
+
? (0, helpers_js_1.nodeLayerImport)("logger")
|
|
10
|
+
: "../../shared/logger";
|
|
11
|
+
// db is never in the layer, so it is always imported by relative path and bundled.
|
|
12
|
+
const dbFrom = "../../shared/db";
|
|
13
|
+
const lines = [`import { logger } from "${loggerFrom}";`];
|
|
14
|
+
if (answers.database === "prisma") {
|
|
15
|
+
lines.push(`import { prisma } from "${dbFrom}";`);
|
|
16
|
+
}
|
|
17
|
+
else if (answers.database === "mongoose") {
|
|
18
|
+
lines.push(`import { connectDb } from "${dbFrom}";`);
|
|
19
|
+
}
|
|
20
|
+
else if (answers.database === "dynamodb") {
|
|
21
|
+
lines.push(`import { docClient } from "${dbFrom}";`);
|
|
22
|
+
}
|
|
23
|
+
return `${lines.join("\n")}\n`;
|
|
24
|
+
}
|
|
25
|
+
function nodeService(answers, fn, typed) {
|
|
26
|
+
const dbSetup = answers.database === "mongoose"
|
|
27
|
+
? " await connectDb();\n"
|
|
28
|
+
: answers.database === "prisma"
|
|
29
|
+
? " void prisma;\n"
|
|
30
|
+
: answers.database === "dynamodb"
|
|
31
|
+
? " void docClient;\n"
|
|
32
|
+
: "";
|
|
33
|
+
const eventType = typed
|
|
34
|
+
? `import type { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";\n`
|
|
35
|
+
: "";
|
|
36
|
+
const signature = typed
|
|
37
|
+
? `export async function ${fn.name}(
|
|
38
|
+
event: APIGatewayProxyEvent
|
|
39
|
+
): Promise<APIGatewayProxyResult> {`
|
|
40
|
+
: `export async function ${fn.name}(event) {`;
|
|
41
|
+
return `${eventType}${nodeSharedImports(answers)}
|
|
42
|
+
${signature}
|
|
43
|
+
${dbSetup} logger.info("${fn.name} invoked");
|
|
44
|
+
const payload = event.body ? JSON.parse(event.body) : {};
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
statusCode: 200,
|
|
48
|
+
headers: { "Content-Type": "application/json" },
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
message: "${fn.name}",
|
|
51
|
+
input: payload,
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
// Used when a function's runtime family differs from the project's: it can't attach
|
|
58
|
+
// the project's layer or import its db client (built for the other family), so it
|
|
59
|
+
// ships as a plain, self-contained handler instead.
|
|
60
|
+
function standaloneNodeService(fn, typed) {
|
|
61
|
+
const eventType = typed
|
|
62
|
+
? `import type { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";\n\n`
|
|
63
|
+
: "";
|
|
64
|
+
const signature = typed
|
|
65
|
+
? `export async function ${fn.name}(
|
|
66
|
+
event: APIGatewayProxyEvent
|
|
67
|
+
): Promise<APIGatewayProxyResult> {`
|
|
68
|
+
: `export async function ${fn.name}(event) {`;
|
|
69
|
+
return `${eventType}${signature}
|
|
70
|
+
console.log(JSON.stringify({ level: "info", message: "${fn.name} invoked" }));
|
|
71
|
+
const payload = event.body ? JSON.parse(event.body) : {};
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
statusCode: 200,
|
|
75
|
+
headers: { "Content-Type": "application/json" },
|
|
76
|
+
body: JSON.stringify({
|
|
77
|
+
message: "${fn.name}",
|
|
78
|
+
input: payload,
|
|
79
|
+
}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
`;
|
|
83
|
+
}
|
|
84
|
+
function nodeHandler(answers, appName, fn, typed) {
|
|
85
|
+
const eventType = typed
|
|
86
|
+
? `import type { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";\n`
|
|
87
|
+
: "";
|
|
88
|
+
const signature = typed
|
|
89
|
+
? `export async function handler(
|
|
90
|
+
event: APIGatewayProxyEvent
|
|
91
|
+
): Promise<APIGatewayProxyResult> {`
|
|
92
|
+
: `export async function handler(event) {`;
|
|
93
|
+
return `${eventType}import { ${fn.name} } from "../../../services/${appName}/${fn.name}";
|
|
94
|
+
|
|
95
|
+
${signature}
|
|
96
|
+
return ${fn.name}(event);
|
|
97
|
+
}
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InitAnswers } from "../types.js";
|
|
2
|
+
export declare function gitignore(runtime: InitAnswers["runtime"]): string;
|
|
3
|
+
export declare function readme(answers: InitAnswers): string;
|
|
4
|
+
export declare function packageJson(answers: InitAnswers): string;
|
|
5
|
+
export declare function tsconfig(answers: InitAnswers): string;
|
|
6
|
+
export declare function databaseSeedVariables(database: InitAnswers["database"]): string | undefined;
|
|
7
|
+
export declare function environmentDotenv(environment: string, database: InitAnswers["database"]): string;
|
|
8
|
+
export declare function requirementsTxt(answers: InitAnswers): string;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitignore = gitignore;
|
|
4
|
+
exports.readme = readme;
|
|
5
|
+
exports.packageJson = packageJson;
|
|
6
|
+
exports.tsconfig = tsconfig;
|
|
7
|
+
exports.databaseSeedVariables = databaseSeedVariables;
|
|
8
|
+
exports.environmentDotenv = environmentDotenv;
|
|
9
|
+
exports.requirementsTxt = requirementsTxt;
|
|
10
|
+
const environments_js_1 = require("../../../core/environments.js");
|
|
11
|
+
const types_js_1 = require("../types.js");
|
|
12
|
+
const helpers_js_1 = require("./helpers.js");
|
|
13
|
+
function gitignore(runtime) {
|
|
14
|
+
const lines = [
|
|
15
|
+
"node_modules/",
|
|
16
|
+
"dist/",
|
|
17
|
+
".aws-sam/",
|
|
18
|
+
".slskit-local.yaml",
|
|
19
|
+
".env",
|
|
20
|
+
".env.*",
|
|
21
|
+
".DS_Store",
|
|
22
|
+
"*.log",
|
|
23
|
+
];
|
|
24
|
+
if (runtime === "python") {
|
|
25
|
+
lines.push(".venv/", "__pycache__/", "*.pyc");
|
|
26
|
+
}
|
|
27
|
+
return `${lines.join("\n")}\n`;
|
|
28
|
+
}
|
|
29
|
+
function prismaSteps(answers) {
|
|
30
|
+
if (answers.database !== "prisma" || answers.runtime === "python") {
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
return `
|
|
34
|
+
## Prisma
|
|
35
|
+
|
|
36
|
+
Point \`DATABASE_URL\` in \`.env.${environments_js_1.DEFAULT_ENVIRONMENT}\` at your database, then:
|
|
37
|
+
|
|
38
|
+
\`\`\`bash
|
|
39
|
+
npm run prisma:migrate # create and apply a migration (development)
|
|
40
|
+
npm run prisma:generate # regenerate the client after editing schema.prisma
|
|
41
|
+
npm run prisma:studio # browse the data
|
|
42
|
+
\`\`\`
|
|
43
|
+
|
|
44
|
+
Deployments apply already-created migrations instead:
|
|
45
|
+
|
|
46
|
+
\`\`\`bash
|
|
47
|
+
npm run prisma:deploy
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
Those scripts read \`.env.${environments_js_1.DEFAULT_ENVIRONMENT}\`. Run them against another
|
|
51
|
+
environment by naming its file:
|
|
52
|
+
|
|
53
|
+
\`\`\`bash
|
|
54
|
+
npx dotenv -e .env.production -- npx prisma migrate deploy
|
|
55
|
+
\`\`\`
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
function readme(answers) {
|
|
59
|
+
const layerRuntime = answers.layer && answers.runtime === "typescript" ? "javascript" : answers.runtime;
|
|
60
|
+
const sharedFiles = [
|
|
61
|
+
`│ │ └── logger.${(0, helpers_js_1.loggerExt)(layerRuntime)}`,
|
|
62
|
+
...(answers.database !== "none" ? ["│ │ └── db." + (0, types_js_1.sourceExt)(answers.runtime)] : []),
|
|
63
|
+
];
|
|
64
|
+
const nextSteps = ["```bash", "sam build", "sam deploy --guided", "```"];
|
|
65
|
+
return `# ${answers.name}
|
|
66
|
+
|
|
67
|
+
Generated by **slskit init**.
|
|
68
|
+
|
|
69
|
+
- Runtime: ${answers.runtime}
|
|
70
|
+
- Framework: AWS SAM
|
|
71
|
+
- Database: ${answers.database}
|
|
72
|
+
- API Gateway: ${answers.apiGateway
|
|
73
|
+
? "yes (each service owns an HTTP API in its own template)"
|
|
74
|
+
: "no"}
|
|
75
|
+
- Common layer: ${answers.layer ? "yes (src/shared attached to every function)" : "no"}
|
|
76
|
+
- Function memory: ${answers.memorySize} MB
|
|
77
|
+
|
|
78
|
+
See \`slskit.json\` for the full project graph.
|
|
79
|
+
|
|
80
|
+
## Layout
|
|
81
|
+
|
|
82
|
+
Every service owns a \`${types_js_1.INFRA_FILE}\` next to its handlers, so services can be
|
|
83
|
+
deployed one at a time. The root \`template.yaml\` pulls them all together.
|
|
84
|
+
|
|
85
|
+
\`\`\`text
|
|
86
|
+
${answers.name}/
|
|
87
|
+
├── ${types_js_1.SRC_DIR}/
|
|
88
|
+
│ ├── functions/
|
|
89
|
+
│ │ ├── auth/
|
|
90
|
+
│ │ │ ├── ${types_js_1.INFRA_FILE}
|
|
91
|
+
│ │ │ ├── login/handler.${(0, types_js_1.sourceExt)(answers.runtime)}
|
|
92
|
+
│ │ │ └── register/handler.${(0, types_js_1.sourceExt)(answers.runtime)}
|
|
93
|
+
│ │ └── product/
|
|
94
|
+
│ │ ├── ${types_js_1.INFRA_FILE}
|
|
95
|
+
│ │ ├── getProducts/handler.${(0, types_js_1.sourceExt)(answers.runtime)}
|
|
96
|
+
│ │ └── createProduct/handler.${(0, types_js_1.sourceExt)(answers.runtime)}
|
|
97
|
+
│ ├── services/
|
|
98
|
+
│ │ ├── auth/login.${(0, types_js_1.sourceExt)(answers.runtime)}
|
|
99
|
+
│ │ └── product/getProducts.${(0, types_js_1.sourceExt)(answers.runtime)}
|
|
100
|
+
│ └── shared/
|
|
101
|
+
${sharedFiles.join("\n")}
|
|
102
|
+
├── template.yaml (root stack)
|
|
103
|
+
├── .env.${environments_js_1.DEFAULT_ENVIRONMENT} (the "${environments_js_1.DEFAULT_ENVIRONMENT}" environment's values, gitignored)
|
|
104
|
+
├── package.json
|
|
105
|
+
├── slskit.json
|
|
106
|
+
└── README.md
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
Each function delegates to a matching service module: \`${types_js_1.SRC_DIR}/functions/auth/login\`
|
|
110
|
+
calls \`${types_js_1.SRC_DIR}/services/auth/login\`.
|
|
111
|
+
|
|
112
|
+
## Environments
|
|
113
|
+
|
|
114
|
+
The project starts with one environment, \`${environments_js_1.DEFAULT_ENVIRONMENT}\`, and its values live in
|
|
115
|
+
\`.env.${environments_js_1.DEFAULT_ENVIRONMENT}\`. Add more as you need them -- each one gets its own file,
|
|
116
|
+
its own CloudFormation stack, and its own \`${environments_js_1.APP_ENVIRONMENT_KEY}\`.
|
|
117
|
+
|
|
118
|
+
\`\`\`bash
|
|
119
|
+
slskit env list
|
|
120
|
+
slskit env add production --profile prod-admin --region eu-west-2
|
|
121
|
+
slskit env set LOG_LEVEL=debug
|
|
122
|
+
\`\`\`
|
|
123
|
+
|
|
124
|
+
## Next steps
|
|
125
|
+
|
|
126
|
+
${nextSteps.join("\n")}
|
|
127
|
+
${prismaSteps(answers)}`;
|
|
128
|
+
}
|
|
129
|
+
function packageJson(answers) {
|
|
130
|
+
const isNode = answers.runtime !== "python";
|
|
131
|
+
const dependencies = {};
|
|
132
|
+
const devDependencies = {};
|
|
133
|
+
if (isNode) {
|
|
134
|
+
if (answers.runtime === "typescript") {
|
|
135
|
+
devDependencies.typescript = "^5.7.2";
|
|
136
|
+
devDependencies["@types/node"] = "^22.10.2";
|
|
137
|
+
devDependencies["@types/aws-lambda"] = "^8.10.145";
|
|
138
|
+
}
|
|
139
|
+
if (answers.database === "prisma") {
|
|
140
|
+
dependencies["@prisma/client"] = "^6.5.0";
|
|
141
|
+
devDependencies.prisma = "^6.5.0";
|
|
142
|
+
// The Prisma CLI only reads ".env"; this points it at the environment file instead.
|
|
143
|
+
devDependencies["dotenv-cli"] = "^8.0.0";
|
|
144
|
+
}
|
|
145
|
+
if (answers.database === "mongoose") {
|
|
146
|
+
dependencies.mongoose = "^8.12.1";
|
|
147
|
+
}
|
|
148
|
+
if (answers.database === "dynamodb") {
|
|
149
|
+
dependencies["@aws-sdk/client-dynamodb"] = "^3.750.0";
|
|
150
|
+
dependencies["@aws-sdk/lib-dynamodb"] = "^3.750.0";
|
|
151
|
+
}
|
|
152
|
+
// sam build stages the project with `npm install --omit=dev`, so esbuild must be a regular dependency.
|
|
153
|
+
dependencies.esbuild = "^0.25.0";
|
|
154
|
+
}
|
|
155
|
+
const scripts = {
|
|
156
|
+
build: "sam build",
|
|
157
|
+
deploy: "sam deploy --guided",
|
|
158
|
+
};
|
|
159
|
+
if (answers.runtime === "typescript") {
|
|
160
|
+
scripts.typecheck = "tsc --noEmit";
|
|
161
|
+
}
|
|
162
|
+
if (answers.database === "prisma" && isNode) {
|
|
163
|
+
const withEnv = `dotenv -e .env.${environments_js_1.DEFAULT_ENVIRONMENT} --`;
|
|
164
|
+
scripts["prisma:generate"] = `${withEnv} prisma generate`;
|
|
165
|
+
scripts["prisma:migrate"] = `${withEnv} prisma migrate dev`;
|
|
166
|
+
// migrate dev is interactive and dev-only; deployments need migrate deploy.
|
|
167
|
+
scripts["prisma:deploy"] = `${withEnv} prisma migrate deploy`;
|
|
168
|
+
scripts["prisma:studio"] = `${withEnv} prisma studio`;
|
|
169
|
+
}
|
|
170
|
+
return `${JSON.stringify({
|
|
171
|
+
name: answers.name,
|
|
172
|
+
version: "0.1.0",
|
|
173
|
+
private: true,
|
|
174
|
+
description: `${answers.name} AWS SAM app generated by slskit`,
|
|
175
|
+
scripts,
|
|
176
|
+
dependencies,
|
|
177
|
+
devDependencies,
|
|
178
|
+
}, null, 2)}\n`;
|
|
179
|
+
}
|
|
180
|
+
function tsconfig(answers) {
|
|
181
|
+
const compilerOptions = {
|
|
182
|
+
target: "ES2020",
|
|
183
|
+
module: "node16",
|
|
184
|
+
moduleResolution: "node16",
|
|
185
|
+
lib: ["ES2020"],
|
|
186
|
+
strict: true,
|
|
187
|
+
esModuleInterop: true,
|
|
188
|
+
forceConsistentCasingInFileNames: true,
|
|
189
|
+
skipLibCheck: true,
|
|
190
|
+
types: ["node"],
|
|
191
|
+
outDir: "dist",
|
|
192
|
+
rootDir: types_js_1.SRC_DIR,
|
|
193
|
+
};
|
|
194
|
+
if (answers.layer && answers.runtime !== "python") {
|
|
195
|
+
compilerOptions.paths = {
|
|
196
|
+
"/opt/nodejs/*": [`./${types_js_1.SRC_DIR}/shared/nodejs/*`],
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
// "sam build" copies the whole project root -- tsconfig.json included -- into
|
|
200
|
+
// .aws-sam/build/<Function>/, and wipes it on the next build. Without an explicit
|
|
201
|
+
// exclude an editor loads those copies as extra TypeScript programs and then
|
|
202
|
+
// reports their vanished files as "not found" against this include pattern.
|
|
203
|
+
return `${JSON.stringify({
|
|
204
|
+
compilerOptions,
|
|
205
|
+
include: [`${types_js_1.SRC_DIR}/**/*.ts`],
|
|
206
|
+
exclude: ["node_modules", "dist", ".aws-sam", ".venv"],
|
|
207
|
+
}, null, 2)}\n`;
|
|
208
|
+
}
|
|
209
|
+
// The connection string a database needs, seeded into the first environment file as
|
|
210
|
+
// an ordinary stage variable. DynamoDB is absent on purpose: the templates create
|
|
211
|
+
// those tables and hardcode their names, so they are not stage configuration.
|
|
212
|
+
function databaseSeedVariables(database) {
|
|
213
|
+
if (database === "prisma") {
|
|
214
|
+
return `DATABASE_URL="postgresql://user:password@localhost:5432/app"\n`;
|
|
215
|
+
}
|
|
216
|
+
if (database === "mongoose") {
|
|
217
|
+
return `MONGODB_URI="mongodb://127.0.0.1:27017/app"\n`;
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
// Matches the format "slskit env set" writes, so the two never fight over the file.
|
|
222
|
+
function environmentDotenv(environment, database) {
|
|
223
|
+
const lines = [`${environments_js_1.APP_ENVIRONMENT_KEY}=${environment}`];
|
|
224
|
+
const dbExample = databaseSeedVariables(database);
|
|
225
|
+
if (dbExample) {
|
|
226
|
+
lines.push(...dbExample.trimEnd().split("\n"));
|
|
227
|
+
}
|
|
228
|
+
return `# Values for the "${environment}" environment. Never commit this file.\n${lines.join("\n")}\n`;
|
|
229
|
+
}
|
|
230
|
+
function requirementsTxt(answers) {
|
|
231
|
+
const lines = ["boto3>=1.35.0"];
|
|
232
|
+
if (answers.database === "prisma") {
|
|
233
|
+
lines.push("prisma>=0.15.0");
|
|
234
|
+
}
|
|
235
|
+
if (answers.database === "mongoose") {
|
|
236
|
+
lines.push("pymongo>=4.10.0");
|
|
237
|
+
}
|
|
238
|
+
return `${lines.join("\n")}\n`;
|
|
239
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { InitAnswers, ServiceFunction } from "../types.js";
|
|
2
|
+
export declare function pythonService(answers: InitAnswers, fn: ServiceFunction): string;
|
|
3
|
+
export declare function standalonePythonService(fn: ServiceFunction): string;
|
|
4
|
+
export declare function pythonHandler(appName: string, fn: ServiceFunction): string;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pythonService = pythonService;
|
|
4
|
+
exports.standalonePythonService = standalonePythonService;
|
|
5
|
+
exports.pythonHandler = pythonHandler;
|
|
6
|
+
const types_js_1 = require("../types.js");
|
|
7
|
+
function pythonService(answers, fn) {
|
|
8
|
+
// The layer lands on sys.path as /opt/python, so its modules are imported bare.
|
|
9
|
+
// Everything else is packaged from the project root, hence the src. prefix.
|
|
10
|
+
const loggerImport = answers.layer
|
|
11
|
+
? "from logger import logger"
|
|
12
|
+
: `from ${types_js_1.SRC_DIR}.shared.logger import logger`;
|
|
13
|
+
// db is never in the layer, so it is always imported from the packaged source tree.
|
|
14
|
+
const dbImport = answers.database === "none"
|
|
15
|
+
? ""
|
|
16
|
+
: answers.database === "dynamodb"
|
|
17
|
+
? `from ${types_js_1.SRC_DIR}.shared.db import users_table, products_table\n`
|
|
18
|
+
: `from ${types_js_1.SRC_DIR}.shared.db import connect_db\n`;
|
|
19
|
+
const dbSetup = answers.database === "none"
|
|
20
|
+
? ""
|
|
21
|
+
: answers.database === "dynamodb"
|
|
22
|
+
? " _ = (users_table, products_table)\n"
|
|
23
|
+
: " _ = connect_db\n";
|
|
24
|
+
return `import json
|
|
25
|
+
${loggerImport}
|
|
26
|
+
${dbImport}
|
|
27
|
+
def ${fn.name}(event, context):
|
|
28
|
+
${dbSetup} logger.info("${fn.name} invoked")
|
|
29
|
+
body = event.get("body")
|
|
30
|
+
payload = json.loads(body) if body else {}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
"statusCode": 200,
|
|
34
|
+
"headers": {"Content-Type": "application/json"},
|
|
35
|
+
"body": json.dumps({"message": "${fn.name}", "input": payload}),
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
// Used when a function's runtime family differs from the project's: it can't attach
|
|
40
|
+
// the project's layer or import its db client (built for the other family), so it
|
|
41
|
+
// ships as a plain, self-contained handler instead.
|
|
42
|
+
function standalonePythonService(fn) {
|
|
43
|
+
return `import json
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def ${fn.name}(event, context):
|
|
47
|
+
print(json.dumps({"level": "info", "message": "${fn.name} invoked"}))
|
|
48
|
+
body = event.get("body")
|
|
49
|
+
payload = json.loads(body) if body else {}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
"statusCode": 200,
|
|
53
|
+
"headers": {"Content-Type": "application/json"},
|
|
54
|
+
"body": json.dumps({"message": "${fn.name}", "input": payload}),
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
function pythonHandler(appName, fn) {
|
|
59
|
+
return `from ${types_js_1.SRC_DIR}.services.${appName}.${fn.name} import ${fn.name}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def handler(event, context):
|
|
63
|
+
return ${fn.name}(event, context)
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { InitAnswers, ServiceDef } from "../types.js";
|
|
2
|
+
export declare function samServiceTemplate(answers: InitAnswers, service: ServiceDef, envKeys?: string[]): string;
|
|
3
|
+
export declare function samFlatTemplate(answers: InitAnswers, apps: ServiceDef[], envKeys?: string[]): string;
|
|
4
|
+
export declare function samRootTemplate(answers: InitAnswers, apps: ServiceDef[], envKeys?: string[]): string;
|