@sonatel-os/openapi-runtime 0.1.1 → 0.2.1
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 +458 -170
- package/dist/errors.cjs +154 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.esm.js +154 -0
- package/dist/errors.esm.js.map +1 -0
- package/dist/index.cjs +557 -5453
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -74
- package/dist/index.esm.js +560 -5455
- package/dist/index.esm.js.map +1 -1
- package/dist/react/index.cjs +129 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.esm.js +129 -0
- package/dist/react/index.esm.js.map +1 -0
- package/dist/src/auth/config.d.ts +170 -0
- package/dist/src/auth/index.d.ts +3 -0
- package/dist/src/auth/manager.d.ts +51 -0
- package/dist/src/auth/providers.d.ts +178 -0
- package/dist/src/constants.d.ts +30 -0
- package/dist/src/core/client.d.ts +83 -0
- package/dist/src/core/registry.d.ts +116 -0
- package/dist/src/errors.d.ts +126 -0
- package/dist/src/index.d.ts +230 -0
- package/dist/src/mocking/index.d.ts +1 -0
- package/dist/src/mocking/sampler.d.ts +87 -0
- package/dist/src/react/useOpenAPI.d.ts +127 -3
- package/dist/src/utils.d.ts +103 -0
- package/dist/src/validation/index.d.ts +1 -0
- package/dist/src/validation/validator.d.ts +117 -0
- package/package.json +25 -8
- package/dist/src/auth.d.ts +0 -33
- package/dist/src/client.d.ts +0 -20
- package/dist/src/config.d.ts +0 -10
- package/dist/src/http.d.ts +0 -0
- package/dist/src/registry.d.ts +0 -28
- package/dist/src/sampler.d.ts +0 -2
- package/dist/src/validate.d.ts +0 -17
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers an OpenAPI spec by name.
|
|
3
|
+
* Normalizes missing operationIds and auto-detects auth.
|
|
4
|
+
*
|
|
5
|
+
* @param {{ name: string, specName: string | object, autoAuth?: boolean }} opts
|
|
6
|
+
* @returns {Promise<{ name: string, operations: import('./core/registry.js').OperationInfo[] }>}
|
|
7
|
+
* @throws {InvalidInputError} If name or specName is missing/invalid
|
|
8
|
+
* @throws {SpecLoadError} If spec file cannot be loaded
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // From file
|
|
12
|
+
* await save({ name: 'products', specName: 'products.openapi.json' })
|
|
13
|
+
*
|
|
14
|
+
* // From object
|
|
15
|
+
* await save({ name: 'users', specName: openApiSpec })
|
|
16
|
+
*/
|
|
17
|
+
export function save({ name, specName, autoAuth }: {
|
|
18
|
+
name: string;
|
|
19
|
+
specName: string | object;
|
|
20
|
+
autoAuth?: boolean;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
name: string;
|
|
23
|
+
operations: import("./core/registry.js").OperationInfo[];
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Re-registers a spec (alias for save).
|
|
27
|
+
*
|
|
28
|
+
* @param {Parameters<typeof save>[0]} opts - Same as save()
|
|
29
|
+
* @returns {ReturnType<typeof save>}
|
|
30
|
+
*/
|
|
31
|
+
export function update(opts: Parameters<typeof save>[0]): ReturnType<typeof save>;
|
|
32
|
+
/**
|
|
33
|
+
* Removes a spec from the registry.
|
|
34
|
+
*
|
|
35
|
+
* @param {{ name: string }} opts
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* remove({ name: 'products' })
|
|
39
|
+
*/
|
|
40
|
+
export function remove({ name }: {
|
|
41
|
+
name: string;
|
|
42
|
+
}): void;
|
|
43
|
+
/**
|
|
44
|
+
* Lists all registered spec names.
|
|
45
|
+
*
|
|
46
|
+
* @returns {string[]} Array of spec names
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* const specs = listSpecs() // ['products', 'users']
|
|
50
|
+
*/
|
|
51
|
+
export function listSpecs(): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Lists all operations for a registered spec.
|
|
54
|
+
*
|
|
55
|
+
* @param {{ name: string }} opts
|
|
56
|
+
* @returns {import('./core/registry.js').OperationInfo[]}
|
|
57
|
+
* @throws {SpecNotFoundError} If spec is not registered
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const apis = listAPIs({ name: 'products' })
|
|
61
|
+
* // [{ operationId: 'getProducts', method: 'get', path: '/products' }, ...]
|
|
62
|
+
*/
|
|
63
|
+
export function listAPIs({ name }: {
|
|
64
|
+
name: string;
|
|
65
|
+
}): import("./core/registry.js").OperationInfo[];
|
|
66
|
+
/**
|
|
67
|
+
* Returns the raw OpenAPI operation object.
|
|
68
|
+
*
|
|
69
|
+
* @param {{ name: string, api: string }} opts
|
|
70
|
+
* @returns {object} OpenAPI operation object with method/path
|
|
71
|
+
* @throws {SpecNotFoundError} If spec is not registered
|
|
72
|
+
* @throws {OperationNotFoundError} If operation doesn't exist
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* const contract = showContract({ name: 'products', api: 'getProducts' })
|
|
76
|
+
*/
|
|
77
|
+
export function showContract({ name, api }: {
|
|
78
|
+
name: string;
|
|
79
|
+
api: string;
|
|
80
|
+
}): object;
|
|
81
|
+
/**
|
|
82
|
+
* Generates a sample response for an operation.
|
|
83
|
+
*
|
|
84
|
+
* @param {{ name: string, api: string, status?: string | number }} opts
|
|
85
|
+
* @returns {any} Sample response data or null
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const sample = showResponseSample({ name: 'products', api: 'getProducts' })
|
|
89
|
+
*/
|
|
90
|
+
export function showResponseSample({ name, api, status }: {
|
|
91
|
+
name: string;
|
|
92
|
+
api: string;
|
|
93
|
+
status?: string | number;
|
|
94
|
+
}): any;
|
|
95
|
+
/**
|
|
96
|
+
* Generates a sample request body for an operation.
|
|
97
|
+
*
|
|
98
|
+
* @param {{ name: string, api: string }} opts
|
|
99
|
+
* @returns {any} Sample request body or null
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const sample = showRequestSample({ name: 'products', api: 'createProduct' })
|
|
103
|
+
*/
|
|
104
|
+
export function showRequestSample({ name, api }: {
|
|
105
|
+
name: string;
|
|
106
|
+
api: string;
|
|
107
|
+
}): any;
|
|
108
|
+
/**
|
|
109
|
+
* Executes an API operation.
|
|
110
|
+
*
|
|
111
|
+
* @param {{ name: string, api: string, params?: object, body?: any, headers?: object, qs?: object }} opts
|
|
112
|
+
* @returns {Promise<object>} API response
|
|
113
|
+
* @throws {SpecNotFoundError} If spec is not registered
|
|
114
|
+
* @throws {AuthenticationError} If auth is required but fails
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* const response = await executeAPI({
|
|
118
|
+
* name: 'products',
|
|
119
|
+
* api: 'createProduct',
|
|
120
|
+
* body: { name: 'Widget', price: 9.99 }
|
|
121
|
+
* })
|
|
122
|
+
*/
|
|
123
|
+
export function executeAPI({ name, api, params, body, headers, qs }: {
|
|
124
|
+
name: string;
|
|
125
|
+
api: string;
|
|
126
|
+
params?: object;
|
|
127
|
+
body?: any;
|
|
128
|
+
headers?: object;
|
|
129
|
+
qs?: object;
|
|
130
|
+
}): Promise<object>;
|
|
131
|
+
/**
|
|
132
|
+
* Validates data against an operation's response schema.
|
|
133
|
+
*
|
|
134
|
+
* @param {{ name: string, api: string, status: string | number, contentType?: string, data: any }} opts
|
|
135
|
+
* @returns {{ valid: boolean, errors?: object[] }}
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* const result = validateResponseData({
|
|
139
|
+
* name: 'products',
|
|
140
|
+
* api: 'getProducts',
|
|
141
|
+
* status: 200,
|
|
142
|
+
* data: responseData
|
|
143
|
+
* })
|
|
144
|
+
*/
|
|
145
|
+
export function validateResponseData(opts: {
|
|
146
|
+
name: string;
|
|
147
|
+
api: string;
|
|
148
|
+
status: string | number;
|
|
149
|
+
contentType?: string;
|
|
150
|
+
data: any;
|
|
151
|
+
}): {
|
|
152
|
+
valid: boolean;
|
|
153
|
+
errors?: object[];
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Validates data against an operation's request schema.
|
|
157
|
+
*
|
|
158
|
+
* @param {{ name: string, api: string, body: any, contentType?: string }} opts
|
|
159
|
+
* @returns {{ valid: boolean, errors?: object[] }}
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* const result = validateRequestData({
|
|
163
|
+
* name: 'products',
|
|
164
|
+
* api: 'createProduct',
|
|
165
|
+
* body: productData
|
|
166
|
+
* })
|
|
167
|
+
*/
|
|
168
|
+
export function validateRequestData(opts: {
|
|
169
|
+
name: string;
|
|
170
|
+
api: string;
|
|
171
|
+
body: any;
|
|
172
|
+
contentType?: string;
|
|
173
|
+
}): {
|
|
174
|
+
valid: boolean;
|
|
175
|
+
errors?: object[];
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Returns a mocked response (no network call).
|
|
179
|
+
*
|
|
180
|
+
* @param {{ name: string, api: string, status?: string | number }} opts
|
|
181
|
+
* @returns {any} Mock response data
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* const mock = mockAPI({ name: 'products', api: 'getProducts' })
|
|
185
|
+
*/
|
|
186
|
+
export function mockAPI({ name, api, status }: {
|
|
187
|
+
name: string;
|
|
188
|
+
api: string;
|
|
189
|
+
status?: string | number;
|
|
190
|
+
}): any;
|
|
191
|
+
/**
|
|
192
|
+
* Sets global headers applied to all specs.
|
|
193
|
+
*
|
|
194
|
+
* @param {Record<string, string>} headers
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* setGlobalHeaders({ 'X-Correlation-ID': correlationId })
|
|
198
|
+
*/
|
|
199
|
+
export function setGlobalHeaders(headers: Record<string, string>): void;
|
|
200
|
+
/**
|
|
201
|
+
* Sets default headers for a specific spec.
|
|
202
|
+
*
|
|
203
|
+
* @param {string} name - Spec name
|
|
204
|
+
* @param {Record<string, string>} headers
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* setSpecHeaders('products', { 'X-Tenant': 'acme' })
|
|
208
|
+
*/
|
|
209
|
+
export function setSpecHeaders(name: string, headers: Record<string, string>): void;
|
|
210
|
+
/**
|
|
211
|
+
* Sets interceptors for a spec.
|
|
212
|
+
*
|
|
213
|
+
* @param {string} name - Spec name
|
|
214
|
+
* @param {{ request?: Function, response?: Function, error?: Function }} interceptors
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* setInterceptors('products', {
|
|
218
|
+
* request: (req) => { console.log('Request:', req); return req },
|
|
219
|
+
* response: (res) => { console.log('Response:', res); return res },
|
|
220
|
+
* error: (err) => { console.error('Error:', err); throw err }
|
|
221
|
+
* })
|
|
222
|
+
*/
|
|
223
|
+
export function setInterceptors(name: string, interceptors: {
|
|
224
|
+
request?: Function;
|
|
225
|
+
response?: Function;
|
|
226
|
+
error?: Function;
|
|
227
|
+
}): void;
|
|
228
|
+
export { clearRegistry } from "./core/registry.js";
|
|
229
|
+
export { setAuth, apiKey, bearer, basic, clientCredentials } from "./auth/index.js";
|
|
230
|
+
export { OpenAPIRuntimeError, SpecNotFoundError, OperationNotFoundError, AuthenticationError, SecurityError, ValidationError, SpecLoadError, ConfigurationError, InvalidInputError } from "./errors.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sampleResponse, sampleRequest, sampleParameters, generateMock } from "./sampler.js";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sampler options.
|
|
3
|
+
* @typedef {Object} SamplerOptions
|
|
4
|
+
* @property {boolean} [skipReadOnly=false] - Skip readOnly properties
|
|
5
|
+
* @property {boolean} [skipWriteOnly=false] - Skip writeOnly properties
|
|
6
|
+
* @property {boolean} [skipNonRequired=false] - Skip non-required properties
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Generates a sample response for an operation.
|
|
10
|
+
*
|
|
11
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
12
|
+
* @param {string} operationId - Operation ID
|
|
13
|
+
* @param {string | number} [status] - HTTP status code (default: first 2xx or first available)
|
|
14
|
+
* @param {SamplerOptions} [options] - Sampling options
|
|
15
|
+
* @returns {any} Sample response data or null if no schema
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const mockUser = sampleResponse(entry, 'getUser', 200)
|
|
19
|
+
* // { id: 123, name: 'string', email: 'user@example.com' }
|
|
20
|
+
*/
|
|
21
|
+
export function sampleResponse(entry: import("../core/registry.js").SpecEntry, operationId: string, status?: string | number, options?: SamplerOptions): any;
|
|
22
|
+
/**
|
|
23
|
+
* Generates a sample request body for an operation.
|
|
24
|
+
*
|
|
25
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
26
|
+
* @param {string} operationId - Operation ID
|
|
27
|
+
* @param {SamplerOptions} [options] - Sampling options
|
|
28
|
+
* @returns {any} Sample request body or null if no schema
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const mockBody = sampleRequest(entry, 'createUser')
|
|
32
|
+
* // { name: 'string', email: 'user@example.com' }
|
|
33
|
+
*/
|
|
34
|
+
export function sampleRequest(entry: import("../core/registry.js").SpecEntry, operationId: string, options?: SamplerOptions): any;
|
|
35
|
+
/**
|
|
36
|
+
* Generates sample parameters for an operation.
|
|
37
|
+
*
|
|
38
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
39
|
+
* @param {string} operationId - Operation ID
|
|
40
|
+
* @returns {{ path: Record<string, any>, query: Record<string, any>, header: Record<string, any> }}
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const params = sampleParameters(entry, 'getUserById')
|
|
44
|
+
* // { path: { id: 123 }, query: {}, header: {} }
|
|
45
|
+
*/
|
|
46
|
+
export function sampleParameters(entry: import("../core/registry.js").SpecEntry, operationId: string): {
|
|
47
|
+
path: Record<string, any>;
|
|
48
|
+
query: Record<string, any>;
|
|
49
|
+
header: Record<string, any>;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Generates a complete mock for an operation including parameters and body.
|
|
53
|
+
*
|
|
54
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
55
|
+
* @param {string} operationId - Operation ID
|
|
56
|
+
* @returns {{ parameters: object, body: any, response: any }}
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const mock = generateMock(entry, 'createUser')
|
|
60
|
+
* // {
|
|
61
|
+
* // parameters: { path: {}, query: {}, header: {} },
|
|
62
|
+
* // body: { name: 'string', email: 'user@example.com' },
|
|
63
|
+
* // response: { id: 123, name: 'string' }
|
|
64
|
+
* // }
|
|
65
|
+
*/
|
|
66
|
+
export function generateMock(entry: import("../core/registry.js").SpecEntry, operationId: string): {
|
|
67
|
+
parameters: object;
|
|
68
|
+
body: any;
|
|
69
|
+
response: any;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Sampler options.
|
|
73
|
+
*/
|
|
74
|
+
export type SamplerOptions = {
|
|
75
|
+
/**
|
|
76
|
+
* - Skip readOnly properties
|
|
77
|
+
*/
|
|
78
|
+
skipReadOnly?: boolean | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* - Skip writeOnly properties
|
|
81
|
+
*/
|
|
82
|
+
skipWriteOnly?: boolean | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* - Skip non-required properties
|
|
85
|
+
*/
|
|
86
|
+
skipNonRequired?: boolean | undefined;
|
|
87
|
+
};
|
|
@@ -1,6 +1,130 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @
|
|
2
|
+
* Hook return type.
|
|
3
|
+
* @typedef {Object} UseOpenAPIReturn
|
|
4
|
+
* @property {(specName: string | object, options?: { autoAuth?: boolean }) => Promise<object>} save - Register a spec
|
|
5
|
+
* @property {() => import('../core/registry.js').OperationInfo[]} listAPIs - List operations
|
|
6
|
+
* @property {(api: string) => object} showContract - Get operation details
|
|
7
|
+
* @property {(api: string, status?: string | number) => any} showResponseSample - Get response sample
|
|
8
|
+
* @property {(api: string) => any} showRequestSample - Get request sample
|
|
9
|
+
* @property {(api: string, options?: { params?: object, body?: any, headers?: object, qs?: object }) => Promise<object>} executeAPI - Execute an operation
|
|
10
|
+
* @property {(api: string, options: { status: string | number, data: any, contentType?: string }) => object} validateResponse - Validate response
|
|
11
|
+
* @property {(api: string, options: { body: any, contentType?: string }) => object} validateRequest - Validate request
|
|
12
|
+
* @property {(api: string, status?: string | number) => any} mockAPI - Get mock response
|
|
4
13
|
*/
|
|
5
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Hook options.
|
|
16
|
+
* @typedef {Object} UseOpenAPIOptions
|
|
17
|
+
* @property {boolean} [throwOnError=false] - Throw errors instead of returning them
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* React hook for OpenAPI runtime operations.
|
|
21
|
+
* Binds all operations to a specific spec name for convenience.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} name - Registered spec name
|
|
24
|
+
* @param {UseOpenAPIOptions} [options] - Hook options
|
|
25
|
+
* @returns {UseOpenAPIReturn} Bound API operations
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* function ProductList() {
|
|
29
|
+
* const api = useOpenAPI('products')
|
|
30
|
+
*
|
|
31
|
+
* useEffect(() => {
|
|
32
|
+
* api.executeAPI('getProducts')
|
|
33
|
+
* .then(res => setProducts(res.body))
|
|
34
|
+
* }, [])
|
|
35
|
+
*
|
|
36
|
+
* return <div>...</div>
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
export function useOpenAPI(name: string, options?: UseOpenAPIOptions): UseOpenAPIReturn;
|
|
40
|
+
/**
|
|
41
|
+
* React hook for OpenAPI with loading/error state management.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} name - Registered spec name
|
|
44
|
+
* @returns {{ api: UseOpenAPIReturn, loading: boolean, error: Error | null, execute: Function }}
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* function ProductList() {
|
|
48
|
+
* const { api, loading, error, execute } = useOpenAPIWithState('products')
|
|
49
|
+
*
|
|
50
|
+
* const loadProducts = () => execute(
|
|
51
|
+
* () => api.executeAPI('getProducts'),
|
|
52
|
+
* (res) => setProducts(res.body)
|
|
53
|
+
* )
|
|
54
|
+
*
|
|
55
|
+
* if (loading) return <Spinner />
|
|
56
|
+
* if (error) return <Error message={error.message} />
|
|
57
|
+
* return <div>...</div>
|
|
58
|
+
* }
|
|
59
|
+
*/
|
|
60
|
+
export function useOpenAPIWithState(name: string): {
|
|
61
|
+
api: UseOpenAPIReturn;
|
|
62
|
+
loading: boolean;
|
|
63
|
+
error: Error | null;
|
|
64
|
+
execute: Function;
|
|
65
|
+
};
|
|
6
66
|
export default useOpenAPI;
|
|
67
|
+
/**
|
|
68
|
+
* Hook return type.
|
|
69
|
+
*/
|
|
70
|
+
export type UseOpenAPIReturn = {
|
|
71
|
+
/**
|
|
72
|
+
* - Register a spec
|
|
73
|
+
*/
|
|
74
|
+
save: (specName: string | object, options?: {
|
|
75
|
+
autoAuth?: boolean;
|
|
76
|
+
}) => Promise<object>;
|
|
77
|
+
/**
|
|
78
|
+
* - List operations
|
|
79
|
+
*/
|
|
80
|
+
listAPIs: () => import("../core/registry.js").OperationInfo[];
|
|
81
|
+
/**
|
|
82
|
+
* - Get operation details
|
|
83
|
+
*/
|
|
84
|
+
showContract: (api: string) => object;
|
|
85
|
+
/**
|
|
86
|
+
* - Get response sample
|
|
87
|
+
*/
|
|
88
|
+
showResponseSample: (api: string, status?: string | number) => any;
|
|
89
|
+
/**
|
|
90
|
+
* - Get request sample
|
|
91
|
+
*/
|
|
92
|
+
showRequestSample: (api: string) => any;
|
|
93
|
+
/**
|
|
94
|
+
* - Execute an operation
|
|
95
|
+
*/
|
|
96
|
+
executeAPI: (api: string, options?: {
|
|
97
|
+
params?: object;
|
|
98
|
+
body?: any;
|
|
99
|
+
headers?: object;
|
|
100
|
+
qs?: object;
|
|
101
|
+
}) => Promise<object>;
|
|
102
|
+
/**
|
|
103
|
+
* - Validate response
|
|
104
|
+
*/
|
|
105
|
+
validateResponse: (api: string, options: {
|
|
106
|
+
status: string | number;
|
|
107
|
+
data: any;
|
|
108
|
+
contentType?: string;
|
|
109
|
+
}) => object;
|
|
110
|
+
/**
|
|
111
|
+
* - Validate request
|
|
112
|
+
*/
|
|
113
|
+
validateRequest: (api: string, options: {
|
|
114
|
+
body: any;
|
|
115
|
+
contentType?: string;
|
|
116
|
+
}) => object;
|
|
117
|
+
/**
|
|
118
|
+
* - Get mock response
|
|
119
|
+
*/
|
|
120
|
+
mockAPI: (api: string, status?: string | number) => any;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Hook options.
|
|
124
|
+
*/
|
|
125
|
+
export type UseOpenAPIOptions = {
|
|
126
|
+
/**
|
|
127
|
+
* - Throw errors instead of returning them
|
|
128
|
+
*/
|
|
129
|
+
throwOnError?: boolean | undefined;
|
|
130
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the media type object from OpenAPI content map.
|
|
3
|
+
* Prefers the specified type, falls back to application/json, then first available.
|
|
4
|
+
*
|
|
5
|
+
* @param {Record<string, object> | undefined} content - OpenAPI content object
|
|
6
|
+
* @param {string} [preferredType] - Preferred content type
|
|
7
|
+
* @returns {object | null} Media type object or null if not found
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const media = resolveMediaType(response.content)
|
|
11
|
+
* const schema = media?.schema
|
|
12
|
+
*/
|
|
13
|
+
export function resolveMediaType(content: Record<string, object> | undefined, preferredType?: string): object | null;
|
|
14
|
+
/**
|
|
15
|
+
* Retrieves an operation from a spec entry, throwing if not found.
|
|
16
|
+
*
|
|
17
|
+
* @param {import('./core/registry.js').SpecEntry} entry - Spec registry entry
|
|
18
|
+
* @param {string} operationId - Operation ID to find
|
|
19
|
+
* @returns {object} The operation object
|
|
20
|
+
* @throws {OperationNotFoundError} If operation doesn't exist
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const op = getOperation(entry, 'getUsers')
|
|
24
|
+
*/
|
|
25
|
+
export function getOperation(entry: import("./core/registry.js").SpecEntry, operationId: string): object;
|
|
26
|
+
/**
|
|
27
|
+
* Safely merges headers, handling undefined/null cases.
|
|
28
|
+
*
|
|
29
|
+
* @param {Record<string, string> | undefined} existing - Current headers
|
|
30
|
+
* @param {Record<string, string>} additions - Headers to add
|
|
31
|
+
* @returns {Record<string, string>} Merged headers object
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* req.headers = mergeHeaders(req.headers, { Authorization: 'Bearer xxx' })
|
|
35
|
+
*/
|
|
36
|
+
export function mergeHeaders(existing: Record<string, string> | undefined, additions: Record<string, string>): Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Validates a spec name against allowed pattern.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} name - Spec name to validate
|
|
41
|
+
* @throws {InvalidInputError} If name is invalid
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* validateSpecName('my-api') // OK
|
|
45
|
+
* validateSpecName('123bad') // throws
|
|
46
|
+
*/
|
|
47
|
+
export function validateSpecName(name: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Validates that required fields are present in an options object.
|
|
50
|
+
*
|
|
51
|
+
* @param {object} opts - Options object to validate
|
|
52
|
+
* @param {string[]} required - List of required field names
|
|
53
|
+
* @param {string} context - Function/context name for error messages
|
|
54
|
+
* @throws {InvalidInputError} If any required field is missing
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* validateRequired({ name: 'foo' }, ['name', 'spec'], 'save()')
|
|
58
|
+
*/
|
|
59
|
+
export function validateRequired(opts: object, required: string[], context: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Resolves a value that may be a function (sync or async).
|
|
62
|
+
*
|
|
63
|
+
* @template T
|
|
64
|
+
* @param {T | (() => T) | (() => Promise<T>)} valueOrFn - Value or function
|
|
65
|
+
* @returns {Promise<T>} Resolved value
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* const token = await resolveMaybeFn(getToken) // works with fn or value
|
|
69
|
+
*/
|
|
70
|
+
export function resolveMaybeFn<T>(valueOrFn: T | (() => T) | (() => Promise<T>)): Promise<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Finds the best 2xx status code from a responses object.
|
|
73
|
+
*
|
|
74
|
+
* @param {Record<string, object> | undefined} responses - OpenAPI responses object
|
|
75
|
+
* @returns {string | undefined} Best 2xx status code or first available
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* const status = pick2xxStatus(operation.responses) // '200'
|
|
79
|
+
*/
|
|
80
|
+
export function pick2xxStatus(responses: Record<string, object> | undefined): string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Safely reads an environment variable with optional default.
|
|
83
|
+
* Supports "KEY|default" syntax for inline defaults.
|
|
84
|
+
*
|
|
85
|
+
* @param {string | undefined} keyOrExpr - Env var key or "key|default" expression
|
|
86
|
+
* @returns {string | undefined} Environment variable value or default
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* getEnv('API_KEY') // process.env.API_KEY
|
|
90
|
+
* getEnv('API_KEY|fallback') // API_KEY value or 'fallback'
|
|
91
|
+
*/
|
|
92
|
+
export function getEnv(keyOrExpr: string | undefined): string | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Validates that a URL uses HTTPS protocol.
|
|
95
|
+
*
|
|
96
|
+
* @param {string} url - URL to validate
|
|
97
|
+
* @param {string} context - Context for error message
|
|
98
|
+
* @throws {import('./errors.js').SecurityError} If URL is not HTTPS
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* enforceHttps('https://auth.example.com/token', 'OAuth token URL')
|
|
102
|
+
*/
|
|
103
|
+
export function enforceHttps(url: string, context: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { validateResponse, validateRequest, assertValidResponse, assertValidRequest, clearValidationCache } from "./validator.js";
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates a response against the operation's response schema.
|
|
3
|
+
*
|
|
4
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
5
|
+
* @param {ValidateResponseOptions} opts - Validation options
|
|
6
|
+
* @returns {ValidationResult} Validation result
|
|
7
|
+
* @throws {OperationNotFoundError} If operation doesn't exist
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const result = validateResponse(entry, {
|
|
11
|
+
* api: 'getUsers',
|
|
12
|
+
* status: 200,
|
|
13
|
+
* data: responseData
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* if (!result.valid) {
|
|
17
|
+
* console.error('Validation errors:', result.errors)
|
|
18
|
+
* }
|
|
19
|
+
*/
|
|
20
|
+
export function validateResponse(entry: import("../core/registry.js").SpecEntry, { api, status, contentType, data }: ValidateResponseOptions): ValidationResult;
|
|
21
|
+
/**
|
|
22
|
+
* Validates a request body against the operation's request schema.
|
|
23
|
+
*
|
|
24
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
25
|
+
* @param {ValidateRequestOptions} opts - Validation options
|
|
26
|
+
* @returns {ValidationResult} Validation result
|
|
27
|
+
* @throws {OperationNotFoundError} If operation doesn't exist
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const result = validateRequest(entry, {
|
|
31
|
+
* api: 'createUser',
|
|
32
|
+
* body: { name: 'John', email: 'john@example.com' }
|
|
33
|
+
* })
|
|
34
|
+
*
|
|
35
|
+
* if (!result.valid) {
|
|
36
|
+
* throw new Error('Invalid request: ' + JSON.stringify(result.errors))
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
export function validateRequest(entry: import("../core/registry.js").SpecEntry, { api, body, contentType }: ValidateRequestOptions): ValidationResult;
|
|
40
|
+
/**
|
|
41
|
+
* Validates response data, throwing on failure.
|
|
42
|
+
*
|
|
43
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
44
|
+
* @param {ValidateResponseOptions} opts - Validation options
|
|
45
|
+
* @throws {ValidationError} If validation fails
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* assertValidResponse(entry, { api: 'getUsers', status: 200, data })
|
|
49
|
+
*/
|
|
50
|
+
export function assertValidResponse(entry: import("../core/registry.js").SpecEntry, opts: ValidateResponseOptions): void;
|
|
51
|
+
/**
|
|
52
|
+
* Validates request body, throwing on failure.
|
|
53
|
+
*
|
|
54
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
55
|
+
* @param {ValidateRequestOptions} opts - Validation options
|
|
56
|
+
* @throws {ValidationError} If validation fails
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* assertValidRequest(entry, { api: 'createUser', body: userData })
|
|
60
|
+
*/
|
|
61
|
+
export function assertValidRequest(entry: import("../core/registry.js").SpecEntry, opts: ValidateRequestOptions): void;
|
|
62
|
+
/**
|
|
63
|
+
* Clears the compiled schema cache.
|
|
64
|
+
* Useful for testing or after spec updates.
|
|
65
|
+
*/
|
|
66
|
+
export function clearValidationCache(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Validation result.
|
|
69
|
+
*/
|
|
70
|
+
export type ValidationResult = {
|
|
71
|
+
/**
|
|
72
|
+
* - Whether validation passed
|
|
73
|
+
*/
|
|
74
|
+
valid: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* - AJV errors if invalid
|
|
77
|
+
*/
|
|
78
|
+
errors?: object[] | undefined;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Response validation options.
|
|
82
|
+
*/
|
|
83
|
+
export type ValidateResponseOptions = {
|
|
84
|
+
/**
|
|
85
|
+
* - Operation ID
|
|
86
|
+
*/
|
|
87
|
+
api: string;
|
|
88
|
+
/**
|
|
89
|
+
* - HTTP status code
|
|
90
|
+
*/
|
|
91
|
+
status: string | number;
|
|
92
|
+
/**
|
|
93
|
+
* - Response content type
|
|
94
|
+
*/
|
|
95
|
+
contentType?: string | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* - Response data to validate
|
|
98
|
+
*/
|
|
99
|
+
data: any;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Request validation options.
|
|
103
|
+
*/
|
|
104
|
+
export type ValidateRequestOptions = {
|
|
105
|
+
/**
|
|
106
|
+
* - Operation ID
|
|
107
|
+
*/
|
|
108
|
+
api: string;
|
|
109
|
+
/**
|
|
110
|
+
* - Request body to validate
|
|
111
|
+
*/
|
|
112
|
+
body: any;
|
|
113
|
+
/**
|
|
114
|
+
* - Request content type
|
|
115
|
+
*/
|
|
116
|
+
contentType?: string | undefined;
|
|
117
|
+
};
|