kontract 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +435 -0
- package/dist/builder/define-controller.d.ts +115 -0
- package/dist/builder/define-controller.d.ts.map +1 -0
- package/dist/builder/define-controller.js +80 -0
- package/dist/builder/define-controller.js.map +1 -0
- package/dist/builder/define-endpoint.d.ts +157 -0
- package/dist/builder/define-endpoint.d.ts.map +1 -0
- package/dist/builder/define-endpoint.js +103 -0
- package/dist/builder/define-endpoint.js.map +1 -0
- package/dist/builder/define-route.d.ts +191 -0
- package/dist/builder/define-route.d.ts.map +1 -0
- package/dist/builder/define-route.js +124 -0
- package/dist/builder/define-route.js.map +1 -0
- package/dist/builder/index.d.ts +5 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +7 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/openapi-builder.d.ts +120 -0
- package/dist/builder/openapi-builder.d.ts.map +1 -0
- package/dist/builder/openapi-builder.js +349 -0
- package/dist/builder/openapi-builder.js.map +1 -0
- package/dist/builder/path-params.d.ts +129 -0
- package/dist/builder/path-params.d.ts.map +1 -0
- package/dist/builder/path-params.js +85 -0
- package/dist/builder/path-params.js.map +1 -0
- package/dist/builder/types.d.ts +149 -0
- package/dist/builder/types.d.ts.map +1 -0
- package/dist/builder/types.js +6 -0
- package/dist/builder/types.js.map +1 -0
- package/dist/config/defaults.d.ts +10 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +28 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/define-config.d.ts +50 -0
- package/dist/config/define-config.d.ts.map +1 -0
- package/dist/config/define-config.js +80 -0
- package/dist/config/define-config.js.map +1 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +103 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/decorators/api.d.ts +35 -0
- package/dist/decorators/api.d.ts.map +1 -0
- package/dist/decorators/api.js +34 -0
- package/dist/decorators/api.js.map +1 -0
- package/dist/decorators/controller.d.ts +35 -0
- package/dist/decorators/controller.d.ts.map +1 -0
- package/dist/decorators/controller.js +34 -0
- package/dist/decorators/controller.js.map +1 -0
- package/dist/decorators/endpoint.d.ts +93 -0
- package/dist/decorators/endpoint.d.ts.map +1 -0
- package/dist/decorators/endpoint.js +108 -0
- package/dist/decorators/endpoint.js.map +1 -0
- package/dist/decorators/index.d.ts +5 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +6 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/route.d.ts +93 -0
- package/dist/decorators/route.d.ts.map +1 -0
- package/dist/decorators/route.js +108 -0
- package/dist/decorators/route.js.map +1 -0
- package/dist/errors/base.d.ts +8 -0
- package/dist/errors/base.d.ts.map +1 -0
- package/dist/errors/base.js +13 -0
- package/dist/errors/base.js.map +1 -0
- package/dist/errors/configuration.d.ts +22 -0
- package/dist/errors/configuration.d.ts.map +1 -0
- package/dist/errors/configuration.js +33 -0
- package/dist/errors/configuration.js.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/validation.d.ts +46 -0
- package/dist/errors/validation.d.ts.map +1 -0
- package/dist/errors/validation.js +52 -0
- package/dist/errors/validation.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata/index.d.ts +2 -0
- package/dist/metadata/index.d.ts.map +1 -0
- package/dist/metadata/index.js +2 -0
- package/dist/metadata/index.js.map +1 -0
- package/dist/metadata/storage.d.ts +50 -0
- package/dist/metadata/storage.d.ts.map +1 -0
- package/dist/metadata/storage.js +100 -0
- package/dist/metadata/storage.js.map +1 -0
- package/dist/metadata/types.d.ts +142 -0
- package/dist/metadata/types.d.ts.map +1 -0
- package/dist/metadata/types.js +2 -0
- package/dist/metadata/types.js.map +1 -0
- package/dist/response/helpers.d.ts +132 -0
- package/dist/response/helpers.d.ts.map +1 -0
- package/dist/response/helpers.js +197 -0
- package/dist/response/helpers.js.map +1 -0
- package/dist/response/index.d.ts +4 -0
- package/dist/response/index.d.ts.map +1 -0
- package/dist/response/index.js +4 -0
- package/dist/response/index.js.map +1 -0
- package/dist/response/types.d.ts +59 -0
- package/dist/response/types.d.ts.map +1 -0
- package/dist/response/types.js +26 -0
- package/dist/response/types.js.map +1 -0
- package/dist/runtime/adapter-types.d.ts +119 -0
- package/dist/runtime/adapter-types.d.ts.map +1 -0
- package/dist/runtime/adapter-types.js +2 -0
- package/dist/runtime/adapter-types.js.map +1 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/response-helpers.d.ts +138 -0
- package/dist/runtime/response-helpers.d.ts.map +1 -0
- package/dist/runtime/response-helpers.js +105 -0
- package/dist/runtime/response-helpers.js.map +1 -0
- package/dist/runtime/route-utils.d.ts +22 -0
- package/dist/runtime/route-utils.d.ts.map +1 -0
- package/dist/runtime/route-utils.js +47 -0
- package/dist/runtime/route-utils.js.map +1 -0
- package/dist/runtime/types.d.ts +125 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +3 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/types.d.ts +55 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +2 -0
- package/dist/validation/types.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { NormalizedResponses } from './adapter-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default error codes for each HTTP status.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ERROR_CODES: Record<number, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Create a success helper (just wraps data with status).
|
|
8
|
+
*/
|
|
9
|
+
export declare function createSuccessHelper(status: number): (data: unknown) => {
|
|
10
|
+
status: number;
|
|
11
|
+
data: unknown;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Create an error helper with smart defaults.
|
|
15
|
+
* - No args: use description from response definition as message
|
|
16
|
+
* - String passed: use as message, auto-fill status and code
|
|
17
|
+
* - Object passed: merge with defaults (status, code, and description as message)
|
|
18
|
+
*/
|
|
19
|
+
export declare function createErrorHelper(status: number, defaultCode: string, defaultMessage: string): (dataOrMessage?: unknown) => {
|
|
20
|
+
status: number;
|
|
21
|
+
data: {
|
|
22
|
+
status: number;
|
|
23
|
+
code: string;
|
|
24
|
+
message: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Get the default error message for a status code.
|
|
29
|
+
* Priority: explicit description > schema description > generic fallback
|
|
30
|
+
*/
|
|
31
|
+
export declare function getErrorMessage(responses: NormalizedResponses, status: number, fallback: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Create namespaced response helper functions bound to the route's response schemas.
|
|
34
|
+
* These helpers don't need the schema passed - they're pre-typed at compile time.
|
|
35
|
+
*
|
|
36
|
+
* Returns `{ reply, error }` namespaces:
|
|
37
|
+
* - `reply` contains success helpers (ok, created, accepted, noContent, list)
|
|
38
|
+
* - `error` contains error helpers with smart defaults (uses schema description as default message)
|
|
39
|
+
*/
|
|
40
|
+
export declare function createResponseHelpers(responses: NormalizedResponses): {
|
|
41
|
+
reply: {
|
|
42
|
+
ok: (data: unknown) => {
|
|
43
|
+
status: number;
|
|
44
|
+
data: unknown;
|
|
45
|
+
};
|
|
46
|
+
created: (data: unknown) => {
|
|
47
|
+
status: number;
|
|
48
|
+
data: unknown;
|
|
49
|
+
};
|
|
50
|
+
accepted: (data: unknown) => {
|
|
51
|
+
status: number;
|
|
52
|
+
data: unknown;
|
|
53
|
+
};
|
|
54
|
+
noContent: () => {
|
|
55
|
+
status: 204;
|
|
56
|
+
data: null;
|
|
57
|
+
};
|
|
58
|
+
list: (data: unknown) => {
|
|
59
|
+
status: number;
|
|
60
|
+
data: unknown;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
error: {
|
|
64
|
+
badRequest: (dataOrMessage?: unknown) => {
|
|
65
|
+
status: number;
|
|
66
|
+
data: {
|
|
67
|
+
status: number;
|
|
68
|
+
code: string;
|
|
69
|
+
message: string;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
unauthorized: (dataOrMessage?: unknown) => {
|
|
73
|
+
status: number;
|
|
74
|
+
data: {
|
|
75
|
+
status: number;
|
|
76
|
+
code: string;
|
|
77
|
+
message: string;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
forbidden: (dataOrMessage?: unknown) => {
|
|
81
|
+
status: number;
|
|
82
|
+
data: {
|
|
83
|
+
status: number;
|
|
84
|
+
code: string;
|
|
85
|
+
message: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
notFound: (dataOrMessage?: unknown) => {
|
|
89
|
+
status: number;
|
|
90
|
+
data: {
|
|
91
|
+
status: number;
|
|
92
|
+
code: string;
|
|
93
|
+
message: string;
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
conflict: (dataOrMessage?: unknown) => {
|
|
97
|
+
status: number;
|
|
98
|
+
data: {
|
|
99
|
+
status: number;
|
|
100
|
+
code: string;
|
|
101
|
+
message: string;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
validationError: (dataOrMessage?: unknown) => {
|
|
105
|
+
status: number;
|
|
106
|
+
data: {
|
|
107
|
+
status: number;
|
|
108
|
+
code: string;
|
|
109
|
+
message: string;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
tooManyRequests: (dataOrMessage?: unknown) => {
|
|
113
|
+
status: number;
|
|
114
|
+
data: {
|
|
115
|
+
status: number;
|
|
116
|
+
code: string;
|
|
117
|
+
message: string;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
internal: (dataOrMessage?: unknown) => {
|
|
121
|
+
status: number;
|
|
122
|
+
data: {
|
|
123
|
+
status: number;
|
|
124
|
+
code: string;
|
|
125
|
+
message: string;
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
serviceUnavailable: (dataOrMessage?: unknown) => {
|
|
129
|
+
status: number;
|
|
130
|
+
data: {
|
|
131
|
+
status: number;
|
|
132
|
+
code: string;
|
|
133
|
+
message: string;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=response-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-helpers.d.ts","sourceRoot":"","sources":["../../src/runtime/response-helpers.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAM7D;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAU9C,CAAA;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,IACxC,MAAM,OAAO;;;EACtB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,IACnF,gBAAgB,OAAO;;;;;;;EA2BhC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,mBAAmB,EAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,CAKR;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,mBAAmB;;mBA9DpD,OAAO;;;;wBAAP,OAAO;;;;yBAAP,OAAO;;;;;;;;qBAAP,OAAO;;;;;;qCAUG,OAAO;;;;;;;;uCAAP,OAAO;;;;;;;;oCAAP,OAAO;;;;;;;;mCAAP,OAAO;;;;;;;;mCAAP,OAAO;;;;;;;;0CAAP,OAAO;;;;;;;;0CAAP,OAAO;;;;;;;;mCAAP,OAAO;;;;;;;;6CAAP,OAAO;;;;;;;;;EA4EhC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Constants
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/**
|
|
5
|
+
* Default error codes for each HTTP status.
|
|
6
|
+
*/
|
|
7
|
+
export const ERROR_CODES = {
|
|
8
|
+
400: 'E_BAD_REQUEST',
|
|
9
|
+
401: 'E_UNAUTHORIZED',
|
|
10
|
+
403: 'E_FORBIDDEN',
|
|
11
|
+
404: 'E_NOT_FOUND',
|
|
12
|
+
409: 'E_CONFLICT',
|
|
13
|
+
422: 'E_VALIDATION',
|
|
14
|
+
429: 'E_TOO_MANY_REQUESTS',
|
|
15
|
+
500: 'E_INTERNAL_SERVER_ERROR',
|
|
16
|
+
503: 'E_SERVICE_UNAVAILABLE',
|
|
17
|
+
};
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Helper Functions
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Create a success helper (just wraps data with status).
|
|
23
|
+
*/
|
|
24
|
+
export function createSuccessHelper(status) {
|
|
25
|
+
return (data) => ({ status, data });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create an error helper with smart defaults.
|
|
29
|
+
* - No args: use description from response definition as message
|
|
30
|
+
* - String passed: use as message, auto-fill status and code
|
|
31
|
+
* - Object passed: merge with defaults (status, code, and description as message)
|
|
32
|
+
*/
|
|
33
|
+
export function createErrorHelper(status, defaultCode, defaultMessage) {
|
|
34
|
+
return (dataOrMessage) => {
|
|
35
|
+
// No args: error.internal() - use description as default message
|
|
36
|
+
if (dataOrMessage === undefined) {
|
|
37
|
+
return {
|
|
38
|
+
status,
|
|
39
|
+
data: { status, code: defaultCode, message: defaultMessage },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// String shorthand: error.badRequest('Invalid token')
|
|
43
|
+
if (typeof dataOrMessage === 'string') {
|
|
44
|
+
return {
|
|
45
|
+
status,
|
|
46
|
+
data: { status, code: defaultCode, message: dataOrMessage },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Object: merge with defaults
|
|
50
|
+
const data = dataOrMessage;
|
|
51
|
+
return {
|
|
52
|
+
status,
|
|
53
|
+
data: {
|
|
54
|
+
status,
|
|
55
|
+
code: defaultCode,
|
|
56
|
+
message: defaultMessage, // Default from description
|
|
57
|
+
...data, // User can override
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get the default error message for a status code.
|
|
64
|
+
* Priority: explicit description > schema description > generic fallback
|
|
65
|
+
*/
|
|
66
|
+
export function getErrorMessage(responses, status, fallback) {
|
|
67
|
+
const response = responses[status];
|
|
68
|
+
return response?.description
|
|
69
|
+
?? response?.schema?.description
|
|
70
|
+
?? fallback;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create namespaced response helper functions bound to the route's response schemas.
|
|
74
|
+
* These helpers don't need the schema passed - they're pre-typed at compile time.
|
|
75
|
+
*
|
|
76
|
+
* Returns `{ reply, error }` namespaces:
|
|
77
|
+
* - `reply` contains success helpers (ok, created, accepted, noContent, list)
|
|
78
|
+
* - `error` contains error helpers with smart defaults (uses schema description as default message)
|
|
79
|
+
*/
|
|
80
|
+
export function createResponseHelpers(responses) {
|
|
81
|
+
return {
|
|
82
|
+
// Success responses namespace (2xx)
|
|
83
|
+
reply: {
|
|
84
|
+
ok: createSuccessHelper(200),
|
|
85
|
+
created: createSuccessHelper(201),
|
|
86
|
+
accepted: createSuccessHelper(202),
|
|
87
|
+
noContent: () => ({ status: 204, data: null }),
|
|
88
|
+
list: createSuccessHelper(200),
|
|
89
|
+
},
|
|
90
|
+
// Error responses namespace (4xx/5xx) - with smart defaults
|
|
91
|
+
// Default message: explicit description > schema.description > generic fallback
|
|
92
|
+
error: {
|
|
93
|
+
badRequest: createErrorHelper(400, ERROR_CODES[400], getErrorMessage(responses, 400, 'Bad request')),
|
|
94
|
+
unauthorized: createErrorHelper(401, ERROR_CODES[401], getErrorMessage(responses, 401, 'Unauthorized')),
|
|
95
|
+
forbidden: createErrorHelper(403, ERROR_CODES[403], getErrorMessage(responses, 403, 'Forbidden')),
|
|
96
|
+
notFound: createErrorHelper(404, ERROR_CODES[404], getErrorMessage(responses, 404, 'Not found')),
|
|
97
|
+
conflict: createErrorHelper(409, ERROR_CODES[409], getErrorMessage(responses, 409, 'Conflict')),
|
|
98
|
+
validationError: createErrorHelper(422, ERROR_CODES[422], getErrorMessage(responses, 422, 'Validation failed')),
|
|
99
|
+
tooManyRequests: createErrorHelper(429, ERROR_CODES[429], getErrorMessage(responses, 429, 'Too many requests')),
|
|
100
|
+
internal: createErrorHelper(500, ERROR_CODES[500], getErrorMessage(responses, 500, 'Internal server error')),
|
|
101
|
+
serviceUnavailable: createErrorHelper(503, ERROR_CODES[503], getErrorMessage(responses, 503, 'Service unavailable')),
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=response-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-helpers.js","sourceRoot":"","sources":["../../src/runtime/response-helpers.ts"],"names":[],"mappings":"AASA,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA2B;IACjD,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,gBAAgB;IACrB,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,YAAY;IACjB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,qBAAqB;IAC1B,GAAG,EAAE,yBAAyB;IAC9B,GAAG,EAAE,uBAAuB;CAC7B,CAAA;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAO,CAAC,IAAa,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;AAC9C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,WAAmB,EAAE,cAAsB;IAC3F,OAAO,CAAC,aAAuB,EAAE,EAAE;QACjC,iEAAiE;QACjE,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO;gBACL,MAAM;gBACN,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE;aAC7D,CAAA;QACH,CAAC;QACD,sDAAsD;QACtD,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO;gBACL,MAAM;gBACN,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE;aAC5D,CAAA;QACH,CAAC;QACD,8BAA8B;QAC9B,MAAM,IAAI,GAAG,aAAwC,CAAA;QACrD,OAAO;YACL,MAAM;YACN,IAAI,EAAE;gBACJ,MAAM;gBACN,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,cAAc,EAAE,2BAA2B;gBACpD,GAAG,IAAI,EAAE,oBAAoB;aAC9B;SACF,CAAA;IACH,CAAC,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,SAA8B,EAC9B,MAAc,EACd,QAAgB;IAEhB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAClC,OAAO,QAAQ,EAAE,WAAW;WACtB,QAAQ,EAAE,MAAoD,EAAE,WAAW;WAC5E,QAAQ,CAAA;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAA8B;IAClE,OAAO;QACL,oCAAoC;QACpC,KAAK,EAAE;YACL,EAAE,EAAE,mBAAmB,CAAC,GAAG,CAAC;YAC5B,OAAO,EAAE,mBAAmB,CAAC,GAAG,CAAC;YACjC,QAAQ,EAAE,mBAAmB,CAAC,GAAG,CAAC;YAClC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,GAAY,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YACvD,IAAI,EAAE,mBAAmB,CAAC,GAAG,CAAC;SAC/B;QACD,4DAA4D;QAC5D,gFAAgF;QAChF,KAAK,EAAE;YACL,UAAU,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;YACpG,YAAY,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;YACvG,SAAS,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;YACjG,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;YAChG,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;YAC/F,eAAe,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,mBAAmB,CAAC,CAAC;YAC/G,eAAe,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,mBAAmB,CAAC,CAAC;YAC/G,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,uBAAuB,CAAC,CAAC;YAC5G,kBAAkB,EAAE,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,qBAAqB,CAAC,CAAC;SACrH;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ApiResponse } from '../response/types.js';
|
|
2
|
+
import type { RouteString } from '../metadata/types.js';
|
|
3
|
+
import type { ResponsesConfig, NormalizedResponses } from './adapter-types.js';
|
|
4
|
+
export type { RouteString } from '../metadata/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse a route string into method and path.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseRouteString(route: RouteString): [string, string];
|
|
9
|
+
/**
|
|
10
|
+
* Normalize response definitions to consistent format.
|
|
11
|
+
* Preserves all fields including headers, examples, and example.
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeResponses(responses: ResponsesConfig): NormalizedResponses;
|
|
14
|
+
/**
|
|
15
|
+
* Check if a value looks like an API response object.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isApiResponse(value: unknown): value is ApiResponse<number, unknown>;
|
|
18
|
+
/**
|
|
19
|
+
* Return 204 No Content.
|
|
20
|
+
*/
|
|
21
|
+
export declare function noContent(): ApiResponse<204, null>;
|
|
22
|
+
//# sourceMappingURL=route-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-utils.d.ts","sourceRoot":"","sources":["../../src/runtime/route-utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,eAAe,EAAsB,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAGlG,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAKrE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,eAAe,GAAG,mBAAmB,CAelF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CASnF;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAElD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a route string into method and path.
|
|
3
|
+
*/
|
|
4
|
+
export function parseRouteString(route) {
|
|
5
|
+
const spaceIndex = route.indexOf(' ');
|
|
6
|
+
const method = route.slice(0, spaceIndex).toLowerCase();
|
|
7
|
+
const path = route.slice(spaceIndex + 1);
|
|
8
|
+
return [method, path];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Normalize response definitions to consistent format.
|
|
12
|
+
* Preserves all fields including headers, examples, and example.
|
|
13
|
+
*/
|
|
14
|
+
export function normalizeResponses(responses) {
|
|
15
|
+
const normalized = {};
|
|
16
|
+
for (const [status, value] of Object.entries(responses)) {
|
|
17
|
+
if (value === null) {
|
|
18
|
+
normalized[Number(status)] = { schema: null };
|
|
19
|
+
}
|
|
20
|
+
else if (typeof value === 'object' && 'schema' in value) {
|
|
21
|
+
// Preserve all fields: schema, description, headers, examples, example
|
|
22
|
+
normalized[Number(status)] = value;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
normalized[Number(status)] = { schema: value };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return normalized;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if a value looks like an API response object.
|
|
32
|
+
*/
|
|
33
|
+
export function isApiResponse(value) {
|
|
34
|
+
return (value !== null
|
|
35
|
+
&& typeof value === 'object'
|
|
36
|
+
&& 'status' in value
|
|
37
|
+
&& typeof value.status === 'number'
|
|
38
|
+
&& 'data' in value
|
|
39
|
+
&& !('binary' in value));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Return 204 No Content.
|
|
43
|
+
*/
|
|
44
|
+
export function noContent() {
|
|
45
|
+
return { status: 204, data: null };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=route-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-utils.js","sourceRoot":"","sources":["../../src/runtime/route-utils.ts"],"names":[],"mappings":"AAaA;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,WAAW,EAAE,CAAA;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IACxC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAA0B;IAC3D,MAAM,UAAU,GAAwB,EAAE,CAAA;IAE1C,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACxD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QAC/C,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC1D,uEAAuE;YACvE,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAA2B,CAAA;QAC1D,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAgB,EAAE,CAAA;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,CACL,KAAK,KAAK,IAAI;WACX,OAAO,KAAK,KAAK,QAAQ;WACzB,QAAQ,IAAI,KAAK;WACjB,OAAQ,KAA6B,CAAC,MAAM,KAAK,QAAQ;WACzD,MAAM,IAAI,KAAK;WACf,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,CACxB,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AACpC,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { HttpMethod, EndpointMetadata } from '../metadata/types.js';
|
|
2
|
+
import type { AnyResponse } from '../response/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Framework-agnostic request representation.
|
|
5
|
+
*/
|
|
6
|
+
export interface RequestContext {
|
|
7
|
+
/** HTTP method (lowercase) */
|
|
8
|
+
method: HttpMethod;
|
|
9
|
+
/** Request path */
|
|
10
|
+
path: string;
|
|
11
|
+
/** Parsed path parameters */
|
|
12
|
+
params: Record<string, string>;
|
|
13
|
+
/** Parsed query parameters */
|
|
14
|
+
query: Record<string, unknown>;
|
|
15
|
+
/** Request body (parsed) */
|
|
16
|
+
body: unknown;
|
|
17
|
+
/** Request headers */
|
|
18
|
+
headers: Record<string, string | string[] | undefined>;
|
|
19
|
+
/** Framework-specific request object */
|
|
20
|
+
raw: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* User information from authentication.
|
|
24
|
+
*/
|
|
25
|
+
export interface AuthUser {
|
|
26
|
+
id: string | number;
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Authentication result.
|
|
31
|
+
*/
|
|
32
|
+
export interface AuthResult {
|
|
33
|
+
authenticated: boolean;
|
|
34
|
+
user?: AuthUser;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Route handler signature for adapter implementations.
|
|
38
|
+
* @see RouteHandler from builder/define-route.ts for user-facing handler type
|
|
39
|
+
*/
|
|
40
|
+
export type AdapterRouteHandler = (ctx: RequestContext) => Promise<AnyResponse>;
|
|
41
|
+
/**
|
|
42
|
+
* Router adapter interface.
|
|
43
|
+
* Implement this to integrate with a web framework.
|
|
44
|
+
*/
|
|
45
|
+
export interface RouterAdapter {
|
|
46
|
+
/**
|
|
47
|
+
* Register a route with the framework.
|
|
48
|
+
*/
|
|
49
|
+
register(method: HttpMethod, path: string, handler: AdapterRouteHandler, metadata: EndpointMetadata): void;
|
|
50
|
+
/**
|
|
51
|
+
* Get all registered routes (optional, for debugging).
|
|
52
|
+
*/
|
|
53
|
+
getRoutes?(): Array<{
|
|
54
|
+
method: HttpMethod;
|
|
55
|
+
path: string;
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Authentication adapter interface.
|
|
60
|
+
* Implement this to integrate with an auth system.
|
|
61
|
+
*/
|
|
62
|
+
export interface AuthAdapter {
|
|
63
|
+
/**
|
|
64
|
+
* Authenticate the request.
|
|
65
|
+
* Should return user info if authenticated, or null/undefined otherwise.
|
|
66
|
+
*/
|
|
67
|
+
authenticate(ctx: RequestContext): Promise<AuthResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Get the authenticated user or throw if not authenticated.
|
|
70
|
+
*/
|
|
71
|
+
getUserOrFail(ctx: RequestContext): Promise<AuthUser>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Container/DI adapter interface.
|
|
75
|
+
* Implement this to integrate with a dependency injection container.
|
|
76
|
+
*/
|
|
77
|
+
export interface ContainerAdapter {
|
|
78
|
+
/**
|
|
79
|
+
* Resolve a class from the container.
|
|
80
|
+
*/
|
|
81
|
+
resolve<T>(target: new (...args: unknown[]) => T): T;
|
|
82
|
+
/**
|
|
83
|
+
* Check if a class is registered in the container.
|
|
84
|
+
*/
|
|
85
|
+
has(target: new (...args: unknown[]) => unknown): boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Response adapter interface.
|
|
89
|
+
* Implement this to send responses through the framework.
|
|
90
|
+
*/
|
|
91
|
+
export interface ResponseAdapter {
|
|
92
|
+
/**
|
|
93
|
+
* Send a JSON response.
|
|
94
|
+
*/
|
|
95
|
+
sendJson(ctx: RequestContext, status: number, data: unknown): void;
|
|
96
|
+
/**
|
|
97
|
+
* Send a binary/file response.
|
|
98
|
+
*/
|
|
99
|
+
sendBinary(ctx: RequestContext, status: number, contentType: string, data: Buffer | string, filename?: string): void;
|
|
100
|
+
/**
|
|
101
|
+
* Send an empty response (204 No Content).
|
|
102
|
+
*/
|
|
103
|
+
sendEmpty(ctx: RequestContext, status: number): void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Logger adapter interface.
|
|
107
|
+
* Implement this to integrate with a logging system.
|
|
108
|
+
*/
|
|
109
|
+
export interface LoggerAdapter {
|
|
110
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
111
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
112
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
113
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Complete adapter set for a framework integration.
|
|
117
|
+
*/
|
|
118
|
+
export interface FrameworkAdapters {
|
|
119
|
+
router: RouterAdapter;
|
|
120
|
+
auth?: AuthAdapter;
|
|
121
|
+
container?: ContainerAdapter;
|
|
122
|
+
response: ResponseAdapter;
|
|
123
|
+
logger?: LoggerAdapter;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,MAAM,EAAE,UAAU,CAAA;IAClB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,4BAA4B;IAC5B,IAAI,EAAE,OAAO,CAAA;IACb,sBAAsB;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IACtD,wCAAwC;IACxC,GAAG,EAAE,OAAO,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,OAAO,CAAA;IACtB,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;AAE/E;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,QAAQ,CACN,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,gBAAgB,GACzB,IAAI,CAAA;IAEP;;OAEG;IACH,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,MAAM,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC1D;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAEtD;;OAEG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtD;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;IAEpD;;OAEG;IACH,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,OAAO,CAAA;CAC1D;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IAElE;;OAEG;IACH,UAAU,CACR,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAA;IAEP;;OAEG;IACH,SAAS,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACrD;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC5D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC3D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC3D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,CAAA;IACrB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,SAAS,CAAC,EAAE,gBAAgB,CAAA;IAC5B,QAAQ,EAAE,eAAe,CAAA;IACzB,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAMA,8CAA8C;AAC9C,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GAExB,MAAM,yBAAyB,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { TSchema } from '@sinclair/typebox';
|
|
2
|
+
import type { ValidationErrorDetail } from '../errors/validation.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validator interface for schema validation.
|
|
5
|
+
* Implement this to use a different validation library.
|
|
6
|
+
*/
|
|
7
|
+
export interface Validator {
|
|
8
|
+
/**
|
|
9
|
+
* Validate data against a schema.
|
|
10
|
+
* @returns Array of errors, or empty array if valid
|
|
11
|
+
*/
|
|
12
|
+
validate(schema: TSchema, data: unknown): ValidationErrorDetail[];
|
|
13
|
+
/**
|
|
14
|
+
* Validate and throw if invalid.
|
|
15
|
+
* @throws ValidationError if validation fails
|
|
16
|
+
*/
|
|
17
|
+
validateOrThrow(schema: TSchema, data: unknown): void;
|
|
18
|
+
/**
|
|
19
|
+
* Compile a schema for repeated validation.
|
|
20
|
+
* Optional optimization for validators that support it.
|
|
21
|
+
*/
|
|
22
|
+
compile?(schema: TSchema): CompiledValidator;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Pre-compiled validator for performance.
|
|
26
|
+
*/
|
|
27
|
+
export interface CompiledValidator {
|
|
28
|
+
validate(data: unknown): ValidationErrorDetail[];
|
|
29
|
+
validateOrThrow(data: unknown): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Options for creating a validator.
|
|
33
|
+
*/
|
|
34
|
+
export interface ValidatorOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Whether to remove additional properties not in schema.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
removeAdditional?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Whether to coerce types (e.g., "123" to 123).
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
coerceTypes?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Whether to use defaults from schema.
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
49
|
+
useDefaults?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Custom formats to register.
|
|
52
|
+
*/
|
|
53
|
+
formats?: Record<string, (value: string) => boolean>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/validation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAEpE;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,qBAAqB,EAAE,CAAA;IAEjE;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IAErD;;;OAGG;IACH,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,GAAG,iBAAiB,CAAA;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,EAAE,CAAA;IAChD,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAE1B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAA;CACrD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/validation/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kontract",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-agnostic type-safe API contracts with TypeBox schema support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./response": {
|
|
14
|
+
"types": "./dist/response/index.d.ts",
|
|
15
|
+
"import": "./dist/response/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./metadata": {
|
|
18
|
+
"types": "./dist/metadata/index.d.ts",
|
|
19
|
+
"import": "./dist/metadata/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./config": {
|
|
22
|
+
"types": "./dist/config/index.d.ts",
|
|
23
|
+
"import": "./dist/config/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./errors": {
|
|
26
|
+
"types": "./dist/errors/index.d.ts",
|
|
27
|
+
"import": "./dist/errors/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./validation": {
|
|
30
|
+
"types": "./dist/validation/index.d.ts",
|
|
31
|
+
"import": "./dist/validation/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./runtime": {
|
|
34
|
+
"types": "./dist/runtime/index.d.ts",
|
|
35
|
+
"import": "./dist/runtime/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./builder": {
|
|
38
|
+
"types": "./dist/builder/index.d.ts",
|
|
39
|
+
"import": "./dist/builder/index.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"README.md"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc",
|
|
48
|
+
"dev": "tsc --watch",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"lint": "eslint src/",
|
|
51
|
+
"lint:fix": "eslint src/ --fix",
|
|
52
|
+
"clean": "rm -rf dist",
|
|
53
|
+
"test": "TSX_TSCONFIG_PATH=tsconfig.test.json node --import=tsx bin/test.ts"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@sinclair/typebox": "^0.34.33"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@japa/assert": "^4.2.0",
|
|
60
|
+
"@japa/runner": "^4.4.0",
|
|
61
|
+
"@types/node": "^22.15.21",
|
|
62
|
+
"tsx": "^4.19.0",
|
|
63
|
+
"typescript": "^5.8.3"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"@sinclair/typebox": ">=0.32.0"
|
|
67
|
+
},
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=20.0.0"
|
|
70
|
+
},
|
|
71
|
+
"keywords": [
|
|
72
|
+
"openapi",
|
|
73
|
+
"swagger",
|
|
74
|
+
"typescript",
|
|
75
|
+
"typebox",
|
|
76
|
+
"api",
|
|
77
|
+
"rest",
|
|
78
|
+
"documentation",
|
|
79
|
+
"type-safe",
|
|
80
|
+
"contracts"
|
|
81
|
+
],
|
|
82
|
+
"author": "Drew Daniels",
|
|
83
|
+
"license": "MIT",
|
|
84
|
+
"repository": {
|
|
85
|
+
"type": "git",
|
|
86
|
+
"url": "https://github.com/Drew-Daniels/kontract.git",
|
|
87
|
+
"directory": "packages/kontract"
|
|
88
|
+
},
|
|
89
|
+
"homepage": "https://github.com/Drew-Daniels/kontract#readme",
|
|
90
|
+
"bugs": {
|
|
91
|
+
"url": "https://github.com/Drew-Daniels/kontract/issues"
|
|
92
|
+
}
|
|
93
|
+
}
|