@xyd-js/openapi 0.1.0-xyd.6 → 0.1.0-xyd.64

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 (51) hide show
  1. package/CHANGELOG.md +518 -0
  2. package/LICENSE +21 -0
  3. package/__fixtures__/-2.complex.openai/input.yaml +39848 -0
  4. package/__fixtures__/-2.complex.openai/output.json +321646 -0
  5. package/__fixtures__/-2.complex.openai/pluginOasOpenai.ts +553 -0
  6. package/__fixtures__/1.basic/input.yaml +226 -0
  7. package/__fixtures__/1.basic/output.json +1919 -0
  8. package/__fixtures__/2.more/input.yaml +76 -0
  9. package/__fixtures__/2.more/output.json +292 -0
  10. package/__fixtures__/3.multiple-responses/input.yaml +48 -0
  11. package/__fixtures__/3.multiple-responses/output.json +266 -0
  12. package/__fixtures__/4.abc/input.yaml +639 -0
  13. package/__fixtures__/4.abc/output.json +3828 -0
  14. package/__fixtures__/5.xdocs.codeLanguages/input.yaml +231 -0
  15. package/__fixtures__/5.xdocs.codeLanguages/output.json +1879 -0
  16. package/__fixtures__/5.xdocs.sidebar/input.yaml +256 -0
  17. package/__fixtures__/5.xdocs.sidebar/output.json +843 -0
  18. package/__fixtures__/6.codeSamples/input.yaml +75 -0
  19. package/__fixtures__/6.codeSamples/output.json +293 -0
  20. package/__tests__/oapSchemaToReferences.test.ts +88 -0
  21. package/__tests__/utils.ts +81 -0
  22. package/dist/index.cjs +1860 -163
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +36 -4
  25. package/dist/index.d.ts +36 -4
  26. package/dist/index.js +1856 -156
  27. package/dist/index.js.map +1 -1
  28. package/examples/basic/index2.ts +2 -2
  29. package/index.ts +10 -2
  30. package/package.json +11 -7
  31. package/src/const.ts +5 -1
  32. package/src/converters/oas-componentSchemas.ts +205 -0
  33. package/src/converters/oas-examples.ts +417 -0
  34. package/src/{parameters.ts → converters/oas-parameters.ts} +17 -3
  35. package/src/converters/oas-paths.ts +354 -0
  36. package/src/{requestBody.ts → converters/oas-requestBody.ts} +30 -10
  37. package/src/converters/oas-responses.ts +76 -0
  38. package/src/converters/oas-schema.ts +141 -0
  39. package/src/index.ts +13 -5
  40. package/src/oas-core.ts +579 -0
  41. package/src/types.ts +18 -0
  42. package/src/utils.ts +103 -89
  43. package/src/xdocs/index.ts +18 -0
  44. package/src/xdocs/pluginSidebar.ts +580 -0
  45. package/src/xdocs/types.ts +26 -0
  46. package/vitest.config.ts +7 -0
  47. package/src/examples.ts +0 -116
  48. package/src/paths.ts +0 -103
  49. package/src/properties.ts +0 -37
  50. package/src/responses.ts +0 -38
  51. package/src/schema.ts +0 -62
package/src/utils.ts CHANGED
@@ -1,28 +1,108 @@
1
1
  import path from "path";
2
- import fs from "fs";
2
+ import fs from "fs/promises";
3
+
3
4
  import yaml from "js-yaml";
4
- import $refParser from "json-schema-ref-parser";
5
- import {OpenAPIV3} from "openapi-types";
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 options: ParserOptions = {
29
+ dereference: {
30
+ onDereference(path: any, value: any, parent: any) {
31
+ if (value && typeof value === 'object') {
32
+ value.__UNSAFE_refPath = () => path
33
+ }
34
+ if (parent && typeof parent === 'object') {
35
+ parent.__UNSAFE_refPath = () => path
36
+ }
37
+ }
38
+ }
39
+ } as ParserOptions;
6
40
 
7
- import {ReferenceType} from "@xyd-js/uniform";
41
+ if (remoteOasPath) {
42
+ if (!options.resolve) {
43
+ options.resolve = {}
44
+ }
8
45
 
9
- type Parameters = {
10
- query?: Record<string, string | number | boolean>;
11
- headers?: Record<string, string>;
12
- };
46
+ options.resolve.file = {
47
+ read: async (file: any) => {
48
+ // 1) Convert absolute local path back into a repo-relative path:
49
+ // "/Users/.../docs/foo.md" → "docs/foo.md"
50
+ let rel = path.relative(cwd, file.url);
51
+ rel = rel.split(path.sep).join('/');
52
+
53
+ // 2) Resolve against your GitHub raw URL:
54
+ const absoluteUrl = new URL(rel, openApiPath).href;
55
+ // → "https://raw.githubusercontent.com/.../docs/foo.md"
56
+
57
+ // 3) Fetch it:
58
+ const res = await fetch(absoluteUrl);
59
+ if (!res.ok) {
60
+ throw new Error(`Failed to fetch ${absoluteUrl}: ${res.status}`);
61
+ }
62
+
63
+ let content;
64
+ if (file.extension === '.json' || file.extension === '.yaml' || file.extension === '.yml') {
65
+ // If the file is JSON or YAML, return the parsed content
66
+ if (file.extension === '.json') {
67
+ content = await res.json();
68
+ } else {
69
+ content = yaml.load(await res.text());
70
+ }
71
+ } else {
72
+ content = await res.text(); // hand back the Markdown
73
+ }
74
+
75
+ return content;
76
+ }
77
+ }
78
+ }
13
79
 
