@mintlify/scraping 4.0.70 → 4.0.72
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/__test__/generateOpenApiPagesForDocsConfig.test.ts +149 -0
- package/__test__/getOpenApiDefinition.test.ts +1 -1
- package/__test__/prepareStringToBeValidFilename.test.ts +1 -1
- package/bin/index.d.ts +1 -0
- package/bin/index.js +1 -0
- package/bin/index.js.map +1 -1
- package/bin/openapi/common.d.ts +26 -0
- package/bin/openapi/common.js +112 -0
- package/bin/openapi/common.js.map +1 -0
- package/bin/openapi/generateOpenApiPages.d.ts +3 -20
- package/bin/openapi/generateOpenApiPages.js +6 -113
- package/bin/openapi/generateOpenApiPages.js.map +1 -1
- package/bin/openapi/generateOpenApiPagesForDocsConfig.d.ts +4 -0
- package/bin/openapi/generateOpenApiPagesForDocsConfig.js +42 -0
- package/bin/openapi/generateOpenApiPagesForDocsConfig.js.map +1 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/index.ts +1 -0
- package/src/openapi/common.ts +168 -0
- package/src/openapi/generateOpenApiPages.ts +27 -158
- package/src/openapi/generateOpenApiPagesForDocsConfig.ts +81 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { OpenAPI } from 'openapi-types';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_API_GROUP_NAME } from '../src/openapi/common.js';
|
|
5
|
+
import { generateOpenApiPagesForDocsConfig } from '../src/openapi/generateOpenApiPagesForDocsConfig.js';
|
|
6
|
+
|
|
7
|
+
describe('generateOpenApiPagesForDocsConfig', () => {
|
|
8
|
+
it('should throw error for empty paths', async () => {
|
|
9
|
+
const emptyDoc: OpenAPI.Document = {
|
|
10
|
+
openapi: '3.0.0',
|
|
11
|
+
info: {
|
|
12
|
+
title: 'Test API',
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
},
|
|
15
|
+
paths: {},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
await expect(generateOpenApiPagesForDocsConfig(emptyDoc)).rejects.toThrow('No paths defined.');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should generate navigation structure for simple API', async () => {
|
|
22
|
+
const simpleDoc: OpenAPI.Document = {
|
|
23
|
+
openapi: '3.0.0',
|
|
24
|
+
info: {
|
|
25
|
+
title: 'Test API',
|
|
26
|
+
version: '1.0.0',
|
|
27
|
+
},
|
|
28
|
+
paths: {
|
|
29
|
+
'/users': {
|
|
30
|
+
get: {
|
|
31
|
+
operationId: 'getUsers',
|
|
32
|
+
summary: 'Get Users',
|
|
33
|
+
responses: {
|
|
34
|
+
'200': {
|
|
35
|
+
description: 'Successful response',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const result = await generateOpenApiPagesForDocsConfig(simpleDoc);
|
|
44
|
+
|
|
45
|
+
// Check nav structure
|
|
46
|
+
expect(result.nav).toHaveLength(1);
|
|
47
|
+
expect(result.nav[0]).toHaveProperty('group', DEFAULT_API_GROUP_NAME);
|
|
48
|
+
expect(result.nav[0]).toHaveProperty('pages');
|
|
49
|
+
|
|
50
|
+
// Check decorated nav structure
|
|
51
|
+
expect(result.decoratedNav).toHaveLength(1);
|
|
52
|
+
expect(result.decoratedNav[0]).toHaveProperty('group', DEFAULT_API_GROUP_NAME);
|
|
53
|
+
expect(result.decoratedNav[0]).toHaveProperty('pages');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should handle custom group names', async () => {
|
|
57
|
+
const docWithTags: OpenAPI.Document = {
|
|
58
|
+
openapi: '3.0.0',
|
|
59
|
+
info: {
|
|
60
|
+
title: 'Test API',
|
|
61
|
+
version: '1.0.0',
|
|
62
|
+
},
|
|
63
|
+
paths: {
|
|
64
|
+
'/users': {
|
|
65
|
+
get: {
|
|
66
|
+
operationId: 'getUsers',
|
|
67
|
+
summary: 'Get Users',
|
|
68
|
+
tags: ['Users'],
|
|
69
|
+
responses: {
|
|
70
|
+
'200': {
|
|
71
|
+
description: 'Successful response',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const result = await generateOpenApiPagesForDocsConfig(docWithTags);
|
|
80
|
+
|
|
81
|
+
// Check that the group name matches the tag
|
|
82
|
+
expect(result.nav).toHaveLength(1);
|
|
83
|
+
expect(result.nav[0]).toHaveProperty('group', 'Users');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should handle multiple paths and methods', async () => {
|
|
87
|
+
const complexDoc: OpenAPI.Document = {
|
|
88
|
+
openapi: '3.0.0',
|
|
89
|
+
info: {
|
|
90
|
+
title: 'Test API',
|
|
91
|
+
version: '1.0.0',
|
|
92
|
+
},
|
|
93
|
+
paths: {
|
|
94
|
+
'/users': {
|
|
95
|
+
get: {
|
|
96
|
+
operationId: 'getUsers',
|
|
97
|
+
summary: 'Get Users',
|
|
98
|
+
tags: ['Users'],
|
|
99
|
+
responses: {
|
|
100
|
+
'200': {
|
|
101
|
+
description: 'Successful response',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
post: {
|
|
106
|
+
operationId: 'createUser',
|
|
107
|
+
summary: 'Create User',
|
|
108
|
+
tags: ['Users'],
|
|
109
|
+
responses: {
|
|
110
|
+
'201': {
|
|
111
|
+
description: 'User created',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
'/products': {
|
|
117
|
+
get: {
|
|
118
|
+
operationId: 'getProducts',
|
|
119
|
+
summary: 'Get Products',
|
|
120
|
+
tags: ['Products'],
|
|
121
|
+
responses: {
|
|
122
|
+
'200': {
|
|
123
|
+
description: 'Successful response',
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const result = await generateOpenApiPagesForDocsConfig(complexDoc);
|
|
132
|
+
|
|
133
|
+
// Should have two groups (Users and Products)
|
|
134
|
+
expect(result.nav).toHaveLength(2);
|
|
135
|
+
|
|
136
|
+
// Check that pages were generated for all operations
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
|
+
const allPages = result.nav.flatMap((group) => (group as any).pages);
|
|
139
|
+
expect(allPages).toHaveLength(3); // getUsers, createUser, getProducts
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should handle URL input', async () => {
|
|
143
|
+
const validUrl = new URL('https://api.example.com/openapi.json');
|
|
144
|
+
|
|
145
|
+
// Mock fetch implementation would be needed for this test
|
|
146
|
+
// This is just to show the structure
|
|
147
|
+
await expect(generateOpenApiPagesForDocsConfig(validUrl)).rejects.toThrow();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -3,7 +3,7 @@ import yaml from 'js-yaml';
|
|
|
3
3
|
import { OpenAPI } from 'openapi-types';
|
|
4
4
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
5
5
|
|
|
6
|
-
import { getOpenApiDefinition } from '../src/openapi/
|
|
6
|
+
import { getOpenApiDefinition } from '../src/openapi/common.js';
|
|
7
7
|
|
|
8
8
|
vi.mock('fs/promises');
|
|
9
9
|
vi.mock('node-fetch');
|
package/bin/index.d.ts
CHANGED
package/bin/index.js
CHANGED
package/bin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DecoratedNavigationPage, NavigationEntry } from '@mintlify/models';
|
|
2
|
+
import { OpenAPI, OpenAPIV3 } from 'openapi-types';
|
|
3
|
+
export declare const getOpenApiDefinition: (pathOrDocumentOrUrl: string | OpenAPI.Document | URL) => Promise<{
|
|
4
|
+
document: OpenAPI.Document;
|
|
5
|
+
isUrl: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const generateUniqueFilenameWithoutExtension: (pages: NavigationEntry[], base: string) => string;
|
|
8
|
+
export declare const createOpenApiFrontmatter: (filename: string, openApiMetaTag: string, version?: string) => Promise<void>;
|
|
9
|
+
export declare const prepareStringToBeValidFilename: (str?: string) => string | undefined;
|
|
10
|
+
export type GenerateOpenApiPagesOptions = {
|
|
11
|
+
openApiFilePath?: string;
|
|
12
|
+
version?: string;
|
|
13
|
+
writeFiles?: boolean;
|
|
14
|
+
outDir?: string;
|
|
15
|
+
outDirBasePath?: string;
|
|
16
|
+
overwrite?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type OpenApiPageGenerationResult<N, DN> = {
|
|
19
|
+
nav: N;
|
|
20
|
+
decoratedNav: DN;
|
|
21
|
+
spec: OpenAPI.Document;
|
|
22
|
+
pagesAcc: Record<string, DecoratedNavigationPage>;
|
|
23
|
+
isUrl: boolean;
|
|
24
|
+
};
|
|
25
|
+
export declare function processOpenApiPath<N, DN>(path: string, pathItemObject: OpenAPIV3.PathItemObject, schema: OpenAPI.Document, nav: N, decoratedNav: DN, writePromises: Promise<void>[], pagesAcc: Record<string, DecoratedNavigationPage>, options: GenerateOpenApiPagesOptions, findNavGroup: (nav: any, groupName?: string) => any): void;
|
|
26
|
+
export declare const DEFAULT_API_GROUP_NAME = "API Reference";
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { getOpenApiTitleAndDescription, optionallyAddLeadingSlash, slugToTitle, } from '@mintlify/common';
|
|
2
|
+
import { outputFile } from 'fs-extra';
|
|
3
|
+
import fse from 'fs-extra';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import yaml from 'js-yaml';
|
|
6
|
+
import { OpenAPIV3 } from 'openapi-types';
|
|
7
|
+
import path, { join, parse, resolve } from 'path';
|
|
8
|
+
import { fetchOpenApi } from '../utils/network.js';
|
|
9
|
+
export const getOpenApiDefinition = async (pathOrDocumentOrUrl) => {
|
|
10
|
+
if (typeof pathOrDocumentOrUrl === 'string') {
|
|
11
|
+
if (pathOrDocumentOrUrl.startsWith('http://')) {
|
|
12
|
+
// This is an invalid location either for a file or a URL
|
|
13
|
+
throw new Error('Only HTTPS URLs are supported. Please provide an HTTPS URL');
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
try {
|
|
17
|
+
const url = new URL(pathOrDocumentOrUrl);
|
|
18
|
+
pathOrDocumentOrUrl = url;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
const pathname = path.join(process.cwd(), pathOrDocumentOrUrl.toString());
|
|
22
|
+
const file = await fs.readFile(pathname, 'utf-8');
|
|
23
|
+
pathOrDocumentOrUrl = yaml.load(file);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const isUrl = pathOrDocumentOrUrl instanceof URL;
|
|
28
|
+
if (pathOrDocumentOrUrl instanceof URL) {
|
|
29
|
+
if (pathOrDocumentOrUrl.protocol !== 'https:') {
|
|
30
|
+
throw new Error('Only HTTPS URLs are supported. Please provide an HTTPS URL');
|
|
31
|
+
}
|
|
32
|
+
pathOrDocumentOrUrl = await fetchOpenApi(pathOrDocumentOrUrl);
|
|
33
|
+
}
|
|
34
|
+
return { document: pathOrDocumentOrUrl, isUrl };
|
|
35
|
+
};
|
|
36
|
+
// returns a filename that is unique within the given array of pages
|
|
37
|
+
export const generateUniqueFilenameWithoutExtension = (pages, base) => {
|
|
38
|
+
let filename = base;
|
|
39
|
+
if (pages.includes(filename)) {
|
|
40
|
+
let extension = 1;
|
|
41
|
+
filename = `${base}-${extension}`;
|
|
42
|
+
while (pages.includes(filename)) {
|
|
43
|
+
extension += 1;
|
|
44
|
+
filename = `${base}-${extension}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return filename;
|
|
48
|
+
};
|
|
49
|
+
export const createOpenApiFrontmatter = async (filename, openApiMetaTag, version) => {
|
|
50
|
+
const data = `---
|
|
51
|
+
openapi: ${openApiMetaTag}${version ? `\nversion: ${version}` : ''}
|
|
52
|
+
---`;
|
|
53
|
+
await outputFile(filename, data);
|
|
54
|
+
};
|
|
55
|
+
export const prepareStringToBeValidFilename = (str) => str
|
|
56
|
+
? str
|
|
57
|
+
.replaceAll(' ', '-')
|
|
58
|
+
.replace(/\{.*?\}/g, '-') // remove path parameters
|
|
59
|
+
.replace(/^-/, '')
|
|
60
|
+
.replace(/-$/, '')
|
|
61
|
+
.replace(/[{}(),.'\n\/]/g, '') // remove special characters
|
|
62
|
+
.replaceAll(/--/g, '-') // replace double hyphens
|
|
63
|
+
.toLowerCase()
|
|
64
|
+
: undefined;
|
|
65
|
+
export function processOpenApiPath(path, pathItemObject, schema, nav, decoratedNav, writePromises, pagesAcc, options,
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
findNavGroup) {
|
|
68
|
+
const openApiFilePathFromRoot = options.openApiFilePath
|
|
69
|
+
? optionallyAddLeadingSlash(options.openApiFilePath)
|
|
70
|
+
: undefined;
|
|
71
|
+
Object.values(OpenAPIV3.HttpMethods).forEach((method) => {
|
|
72
|
+
if (method in pathItemObject) {
|
|
73
|
+
const operation = pathItemObject[method];
|
|
74
|
+
const groupName = operation?.tags?.[0];
|
|
75
|
+
const title = prepareStringToBeValidFilename(operation?.summary) ??
|
|
76
|
+
`${method}-${prepareStringToBeValidFilename(path)}`;
|
|
77
|
+
const folder = prepareStringToBeValidFilename(groupName) ?? '';
|
|
78
|
+
const base = join(options.outDir ?? '', folder, title);
|
|
79
|
+
const navGroup = findNavGroup(nav, groupName);
|
|
80
|
+
const decoratedNavGroup = findNavGroup(decoratedNav, groupName);
|
|
81
|
+
const filenameWithoutExtension = generateUniqueFilenameWithoutExtension(navGroup, base);
|
|
82
|
+
const openapiMetaTag = `${openApiFilePathFromRoot ? `${openApiFilePathFromRoot} ` : ''}${method} ${path}`;
|
|
83
|
+
const { title: titleTag, description } = getOpenApiTitleAndDescription([
|
|
84
|
+
{
|
|
85
|
+
filename: options.openApiFilePath
|
|
86
|
+
? parse(options.openApiFilePath).name
|
|
87
|
+
: 'filler-filename',
|
|
88
|
+
spec: schema,
|
|
89
|
+
originalFileLocation: options.openApiFilePath,
|
|
90
|
+
},
|
|
91
|
+
], openapiMetaTag);
|
|
92
|
+
navGroup.push(filenameWithoutExtension);
|
|
93
|
+
const page = {
|
|
94
|
+
openapi: openapiMetaTag,
|
|
95
|
+
href: resolve('/', filenameWithoutExtension),
|
|
96
|
+
title: titleTag ?? slugToTitle(filenameWithoutExtension),
|
|
97
|
+
description,
|
|
98
|
+
version: options.version,
|
|
99
|
+
};
|
|
100
|
+
decoratedNavGroup.push(page);
|
|
101
|
+
pagesAcc[filenameWithoutExtension] = page;
|
|
102
|
+
const targetPath = options.outDirBasePath
|
|
103
|
+
? join(options.outDirBasePath, `${filenameWithoutExtension}.mdx`)
|
|
104
|
+
: `${filenameWithoutExtension}.mdx`;
|
|
105
|
+
if (options.writeFiles && (!fse.pathExistsSync(targetPath) || options.overwrite)) {
|
|
106
|
+
writePromises.push(createOpenApiFrontmatter(targetPath, openapiMetaTag, options.version));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export const DEFAULT_API_GROUP_NAME = 'API Reference';
|
|
112
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/openapi/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
import type { DecoratedNavigation, Navigation
|
|
1
|
+
import type { DecoratedNavigation, Navigation } from '@mintlify/models';
|
|
2
2
|
import { OpenAPI } from 'openapi-types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
isUrl: boolean;
|
|
6
|
-
}>;
|
|
7
|
-
export declare const generateOpenApiPages: (pathOrDocumentOrUrl: string | OpenAPI.Document | URL, opts?: {
|
|
8
|
-
openApiFilePath?: string | undefined;
|
|
9
|
-
version?: string | undefined;
|
|
10
|
-
writeFiles?: boolean;
|
|
11
|
-
outDir?: string;
|
|
12
|
-
outDirBasePath?: string;
|
|
13
|
-
overwrite?: boolean;
|
|
14
|
-
}) => Promise<{
|
|
15
|
-
nav: Navigation;
|
|
16
|
-
decoratedNav: DecoratedNavigation;
|
|
17
|
-
spec: OpenAPI.Document;
|
|
18
|
-
pagesAcc: Record<string, DecoratedNavigationPage>;
|
|
19
|
-
isUrl: boolean;
|
|
20
|
-
}>;
|
|
21
|
-
export declare const prepareStringToBeValidFilename: (str?: string) => string | undefined;
|
|
3
|
+
import { GenerateOpenApiPagesOptions, OpenApiPageGenerationResult } from './common.js';
|
|
4
|
+
export declare function generateOpenApiPages(pathOrDocumentOrUrl: string | OpenAPI.Document | URL, opts?: GenerateOpenApiPagesOptions): Promise<OpenApiPageGenerationResult<Navigation, DecoratedNavigation>>;
|
|
@@ -1,43 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import yaml from 'js-yaml';
|
|
5
|
-
import { OpenAPIV3 } from 'openapi-types';
|
|
6
|
-
import { join, resolve, parse } from 'path';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { fetchOpenApi } from '../utils/network.js';
|
|
9
|
-
export const getOpenApiDefinition = async (pathOrDocumentOrUrl) => {
|
|
10
|
-
if (typeof pathOrDocumentOrUrl === 'string') {
|
|
11
|
-
if (pathOrDocumentOrUrl.startsWith('http://')) {
|
|
12
|
-
// This is an invalid location either for a file or a URL
|
|
13
|
-
throw new Error('Only HTTPS URLs are supported. Please provide an HTTPS URL');
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
try {
|
|
17
|
-
const url = new URL(pathOrDocumentOrUrl);
|
|
18
|
-
pathOrDocumentOrUrl = url;
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
const pathname = path.join(process.cwd(), pathOrDocumentOrUrl.toString());
|
|
22
|
-
const file = await fs.readFile(pathname, 'utf-8');
|
|
23
|
-
pathOrDocumentOrUrl = yaml.load(file);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const isUrl = pathOrDocumentOrUrl instanceof URL;
|
|
28
|
-
if (pathOrDocumentOrUrl instanceof URL) {
|
|
29
|
-
if (pathOrDocumentOrUrl.protocol !== 'https:') {
|
|
30
|
-
throw new Error('Only HTTPS URLs are supported. Please provide an HTTPS URL');
|
|
31
|
-
}
|
|
32
|
-
pathOrDocumentOrUrl = await fetchOpenApi(pathOrDocumentOrUrl);
|
|
33
|
-
}
|
|
34
|
-
return { document: pathOrDocumentOrUrl, isUrl };
|
|
35
|
-
};
|
|
36
|
-
export const generateOpenApiPages = async (pathOrDocumentOrUrl, opts) => {
|
|
37
|
-
const { openApiFilePath, version, writeFiles, outDir, outDirBasePath } = opts ?? {};
|
|
38
|
-
const openApiFilePathFromRoot = openApiFilePath
|
|
39
|
-
? optionallyAddLeadingSlash(openApiFilePath)
|
|
40
|
-
: undefined;
|
|
1
|
+
import { validate } from '@mintlify/common';
|
|
2
|
+
import { getOpenApiDefinition, processOpenApiPath, DEFAULT_API_GROUP_NAME, } from './common.js';
|
|
3
|
+
export async function generateOpenApiPages(pathOrDocumentOrUrl, opts) {
|
|
41
4
|
const { document, isUrl } = await getOpenApiDefinition(pathOrDocumentOrUrl);
|
|
42
5
|
const { schema } = await validate(document);
|
|
43
6
|
if (schema?.paths === undefined || Object.keys(schema.paths).length === 0) {
|
|
@@ -51,44 +14,7 @@ export const generateOpenApiPages = async (pathOrDocumentOrUrl, opts) => {
|
|
|
51
14
|
if (!pathItemObject || typeof pathItemObject !== 'object') {
|
|
52
15
|
return;
|
|
53
16
|
}
|
|
54
|
-
|
|
55
|
-
Object.values(OpenAPIV3.HttpMethods).forEach((method) => {
|
|
56
|
-
if (method in typedPathItemObject) {
|
|
57
|
-
const operation = typedPathItemObject[method];
|
|
58
|
-
const groupName = operation?.tags?.[0];
|
|
59
|
-
const title = prepareStringToBeValidFilename(operation?.summary) ??
|
|
60
|
-
`${method}-${prepareStringToBeValidFilename(path)}`;
|
|
61
|
-
const folder = prepareStringToBeValidFilename(groupName) ?? '';
|
|
62
|
-
const base = join(outDir ?? '', folder, title);
|
|
63
|
-
const navGroup = findNavGroup(nav, groupName);
|
|
64
|
-
const decoratedNavGroup = findNavGroup(decoratedNav, groupName);
|
|
65
|
-
const filenameWithoutExtension = generateUniqueFilenameWithoutExtension(navGroup, base);
|
|
66
|
-
const openapiMetaTag = `${openApiFilePathFromRoot ? `${openApiFilePathFromRoot} ` : ''}${method} ${path}`;
|
|
67
|
-
const { title: titleTag, description } = getOpenApiTitleAndDescription([
|
|
68
|
-
{
|
|
69
|
-
filename: openApiFilePath ? parse(openApiFilePath).name : 'filler-filename',
|
|
70
|
-
spec: schema,
|
|
71
|
-
originalFileLocation: openApiFilePath,
|
|
72
|
-
},
|
|
73
|
-
], openapiMetaTag);
|
|
74
|
-
navGroup.push(filenameWithoutExtension);
|
|
75
|
-
const page = {
|
|
76
|
-
openapi: openapiMetaTag,
|
|
77
|
-
href: resolve('/', filenameWithoutExtension),
|
|
78
|
-
title: titleTag ?? slugToTitle(filenameWithoutExtension),
|
|
79
|
-
description,
|
|
80
|
-
version,
|
|
81
|
-
};
|
|
82
|
-
decoratedNavGroup.push(page);
|
|
83
|
-
pagesAcc[filenameWithoutExtension] = page;
|
|
84
|
-
const targetPath = outDirBasePath
|
|
85
|
-
? join(outDirBasePath, `${filenameWithoutExtension}.mdx`)
|
|
86
|
-
: `${filenameWithoutExtension}.mdx`;
|
|
87
|
-
if (writeFiles && (!fse.pathExistsSync(targetPath) || opts?.overwrite)) {
|
|
88
|
-
writePromises.push(createOpenApiFrontmatter(targetPath, openapiMetaTag, version));
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
17
|
+
processOpenApiPath(path, pathItemObject, schema, nav, decoratedNav, writePromises, pagesAcc, opts ?? {}, findNavGroup);
|
|
92
18
|
});
|
|
93
19
|
await Promise.all(writePromises);
|
|
94
20
|
return {
|
|
@@ -98,12 +24,8 @@ export const generateOpenApiPages = async (pathOrDocumentOrUrl, opts) => {
|
|
|
98
24
|
pagesAcc,
|
|
99
25
|
isUrl,
|
|
100
26
|
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const findNavGroup = (nav, groupName) => {
|
|
104
|
-
if (groupName === undefined) {
|
|
105
|
-
groupName = 'API Reference';
|
|
106
|
-
}
|
|
27
|
+
}
|
|
28
|
+
const findNavGroup = (nav, groupName = DEFAULT_API_GROUP_NAME) => {
|
|
107
29
|
const group = nav.find((fileOrGroup) => typeof fileOrGroup === 'object' && 'group' in fileOrGroup && fileOrGroup.group === groupName);
|
|
108
30
|
if (group === undefined) {
|
|
109
31
|
const newGroup = {
|
|
@@ -117,33 +39,4 @@ const findNavGroup = (nav, groupName) => {
|
|
|
117
39
|
return group.pages;
|
|
118
40
|
}
|
|
119
41
|
};
|
|
120
|
-
// returns a filename that is unique within the given array of pages
|
|
121
|
-
const generateUniqueFilenameWithoutExtension = (pages, base) => {
|
|
122
|
-
let filename = base;
|
|
123
|
-
if (pages.includes(filename)) {
|
|
124
|
-
let extension = 1;
|
|
125
|
-
filename = `${base}-${extension}`;
|
|
126
|
-
while (pages.includes(filename)) {
|
|
127
|
-
extension += 1;
|
|
128
|
-
filename = `${base}-${extension}`;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return filename;
|
|
132
|
-
};
|
|
133
|
-
const createOpenApiFrontmatter = async (filename, openApiMetaTag, version) => {
|
|
134
|
-
const data = `---
|
|
135
|
-
openapi: ${openApiMetaTag}${version ? `\nversion: ${version}` : ''}
|
|
136
|
-
---`;
|
|
137
|
-
await outputFile(filename, data);
|
|
138
|
-
};
|
|
139
|
-
export const prepareStringToBeValidFilename = (str) => str
|
|
140
|
-
? str
|
|
141
|
-
.replaceAll(' ', '-')
|
|
142
|
-
.replace(/\{.*?\}/g, '-') // remove path parameters
|
|
143
|
-
.replace(/^-/, '')
|
|
144
|
-
.replace(/-$/, '')
|
|
145
|
-
.replace(/[{}(),.'\n\/]/g, '') // remove special characters
|
|
146
|
-
.replaceAll(/--/g, '-') // replace double hyphens
|
|
147
|
-
.toLowerCase()
|
|
148
|
-
: undefined;
|
|
149
42
|
//# sourceMappingURL=generateOpenApiPages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateOpenApiPages.js","sourceRoot":"","sources":["../../src/openapi/generateOpenApiPages.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"generateOpenApiPages.js","sourceRoot":"","sources":["../../src/openapi/generateOpenApiPages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAU5C,OAAO,EACL,oBAAoB,EAGpB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,mBAAoD,EACpD,IAAkC;IAElC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,MAAM,oBAAoB,CAAC,mBAAmB,CAAC,CAAC;IAC5E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,MAAM,EAAE,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,MAAM,YAAY,GAAwB,EAAE,CAAC;IAC7C,MAAM,aAAa,GAAoB,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAA4C,EAAE,CAAC;IAE7D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;QAC9D,IAAI,CAAC,cAAc,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;YAC1D,OAAO;QACT,CAAC;QACD,kBAAkB,CAChB,IAAI,EACJ,cAAc,EACd,MAA0B,EAC1B,GAAG,EACH,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,IAAI,IAAI,EAAE,EACV,YAAY,CACb,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAEjC,OAAO;QACL,GAAG;QACH,YAAY;QACZ,IAAI,EAAE,MAA0B;QAChC,QAAQ;QACR,KAAK;KACN,CAAC;AACJ,CAAC;AACD,MAAM,YAAY,GAAG,CACnB,GAAyB,EACzB,YAAoB,sBAAsB,EACpB,EAAE;IACxB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CACpB,CAAC,WAAW,EAAE,EAAE,CACd,OAAO,WAAW,KAAK,QAAQ,IAAI,OAAO,IAAI,WAAW,IAAI,WAAW,CAAC,KAAK,KAAK,SAAS,CAC9E,CAAC;IACnB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG;YACf,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,EAAE;SACV,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnB,OAAO,QAAQ,CAAC,KAAK,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DecoratedGroupsConfig, GroupsConfig } from '@mintlify/validation';
|
|
2
|
+
import { OpenAPI } from 'openapi-types';
|
|
3
|
+
import { GenerateOpenApiPagesOptions, OpenApiPageGenerationResult } from './common.js';
|
|
4
|
+
export declare function generateOpenApiPagesForDocsConfig(pathOrDocumentOrUrl: string | OpenAPI.Document | URL, opts?: GenerateOpenApiPagesOptions): Promise<OpenApiPageGenerationResult<GroupsConfig, DecoratedGroupsConfig>>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { validate } from '@mintlify/common';
|
|
2
|
+
import { getOpenApiDefinition, processOpenApiPath, DEFAULT_API_GROUP_NAME, } from './common.js';
|
|
3
|
+
export async function generateOpenApiPagesForDocsConfig(pathOrDocumentOrUrl, opts) {
|
|
4
|
+
const { document, isUrl } = await getOpenApiDefinition(pathOrDocumentOrUrl);
|
|
5
|
+
const { schema } = await validate(document);
|
|
6
|
+
if (schema?.paths === undefined || Object.keys(schema.paths).length === 0) {
|
|
7
|
+
throw new Error('No paths defined.');
|
|
8
|
+
}
|
|
9
|
+
const nav = [];
|
|
10
|
+
const decoratedNav = [];
|
|
11
|
+
const writePromises = [];
|
|
12
|
+
const pagesAcc = {};
|
|
13
|
+
Object.entries(schema.paths).forEach(([path, pathItemObject]) => {
|
|
14
|
+
if (!pathItemObject || typeof pathItemObject !== 'object') {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
processOpenApiPath(path, pathItemObject, schema, nav, decoratedNav, writePromises, pagesAcc, opts ?? {}, findNavGroup);
|
|
18
|
+
});
|
|
19
|
+
await Promise.all(writePromises);
|
|
20
|
+
return {
|
|
21
|
+
nav,
|
|
22
|
+
decoratedNav,
|
|
23
|
+
spec: schema,
|
|
24
|
+
pagesAcc,
|
|
25
|
+
isUrl,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const findNavGroup = (nav, groupName = DEFAULT_API_GROUP_NAME) => {
|
|
29
|
+
const group = nav.find((fileOrGroup) => typeof fileOrGroup === 'object' && 'group' in fileOrGroup && fileOrGroup.group === groupName);
|
|
30
|
+
if (group === undefined || !('pages' in group)) {
|
|
31
|
+
const newGroup = {
|
|
32
|
+
group: groupName,
|
|
33
|
+
pages: [],
|
|
34
|
+
};
|
|
35
|
+
nav.push(newGroup);
|
|
36
|
+
return newGroup.pages;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return group.pages;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=generateOpenApiPagesForDocsConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateOpenApiPagesForDocsConfig.js","sourceRoot":"","sources":["../../src/openapi/generateOpenApiPagesForDocsConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAU5C,OAAO,EACL,oBAAoB,EAGpB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,mBAAoD,EACpD,IAAkC;IAElC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,MAAM,oBAAoB,CAAC,mBAAmB,CAAC,CAAC;IAC5E,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,MAAM,EAAE,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,MAAM,YAAY,GAA0B,EAAE,CAAC;IAC/C,MAAM,aAAa,GAAoB,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAA4C,EAAE,CAAC;IAE7D,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,EAAE;QAC9D,IAAI,CAAC,cAAc,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;YAC1D,OAAO;QACT,CAAC;QACD,kBAAkB,CAChB,IAAI,EACJ,cAAc,EACd,MAA0B,EAC1B,GAAG,EACH,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,IAAI,IAAI,EAAE,EACV,YAAY,CACb,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAEjC,OAAO;QACL,GAAG;QACH,YAAY;QACZ,IAAI,EAAE,MAA0B;QAChC,QAAQ;QACR,KAAK;KACN,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG,CACnB,GAAyC,EACzC,YAAoB,sBAAsB,EACN,EAAE;IACtC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CACpB,CAAC,WAAW,EAAE,EAAE,CACd,OAAO,WAAW,KAAK,QAAQ,IAAI,OAAO,IAAI,WAAW,IAAI,WAAW,CAAC,KAAK,KAAK,SAAS,CAC/F,CAAC;IACF,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG;YACf,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,EAAE;SACV,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnB,OAAO,QAAQ,CAAC,KAAK,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;AACH,CAAC,CAAC"}
|