@run402/functions 2.4.0 → 2.5.1
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 +107 -0
- package/dist/auth.d.ts +46 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +50 -0
- package/dist/auth.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/routed-http.d.ts +15 -6
- package/dist/routed-http.d.ts.map +1 -1
- package/dist/routed-http.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,113 @@ if (!user) return new Response("unauthorized", { status: 401 });
|
|
|
98
98
|
|
|
99
99
|
The function's own `RUN402_PROJECT_ID` is used to scope the verification.
|
|
100
100
|
|
|
101
|
+
**Note on `user.role`:** this is the JWT system role (`anon`, `authenticated`, `project_admin`, …) — the same value PostgREST uses to evaluate RLS. It is **not** your application role from a declarative `requireRole` gate (admin/moderator/etc.). For the gate-resolved application role, use `getRole(req)` (see "Function-level auth gates" below). Don't write `getUser(req).role === "admin"` thinking you're checking the gate role — `"admin"` is not a JWT role.
|
|
102
|
+
|
|
103
|
+
## Function-level auth gates
|
|
104
|
+
|
|
105
|
+
A function can declare auth requirements directly on its `FunctionSpec`. When you set `requireAuth: true` or `requireRole: { ... }`, the gateway enforces them **before** invoking your function — unauthorized callers get `401` / `403` without your code running, and the gateway injects the resolved identity into request headers your function can trust.
|
|
106
|
+
|
|
107
|
+
This lets you delete the hand-rolled "fetch JWT, query members table, check role, return 403" boilerplate from every privileged function. Declare the gate in your `FunctionSpec`; read the resolved identity with `getUserId(req)` and `getRole(req)`.
|
|
108
|
+
|
|
109
|
+
### Declaring a gate (deploy spec)
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { run402 } from "@run402/sdk/node";
|
|
113
|
+
|
|
114
|
+
const r = run402();
|
|
115
|
+
await r.project(projectId).apply({
|
|
116
|
+
functions: {
|
|
117
|
+
patch: {
|
|
118
|
+
set: {
|
|
119
|
+
// 1. Authentication only — any valid JWT for this project passes.
|
|
120
|
+
"list-my-items": {
|
|
121
|
+
source: { sha256, size },
|
|
122
|
+
requireAuth: true,
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
// 2. Authentication + role check against your members table.
|
|
126
|
+
"delete-content": {
|
|
127
|
+
source: { sha256, size },
|
|
128
|
+
requireRole: {
|
|
129
|
+
table: "members", // project-schema table
|
|
130
|
+
idColumn: "user_id", // FK to the user.id from the JWT
|
|
131
|
+
roleColumn: "role", // column holding the role string
|
|
132
|
+
allowed: ["admin"], // case-sensitive byte-equality allowlist
|
|
133
|
+
cacheTtl: 60, // optional, seconds, default 60, max 600, 0 disables
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
// 3. Multi-role — any role in `allowed` passes the gate.
|
|
138
|
+
"moderate-content": {
|
|
139
|
+
source: { sha256, size },
|
|
140
|
+
requireRole: {
|
|
141
|
+
table: "members",
|
|
142
|
+
idColumn: "user_id",
|
|
143
|
+
roleColumn: "role",
|
|
144
|
+
allowed: ["admin", "moderator"],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`requireAuth` and `requireRole` are independent. `requireRole` on its own implies authentication (no valid JWT → 401), then runs the role lookup. `requireAuth: true` alone does a session check with no DB lookup. Set neither to opt out of platform auth (your function owns the check, as today).
|
|
154
|
+
|
|
155
|
+
**Single role-table per release:** all `requireRole` blocks in a single release must share the same `(table, idColumn, roleColumn)` triple. Different `allowed` sets are fine; different tables are not. The gateway rejects conflicting triples at plan time with `INVALID_SPEC`.
|
|
156
|
+
|
|
157
|
+
### Reading the gate result inside your function
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { getUserId, getRole } from "@run402/functions";
|
|
161
|
+
|
|
162
|
+
export default async (req: Request): Promise<Response> => {
|
|
163
|
+
const userId = getUserId(req); // string | null
|
|
164
|
+
const role = getRole(req); // string | null
|
|
165
|
+
|
|
166
|
+
// For a gated function reached through the gateway, both are guaranteed:
|
|
167
|
+
// - getUserId(req) is non-null when requireAuth OR requireRole is on.
|
|
168
|
+
// - getRole(req) is non-null when requireRole is on (and is one of `allowed`).
|
|
169
|
+
// The null case covers local invokes / direct Lambda tests / ungated functions.
|
|
170
|
+
|
|
171
|
+
if (role === "admin") {
|
|
172
|
+
// Privileged path — the gate already verified.
|
|
173
|
+
} else {
|
|
174
|
+
// role === "moderator" (the only other value `allowed` permits).
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return Response.json({ ok: true, actor: userId, role });
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The two headers (`x-run402-user-id`, `x-run402-user-role`) are injected by the gateway after the gate passes, and inbound `x-run402-*` headers from the browser are stripped before injection — so the values are trustworthy without any further verification.
|
|
182
|
+
|
|
183
|
+
### Direct vs routed invocation
|
|
184
|
+
|
|
185
|
+
The gate applies to **both** routed (browser via `/your/route`) and direct (`POST /functions/v1/:name` with an API key plus a user JWT) invocation. Direct invocation still requires the project API key at the edge; the gate runs after API-key authentication, against the user JWT.
|
|
186
|
+
|
|
187
|
+
### Deploy-time validation
|
|
188
|
+
|
|
189
|
+
If a `requireRole` block references a table or column that doesn't exist in the project schema at activation time, the deploy fails with `DEPLOY_INVALID_ROLE_GATE` (HTTP 422) **before** flipping the live release. Schema-qualified identifiers (`public.members`), empty `allowed`, and out-of-range `cacheTtl` are rejected earlier at plan time with `INVALID_SPEC` (HTTP 400).
|
|
190
|
+
|
|
191
|
+
### Caching and staleness
|
|
192
|
+
|
|
193
|
+
Role lookups are cached per `(projectId, userId)` for `cacheTtl` seconds (default 60, max 600). **A demoted user keeps the cached role until the TTL expires** — for high-stakes operations where instant revocation matters, set `cacheTtl: 0` to issue a fresh lookup on every request. The cache is bypassed when no `requireRole` gate runs.
|
|
194
|
+
|
|
195
|
+
### Relationship to `getUser`
|
|
196
|
+
|
|
197
|
+
`getUser(req)` decodes the JWT and gives you `{ id, role, email }` where `role` is the JWT system role. The gate-injected headers give you the gate-resolved identity:
|
|
198
|
+
|
|
199
|
+
| Helper | Source | Role meaning |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `getUser(req).id` | JWT `sub` (decoded in-function) | — |
|
|
202
|
+
| `getUser(req).role` | JWT `role` claim | System role (`anon`, `authenticated`, `project_admin`) |
|
|
203
|
+
| `getUserId(req)` | `x-run402-user-id` header (injected by gateway) | — |
|
|
204
|
+
| `getRole(req)` | `x-run402-user-role` header (injected by gateway) | Application role from your `members` table |
|
|
205
|
+
|
|
206
|
+
For a gated function reached through the gateway, `getUserId(req)` and `getUser(req).id` will agree. The gate-side helpers skip the JWT decode (the gateway already did it), so they're slightly cheaper and stringly-typed against the trusted headers; use them when the gate guarantees the identity.
|
|
207
|
+
|
|
101
208
|
## `email.send(...)` — send mail from the project's mailbox
|
|
102
209
|
|
|
103
210
|
Auto-discovers the project's mailbox on first call (the project must already have one — create it once with `run402 email create <slug>` or the `create_mailbox` MCP tool). After that the mailbox id is cached for the function's lifetime.
|
package/dist/auth.d.ts
CHANGED
|
@@ -6,6 +6,52 @@ export interface User {
|
|
|
6
6
|
/**
|
|
7
7
|
* Verify the caller's JWT and return user identity.
|
|
8
8
|
* Returns { id, role, email } or null if unauthenticated/invalid.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: `role` here is the JWT claim (`anon`, `authenticated`,
|
|
11
|
+
* `project_admin`, …) — the PostgREST/RLS system role, NOT the
|
|
12
|
+
* application role from a declarative `requireRole` gate. For the
|
|
13
|
+
* gate-resolved application role, use {@link getRole}.
|
|
9
14
|
*/
|
|
10
15
|
export declare function getUser(req: Request): User | null;
|
|
16
|
+
/**
|
|
17
|
+
* Read the gate-resolved user id from the request.
|
|
18
|
+
*
|
|
19
|
+
* Returns the value of the `x-run402-user-id` request header, which the
|
|
20
|
+
* Run402 gateway injects when a function-level `requireAuth` or
|
|
21
|
+
* `requireRole` gate evaluates successfully on this dispatch. Inbound
|
|
22
|
+
* `x-run402-*` headers from the browser are stripped by the gateway
|
|
23
|
+
* before injection, so the value is trustworthy.
|
|
24
|
+
*
|
|
25
|
+
* Returns `null` when the function has no gate declared, or when the
|
|
26
|
+
* function is invoked outside the gateway (local test harness, direct
|
|
27
|
+
* Lambda invoke). For gated functions reached through the gateway, the
|
|
28
|
+
* value is non-null by construction.
|
|
29
|
+
*
|
|
30
|
+
* This is the gate-side companion to {@link getUser}, which decodes
|
|
31
|
+
* the JWT directly. The two layers are independent: a function with
|
|
32
|
+
* only `requireRole` runs the role lookup against the project's
|
|
33
|
+
* `members` table via gateway-side RLS-bypass; user code does not
|
|
34
|
+
* need to re-decode the JWT.
|
|
35
|
+
*/
|
|
36
|
+
export declare function getUserId(req: Request): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Read the gate-resolved application role from the request.
|
|
39
|
+
*
|
|
40
|
+
* Returns the value of the `x-run402-user-role` request header, which
|
|
41
|
+
* the Run402 gateway injects when a function-level `requireRole` gate
|
|
42
|
+
* evaluates successfully on this dispatch. The value is the role string
|
|
43
|
+
* from the project-schema `members.role` (or whatever
|
|
44
|
+
* `(table, idColumn, roleColumn)` triple the gate declared), already
|
|
45
|
+
* confirmed to be in `requireRole.allowed`. Inbound `x-run402-*`
|
|
46
|
+
* headers are stripped, so the value is trustworthy.
|
|
47
|
+
*
|
|
48
|
+
* Returns `null` when no `requireRole` gate ran on this dispatch
|
|
49
|
+
* (function has only `requireAuth`, no gate at all, or is invoked
|
|
50
|
+
* outside the gateway).
|
|
51
|
+
*
|
|
52
|
+
* This is the application role, NOT the JWT role from
|
|
53
|
+
* {@link getUser}. The two are independent — see the JSDoc on
|
|
54
|
+
* `getUser` for the distinction.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getRole(req: Request): string | null;
|
|
11
57
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAmBjD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAErD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEnD"}
|
package/dist/auth.js
CHANGED
|
@@ -3,6 +3,11 @@ import { config } from "./config.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Verify the caller's JWT and return user identity.
|
|
5
5
|
* Returns { id, role, email } or null if unauthenticated/invalid.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: `role` here is the JWT claim (`anon`, `authenticated`,
|
|
8
|
+
* `project_admin`, …) — the PostgREST/RLS system role, NOT the
|
|
9
|
+
* application role from a declarative `requireRole` gate. For the
|
|
10
|
+
* gate-resolved application role, use {@link getRole}.
|
|
6
11
|
*/
|
|
7
12
|
export function getUser(req) {
|
|
8
13
|
const authHeader = typeof req.headers.get === "function"
|
|
@@ -21,4 +26,49 @@ export function getUser(req) {
|
|
|
21
26
|
return null;
|
|
22
27
|
}
|
|
23
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Read the gate-resolved user id from the request.
|
|
31
|
+
*
|
|
32
|
+
* Returns the value of the `x-run402-user-id` request header, which the
|
|
33
|
+
* Run402 gateway injects when a function-level `requireAuth` or
|
|
34
|
+
* `requireRole` gate evaluates successfully on this dispatch. Inbound
|
|
35
|
+
* `x-run402-*` headers from the browser are stripped by the gateway
|
|
36
|
+
* before injection, so the value is trustworthy.
|
|
37
|
+
*
|
|
38
|
+
* Returns `null` when the function has no gate declared, or when the
|
|
39
|
+
* function is invoked outside the gateway (local test harness, direct
|
|
40
|
+
* Lambda invoke). For gated functions reached through the gateway, the
|
|
41
|
+
* value is non-null by construction.
|
|
42
|
+
*
|
|
43
|
+
* This is the gate-side companion to {@link getUser}, which decodes
|
|
44
|
+
* the JWT directly. The two layers are independent: a function with
|
|
45
|
+
* only `requireRole` runs the role lookup against the project's
|
|
46
|
+
* `members` table via gateway-side RLS-bypass; user code does not
|
|
47
|
+
* need to re-decode the JWT.
|
|
48
|
+
*/
|
|
49
|
+
export function getUserId(req) {
|
|
50
|
+
return req.headers.get("x-run402-user-id");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Read the gate-resolved application role from the request.
|
|
54
|
+
*
|
|
55
|
+
* Returns the value of the `x-run402-user-role` request header, which
|
|
56
|
+
* the Run402 gateway injects when a function-level `requireRole` gate
|
|
57
|
+
* evaluates successfully on this dispatch. The value is the role string
|
|
58
|
+
* from the project-schema `members.role` (or whatever
|
|
59
|
+
* `(table, idColumn, roleColumn)` triple the gate declared), already
|
|
60
|
+
* confirmed to be in `requireRole.allowed`. Inbound `x-run402-*`
|
|
61
|
+
* headers are stripped, so the value is trustworthy.
|
|
62
|
+
*
|
|
63
|
+
* Returns `null` when no `requireRole` gate ran on this dispatch
|
|
64
|
+
* (function has only `requireAuth`, no gate at all, or is invoked
|
|
65
|
+
* outside the gateway).
|
|
66
|
+
*
|
|
67
|
+
* This is the application role, NOT the JWT role from
|
|
68
|
+
* {@link getUser}. The two are independent — see the JSDoc on
|
|
69
|
+
* `getUser` for the distinction.
|
|
70
|
+
*/
|
|
71
|
+
export function getRole(req) {
|
|
72
|
+
return req.headers.get("x-run402-user-role");
|
|
73
|
+
}
|
|
24
74
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAC,GAAY;IAClC,MAAM,UAAU,GACd,OAAQ,GAAG,CAAC,OAA6C,CAAC,GAAG,KAAK,UAAU;QAC1E,CAAC,CAAE,GAAG,CAAC,OAAmB,CAAC,GAAG,CAAC,eAAe,CAAC;QAC/C,CAAC,CAAE,GAAG,CAAC,OAAyD,EAAE,aAAa,CAAC;IACpF,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAKlD,CAAC;QACF,IAAI,OAAO,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAC1D,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,OAAO,CAAC,GAAY;IAClC,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { db, adminDb, QueryBuilder } from "./db.js";
|
|
2
|
-
export { getUser } from "./auth.js";
|
|
2
|
+
export { getUser, getUserId, getRole } from "./auth.js";
|
|
3
3
|
export type { User } from "./auth.js";
|
|
4
4
|
export { email } from "./email.js";
|
|
5
5
|
export type { EmailSendOptions, EmailRawOptions, EmailTemplateOptions, EmailSendResult } from "./email.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACxD,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,YAAY,EAEZ,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAS7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAgBrC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/routed-http.d.ts
CHANGED
|
@@ -34,14 +34,23 @@ export interface RoutedHttpRequestV1 {
|
|
|
34
34
|
/** Capability `routed-locale-context`. Canonical locale tag (byte-
|
|
35
35
|
* identical to an entry in the active release's `i18n.locales[]`)
|
|
36
36
|
* when the release declares an i18n slice, `null` otherwise.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* `
|
|
37
|
+
*
|
|
38
|
+
* **User functions read this via REQUEST HEADERS, not via `event.context`.**
|
|
39
|
+
* The bundled `@run402/functions` runtime translates the routed envelope
|
|
40
|
+
* into a Web-standard `Request` before calling user code, dropping
|
|
41
|
+
* `event.context`. The gateway also adds `x-run402-locale` to the
|
|
42
|
+
* forwarded request headers, alongside `x-run402-project-id` etc.:
|
|
43
|
+
* `const locale = req.headers.get('x-run402-locale');`
|
|
44
|
+
*
|
|
45
|
+
* This `context.locale` field is preserved for raw-envelope consumers
|
|
46
|
+
* (custom Lambda runtimes that bypass `buildEntryWrapper`). OPTIONAL on
|
|
47
|
+
* the type: gateways predating 2.3.0 / releases without `spec.i18n`
|
|
48
|
+
* omit this field entirely. Read as `event.context.locale ?? null`. */
|
|
41
49
|
locale?: string | null;
|
|
42
50
|
/** Echoed verbatim from the active release's `i18n.defaultLocale`,
|
|
43
|
-
* `null` when the release has no i18n slice. Same
|
|
44
|
-
*
|
|
51
|
+
* `null` when the release has no i18n slice. Same access rules as
|
|
52
|
+
* `locale`: user functions read `req.headers.get('x-run402-default-locale')`;
|
|
53
|
+
* raw-envelope consumers read `event.context.defaultLocale ?? null`. */
|
|
45
54
|
defaultLocale?: string | null;
|
|
46
55
|
};
|
|
47
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routed-http.d.ts","sourceRoot":"","sources":["../src/routed-http.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,uBAAuB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAChC,IAAI,EAAE,IAAI,GAAG;QACX,QAAQ,EAAE,QAAQ,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,EAAE;QACP,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAC;QAC9B,WAAW,EAAE;YAAE,IAAI,EAAE,UAAU,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAChD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB
|
|
1
|
+
{"version":3,"file":"routed-http.d.ts","sourceRoot":"","sources":["../src/routed-http.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,oBAAoB,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,uBAAuB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAChC,IAAI,EAAE,IAAI,GAAG;QACX,QAAQ,EAAE,QAAQ,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,EAAE;QACP,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,OAAO,GAAG,QAAQ,CAAC;QAC9B,WAAW,EAAE;YAAE,IAAI,EAAE,UAAU,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAChD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB;;;;;;;;;;;;;;gFAcwE;QACxE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB;;;iFAGyE;QACzE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,IAAI,GAAG;QACZ,QAAQ,EAAE,QAAQ,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,sBAA2B,GAChC,oBAAoB,CAMtB;AAED,wBAAgB,IAAI,CAClB,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,sBAA2B,GAChC,oBAAoB,CAMtB;AAED,wBAAgB,KAAK,CACnB,KAAK,EAAE,UAAU,EACjB,IAAI,GAAE,sBAA2B,GAChC,oBAAoB,CAEtB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAEtE;AAED,eAAO,MAAM,UAAU;;;;;CAKtB,CAAC"}
|
package/dist/routed-http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routed-http.js","sourceRoot":"","sources":["../src/routed-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"routed-http.js","sourceRoot":"","sources":["../src/routed-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAwErC,MAAM,UAAU,IAAI,CAClB,IAAY,EACZ,OAA+B,EAAE;IAEjC,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;QACzC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,sBAAsB,CAAC,IAAI,CAAC,OAAO,EAAE,2BAA2B,CAAC;QAC1E,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,KAAc,EACd,OAA+B,EAAE;IAEjC,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAAE;QAC1D,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE,sBAAsB,CAAC,IAAI,CAAC,OAAO,EAAE,iCAAiC,CAAC;QAChF,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,KAAiB,EACjB,OAA+B,EAAE;IAEjC,OAAO,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,uBAAuB,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,SAAS;CACV,CAAC;AAEF,SAAS,QAAQ,CACf,KAAiB,EACjB,IAA4B;IAE5B,MAAM,SAAS,GAAG,KAAK,YAAY,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAyB;QACrC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG;QAC1B,IAAI,EAAE;YACJ,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAClC,IAAI,EAAE,SAAS,CAAC,UAAU;SAC3B;KACF,CAAC;IACF,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAChE,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAChE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAyC,EACzC,WAAmB;IAEnB,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,MAAM,cAAc,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,CAAC;IACnF,IAAI,CAAC,cAAc;QAAE,GAAG,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;IAChE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC;AACrD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@run402/functions",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "In-function helper library for Run402 serverless functions — db, adminDb, getUser, email, ai, assets. Auto-bundled into deployed functions; also installable for local TypeScript autocomplete.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|