@kirkelliott/zap 0.1.21 → 0.1.23

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/README.md CHANGED
@@ -213,20 +213,38 @@ Both pages share `lib/page.zap`. Update that one file in S3 — both pages chang
213
213
 
214
214
  ## Environments
215
215
 
216
- `zap init --env <name>` provisions a fully isolated stack — separate bucket, Lambda, and KV table for each environment. Prod is the default.
216
+ Each environment is a fully isolated AWS stack — its own S3 bucket, Lambda function, KV table, and URL. `prod` is the default. No flags needed for prod.
217
217
 
218
218
  ```bash
219
+ # spin up staging (takes ~30 seconds, same as init)
219
220
  zap init --env staging
221
+
222
+ # deploy and test there
220
223
  zap deploy --env staging api.zap
224
+ curl https://staging-url.lambda-url.us-east-1.on.aws/api
225
+
226
+ # promote to prod when ready
227
+ zap promote api --from staging --to prod
221
228
  ```
222
229
 
223
- Each environment gets its own URL. When you're happy with staging, promote to prod:
230
+ `promote` copies the file from one bucket to the other. The prod URL is live instantly.
224
231
 
225
- ```bash
226
- zap promote api --from staging --to prod
232
+ `.zaprc` stores each environment under its own key:
233
+
234
+ ```json
235
+ {
236
+ "prod": { "bucket": "zap-a3f2b8c1", "url": "https://abc.lambda-url…", … },
237
+ "staging": { "bucket": "zap-f9e2d4c7", "url": "https://xyz.lambda-url…", … }
238
+ }
227
239
  ```
228
240
 
229
- That's it. No traffic splitting config. No YAML. Just copy the file across.
241
+ Every command accepts `--env`:
242
+
243
+ ```bash
244
+ zap ls --env staging
245
+ zap rollback api --env staging
246
+ zap rm old-handler --env staging
247
+ ```
230
248
 
231
249
  ---
232
250
 
@@ -308,23 +326,4 @@ MIT
308
326
 
309
327
  ---
310
328
 
311
- The file in S3 is just a carrier. You don't need it.
312
-
313
- ```js
314
- // live.zap
315
- export default async (req) => {
316
- if (!req.body) return { status: 400, body: 'POST a function' }
317
- return { body: await eval(`(${req.body})`)({ kv, fetch }) }
318
- }
319
- ```
320
-
321
- ```bash
322
- curl -X POST https://your-endpoint/live \
323
- -d 'async ({ kv }) => kv.get("visits")'
324
- ```
325
-
326
- Deploy `live.zap` once. Then POST JavaScript directly — no S3, no CLI, no deploy step. The runtime running inside itself.
327
-
328
- ---
329
-
330
329
  **[live demo →](https://zn2qgaqlofvauxmoncf36m4ynq0pfarj.lambda-url.us-east-1.on.aws/)**
package/dist/handler.js CHANGED
@@ -10,13 +10,15 @@ const loader = async (name) => {
10
10
  const { Body } = await s3.send(new client_s3_1.GetObjectCommand({ Bucket: BUCKET, Key: `${name}.zap` }));
11
11
  return Body.transformToString();
12
12
  };
13
- const handler = async (event) => {
13
+ const handler = async (event, context) => {
14
+ const start = Date.now();
14
15
  // Cron invocation from EventBridge
15
16
  if (event?.zap?.cron) {
16
17
  try {
17
18
  const source = await loader(event.zap.cron);
18
19
  const fn = (0, eval_1.evalModule)(source, loader);
19
20
  await fn();
21
+ console.log(JSON.stringify({ type: 'cron', handler: event.zap.cron, ms: Date.now() - start, requestId: context.awsRequestId }));
20
22
  }
21
23
  catch (err) {
22
24
  console.error(`cron error [${event.zap.cron}]:`, err.message);
@@ -32,16 +34,18 @@ const handler = async (event) => {
32
34
  headers: e.headers,
33
35
  body: e.body ?? null,
34
36
  };
37
+ const key = req.path === '/' ? 'index' : req.path.replace(/^\//, '');
35
38
  try {
36
- const key = req.path === '/' ? 'index' : req.path.replace(/^\//, '');
37
39
  const source = await loader(key);
38
40
  const res = await (0, eval_1.run)(source, req, loader);
39
- return { statusCode: res.status ?? 200, headers: res.headers, body: (0, types_1.serialize)(res.body) };
41
+ const status = res.status ?? 200;
42
+ console.log(JSON.stringify({ handler: key, method: req.method, status, ms: Date.now() - start, requestId: context.awsRequestId }));
43
+ return { statusCode: status, headers: res.headers, body: (0, types_1.serialize)(res.body) };
40
44
  }
41
45
  catch (err) {
42
- if (err.name === 'NoSuchKey')
43
- return { statusCode: 404, body: `No handler for ${req.path}` };
44
- return { statusCode: 500, body: err.message };
46
+ const status = err.name === 'NoSuchKey' ? 404 : 500;
47
+ console.log(JSON.stringify({ handler: key, method: req.method, status, ms: Date.now() - start, requestId: context.awsRequestId }));
48
+ return { statusCode: status, body: status === 404 ? `No handler for ${req.path}` : err.message };
45
49
  }
46
50
  };
47
51
  exports.handler = handler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kirkelliott/zap",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "Drop a .zap file in S3. It becomes an API endpoint.",
5
5
  "main": "dist/handler.js",
6
6
  "bin": {
package/demo/live.zap DELETED
@@ -1,4 +0,0 @@
1
- export default async (req) => {
2
- if (!req.body) return { status: 400, body: 'POST a function' }
3
- return { body: await eval(`(${req.body})`)({ kv, fetch }) }
4
- }