@beignet/core 0.0.2 → 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 +173 -0
- package/README.md +821 -30
- 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 +148 -16
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +174 -14
- 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 +18 -4
- package/dist/outbox/index.d.ts.map +1 -1
- package/dist/outbox/index.js +104 -4
- 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 +46 -5
- 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 +89 -65
- package/dist/server/hooks/auth.d.ts.map +1 -1
- package/dist/server/hooks/auth.js +84 -55
- 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 +84 -6
- package/dist/server/http.d.ts.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 +148 -35
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +482 -145
- 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 +611 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +434 -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 +278 -0
- package/dist/uploads/client.d.ts.map +1 -0
- package/dist/uploads/client.js +428 -0
- package/dist/uploads/client.js.map +1 -0
- package/dist/uploads/index.d.ts +361 -0
- package/dist/uploads/index.d.ts.map +1 -0
- package/dist/uploads/index.js +543 -0
- package/dist/uploads/index.js.map +1 -0
- package/package.json +34 -3
- 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 +340 -29
- 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 +151 -6
- 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 +93 -8
- 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 +175 -158
- 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 +15 -12
- 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 +112 -6
- package/src/server/index.ts +63 -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 +1045 -229
- 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 +1153 -6
- package/src/tracing/index.ts +176 -0
- package/src/uploads/client.ts +861 -0
- package/src/uploads/index.ts +1071 -0
- 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
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal schema shape helpers shared by server route registration and
|
|
3
|
+
* OpenAPI generation.
|
|
4
|
+
*
|
|
5
|
+
* These helpers are intentionally zod-free: zod is an optional peer
|
|
6
|
+
* dependency, so shape extraction duck-types Zod's `_def.shape` internals and
|
|
7
|
+
* returns undefined for schemas it cannot introspect. This module is not
|
|
8
|
+
* exported from the package index.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Extract the field shape (field name → field schema) from an object schema.
|
|
13
|
+
*
|
|
14
|
+
* Returns undefined when the schema is not an introspectable object schema,
|
|
15
|
+
* for example a non-Zod Standard Schema.
|
|
16
|
+
*/
|
|
17
|
+
export function getObjectSchemaShape(
|
|
18
|
+
schema: unknown,
|
|
19
|
+
): Record<string, unknown> | undefined {
|
|
20
|
+
if (!schema || typeof schema !== "object") return undefined;
|
|
21
|
+
|
|
22
|
+
const schemaDef = (schema as Record<string, unknown>)?._def;
|
|
23
|
+
if (!schemaDef || typeof schemaDef !== "object") return undefined;
|
|
24
|
+
|
|
25
|
+
if (!("shape" in schemaDef)) return undefined;
|
|
26
|
+
|
|
27
|
+
let shape: unknown;
|
|
28
|
+
if (typeof schemaDef.shape === "function") {
|
|
29
|
+
shape = schemaDef.shape();
|
|
30
|
+
} else if (typeof schemaDef.shape === "object") {
|
|
31
|
+
shape = schemaDef.shape;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!shape || typeof shape !== "object") return undefined;
|
|
35
|
+
|
|
36
|
+
return shape as Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Compare a path template's dynamic keys against a pathParams schema shape.
|
|
41
|
+
*/
|
|
42
|
+
export function comparePathParamsToTemplate(args: {
|
|
43
|
+
pathKeys: readonly string[];
|
|
44
|
+
shapeKeys: readonly string[];
|
|
45
|
+
}): { missingKeys: string[]; extraKeys: string[] } {
|
|
46
|
+
const missingKeys = args.pathKeys.filter(
|
|
47
|
+
(key) => !args.shapeKeys.includes(key),
|
|
48
|
+
);
|
|
49
|
+
const extraKeys = args.shapeKeys.filter(
|
|
50
|
+
(key) => !args.pathKeys.includes(key),
|
|
51
|
+
);
|
|
52
|
+
return { missingKeys, extraKeys };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Format a pathParams/template mismatch for error messages.
|
|
57
|
+
*
|
|
58
|
+
* Shared so server registration and OpenAPI generation report the same
|
|
59
|
+
* diagnostic details.
|
|
60
|
+
*/
|
|
61
|
+
export function formatPathParamsMismatch(args: {
|
|
62
|
+
missingKeys: readonly string[];
|
|
63
|
+
extraKeys: readonly string[];
|
|
64
|
+
}): string {
|
|
65
|
+
return [
|
|
66
|
+
args.missingKeys.length > 0
|
|
67
|
+
? `missing pathParams keys: ${args.missingKeys.join(", ")}`
|
|
68
|
+
: undefined,
|
|
69
|
+
args.extraKeys.length > 0
|
|
70
|
+
? `extra pathParams keys: ${args.extraKeys.join(", ")}`
|
|
71
|
+
: undefined,
|
|
72
|
+
]
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
.join("; ");
|
|
75
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { HttpContractConfig } from "./types.js";
|
|
2
|
+
|
|
3
|
+
type Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
|
|
4
|
+
type ToNumber<S extends string> = S extends `${infer N extends number}`
|
|
5
|
+
? N
|
|
6
|
+
: never;
|
|
7
|
+
type Any2xxCode = ToNumber<`2${Digit}${Digit}`>;
|
|
8
|
+
type NumericKey<K> = K extends number
|
|
9
|
+
? K
|
|
10
|
+
: K extends `${infer N extends number}`
|
|
11
|
+
? N
|
|
12
|
+
: never;
|
|
13
|
+
|
|
14
|
+
type UnionToIntersection<T> = (
|
|
15
|
+
T extends unknown
|
|
16
|
+
? (value: T) => void
|
|
17
|
+
: never
|
|
18
|
+
) extends (value: infer I) => void
|
|
19
|
+
? I
|
|
20
|
+
: never;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* All declared 2xx status codes from a contract `responses` record, as
|
|
24
|
+
* numeric literal keys.
|
|
25
|
+
*/
|
|
26
|
+
export type Success2xxKeys<TResponses extends object> = {
|
|
27
|
+
[K in keyof TResponses]: NumericKey<K> extends Any2xxCode
|
|
28
|
+
? NumericKey<K>
|
|
29
|
+
: never;
|
|
30
|
+
}[keyof TResponses];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Whether a contract `responses` record declares exactly one 2xx status.
|
|
34
|
+
*/
|
|
35
|
+
export type IsSingle2xx<TResponses extends object> = [
|
|
36
|
+
Success2xxKeys<TResponses>,
|
|
37
|
+
] extends [never]
|
|
38
|
+
? false
|
|
39
|
+
: [Success2xxKeys<TResponses>] extends [
|
|
40
|
+
UnionToIntersection<Success2xxKeys<TResponses>>,
|
|
41
|
+
]
|
|
42
|
+
? true
|
|
43
|
+
: false;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* List the declared 2xx statuses of a contract at runtime.
|
|
47
|
+
*/
|
|
48
|
+
export function getSuccess2xxStatuses(
|
|
49
|
+
contract: Pick<HttpContractConfig, "responses">,
|
|
50
|
+
): number[] {
|
|
51
|
+
return Object.keys(contract.responses)
|
|
52
|
+
.map((status) => Number(status))
|
|
53
|
+
.filter(
|
|
54
|
+
(status) => Number.isInteger(status) && status >= 200 && status < 300,
|
|
55
|
+
)
|
|
56
|
+
.sort((a, b) => a - b);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Resolve the sole declared 2xx status of a contract, or `undefined` when the
|
|
61
|
+
* contract declares zero or multiple 2xx statuses.
|
|
62
|
+
*/
|
|
63
|
+
export function inferSoleSuccessStatus(
|
|
64
|
+
contract: Pick<HttpContractConfig, "responses">,
|
|
65
|
+
): number | undefined {
|
|
66
|
+
const statuses = getSuccess2xxStatuses(contract);
|
|
67
|
+
return statuses.length === 1 ? statuses[0] : undefined;
|
|
68
|
+
}
|
package/src/contracts/types.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
-
import type { IdempotencyMeta } from "../idempotency";
|
|
3
|
-
import type { OpenAPIOperationMeta } from "./openapi-meta";
|
|
4
|
-
import type { RateLimitMeta } from "./rate-limit";
|
|
2
|
+
import type { IdempotencyMeta } from "../idempotency/index.js";
|
|
3
|
+
import type { OpenAPIOperationMeta } from "./openapi-meta.js";
|
|
4
|
+
import type { RateLimitMeta } from "./rate-limit.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Any Standard Schema compatible validator.
|
|
@@ -72,6 +72,21 @@ export type ResponsesFromErrorDefinitions<T extends ContractErrorResponses> = {
|
|
|
72
72
|
[K in keyof T as T[K]["status"]]: StandardErrorResponseSchema;
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Merge catalog errors already declared in contract metadata with newly
|
|
77
|
+
* declared error definitions.
|
|
78
|
+
*
|
|
79
|
+
* `.errors()` declarations compose: contracts keep the union of group-declared
|
|
80
|
+
* and route-declared catalog errors. Later declarations win when the same
|
|
81
|
+
* catalog key is declared twice.
|
|
82
|
+
*/
|
|
83
|
+
export type MergedContractErrorResponses<
|
|
84
|
+
TMeta extends ContractMeta,
|
|
85
|
+
TErrorDefs extends ContractErrorResponses,
|
|
86
|
+
> = TMeta["errors"] extends ContractErrorResponses
|
|
87
|
+
? Omit<TMeta["errors"], keyof TErrorDefs> & TErrorDefs
|
|
88
|
+
: TErrorDefs;
|
|
89
|
+
|
|
75
90
|
/**
|
|
76
91
|
* Header schema declaration for a contract.
|
|
77
92
|
*/
|
|
@@ -222,13 +237,25 @@ export type ContractMeta = {
|
|
|
222
237
|
/**
|
|
223
238
|
* Optional idempotency configuration for this contract.
|
|
224
239
|
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
240
|
+
* Enforced at the HTTP boundary by `createIdempotencyHooks(...)`.
|
|
241
|
+
* `runIdempotently(...)` remains the primitive for non-HTTP workflows.
|
|
227
242
|
*/
|
|
228
243
|
idempotency?: IdempotencyMeta;
|
|
229
244
|
[namespace: string]: unknown;
|
|
230
245
|
};
|
|
231
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Omit metadata keys while preserving literal property types.
|
|
249
|
+
*
|
|
250
|
+
* `ContractMeta` carries an index signature, so the built-in `Omit` collapses
|
|
251
|
+
* `keyof` to `string` and erases literal metadata such as
|
|
252
|
+
* `idempotency: { header: "idempotency-key" }` that typed clients rely on.
|
|
253
|
+
* Key remapping keeps known properties and the index signature intact.
|
|
254
|
+
*/
|
|
255
|
+
export type OmitMetaKeys<TMeta, K extends PropertyKey> = {
|
|
256
|
+
[P in keyof TMeta as P extends K ? never : P]: TMeta[P];
|
|
257
|
+
};
|
|
258
|
+
|
|
232
259
|
/**
|
|
233
260
|
* Plain HTTP contract configuration consumed by server, client, and tooling.
|
|
234
261
|
*/
|
package/src/contracts/utils.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
type PathTemplateSegment,
|
|
3
|
+
parsePathTemplate,
|
|
4
|
+
} from "./path-template.js";
|
|
5
|
+
import type { HttpMethod } from "./types.js";
|
|
3
6
|
|
|
4
7
|
const methodNameMap: Record<HttpMethod, string> = {
|
|
5
8
|
GET: "get",
|
package/src/domain/events.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
EventDef,
|
|
3
|
+
InferEventPayload,
|
|
4
|
+
StandardSchema,
|
|
5
|
+
} from "../events/index.js";
|
|
6
|
+
import { defineEvent } from "../events/index.js";
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
9
|
* Domain event definition with a stable name and payload schema.
|
package/src/domain/index.ts
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* - A Domain Event helper (defineDomainEvent)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
export { defineEntity, type EntityDef, type EntityInstance } from "./entity";
|
|
12
|
+
export { defineEntity, type EntityDef, type EntityInstance } from "./entity.js";
|
|
13
13
|
export {
|
|
14
14
|
type DomainEventDef,
|
|
15
15
|
defineDomainEvent,
|
|
16
16
|
type InferEventPayload,
|
|
17
|
-
} from "./events";
|
|
18
|
-
export { defineValueObject, type ValueObjectDef } from "./value-object";
|
|
17
|
+
} from "./events.js";
|
|
18
|
+
export { defineValueObject, type ValueObjectDef } from "./value-object.js";
|
package/src/errors/catalog.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface ErrorDef<
|
|
|
26
26
|
*
|
|
27
27
|
* Beignet uses this for TypeScript inference. Details are not runtime
|
|
28
28
|
* validated by `AppError`; validate before constructing errors when needed.
|
|
29
|
+
* Details become public response data when the error crosses the HTTP
|
|
30
|
+
* boundary, so use app-owned safe fields instead of raw diagnostics.
|
|
29
31
|
*/
|
|
30
32
|
details?: TDetails;
|
|
31
33
|
}
|
|
@@ -64,7 +66,13 @@ export class AppError<TDef extends ErrorDef = ErrorDef> extends Error {
|
|
|
64
66
|
readonly [APP_ERROR_BRAND] = true;
|
|
65
67
|
/** Error definition from the catalog. */
|
|
66
68
|
readonly def: TDef;
|
|
67
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Optional structured details for clients or UI.
|
|
71
|
+
*
|
|
72
|
+
* Beignet does not automatically redact route-owned error details. Keep
|
|
73
|
+
* provider errors, stack traces, secrets, and private content in `cause`,
|
|
74
|
+
* logs, or error reporting instead.
|
|
75
|
+
*/
|
|
68
76
|
readonly details?: InferErrorDetails<TDef>;
|
|
69
77
|
|
|
70
78
|
constructor(
|
package/src/errors/http.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* A base catalog of common HTTP-related errors that apps can reuse and extend.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { defineErrors } from "./catalog";
|
|
7
|
+
import { defineErrors } from "./catalog.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* A base catalog of common HTTP-related errors.
|
|
@@ -52,6 +52,16 @@ export const httpErrors = defineErrors({
|
|
|
52
52
|
status: 409,
|
|
53
53
|
message: "Conflict",
|
|
54
54
|
},
|
|
55
|
+
IdempotencyConflict: {
|
|
56
|
+
code: "IDEMPOTENCY_CONFLICT",
|
|
57
|
+
status: 409,
|
|
58
|
+
message: "Idempotency key was already used with a different request",
|
|
59
|
+
},
|
|
60
|
+
IdempotencyInProgress: {
|
|
61
|
+
code: "IDEMPOTENCY_IN_PROGRESS",
|
|
62
|
+
status: 409,
|
|
63
|
+
message: "Idempotency key is already being processed",
|
|
64
|
+
},
|
|
55
65
|
TooManyRequests: {
|
|
56
66
|
code: "TOO_MANY_REQUESTS",
|
|
57
67
|
status: 429,
|
package/src/errors/index.ts
CHANGED
|
@@ -14,15 +14,15 @@ export {
|
|
|
14
14
|
type ErrorDef,
|
|
15
15
|
type InferErrorDetails,
|
|
16
16
|
isAppError,
|
|
17
|
-
} from "./catalog";
|
|
17
|
+
} from "./catalog.js";
|
|
18
18
|
// HTTP error helpers
|
|
19
|
-
export { type HttpErrorCatalog, httpErrors } from "./http";
|
|
19
|
+
export { type HttpErrorCatalog, httpErrors } from "./http.js";
|
|
20
20
|
// Error response utilities
|
|
21
21
|
export {
|
|
22
22
|
createErrorResponseBody,
|
|
23
23
|
type ErrorResponseBody,
|
|
24
24
|
isErrorResponseBody,
|
|
25
25
|
toErrorResponseBody,
|
|
26
|
-
} from "./response";
|
|
26
|
+
} from "./response.js";
|
|
27
27
|
// Schema validation error (shared across client/core/server)
|
|
28
|
-
export { SchemaValidationError, type ValidationIssue } from "./validation";
|
|
28
|
+
export { SchemaValidationError, type ValidationIssue } from "./validation.js";
|
package/src/errors/response.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Standard error response schema and utilities for Beignet
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type { AppError, ErrorDef } from "./catalog";
|
|
5
|
+
import type { AppError, ErrorDef } from "./catalog.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Standard Beignet error response body.
|
|
@@ -18,6 +18,9 @@ export interface ErrorResponseBody {
|
|
|
18
18
|
message: string;
|
|
19
19
|
/**
|
|
20
20
|
* Optional structured details.
|
|
21
|
+
*
|
|
22
|
+
* These details are sent to clients. Beignet does not automatically redact
|
|
23
|
+
* app-owned response details, so only include values that are safe to expose.
|
|
21
24
|
*/
|
|
22
25
|
details?: unknown;
|
|
23
26
|
/**
|
package/src/events/index.ts
CHANGED
|
@@ -168,9 +168,9 @@ export interface RegisterListenersOptions<Ctx> {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
|
-
* Context-bound
|
|
171
|
+
* Context-bound listener helper factory.
|
|
172
172
|
*/
|
|
173
|
-
export interface
|
|
173
|
+
export interface Listeners<Ctx> {
|
|
174
174
|
/**
|
|
175
175
|
* Define a listener with the bound context type.
|
|
176
176
|
*/
|
|
@@ -178,15 +178,6 @@ export interface EventHandlers<Ctx> {
|
|
|
178
178
|
event: E,
|
|
179
179
|
options: DefineListenerOptions<E, Ctx, Name>,
|
|
180
180
|
): ListenerDef<E, Ctx, Name>;
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Register listeners with an event bus.
|
|
184
|
-
*/
|
|
185
|
-
registerListeners(
|
|
186
|
-
eventBus: EventBusLike,
|
|
187
|
-
listeners: readonly ListenerDef<EventDef, Ctx>[],
|
|
188
|
-
options?: RegisterListenersOptions<Ctx>,
|
|
189
|
-
): () => void;
|
|
190
181
|
}
|
|
191
182
|
|
|
192
183
|
/**
|
|
@@ -280,10 +271,7 @@ export function defineEvent<
|
|
|
280
271
|
};
|
|
281
272
|
}
|
|
282
273
|
|
|
283
|
-
|
|
284
|
-
* Define a listener for one event.
|
|
285
|
-
*/
|
|
286
|
-
export function defineListener<
|
|
274
|
+
function defineListenerImpl<
|
|
287
275
|
E extends EventDef,
|
|
288
276
|
Ctx = unknown,
|
|
289
277
|
Name extends string = string,
|
|
@@ -358,23 +346,21 @@ export function registerListeners<Ctx>(
|
|
|
358
346
|
}
|
|
359
347
|
|
|
360
348
|
/**
|
|
361
|
-
* Create
|
|
349
|
+
* Create listener helper methods bound to an application context type.
|
|
350
|
+
*
|
|
351
|
+
* Call it once in `lib/listeners.ts`:
|
|
352
|
+
*
|
|
353
|
+
* ```ts
|
|
354
|
+
* export const { defineListener } = createListeners<AppContext>();
|
|
355
|
+
* ```
|
|
362
356
|
*/
|
|
363
|
-
export function
|
|
357
|
+
export function createListeners<Ctx>(): Listeners<Ctx> {
|
|
364
358
|
return {
|
|
365
359
|
defineListener<E extends EventDef, Name extends string = string>(
|
|
366
360
|
event: E,
|
|
367
361
|
options: DefineListenerOptions<E, Ctx, Name>,
|
|
368
362
|
): ListenerDef<E, Ctx, Name> {
|
|
369
|
-
return
|
|
370
|
-
},
|
|
371
|
-
|
|
372
|
-
registerListeners(
|
|
373
|
-
eventBus: EventBusLike,
|
|
374
|
-
listeners: readonly ListenerDef<EventDef, Ctx>[],
|
|
375
|
-
options: RegisterListenersOptions<Ctx> = {},
|
|
376
|
-
): () => void {
|
|
377
|
-
return registerListeners(eventBus, listeners, options);
|
|
363
|
+
return defineListenerImpl(event, options);
|
|
378
364
|
},
|
|
379
365
|
};
|
|
380
366
|
}
|
package/src/idempotency/index.ts
CHANGED
|
@@ -38,13 +38,15 @@ export type IdempotencyScopeMode =
|
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Contract metadata for idempotency-aware routes.
|
|
41
|
+
*
|
|
42
|
+
* This metadata is enforced at the HTTP boundary by
|
|
43
|
+
* `createIdempotencyHooks(...)` from `@beignet/core/server`.
|
|
44
|
+
* `runIdempotently(...)` remains the primitive for non-HTTP workflows such as
|
|
45
|
+
* jobs, listeners, webhooks, and schedules.
|
|
41
46
|
*/
|
|
42
47
|
export interface IdempotencyMeta {
|
|
43
48
|
/**
|
|
44
49
|
* Whether this operation requires an idempotency key at the HTTP boundary.
|
|
45
|
-
*
|
|
46
|
-
* This is metadata for hooks, docs, and generated OpenAPI. Use cases should
|
|
47
|
-
* still call `runIdempotently(...)` for workflows that must be retry-safe.
|
|
48
50
|
*/
|
|
49
51
|
required?: boolean;
|
|
50
52
|
|