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
package/CHANGELOG.md ADDED
@@ -0,0 +1,61 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - a6d08e3: First stable release: slskit 1.0.0 — scaffold, run, and deploy multi-service AWS Lambda projects on AWS SAM.
8
+
9
+ ## 0.2.0
10
+
11
+ First release published to npm.
12
+
13
+ ### Added
14
+
15
+ - `slskit rm` (aliased `slskit remove`) removes a function, or a service and every
16
+ function in it: the handler, the service file, the service template, the manifest
17
+ entry, the route, the layer attachment and the service's nesting in the root stack.
18
+ It asks what to remove when given no flags, prints the plan before deleting, and
19
+ needs `--yes` without a TTY. Removing a service's last function removes the service,
20
+ because a template with no resources is not valid CloudFormation; emptying the
21
+ project entirely is refused.
22
+ - `slskit run` and `slskit deploy` ask what to act on — everything, one service, or a
23
+ single function — and accept `--service`, `--function` and `--all` to skip the
24
+ question. A scoped run serves a template containing only those functions, so SAM
25
+ builds only those.
26
+ - Watch mode: `slskit run` rebuilds on save, rebuilding only the function that
27
+ changed. `--no-watch` turns it off.
28
+ - `slskit deploy` reports each stack's API Gateway URL when it finishes.
29
+ - Variables can be added by editing `.env.<environment>` directly; `run` and `deploy`
30
+ reconcile the templates with the current set of names before calling SAM.
31
+ - `COMMAND.md`: a full command reference.
32
+
33
+ ### Changed
34
+
35
+ - Every project is now a root stack nesting one template per service under
36
+ `templates/`, so the root file stays short as the project grows.
37
+ - `--shared-api` now decides only where the API Gateway lives, not the file layout.
38
+ It defaults to `no` (one API per service).
39
+ - With a shared API, `slskit run` serves a flattened template generated from
40
+ `slskit.json`, because SAM local cannot resolve an API held in a parent stack.
41
+ - The manifest is `slskit.json`. A project still holding `sless.json` is read as
42
+ before and migrated on the next write.
43
+ - Serverless Framework support was removed; generated projects are AWS SAM only.
44
+
45
+ ### Fixed
46
+
47
+ - `slskit function` no longer wipes every environment except `dev` from
48
+ `slskit.json` — regions, profiles and variables are preserved.
49
+ - A function name reused in another service is refused instead of silently
50
+ overwriting the first function in the template.
51
+ - Parameter values containing spaces are no longer truncated on their way to SAM.
52
+ - `DATABASE_URL` reached deployed functions as the literal string `DatabaseUrl`.
53
+
54
+ ## 0.1.0
55
+
56
+ Initial release.
57
+
58
+ ---
59
+
60
+ Entries from 0.3.0 onward are generated by [Changesets](https://github.com/changesets/changesets)
61
+ from the files contributors add with `npx changeset`. Do not edit released sections by hand.
package/COMMAND.md ADDED
@@ -0,0 +1,636 @@
1
+ # slskit — command reference
2
+
3
+ Every command, every flag, and what each one actually does.
4
+
5
+ `slskit` scaffolds and grows multi-service AWS Lambda projects built on AWS SAM.
6
+ It has two runtime dependencies (`commander` and `@inquirer/prompts`) and shells out
7
+ to the AWS SAM CLI and the AWS CLI for everything that touches AWS.
8
+
9
+ | Command | What it does |
10
+ | --- | --- |
11
+ | [`slskit init`](#slskit-init-name) | Scaffold a new project |
12
+ | [`slskit run`](#slskit-run-environment) | Run it locally on one API Gateway port |
13
+ | [`slskit function`](#slskit-function-name) | Add a function to a new or existing service |
14
+ | [`slskit rm`](#slskit-rm-name) | Remove a function or a service |
15
+ | [`slskit configure`](#slskit-configure) | Set AWS credentials and the deploy target |
16
+ | [`slskit env`](#slskit-env) | Manage environments and their variables |
17
+ | [`slskit deploy`](#slskit-deploy-environment) | Deploy to AWS |
18
+
19
+ Conventions used below: `<required>`, `[optional]`. Every command that reads a
20
+ project must be run from the project root — the directory holding `slskit.json` —
21
+ or passed `--cwd` to that directory.
22
+
23
+ Every command also accepts `--debug` (stack traces), `--silent` (no info logs)
24
+ and `--json` (suppress human output). The generated flag list is in
25
+ [docs/flags.md](docs/flags.md); this file is the narrative reference.
26
+
27
+ ---
28
+
29
+ ## Concepts
30
+
31
+ Four ideas explain most of the behaviour.
32
+
33
+ **The manifest.** `slskit.json` is the project graph: services, functions, runtimes,
34
+ routes, environments. Every command reads it, and the templates are regenerated from
35
+ it, so it is the source of truth rather than the YAML. A project generated before the
36
+ CLI was renamed still has `sless.json`; that is read as a fallback and migrated to the
37
+ new name the next time anything writes to it.
38
+
39
+ **Environments.** An environment is one deploy target: its own region, AWS profile,
40
+ CloudFormation stack and variables. Every project starts with `dev`. Environments
41
+ never share resources — `dev` and `production` are separate stacks with separately
42
+ named functions.
43
+
44
+ **`APP_ENVIRONMENT`.** One variable is generated for every environment and always
45
+ equals its name. Every stage-scoped resource name is built from it:
46
+
47
+ | Thing | Name |
48
+ | --- | --- |
49
+ | CloudFormation stack | `<project>-<APP_ENVIRONMENT>` |
50
+ | Lambda function | `<project>-<APP_ENVIRONMENT>-<function>` |
51
+
52
+ Because a Lambda name is capped at 64 characters, an environment name that would push
53
+ any function past the limit is refused up front rather than failing mid-deploy.
54
+
55
+ **Project layout.** A root stack nests one template per service:
56
+
57
+ ```text
58
+ my-lambda-app/
59
+ ├── src/
60
+ │ ├── functions/ # handlers, one folder per service
61
+ │ ├── services/ # business logic the handlers import
62
+ │ └── shared/ # shared utilities (a Lambda layer when --layer yes)
63
+ ├── templates/ # one stack per service: auth.yaml, product.yaml
64
+ ├── template.yaml # root stack, nests them
65
+ ├── .env.dev # the dev environment's variables (gitignored)
66
+ └── slskit.json # the project graph
67
+ ```
68
+
69
+ ---
70
+
71
+ ## `slskit init [name]`
72
+
73
+ Scaffolds a new AWS SAM project with two example services (`auth`, `product`), their
74
+ handlers, business logic, shared code and templates, then runs `npm install`.
75
+
76
+ ```bash
77
+ slskit init my-lambda-app
78
+ slskit init . # scaffold into the current directory
79
+
80
+ slskit init my-lambda-app \
81
+ --runtime typescript \
82
+ --database none \
83
+ --api-gateway yes \
84
+ --shared-api no \
85
+ --layer yes \
86
+ --memory 128
87
+ ```
88
+
89
+ | Argument | Meaning |
90
+ | --- | --- |
91
+ | `name` | Project name, and the folder it is created in. `.` uses the current directory. |
92
+
93
+ | Flag | Values |
94
+ | --- | --- |
95
+ | `-r, --runtime` | `typescript` \| `javascript` \| `python` |
96
+ | `--database` | `none` \| `prisma` \| `mongoose` \| `dynamodb` |
97
+ | `--api-gateway` | `yes` \| `no` — expose the functions over HTTP |
98
+ | `--shared-api` | `yes` \| `no` — one API Gateway for everything. Default `no`. |
99
+ | `--layer` | `yes` \| `no` — publish `shared/` as a common Lambda layer |
100
+ | `--memory` | `128` \| `256` \| `512` \| `1024` \| `2048` \| `3008` \| `4096` \| `10240` |
101
+ | `-f, --force` | Overwrite files if the folder already exists |
102
+
103
+ Prompts for anything not passed. In a non-interactive shell every flag except
104
+ `--shared-api` and `--force` must be supplied.
105
+
106
+ > `--force` overwrites existing files in place. Never run it in a directory holding a
107
+ > project you care about.
108
+
109
+ ### One API Gateway, or one per service
110
+
111
+ Either way you get a root stack nesting `templates/<service>.yaml`, so the root file
112
+ stays short as the project grows. The flag only decides where the API lives.
113
+
114
+ | | `--shared-api no` (default) | `--shared-api yes` |
115
+ | --- | --- | --- |
116
+ | API Gateways | one per service | 1 |
117
+ | Routes declared as | SAM `HttpApi` events | API Gateway v2 resources |
118
+ | Stack output | `AuthApiUrl`, `ProductApiUrl`, … | `ApiUrl` |
119
+
120
+ Multiple API Gateways do not cost more — HTTP APIs bill per request, not per gateway.
121
+ The usual way to put one public URL in front of several is a custom domain with path
122
+ mappings.
123
+
124
+ A shared API has to be declared with plain `AWS::ApiGatewayV2::Route` resources,
125
+ because SAM only resolves an `ApiId` inside the template that declares the API:
126
+
127
+ ```text
128
+ ApiId must be a valid reference to an 'AWS::Serverless::HttpApi' resource in same template
129
+ ```
130
+
131
+ That deploys correctly but `sam local start-api` cannot serve it — it returns 502 on
132
+ every route. So `slskit run` serves a flattened copy instead; see below.
133
+
134
+ ---
135
+
136
+ ## `slskit run [environment]`
137
+
138
+ Runs the project locally, serving every route from a single API Gateway port. Checks
139
+ that the AWS SAM CLI is installed first, and offers to install it (Homebrew on macOS,
140
+ snap on Linux) when it is missing.
141
+
142
+ ```bash
143
+ slskit run # default environment, port 3000
144
+ slskit run staging # run with the staging environment
145
+ slskit run dev --port 4000
146
+ slskit run --service auth # only auth's routes
147
+ slskit run --function getProducts # only that one
148
+ slskit run --all # everything, without being asked
149
+ slskit run --no-build
150
+ slskit run --no-watch
151
+ ```
152
+
153
+ | Argument | Meaning |
154
+ | --- | --- |
155
+ | `environment` | Environment to run with. Defaults to the default environment. |
156
+
157
+ | Flag | Meaning |
158
+ | --- | --- |
159
+ | `-e, --env <name>` | Same as the positional argument |
160
+ | `-p, --port <port>` | Local API Gateway port (default `3000`) |
161
+ | `-s, --service <name>` | Run every function in one service |
162
+ | `--function <name>` | Run one function on its own |
163
+ | `--all` | Run everything without being asked what to run |
164
+ | `--no-build` | Skip `sam build` before starting |
165
+ | `--no-watch` | Don't rebuild on save |
166
+
167
+ ### Choosing what to run
168
+
169
+ With a TTY and no scope flag, it asks:
170
+
171
+ ```text
172
+ ? What do you want to run?
173
+ ❯ Everything — every service
174
+ One service — all of its functions
175
+ One function
176
+ ? Service: auth (2 functions)
177
+ ```
178
+
179
+ A scoped run is meaningfully faster: it serves a template containing only those
180
+ functions, so `sam build` compiles only those. Routes outside the scope are not
181
+ mounted. Function names are unique project-wide, so `--function` finds its own
182
+ service. An unknown name fails before SAM starts.
183
+
184
+ Without a TTY the scope defaults to everything, so scripted runs are unchanged.
185
+
186
+ ### Watch mode
187
+
188
+ On by default. Saving a file rebuilds the smallest thing that can change:
189
+
190
+ | Changed | What happens |
191
+ | --- | --- |
192
+ | a handler or service file | only that function is rebuilt; the next request uses it |
193
+ | `src/shared/**` | full rebuild |
194
+ | a template, `slskit.json`, or a `.env` file | full rebuild, then the local API restarts |
195
+
196
+ A rebuild that fails leaves the previous build serving and waits for the next save,
197
+ so a syntax error never takes the session down.
198
+
199
+ ### The generated local template
200
+
201
+ A project whose services share one API Gateway is served from `.slskit-local.yaml`, a
202
+ flattened copy generated from `slskit.json` on every run and built into
203
+ `.aws-sam/local/`. It is gitignored and never deployed. Because both it and the real
204
+ templates come from the same manifest, they cannot drift.
205
+
206
+ Environment variables reach the running functions exactly as they will in AWS, and
207
+ override values are never printed — only how many there are. A `--secret` variable
208
+ missing from `.env.<environment>` fails before SAM starts rather than booting with an
209
+ empty value.
210
+
211
+ ---
212
+
213
+ ## `slskit function [name]`
214
+
215
+ Adds a function to an existing service, or creates a new one. Run from the project
216
+ root. Updates the service template, the root template when the service is new,
217
+ `slskit.json`, and installs any tooling the new function needs.
218
+
219
+ ```bash
220
+ slskit function resetPassword --app auth --method POST --memory 512 --runtime typescript
221
+ slskit function list --new-app category --method GET --memory 128 --runtime typescript
222
+ ```
223
+
224
+ | Argument | Meaning |
225
+ | --- | --- |
226
+ | `name` | Function name. Letters and digits, starting with a letter. |
227
+
228
+ | Flag | Values |
229
+ | --- | --- |
230
+ | `--app <name>` | Attach to an existing service (mutually exclusive with `--new-app`) |
231
+ | `--new-app <name>` | Create a new service with this name |
232
+ | `--method` | `GET` \| `POST` \| `PUT` \| `DELETE` \| `PATCH` |
233
+ | `--memory` | `128` \| `256` \| `512` \| `1024` \| `2048` \| `3008` \| `4096` \| `10240` |
234
+ | `-r, --runtime` | `typescript` \| `javascript` \| `python` |
235
+
236
+ The route is `/<service>/<function>`.
237
+
238
+ ### Names are unique across the project
239
+
240
+ Not just within one service. The Lambda is physically named
241
+ `<project>-<environment>-<function>`, and with a shared API the template's logical id
242
+ is `<Name>Function` — both project-scoped. A reused name is refused, and the prompt
243
+ asks again rather than giving up:
244
+
245
+ ```text
246
+ ? Function name: list
247
+ > Function "list" already exists in application "category". Choose another name.
248
+ ? Function name:
249
+ ```
250
+
251
+ With `--name` in a non-interactive shell it fails with the same message.
252
+
253
+ ### Mixed runtimes
254
+
255
+ Each function can use a different language from the rest of the project. A function
256
+ whose runtime family differs (Node vs. Python) cannot attach the project's layer or
257
+ import its database client, so it is generated standalone — a plain success response,
258
+ no shared imports. If the project lacks the tooling that function needs (the first
259
+ TypeScript function in a JavaScript project, say), `package.json` / `tsconfig.json`
260
+ are updated and `npm install` runs.
261
+
262
+ ---
263
+
264
+ ## `slskit rm [name]`
265
+
266
+ Removes a function, or a whole service and every function in it. The inverse of
267
+ `slskit function`: it deletes the code, prunes `slskit.json`, and regenerates every
268
+ template that referenced what went. Aliased as `slskit remove`.
269
+
270
+ ```bash
271
+ slskit rm # asks what to remove, then which one
272
+ slskit rm login # resolved by name
273
+ slskit rm --function login
274
+ slskit rm --service auth # the service and all of its functions
275
+ slskit rm --app auth # same thing
276
+ slskit rm login --yes # skip the confirmation
277
+ ```
278
+
279
+ | Argument | Meaning |
280
+ | --- | --- |
281
+ | `name` | A function or service name. Looked up in the project; `--function`/`--service` settle it if one name is both. |
282
+
283
+ | Flag | Meaning |
284
+ | --- | --- |
285
+ | `--function <name>` | Remove this function |
286
+ | `--service <name>` | Remove this service and every function in it |
287
+ | `--app <name>` | Same as `--service` |
288
+ | `-y, --yes` | Skip the confirmation prompt — required in a non-interactive shell |
289
+
290
+ ### What it deletes
291
+
292
+ | Removing | Gone |
293
+ | --- | --- |
294
+ | a function | `src/functions/<service>/<function>/`, `src/services/<service>/<function>.<ext>` |
295
+ | a service | `src/functions/<service>/`, `src/services/<service>/`, `templates/<service>.yaml` |
296
+
297
+ And in every case: the function's entry in `slskit.json`, its route, its layer
298
+ attachment, its directory listing — plus the service's nesting in `template.yaml` and
299
+ its entry in `framework.files.applications`, `apiGateway.templates` and
300
+ `layer.templates` when a whole service goes.
301
+
302
+ The manifest is rebuilt from the pruned service list rather than edited in place, so
303
+ nothing derived from it can be left behind. Environments, their variables and the
304
+ project version are carried through untouched.
305
+
306
+ ### It asks before it deletes
307
+
308
+ With no flags and a TTY it asks what kind of thing to remove, then which one:
309
+
310
+ ```text
311
+ ? What do you want to remove?
312
+ ❯ A function
313
+ An application — and every function in it
314
+ ? Function: auth/login POST /auth/login
315
+ ```
316
+
317
+ Then it prints exactly what will go and waits for a yes. `--yes` skips that, and is
318
+ required without a TTY — where the command prints the same plan and stops rather than
319
+ deleting anything.
320
+
321
+ ### Removing the last function removes its service
322
+
323
+ A service template with no functions is not valid CloudFormation, so a function that
324
+ is the last one in its service takes the service with it. The command says so before
325
+ asking.
326
+
327
+ For the same reason it refuses to empty the project:
328
+
329
+ ```text
330
+ "login" is the only function in this project, and a stack with no resources cannot be
331
+ deployed. Add another function first, or start over with "slskit init".
332
+ ```
333
+
334
+ ### It does not touch AWS
335
+
336
+ `slskit rm` only changes your project. Resources already deployed stay until the next
337
+ full deploy removes them from the stack:
338
+
339
+ ```bash
340
+ slskit deploy production --all
341
+ ```
342
+
343
+ A scoped deploy cannot do it — removing a resource is an infrastructure change.
344
+
345
+ ---
346
+
347
+ ## `slskit configure`
348
+
349
+ Records the AWS credentials and deploy target for an environment. Run before
350
+ deploying.
351
+
352
+ ```bash
353
+ slskit configure # interactive, environment "dev"
354
+ slskit configure --profile work --region us-east-1
355
+ slskit configure --env production --profile prod-admin --region eu-west-2
356
+ slskit configure --set-credentials # enter an access key
357
+ ```
358
+
359
+ | Flag | Meaning |
360
+ | --- | --- |
361
+ | `-e, --env <name>` | Environment to configure (default `dev`) |
362
+ | `--profile <name>` | AWS named profile to resolve credentials from |
363
+ | `--region <region>` | AWS region to deploy into |
364
+ | `--stack-name <name>` | CloudFormation stack name (default `<project>-<environment>`) |
365
+ | `--skip-verify` | Save without checking that the credentials work |
366
+ | `--set-credentials` | Enter an AWS access key and store it in `~/.aws/credentials` |
367
+
368
+ Each value falls back, in order, to: the flag, whatever the environment already had,
369
+ the shell (`AWS_PROFILE`, `AWS_REGION`), then your AWS config file. Credentials are
370
+ verified with `aws sts get-caller-identity` and nothing is written if they don't work
371
+ — use `--skip-verify` to save regardless. When the AWS CLI isn't installed the check
372
+ is skipped with a notice.
373
+
374
+ ### Storing an access key
375
+
376
+ If credentials don't verify, `configure` offers to take a key there and then:
377
+
378
+ ```text
379
+ Could not verify AWS credentials for profile "work" in us-east-1.
380
+ ? Enter an AWS access key now and store it in ~/.aws/credentials? Yes
381
+ ? AWS Access Key ID: AKIA...
382
+ ? AWS Secret Access Key: [hidden]
383
+ ```
384
+
385
+ The secret is never echoed. It is handed to `aws configure set`, which writes it to
386
+ `~/.aws/credentials` — **outside your project**, so it cannot be committed.
387
+
388
+ **No credential material is ever written into the project.** Only the profile *name*
389
+ goes into `slskit.json`, resolved at deploy time; when credentials come from
390
+ environment variables, no profile is recorded at all.
391
+
392
+ ---
393
+
394
+ ## `slskit env`
395
+
396
+ Manages environments and their variables.
397
+
398
+ ```bash
399
+ slskit env list
400
+ slskit env add production --profile prod-admin --region eu-west-2
401
+ slskit env use production
402
+ slskit env remove staging --yes
403
+ slskit env set LOG_LEVEL=debug
404
+ slskit env unset API_KEY
405
+ slskit env vars --env production
406
+ ```
407
+
408
+ ### `slskit env list` (alias `ls`)
409
+
410
+ Shows every environment with its stack, region, profile and variable count. `*` marks
411
+ the default.
412
+
413
+ ### `slskit env add <name>`
414
+
415
+ Creates an environment and configures its deploy target — the same credential flow as
416
+ `configure`.
417
+
418
+ | Flag | Meaning |
419
+ | --- | --- |
420
+ | `--profile <name>` | AWS named profile |
421
+ | `--region <region>` | AWS region |
422
+ | `--stack-name <name>` | CloudFormation stack name |
423
+ | `--skip-verify` | Save without checking the credentials |
424
+
425
+ Names are lowercase, starting with a letter: `[a-z][a-z0-9-]*`. A name that would push
426
+ any Lambda past the 64-character limit is refused.
427
+
428
+ ### `slskit env use <name>`
429
+
430
+ Sets the environment every other command defaults to.
431
+
432
+ ### `slskit env remove <name>` (alias `rm`)
433
+
434
+ Removes an environment from `slskit.json` and regenerates the templates. `-y, --yes`
435
+ skips the confirmation, and is required in a non-interactive shell. The
436
+ `.env.<environment>` file is left on disk — delete it yourself.
437
+
438
+ ### `slskit env set <KEY=value>`
439
+
440
+ | Flag | Meaning |
441
+ | --- | --- |
442
+ | `-e, --env <name>` | Environment to change (default: the default one) |
443
+ | `--secret` | Store the value in `.env.<environment>`, never in `slskit.json` |
444
+ | `--ssm <path>` | Store only the SSM path; AWS resolves the value at deploy |
445
+
446
+ ```bash
447
+ slskit env set LOG_LEVEL=debug # plain value, in slskit.json
448
+ slskit env set API_KEY=sk-live-abc --secret # value in .env.<environment>
449
+ slskit env set DB_PASSWORD --ssm /shop/prod/db # resolved by AWS at deploy
450
+ ```
451
+
452
+ `APP_ENVIRONMENT` is managed by slskit and cannot be set.
453
+
454
+ ### `slskit env unset <key>`
455
+
456
+ Removes a variable. `-e, --env` selects the environment.
457
+
458
+ ### `slskit env vars`
459
+
460
+ Shows every variable for an environment, secrets masked. `--show-secrets` reveals
461
+ them; `-e, --env` selects the environment.
462
+
463
+ ### How variables reach your functions
464
+
465
+ You can also just edit `.env.<environment>` — a key typed in by hand is a real
466
+ variable. `run` and `deploy` reconcile the templates with the current set of names
467
+ before handing anything to SAM, so no extra command is needed.
468
+
469
+ Each variable becomes a CloudFormation parameter (`LOG_LEVEL` → `EnvLogLevel`) wired
470
+ into every function's `Environment.Variables`, supplied at deploy as a
471
+ `--parameter-overrides` entry. Every stage parameter is `NoEcho` and defaults to
472
+ empty, so an environment that doesn't set one still deploys.
473
+
474
+ | Kind | Stored in | Reaches AWS as |
475
+ | --- | --- | --- |
476
+ | plain | `slskit.json` | the literal value |
477
+ | `--secret` | `.env.<environment>` (gitignored) | the value read from that file at deploy |
478
+ | `--ssm` | `slskit.json` (path only) | `{{resolve:ssm:<path>}}`, resolved by CloudFormation |
479
+ | edited by hand | `.env.<environment>` (gitignored) | the value read from that file at deploy |
480
+
481
+ A `--secret` variable missing from its `.env` file fails the command with the exact
482
+ `slskit env set` line that fixes it, rather than deploying an empty string.
483
+
484
+ Values are passed as `ParameterKey=…,ParameterValue="…"` rather than SAM's shorthand,
485
+ because the shorthand splits on whitespace and would silently truncate `hello world`
486
+ to `hello`.
487
+
488
+ > A Lambda environment variable is readable in plaintext by anyone with
489
+ > `lambda:GetFunctionConfiguration`. `NoEcho` hides it in CloudFormation, not from
490
+ > your account's users. For real secrets prefer `--ssm`.
491
+
492
+ ---
493
+
494
+ ## `slskit deploy [environment]`
495
+
496
+ Deploys to AWS — every function, API Gateway, layer and table, under that
497
+ environment's own CloudFormation stack.
498
+
499
+ ```bash
500
+ slskit deploy # default environment
501
+ slskit deploy production
502
+ slskit deploy production -y # skip the confirmation (CI)
503
+ slskit deploy dev --service auth # every function in auth
504
+ slskit deploy dev --function login # just that one
505
+ slskit deploy dev --all # whole project, no question
506
+ ```
507
+
508
+ | Argument | Meaning |
509
+ | --- | --- |
510
+ | `environment` | Environment to deploy. Defaults to the default environment. |
511
+
512
+ | Flag | Meaning |
513
+ | --- | --- |
514
+ | `-e, --env <name>` | Same as the positional argument |
515
+ | `-s, --service <name>` | Deploy every function in one service |
516
+ | `--function <name>` | Deploy one function on its own |
517
+ | `--all` | Deploy everything without being asked |
518
+ | `-y, --yes` | Skip the confirmation prompt — required in a non-interactive shell |
519
+ | `--no-build` | Skip `sam build` |
520
+ | `--skip-verify` | Deploy without checking the credentials first |
521
+ | `--guided` | Run `sam deploy --guided` instead of the managed defaults |
522
+
523
+ ### Choosing what to deploy
524
+
525
+ With a TTY and no scope flag, it asks the same way `run` does. Naming an unknown
526
+ service or function fails immediately, before anything reaches AWS.
527
+
528
+ A scoped deploy is a **code-only** update: it runs `sam sync --code` against functions
529
+ already in the stack. Much faster, but it cannot change infrastructure.
530
+
531
+ | Changed | Use |
532
+ | --- | --- |
533
+ | business logic in a handler or service | `--function` or `--service` |
534
+ | a route, memory size, or a variable | `--all` |
535
+ | a function added with `slskit function` | `--all` |
536
+
537
+ Because a code sync updates functions rather than creating them, it needs a stack that
538
+ already exists:
539
+
540
+ ```text
541
+ Stack "shop-dev" does not exist yet, so there is nothing to update.
542
+ Deploy the whole project first: slskit deploy dev --all
543
+ ```
544
+
545
+ ### What it does
546
+
547
+ It stops before calling AWS if the environment has no region, doesn't exist, the
548
+ credentials don't verify, or a `--secret` variable is missing — so a failed deploy
549
+ costs nothing. Then it prints the plan and asks:
550
+
551
+ ```text
552
+ About to deploy the whole project of "shop" to AWS.
553
+ APP_ENVIRONMENT: production
554
+ stack: shop-production
555
+ region: eu-west-2
556
+ functions: 4
557
+ shop-production-login
558
+ ...
559
+ This creates real AWS resources in your account and they cost money.
560
+ ? Deploy to "production"? (y/N)
561
+ ```
562
+
563
+ Deploys are granted `CAPABILITY_IAM` and `CAPABILITY_AUTO_EXPAND` (the latter for the
564
+ nested service stacks), and `--resolve-s3` provisions the artifact bucket, so a first
565
+ deploy needs no manual setup. Afterwards it prints the stack outputs:
566
+
567
+ ```text
568
+ Deployed the whole project of "shop" to "dev".
569
+ stack: shop-dev
570
+ region: us-east-1
571
+
572
+ Endpoints:
573
+ ApiUrl: https://6hjgplpky0.execute-api.us-east-1.amazonaws.com
574
+ ```
575
+
576
+ Each environment deploys to its own stack, so they never touch each other:
577
+
578
+ | | dev | production |
579
+ | --- | --- | --- |
580
+ | Stack | `shop-dev` | `shop-production` |
581
+ | Lambda | `shop-dev-login` | `shop-production-login` |
582
+
583
+ ---
584
+
585
+ ## Typical sessions
586
+
587
+ **Start a project and see it running**
588
+
589
+ ```bash
590
+ slskit init my-lambda-app
591
+ cd my-lambda-app
592
+ slskit run
593
+ ```
594
+
595
+ **Add a function and try it**
596
+
597
+ ```bash
598
+ slskit function resetPassword --app auth --method POST --memory 128 --runtime typescript
599
+ slskit run --service auth
600
+ ```
601
+
602
+ **First deploy**
603
+
604
+ ```bash
605
+ slskit configure --set-credentials
606
+ slskit deploy dev
607
+ ```
608
+
609
+ **Add a production environment**
610
+
611
+ ```bash
612
+ slskit env add production --profile prod-admin --region eu-west-2
613
+ slskit env set LOG_LEVEL=warn --env production
614
+ slskit env set API_KEY=sk-live-xxx --secret --env production
615
+ slskit deploy production
616
+ ```
617
+
618
+ **Ship a logic change to one function**
619
+
620
+ ```bash
621
+ slskit deploy production --function login
622
+ ```
623
+
624
+ ---
625
+
626
+ ## Files slskit writes
627
+
628
+ | Path | Committed? | What it is |
629
+ | --- | --- | --- |
630
+ | `slskit.json` | yes | the project graph |
631
+ | `template.yaml` | yes | root stack |
632
+ | `templates/<service>.yaml` | yes | one stack per service |
633
+ | `.env.<environment>` | **no** | that environment's variable values |
634
+ | `.slskit-local.yaml` | **no** | generated local-run template |
635
+ | `.aws-sam/` | **no** | SAM build output |
636
+ | `~/.aws/credentials` | n/a | outside the project; where access keys go |