@beignet/core 0.0.3 → 0.0.4
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/CHANGELOG.md +157 -0
- package/README.md +785 -43
- package/dist/application/index.d.ts +28 -2
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +140 -12
- package/dist/application/index.js.map +1 -1
- package/dist/client/client.d.ts +2 -2
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +136 -48
- package/dist/client/client.js.map +1 -1
- package/dist/client/error-messages.d.ts +14 -0
- package/dist/client/error-messages.d.ts.map +1 -0
- package/dist/client/error-messages.js +23 -0
- package/dist/client/error-messages.js.map +1 -0
- package/dist/client/index.d.ts +8 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +35 -5
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client-only.d.ts +8 -0
- package/dist/client-only.d.ts.map +1 -0
- package/dist/client-only.js +8 -0
- package/dist/client-only.js.map +1 -0
- package/dist/config/index.d.ts +5 -5
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -2
- package/dist/config/index.js.map +1 -1
- package/dist/contracts/catalog-errors.d.ts +27 -0
- package/dist/contracts/catalog-errors.d.ts.map +1 -0
- package/dist/contracts/catalog-errors.js +69 -0
- package/dist/contracts/catalog-errors.js.map +1 -0
- package/dist/contracts/contract-builder.d.ts +15 -12
- package/dist/contracts/contract-builder.d.ts.map +1 -1
- package/dist/contracts/contract-builder.js +15 -41
- package/dist/contracts/contract-builder.js.map +1 -1
- package/dist/contracts/contract-group.d.ts +11 -8
- package/dist/contracts/contract-group.d.ts.map +1 -1
- package/dist/contracts/contract-group.js +13 -40
- package/dist/contracts/contract-group.js.map +1 -1
- package/dist/contracts/contract-like.d.ts +1 -1
- package/dist/contracts/contract-like.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +13 -9
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +9 -5
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/openapi-meta.d.ts +48 -0
- package/dist/contracts/openapi-meta.d.ts.map +1 -1
- package/dist/contracts/openapi-meta.js +3 -0
- package/dist/contracts/openapi-meta.js.map +1 -1
- package/dist/contracts/path-template.d.ts +1 -1
- package/dist/contracts/path-template.js +2 -2
- package/dist/contracts/path-template.js.map +1 -1
- package/dist/contracts/schema-shape.d.ts +37 -0
- package/dist/contracts/schema-shape.d.ts.map +1 -0
- package/dist/contracts/schema-shape.js +61 -0
- package/dist/contracts/schema-shape.js.map +1 -0
- package/dist/contracts/success-status.d.ts +32 -0
- package/dist/contracts/success-status.d.ts.map +1 -0
- package/dist/contracts/success-status.js +18 -0
- package/dist/contracts/success-status.js.map +1 -0
- package/dist/contracts/types.d.ts +25 -5
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/types.js.map +1 -1
- package/dist/contracts/utils.d.ts +1 -1
- package/dist/contracts/utils.d.ts.map +1 -1
- package/dist/contracts/utils.js +1 -1
- package/dist/contracts/utils.js.map +1 -1
- package/dist/domain/events.d.ts +1 -1
- package/dist/domain/events.d.ts.map +1 -1
- package/dist/domain/events.js +1 -1
- package/dist/domain/events.js.map +1 -1
- package/dist/domain/index.d.ts +3 -3
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +3 -3
- package/dist/domain/index.js.map +1 -1
- package/dist/errors/catalog.d.ts +9 -1
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/catalog.js +7 -1
- package/dist/errors/catalog.js.map +1 -1
- package/dist/errors/http.d.ts +10 -0
- package/dist/errors/http.d.ts.map +1 -1
- package/dist/errors/http.js +11 -1
- package/dist/errors/http.js.map +1 -1
- package/dist/errors/index.d.ts +4 -4
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +4 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/response.d.ts +4 -1
- package/dist/errors/response.d.ts.map +1 -1
- package/dist/errors/response.js.map +1 -1
- package/dist/events/index.d.ts +10 -12
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +10 -10
- package/dist/events/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +5 -3
- package/dist/idempotency/index.d.ts.map +1 -1
- package/dist/idempotency/index.js.map +1 -1
- package/dist/jobs/index.d.ts +12 -14
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +13 -13
- package/dist/jobs/index.js.map +1 -1
- package/dist/notifications/index.d.ts +14 -16
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +14 -14
- package/dist/notifications/index.js.map +1 -1
- package/dist/openapi/index.d.ts +8 -3
- package/dist/openapi/index.d.ts.map +1 -1
- package/dist/openapi/index.js +41 -29
- package/dist/openapi/index.js.map +1 -1
- package/dist/openapi/schema-introspector.d.ts +37 -0
- package/dist/openapi/schema-introspector.d.ts.map +1 -1
- package/dist/openapi/schema-introspector.js +23 -17
- package/dist/openapi/schema-introspector.js.map +1 -1
- package/dist/outbox/index.d.ts +15 -6
- package/dist/outbox/index.d.ts.map +1 -1
- package/dist/outbox/index.js +60 -16
- package/dist/outbox/index.js.map +1 -1
- package/dist/ports/audit.d.ts +56 -10
- package/dist/ports/audit.d.ts.map +1 -1
- package/dist/ports/audit.js +71 -3
- package/dist/ports/audit.js.map +1 -1
- package/dist/ports/auth.d.ts +92 -0
- package/dist/ports/auth.d.ts.map +1 -1
- package/dist/ports/auth.js +92 -0
- package/dist/ports/auth.js.map +1 -1
- package/dist/ports/events.d.ts +2 -2
- package/dist/ports/events.d.ts.map +1 -1
- package/dist/ports/index.d.ts +62 -33
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +28 -34
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/policy.d.ts +32 -3
- package/dist/ports/policy.d.ts.map +1 -1
- package/dist/ports/policy.js +13 -2
- package/dist/ports/policy.js.map +1 -1
- package/dist/ports/testing.d.ts +1030 -2
- package/dist/ports/testing.d.ts.map +1 -1
- package/dist/ports/testing.js +1031 -1
- package/dist/ports/testing.js.map +1 -1
- package/dist/ports/unbound.d.ts +21 -0
- package/dist/ports/unbound.d.ts.map +1 -0
- package/dist/ports/unbound.js +57 -0
- package/dist/ports/unbound.js.map +1 -0
- package/dist/ports/unit-of-work.d.ts +1 -1
- package/dist/ports/unit-of-work.d.ts.map +1 -1
- package/dist/ports/unit-of-work.js +1 -1
- package/dist/ports/unit-of-work.js.map +1 -1
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +3 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/instrumentation.d.ts +45 -4
- package/dist/providers/instrumentation.d.ts.map +1 -1
- package/dist/providers/instrumentation.js +25 -6
- package/dist/providers/instrumentation.js.map +1 -1
- package/dist/providers/metadata.d.ts +39 -0
- package/dist/providers/metadata.d.ts.map +1 -0
- package/dist/providers/metadata.js +169 -0
- package/dist/providers/metadata.js.map +1 -0
- package/dist/providers/provider.d.ts +114 -9
- package/dist/providers/provider.d.ts.map +1 -1
- package/dist/providers/provider.js +3 -20
- package/dist/providers/provider.js.map +1 -1
- package/dist/schedules/index.d.ts +94 -13
- package/dist/schedules/index.d.ts.map +1 -1
- package/dist/schedules/index.js +66 -12
- package/dist/schedules/index.js.map +1 -1
- package/dist/server/audit-context.d.ts +29 -0
- package/dist/server/audit-context.d.ts.map +1 -0
- package/dist/server/audit-context.js +44 -0
- package/dist/server/audit-context.js.map +1 -0
- package/dist/server/context.d.ts +141 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +39 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/contract-like.d.ts +1 -1
- package/dist/server/contract-like.d.ts.map +1 -1
- package/dist/server/contract-like.js +1 -1
- package/dist/server/contract-like.js.map +1 -1
- package/dist/server/health.d.ts +2 -2
- package/dist/server/health.d.ts.map +1 -1
- package/dist/server/hooks/auth.d.ts +49 -10
- package/dist/server/hooks/auth.d.ts.map +1 -1
- package/dist/server/hooks/auth.js +77 -37
- package/dist/server/hooks/auth.js.map +1 -1
- package/dist/server/hooks/cors.d.ts +1 -1
- package/dist/server/hooks/cors.d.ts.map +1 -1
- package/dist/server/hooks/errors.d.ts +2 -2
- package/dist/server/hooks/errors.d.ts.map +1 -1
- package/dist/server/hooks/errors.js +2 -2
- package/dist/server/hooks/errors.js.map +1 -1
- package/dist/server/hooks/idempotency.d.ts +78 -0
- package/dist/server/hooks/idempotency.d.ts.map +1 -0
- package/dist/server/hooks/idempotency.js +154 -0
- package/dist/server/hooks/idempotency.js.map +1 -0
- package/dist/server/hooks/index.d.ts +8 -7
- package/dist/server/hooks/index.d.ts.map +1 -1
- package/dist/server/hooks/index.js +6 -5
- package/dist/server/hooks/index.js.map +1 -1
- package/dist/server/hooks/logging.d.ts +2 -2
- package/dist/server/hooks/logging.d.ts.map +1 -1
- package/dist/server/hooks/logging.js +1 -1
- package/dist/server/hooks/logging.js.map +1 -1
- package/dist/server/hooks/rate-limit.d.ts +25 -7
- package/dist/server/hooks/rate-limit.d.ts.map +1 -1
- package/dist/server/hooks/rate-limit.js +47 -12
- package/dist/server/hooks/rate-limit.js.map +1 -1
- package/dist/server/hooks.d.ts +1 -1
- package/dist/server/hooks.d.ts.map +1 -1
- package/dist/server/hooks.js +1 -1
- package/dist/server/hooks.js.map +1 -1
- package/dist/server/http.d.ts +61 -35
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +1 -20
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.d.ts +36 -12
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +24 -8
- package/dist/server/index.js.map +1 -1
- package/dist/server/instrumentation.d.ts +108 -0
- package/dist/server/instrumentation.d.ts.map +1 -0
- package/dist/server/instrumentation.js +297 -0
- package/dist/server/instrumentation.js.map +1 -0
- package/dist/server/openapi.d.ts +3 -3
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/openapi.js +1 -1
- package/dist/server/openapi.js.map +1 -1
- package/dist/server/providers/index.d.ts +3 -3
- package/dist/server/providers/index.d.ts.map +1 -1
- package/dist/server/providers/index.js +3 -3
- package/dist/server/providers/index.js.map +1 -1
- package/dist/server/providers/loadProviderConfig.d.ts +2 -2
- package/dist/server/providers/loadProviderConfig.d.ts.map +1 -1
- package/dist/server/providers/loadProviderConfig.js +2 -2
- package/dist/server/providers/loadProviderConfig.js.map +1 -1
- package/dist/server/request-context.d.ts +67 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/request-context.js +79 -0
- package/dist/server/request-context.js.map +1 -0
- package/dist/server/server-context.d.ts +38 -0
- package/dist/server/server-context.d.ts.map +1 -0
- package/dist/server/server-context.js +38 -0
- package/dist/server/server-context.js.map +1 -0
- package/dist/server/server.d.ts +105 -33
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +434 -118
- package/dist/server/server.js.map +1 -1
- package/dist/server/types.d.ts +2 -2
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +2 -2
- package/dist/server/types.js.map +1 -1
- package/dist/server/use-case-route.d.ts +263 -0
- package/dist/server/use-case-route.d.ts.map +1 -0
- package/dist/server/use-case-route.js +77 -0
- package/dist/server/use-case-route.js.map +1 -0
- package/dist/server-only.d.ts +8 -0
- package/dist/server-only.d.ts.map +1 -0
- package/dist/server-only.js +8 -0
- package/dist/server-only.js.map +1 -0
- package/dist/tasks/index.d.ts +139 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +98 -0
- package/dist/tasks/index.js.map +1 -0
- package/dist/testing/index.d.ts +607 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +426 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/tracing/index.d.ts +89 -0
- package/dist/tracing/index.d.ts.map +1 -0
- package/dist/tracing/index.js +101 -0
- package/dist/tracing/index.js.map +1 -0
- package/dist/uploads/client.d.ts +1 -1
- package/dist/uploads/client.d.ts.map +1 -1
- package/dist/uploads/index.d.ts +2 -2
- package/dist/uploads/index.d.ts.map +1 -1
- package/dist/uploads/index.js +1 -1
- package/dist/uploads/index.js.map +1 -1
- package/package.json +24 -2
- package/src/application/index.ts +193 -10
- package/src/client/client.ts +148 -150
- package/src/client/error-messages.ts +35 -0
- package/src/client/index.ts +12 -4
- package/src/client/types.ts +44 -5
- package/src/client-only.ts +7 -0
- package/src/config/index.ts +6 -6
- package/src/contracts/catalog-errors.ts +115 -0
- package/src/contracts/contract-builder.ts +39 -76
- package/src/contracts/contract-group.ts +33 -68
- package/src/contracts/contract-like.ts +1 -1
- package/src/contracts/index.ts +24 -11
- package/src/contracts/openapi-meta.ts +55 -0
- package/src/contracts/path-template.ts +2 -2
- package/src/contracts/schema-shape.ts +75 -0
- package/src/contracts/success-status.ts +68 -0
- package/src/contracts/types.ts +32 -5
- package/src/contracts/utils.ts +5 -2
- package/src/domain/events.ts +6 -2
- package/src/domain/index.ts +3 -3
- package/src/errors/catalog.ts +9 -1
- package/src/errors/http.ts +11 -1
- package/src/errors/index.ts +4 -4
- package/src/errors/response.ts +4 -1
- package/src/events/index.ts +12 -26
- package/src/idempotency/index.ts +5 -3
- package/src/jobs/index.ts +14 -24
- package/src/notifications/index.ts +17 -27
- package/src/openapi/index.ts +73 -38
- package/src/openapi/schema-introspector.ts +68 -17
- package/src/outbox/index.ts +84 -19
- package/src/ports/audit.ts +120 -11
- package/src/ports/auth.ts +132 -0
- package/src/ports/events.ts +2 -2
- package/src/ports/index.ts +104 -35
- package/src/ports/policy.ts +50 -3
- package/src/ports/testing.ts +2220 -33
- package/src/ports/unbound.ts +64 -0
- package/src/ports/unit-of-work.ts +6 -2
- package/src/providers/index.ts +16 -3
- package/src/providers/instrumentation.ts +86 -7
- package/src/providers/metadata.ts +234 -0
- package/src/providers/provider.ts +168 -9
- package/src/schedules/index.ts +173 -23
- package/src/server/audit-context.ts +45 -0
- package/src/server/context.ts +224 -0
- package/src/server/contract-like.ts +1 -1
- package/src/server/health.ts +2 -2
- package/src/server/hooks/auth.ts +141 -51
- package/src/server/hooks/cors.ts +1 -1
- package/src/server/hooks/errors.ts +7 -4
- package/src/server/hooks/idempotency.ts +263 -0
- package/src/server/hooks/index.ts +14 -7
- package/src/server/hooks/logging.ts +3 -3
- package/src/server/hooks/rate-limit.ts +85 -17
- package/src/server/hooks.ts +1 -1
- package/src/server/http.ts +78 -51
- package/src/server/index.ts +62 -12
- package/src/server/instrumentation.ts +470 -0
- package/src/server/openapi.ts +4 -4
- package/src/server/providers/index.ts +6 -3
- package/src/server/providers/loadProviderConfig.ts +4 -4
- package/src/server/request-context.ts +116 -0
- package/src/server/server-context.ts +44 -0
- package/src/server/server.ts +886 -238
- package/src/server/types.ts +2 -2
- package/src/server/use-case-route.ts +430 -0
- package/src/server-only.ts +7 -0
- package/src/tasks/index.ts +275 -0
- package/src/testing/index.ts +1142 -6
- package/src/tracing/index.ts +176 -0
- package/src/uploads/client.ts +1 -1
- package/src/uploads/index.ts +7 -3
- package/dist/ports/mailer.d.ts +0 -6
- package/dist/ports/mailer.d.ts.map +0 -1
- package/dist/ports/mailer.js +0 -2
- package/dist/ports/mailer.js.map +0 -1
- package/dist/ports/schedules.d.ts +0 -9
- package/dist/ports/schedules.d.ts.map +0 -1
- package/dist/ports/schedules.js +0 -2
- package/dist/ports/schedules.js.map +0 -1
|
@@ -1,50 +1,90 @@
|
|
|
1
|
-
import { AuthUnauthorizedError } from "../../ports";
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { AuthUnauthorizedError } from "../../ports/index.js";
|
|
2
|
+
function rawRequestHeaders(req) {
|
|
3
|
+
const record = {};
|
|
4
|
+
req.headers.forEach((value, key) => {
|
|
5
|
+
record[key.toLowerCase()] = value;
|
|
6
|
+
});
|
|
7
|
+
return record;
|
|
8
|
+
}
|
|
9
|
+
async function parseAuthHeaders(schema, req) {
|
|
10
|
+
const raw = rawRequestHeaders(req);
|
|
11
|
+
if (!schema) {
|
|
12
|
+
return { ok: true, headers: raw };
|
|
13
|
+
}
|
|
14
|
+
const result = await schema["~standard"].validate(raw);
|
|
15
|
+
if (result.issues) {
|
|
16
|
+
return { ok: false };
|
|
17
|
+
}
|
|
18
|
+
return { ok: true, headers: result.value };
|
|
12
19
|
}
|
|
13
20
|
/**
|
|
14
21
|
* Create route-scoped authentication hooks.
|
|
15
22
|
*
|
|
23
|
+
* The outer call binds the app context; the inner call takes auth options and
|
|
24
|
+
* infers the added context from `resolve`:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* const auth = createAuthHooks<AppContext>()({
|
|
28
|
+
* resolve: ({ ctx }) => (ctx.auth ? { user: ctx.auth.user } : null),
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
16
32
|
* Use `auth.required()` on routes that require an authenticated actor and
|
|
17
33
|
* `auth.optional()` where handlers can use auth when present. The returned
|
|
18
34
|
* route hooks enrich handler `ctx`; business authorization still belongs in
|
|
19
35
|
* feature policies or use cases.
|
|
20
36
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
37
|
+
* Declare a `headers` schema when credentials live in request headers. The
|
|
38
|
+
* hook validates the raw lowercase header record itself, so `resolve` receives
|
|
39
|
+
* typed headers without contract casts and a `required()` hook rejects
|
|
40
|
+
* missing or malformed credentials with a framework-owned 401.
|
|
41
|
+
*
|
|
42
|
+
* @returns A function that takes auth options and returns public, optional,
|
|
43
|
+
* and required route-hook factories.
|
|
23
44
|
*/
|
|
24
|
-
export function createAuthHooks(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
export function createAuthHooks() {
|
|
46
|
+
return (options) => {
|
|
47
|
+
const name = options.name ?? "auth";
|
|
48
|
+
const toAuthArgs = (args, headers) => ({
|
|
49
|
+
req: args.req,
|
|
50
|
+
ctx: args.ctx,
|
|
51
|
+
contract: args.contract,
|
|
52
|
+
path: args.path,
|
|
53
|
+
query: args.query,
|
|
54
|
+
headers,
|
|
55
|
+
body: args.body,
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
public: () => ({
|
|
59
|
+
name: `${name}.public`,
|
|
60
|
+
resolve: () => undefined,
|
|
61
|
+
}),
|
|
62
|
+
optional: () => ({
|
|
63
|
+
name: `${name}.optional`,
|
|
64
|
+
resolve: async (args) => {
|
|
65
|
+
const parsed = await parseAuthHeaders(options.headers, args.req);
|
|
66
|
+
if (!parsed.ok) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const additions = await options.resolve(toAuthArgs(args, parsed.headers));
|
|
70
|
+
return additions ?? undefined;
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
required: () => ({
|
|
74
|
+
name: `${name}.required`,
|
|
75
|
+
resolve: async (args) => {
|
|
76
|
+
const parsed = await parseAuthHeaders(options.headers, args.req);
|
|
77
|
+
if (!parsed.ok) {
|
|
78
|
+
throw new AuthUnauthorizedError();
|
|
79
|
+
}
|
|
80
|
+
const additions = await options.resolve(toAuthArgs(args, parsed.headers));
|
|
81
|
+
if (!additions) {
|
|
82
|
+
throw new AuthUnauthorizedError();
|
|
83
|
+
}
|
|
84
|
+
return additions;
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
48
88
|
};
|
|
49
89
|
}
|
|
50
90
|
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/server/hooks/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/server/hooks/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/cors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/cors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IACzB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAmBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,GAAG,EAAE,eAAe,EACpB,UAAU,EAAE,UAAU,GACrB,IAAI,CA4BN;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAsBxE"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Framework-agnostic error mapping utilities for @beignet/core/server
|
|
3
3
|
*/
|
|
4
|
-
import type { AppEnvironment } from "../health";
|
|
4
|
+
import type { AppEnvironment } from "../health.js";
|
|
5
5
|
/**
|
|
6
6
|
* Re-export `AppEnvironment` for convenience.
|
|
7
7
|
*/
|
|
8
|
-
export type { AppEnvironment } from "../health";
|
|
8
|
+
export type { AppEnvironment } from "../health.js";
|
|
9
9
|
/**
|
|
10
10
|
* Framework-neutral response produced by an error mapper.
|
|
11
11
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD;;GAEG;AACH,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,GAAG;IACrC,oCAAoC;IACpC,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,kBAAkB,CAAC;IAEpE,6EAA6E;IAC7E,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,+BAA+B;IAC/B,GAAG,CAAC,EAAE,cAAc,CAAC;CACtB;AA0BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAC3C,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,GAC9B,kBAAkB,CAwBpB"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Framework-agnostic error mapping utilities for @beignet/core/server
|
|
3
3
|
*/
|
|
4
|
-
import { createErrorResponseBody } from "../../errors";
|
|
5
|
-
import { getRequestIdFromContext } from "./utils";
|
|
4
|
+
import { createErrorResponseBody, } from "../../errors/index.js";
|
|
5
|
+
import { getRequestIdFromContext } from "./utils.js";
|
|
6
6
|
/**
|
|
7
7
|
* Create default error response body
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/server/hooks/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/server/hooks/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,uBAAuB,GAExB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAuCrD;;GAEG;AACH,SAAS,sBAAsB,CAC7B,GAAY,EACZ,YAAqB,EACrB,SAAkB;IAElB,OAAO,uBAAuB,CAAC;QAC7B,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,uBAAuB;QAChC,SAAS;QACT,OAAO,EACL,YAAY,IAAI,GAAG,YAAY,KAAK;YAClC,CAAC,CAAC;gBACE,KAAK,EAAE;oBACL,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,KAAK,EAAE,GAAG,CAAC,KAAK;iBACjB;aACF;YACH,CAAC,CAAC,SAAS;KAChB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,UAAU,yBAAyB,CACvC,GAAY,EACZ,GAAQ,EACR,MAA+B;IAE/B,6CAA6C;IAC7C,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,+CAA+C;QACjD,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,MAAM,YAAY,GAChB,MAAM,CAAC,sBAAsB;QAC7B,CAAC,MAAM,CAAC,GAAG,KAAK,aAAa,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;IAE1D,yBAAyB;IACzB,MAAM,SAAS,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,sBAAsB,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IAElE,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI;QACJ,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAChD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotency hooks for @beignet/core/server
|
|
3
|
+
*/
|
|
4
|
+
import { type IdempotencyMeta, type IdempotencyPort, type IdempotencyScope } from "../../idempotency/index.js";
|
|
5
|
+
import type { ActivityActor, ActivityTenant } from "../../ports/index.js";
|
|
6
|
+
import type { HttpRequestLike, ServerHook } from "../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Ports required by idempotency hooks.
|
|
9
|
+
*/
|
|
10
|
+
export type IdempotencyPorts = {
|
|
11
|
+
idempotency: IdempotencyPort;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Minimal context shape required for actor- and tenant-scoped idempotency.
|
|
15
|
+
*/
|
|
16
|
+
export type CtxWithIdempotency = {
|
|
17
|
+
ports: IdempotencyPorts;
|
|
18
|
+
actor?: ActivityActor;
|
|
19
|
+
tenant?: ActivityTenant;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Options for `createIdempotencyHooks(...)`.
|
|
23
|
+
*/
|
|
24
|
+
export interface IdempotencyHooksOptions<Ctx> {
|
|
25
|
+
/**
|
|
26
|
+
* Build the idempotency namespace for a contract.
|
|
27
|
+
*
|
|
28
|
+
* Defaults to `http.<contract name>` so HTTP reservations never collide with
|
|
29
|
+
* use-case `runIdempotently(...)` namespaces.
|
|
30
|
+
*/
|
|
31
|
+
namespace?: (args: {
|
|
32
|
+
contract: {
|
|
33
|
+
name: string;
|
|
34
|
+
};
|
|
35
|
+
}) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Build the idempotency scope after context exists.
|
|
38
|
+
*
|
|
39
|
+
* Defaults to a scope derived from `meta.scope`: `"global"` stays global,
|
|
40
|
+
* `"actor"` scopes by `ctx.actor?.id`, `"tenant"` scopes by `ctx.tenant?.id`,
|
|
41
|
+
* and `"actor-tenant"` scopes by both.
|
|
42
|
+
*/
|
|
43
|
+
scope?: (args: {
|
|
44
|
+
ctx: Ctx;
|
|
45
|
+
req: HttpRequestLike;
|
|
46
|
+
meta: IdempotencyMeta;
|
|
47
|
+
}) => IdempotencyScope;
|
|
48
|
+
/**
|
|
49
|
+
* Build the fingerprint input from the parsed request.
|
|
50
|
+
*
|
|
51
|
+
* Defaults to `{ path, query, body }`.
|
|
52
|
+
*/
|
|
53
|
+
fingerprintInput?: (args: {
|
|
54
|
+
path: unknown;
|
|
55
|
+
query: unknown;
|
|
56
|
+
body: unknown;
|
|
57
|
+
}) => unknown;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create metadata-driven idempotency hooks.
|
|
61
|
+
*
|
|
62
|
+
* The hook reads `contract.metadata.idempotency` and enforces it with
|
|
63
|
+
* `ctx.ports.idempotency`. In `beforeHandle` it reserves the client key after
|
|
64
|
+
* request parsing, replays completed matching responses with an
|
|
65
|
+
* `idempotency-replayed: true` header, and rejects in-progress or conflicting
|
|
66
|
+
* keys with the framework `IdempotencyInProgress`/`IdempotencyConflict` catalog
|
|
67
|
+
* errors. In `beforeSend` it stores 2xx framework-neutral responses for replay
|
|
68
|
+
* and releases the reservation for errors, non-2xx responses, and native
|
|
69
|
+
* `Response` results, which are not replayable.
|
|
70
|
+
*
|
|
71
|
+
* Use `runIdempotently(...)` from `@beignet/core/idempotency` for non-HTTP
|
|
72
|
+
* workflows such as jobs, listeners, webhooks, and schedules.
|
|
73
|
+
*
|
|
74
|
+
* @param options - Optional namespace, scope, and fingerprint-input builders.
|
|
75
|
+
* @returns A server hook backed by `ctx.ports.idempotency`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createIdempotencyHooks<Ctx extends CtxWithIdempotency>(options?: IdempotencyHooksOptions<Ctx>): ServerHook<Ctx, IdempotencyPorts>;
|
|
78
|
+
//# sourceMappingURL=idempotency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/idempotency.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EACV,eAAe,EAEf,UAAU,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,gBAAgB,CAAC;IACxB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,GAAG;IAC1C;;;;;OAKG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,MAAM,CAAC;IAC7D;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE;QACb,GAAG,EAAE,GAAG,CAAC;QACT,GAAG,EAAE,eAAe,CAAC;QACrB,IAAI,EAAE,eAAe,CAAC;KACvB,KAAK,gBAAgB,CAAC;IACvB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;QACf,IAAI,EAAE,OAAO,CAAC;KACf,KAAK,OAAO,CAAC;CACf;AAmDD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,SAAS,kBAAkB,EACnE,OAAO,GAAE,uBAAuB,CAAC,GAAG,CAAM,GACzC,UAAU,CAAC,GAAG,EAAE,gBAAgB,CAAC,CA0HnC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idempotency hooks for @beignet/core/server
|
|
3
|
+
*/
|
|
4
|
+
import { AppError, httpErrors } from "../../errors/index.js";
|
|
5
|
+
import { createIdempotencyFingerprint, IdempotencyConflictError, IdempotencyInProgressError, } from "../../idempotency/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Header set on replayed responses.
|
|
8
|
+
*/
|
|
9
|
+
const IDEMPOTENCY_REPLAYED_HEADER = "idempotency-replayed";
|
|
10
|
+
function defaultIdempotencyScope(ctx, meta) {
|
|
11
|
+
const mode = meta.scope ?? "global";
|
|
12
|
+
switch (mode) {
|
|
13
|
+
case "global":
|
|
14
|
+
return "global";
|
|
15
|
+
case "actor":
|
|
16
|
+
return { actorId: ctx.actor?.id };
|
|
17
|
+
case "tenant":
|
|
18
|
+
return { tenantId: ctx.tenant?.id };
|
|
19
|
+
case "actor-tenant":
|
|
20
|
+
return { actorId: ctx.actor?.id, tenantId: ctx.tenant?.id };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function isReplayableHttpResponse(value) {
|
|
24
|
+
if (typeof value !== "object" || value === null)
|
|
25
|
+
return false;
|
|
26
|
+
const candidate = value;
|
|
27
|
+
if (typeof candidate.status !== "number")
|
|
28
|
+
return false;
|
|
29
|
+
if (candidate.headers !== undefined &&
|
|
30
|
+
(typeof candidate.headers !== "object" ||
|
|
31
|
+
candidate.headers === null ||
|
|
32
|
+
Array.isArray(candidate.headers))) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create metadata-driven idempotency hooks.
|
|
39
|
+
*
|
|
40
|
+
* The hook reads `contract.metadata.idempotency` and enforces it with
|
|
41
|
+
* `ctx.ports.idempotency`. In `beforeHandle` it reserves the client key after
|
|
42
|
+
* request parsing, replays completed matching responses with an
|
|
43
|
+
* `idempotency-replayed: true` header, and rejects in-progress or conflicting
|
|
44
|
+
* keys with the framework `IdempotencyInProgress`/`IdempotencyConflict` catalog
|
|
45
|
+
* errors. In `beforeSend` it stores 2xx framework-neutral responses for replay
|
|
46
|
+
* and releases the reservation for errors, non-2xx responses, and native
|
|
47
|
+
* `Response` results, which are not replayable.
|
|
48
|
+
*
|
|
49
|
+
* Use `runIdempotently(...)` from `@beignet/core/idempotency` for non-HTTP
|
|
50
|
+
* workflows such as jobs, listeners, webhooks, and schedules.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Optional namespace, scope, and fingerprint-input builders.
|
|
53
|
+
* @returns A server hook backed by `ctx.ports.idempotency`.
|
|
54
|
+
*/
|
|
55
|
+
export function createIdempotencyHooks(options = {}) {
|
|
56
|
+
const pending = new WeakMap();
|
|
57
|
+
return {
|
|
58
|
+
name: "idempotency",
|
|
59
|
+
beforeHandle: async ({ ctx, contract, req, path, query, body }) => {
|
|
60
|
+
const meta = contract.metadata?.idempotency;
|
|
61
|
+
if (!meta) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const header = (meta.header ?? "idempotency-key").toLowerCase();
|
|
65
|
+
const key = req.headers.get(header);
|
|
66
|
+
if (!key) {
|
|
67
|
+
if (meta.required) {
|
|
68
|
+
throw new AppError(httpErrors.BadRequest, {
|
|
69
|
+
contract: contract.name,
|
|
70
|
+
header,
|
|
71
|
+
}, `Missing required idempotency key header "${header}"`);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const namespace = options.namespace?.({ contract: { name: contract.name } }) ??
|
|
76
|
+
`http.${contract.name}`;
|
|
77
|
+
const scope = options.scope?.({ ctx, req, meta }) ??
|
|
78
|
+
defaultIdempotencyScope(ctx, meta);
|
|
79
|
+
const fingerprint = await createIdempotencyFingerprint(options.fingerprintInput?.({ path, query, body }) ?? {
|
|
80
|
+
path,
|
|
81
|
+
query,
|
|
82
|
+
body,
|
|
83
|
+
});
|
|
84
|
+
const reservation = await ctx.ports.idempotency.reserve({
|
|
85
|
+
namespace,
|
|
86
|
+
key,
|
|
87
|
+
scope,
|
|
88
|
+
fingerprint,
|
|
89
|
+
ttlSec: meta.ttlSec,
|
|
90
|
+
});
|
|
91
|
+
switch (reservation.status) {
|
|
92
|
+
case "replay": {
|
|
93
|
+
if (!isReplayableHttpResponse(reservation.result)) {
|
|
94
|
+
throw new AppError(httpErrors.InternalServerError, { namespace, key }, `Stored idempotency result for "${namespace}" key "${key}" is not a replayable HTTP response`);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
status: reservation.result.status,
|
|
98
|
+
headers: {
|
|
99
|
+
...(reservation.result.headers ?? {}),
|
|
100
|
+
[IDEMPOTENCY_REPLAYED_HEADER]: "true",
|
|
101
|
+
},
|
|
102
|
+
body: reservation.result.body,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
case "inProgress": {
|
|
106
|
+
throw new IdempotencyInProgressError(reservation);
|
|
107
|
+
}
|
|
108
|
+
case "conflict": {
|
|
109
|
+
throw new IdempotencyConflictError(reservation);
|
|
110
|
+
}
|
|
111
|
+
case "reserved": {
|
|
112
|
+
pending.set(req, {
|
|
113
|
+
port: ctx.ports.idempotency,
|
|
114
|
+
namespace,
|
|
115
|
+
key,
|
|
116
|
+
scope,
|
|
117
|
+
fingerprint,
|
|
118
|
+
});
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
beforeSend: async ({ req, response, error, native }) => {
|
|
124
|
+
const reservation = pending.get(req);
|
|
125
|
+
if (!reservation) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
pending.delete(req);
|
|
129
|
+
const { port, namespace, key, scope, fingerprint } = reservation;
|
|
130
|
+
if (!native &&
|
|
131
|
+
!error &&
|
|
132
|
+
response.status >= 200 &&
|
|
133
|
+
response.status < 300) {
|
|
134
|
+
await port.complete({
|
|
135
|
+
namespace,
|
|
136
|
+
key,
|
|
137
|
+
scope,
|
|
138
|
+
fingerprint,
|
|
139
|
+
result: {
|
|
140
|
+
status: response.status,
|
|
141
|
+
headers: response.headers,
|
|
142
|
+
body: response.body,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
// Errors, non-2xx responses, and native `Response` results release the
|
|
148
|
+
// reservation. Streams are not replayable.
|
|
149
|
+
await port.fail({ namespace, key, scope, fingerprint, error });
|
|
150
|
+
return undefined;
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=idempotency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../../src/server/hooks/idempotency.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,0BAA0B,GAI3B,MAAM,4BAA4B,CAAC;AA2DpC;;GAEG;AACH,MAAM,2BAA2B,GAAG,sBAAsB,CAAC;AAU3D,SAAS,uBAAuB,CAC9B,GAAuB,EACvB,IAAqB;IAErB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;IAEpC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,OAAO;YACV,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC;QACpC,KAAK,QAAQ;YACX,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;QACtC,KAAK,cAAc;YACjB,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;IAChE,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAE9D,MAAM,SAAS,GAAG,KAAgD,CAAC;IACnE,IAAI,OAAO,SAAS,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAEvD,IACE,SAAS,CAAC,OAAO,KAAK,SAAS;QAC/B,CAAC,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ;YACpC,SAAS,CAAC,OAAO,KAAK,IAAI;YAC1B,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EACnC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,UAAwC,EAAE;IAE1C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAuC,CAAC;IAEnE,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,YAAY,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;YAChE,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;YAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC,WAAW,EAAE,CAAC;YAChE,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAEpC,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAClB,MAAM,IAAI,QAAQ,CAChB,UAAU,CAAC,UAAU,EACrB;wBACE,QAAQ,EAAE,QAAQ,CAAC,IAAI;wBACvB,MAAM;qBACP,EACD,4CAA4C,MAAM,GAAG,CACtD,CAAC;gBACJ,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,MAAM,SAAS,GACb,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC1D,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC1B,MAAM,KAAK,GACT,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;gBACnC,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM,WAAW,GAAG,MAAM,4BAA4B,CACpD,OAAO,CAAC,gBAAgB,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI;gBACnD,IAAI;gBACJ,KAAK;gBACL,IAAI;aACL,CACF,CAAC;YAEF,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC;gBACtD,SAAS;gBACT,GAAG;gBACH,KAAK;gBACL,WAAW;gBACX,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;YAEH,QAAQ,WAAW,CAAC,MAAM,EAAE,CAAC;gBAC3B,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,IAAI,CAAC,wBAAwB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;wBAClD,MAAM,IAAI,QAAQ,CAChB,UAAU,CAAC,mBAAmB,EAC9B,EAAE,SAAS,EAAE,GAAG,EAAE,EAClB,kCAAkC,SAAS,UAAU,GAAG,qCAAqC,CAC9F,CAAC;oBACJ,CAAC;oBAED,OAAO;wBACL,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM;wBACjC,OAAO,EAAE;4BACP,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;4BACrC,CAAC,2BAA2B,CAAC,EAAE,MAAM;yBACtC;wBACD,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI;qBAC9B,CAAC;gBACJ,CAAC;gBACD,KAAK,YAAY,CAAC,CAAC,CAAC;oBAClB,MAAM,IAAI,0BAA0B,CAAC,WAAW,CAAC,CAAC;gBACpD,CAAC;gBACD,KAAK,UAAU,CAAC,CAAC,CAAC;oBAChB,MAAM,IAAI,wBAAwB,CAAC,WAAW,CAAC,CAAC;gBAClD,CAAC;gBACD,KAAK,UAAU,CAAC,CAAC,CAAC;oBAChB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;wBACf,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW;wBAC3B,SAAS;wBACT,GAAG;wBACH,KAAK;wBACL,WAAW;qBACZ,CAAC,CAAC;oBACH,OAAO,SAAS,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;QACD,UAAU,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;YACrD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAEpB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC;YAEjE,IACE,CAAC,MAAM;gBACP,CAAC,KAAK;gBACN,QAAQ,CAAC,MAAM,IAAI,GAAG;gBACtB,QAAQ,CAAC,MAAM,GAAG,GAAG,EACrB,CAAC;gBACD,MAAM,IAAI,CAAC,QAAQ,CAAC;oBAClB,SAAS;oBACT,GAAG;oBACH,KAAK;oBACL,WAAW;oBACX,MAAM,EAAE;wBACN,MAAM,EAAE,QAAQ,CAAC,MAAM;wBACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;wBACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;qBACpB;iBACF,CAAC,CAAC;gBACH,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,uEAAuE;YACvE,2CAA2C;YAC3C,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;YAC/D,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook utilities for @beignet/core/server
|
|
3
3
|
*/
|
|
4
|
-
import type { AnyPorts } from "../../ports";
|
|
5
|
-
import type { ServerHook } from "../http";
|
|
6
|
-
export { type AuthHookArgs, type AuthHooksOptions, type AuthRouteHooks, createAuthHooks, } from "./auth";
|
|
7
|
-
export { applyCorsHeaders, type CorsConfig, createCorsHooks, } from "./cors";
|
|
8
|
-
export { defaultMapErrorToResponse, type ErrorMappingConfig, type ErrorMappingResult, } from "./errors";
|
|
9
|
-
export {
|
|
10
|
-
export { type
|
|
4
|
+
import type { AnyPorts } from "../../ports/index.js";
|
|
5
|
+
import type { ServerHook } from "../http.js";
|
|
6
|
+
export { type AuthHookArgs, type AuthHooksOptions, type AuthRouteHooks, createAuthHooks, } from "./auth.js";
|
|
7
|
+
export { applyCorsHeaders, type CorsConfig, createCorsHooks, } from "./cors.js";
|
|
8
|
+
export { defaultMapErrorToResponse, type ErrorMappingConfig, type ErrorMappingResult, } from "./errors.js";
|
|
9
|
+
export { type CtxWithIdempotency, createIdempotencyHooks, type IdempotencyHooksOptions, type IdempotencyPorts, } from "./idempotency.js";
|
|
10
|
+
export { createLoggingHooks, type Logger, type LoggingConfig, } from "./logging.js";
|
|
11
|
+
export { type CtxWithRateLimit, createRateLimitHooks, type RateLimitIpSource, type RateLimitOptions, } from "./rate-limit.js";
|
|
11
12
|
/**
|
|
12
13
|
* Flatten hook arrays into a single hook list.
|
|
13
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,yBAAyB,EACzB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,kBAAkB,EACvB,sBAAsB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,EAClB,KAAK,MAAM,EACX,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,gBAAgB,EACrB,oBAAoB,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,SAAS,QAAQ,GAAG,QAAQ,EACjE,GAAG,KAAK,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,SAAS,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,GACvE,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAE1B"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook utilities for @beignet/core/server
|
|
3
3
|
*/
|
|
4
|
-
export { createAuthHooks, } from "./auth";
|
|
5
|
-
export { applyCorsHeaders, createCorsHooks, } from "./cors";
|
|
6
|
-
export { defaultMapErrorToResponse, } from "./errors";
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
4
|
+
export { createAuthHooks, } from "./auth.js";
|
|
5
|
+
export { applyCorsHeaders, createCorsHooks, } from "./cors.js";
|
|
6
|
+
export { defaultMapErrorToResponse, } from "./errors.js";
|
|
7
|
+
export { createIdempotencyHooks, } from "./idempotency.js";
|
|
8
|
+
export { createLoggingHooks, } from "./logging.js";
|
|
9
|
+
export { createRateLimitHooks, } from "./rate-limit.js";
|
|
9
10
|
/**
|
|
10
11
|
* Flatten hook arrays into a single hook list.
|
|
11
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAIL,eAAe,GAChB,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAIL,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gBAAgB,EAEhB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,yBAAyB,GAG1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,sBAAsB,GAGvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,kBAAkB,GAGnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,oBAAoB,GAGrB,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAG,KAAqE;IAExE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Logging hook utilities for @beignet/core/server
|
|
3
3
|
*/
|
|
4
|
-
import type { HttpContractConfig } from "../../contracts";
|
|
5
|
-
import type { HttpRequestLike, ServerHook } from "../types";
|
|
4
|
+
import type { HttpContractConfig } from "../../contracts/index.js";
|
|
5
|
+
import type { HttpRequestLike, ServerHook } from "../types.js";
|
|
6
6
|
/**
|
|
7
7
|
* Minimal logger shape accepted by `createLoggingHooks(...)`.
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/logging.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/logging.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG/D;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC;;OAEG;IACH,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,GAAG;IAChC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE;QACtB,GAAG,CAAC,EAAE,GAAG,CAAC;QACV,GAAG,EAAE,eAAe,CAAC;QACrB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;KAC/B,KAAK,IAAI,CAAC;IACX;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QACpB,GAAG,CAAC,EAAE,GAAG,CAAC;QACV,GAAG,EAAE,eAAe,CAAC;QACrB,GAAG,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;SAAE,CAAC;QACzD,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;QAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,KAAK,IAAI,CAAC;CACZ;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EACpC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,GACzB,UAAU,CAAC,GAAG,CAAC,CAqFjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../../src/server/hooks/logging.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,uBAAuB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../../src/server/hooks/logging.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rate limit hooks for @beignet/core/server
|
|
3
3
|
*/
|
|
4
|
-
import type { RateLimitScope } from "../../contracts";
|
|
5
|
-
import type { ActivityActor, RateLimitPort } from "../../ports";
|
|
6
|
-
import type { HttpRequestLike, ServerHook } from "../types";
|
|
4
|
+
import type { RateLimitScope } from "../../contracts/index.js";
|
|
5
|
+
import type { ActivityActor, RateLimitPort } from "../../ports/index.js";
|
|
6
|
+
import type { HttpRequestLike, ServerHook } from "../types.js";
|
|
7
7
|
/**
|
|
8
8
|
* Ports required by rate-limit hooks.
|
|
9
9
|
*/
|
|
@@ -18,6 +18,19 @@ export type CtxWithRateLimit = {
|
|
|
18
18
|
actor?: ActivityActor;
|
|
19
19
|
};
|
|
20
20
|
type EarlyRateLimitScope = Exclude<RateLimitScope, "user">;
|
|
21
|
+
/**
|
|
22
|
+
* Strategy for resolving the client IP used by `ip`-scoped limits.
|
|
23
|
+
*
|
|
24
|
+
* - `"x-forwarded-for-last"` (default): the last `x-forwarded-for` entry.
|
|
25
|
+
* This is the address appended by the platform's trusted reverse proxy and
|
|
26
|
+
* cannot be chosen by the client.
|
|
27
|
+
* - `"x-forwarded-for-first"`: the first `x-forwarded-for` entry. This value
|
|
28
|
+
* is client-controlled, so only use it when a trusted edge normalizes the
|
|
29
|
+
* header before it reaches the app.
|
|
30
|
+
* - A function receives the raw request and returns the client IP, for
|
|
31
|
+
* platform-specific headers such as `cf-connecting-ip`.
|
|
32
|
+
*/
|
|
33
|
+
export type RateLimitIpSource = "x-forwarded-for-last" | "x-forwarded-for-first" | ((req: HttpRequestLike) => string | undefined);
|
|
21
34
|
/**
|
|
22
35
|
* Options for `createRateLimitHooks(...)`.
|
|
23
36
|
*/
|
|
@@ -42,9 +55,12 @@ export interface RateLimitOptions<Ctx> {
|
|
|
42
55
|
scope: EarlyRateLimitScope;
|
|
43
56
|
}) => string;
|
|
44
57
|
/**
|
|
45
|
-
* Resolve
|
|
58
|
+
* Resolve the client IP for `ip`-scoped limits.
|
|
59
|
+
*
|
|
60
|
+
* Defaults to `"x-forwarded-for-last"`, the entry appended by the
|
|
61
|
+
* platform's trusted proxy. Pass a function for platform-specific headers.
|
|
46
62
|
*/
|
|
47
|
-
|
|
63
|
+
ipSource?: RateLimitIpSource;
|
|
48
64
|
}
|
|
49
65
|
/**
|
|
50
66
|
* Create metadata-driven rate-limit hooks.
|
|
@@ -52,9 +68,11 @@ export interface RateLimitOptions<Ctx> {
|
|
|
52
68
|
* The hook reads `contract.metadata.rateLimit`. Global and IP-scoped limits run
|
|
53
69
|
* in `onRequest` before context creation; user-scoped limits run in
|
|
54
70
|
* `beforeHandle` after `ctx.actor` is available. Exceeded limits throw the
|
|
55
|
-
* framework `TooManyRequests` app error
|
|
71
|
+
* framework `TooManyRequests` app error with `scope`, `retryAfterSeconds`, and
|
|
72
|
+
* `resetAt` details. The bucket key is never sent to clients; denials emit a
|
|
73
|
+
* `rateLimit.denied` instrumentation event that carries the key for operators.
|
|
56
74
|
*
|
|
57
|
-
* @param options - Optional key builders and client-IP
|
|
75
|
+
* @param options - Optional key builders and client-IP source.
|
|
58
76
|
* @returns A server hook backed by `ctx.ports.rateLimit`.
|
|
59
77
|
*/
|
|
60
78
|
export declare function createRateLimitHooks<Ctx extends CtxWithRateLimit>(options?: RateLimitOptions<Ctx>): ServerHook<Ctx, RateLimitPorts>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../src/server/hooks/rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAKzE,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,aAAa,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,iBAAiB,GACzB,sBAAsB,GACtB,uBAAuB,GACvB,CAAC,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,GAAG;IACnC;;;;OAIG;IACH,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE;QACX,GAAG,EAAE,GAAG,CAAC;QACT,GAAG,EAAE,eAAe,CAAC;QACrB,KAAK,EAAE,cAAc,CAAC;KACvB,KAAK,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE;QAChB,GAAG,EAAE,eAAe,CAAC;QACrB,KAAK,EAAE,mBAAmB,CAAC;KAC5B,KAAK,MAAM,CAAC;IACb;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AA4HD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,gBAAgB,EAC/D,OAAO,GAAE,gBAAgB,CAAC,GAAG,CAAM,GAClC,UAAU,CAAC,GAAG,EAAE,cAAc,CAAC,CAuDjC"}
|