lambder 4.9.1 → 5.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/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # Lambder
2
+
3
+ A highly opinionated serverless web framework for TypeScript on AWS Lambda.
4
+ Lambder handles HTTP requests, routes, type-safe APIs, sessions and the
5
+ declarative policy layer around them (rate limits, authorization guards,
6
+ idempotency), so an application is a set of declarations rather than a pile of
7
+ per-handler boilerplate.
8
+
9
+ ```typescript
10
+ import { initLambder, LambderLocalFileSource } from "lambder";
11
+ import { z } from "zod";
12
+
13
+ const lambder = initLambder<SessionData>().create({
14
+ apiPath: "/api",
15
+ files: new LambderLocalFileSource({ root: "./public" }),
16
+ session: { tableName: "app-session", tableRegion: "us-east-1", sessionSalt: process.env.SESSION_SALT! },
17
+ });
18
+
19
+ lambder.addApi("getCompany", {
20
+ input: z.object({ slug: z.string() }),
21
+ output: z.object({ id: z.string(), name: z.string() }),
22
+ }, async ({ apiPayload }, res) => res.api(await loadCompany(apiPayload.slug)));
23
+
24
+ export type ApiContractType = typeof lambder.ApiContract;
25
+ export const handler = lambder.getHandler();
26
+ ```
27
+
28
+ The frontend imports that contract type and gets autocomplete, typed payloads
29
+ and typed results with no hand-written client:
30
+
31
+ ```typescript
32
+ import { LambderCaller } from "lambder/client";
33
+ import type { ApiContractType } from "./backend/handler";
34
+
35
+ const caller = new LambderCaller<ApiContractType>({ apiPath: "/api", isCorsEnabled: false });
36
+ const company = await caller.api("getCompany", { slug: "acme" });
37
+ ```
38
+
39
+ ## Features
40
+
41
+ - **Type-safe APIs with Zod.** Define inputs and outputs with Zod schemas; get
42
+ runtime validation and compile-time inference on both sides of the wire.
43
+ - **One inferred contract.** The API contract is derived from the backend code
44
+ and consumed by the frontend as a type-only import.
45
+ - **Simple route and API declaration.** Paths, regexes, predicates and
46
+ structured matchers, chained fluently.
47
+ - **Sessions.** DynamoDB-backed, with secrets hashed at rest, sliding
48
+ expiration, data refresh and cross-subdomain cookies.
49
+ - **Declarative policies.** Named rate-limit policies, authorization guards and
50
+ idempotency, referenced by name from an API declaration and checked at
51
+ compile time.
52
+ - **A real response pipeline.** Automatic Brotli/gzip, ETag and 304 handling,
53
+ cookies, and a guard against Lambda's response size cap.
54
+ - **Hooks and actions.** Lifecycle hooks, plus `addAction()` for the non-HTTP
55
+ invocations (EventBridge, SQS, custom events) the same function receives.
56
+ - **Frontend hosting.** Serve a build from a folder, S3 or R2, with an app
57
+ shell rendered through a build-pipeline-safe template engine.
58
+ - **Runs anywhere Lambda does.** API Gateway REST APIs (payload v1), HTTP APIs
59
+ (payload v2) and Lambda Function URLs; the payload format is detected per
60
+ event.
61
+
62
+ ## Installation
63
+
64
+ ```bash
65
+ npm install lambder zod
66
+ ```
67
+
68
+ `zod` and the AWS SDK clients are optional peer dependencies, so installing
69
+ lambder never drags them into your tree. Add whatever the code you actually
70
+ import needs:
71
+
72
+ | What you import | What to install alongside |
73
+ | --- | --- |
74
+ | `lambder/client` (browser, shared isomorphic code) | `zod` |
75
+ | `lambder` on AWS Lambda (`nodejs18.x` and later) | `zod`. The runtime already provides the AWS SDK v3, so mark the SDK packages as dev dependencies and keep them out of the deployment package |
76
+ | `lambder` anywhere else (a long-running server, a container, local tests) | `zod`, `@aws-sdk/client-dynamodb`, `@aws-sdk/lib-dynamodb` |
77
+ | `LambderS3FileSource` | `@aws-sdk/client-s3`, loaded on first read |
78
+ | `lambder/testing` | `msw` |
79
+
80
+ The SDK and its `@smithy` tree are roughly 21MB installed, which is why they are
81
+ peers rather than dependencies: a frontend importing only `lambder/client` has
82
+ no use for any of it, and a Lambda deployment package should not ship a second
83
+ copy of what the runtime already loads. The runtime pins its own SDK version,
84
+ so if you need a specific one, install it and bundle it yourself.
85
+
86
+ ## Package entry points
87
+
88
+ The package ships three entry points; pick by where the code runs:
89
+
90
+ | Entry | Runs in | Carries |
91
+ | --- | --- | --- |
92
+ | `lambder` | Server (Lambda) | The full framework: pipeline, sessions, DDB stores, policies, plus everything from `lambder/client` |
93
+ | `lambder/client` | Browser and isomorphic shared code | `LambderCaller`, `LambderApiError`/`refuse`, the API contract and envelope types, `html`/`xml` tagged templates, `createLambderI18n` |
94
+ | `lambder/testing` | Dev and test tooling | `LambderMSW`, the MSW adapter that serves your typed contract from mock handlers |
95
+
96
+ Frontends and shared isomorphic packages should import from `lambder/client`
97
+ only; the entry's module graph contains no AWS SDK, Node built-ins, or server
98
+ pipeline, so the browser boundary is structural rather than left to
99
+ tree-shaking.
100
+
101
+ Source layout mirrors this: `src/core/` (request pipeline), `src/policies/`
102
+ (declarative rate limits, guards, idempotency), `src/session/`, `src/stores/`
103
+ (DynamoDB primitives), `src/client/`, and `src/shared/` (isomorphic modules
104
+ both entries re-export).
105
+
106
+ ## Documentation
107
+
108
+ Start with [Getting started](./docs/getting-started.md), then reach for the
109
+ guide that matches what you are building. The full index lives in
110
+ [docs/](./docs/README.md).
111
+
112
+ | Guide | Covers |
113
+ | --- | --- |
114
+ | [Getting started](./docs/getting-started.md) | The three-step path from a first API to a typed frontend call |
115
+ | [Configuration](./docs/configuration.md) | Every `initLambder().create({...})` option, in one reference |
116
+ | [Routing and actions](./docs/routing.md) | Routes, matchers, hooks, fallbacks, and non-HTTP invocations |
117
+ | [APIs and refusals](./docs/apis.md) | `addApi`/`addSessionApi`, the inferred contract, `refuse()` and `LambderApiError` |
118
+ | [Responses](./docs/responses.md) | The render context, resolver methods, cookies, compression, ETag and the size cap |
119
+ | [Sessions](./docs/sessions.md) | DynamoDB sessions, cookie scope, secrets at rest, `dataRefresh`, the controller API |
120
+ | [API policies](./docs/api-policies.md) | Declarative rate limits, guards and idempotency, and mandatory authorization declarations |
121
+ | [Frontend client](./docs/client.md) | `LambderCaller`: typed calls, failure outcomes, timeouts, guard inputs, request compression |
122
+ | [Frontend hosting](./docs/frontend-hosting.md) | File sources, `servePublicFiles`, `serveIndexHtml`, `res.templateFile` |
123
+ | [Templating](./docs/templating.md) | `html`/`xml` tagged templates and `LambderTemplatingEngine` |
124
+ | [Translations](./docs/i18n.md) | `createLambderI18n`: typed keys, extension, detection, runtime dictionaries |
125
+ | [Testing](./docs/testing.md) | `LambderMSW`: typed MSW mocking of the API contract |
126
+ | [DynamoDB tables](./docs/dynamodb-tables.md) | Table shapes, TTL and IAM for sessions, cache, rate limits and idempotency |
127
+ | [Exports reference](./docs/exports.md) | Every name the three entry points export, grouped by purpose |
128
+
129
+ ## Standalone modules
130
+
131
+ Self-contained tools that ship with the package and work with or without the
132
+ framework:
133
+
134
+ | Module | Guide | Description |
135
+ | --- | --- | --- |
136
+ | `html` / `xml` tags + `LambderTemplatingEngine` | [Templating](./docs/templating.md) | Type-safe tagged templates and a comment-only HTML template engine (build-pipeline-safe) |
137
+ | `createLambderI18n` | [Translations](./docs/i18n.md) | Typed translations with enforced/optional languages, component-level extension and auto language detection (isomorphic) |
138
+ | `LambderDdbCache` | [DynamoDB cache](./docs/ddb-cache.md) | DynamoDB-backed compressed JSON cache with lease-based single-fill and grouped keys (server-only) |
139
+ | `LambderDdbRateLimiter` | [Rate limiter](./docs/ddb-rate-limiter.md) | DynamoDB fixed-window rate limiter, atomic per window (server-only) |
140
+ | `LambderDdbIdempotency` | [Idempotency store](./docs/ddb-idempotency.md) | DynamoDB idempotency records with owner-checked claims and compressed replays (server-only) |
141
+ | `LambderMSW` | [Testing](./docs/testing.md) | Typed MSW mocking of the API contract for frontend development |
142
+
143
+ ## Versioning and changes
144
+
145
+ Released versions and what each one changed are in
146
+ [CHANGELOG.md](./CHANGELOG.md). The current major is v5, which is v4's API
147
+ plus this documentation set: upgrading from 4.x needs no code changes.
148
+ Upgrading from 3.x is covered by the breaking-changes section of the 4.0.1
149
+ entry.
150
+
151
+ ## Contributing
152
+
153
+ Contributions are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) for how to
154
+ run the tests and what a good change looks like.
155
+
156
+ ## License
157
+
158
+ MIT. See [LICENSE](./LICENSE).
@@ -4,7 +4,7 @@
4
4
  * Zero dependencies, no Node/DOM requirements (browser detection is feature-gated),
