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.
Files changed (135) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/COMMAND.md +636 -0
  3. package/LICENSE +21 -0
  4. package/NOTICE.md +22 -0
  5. package/README.md +168 -0
  6. package/bin/slskit.js +3 -0
  7. package/dist/cli.d.ts +1 -0
  8. package/dist/cli.js +25 -0
  9. package/dist/commands/base-command.d.ts +5 -0
  10. package/dist/commands/base-command.js +29 -0
  11. package/dist/commands/configure/action.d.ts +2 -0
  12. package/dist/commands/configure/action.js +120 -0
  13. package/dist/commands/configure/aws-cli.d.ts +16 -0
  14. package/dist/commands/configure/aws-cli.js +135 -0
  15. package/dist/commands/configure/index.d.ts +2 -0
  16. package/dist/commands/configure/index.js +20 -0
  17. package/dist/commands/configure/prompts.d.ts +8 -0
  18. package/dist/commands/configure/prompts.js +117 -0
  19. package/dist/commands/configure/types.d.ts +24 -0
  20. package/dist/commands/configure/types.js +6 -0
  21. package/dist/commands/deploy/action.d.ts +2 -0
  22. package/dist/commands/deploy/action.js +115 -0
  23. package/dist/commands/deploy/index.d.ts +2 -0
  24. package/dist/commands/deploy/index.js +23 -0
  25. package/dist/commands/deploy/sam-deploy.d.ts +10 -0
  26. package/dist/commands/deploy/sam-deploy.js +127 -0
  27. package/dist/commands/deploy/scope.d.ts +9 -0
  28. package/dist/commands/deploy/scope.js +34 -0
  29. package/dist/commands/deploy/types.d.ts +20 -0
  30. package/dist/commands/deploy/types.js +2 -0
  31. package/dist/commands/env/action.d.ts +11 -0
  32. package/dist/commands/env/action.js +274 -0
  33. package/dist/commands/env/dotenv.d.ts +6 -0
  34. package/dist/commands/env/dotenv.js +99 -0
  35. package/dist/commands/env/index.d.ts +2 -0
  36. package/dist/commands/env/index.js +76 -0
  37. package/dist/commands/env/keys.d.ts +8 -0
  38. package/dist/commands/env/keys.js +41 -0
  39. package/dist/commands/env/parameters.d.ts +7 -0
  40. package/dist/commands/env/parameters.js +63 -0
  41. package/dist/commands/env/templates.d.ts +3 -0
  42. package/dist/commands/env/templates.js +65 -0
  43. package/dist/commands/env/types.d.ts +21 -0
  44. package/dist/commands/env/types.js +2 -0
  45. package/dist/commands/function/action.d.ts +2 -0
  46. package/dist/commands/function/action.js +71 -0
  47. package/dist/commands/function/generator.d.ts +8 -0
  48. package/dist/commands/function/generator.js +58 -0
  49. package/dist/commands/function/index.d.ts +2 -0
  50. package/dist/commands/function/index.js +26 -0
  51. package/dist/commands/function/manifest.d.ts +5 -0
  52. package/dist/commands/function/manifest.js +57 -0
  53. package/dist/commands/function/prompts.d.ts +18 -0
  54. package/dist/commands/function/prompts.js +196 -0
  55. package/dist/commands/function/tooling.d.ts +2 -0
  56. package/dist/commands/function/tooling.js +43 -0
  57. package/dist/commands/function/types.d.ts +52 -0
  58. package/dist/commands/function/types.js +2 -0
  59. package/dist/commands/index.d.ts +2 -0
  60. package/dist/commands/index.js +19 -0
  61. package/dist/commands/init/action.d.ts +2 -0
  62. package/dist/commands/init/action.js +36 -0
  63. package/dist/commands/init/content.d.ts +2 -0
  64. package/dist/commands/init/content.js +97 -0
  65. package/dist/commands/init/index.d.ts +2 -0
  66. package/dist/commands/init/index.js +30 -0
  67. package/dist/commands/init/manifest.d.ts +6 -0
  68. package/dist/commands/init/manifest.js +147 -0
  69. package/dist/commands/init/prompts.d.ts +6 -0
  70. package/dist/commands/init/prompts.js +155 -0
  71. package/dist/commands/init/scaffold.d.ts +7 -0
  72. package/dist/commands/init/scaffold.js +85 -0
  73. package/dist/commands/init/templates/helpers.d.ts +9 -0
  74. package/dist/commands/init/templates/helpers.js +42 -0
  75. package/dist/commands/init/templates/node.d.ts +4 -0
  76. package/dist/commands/init/templates/node.js +99 -0
  77. package/dist/commands/init/templates/project.d.ts +8 -0
  78. package/dist/commands/init/templates/project.js +239 -0
  79. package/dist/commands/init/templates/python.d.ts +4 -0
  80. package/dist/commands/init/templates/python.js +65 -0
  81. package/dist/commands/init/templates/sam.d.ts +4 -0
  82. package/dist/commands/init/templates/sam.js +369 -0
  83. package/dist/commands/init/templates/shared-code.d.ts +6 -0
  84. package/dist/commands/init/templates/shared-code.js +159 -0
  85. package/dist/commands/init/types.d.ts +47 -0
  86. package/dist/commands/init/types.js +75 -0
  87. package/dist/commands/rm/action.d.ts +2 -0
  88. package/dist/commands/rm/action.js +89 -0
  89. package/dist/commands/rm/index.d.ts +2 -0
  90. package/dist/commands/rm/index.js +25 -0
  91. package/dist/commands/rm/plan.d.ts +19 -0
  92. package/dist/commands/rm/plan.js +78 -0
  93. package/dist/commands/rm/prompts.d.ts +4 -0
  94. package/dist/commands/rm/prompts.js +107 -0
  95. package/dist/commands/rm/types.d.ts +7 -0
  96. package/dist/commands/rm/types.js +2 -0
  97. package/dist/commands/run/action.d.ts +2 -0
  98. package/dist/commands/run/action.js +171 -0
  99. package/dist/commands/run/index.d.ts +2 -0
  100. package/dist/commands/run/index.js +21 -0
  101. package/dist/commands/run/local-template.d.ts +7 -0
  102. package/dist/commands/run/local-template.js +51 -0
  103. package/dist/commands/run/manifest.d.ts +2 -0
  104. package/dist/commands/run/manifest.js +20 -0
  105. package/dist/commands/run/resources.d.ts +20 -0
  106. package/dist/commands/run/resources.js +93 -0
  107. package/dist/commands/run/sam-cli.d.ts +10 -0
  108. package/dist/commands/run/sam-cli.js +183 -0
  109. package/dist/commands/run/types.d.ts +18 -0
  110. package/dist/commands/run/types.js +2 -0
  111. package/dist/commands/run/watch.d.ts +11 -0
  112. package/dist/commands/run/watch.js +131 -0
  113. package/dist/core/context.d.ts +15 -0
  114. package/dist/core/context.js +41 -0
  115. package/dist/core/credentials.d.ts +10 -0
  116. package/dist/core/credentials.js +22 -0
  117. package/dist/core/environments.d.ts +46 -0
  118. package/dist/core/environments.js +161 -0
  119. package/dist/core/errors.d.ts +4 -0
  120. package/dist/core/errors.js +11 -0
  121. package/dist/core/flags-docs.d.ts +2 -0
  122. package/dist/core/flags-docs.js +63 -0
  123. package/dist/core/is-ci.d.ts +4 -0
  124. package/dist/core/is-ci.js +16 -0
  125. package/dist/core/logger.d.ts +4 -0
  126. package/dist/core/logger.js +19 -0
  127. package/dist/core/run.d.ts +1 -0
  128. package/dist/core/run.js +27 -0
  129. package/dist/core/scope.d.ts +33 -0
  130. package/dist/core/scope.js +108 -0
  131. package/dist/index.d.ts +3 -0
  132. package/dist/index.js +9 -0
  133. package/dist/program.d.ts +2 -0
  134. package/dist/program.js +26 -0
  135. 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;