@furystack/rest 8.0.42 → 8.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/CHANGELOG.md +71 -0
- package/README.md +37 -1
- package/esm/api-endpoint-schema.d.ts +47 -2
- package/esm/api-endpoint-schema.d.ts.map +1 -1
- package/esm/index.d.ts +4 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -1
- package/esm/index.js.map +1 -1
- package/esm/openapi-document.d.ts +303 -0
- package/esm/openapi-document.d.ts.map +1 -0
- package/esm/openapi-document.js +2 -0
- package/esm/openapi-document.js.map +1 -0
- package/esm/openapi-resolve-refs.d.ts +20 -0
- package/esm/openapi-resolve-refs.d.ts.map +1 -0
- package/esm/openapi-resolve-refs.js +68 -0
- package/esm/openapi-resolve-refs.js.map +1 -0
- package/esm/openapi-resolve-refs.spec.d.ts +2 -0
- package/esm/openapi-resolve-refs.spec.d.ts.map +1 -0
- package/esm/openapi-resolve-refs.spec.js +294 -0
- package/esm/openapi-resolve-refs.spec.js.map +1 -0
- package/esm/openapi-to-rest-api.d.ts +197 -0
- package/esm/openapi-to-rest-api.d.ts.map +1 -0
- package/esm/openapi-to-rest-api.js +2 -0
- package/esm/openapi-to-rest-api.js.map +1 -0
- package/esm/openapi-to-rest-api.spec.d.ts +2 -0
- package/esm/openapi-to-rest-api.spec.d.ts.map +1 -0
- package/esm/openapi-to-rest-api.spec.js +665 -0
- package/esm/openapi-to-rest-api.spec.js.map +1 -0
- package/esm/openapi-to-schema.d.ts +24 -0
- package/esm/openapi-to-schema.d.ts.map +1 -0
- package/esm/openapi-to-schema.js +145 -0
- package/esm/openapi-to-schema.js.map +1 -0
- package/esm/openapi-to-schema.spec.d.ts +2 -0
- package/esm/openapi-to-schema.spec.d.ts.map +1 -0
- package/esm/openapi-to-schema.spec.js +610 -0
- package/esm/openapi-to-schema.spec.js.map +1 -0
- package/esm/rest-api.d.ts +21 -4
- package/esm/rest-api.d.ts.map +1 -1
- package/esm/swagger-document.d.ts +2 -195
- package/esm/swagger-document.d.ts.map +1 -1
- package/esm/swagger-document.js +2 -1
- package/esm/swagger-document.js.map +1 -1
- package/package.json +3 -3
- package/src/api-endpoint-schema.ts +56 -3
- package/src/index.ts +4 -1
- package/src/openapi-document.ts +328 -0
- package/src/openapi-resolve-refs.spec.ts +324 -0
- package/src/openapi-resolve-refs.ts +71 -0
- package/src/openapi-to-rest-api.spec.ts +823 -0
- package/src/openapi-to-rest-api.ts +263 -0
- package/src/openapi-to-schema.spec.ts +707 -0
- package/src/openapi-to-schema.ts +163 -0
- package/src/rest-api.ts +26 -5
- package/src/swagger-document.ts +2 -220
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { OpenApiDocument } from './openapi-document.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves an internal JSON Pointer (e.g. `#/components/schemas/User`) against a document tree.
|
|
5
|
+
*/
|
|
6
|
+
const resolvePointer = (root: unknown, pointer: string): unknown => {
|
|
7
|
+
const segments = pointer
|
|
8
|
+
.replace(/^#\//, '')
|
|
9
|
+
.split('/')
|
|
10
|
+
.map((s) => s.replace(/~1/g, '/').replace(/~0/g, '~'))
|
|
11
|
+
|
|
12
|
+
let current: unknown = root
|
|
13
|
+
for (const segment of segments) {
|
|
14
|
+
if (current === null || current === undefined || typeof current !== 'object') return undefined
|
|
15
|
+
current = (current as Record<string, unknown>)[segment]
|
|
16
|
+
}
|
|
17
|
+
return current
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Deep-walks a value and replaces all `{ $ref: "#/..." }` objects with the resolved target.
|
|
22
|
+
* Tracks visited `$ref` strings to prevent infinite loops from circular references.
|
|
23
|
+
*/
|
|
24
|
+
const resolveNode = (node: unknown, root: unknown, visited: Set<string>): unknown => {
|
|
25
|
+
if (node === null || node === undefined || typeof node !== 'object') return node
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(node)) {
|
|
28
|
+
return node.map((item) => resolveNode(item, root, visited))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const obj = node as Record<string, unknown>
|
|
32
|
+
|
|
33
|
+
if (typeof obj.$ref === 'string') {
|
|
34
|
+
const ref = obj.$ref
|
|
35
|
+
if (!ref.startsWith('#/')) return node
|
|
36
|
+
if (visited.has(ref)) return {}
|
|
37
|
+
visited.add(ref)
|
|
38
|
+
const resolved = resolvePointer(root, ref)
|
|
39
|
+
if (resolved === undefined) return node
|
|
40
|
+
const result = resolveNode(resolved, root, new Set(visited))
|
|
41
|
+
visited.delete(ref)
|
|
42
|
+
return result
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const result: Record<string, unknown> = {}
|
|
46
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
47
|
+
result[key] = resolveNode(value, root, visited)
|
|
48
|
+
}
|
|
49
|
+
return result
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Resolves all internal `$ref` pointers in an OpenAPI document, inlining the referenced objects.
|
|
54
|
+
*
|
|
55
|
+
* Only internal references (`#/...`) are supported. External file references are left as-is.
|
|
56
|
+
* Circular references are broken by substituting an empty object `{}`.
|
|
57
|
+
*
|
|
58
|
+
* @param doc - The OpenAPI document with `$ref` pointers
|
|
59
|
+
* @returns A new OpenAPI document with all internal `$ref` pointers resolved
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* import { resolveOpenApiRefs } from '@furystack/rest'
|
|
64
|
+
*
|
|
65
|
+
* const resolved = resolveOpenApiRefs(myOpenApiDoc)
|
|
66
|
+
* // All $ref pointers have been replaced with the actual schemas
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export const resolveOpenApiRefs = (doc: OpenApiDocument): OpenApiDocument => {
|
|
70
|
+
return resolveNode(structuredClone(doc), doc, new Set()) as OpenApiDocument
|
|
71
|
+
}
|