@xyd-js/openapi 0.1.0-build.168

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +1517 -0
  2. package/LICENSE +21 -0
  3. package/README.md +3 -0
  4. package/__fixtures__/-2.complex.openai/input.yaml +39848 -0
  5. package/__fixtures__/-2.complex.openai/output.json +321646 -0
  6. package/__fixtures__/-2.complex.openai/pluginOasOpenai.ts +553 -0
  7. package/__fixtures__/-3.random/input.yaml +234 -0
  8. package/__fixtures__/-3.random/output.json +1140 -0
  9. package/__fixtures__/1.basic/input.yaml +226 -0
  10. package/__fixtures__/1.basic/output.json +1919 -0
  11. package/__fixtures__/2.more/input.yaml +76 -0
  12. package/__fixtures__/2.more/output.json +327 -0
  13. package/__fixtures__/3.multiple-responses/input.yaml +48 -0
  14. package/__fixtures__/3.multiple-responses/output.json +311 -0
  15. package/__fixtures__/5.xdocs.codeLanguages/input.yaml +231 -0
  16. package/__fixtures__/5.xdocs.codeLanguages/output.json +1879 -0
  17. package/__fixtures__/5.xdocs.sidebar/input.yaml +256 -0
  18. package/__fixtures__/5.xdocs.sidebar/output.json +843 -0
  19. package/__fixtures__/6.codeSamples/input.yaml +75 -0
  20. package/__fixtures__/6.codeSamples/output.json +293 -0
  21. package/__tests__/oapSchemaToReferences.test.ts +82 -0
  22. package/__tests__/utils.ts +81 -0
  23. package/dist/index.cjs +2154 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +40 -0
  26. package/dist/index.d.ts +40 -0
  27. package/dist/index.js +2119 -0
  28. package/dist/index.js.map +1 -0
  29. package/examples/basic/index.ts +20 -0
  30. package/examples/basic/index2.ts +36 -0
  31. package/examples/basic/openapi.yaml +124 -0
  32. package/examples/dist/index.cjs +2 -0
  33. package/examples/dist/index.cjs.map +1 -0
  34. package/examples/dist/index.d.cts +2 -0
  35. package/examples/dist/index.d.ts +2 -0
  36. package/examples/dist/index.js +2 -0
  37. package/examples/dist/index.js.map +1 -0
  38. package/examples/semi/index.ts +16 -0
  39. package/examples/semi/openapi.yaml +365 -0
  40. package/examples/semi/references.json +500 -0
  41. package/examples/webhooks/index.ts +16 -0
  42. package/examples/webhooks/openapi.yaml +248 -0
  43. package/examples/webhooks/references.json +895 -0
  44. package/index.ts +12 -0
  45. package/package.json +31 -0
  46. package/src/const.ts +14 -0
  47. package/src/converters/oas-componentSchemas.ts +205 -0
  48. package/src/converters/oas-examples.ts +530 -0
  49. package/src/converters/oas-parameters.ts +41 -0
  50. package/src/converters/oas-paths.ts +354 -0
  51. package/src/converters/oas-requestBody.ts +57 -0
  52. package/src/converters/oas-responses.ts +76 -0
  53. package/src/converters/oas-schema.ts +141 -0
  54. package/src/index.ts +21 -0
  55. package/src/oas-core.ts +579 -0
  56. package/src/types.ts +18 -0
  57. package/src/utils.ts +157 -0
  58. package/src/xdocs/index.ts +18 -0
  59. package/src/xdocs/pluginSidebar.ts +580 -0
  60. package/src/xdocs/types.ts +26 -0
  61. package/tsconfig.json +18 -0
  62. package/tsup.config.ts +19 -0
  63. package/tsup.examples-config.ts +30 -0
  64. package/vitest.config.ts +7 -0