5
5
  * safe to import in both lambda backends and frontend bundles.
6
6
  *
7
- * See docs/I18N.md for the full guide.
7
+ * See docs/i18n.md for the full guide.
8
8
  */
9
9
  export interface LambderLanguageMeta {
10
10
  /** Native language name (shown in language switchers). */
@@ -4,7 +4,7 @@
4
4
  * Zero dependencies, no Node/DOM requirements (browser detection is feature-gated),
5
5
  * safe to import in both lambda backends and frontend bundles.
6
6
  *
7
- * See docs/I18N.md for the full guide.
7
+ * See docs/i18n.md for the full guide.
8
8
  */
9
9
  // ---------------------------------------------------------------------------
10
10
  // Implementation
package/package.json CHANGED
@@ -1,10 +1,40 @@
1
1
  {
2
2
  "name": "lambder",
3
- "version": "4.9.1",
4
- "description": "",
3
+ "version": "5.0.0",
4
+ "description": "Opinionated serverless web framework for TypeScript on AWS Lambda: type-safe APIs from Zod schemas, DynamoDB sessions, and declarative rate limits, authorization guards and idempotency.",
5
+ "keywords": [
6
+ "lambda",
7
+ "aws-lambda",
8
+ "serverless",
9
+ "framework",
10
+ "typescript",
11
+ "api",
12
+ "zod",
13
+ "type-safe",
14
+ "rest",
15
+ "api-gateway",
16
+ "dynamodb",
17
+ "session",
18
+ "rate-limit",
19
+ "idempotency",
20
+ "guards",
21
+ "msw",
22
+ "i18n",
23
+ "templating"
24
+ ],
25
+ "homepage": "https://github.com/nesovera/lambder#readme",
26
+ "bugs": {
27
+ "url": "https://github.com/nesovera/lambder/issues"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/nesovera/lambder.git"
32
+ },
33
+ "license": "MIT",
34
+ "author": "NesoVera",
35
+ "type": "module",
5
36
  "main": "dist/index.js",
6
37
  "types": "dist/index.d.ts",
7
- "type": "module",
8
38
  "exports": {
9
39
  ".": {
10
40
  "types": "./dist/index.d.ts",
@@ -38,6 +68,9 @@
38
68
  "files": [
39
69
  "dist"
40
70
  ],
71
+ "engines": {
72
+ "node": ">=18"
73
+ },
41
74
  "scripts": {
42
75
  "typecheck": "tsc -p tsconfig.tests.json",
43
76
  "test": "npm run typecheck && vitest run",
@@ -45,12 +78,6 @@
45
78
  "build": "tsc",
46
79
  "lint": "eslint . --ext .ts,.tsx --fix"
47
80
  },
48
- "author": "",
49
- "license": "MIT",
50
- "repository": {
51
- "type": "git",
52
- "url": "https://github.com/nesovera/lambder.git"
53
- },
54
81
  "dependencies": {
55
82
  "cookie": "^1.0.2",
56
83
  "js-cookie": "^3.0.5",