14
- export function toPascalCase(str: string): string {
15
- return str
16
- .split(/[\s_-]+/)
17
- .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
18
- .join('');
80
+ await $refParser.dereference(openApiSpec, options);
81
+
82
+ return openApiSpec as OpenAPIV3.Document
19
83
  }
20
84
 
21
- // readOpenApiSpec reads an OpenAPI spec file and returns the content
22
- function readOpenApiSpec(filePath: string) {
23
- const ext = path.extname(filePath).toLowerCase();
24
- const content = fs.readFileSync(filePath, 'utf-8');
85
+ // readOpenApiSpec reads an OpenAPI spec file or URL and returns the content
86
+ async function readOpenApiSpec(filePath: string) {
87
+ let content: string;
25
88
 
89
+ if (filePath.startsWith('http://') || filePath.startsWith('https://')) {
90
+ const response = await fetch(filePath);
91
+ if (!response.ok) {
92
+ throw new Error(`Failed to fetch OpenAPI spec from URL: ${response.statusText}`);
93
+ }
94
+ content = await response.text();
95
+ } else {
96
+ try {
97
+ await fs.access(filePath);
98
+ } catch (error) {
99
+ console.log(`⚠️ "${filePath}" is defined in the docs.json navigation but the file does not exist.`)
100
+ return
101
+ }
102
+ content = await fs.readFile(filePath, 'utf-8');
103
+ }
104
+
105
+ const ext = path.extname(filePath).toLowerCase();
26
106
  if (ext === '.yaml' || ext === '.yml') {
27
107
  return yaml.load(content);
28
108
  } else if (ext === '.json') {
@@ -32,17 +112,6 @@ function readOpenApiSpec(filePath: string) {
32
112
  }
33
113
  }
34
114
 
35
- // deferencedOpenAPI reads an OpenAPI spec file and returns a dereferenced OpenAPIV3.Document
36
- // dereferenced means that all $ref references are resolved automatically
37
- export async function deferencedOpenAPI(openApiPath: string) {
38
- const openApiSpec = readOpenApiSpec(openApiPath);
39
-
40
- //@ts-ignore TODO: fix ts
41
- await $refParser.dereference(openApiSpec);
42
-
43
- return openApiSpec as OpenAPIV3.Document
44
- }
45
-
46
115
  // httpMethodToUniformMethod converts an HTTP method to a uniform ReferenceType
47
116
  export function httpMethodToUniformMethod(method: string): ReferenceType | null {
48
117
  switch (method) {
@@ -56,69 +125,14 @@ export function httpMethodToUniformMethod(method: string): ReferenceType | null
56
125
  return ReferenceType.REST_HTTP_POST
57
126
  case 'delete':
58
127
  return ReferenceType.REST_HTTP_DELETE
59
- // case 'options':
60
- // return ReferenceType.REST_HTTP_OPTIONS
61
- // case 'head':
62
- // return ReferenceType.REST_HTTP_HEAD
63
- // case 'trace':
64
- // return ReferenceType.REST_HTTP_TRACE
128
+ case 'options':
129
+ return ReferenceType.REST_HTTP_OPTIONS
130
+ case 'head':
131
+ return ReferenceType.REST_HTTP_HEAD
132
+ case 'trace':
133
+ return ReferenceType.REST_HTTP_TRACE
65
134
  default:
66
135
  return null
67
136
  }
68
137
  }
69
138
 
70
- // schemaToRequestBody generates a request body from an OpenAPI schema
71
- function schemaToRequestBody(schema: OpenAPIV3.SchemaObject): string {
72
- const requestBody: any = {};
73
-
74
- if (schema.type === 'object' && schema.properties) {
75
- for (const [key, value] of Object.entries(schema.properties)) {
76
- if ((value as OpenAPIV3.SchemaObject).default !== undefined) {
77
- requestBody[key] = (value as OpenAPIV3.SchemaObject).default;
78
- } else {
79
- requestBody[key] = null; // or some placeholder value
80
- }
81
- }
82
- }
83
-
84
- return JSON.stringify(requestBody);
85
- }
86
-
87
- // generateRequestInitFromOpenAPIObject generates a RequestInit object from an OpenAPI object
88
- export function generateRequestInitFromOapOperation(
89
- urlPath: string,
90
- operation: OpenAPIV3.OperationObject
91
- ): { url: string, reqInit: RequestInit } {
92
- const reqInit: RequestInit = {}
93
- let queryParams = '';
94
-
95
- if (operation.parameters) {
96
- const parameters = operation.parameters as OpenAPIV3.ParameterObject[]
97
-
98
- const params = new URLSearchParams(
99
- Object.entries(parameters).map(([key, value]) => [key, String(value)])
100
- ).toString();
101
-
102
- queryParams += `?${params}`;
103
- }
104
-
105
- if (operation.requestBody) {
106
- const reqBody = operation.requestBody as OpenAPIV3.RequestBodyObject;
107
- const contentType = Object.keys(reqBody.content || {})[0];
108
-
109
- if (contentType === "application/json") {
110
- const schema = reqBody.content['application/json'].schema as OpenAPIV3.SchemaObject
111
-
112
- reqInit.body = schemaToRequestBody(schema);
113
- reqInit.headers = {
114
- 'Content-Type': 'application/json',
115
- }
116
- }
117
- }
118
-
119
- return {
120
- url: `${urlPath}${queryParams}`,
121
- reqInit,
122
- };
123
- }
124
-
@@ -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
+ }