package/src/utils.ts ADDED
@@ -0,0 +1,157 @@
1
+ import path from "path";
2
+ import fs from "fs/promises";
3
+
4
+ import yaml from "js-yaml";
5
+ import {OpenAPIV3} from "openapi-types";
6
+ import GithubSlugger from 'github-slugger';
7
+ import $refParser, {ParserOptions} from "@apidevtools/json-schema-ref-parser";
8
+
9
+ import {ReferenceType} from "@xyd-js/uniform";
10
+
11
+ export function slug(str: string): string {
12
+ const slugger = new GithubSlugger();
13
+ return slugger.slug(str);
14
+ }
15
+
16
+ // deferencedOpenAPI reads an OpenAPI spec file and returns a dereferenced OpenAPIV3.Document
17
+ // dereferenced means that all $ref references are resolved automatically
18
+ export async function deferencedOpenAPI(openApiPath: string) {
19
+ const openApiSpec = await readOpenApiSpec(openApiPath);
20
+ if (!openApiSpec) {
21
+ return
22
+ }
23
+
24
+ const cwd = process.cwd();
25
+
26
+ const remoteOasPath = openApiPath.startsWith('http://') || openApiPath.startsWith('https://') ? true : false
27
+
28
+ const circularRefs: Set<string> = new Set();
29
+
30
+ const options: ParserOptions = {
31
+ dereference: {
32
+ onCircular(defPath: string) {
33
+ const v = `#${defPath.split('#')[1]}`
34
+ circularRefs.add(v);
35
+ },
36
+ // circular: true, // ignore circular references,
37
+ // onCi
38
+ onDereference(defPath: any, value: any, parent: any) {
39
+ if (circularRefs.has(defPath) || circularRefs.has(path.join(defPath, "properties"))) {
40
+ value.__UNSAFE_circular = true; // TODO: BETTER WAY TO MARK CIRCULAR REFS
41
+ }
42
+ if (value && typeof value === 'object') {
43
+ value.__UNSAFE_refPath = () => defPath
44
+ }
45
+ if (parent && typeof parent === 'object') {
46
+ parent.__UNSAFE_refPath = () => defPath
47
+ }
48
+ }
49
+ }
50
+ } as ParserOptions;
51
+
52
+ if (remoteOasPath) {
53
+ if (!options.resolve) {
54
+ options.resolve = {}
55
+ }
56
+
57
+ options.resolve.file = {
58
+ read: async (file: any) => {
59
+ // 1) Convert absolute local path back into a repo-relative path:
60
+ // "/Users/.../docs/foo.md" → "docs/foo.md"
61
+ let rel = path.relative(cwd, file.url);
62
+ rel = rel.split(path.sep).join('/');
63
+
64
+ // 2) Resolve against your GitHub raw URL:
65
+ const absoluteUrl = new URL(rel, openApiPath).href;
66
+ // → "https://raw.githubusercontent.com/.../docs/foo.md"
67
+
68
+ // 3) Fetch it:
69
+ const res = await fetch(absoluteUrl);
70
+ if (!res.ok) {
71
+ throw new Error(`Failed to fetch ${absoluteUrl}: ${res.status}`);
72
+ }
73
+
74
+ let content;
75
+ if (file.extension === '.json' || file.extension === '.yaml' || file.extension === '.yml') {
76
+ // If the file is JSON or YAML, return the parsed content
77
+ if (file.extension === '.json') {
78
+ content = await res.json();
79
+ } else {
80
+ content = yaml.load(await res.text());
81
+ }
82
+ } else {
83
+ content = await res.text(); // hand back the Markdown
84
+ }
85
+
86
+ return content;
87
+ }
88
+ }
89
+ }
90
+
91
+ await $refParser.dereference(openApiSpec, options);
92
+ // await $refParser.bundle(openApiSpec, options);
93
+
94
+ return openApiSpec as OpenAPIV3.Document
95
+ }
96
+
97
+ // readOpenApiSpec reads an OpenAPI spec file or URL and returns the content
98
+ async function readOpenApiSpec(filePath: string) {
99
+ let content: string;
100
+ let fromUrl = false
101
+ if (filePath.startsWith('http://') || filePath.startsWith('https://')) {
102
+ const response = await fetch(filePath);
103
+ if (!response.ok) {
104
+ throw new Error(`Failed to fetch OpenAPI spec from URL: ${response.statusText}`);
105
+ }
106
+ content = await response.text();
107
+ fromUrl = true
108
+ } else {
109
+ try {
110
+ await fs.access(filePath);
111
+ } catch (error) {
112
+ console.log(`⚠️ "(openapi): ${filePath}" is defined in the docs.json navigation but the file does not exist.`)
113
+ return
114
+ }
115
+ content = await fs.readFile(filePath, 'utf-8');
116
+ }
117
+
118
+ const ext = path.extname(filePath).toLowerCase();
119
+ if (ext === '.yaml' || ext === '.yml') {
120
+ return yaml.load(content);
121
+ } else if (ext === '.json') {
122
+ return JSON.parse(content);
123
+ } else if (fromUrl && content.startsWith('{')) {
124
+ try {
125
+ return JSON.parse(content);
126
+ } catch (error) {
127
+ throw new Error(`Failed to parse JSON from URL: ${error}`);
128
+ }
129
+ } else {
130
+ throw new Error('Unsupported file format. Use JSON or YAML.');
131
+ }
132
+ }
133
+
134
+ // httpMethodToUniformMethod converts an HTTP method to a uniform ReferenceType
135
+ export function httpMethodToUniformMethod(method: string): ReferenceType | null {
136
+ switch (method) {
137
+ case 'get':
138
+ return ReferenceType.REST_HTTP_GET
139
+ case 'put':
140
+ return ReferenceType.REST_HTTP_PUT
141
+ case 'patch':
142
+ return ReferenceType.REST_HTTP_PATCH
143
+ case 'post':
144
+ return ReferenceType.REST_HTTP_POST
145
+ case 'delete':
146
+ return ReferenceType.REST_HTTP_DELETE
147
+ case 'options':
148
+ return ReferenceType.REST_HTTP_OPTIONS
149
+ case 'head':
150
+ return ReferenceType.REST_HTTP_HEAD
151
+ case 'trace':
152
+ return ReferenceType.REST_HTTP_TRACE
153
+ default:
154
+ return null
155
+ }
156
+ }
157
+
@@ -0,0 +1,18 @@
1
+ import {OpenAPIV3} from "openapi-types";
2
+ import {XDocs} from "./types";
3
+
4
+ export function xDocsLanguages(oasDoc: OpenAPIV3.Document): string[] | null {
5
+ const xDocs = getXDocs(oasDoc);
6
+ if (!xDocs) {
7
+ return null
8
+ }
9
+
10
+ return xDocs?.codeLanguages ?? null
11
+ }
12
+
13
+ export function getXDocs(oasDoc: OpenAPIV3.Document): XDocs | null {
14
+ if (!("x-docs" in oasDoc)) {
15
+ return null
16
+ }
17
+ return oasDoc["x-docs"] as XDocs | null
18
+ }