@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
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ContractErrorDefinition,
|
|
3
|
+
ContractErrorResponses,
|
|
4
|
+
ContractMeta,
|
|
5
|
+
ContractResponses,
|
|
6
|
+
} from "./types.js";
|
|
7
|
+
import { STANDARD_ERROR_RESPONSE_SCHEMA } from "./types.js";
|
|
8
|
+
|
|
9
|
+
function isContractErrorDefinition(
|
|
10
|
+
value: unknown,
|
|
11
|
+
): value is ContractErrorDefinition {
|
|
12
|
+
return (
|
|
13
|
+
typeof value === "object" &&
|
|
14
|
+
value !== null &&
|
|
15
|
+
typeof (value as { code?: unknown }).code === "string" &&
|
|
16
|
+
typeof (value as { status?: unknown }).status === "number" &&
|
|
17
|
+
typeof (value as { message?: unknown }).message === "string"
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Extract catalog error definitions declared in contract metadata.
|
|
23
|
+
*/
|
|
24
|
+
export function catalogErrorsFromMeta(
|
|
25
|
+
metadata: ContractMeta,
|
|
26
|
+
): ContractErrorResponses {
|
|
27
|
+
const errors = metadata.errors;
|
|
28
|
+
if (typeof errors !== "object" || errors === null) return {};
|
|
29
|
+
|
|
30
|
+
const catalog: ContractErrorResponses = {};
|
|
31
|
+
for (const [key, definition] of Object.entries(errors)) {
|
|
32
|
+
if (isContractErrorDefinition(definition)) {
|
|
33
|
+
catalog[key] = definition;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return catalog;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Convert catalog error definitions into standard envelope response schemas.
|
|
41
|
+
*/
|
|
42
|
+
export function responsesFromErrors(
|
|
43
|
+
errors: ContractErrorResponses,
|
|
44
|
+
): ContractResponses {
|
|
45
|
+
const responses: ContractResponses = {};
|
|
46
|
+
for (const error of Object.values(errors)) {
|
|
47
|
+
responses[error.status] = STANDARD_ERROR_RESPONSE_SCHEMA;
|
|
48
|
+
}
|
|
49
|
+
return responses;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Merge catalog errors already declared in metadata with new declarations.
|
|
54
|
+
*
|
|
55
|
+
* Later declarations win when the same catalog key is declared twice.
|
|
56
|
+
*/
|
|
57
|
+
export function mergeCatalogErrors(
|
|
58
|
+
metadata: ContractMeta,
|
|
59
|
+
errorDefs: ContractErrorResponses,
|
|
60
|
+
): ContractErrorResponses {
|
|
61
|
+
return { ...catalogErrorsFromMeta(metadata), ...errorDefs };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function catalogErrorStatuses(metadata: ContractMeta): Set<string> {
|
|
65
|
+
return new Set(
|
|
66
|
+
Object.values(catalogErrorsFromMeta(metadata)).map((error) =>
|
|
67
|
+
String(error.status),
|
|
68
|
+
),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Reject `.errors()` statuses that collide with custom response schemas.
|
|
74
|
+
*
|
|
75
|
+
* Statuses declared by earlier `.errors()` calls are allowed: catalog errors
|
|
76
|
+
* share the standard error envelope, so multiple codes can map to one status.
|
|
77
|
+
*/
|
|
78
|
+
export function assertErrorsAvoidCustomResponseStatuses(
|
|
79
|
+
metadata: ContractMeta,
|
|
80
|
+
responses: ContractResponses,
|
|
81
|
+
nextErrorResponses: ContractResponses,
|
|
82
|
+
): void {
|
|
83
|
+
const existingErrorStatuses = catalogErrorStatuses(metadata);
|
|
84
|
+
const customStatuses = new Set(
|
|
85
|
+
Object.keys(responses).filter(
|
|
86
|
+
(status) => !existingErrorStatuses.has(status),
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
const conflicts = Object.keys(nextErrorResponses).filter((status) =>
|
|
90
|
+
customStatuses.has(status),
|
|
91
|
+
);
|
|
92
|
+
if (conflicts.length) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`.errors() cannot declare status ${conflicts.join(", ")} because a response schema for that status already exists. Use .responses() without .errors() when you need a custom error response body.`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reject `.responses()` statuses already declared by catalog errors.
|
|
101
|
+
*/
|
|
102
|
+
export function assertResponsesAvoidCatalogErrorStatuses(
|
|
103
|
+
metadata: ContractMeta,
|
|
104
|
+
next: ContractResponses,
|
|
105
|
+
): void {
|
|
106
|
+
const errorStatuses = catalogErrorStatuses(metadata);
|
|
107
|
+
const conflicts = Object.keys(next).filter((status) =>
|
|
108
|
+
errorStatuses.has(status),
|
|
109
|
+
);
|
|
110
|
+
if (conflicts.length) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`.responses() cannot declare status ${conflicts.join(", ")} because that status is already declared by .errors(). Use .responses() without .errors() when you need a custom error response body.`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
assertErrorsAvoidCustomResponseStatuses,
|
|
4
|
+
assertResponsesAvoidCatalogErrorStatuses,
|
|
5
|
+
mergeCatalogErrors,
|
|
6
|
+
responsesFromErrors,
|
|
7
|
+
} from "./catalog-errors.js";
|
|
8
|
+
import type { OpenAPIOperationMeta } from "./openapi-meta.js";
|
|
9
|
+
import { parsePathTemplate } from "./path-template.js";
|
|
4
10
|
import type {
|
|
5
11
|
BodyHttpMethod,
|
|
6
12
|
ContractErrorResponses,
|
|
@@ -9,67 +15,13 @@ import type {
|
|
|
9
15
|
ContractResponses,
|
|
10
16
|
HttpContractConfig,
|
|
11
17
|
HttpMethod,
|
|
18
|
+
MergedContractErrorResponses,
|
|
19
|
+
OmitMetaKeys,
|
|
12
20
|
ResponsesFromErrorDefinitions,
|
|
13
21
|
StandardSchema,
|
|
14
|
-
} from "./types";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
STANDARD_ERROR_RESPONSE_SCHEMA,
|
|
18
|
-
} from "./types";
|
|
19
|
-
import { generateContractName } from "./utils";
|
|
20
|
-
|
|
21
|
-
function responsesFromErrors(
|
|
22
|
-
errors: ContractErrorResponses,
|
|
23
|
-
): ContractResponses {
|
|
24
|
-
const responses: ContractResponses = {};
|
|
25
|
-
for (const error of Object.values(errors)) {
|
|
26
|
-
responses[error.status] = STANDARD_ERROR_RESPONSE_SCHEMA;
|
|
27
|
-
}
|
|
28
|
-
return responses;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function assertNoResponseStatusConflicts(
|
|
32
|
-
current: ContractResponses,
|
|
33
|
-
next: ContractResponses,
|
|
34
|
-
): void {
|
|
35
|
-
const currentStatuses = new Set(Object.keys(current));
|
|
36
|
-
const conflicts = Object.keys(next).filter((status) =>
|
|
37
|
-
currentStatuses.has(status),
|
|
38
|
-
);
|
|
39
|
-
if (conflicts.length) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
`.errors() cannot declare status ${conflicts.join(", ")} because a response schema for that status already exists. Use .responses() without .errors() when you need a custom error response body.`,
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function assertNoCatalogErrorStatusConflicts(
|
|
47
|
-
metadata: ContractMeta,
|
|
48
|
-
next: ContractResponses,
|
|
49
|
-
): void {
|
|
50
|
-
const errors = metadata.errors;
|
|
51
|
-
if (typeof errors !== "object" || errors === null) return;
|
|
52
|
-
|
|
53
|
-
const errorStatuses = new Set(
|
|
54
|
-
Object.values(errors)
|
|
55
|
-
.map((error) =>
|
|
56
|
-
typeof error === "object" &&
|
|
57
|
-
error !== null &&
|
|
58
|
-
typeof (error as { status?: unknown }).status === "number"
|
|
59
|
-
? String((error as { status: number }).status)
|
|
60
|
-
: undefined,
|
|
61
|
-
)
|
|
62
|
-
.filter((status): status is string => status !== undefined),
|
|
63
|
-
);
|
|
64
|
-
const conflicts = Object.keys(next).filter((status) =>
|
|
65
|
-
errorStatuses.has(status),
|
|
66
|
-
);
|
|
67
|
-
if (conflicts.length) {
|
|
68
|
-
throw new Error(
|
|
69
|
-
`.responses() cannot declare status ${conflicts.join(", ")} because that status is already declared by .errors(). Use .responses() without .errors() when you need a custom error response body.`,
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
22
|
+
} from "./types.js";
|
|
23
|
+
import { methodSupportsRequestBody } from "./types.js";
|
|
24
|
+
import { generateContractName } from "./utils.js";
|
|
73
25
|
|
|
74
26
|
/**
|
|
75
27
|
* Fluent builder for one HTTP contract.
|
|
@@ -397,7 +349,7 @@ export class ContractBuilder<
|
|
|
397
349
|
TMeta,
|
|
398
350
|
TPath
|
|
399
351
|
> {
|
|
400
|
-
|
|
352
|
+
assertResponsesAvoidCatalogErrorStatuses(this._meta, responseSchemas);
|
|
401
353
|
return new ContractBuilder({
|
|
402
354
|
kind: this.kind,
|
|
403
355
|
name: this.name,
|
|
@@ -421,8 +373,11 @@ export class ContractBuilder<
|
|
|
421
373
|
* Declare route-owned application errors from an error catalog.
|
|
422
374
|
*
|
|
423
375
|
* Catalog errors use Beignet's standard error response envelope and remain
|
|
424
|
-
* distinguishable from framework-owned errors.
|
|
425
|
-
*
|
|
376
|
+
* distinguishable from framework-owned errors. Declarations merge with
|
|
377
|
+
* previously declared catalog errors, including shared group errors; later
|
|
378
|
+
* declarations win when the same catalog key is declared twice. Use
|
|
379
|
+
* `.responses()` when a route needs a custom error response body instead of
|
|
380
|
+
* catalog semantics.
|
|
426
381
|
*/
|
|
427
382
|
errors<TErrorDefs extends ContractErrorResponses>(
|
|
428
383
|
errorDefs: TErrorDefs,
|
|
@@ -434,11 +389,17 @@ export class ContractBuilder<
|
|
|
434
389
|
THeaders,
|
|
435
390
|
Omit<TResponses, keyof ResponsesFromErrorDefinitions<TErrorDefs>> &
|
|
436
391
|
ResponsesFromErrorDefinitions<TErrorDefs>,
|
|
437
|
-
|
|
392
|
+
OmitMetaKeys<TMeta, "errors"> & {
|
|
393
|
+
errors: MergedContractErrorResponses<TMeta, TErrorDefs>;
|
|
394
|
+
},
|
|
438
395
|
TPath
|
|
439
396
|
> {
|
|
440
397
|
const errorResponses = responsesFromErrors(errorDefs);
|
|
441
|
-
|
|
398
|
+
assertErrorsAvoidCustomResponseStatuses(
|
|
399
|
+
this._meta,
|
|
400
|
+
this._responses,
|
|
401
|
+
errorResponses,
|
|
402
|
+
);
|
|
442
403
|
return new ContractBuilder({
|
|
443
404
|
kind: this.kind,
|
|
444
405
|
name: this.name,
|
|
@@ -460,8 +421,10 @@ export class ContractBuilder<
|
|
|
460
421
|
ResponsesFromErrorDefinitions<TErrorDefs>,
|
|
461
422
|
metadata: {
|
|
462
423
|
...this._meta,
|
|
463
|
-
errors: errorDefs,
|
|
464
|
-
} as
|
|
424
|
+
errors: mergeCatalogErrors(this._meta, errorDefs),
|
|
425
|
+
} as unknown as OmitMetaKeys<TMeta, "errors"> & {
|
|
426
|
+
errors: MergedContractErrorResponses<TMeta, TErrorDefs>;
|
|
427
|
+
},
|
|
465
428
|
});
|
|
466
429
|
}
|
|
467
430
|
|
|
@@ -480,7 +443,7 @@ export class ContractBuilder<
|
|
|
480
443
|
TBody,
|
|
481
444
|
THeaders,
|
|
482
445
|
TResponses,
|
|
483
|
-
|
|
446
|
+
OmitMetaKeys<TMeta, keyof TNewMeta> & TNewMeta,
|
|
484
447
|
TPath
|
|
485
448
|
> {
|
|
486
449
|
return new ContractBuilder({
|
|
@@ -498,7 +461,7 @@ export class ContractBuilder<
|
|
|
498
461
|
metadata: {
|
|
499
462
|
...this._meta,
|
|
500
463
|
...newMeta,
|
|
501
|
-
} as unknown as
|
|
464
|
+
} as unknown as OmitMetaKeys<TMeta, keyof TNewMeta> & TNewMeta,
|
|
502
465
|
});
|
|
503
466
|
}
|
|
504
467
|
|
|
@@ -542,9 +505,9 @@ export class ContractBuilder<
|
|
|
542
505
|
}
|
|
543
506
|
|
|
544
507
|
/**
|
|
545
|
-
* Options for creating one contract with `
|
|
508
|
+
* Options for creating one contract with `defineContract(...)`.
|
|
546
509
|
*/
|
|
547
|
-
export type
|
|
510
|
+
export type DefineContractOptions<
|
|
548
511
|
TMethod extends HttpMethod = HttpMethod,
|
|
549
512
|
TPath extends string = string,
|
|
550
513
|
> = {
|
|
@@ -559,13 +522,13 @@ export type CreateContractOptions<
|
|
|
559
522
|
/**
|
|
560
523
|
* Create a new HTTP contract builder.
|
|
561
524
|
*
|
|
562
|
-
* Most apps prefer `
|
|
525
|
+
* Most apps prefer `defineContractGroup().namespace(...).prefix(...)` for
|
|
563
526
|
* related feature contracts. Use this lower-level factory when a standalone
|
|
564
527
|
* contract is clearer.
|
|
565
528
|
*
|
|
566
529
|
* @example
|
|
567
530
|
* ```ts
|
|
568
|
-
* const getTodo =
|
|
531
|
+
* const getTodo = defineContract({
|
|
569
532
|
* method: "GET",
|
|
570
533
|
* path: "/api/todos/:id",
|
|
571
534
|
* })
|
|
@@ -576,11 +539,11 @@ export type CreateContractOptions<
|
|
|
576
539
|
* @param options - HTTP method, path template, and optional contract name.
|
|
577
540
|
* @returns A fluent contract builder.
|
|
578
541
|
*/
|
|
579
|
-
export function
|
|
542
|
+
export function defineContract<
|
|
580
543
|
TMethod extends HttpMethod,
|
|
581
544
|
const TPath extends string,
|
|
582
545
|
>(
|
|
583
|
-
options:
|
|
546
|
+
options: DefineContractOptions<TMethod, TPath>,
|
|
584
547
|
): ContractBuilder<
|
|
585
548
|
TMethod,
|
|
586
549
|
null,
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
assertErrorsAvoidCustomResponseStatuses,
|
|
3
|
+
assertResponsesAvoidCatalogErrorStatuses,
|
|
4
|
+
mergeCatalogErrors,
|
|
5
|
+
responsesFromErrors,
|
|
6
|
+
} from "./catalog-errors.js";
|
|
7
|
+
import { ContractBuilder } from "./contract-builder.js";
|
|
8
|
+
import { parsePathTemplate } from "./path-template.js";
|
|
3
9
|
import type {
|
|
4
10
|
ContractErrorResponses,
|
|
5
11
|
ContractHeaderSchemas,
|
|
6
12
|
ContractMeta,
|
|
7
13
|
ContractResponses,
|
|
8
14
|
HttpMethod,
|
|
15
|
+
MergedContractErrorResponses,
|
|
16
|
+
OmitMetaKeys,
|
|
9
17
|
ResponsesFromErrorDefinitions,
|
|
10
18
|
StandardSchema,
|
|
11
|
-
} from "./types";
|
|
12
|
-
import {
|
|
13
|
-
import { generateContractName } from "./utils";
|
|
19
|
+
} from "./types.js";
|
|
20
|
+
import { generateContractName } from "./utils.js";
|
|
14
21
|
|
|
15
22
|
type TrimLeadingSlash<T extends string> = T extends `/${infer Rest}`
|
|
16
23
|
? TrimLeadingSlash<Rest>
|
|
@@ -49,59 +56,6 @@ function joinPathPrefix(prefix: string, path: string): string {
|
|
|
49
56
|
return `/${segments.join("/")}`;
|
|
50
57
|
}
|
|
51
58
|
|
|
52
|
-
function responsesFromErrors(
|
|
53
|
-
errors: ContractErrorResponses,
|
|
54
|
-
): ContractResponses {
|
|
55
|
-
const responses: ContractResponses = {};
|
|
56
|
-
for (const error of Object.values(errors)) {
|
|
57
|
-
responses[error.status] = STANDARD_ERROR_RESPONSE_SCHEMA;
|
|
58
|
-
}
|
|
59
|
-
return responses;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function assertNoResponseStatusConflicts(
|
|
63
|
-
current: ContractResponses,
|
|
64
|
-
next: ContractResponses,
|
|
65
|
-
): void {
|
|
66
|
-
const currentStatuses = new Set(Object.keys(current));
|
|
67
|
-
const conflicts = Object.keys(next).filter((status) =>
|
|
68
|
-
currentStatuses.has(status),
|
|
69
|
-
);
|
|
70
|
-
if (conflicts.length) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
`.errors() cannot declare status ${conflicts.join(", ")} because a response schema for that status already exists. Use .responses() without .errors() when you need a custom error response body.`,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function assertNoCatalogErrorStatusConflicts(
|
|
78
|
-
metadata: ContractMeta,
|
|
79
|
-
next: ContractResponses,
|
|
80
|
-
): void {
|
|
81
|
-
const errors = metadata.errors;
|
|
82
|
-
if (typeof errors !== "object" || errors === null) return;
|
|
83
|
-
|
|
84
|
-
const errorStatuses = new Set(
|
|
85
|
-
Object.values(errors)
|
|
86
|
-
.map((error) =>
|
|
87
|
-
typeof error === "object" &&
|
|
88
|
-
error !== null &&
|
|
89
|
-
typeof (error as { status?: unknown }).status === "number"
|
|
90
|
-
? String((error as { status: number }).status)
|
|
91
|
-
: undefined,
|
|
92
|
-
)
|
|
93
|
-
.filter((status): status is string => status !== undefined),
|
|
94
|
-
);
|
|
95
|
-
const conflicts = Object.keys(next).filter((status) =>
|
|
96
|
-
errorStatuses.has(status),
|
|
97
|
-
);
|
|
98
|
-
if (conflicts.length) {
|
|
99
|
-
throw new Error(
|
|
100
|
-
`.responses() cannot declare status ${conflicts.join(", ")} because that status is already declared by .errors(). Use .responses() without .errors() when you need a custom error response body.`,
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
59
|
/**
|
|
106
60
|
* Feature-scoped factory for related HTTP contracts.
|
|
107
61
|
*
|
|
@@ -195,13 +149,13 @@ export class ContractGroup<
|
|
|
195
149
|
meta: TNewMeta,
|
|
196
150
|
): ContractGroup<
|
|
197
151
|
TSharedResponses,
|
|
198
|
-
|
|
152
|
+
OmitMetaKeys<TSharedMeta, keyof TNewMeta> & TNewMeta,
|
|
199
153
|
TSharedHeaders,
|
|
200
154
|
TPathPrefix
|
|
201
155
|
> {
|
|
202
156
|
return new ContractGroup({
|
|
203
157
|
namespace: this._namespace,
|
|
204
|
-
meta: { ...this._meta, ...meta } as unknown as
|
|
158
|
+
meta: { ...this._meta, ...meta } as unknown as OmitMetaKeys<
|
|
205
159
|
TSharedMeta,
|
|
206
160
|
keyof TNewMeta
|
|
207
161
|
> &
|
|
@@ -226,7 +180,7 @@ export class ContractGroup<
|
|
|
226
180
|
TSharedHeaders,
|
|
227
181
|
TPathPrefix
|
|
228
182
|
> {
|
|
229
|
-
|
|
183
|
+
assertResponsesAvoidCatalogErrorStatuses(this._meta, responseSchemas);
|
|
230
184
|
return new ContractGroup({
|
|
231
185
|
namespace: this._namespace,
|
|
232
186
|
meta: this._meta,
|
|
@@ -244,25 +198,36 @@ export class ContractGroup<
|
|
|
244
198
|
* Declare shared route-owned application errors for contracts in this group.
|
|
245
199
|
*
|
|
246
200
|
* Catalog errors use Beignet's standard error envelope and remain separate
|
|
247
|
-
* from framework-owned errors.
|
|
201
|
+
* from framework-owned errors. Declarations merge with previously declared
|
|
202
|
+
* group errors, and contracts created from the group merge these shared
|
|
203
|
+
* errors with route-level `.errors()` declarations; later declarations win
|
|
204
|
+
* when the same catalog key is declared twice.
|
|
248
205
|
*/
|
|
249
206
|
errors<TErrorDefs extends ContractErrorResponses>(
|
|
250
207
|
errorDefs: TErrorDefs,
|
|
251
208
|
): ContractGroup<
|
|
252
209
|
Omit<TSharedResponses, keyof ResponsesFromErrorDefinitions<TErrorDefs>> &
|
|
253
210
|
ResponsesFromErrorDefinitions<TErrorDefs>,
|
|
254
|
-
|
|
211
|
+
OmitMetaKeys<TSharedMeta, "errors"> & {
|
|
212
|
+
errors: MergedContractErrorResponses<TSharedMeta, TErrorDefs>;
|
|
213
|
+
},
|
|
255
214
|
TSharedHeaders,
|
|
256
215
|
TPathPrefix
|
|
257
216
|
> {
|
|
258
217
|
const errorResponses = responsesFromErrors(errorDefs);
|
|
259
|
-
|
|
218
|
+
assertErrorsAvoidCustomResponseStatuses(
|
|
219
|
+
this._meta,
|
|
220
|
+
this._responses,
|
|
221
|
+
errorResponses,
|
|
222
|
+
);
|
|
260
223
|
return new ContractGroup({
|
|
261
224
|
namespace: this._namespace,
|
|
262
225
|
meta: {
|
|
263
226
|
...this._meta,
|
|
264
|
-
errors: errorDefs,
|
|
265
|
-
} as
|
|
227
|
+
errors: mergeCatalogErrors(this._meta, errorDefs),
|
|
228
|
+
} as unknown as OmitMetaKeys<TSharedMeta, "errors"> & {
|
|
229
|
+
errors: MergedContractErrorResponses<TSharedMeta, TErrorDefs>;
|
|
230
|
+
},
|
|
266
231
|
responses: { ...this._responses, ...errorResponses } as unknown as Omit<
|
|
267
232
|
TSharedResponses,
|
|
268
233
|
keyof ResponsesFromErrorDefinitions<TErrorDefs>
|
|
@@ -495,7 +460,7 @@ export class ContractGroup<
|
|
|
495
460
|
*
|
|
496
461
|
* @example
|
|
497
462
|
* ```ts
|
|
498
|
-
* const todos =
|
|
463
|
+
* const todos = defineContractGroup()
|
|
499
464
|
* .namespace("todos")
|
|
500
465
|
* .prefix("/api/todos")
|
|
501
466
|
* .meta({ auth: "required" })
|
|
@@ -508,7 +473,7 @@ export class ContractGroup<
|
|
|
508
473
|
*
|
|
509
474
|
* @returns An empty immutable contract group.
|
|
510
475
|
*/
|
|
511
|
-
export function
|
|
476
|
+
export function defineContractGroup(): ContractGroup<
|
|
512
477
|
Record<never, never>,
|
|
513
478
|
ContractMeta,
|
|
514
479
|
null,
|
package/src/contracts/index.ts
CHANGED
|
@@ -11,19 +11,22 @@ export type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
|
11
11
|
/**
|
|
12
12
|
* Idempotency metadata types for contracts.
|
|
13
13
|
*/
|
|
14
|
-
export type {
|
|
14
|
+
export type {
|
|
15
|
+
IdempotencyMeta,
|
|
16
|
+
IdempotencyScopeMode,
|
|
17
|
+
} from "../idempotency/index.js";
|
|
15
18
|
/**
|
|
16
19
|
* Contract builder exports.
|
|
17
20
|
*/
|
|
18
21
|
export {
|
|
19
22
|
ContractBuilder,
|
|
20
|
-
type
|
|
21
|
-
|
|
22
|
-
} from "./contract-builder";
|
|
23
|
+
type DefineContractOptions,
|
|
24
|
+
defineContract,
|
|
25
|
+
} from "./contract-builder.js";
|
|
23
26
|
/**
|
|
24
27
|
* Contract group exports.
|
|
25
28
|
*/
|
|
26
|
-
export { ContractGroup,
|
|
29
|
+
export { ContractGroup, defineContractGroup } from "./contract-group.js";
|
|
27
30
|
/**
|
|
28
31
|
* Contract-like helper exports.
|
|
29
32
|
*/
|
|
@@ -31,11 +34,11 @@ export {
|
|
|
31
34
|
type ContractLike,
|
|
32
35
|
type ResolveContract,
|
|
33
36
|
resolveContract,
|
|
34
|
-
} from "./contract-like";
|
|
37
|
+
} from "./contract-like.js";
|
|
35
38
|
/**
|
|
36
39
|
* OpenAPI operation metadata type.
|
|
37
40
|
*/
|
|
38
|
-
export type { OpenAPIOperationMeta } from "./openapi-meta";
|
|
41
|
+
export type { OpenAPIOperationMeta } from "./openapi-meta.js";
|
|
39
42
|
/**
|
|
40
43
|
* Path template parsing exports.
|
|
41
44
|
*/
|
|
@@ -43,11 +46,20 @@ export {
|
|
|
43
46
|
type ParsedPathTemplate,
|
|
44
47
|
type PathTemplateSegment,
|
|
45
48
|
parsePathTemplate,
|
|
46
|
-
} from "./path-template";
|
|
49
|
+
} from "./path-template.js";
|
|
47
50
|
/**
|
|
48
51
|
* Rate limit metadata types for contracts.
|
|
49
52
|
*/
|
|
50
|
-
export type { RateLimitMeta, RateLimitScope } from "./rate-limit";
|
|
53
|
+
export type { RateLimitMeta, RateLimitScope } from "./rate-limit.js";
|
|
54
|
+
/**
|
|
55
|
+
* Success status helpers shared by the server route binder and tooling.
|
|
56
|
+
*/
|
|
57
|
+
export {
|
|
58
|
+
getSuccess2xxStatuses,
|
|
59
|
+
type IsSingle2xx,
|
|
60
|
+
inferSoleSuccessStatus,
|
|
61
|
+
type Success2xxKeys,
|
|
62
|
+
} from "./success-status.js";
|
|
51
63
|
/**
|
|
52
64
|
* Contract config and inference types.
|
|
53
65
|
*/
|
|
@@ -66,15 +78,16 @@ export type {
|
|
|
66
78
|
InferHeaderSchemaOutput,
|
|
67
79
|
InferInput,
|
|
68
80
|
InferOutput,
|
|
81
|
+
MergedContractErrorResponses,
|
|
69
82
|
ResponsesFromErrorDefinitions,
|
|
70
83
|
StandardErrorResponseBody,
|
|
71
84
|
StandardErrorResponseSchema,
|
|
72
85
|
StandardSchema,
|
|
73
|
-
} from "./types";
|
|
86
|
+
} from "./types.js";
|
|
74
87
|
export {
|
|
75
88
|
BEIGNET_ERROR_OWNER_HEADER,
|
|
76
89
|
BODY_HTTP_METHODS,
|
|
77
90
|
getContractHeaderSchemas,
|
|
78
91
|
methodSupportsRequestBody,
|
|
79
92
|
STANDARD_ERROR_RESPONSE_SCHEMA,
|
|
80
|
-
} from "./types";
|
|
93
|
+
} from "./types.js";
|
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* OpenAPI operation-level metadata for HTTP contracts.
|
|
3
3
|
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Inline OpenAPI schema metadata or a `$ref` to a schema component.
|
|
7
|
+
*/
|
|
8
|
+
export type OpenAPISchemaMeta = Record<string, unknown> | { $ref: string };
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* OpenAPI media type metadata for request and response content entries.
|
|
12
|
+
*/
|
|
13
|
+
export type OpenAPIMediaTypeMeta = {
|
|
14
|
+
schema?: OpenAPISchemaMeta;
|
|
15
|
+
examples?: Record<
|
|
16
|
+
string,
|
|
17
|
+
{
|
|
18
|
+
summary?: string;
|
|
19
|
+
value?: unknown;
|
|
20
|
+
}
|
|
21
|
+
>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* OpenAPI request body metadata used to override generated JSON request bodies.
|
|
26
|
+
*/
|
|
27
|
+
export type OpenAPIRequestBodyMeta = {
|
|
28
|
+
required?: boolean;
|
|
29
|
+
description?: string;
|
|
30
|
+
content: Record<string, OpenAPIMediaTypeMeta>;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* OpenAPI response metadata used to add or replace generated responses.
|
|
35
|
+
*/
|
|
36
|
+
export type OpenAPIResponseMeta = {
|
|
37
|
+
description: string;
|
|
38
|
+
content?: Record<string, OpenAPIMediaTypeMeta>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* OpenAPI operation parameter metadata used for custom parameters such as cookies.
|
|
43
|
+
*/
|
|
44
|
+
export type OpenAPIParameterMeta = {
|
|
45
|
+
name: string;
|
|
46
|
+
in: "path" | "query" | "header" | "cookie";
|
|
47
|
+
required?: boolean;
|
|
48
|
+
schema?: OpenAPISchemaMeta;
|
|
49
|
+
description?: string;
|
|
50
|
+
deprecated?: boolean;
|
|
51
|
+
};
|
|
52
|
+
|
|
4
53
|
export type OpenAPIOperationMeta = {
|
|
5
54
|
/** Brief operation summary. */
|
|
6
55
|
summary?: string;
|
|
@@ -19,4 +68,10 @@ export type OpenAPIOperationMeta = {
|
|
|
19
68
|
operationId?: string;
|
|
20
69
|
/** Per-operation security requirements. */
|
|
21
70
|
security?: Array<Record<string, string[]>>;
|
|
71
|
+
/** Additional or replacement operation parameters. */
|
|
72
|
+
parameters?: OpenAPIParameterMeta[];
|
|
73
|
+
/** Replacement request body for non-JSON media such as multipart uploads. */
|
|
74
|
+
requestBody?: OpenAPIRequestBodyMeta;
|
|
75
|
+
/** Additional or replacement responses, useful for files and streams. */
|
|
76
|
+
responses?: Record<string, OpenAPIResponseMeta>;
|
|
22
77
|
};
|
|
@@ -38,7 +38,7 @@ const BRACKET_PARAM = new RegExp(`^\\[(${PARAM_NAME})\\]$`);
|
|
|
38
38
|
function createPathTemplateError(path: string, segment: string): Error {
|
|
39
39
|
return new Error(
|
|
40
40
|
`Unsupported path template segment "${segment}" in "${path}". ` +
|
|
41
|
-
"Use single-segment params like :id or [id].
|
|
41
|
+
"Use single-segment params like :id or [id]. Contract catch-all params such as [...path] and partial-segment params are not supported. Expose a platform catch-all route to the Beignet server, but keep individual contracts on concrete paths.",
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -68,7 +68,7 @@ function parsePathSegment(path: string, segment: string): PathTemplateSegment {
|
|
|
68
68
|
* Parse a Beignet route path template.
|
|
69
69
|
*
|
|
70
70
|
* Paths must start with `/`. Dynamic segments may use `:id` or `[id]`.
|
|
71
|
-
*
|
|
71
|
+
* Contract catch-all segments and partial dynamic segments are intentionally rejected.
|
|
72
72
|
*/
|
|
73
73
|
export function parsePathTemplate(path: string): ParsedPathTemplate {
|
|
74
74
|
if (!path.startsWith("/")) {
|