@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,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const index = require("../index.cjs");
|
|
5
|
+
function useOpenAPI(name, options = {}) {
|
|
6
|
+
const { throwOnError = false } = options;
|
|
7
|
+
const handleError = react.useCallback((error) => {
|
|
8
|
+
if (throwOnError) throw error;
|
|
9
|
+
console.error(`[useOpenAPI:${name}]`, error);
|
|
10
|
+
return { error };
|
|
11
|
+
}, [name, throwOnError]);
|
|
12
|
+
const api = react.useMemo(() => ({
|
|
13
|
+
/**
|
|
14
|
+
* Registers the spec (call once on mount).
|
|
15
|
+
*/
|
|
16
|
+
save: async (specName, opts = {}) => {
|
|
17
|
+
try {
|
|
18
|
+
return await index.save({ name, specName, ...opts });
|
|
19
|
+
} catch (error) {
|
|
20
|
+
return handleError(error);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* Lists all operations for this spec.
|
|
25
|
+
*/
|
|
26
|
+
listAPIs: () => {
|
|
27
|
+
try {
|
|
28
|
+
return index.listAPIs({ name });
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return handleError(error);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Gets the contract for an operation.
|
|
35
|
+
*/
|
|
36
|
+
showContract: (operationId) => {
|
|
37
|
+
try {
|
|
38
|
+
return index.showContract({ name, api: operationId });
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return handleError(error);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* Gets a sample response.
|
|
45
|
+
*/
|
|
46
|
+
showResponseSample: (operationId, status) => {
|
|
47
|
+
try {
|
|
48
|
+
return index.showResponseSample({ name, api: operationId, status });
|
|
49
|
+
} catch (error) {
|
|
50
|
+
return handleError(error);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
/**
|
|
54
|
+
* Gets a sample request body.
|
|
55
|
+
*/
|
|
56
|
+
showRequestSample: (operationId) => {
|
|
57
|
+
try {
|
|
58
|
+
return index.showRequestSample({ name, api: operationId });
|
|
59
|
+
} catch (error) {
|
|
60
|
+
return handleError(error);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* Executes an API operation.
|
|
65
|
+
*/
|
|
66
|
+
executeAPI: async (operationId, opts = {}) => {
|
|
67
|
+
try {
|
|
68
|
+
return await index.executeAPI({ name, api: operationId, ...opts });
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return handleError(error);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Validates a response.
|
|
75
|
+
*/
|
|
76
|
+
validateResponse: (operationId, opts) => {
|
|
77
|
+
try {
|
|
78
|
+
return index.validateResponseData({ name, api: operationId, ...opts });
|
|
79
|
+
} catch (error) {
|
|
80
|
+
return handleError(error);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Validates a request body.
|
|
85
|
+
*/
|
|
86
|
+
validateRequest: (operationId, opts) => {
|
|
87
|
+
try {
|
|
88
|
+
return index.validateRequestData({ name, api: operationId, ...opts });
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return handleError(error);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Gets a mock response.
|
|
95
|
+
*/
|
|
96
|
+
mockAPI: (operationId, status) => {
|
|
97
|
+
try {
|
|
98
|
+
return index.mockAPI({ name, api: operationId, status });
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return handleError(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}), [name, handleError]);
|
|
104
|
+
return api;
|
|
105
|
+
}
|
|
106
|
+
function useOpenAPIWithState(name) {
|
|
107
|
+
const [loading, setLoading] = react.useState(false);
|
|
108
|
+
const [error, setError] = react.useState(null);
|
|
109
|
+
const api = useOpenAPI(name, { throwOnError: true });
|
|
110
|
+
const execute = react.useCallback(async (operation, onSuccess) => {
|
|
111
|
+
setLoading(true);
|
|
112
|
+
setError(null);
|
|
113
|
+
try {
|
|
114
|
+
const result = await operation();
|
|
115
|
+
if (onSuccess) onSuccess(result);
|
|
116
|
+
return result;
|
|
117
|
+
} catch (err) {
|
|
118
|
+
setError(err);
|
|
119
|
+
return null;
|
|
120
|
+
} finally {
|
|
121
|
+
setLoading(false);
|
|
122
|
+
}
|
|
123
|
+
}, []);
|
|
124
|
+
return { api, loading, error, execute };
|
|
125
|
+
}
|
|
126
|
+
exports.default = useOpenAPI;
|
|
127
|
+
exports.useOpenAPI = useOpenAPI;
|
|
128
|
+
exports.useOpenAPIWithState = useOpenAPIWithState;
|
|
129
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/react/useOpenAPI.js"],"sourcesContent":["'use client'\n\n/**\n * @module react/useOpenAPI\n * @description React hook for OpenAPI runtime integration.\n */\n\nimport { useMemo, useCallback, useState } from 'react'\nimport {\n save,\n listAPIs,\n showContract,\n showResponseSample,\n showRequestSample,\n executeAPI,\n validateResponseData,\n validateRequestData,\n mockAPI\n} from '../index.js'\n\n// ============================================================================\n// TYPE DEFINITIONS\n// ============================================================================\n\n/**\n * Hook return type.\n * @typedef {Object} UseOpenAPIReturn\n * @property {(specName: string | object, options?: { autoAuth?: boolean }) => Promise<object>} save - Register a spec\n * @property {() => import('../core/registry.js').OperationInfo[]} listAPIs - List operations\n * @property {(api: string) => object} showContract - Get operation details\n * @property {(api: string, status?: string | number) => any} showResponseSample - Get response sample\n * @property {(api: string) => any} showRequestSample - Get request sample\n * @property {(api: string, options?: { params?: object, body?: any, headers?: object, qs?: object }) => Promise<object>} executeAPI - Execute an operation\n * @property {(api: string, options: { status: string | number, data: any, contentType?: string }) => object} validateResponse - Validate response\n * @property {(api: string, options: { body: any, contentType?: string }) => object} validateRequest - Validate request\n * @property {(api: string, status?: string | number) => any} mockAPI - Get mock response\n */\n\n/**\n * Hook options.\n * @typedef {Object} UseOpenAPIOptions\n * @property {boolean} [throwOnError=false] - Throw errors instead of returning them\n */\n\n// ============================================================================\n// HOOK IMPLEMENTATION\n// ============================================================================\n\n/**\n * React hook for OpenAPI runtime operations.\n * Binds all operations to a specific spec name for convenience.\n *\n * @param {string} name - Registered spec name\n * @param {UseOpenAPIOptions} [options] - Hook options\n * @returns {UseOpenAPIReturn} Bound API operations\n *\n * @example\n * function ProductList() {\n * const api = useOpenAPI('products')\n *\n * useEffect(() => {\n * api.executeAPI('getProducts')\n * .then(res => setProducts(res.body))\n * }, [])\n *\n * return <div>...</div>\n * }\n */\nexport function useOpenAPI(name, options = {}) {\n const { throwOnError = false } = options\n\n /**\n * Error handler wrapper.\n */\n const handleError = useCallback((error) => {\n if (throwOnError) throw error\n console.error(`[useOpenAPI:${name}]`, error)\n return { error }\n }, [name, throwOnError])\n\n /**\n * Memoized API bindings.\n */\n const api = useMemo(() => ({\n /**\n * Registers the spec (call once on mount).\n */\n save: async (specName, opts = {}) => {\n try {\n return await save({ name, specName, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Lists all operations for this spec.\n */\n listAPIs: () => {\n try {\n return listAPIs({ name })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets the contract for an operation.\n */\n showContract: (operationId) => {\n try {\n return showContract({ name, api: operationId })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets a sample response.\n */\n showResponseSample: (operationId, status) => {\n try {\n return showResponseSample({ name, api: operationId, status })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets a sample request body.\n */\n showRequestSample: (operationId) => {\n try {\n return showRequestSample({ name, api: operationId })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Executes an API operation.\n */\n executeAPI: async (operationId, opts = {}) => {\n try {\n return await executeAPI({ name, api: operationId, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Validates a response.\n */\n validateResponse: (operationId, opts) => {\n try {\n return validateResponseData({ name, api: operationId, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Validates a request body.\n */\n validateRequest: (operationId, opts) => {\n try {\n return validateRequestData({ name, api: operationId, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets a mock response.\n */\n mockAPI: (operationId, status) => {\n try {\n return mockAPI({ name, api: operationId, status })\n } catch (error) {\n return handleError(error)\n }\n }\n }), [name, handleError])\n\n return api\n}\n\n// ============================================================================\n// ASYNC HOOK WITH STATE\n// ============================================================================\n\n/**\n * React hook for OpenAPI with loading/error state management.\n *\n * @param {string} name - Registered spec name\n * @returns {{ api: UseOpenAPIReturn, loading: boolean, error: Error | null, execute: Function }}\n *\n * @example\n * function ProductList() {\n * const { api, loading, error, execute } = useOpenAPIWithState('products')\n *\n * const loadProducts = () => execute(\n * () => api.executeAPI('getProducts'),\n * (res) => setProducts(res.body)\n * )\n *\n * if (loading) return <Spinner />\n * if (error) return <Error message={error.message} />\n * return <div>...</div>\n * }\n */\nexport function useOpenAPIWithState(name) {\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState(null)\n\n const api = useOpenAPI(name, { throwOnError: true })\n\n const execute = useCallback(async (operation, onSuccess) => {\n setLoading(true)\n setError(null)\n\n try {\n const result = await operation()\n if (onSuccess) onSuccess(result)\n return result\n } catch (err) {\n setError(err)\n return null\n } finally {\n setLoading(false)\n }\n }, [])\n\n return { api, loading, error, execute }\n}\n\nexport default useOpenAPI\n"],"names":["useCallback","useMemo","save","listAPIs","showContract","showResponseSample","showRequestSample","executeAPI","validateResponseData","validateRequestData","mockAPI","useState"],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import { mockAPI, validateRequestData, validateResponseData, executeAPI, showRequestSample, showResponseSample, showContract, listAPIs, save } from "../index.esm.js";
|
|
3
|
+
function useOpenAPI(name, options = {}) {
|
|
4
|
+
const { throwOnError = false } = options;
|
|
5
|
+
const handleError = useCallback((error) => {
|
|
6
|
+
if (throwOnError) throw error;
|
|
7
|
+
console.error(`[useOpenAPI:${name}]`, error);
|
|
8
|
+
return { error };
|
|
9
|
+
}, [name, throwOnError]);
|
|
10
|
+
const api = useMemo(() => ({
|
|
11
|
+
/**
|
|
12
|
+
* Registers the spec (call once on mount).
|
|
13
|
+
*/
|
|
14
|
+
save: async (specName, opts = {}) => {
|
|
15
|
+
try {
|
|
16
|
+
return await save({ name, specName, ...opts });
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return handleError(error);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
/**
|
|
22
|
+
* Lists all operations for this spec.
|
|
23
|
+
*/
|
|
24
|
+
listAPIs: () => {
|
|
25
|
+
try {
|
|
26
|
+
return listAPIs({ name });
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return handleError(error);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
/**
|
|
32
|
+
* Gets the contract for an operation.
|
|
33
|
+
*/
|
|
34
|
+
showContract: (operationId) => {
|
|
35
|
+
try {
|
|
36
|
+
return showContract({ name, api: operationId });
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return handleError(error);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* Gets a sample response.
|
|
43
|
+
*/
|
|
44
|
+
showResponseSample: (operationId, status) => {
|
|
45
|
+
try {
|
|
46
|
+
return showResponseSample({ name, api: operationId, status });
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return handleError(error);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
/**
|
|
52
|
+
* Gets a sample request body.
|
|
53
|
+
*/
|
|
54
|
+
showRequestSample: (operationId) => {
|
|
55
|
+
try {
|
|
56
|
+
return showRequestSample({ name, api: operationId });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return handleError(error);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Executes an API operation.
|
|
63
|
+
*/
|
|
64
|
+
executeAPI: async (operationId, opts = {}) => {
|
|
65
|
+
try {
|
|
66
|
+
return await executeAPI({ name, api: operationId, ...opts });
|
|
67
|
+
} catch (error) {
|
|
68
|
+
return handleError(error);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Validates a response.
|
|
73
|
+
*/
|
|
74
|
+
validateResponse: (operationId, opts) => {
|
|
75
|
+
try {
|
|
76
|
+
return validateResponseData({ name, api: operationId, ...opts });
|
|
77
|
+
} catch (error) {
|
|
78
|
+
return handleError(error);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
/**
|
|
82
|
+
* Validates a request body.
|
|
83
|
+
*/
|
|
84
|
+
validateRequest: (operationId, opts) => {
|
|
85
|
+
try {
|
|
86
|
+
return validateRequestData({ name, api: operationId, ...opts });
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return handleError(error);
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* Gets a mock response.
|
|
93
|
+
*/
|
|
94
|
+
mockAPI: (operationId, status) => {
|
|
95
|
+
try {
|
|
96
|
+
return mockAPI({ name, api: operationId, status });
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return handleError(error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}), [name, handleError]);
|
|
102
|
+
return api;
|
|
103
|
+
}
|
|
104
|
+
function useOpenAPIWithState(name) {
|
|
105
|
+
const [loading, setLoading] = useState(false);
|
|
106
|
+
const [error, setError] = useState(null);
|
|
107
|
+
const api = useOpenAPI(name, { throwOnError: true });
|
|
108
|
+
const execute = useCallback(async (operation, onSuccess) => {
|
|
109
|
+
setLoading(true);
|
|
110
|
+
setError(null);
|
|
111
|
+
try {
|
|
112
|
+
const result = await operation();
|
|
113
|
+
if (onSuccess) onSuccess(result);
|
|
114
|
+
return result;
|
|
115
|
+
} catch (err) {
|
|
116
|
+
setError(err);
|
|
117
|
+
return null;
|
|
118
|
+
} finally {
|
|
119
|
+
setLoading(false);
|
|
120
|
+
}
|
|
121
|
+
}, []);
|
|
122
|
+
return { api, loading, error, execute };
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
useOpenAPI as default,
|
|
126
|
+
useOpenAPI,
|
|
127
|
+
useOpenAPIWithState
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/react/useOpenAPI.js"],"sourcesContent":["'use client'\n\n/**\n * @module react/useOpenAPI\n * @description React hook for OpenAPI runtime integration.\n */\n\nimport { useMemo, useCallback, useState } from 'react'\nimport {\n save,\n listAPIs,\n showContract,\n showResponseSample,\n showRequestSample,\n executeAPI,\n validateResponseData,\n validateRequestData,\n mockAPI\n} from '../index.js'\n\n// ============================================================================\n// TYPE DEFINITIONS\n// ============================================================================\n\n/**\n * Hook return type.\n * @typedef {Object} UseOpenAPIReturn\n * @property {(specName: string | object, options?: { autoAuth?: boolean }) => Promise<object>} save - Register a spec\n * @property {() => import('../core/registry.js').OperationInfo[]} listAPIs - List operations\n * @property {(api: string) => object} showContract - Get operation details\n * @property {(api: string, status?: string | number) => any} showResponseSample - Get response sample\n * @property {(api: string) => any} showRequestSample - Get request sample\n * @property {(api: string, options?: { params?: object, body?: any, headers?: object, qs?: object }) => Promise<object>} executeAPI - Execute an operation\n * @property {(api: string, options: { status: string | number, data: any, contentType?: string }) => object} validateResponse - Validate response\n * @property {(api: string, options: { body: any, contentType?: string }) => object} validateRequest - Validate request\n * @property {(api: string, status?: string | number) => any} mockAPI - Get mock response\n */\n\n/**\n * Hook options.\n * @typedef {Object} UseOpenAPIOptions\n * @property {boolean} [throwOnError=false] - Throw errors instead of returning them\n */\n\n// ============================================================================\n// HOOK IMPLEMENTATION\n// ============================================================================\n\n/**\n * React hook for OpenAPI runtime operations.\n * Binds all operations to a specific spec name for convenience.\n *\n * @param {string} name - Registered spec name\n * @param {UseOpenAPIOptions} [options] - Hook options\n * @returns {UseOpenAPIReturn} Bound API operations\n *\n * @example\n * function ProductList() {\n * const api = useOpenAPI('products')\n *\n * useEffect(() => {\n * api.executeAPI('getProducts')\n * .then(res => setProducts(res.body))\n * }, [])\n *\n * return <div>...</div>\n * }\n */\nexport function useOpenAPI(name, options = {}) {\n const { throwOnError = false } = options\n\n /**\n * Error handler wrapper.\n */\n const handleError = useCallback((error) => {\n if (throwOnError) throw error\n console.error(`[useOpenAPI:${name}]`, error)\n return { error }\n }, [name, throwOnError])\n\n /**\n * Memoized API bindings.\n */\n const api = useMemo(() => ({\n /**\n * Registers the spec (call once on mount).\n */\n save: async (specName, opts = {}) => {\n try {\n return await save({ name, specName, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Lists all operations for this spec.\n */\n listAPIs: () => {\n try {\n return listAPIs({ name })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets the contract for an operation.\n */\n showContract: (operationId) => {\n try {\n return showContract({ name, api: operationId })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets a sample response.\n */\n showResponseSample: (operationId, status) => {\n try {\n return showResponseSample({ name, api: operationId, status })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets a sample request body.\n */\n showRequestSample: (operationId) => {\n try {\n return showRequestSample({ name, api: operationId })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Executes an API operation.\n */\n executeAPI: async (operationId, opts = {}) => {\n try {\n return await executeAPI({ name, api: operationId, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Validates a response.\n */\n validateResponse: (operationId, opts) => {\n try {\n return validateResponseData({ name, api: operationId, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Validates a request body.\n */\n validateRequest: (operationId, opts) => {\n try {\n return validateRequestData({ name, api: operationId, ...opts })\n } catch (error) {\n return handleError(error)\n }\n },\n\n /**\n * Gets a mock response.\n */\n mockAPI: (operationId, status) => {\n try {\n return mockAPI({ name, api: operationId, status })\n } catch (error) {\n return handleError(error)\n }\n }\n }), [name, handleError])\n\n return api\n}\n\n// ============================================================================\n// ASYNC HOOK WITH STATE\n// ============================================================================\n\n/**\n * React hook for OpenAPI with loading/error state management.\n *\n * @param {string} name - Registered spec name\n * @returns {{ api: UseOpenAPIReturn, loading: boolean, error: Error | null, execute: Function }}\n *\n * @example\n * function ProductList() {\n * const { api, loading, error, execute } = useOpenAPIWithState('products')\n *\n * const loadProducts = () => execute(\n * () => api.executeAPI('getProducts'),\n * (res) => setProducts(res.body)\n * )\n *\n * if (loading) return <Spinner />\n * if (error) return <Error message={error.message} />\n * return <div>...</div>\n * }\n */\nexport function useOpenAPIWithState(name) {\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState(null)\n\n const api = useOpenAPI(name, { throwOnError: true })\n\n const execute = useCallback(async (operation, onSuccess) => {\n setLoading(true)\n setError(null)\n\n try {\n const result = await operation()\n if (onSuccess) onSuccess(result)\n return result\n } catch (err) {\n setError(err)\n return null\n } finally {\n setLoading(false)\n }\n }, [])\n\n return { api, loading, error, execute }\n}\n\nexport default useOpenAPI\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth config structure from YAML.
|
|
3
|
+
* @typedef {Object} AuthConfig
|
|
4
|
+
* @property {Record<string, SpecAuthConfig>} [auth] - Per-spec auth config
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Per-spec auth configuration.
|
|
8
|
+
* @typedef {Object} SpecAuthConfig
|
|
9
|
+
* @property {Record<string, SchemeConfig>} schemes - Auth scheme configs
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Individual scheme configuration.
|
|
13
|
+
* @typedef {Object} SchemeConfig
|
|
14
|
+
* @property {'apiKey' | 'http' | 'oauth2'} type - Scheme type
|
|
15
|
+
* @property {string} [scheme] - For http: 'basic' or 'bearer'
|
|
16
|
+
* @property {string} [in] - For apiKey: 'header' or 'query'
|
|
17
|
+
* @property {string} [name] - For apiKey: header/param name
|
|
18
|
+
* @property {string} [value] - Direct value
|
|
19
|
+
* @property {string} [valueFromEnv] - Env var name for value
|
|
20
|
+
* @property {string} [token] - Bearer token
|
|
21
|
+
* @property {string} [tokenFromEnv] - Env var for bearer token
|
|
22
|
+
* @property {string} [username] - Basic auth username
|
|
23
|
+
* @property {string} [usernameFromEnv] - Env var for username
|
|
24
|
+
* @property {string} [password] - Basic auth password
|
|
25
|
+
* @property {string} [passwordFromEnv] - Env var for password
|
|
26
|
+
* @property {string} [flow] - OAuth2 flow type
|
|
27
|
+
* @property {string} [tokenUrl] - OAuth2 token endpoint
|
|
28
|
+
* @property {string} [clientId] - OAuth2 client ID
|
|
29
|
+
* @property {string} [clientIdFromEnv] - Env var for client ID
|
|
30
|
+
* @property {string} [clientSecret] - OAuth2 client secret
|
|
31
|
+
* @property {string} [clientSecretFromEnv] - Env var for client secret
|
|
32
|
+
* @property {string} [scope] - OAuth2 scopes
|
|
33
|
+
* @property {string} [audience] - OAuth2 audience
|
|
34
|
+
* @property {Record<string, string>} [extraParams] - Extra OAuth2 params
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Loads auth configuration from YAML file.
|
|
38
|
+
*
|
|
39
|
+
* Location: `./openapi.auth.yml` in project root.
|
|
40
|
+
* Supports `${ENV_VAR}` interpolation.
|
|
41
|
+
*
|
|
42
|
+
* @returns {AuthConfig | null} Parsed config or null if not found
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const config = loadAuthConfig()
|
|
46
|
+
* const productAuth = config?.auth?.products
|
|
47
|
+
*/
|
|
48
|
+
export function loadAuthConfig(): AuthConfig | null;
|
|
49
|
+
/**
|
|
50
|
+
* Creates auth providers from YAML configuration.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} _specName - Spec name (for context)
|
|
53
|
+
* @param {object} _spec - OpenAPI spec (for reference)
|
|
54
|
+
* @param {SpecAuthConfig} config - Per-spec auth config
|
|
55
|
+
* @returns {Record<string, import('./providers.js').AuthProvider>} Provider map
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const providers = providersFromConfig('products', spec, config.auth.products)
|
|
59
|
+
* setAuth('products', providers)
|
|
60
|
+
*/
|
|
61
|
+
export function providersFromConfig(_specName: string, _spec: object, config: SpecAuthConfig): Record<string, import("./providers.js").AuthProvider>;
|
|
62
|
+
export { getEnv };
|
|
63
|
+
/**
|
|
64
|
+
* Auth config structure from YAML.
|
|
65
|
+
*/
|
|
66
|
+
export type AuthConfig = {
|
|
67
|
+
/**
|
|
68
|
+
* - Per-spec auth config
|
|
69
|
+
*/
|
|
70
|
+
auth?: Record<string, SpecAuthConfig> | undefined;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Per-spec auth configuration.
|
|
74
|
+
*/
|
|
75
|
+
export type SpecAuthConfig = {
|
|
76
|
+
/**
|
|
77
|
+
* - Auth scheme configs
|
|
78
|
+
*/
|
|
79
|
+
schemes: Record<string, SchemeConfig>;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Individual scheme configuration.
|
|
83
|
+
*/
|
|
84
|
+
export type SchemeConfig = {
|
|
85
|
+
/**
|
|
86
|
+
* - Scheme type
|
|
87
|
+
*/
|
|
88
|
+
type: "apiKey" | "http" | "oauth2";
|
|
89
|
+
/**
|
|
90
|
+
* - For http: 'basic' or 'bearer'
|
|
91
|
+
*/
|
|
92
|
+
scheme?: string | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* - For apiKey: 'header' or 'query'
|
|
95
|
+
*/
|
|
96
|
+
in?: string | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* - For apiKey: header/param name
|
|
99
|
+
*/
|
|
100
|
+
name?: string | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* - Direct value
|
|
103
|
+
*/
|
|
104
|
+
value?: string | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* - Env var name for value
|
|
107
|
+
*/
|
|
108
|
+
valueFromEnv?: string | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* - Bearer token
|
|
111
|
+
*/
|
|
112
|
+
token?: string | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* - Env var for bearer token
|
|
115
|
+
*/
|
|
116
|
+
tokenFromEnv?: string | undefined;
|
|
117
|
+
/**
|
|
118
|
+
* - Basic auth username
|
|
119
|
+
*/
|
|
120
|
+
username?: string | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* - Env var for username
|
|
123
|
+
*/
|
|
124
|
+
usernameFromEnv?: string | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* - Basic auth password
|
|
127
|
+
*/
|
|
128
|
+
password?: string | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* - Env var for password
|
|
131
|
+
*/
|
|
132
|
+
passwordFromEnv?: string | undefined;
|
|
133
|
+
/**
|
|
134
|
+
* - OAuth2 flow type
|
|
135
|
+
*/
|
|
136
|
+
flow?: string | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* - OAuth2 token endpoint
|
|
139
|
+
*/
|
|
140
|
+
tokenUrl?: string | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* - OAuth2 client ID
|
|
143
|
+
*/
|
|
144
|
+
clientId?: string | undefined;
|
|
145
|
+
/**
|
|
146
|
+
* - Env var for client ID
|
|
147
|
+
*/
|
|
148
|
+
clientIdFromEnv?: string | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* - OAuth2 client secret
|
|
151
|
+
*/
|
|
152
|
+
clientSecret?: string | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* - Env var for client secret
|
|
155
|
+
*/
|
|
156
|
+
clientSecretFromEnv?: string | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* - OAuth2 scopes
|
|
159
|
+
*/
|
|
160
|
+
scope?: string | undefined;
|
|
161
|
+
/**
|
|
162
|
+
* - OAuth2 audience
|
|
163
|
+
*/
|
|
164
|
+
audience?: string | undefined;
|
|
165
|
+
/**
|
|
166
|
+
* - Extra OAuth2 params
|
|
167
|
+
*/
|
|
168
|
+
extraParams?: Record<string, string> | undefined;
|
|
169
|
+
};
|
|
170
|
+
import { getEnv } from '../utils.js';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers authentication providers for a spec.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} name - Spec name
|
|
5
|
+
* @param {Record<string, import('./providers.js').AuthProvider>} providers - Provider map
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* setAuth('products', {
|
|
9
|
+
* bearerAuth: bearer({ token: 'xxx' }),
|
|
10
|
+
* apiKeyAuth: apiKey({ in: 'header', name: 'X-Key', getValue: () => 'key' })
|
|
11
|
+
* })
|
|
12
|
+
*/
|
|
13
|
+
export function setAuth(name: string, providers: Record<string, import("./providers.js").AuthProvider>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the auth providers for a spec.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} name - Spec name
|
|
18
|
+
* @returns {AuthRegistryEntry | undefined} Auth registry entry
|
|
19
|
+
*/
|
|
20
|
+
export function getAuth(name: string): AuthRegistryEntry | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Clears auth configuration for a spec or all specs.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} [name] - Spec name (omit to clear all)
|
|
25
|
+
*/
|
|
26
|
+
export function clearAuth(name?: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Applies authentication to a request based on operation security requirements.
|
|
29
|
+
*
|
|
30
|
+
* Security resolution order:
|
|
31
|
+
* 1. Operation-level security (if defined and non-empty)
|
|
32
|
+
* 2. Spec-level security (fallback)
|
|
33
|
+
*
|
|
34
|
+
* For each security requirement, ALL schemes must be satisfied.
|
|
35
|
+
* Multiple requirements are OR'd - first successful one wins.
|
|
36
|
+
*
|
|
37
|
+
* @param {import('../core/registry.js').SpecEntry} entry - Spec entry
|
|
38
|
+
* @param {string} operationId - Operation being called
|
|
39
|
+
* @param {object} req - Request object to mutate
|
|
40
|
+
* @throws {AuthenticationError} If auth is required but all providers fail
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* await applyAuth(entry, 'createUser', requestObject)
|
|
44
|
+
*/
|
|
45
|
+
export function applyAuth(entry: import("../core/registry.js").SpecEntry, operationId: string, req: object): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Auth registry entry for a spec.
|
|
48
|
+
*/
|
|
49
|
+
export type AuthRegistryEntry = {
|
|
50
|
+
providers: Record<string, import("./providers.js").AuthProvider>;
|
|
51
|
+
};
|