@beignet/core 0.0.1 → 0.0.3
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 +27 -0
- package/README.md +202 -8
- package/dist/application/index.d.ts +93 -9
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +11 -11
- package/dist/application/index.js.map +1 -1
- package/dist/client/client.d.ts +73 -12
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +37 -12
- package/dist/client/client.js.map +1 -1
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +69 -8
- package/dist/client/types.d.ts.map +1 -1
- package/dist/config/index.d.ts +84 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +36 -0
- package/dist/config/index.js.map +1 -1
- package/dist/contracts/contract-builder.d.ts +49 -22
- package/dist/contracts/contract-builder.d.ts.map +1 -1
- package/dist/contracts/contract-builder.js +48 -21
- package/dist/contracts/contract-builder.js.map +1 -1
- package/dist/contracts/contract-group.d.ts +35 -19
- package/dist/contracts/contract-group.d.ts.map +1 -1
- package/dist/contracts/contract-group.js +35 -19
- package/dist/contracts/contract-group.js.map +1 -1
- package/dist/contracts/contract-like.d.ts +4 -4
- package/dist/contracts/contract-like.d.ts.map +1 -1
- package/dist/contracts/contract-like.js +2 -1
- package/dist/contracts/contract-like.js.map +1 -1
- package/dist/contracts/index.d.ts +28 -0
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +12 -0
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/openapi-meta.d.ts +8 -8
- package/dist/contracts/openapi-meta.d.ts.map +1 -1
- package/dist/contracts/path-template.d.ts +27 -0
- package/dist/contracts/path-template.d.ts.map +1 -1
- package/dist/contracts/path-template.js +6 -0
- package/dist/contracts/path-template.js.map +1 -1
- package/dist/contracts/types.d.ts +104 -10
- package/dist/contracts/types.d.ts.map +1 -1
- package/dist/contracts/types.js +15 -0
- package/dist/contracts/types.js.map +1 -1
- package/dist/contracts/utils.d.ts +6 -0
- package/dist/contracts/utils.d.ts.map +1 -1
- package/dist/contracts/utils.js +6 -0
- package/dist/contracts/utils.js.map +1 -1
- package/dist/domain/entity.d.ts +22 -11
- package/dist/domain/entity.d.ts.map +1 -1
- package/dist/domain/entity.js +5 -1
- package/dist/domain/entity.js.map +1 -1
- package/dist/domain/events.d.ts +5 -2
- package/dist/domain/events.d.ts.map +1 -1
- package/dist/domain/events.js +4 -1
- package/dist/domain/events.js.map +1 -1
- package/dist/domain/value-object.d.ts +19 -9
- package/dist/domain/value-object.d.ts.map +1 -1
- package/dist/domain/value-object.js +5 -1
- package/dist/domain/value-object.js.map +1 -1
- package/dist/errors/catalog.d.ts +40 -16
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/catalog.js +18 -7
- package/dist/errors/catalog.js.map +1 -1
- package/dist/errors/response.d.ts +16 -4
- package/dist/errors/response.d.ts.map +1 -1
- package/dist/errors/response.js +3 -3
- package/dist/errors/response.js.map +1 -1
- package/dist/errors/validation.d.ts +10 -1
- package/dist/errors/validation.d.ts.map +1 -1
- package/dist/errors/validation.js +3 -0
- package/dist/errors/validation.js.map +1 -1
- package/dist/events/index.d.ts +133 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +30 -0
- package/dist/events/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +355 -0
- package/dist/idempotency/index.d.ts.map +1 -0
- package/dist/idempotency/index.js +360 -0
- package/dist/idempotency/index.js.map +1 -0
- package/dist/jobs/index.d.ts +248 -4
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +183 -1
- package/dist/jobs/index.js.map +1 -1
- package/dist/mail/index.d.ts +149 -0
- package/dist/mail/index.d.ts.map +1 -1
- package/dist/mail/index.js +30 -0
- package/dist/mail/index.js.map +1 -1
- package/dist/notifications/index.d.ts +369 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +310 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/openapi/index.d.ts +132 -16
- package/dist/openapi/index.d.ts.map +1 -1
- package/dist/openapi/index.js +1 -1
- package/dist/openapi/index.js.map +1 -1
- package/dist/outbox/index.d.ts +474 -0
- package/dist/outbox/index.d.ts.map +1 -0
- package/dist/outbox/index.js +538 -0
- package/dist/outbox/index.js.map +1 -0
- package/dist/pagination/index.d.ts +166 -0
- package/dist/pagination/index.d.ts.map +1 -0
- package/dist/pagination/index.js +96 -0
- package/dist/pagination/index.js.map +1 -0
- package/dist/ports/audit.d.ts +271 -0
- package/dist/ports/audit.d.ts.map +1 -1
- package/dist/ports/audit.js +128 -0
- package/dist/ports/audit.js.map +1 -1
- package/dist/ports/auth.d.ts +70 -0
- package/dist/ports/auth.d.ts.map +1 -1
- package/dist/ports/auth.js +30 -0
- package/dist/ports/auth.js.map +1 -1
- package/dist/ports/cache.d.ts +41 -0
- package/dist/ports/cache.d.ts.map +1 -1
- package/dist/ports/cache.js +10 -0
- package/dist/ports/cache.js.map +1 -1
- package/dist/ports/clock.d.ts +38 -0
- package/dist/ports/clock.d.ts.map +1 -1
- package/dist/ports/clock.js +20 -0
- package/dist/ports/clock.js.map +1 -1
- package/dist/ports/id-generator.d.ts +37 -0
- package/dist/ports/id-generator.d.ts.map +1 -1
- package/dist/ports/id-generator.js +22 -0
- package/dist/ports/id-generator.js.map +1 -1
- package/dist/ports/index.d.ts +83 -0
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js +41 -5
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/logger.d.ts +56 -0
- package/dist/ports/logger.d.ts.map +1 -1
- package/dist/ports/logger.js +17 -0
- package/dist/ports/logger.js.map +1 -1
- package/dist/ports/policy.d.ts +132 -0
- package/dist/ports/policy.d.ts.map +1 -1
- package/dist/ports/policy.js +45 -0
- package/dist/ports/policy.js.map +1 -1
- package/dist/ports/rate-limit.d.ts +25 -0
- package/dist/ports/rate-limit.d.ts.map +1 -1
- package/dist/ports/rate-limit.js +10 -0
- package/dist/ports/rate-limit.js.map +1 -1
- package/dist/ports/redaction.d.ts +101 -0
- package/dist/ports/redaction.d.ts.map +1 -1
- package/dist/ports/redaction.js +59 -0
- package/dist/ports/redaction.js.map +1 -1
- package/dist/ports/storage.d.ts +100 -0
- package/dist/ports/storage.d.ts.map +1 -1
- package/dist/ports/storage.js +10 -0
- package/dist/ports/storage.js.map +1 -1
- package/dist/ports/testing.d.ts +47 -0
- package/dist/ports/testing.d.ts.map +1 -1
- package/dist/ports/testing.js +23 -0
- package/dist/ports/testing.js.map +1 -1
- package/dist/ports/unit-of-work.d.ts +60 -3
- package/dist/ports/unit-of-work.d.ts.map +1 -1
- package/dist/ports/unit-of-work.js +11 -2
- package/dist/ports/unit-of-work.js.map +1 -1
- package/dist/providers/instrumentation.d.ts +205 -1
- package/dist/providers/instrumentation.d.ts.map +1 -1
- package/dist/providers/instrumentation.js +14 -0
- package/dist/providers/instrumentation.js.map +1 -1
- package/dist/providers/provider.d.ts +14 -1
- package/dist/providers/provider.d.ts.map +1 -1
- package/dist/providers/provider.js.map +1 -1
- package/dist/schedules/index.d.ts +246 -0
- package/dist/schedules/index.d.ts.map +1 -1
- package/dist/schedules/index.js +27 -0
- package/dist/schedules/index.js.map +1 -1
- package/dist/server/health.d.ts +14 -5
- package/dist/server/health.d.ts.map +1 -1
- package/dist/server/health.js +5 -2
- package/dist/server/health.js.map +1 -1
- package/dist/server/hooks/auth.d.ts +68 -26
- package/dist/server/hooks/auth.d.ts.map +1 -1
- package/dist/server/hooks/auth.js +44 -55
- package/dist/server/hooks/auth.js.map +1 -1
- package/dist/server/hooks/cors.d.ts +27 -0
- package/dist/server/hooks/cors.d.ts.map +1 -1
- package/dist/server/hooks/cors.js +12 -0
- package/dist/server/hooks/cors.js.map +1 -1
- package/dist/server/hooks/errors.d.ts +15 -6
- package/dist/server/hooks/errors.d.ts.map +1 -1
- package/dist/server/hooks/errors.js.map +1 -1
- package/dist/server/hooks/index.d.ts +4 -1
- package/dist/server/hooks/index.d.ts.map +1 -1
- package/dist/server/hooks/index.js +3 -0
- package/dist/server/hooks/index.js.map +1 -1
- package/dist/server/hooks/logging.d.ts +36 -0
- package/dist/server/hooks/logging.d.ts.map +1 -1
- package/dist/server/hooks/logging.js +6 -0
- package/dist/server/hooks/logging.js.map +1 -1
- package/dist/server/hooks/rate-limit.d.ts +33 -0
- package/dist/server/hooks/rate-limit.d.ts.map +1 -1
- package/dist/server/hooks/rate-limit.js +11 -0
- package/dist/server/hooks/rate-limit.js.map +1 -1
- package/dist/server/http.d.ts +222 -0
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +20 -1
- package/dist/server/http.js.map +1 -1
- package/dist/server/index.d.ts +19 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +7 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/openapi.d.ts +5 -3
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/openapi.js +4 -2
- package/dist/server/openapi.js.map +1 -1
- package/dist/server/providers/loadProviderConfig.d.ts +9 -0
- package/dist/server/providers/loadProviderConfig.d.ts.map +1 -1
- package/dist/server/providers/loadProviderConfig.js +9 -0
- package/dist/server/providers/loadProviderConfig.js.map +1 -1
- package/dist/server/server.d.ts +159 -19
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +72 -31
- package/dist/server/server.js.map +1 -1
- package/dist/testing/index.d.ts +171 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +127 -0
- package/dist/testing/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 +31 -2
- package/src/application/index.ts +85 -22
- package/src/client/client.ts +73 -12
- package/src/client/index.ts +12 -0
- package/src/client/types.ts +70 -9
- package/src/config/index.ts +86 -0
- package/src/contracts/contract-builder.ts +49 -22
- package/src/contracts/contract-group.ts +35 -19
- package/src/contracts/contract-like.ts +4 -4
- package/src/contracts/index.ts +28 -1
- package/src/contracts/openapi-meta.ts +8 -8
- package/src/contracts/path-template.ts +27 -0
- package/src/contracts/types.ts +111 -10
- package/src/contracts/utils.ts +6 -0
- package/src/domain/entity.ts +22 -11
- package/src/domain/events.ts +5 -2
- package/src/domain/value-object.ts +19 -9
- package/src/errors/catalog.ts +40 -16
- package/src/errors/response.ts +16 -4
- package/src/errors/validation.ts +10 -1
- package/src/events/index.ts +134 -0
- package/src/idempotency/index.ts +767 -0
- package/src/jobs/index.ts +437 -5
- package/src/mail/index.ts +149 -0
- package/src/notifications/index.ts +771 -0
- package/src/openapi/index.ts +133 -16
- package/src/outbox/index.ts +1104 -0
- package/src/pagination/index.ts +278 -0
- package/src/ports/audit.ts +271 -0
- package/src/ports/auth.ts +70 -0
- package/src/ports/cache.ts +41 -0
- package/src/ports/clock.ts +38 -0
- package/src/ports/id-generator.ts +37 -0
- package/src/ports/index.ts +106 -11
- package/src/ports/logger.ts +56 -0
- package/src/ports/policy.ts +133 -0
- package/src/ports/rate-limit.ts +25 -0
- package/src/ports/redaction.ts +101 -0
- package/src/ports/storage.ts +100 -0
- package/src/ports/testing.ts +47 -0
- package/src/ports/unit-of-work.ts +60 -3
- package/src/providers/instrumentation.ts +211 -1
- package/src/providers/provider.ts +14 -1
- package/src/schedules/index.ts +247 -0
- package/src/server/health.ts +14 -5
- package/src/server/hooks/auth.ts +105 -120
- package/src/server/hooks/cors.ts +27 -0
- package/src/server/hooks/errors.ts +15 -6
- package/src/server/hooks/index.ts +4 -5
- package/src/server/hooks/logging.ts +36 -0
- package/src/server/hooks/rate-limit.ts +33 -0
- package/src/server/http.ts +249 -1
- package/src/server/index.ts +19 -1
- package/src/server/openapi.ts +5 -3
- package/src/server/providers/loadProviderConfig.ts +9 -0
- package/src/server/server.ts +296 -30
- package/src/testing/index.ts +348 -0
- package/src/uploads/client.ts +861 -0
- package/src/uploads/index.ts +1067 -0
package/src/contracts/types.ts
CHANGED
|
@@ -1,42 +1,93 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import type { IdempotencyMeta } from "../idempotency";
|
|
2
3
|
import type { OpenAPIOperationMeta } from "./openapi-meta";
|
|
3
4
|
import type { RateLimitMeta } from "./rate-limit";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Any Standard Schema validator
|
|
7
|
-
* Replaces ZodTypeAny to support all Standard Schema compatible libraries
|
|
7
|
+
* Any Standard Schema compatible validator.
|
|
8
8
|
*/
|
|
9
9
|
export type StandardSchema = StandardSchemaV1<unknown, unknown>;
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Response schema for one HTTP status.
|
|
13
|
+
*
|
|
14
|
+
* Use `null` for empty responses such as 204.
|
|
15
|
+
*/
|
|
11
16
|
export type ContractResponseSchema = StandardSchema | null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Response schemas keyed by HTTP status code.
|
|
20
|
+
*/
|
|
12
21
|
export type ContractResponses = Partial<Record<number, ContractResponseSchema>>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Standard Beignet error response body.
|
|
25
|
+
*/
|
|
13
26
|
export type StandardErrorResponseBody = {
|
|
14
27
|
code: string;
|
|
15
28
|
message: string;
|
|
16
29
|
details?: unknown;
|
|
17
30
|
requestId?: string;
|
|
18
31
|
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Standard Schema for Beignet's error envelope.
|
|
35
|
+
*/
|
|
19
36
|
export type StandardErrorResponseSchema = StandardSchemaV1<
|
|
20
37
|
unknown,
|
|
21
38
|
StandardErrorResponseBody
|
|
22
39
|
>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Route-owned error definition stored in contract metadata.
|
|
43
|
+
*/
|
|
23
44
|
export type ContractErrorDefinition = {
|
|
45
|
+
/**
|
|
46
|
+
* Stable public error code.
|
|
47
|
+
*/
|
|
24
48
|
code: string;
|
|
49
|
+
/**
|
|
50
|
+
* HTTP status code.
|
|
51
|
+
*/
|
|
25
52
|
status: number;
|
|
53
|
+
/**
|
|
54
|
+
* Default human-readable message.
|
|
55
|
+
*/
|
|
26
56
|
message: string;
|
|
57
|
+
/**
|
|
58
|
+
* Optional details schema for TypeScript inference.
|
|
59
|
+
*/
|
|
27
60
|
details?: StandardSchema;
|
|
28
61
|
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Route-owned error definitions keyed by catalog key.
|
|
65
|
+
*/
|
|
29
66
|
export type ContractErrorResponses = Record<string, ContractErrorDefinition>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Convert route-owned error definitions into standard envelope response schemas.
|
|
70
|
+
*/
|
|
30
71
|
export type ResponsesFromErrorDefinitions<T extends ContractErrorResponses> = {
|
|
31
72
|
[K in keyof T as T[K]["status"]]: StandardErrorResponseSchema;
|
|
32
73
|
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Header schema declaration for a contract.
|
|
77
|
+
*/
|
|
33
78
|
export type ContractHeaderSchemas =
|
|
34
79
|
| StandardSchema
|
|
35
80
|
| readonly StandardSchema[]
|
|
36
81
|
| null;
|
|
37
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Header used to distinguish framework-owned and route-owned error responses.
|
|
85
|
+
*/
|
|
38
86
|
export const BEIGNET_ERROR_OWNER_HEADER = "x-beignet-error-owner";
|
|
39
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Infer merged header input from one or more Standard Schema header validators.
|
|
90
|
+
*/
|
|
40
91
|
export type InferHeaderSchemaInput<
|
|
41
92
|
T extends ContractHeaderSchemas | undefined,
|
|
42
93
|
> = T extends readonly StandardSchemaV1[]
|
|
@@ -45,6 +96,9 @@ export type InferHeaderSchemaInput<
|
|
|
45
96
|
? InferInput<T>
|
|
46
97
|
: undefined;
|
|
47
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Infer merged header output from one or more Standard Schema header validators.
|
|
101
|
+
*/
|
|
48
102
|
export type InferHeaderSchemaOutput<
|
|
49
103
|
T extends ContractHeaderSchemas | undefined,
|
|
50
104
|
> = T extends readonly StandardSchemaV1[]
|
|
@@ -62,19 +116,19 @@ type UnionToIntersection<T> = (
|
|
|
62
116
|
: never;
|
|
63
117
|
|
|
64
118
|
/**
|
|
65
|
-
* Infer the output type from a Standard Schema
|
|
119
|
+
* Infer the parsed output type from a Standard Schema.
|
|
66
120
|
*/
|
|
67
121
|
export type InferOutput<T extends StandardSchemaV1> =
|
|
68
122
|
StandardSchemaV1.InferOutput<T>;
|
|
69
123
|
|
|
70
124
|
/**
|
|
71
|
-
* Infer the input type
|
|
125
|
+
* Infer the input type accepted by a Standard Schema.
|
|
72
126
|
*/
|
|
73
127
|
export type InferInput<T extends StandardSchemaV1> =
|
|
74
128
|
StandardSchemaV1.InferInput<T>;
|
|
75
129
|
|
|
76
130
|
/**
|
|
77
|
-
* HTTP methods supported by contracts
|
|
131
|
+
* HTTP methods supported by contracts.
|
|
78
132
|
*/
|
|
79
133
|
export type HttpMethod =
|
|
80
134
|
| "GET"
|
|
@@ -85,20 +139,32 @@ export type HttpMethod =
|
|
|
85
139
|
| "HEAD"
|
|
86
140
|
| "OPTIONS";
|
|
87
141
|
|
|
142
|
+
/**
|
|
143
|
+
* HTTP methods that may carry a JSON request body.
|
|
144
|
+
*/
|
|
88
145
|
export type BodyHttpMethod = Extract<HttpMethod, "POST" | "PUT" | "PATCH">;
|
|
89
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Runtime list of HTTP methods that support request bodies.
|
|
149
|
+
*/
|
|
90
150
|
export const BODY_HTTP_METHODS = [
|
|
91
151
|
"POST",
|
|
92
152
|
"PUT",
|
|
93
153
|
"PATCH",
|
|
94
154
|
] as const satisfies readonly BodyHttpMethod[];
|
|
95
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Check whether a method supports a contract request body.
|
|
158
|
+
*/
|
|
96
159
|
export function methodSupportsRequestBody(
|
|
97
160
|
method: HttpMethod,
|
|
98
161
|
): method is BodyHttpMethod {
|
|
99
162
|
return (BODY_HTTP_METHODS as readonly HttpMethod[]).includes(method);
|
|
100
163
|
}
|
|
101
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Runtime Standard Schema for Beignet's standard error envelope.
|
|
167
|
+
*/
|
|
102
168
|
export const STANDARD_ERROR_RESPONSE_SCHEMA: StandardErrorResponseSchema = {
|
|
103
169
|
"~standard": {
|
|
104
170
|
version: 1,
|
|
@@ -140,11 +206,12 @@ export const STANDARD_ERROR_RESPONSE_SCHEMA: StandardErrorResponseSchema = {
|
|
|
140
206
|
};
|
|
141
207
|
|
|
142
208
|
/**
|
|
143
|
-
* Contract metadata
|
|
144
|
-
* May include an optional openapi namespace for OpenAPI-specific metadata,
|
|
145
|
-
* and an optional rateLimit namespace for rate limiting configuration.
|
|
209
|
+
* Contract metadata consumed by hooks, OpenAPI, and app conventions.
|
|
146
210
|
*/
|
|
147
211
|
export type ContractMeta = {
|
|
212
|
+
/**
|
|
213
|
+
* OpenAPI operation metadata.
|
|
214
|
+
*/
|
|
148
215
|
openapi?: OpenAPIOperationMeta;
|
|
149
216
|
/**
|
|
150
217
|
* Optional rate limit configuration for this contract.
|
|
@@ -152,11 +219,18 @@ export type ContractMeta = {
|
|
|
152
219
|
* If absent, no rate limiting is applied.
|
|
153
220
|
*/
|
|
154
221
|
rateLimit?: RateLimitMeta;
|
|
222
|
+
/**
|
|
223
|
+
* Optional idempotency configuration for this contract.
|
|
224
|
+
*
|
|
225
|
+
* This metadata is intended for hooks, docs, and OpenAPI. Use cases should
|
|
226
|
+
* still call `runIdempotently(...)` for workflows that must be retry-safe.
|
|
227
|
+
*/
|
|
228
|
+
idempotency?: IdempotencyMeta;
|
|
155
229
|
[namespace: string]: unknown;
|
|
156
230
|
};
|
|
157
231
|
|
|
158
232
|
/**
|
|
159
|
-
* HTTP contract configuration
|
|
233
|
+
* Plain HTTP contract configuration consumed by server, client, and tooling.
|
|
160
234
|
*/
|
|
161
235
|
export type HttpContractConfig<
|
|
162
236
|
TMethod extends HttpMethod = HttpMethod,
|
|
@@ -182,21 +256,48 @@ export type HttpContractConfig<
|
|
|
182
256
|
* Contract name without the resource namespace.
|
|
183
257
|
*/
|
|
184
258
|
localName?: string;
|
|
259
|
+
/**
|
|
260
|
+
* HTTP method.
|
|
261
|
+
*/
|
|
185
262
|
method: TMethod;
|
|
263
|
+
/**
|
|
264
|
+
* Path template.
|
|
265
|
+
*/
|
|
186
266
|
path: TPath;
|
|
267
|
+
/**
|
|
268
|
+
* Path parameter schema.
|
|
269
|
+
*/
|
|
187
270
|
pathParams: TPathParams;
|
|
271
|
+
/**
|
|
272
|
+
* Query parameter schema.
|
|
273
|
+
*/
|
|
188
274
|
query: TQuery;
|
|
275
|
+
/**
|
|
276
|
+
* Request header schema or schemas.
|
|
277
|
+
*/
|
|
189
278
|
headers?: THeaders;
|
|
279
|
+
/**
|
|
280
|
+
* Request body schema.
|
|
281
|
+
*/
|
|
190
282
|
body: TBody;
|
|
283
|
+
/**
|
|
284
|
+
* Response schemas keyed by HTTP status code.
|
|
285
|
+
*/
|
|
191
286
|
responses: TResponses;
|
|
287
|
+
/**
|
|
288
|
+
* Contract metadata.
|
|
289
|
+
*/
|
|
192
290
|
metadata: TMeta;
|
|
193
291
|
};
|
|
194
292
|
|
|
195
293
|
/**
|
|
196
|
-
* Any contract
|
|
294
|
+
* Any HTTP contract config.
|
|
197
295
|
*/
|
|
198
296
|
export type AnyContract = HttpContractConfig;
|
|
199
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Normalize a contract header declaration into a schema list.
|
|
300
|
+
*/
|
|
200
301
|
export function getContractHeaderSchemas(
|
|
201
302
|
headers: ContractHeaderSchemas | undefined,
|
|
202
303
|
): readonly StandardSchema[] {
|
package/src/contracts/utils.ts
CHANGED
|
@@ -33,6 +33,12 @@ function getMeaningfulPathSegments(path: string): PathTemplateSegment[] {
|
|
|
33
33
|
return segments;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Generate a stable contract name from an HTTP method and path.
|
|
38
|
+
*
|
|
39
|
+
* `/api` is ignored as a leading path segment so generated names focus on the
|
|
40
|
+
* resource shape.
|
|
41
|
+
*/
|
|
36
42
|
export function generateContractName(method: HttpMethod, path: string): string {
|
|
37
43
|
const methodPrefix = methodNameMap[method];
|
|
38
44
|
const segments = getMeaningfulPathSegments(path);
|
package/src/domain/entity.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Any Standard Schema validator
|
|
4
|
+
* Any Standard Schema compatible validator.
|
|
5
5
|
*/
|
|
6
6
|
export type StandardSchema = StandardSchemaV1<unknown, unknown>;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Infer the output type from a Standard Schema
|
|
9
|
+
* Infer the parsed output type from a Standard Schema.
|
|
10
10
|
*/
|
|
11
11
|
export type InferOutput<T extends StandardSchemaV1> =
|
|
12
12
|
StandardSchemaV1.InferOutput<T>;
|
|
@@ -67,7 +67,8 @@ function validateSchemaSync<T>(
|
|
|
67
67
|
type AnyMethods = Record<string, any>;
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
|
-
*
|
|
70
|
+
* Entity instance with validated props, attached methods, and immutable update
|
|
71
|
+
* helpers.
|
|
71
72
|
*/
|
|
72
73
|
export type EntityInstance<
|
|
73
74
|
Name extends string,
|
|
@@ -75,7 +76,7 @@ export type EntityInstance<
|
|
|
75
76
|
Methods extends AnyMethods,
|
|
76
77
|
> = InferOutput<Schema> & {
|
|
77
78
|
/**
|
|
78
|
-
* Create a new entity instance with
|
|
79
|
+
* Create a new validated entity instance with patched properties.
|
|
79
80
|
*/
|
|
80
81
|
with(
|
|
81
82
|
patch: Partial<InferOutput<Schema>>,
|
|
@@ -89,30 +90,36 @@ export type EntityInstance<
|
|
|
89
90
|
} & Methods;
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
|
-
*
|
|
93
|
+
* Entity definition returned by `defineEntity(...).build()`.
|
|
93
94
|
*/
|
|
94
95
|
export interface EntityDef<
|
|
95
96
|
Name extends string,
|
|
96
97
|
Schema extends StandardSchema,
|
|
97
98
|
Methods extends AnyMethods,
|
|
98
99
|
> {
|
|
99
|
-
/**
|
|
100
|
+
/** Name used for debugging and introspection. */
|
|
100
101
|
name: Name;
|
|
101
|
-
/**
|
|
102
|
+
/** Standard Schema used to validate entity props. */
|
|
102
103
|
schema: Schema;
|
|
103
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* Create a new frozen entity instance from props.
|
|
106
|
+
*
|
|
107
|
+
* Returns a promise when the underlying Standard Schema validates async.
|
|
108
|
+
*/
|
|
104
109
|
create(
|
|
105
110
|
props: InferOutput<Schema>,
|
|
106
111
|
):
|
|
107
112
|
| EntityInstance<Name, Schema, Methods>
|
|
108
113
|
| Promise<EntityInstance<Name, Schema, Methods>>;
|
|
109
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Reconstruct an entity instance from JSON, usually from persistence.
|
|
116
|
+
*/
|
|
110
117
|
fromJSON(
|
|
111
118
|
json: InferOutput<Schema>,
|
|
112
119
|
):
|
|
113
120
|
| EntityInstance<Name, Schema, Methods>
|
|
114
121
|
| Promise<EntityInstance<Name, Schema, Methods>>;
|
|
115
|
-
/** Type alias for the entity instance type */
|
|
122
|
+
/** Type-only alias for the entity instance type. Undefined at runtime. */
|
|
116
123
|
Type: EntityInstance<Name, Schema, Methods>;
|
|
117
124
|
}
|
|
118
125
|
|
|
@@ -229,7 +236,11 @@ class EntityBuilder<
|
|
|
229
236
|
}
|
|
230
237
|
|
|
231
238
|
/**
|
|
232
|
-
* Create a new
|
|
239
|
+
* Create a new entity builder.
|
|
240
|
+
*
|
|
241
|
+
* Entities validate props, attach domain methods, and return frozen immutable
|
|
242
|
+
* instances. `with(...)` revalidates the merged props. `.Type` is type-only and
|
|
243
|
+
* should be used with `typeof Entity.Type`.
|
|
233
244
|
*
|
|
234
245
|
* @example
|
|
235
246
|
* ```ts
|
package/src/domain/events.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { EventDef, InferEventPayload, StandardSchema } from "../events";
|
|
|
2
2
|
import { defineEvent } from "../events";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Domain event definition with a stable name and payload schema.
|
|
6
6
|
*/
|
|
7
7
|
export type DomainEventDef<
|
|
8
8
|
Name extends string = string,
|
|
@@ -29,7 +29,10 @@ export type DomainEventDef<
|
|
|
29
29
|
export type { InferEventPayload };
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
* Create a new
|
|
32
|
+
* Create a new domain event definition.
|
|
33
|
+
*
|
|
34
|
+
* This is a domain-focused alias around `defineEvent(...)` for applications
|
|
35
|
+
* that separate domain events from integration events.
|
|
33
36
|
*
|
|
34
37
|
* @example
|
|
35
38
|
* ```ts
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Any Standard Schema validator
|
|
4
|
+
* Any Standard Schema compatible validator.
|
|
5
5
|
*/
|
|
6
6
|
export type StandardSchema = StandardSchemaV1<unknown, unknown>;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Infer the output type from a Standard Schema
|
|
9
|
+
* Infer the parsed output type from a Standard Schema.
|
|
10
10
|
*/
|
|
11
11
|
export type InferOutput<T extends StandardSchemaV1> =
|
|
12
12
|
StandardSchemaV1.InferOutput<T>;
|
|
@@ -51,21 +51,27 @@ async function isValid<T>(
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* Value object definition returned by `defineValueObject(...).build()`.
|
|
55
55
|
*/
|
|
56
56
|
export interface ValueObjectDef<
|
|
57
57
|
Name extends string,
|
|
58
58
|
Schema extends StandardSchema,
|
|
59
59
|
> {
|
|
60
|
-
/**
|
|
60
|
+
/** Name used for debugging and introspection. */
|
|
61
61
|
name: Name;
|
|
62
|
-
/**
|
|
62
|
+
/** Standard Schema used to validate values. */
|
|
63
63
|
schema: Schema;
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Create a validated value from unknown input.
|
|
66
|
+
*
|
|
67
|
+
* This is async because Standard Schema validators may be async.
|
|
68
|
+
*/
|
|
65
69
|
create(input: unknown): Promise<InferOutput<Schema>>;
|
|
66
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Check whether an input is valid for this value object.
|
|
72
|
+
*/
|
|
67
73
|
isValid(input: unknown): Promise<boolean>;
|
|
68
|
-
/** Type alias for the inferred TypeScript type */
|
|
74
|
+
/** Type-only alias for the inferred TypeScript type. Undefined at runtime. */
|
|
69
75
|
Type: InferOutput<Schema>;
|
|
70
76
|
}
|
|
71
77
|
|
|
@@ -115,7 +121,11 @@ class ValueObjectBuilder<Name extends string, Schema extends StandardSchema> {
|
|
|
115
121
|
}
|
|
116
122
|
|
|
117
123
|
/**
|
|
118
|
-
* Create a new
|
|
124
|
+
* Create a new value object builder.
|
|
125
|
+
*
|
|
126
|
+
* Value objects are schema-backed primitives for domain concepts such as email
|
|
127
|
+
* addresses or money values. Beignet does not add a runtime brand; the schema
|
|
128
|
+
* output controls the runtime value.
|
|
119
129
|
*
|
|
120
130
|
* @example
|
|
121
131
|
* ```ts
|
package/src/errors/catalog.ts
CHANGED
|
@@ -8,29 +8,39 @@ type ErrorDetailsSchema = StandardSchemaV1<unknown, unknown>;
|
|
|
8
8
|
const APP_ERROR_BRAND = Symbol.for("beignet.AppError");
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Definition
|
|
11
|
+
* Definition for one application error catalog entry.
|
|
12
12
|
*/
|
|
13
13
|
export interface ErrorDef<
|
|
14
14
|
TDetails extends ErrorDetailsSchema | undefined =
|
|
15
15
|
| ErrorDetailsSchema
|
|
16
16
|
| undefined,
|
|
17
17
|
> {
|
|
18
|
-
/** Unique, stable code used across layers
|
|
18
|
+
/** Unique, stable code used across layers, such as `"POST_NOT_FOUND"`. */
|
|
19
19
|
code: string;
|
|
20
|
-
/** HTTP status code
|
|
20
|
+
/** HTTP status code returned when this error crosses the HTTP boundary. */
|
|
21
21
|
status: number;
|
|
22
|
-
/** Default human-readable message */
|
|
22
|
+
/** Default human-readable message. */
|
|
23
23
|
message: string;
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Optional schema for the structured details value.
|
|
26
|
+
*
|
|
27
|
+
* Beignet uses this for TypeScript inference. Details are not runtime
|
|
28
|
+
* validated by `AppError`; validate before constructing errors when needed.
|
|
29
|
+
*/
|
|
25
30
|
details?: TDetails;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
34
|
+
* App error catalog keyed by developer-friendly names.
|
|
35
|
+
*
|
|
36
|
+
* Keys are local identifiers used by `createAppError(...)`; the public stable
|
|
37
|
+
* error code lives on each `ErrorDef.code`.
|
|
31
38
|
*/
|
|
32
39
|
export type ErrorCatalog = Record<string, ErrorDef>;
|
|
33
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Infer the details input type for an error definition.
|
|
43
|
+
*/
|
|
34
44
|
export type InferErrorDetails<TDef extends ErrorDef> = TDef extends {
|
|
35
45
|
details: ErrorDetailsSchema;
|
|
36
46
|
}
|
|
@@ -38,21 +48,23 @@ export type InferErrorDetails<TDef extends ErrorDef> = TDef extends {
|
|
|
38
48
|
: unknown;
|
|
39
49
|
|
|
40
50
|
/**
|
|
41
|
-
*
|
|
51
|
+
* Define an application error catalog without losing literal key and code types.
|
|
42
52
|
*/
|
|
43
53
|
export function defineErrors<const T extends ErrorCatalog>(defs: T): T {
|
|
44
54
|
return defs;
|
|
45
55
|
}
|
|
46
56
|
|
|
47
57
|
/**
|
|
48
|
-
* Application error
|
|
49
|
-
*
|
|
58
|
+
* Application error thrown from use cases, policies, and route handlers.
|
|
59
|
+
*
|
|
60
|
+
* The server maps `AppError` instances to Beignet's standard error envelope and
|
|
61
|
+
* marks them as route-owned errors when the contract declares the catalog entry.
|
|
50
62
|
*/
|
|
51
63
|
export class AppError<TDef extends ErrorDef = ErrorDef> extends Error {
|
|
52
64
|
readonly [APP_ERROR_BRAND] = true;
|
|
53
|
-
/**
|
|
65
|
+
/** Error definition from the catalog. */
|
|
54
66
|
readonly def: TDef;
|
|
55
|
-
/** Optional structured details
|
|
67
|
+
/** Optional structured details for clients, logs, or UI. */
|
|
56
68
|
readonly details?: InferErrorDetails<TDef>;
|
|
57
69
|
|
|
58
70
|
constructor(
|
|
@@ -67,22 +79,31 @@ export class AppError<TDef extends ErrorDef = ErrorDef> extends Error {
|
|
|
67
79
|
this.details = details;
|
|
68
80
|
}
|
|
69
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Stable public error code.
|
|
84
|
+
*/
|
|
70
85
|
get code(): string {
|
|
71
86
|
return this.def.code;
|
|
72
87
|
}
|
|
73
88
|
|
|
89
|
+
/**
|
|
90
|
+
* HTTP status code associated with this error.
|
|
91
|
+
*/
|
|
74
92
|
get status(): number {
|
|
75
93
|
return this.def.status;
|
|
76
94
|
}
|
|
77
95
|
}
|
|
78
96
|
|
|
79
97
|
/**
|
|
80
|
-
* Callable helper for creating
|
|
98
|
+
* Callable helper for creating `AppError` instances from a catalog.
|
|
81
99
|
*/
|
|
82
100
|
export type AppErrorCreator<TCatalog extends ErrorCatalog> = {
|
|
101
|
+
/**
|
|
102
|
+
* Original catalog bound to this creator.
|
|
103
|
+
*/
|
|
83
104
|
catalog: TCatalog;
|
|
84
105
|
/**
|
|
85
|
-
* Create an AppError from a catalog key.
|
|
106
|
+
* Create an `AppError` from a catalog key.
|
|
86
107
|
*/
|
|
87
108
|
<Key extends keyof TCatalog>(
|
|
88
109
|
key: Key,
|
|
@@ -95,7 +116,10 @@ export type AppErrorCreator<TCatalog extends ErrorCatalog> = {
|
|
|
95
116
|
};
|
|
96
117
|
|
|
97
118
|
/**
|
|
98
|
-
* Create a callable AppError helper bound to a specific catalog.
|
|
119
|
+
* Create a callable `AppError` helper bound to a specific catalog.
|
|
120
|
+
*
|
|
121
|
+
* The returned function validates the catalog key and preserves each entry's
|
|
122
|
+
* details type for `options.details`.
|
|
99
123
|
*/
|
|
100
124
|
export function createAppError<const T extends ErrorCatalog>(
|
|
101
125
|
catalog: T,
|
|
@@ -127,7 +151,7 @@ export function createAppError<const T extends ErrorCatalog>(
|
|
|
127
151
|
}
|
|
128
152
|
|
|
129
153
|
/**
|
|
130
|
-
*
|
|
154
|
+
* Check whether an unknown value is a Beignet `AppError`.
|
|
131
155
|
*/
|
|
132
156
|
export function isAppError(err: unknown): err is AppError<ErrorDef> {
|
|
133
157
|
if (err instanceof AppError) return true;
|
package/src/errors/response.ts
CHANGED
|
@@ -5,17 +5,29 @@
|
|
|
5
5
|
import type { AppError, ErrorDef } from "./catalog";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Standard error response body
|
|
8
|
+
* Standard Beignet error response body.
|
|
9
9
|
*/
|
|
10
10
|
export interface ErrorResponseBody {
|
|
11
|
+
/**
|
|
12
|
+
* Stable machine-readable error code.
|
|
13
|
+
*/
|
|
11
14
|
code: string;
|
|
15
|
+
/**
|
|
16
|
+
* Human-readable error message.
|
|
17
|
+
*/
|
|
12
18
|
message: string;
|
|
19
|
+
/**
|
|
20
|
+
* Optional structured details.
|
|
21
|
+
*/
|
|
13
22
|
details?: unknown;
|
|
23
|
+
/**
|
|
24
|
+
* Optional request ID for support and log correlation.
|
|
25
|
+
*/
|
|
14
26
|
requestId?: string;
|
|
15
27
|
}
|
|
16
28
|
|
|
17
29
|
/**
|
|
18
|
-
* Create a standard error response body.
|
|
30
|
+
* Create a standard error response body and omit undefined optional fields.
|
|
19
31
|
*/
|
|
20
32
|
export function createErrorResponseBody(
|
|
21
33
|
args: ErrorResponseBody,
|
|
@@ -29,7 +41,7 @@ export function createErrorResponseBody(
|
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
/**
|
|
32
|
-
* Check whether a value
|
|
44
|
+
* Check whether a value looks like a standard Beignet error response body.
|
|
33
45
|
*/
|
|
34
46
|
export function isErrorResponseBody(
|
|
35
47
|
value: unknown,
|
|
@@ -41,7 +53,7 @@ export function isErrorResponseBody(
|
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
/**
|
|
44
|
-
* Convert an AppError to a standard error response body
|
|
56
|
+
* Convert an `AppError` to a standard error response body.
|
|
45
57
|
*/
|
|
46
58
|
export function toErrorResponseBody(
|
|
47
59
|
err: AppError<ErrorDef>,
|
package/src/errors/validation.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Normalized validation issue with simplified path
|
|
4
|
+
* Normalized validation issue with a simplified path.
|
|
5
5
|
*/
|
|
6
6
|
export interface ValidationIssue {
|
|
7
|
+
/**
|
|
8
|
+
* Path to the invalid value.
|
|
9
|
+
*/
|
|
7
10
|
path?: (string | number)[];
|
|
11
|
+
/**
|
|
12
|
+
* Human-readable validation message.
|
|
13
|
+
*/
|
|
8
14
|
message: string;
|
|
9
15
|
}
|
|
10
16
|
|
|
@@ -14,6 +20,9 @@ export interface ValidationIssue {
|
|
|
14
20
|
* regardless of which package threw the error.
|
|
15
21
|
*/
|
|
16
22
|
export class SchemaValidationError extends Error {
|
|
23
|
+
/**
|
|
24
|
+
* Normalized validation issues.
|
|
25
|
+
*/
|
|
17
26
|
readonly issues: ReadonlyArray<ValidationIssue>;
|
|
18
27
|
|
|
19
28
|
constructor(rawIssues: ReadonlyArray<StandardSchemaV1.Issue>) {
|