@mintlify/prebuild 1.0.1186 → 1.0.1188

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.
@@ -6,6 +6,7 @@ export declare const generateAsyncApiFromDocsConfig: (navigation: NavigationConf
6
6
  writeFiles: boolean;
7
7
  targetDir?: string;
8
8
  localSchema?: boolean;
9
+ writeFile?: (filename: string, content: string) => void | Promise<void>;
9
10
  }) => Promise<{
10
11
  newNav: NavigationConfig;
11
12
  newAsyncApiFiles: AsyncAPIFile[];
@@ -4,7 +4,7 @@ import { divisions } from '@mintlify/validation';
4
4
  import * as path from 'path';
5
5
  const DEFAULT_OUTPUT_DIR = 'api-reference';
6
6
  export const generateAsyncApiFromDocsConfig = async (navigation, asyncApiFiles, pagesAcc, opts) => {
7
- const { overwrite, writeFiles, targetDir, localSchema } = opts;
7
+ const { overwrite, writeFiles, targetDir, localSchema, writeFile } = opts;
8
8
  const newAsyncApiFiles = [];
9
9
  async function processAsyncApiInNav(nav) {
10
10
  let outputDir = DEFAULT_OUTPUT_DIR;
@@ -52,6 +52,7 @@ export const generateAsyncApiFromDocsConfig = async (navigation, asyncApiFiles,
52
52
  outDirBasePath: path.join(targetDir ?? '', 'src', '_props'),
53
53
  overwrite,
54
54
  localSchema,
55
+ writeFile,
55
56
  });
56
57
  Object.entries(pagesAccFromGeneratedAsyncApiPages).forEach(([key, value]) => {
57
58
  pagesAcc[key] = value;
@@ -0,0 +1,27 @@
1
+ import type { DecoratedNavigationPage, GraphqlReference, GraphqlTarget } from '@mintlify/models';
2
+ import type { DocsConfig } from '@mintlify/validation';
3
+ export type GeneratedGraphqlPage = {
4
+ slug: string;
5
+ title: string;
6
+ description?: string;
7
+ deprecated?: boolean;
8
+ tag: string;
9
+ target: GraphqlTarget;
10
+ };
11
+ export type GenerateGraphqlDivisionsResult = {
12
+ navigation: DocsConfig['navigation'];
13
+ newDocsConfig: DocsConfig;
14
+ pagesAcc: Record<string, DecoratedNavigationPage>;
15
+ generatedPages: GeneratedGraphqlPage[];
16
+ generatedRoutes: string[];
17
+ parsedReferences: Record<string, GraphqlReference>;
18
+ };
19
+ export type GraphqlSourceLoader = (source: string) => Promise<string>;
20
+ export declare const getGraphqlRouteKey: (route: string) => string;
21
+ /** Transform GraphQL navigation without reading or writing the filesystem. */
22
+ export declare function generateGraphqlDivisionsFromDocsConfig(docsConfig: DocsConfig, loadSource: GraphqlSourceLoader): Promise<GenerateGraphqlDivisionsResult>;
23
+ export declare function generateGraphqlDivisions(docsConfig: DocsConfig, contentDirectoryPath: string, targetDir?: string): Promise<GenerateGraphqlDivisionsResult>;
24
+ export declare function loadGraphqlSdlSource(source: string, contentDirectoryPath: string): Promise<string>;
25
+ export declare const isRemoteGraphqlSource: (source: string) => boolean;
26
+ export declare function writeGraphqlArtifacts(result: GenerateGraphqlDivisionsResult, targetDir?: string): Promise<void>;
27
+ export { loadRemoteGraphqlSdl } from './loadRemoteGraphqlSdl.js';
@@ -0,0 +1,259 @@
1
+ import { parseGraphqlSdl } from '@mintlify/scraping';
2
+ import fse from 'fs-extra';
3
+ import { open } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { getGeneratedRouteKey } from './generatedRouteCollisions.js';
6
+ import { loadRemoteGraphqlSdl, MAX_GRAPHQL_SCHEMA_BYTES } from './loadRemoteGraphqlSdl.js';
7
+ const DEFAULT_OUTPUT_DIR = 'graphql-reference';
8
+ const byName = (left, right) => left.name.localeCompare(right.name);
9
+ export const getGraphqlRouteKey = getGeneratedRouteKey;
10
+ function graphqlConfig(config) {
11
+ return typeof config === 'string'
12
+ ? { source: config, directory: DEFAULT_OUTPUT_DIR }
13
+ : { source: config.source, directory: config.directory ?? DEFAULT_OUTPUT_DIR };
14
+ }
15
+ function makePage(source, directory, kind, entry) {
16
+ const section = kind === 'query' ? 'queries' : kind === 'mutation' ? 'mutations' : 'types';
17
+ return {
18
+ slug: path.posix.join(directory, section, entry.name),
19
+ title: entry.name,
20
+ ...('description' in entry && entry.description ? { description: entry.description } : {}),
21
+ ...(kind !== 'type' && 'deprecationReason' in entry && entry.deprecationReason != null
22
+ ? { deprecated: true }
23
+ : {}),
24
+ tag: kind === 'type' && 'kind' in entry ? entry.kind.toUpperCase() : kind.toUpperCase(),
25
+ target: { source, kind, name: entry.name },
26
+ };
27
+ }
28
+ function generatePages(reference, source, directory) {
29
+ const roots = new Set([reference.queryType, reference.mutationType, reference.subscriptionType].filter((name) => name !== undefined));
30
+ const typeByName = new Map(reference.types.map((type) => [type.name, type]));
31
+ const queryType = reference.queryType ? typeByName.get(reference.queryType) : undefined;
32
+ const mutationType = reference.mutationType ? typeByName.get(reference.mutationType) : undefined;
33
+ const queryFields = reference.queryType
34
+ ? queryType?.kind === 'object'
35
+ ? queryType.fields
36
+ : []
37
+ : [];
38
+ const mutationFields = reference.mutationType
39
+ ? mutationType?.kind === 'object'
40
+ ? mutationType.fields
41
+ : []
42
+ : [];
43
+ return {
44
+ queries: queryFields
45
+ .slice()
46
+ .sort(byName)
47
+ .map((field) => makePage(source, directory, 'query', field)),
48
+ mutations: mutationFields
49
+ .slice()
50
+ .sort(byName)
51
+ .map((field) => makePage(source, directory, 'mutation', field)),
52
+ types: reference.types
53
+ .filter((type) => !roots.has(type.name) &&
54
+ (type.kind === 'object' ||
55
+ type.kind === 'interface' ||
56
+ type.kind === 'union' ||
57
+ type.kind === 'enum'))
58
+ .slice()
59
+ .sort(byName)
60
+ .map((type) => makePage(source, directory, 'type', type)),
61
+ };
62
+ }
63
+ function mdxStub(page) {
64
+ const fields = [
65
+ `title: ${JSON.stringify(page.title)}`,
66
+ ...(page.description ? [`description: ${JSON.stringify(page.description)}`] : []),
67
+ ...(page.deprecated ? ['deprecated: true'] : []),
68
+ `tag: ${JSON.stringify(page.tag)}`,
69
+ `graphql: ${JSON.stringify(page.target)}`,
70
+ ];
71
+ return `---\n${fields.join('\n')}\n---\n`;
72
+ }
73
+ /** Transform GraphQL navigation without reading or writing the filesystem. */
74
+ export async function generateGraphqlDivisionsFromDocsConfig(docsConfig, loadSource) {
75
+ const references = new Map();
76
+ const parsedReferences = new Map();
77
+ const pagesByRouteKey = new Map();
78
+ async function load(source) {
79
+ let pending = references.get(source);
80
+ if (!pending) {
81
+ pending = loadSource(source).then((sdl) => {
82
+ const reference = parseGraphqlSdl(sdl);
83
+ parsedReferences.set(source, reference);
84
+ return reference;
85
+ });
86
+ references.set(source, pending);
87
+ }
88
+ return pending;
89
+ }
90
+ async function processNode(value) {
91
+ if (Array.isArray(value))
92
+ return Promise.all(value.map(processNode));
93
+ if (typeof value !== 'object' || value === null)
94
+ return value;
95
+ const node = value;
96
+ if ('tab' in node && 'graphql' in node) {
97
+ const { graphql, ...tab } = node;
98
+ const { source, directory } = graphqlConfig(graphql);
99
+ const generated = generatePages(await load(source), source, directory);
100
+ const groups = [
101
+ { group: 'Queries', pages: generated.queries.map(({ slug }) => slug) },
102
+ { group: 'Mutations', pages: generated.mutations.map(({ slug }) => slug) },
103
+ { group: 'Types', pages: generated.types.map(({ slug }) => slug) },
104
+ ].filter(({ pages }) => pages.length > 0);
105
+ for (const page of [...generated.queries, ...generated.mutations, ...generated.types]) {
106
+ const routeKey = getGraphqlRouteKey(page.slug);
107
+ const existingPage = pagesByRouteKey.get(routeKey);
108
+ if (existingPage &&
109
+ (existingPage.slug !== page.slug ||
110
+ existingPage.target.source !== page.target.source ||
111
+ existingPage.target.kind !== page.target.kind ||
112
+ existingPage.target.name !== page.target.name)) {
113
+ throw new Error(`Multiple GraphQL references generate colliding routes "${existingPage.slug}" and "${page.slug}"`);
114
+ }
115
+ pagesByRouteKey.set(routeKey, page);
116
+ }
117
+ return { ...tab, groups: [...(tab.groups ?? []), ...groups] };
118
+ }
119
+ return Object.fromEntries(await Promise.all(Object.entries(node).map(async ([key, entry]) => [key, await processNode(entry)])));
120
+ }
121
+ const navigation = await processNode(docsConfig.navigation);
122
+ const generatedPages = [...pagesByRouteKey.values()].sort((left, right) => getGeneratedRouteKey(left.slug).localeCompare(getGeneratedRouteKey(right.slug)) ||
123
+ left.slug.localeCompare(right.slug));
124
+ const pagesAcc = Object.fromEntries(generatedPages.map((page) => [
125
+ page.slug,
126
+ {
127
+ href: `/${page.slug}`,
128
+ title: page.title,
129
+ ...(page.description ? { description: page.description } : {}),
130
+ ...(page.deprecated ? { deprecated: true } : {}),
131
+ tag: page.tag,
132
+ graphql: page.target,
133
+ },
134
+ ]));
135
+ return {
136
+ navigation: navigation,
137
+ newDocsConfig: { ...docsConfig, navigation: navigation },
138
+ pagesAcc,
139
+ generatedPages,
140
+ generatedRoutes: generatedPages.map(({ slug }) => slug),
141
+ parsedReferences: Object.fromEntries([...parsedReferences].sort(([left], [right]) => left.localeCompare(right))),
142
+ };
143
+ }
144
+ export async function generateGraphqlDivisions(docsConfig, contentDirectoryPath, targetDir) {
145
+ const result = await generateGraphqlDivisionsFromDocsConfig(docsConfig, (source) => loadGraphqlSdlSource(source, contentDirectoryPath));
146
+ await writeGraphqlArtifacts(result, targetDir);
147
+ return result;
148
+ }
149
+ export async function loadGraphqlSdlSource(source, contentDirectoryPath) {
150
+ if (path.isAbsolute(source) || path.win32.isAbsolute(source)) {
151
+ throw new Error(`Unable to load GraphQL schema ${source}: path must be relative`);
152
+ }
153
+ let sourceUrl;
154
+ try {
155
+ sourceUrl = new URL(source);
156
+ }
157
+ catch { }
158
+ if (sourceUrl) {
159
+ if (sourceUrl.protocol === 'https:')
160
+ return loadRemoteGraphqlSdl(sourceUrl.href);
161
+ throw new Error(`Unable to load GraphQL schema ${source}: URL must use HTTPS`);
162
+ }
163
+ try {
164
+ const contentRoot = await fse.realpath(contentDirectoryPath);
165
+ const candidatePath = path.resolve(contentRoot, source);
166
+ const relativePath = path.relative(contentRoot, candidatePath);
167
+ if (relativePath === '..' ||
168
+ relativePath.startsWith(`..${path.sep}`) ||
169
+ path.isAbsolute(relativePath)) {
170
+ throw new Error('path escapes the content directory');
171
+ }
172
+ const realSourcePath = await fse.realpath(candidatePath);
173
+ const realRelativePath = path.relative(contentRoot, realSourcePath);
174
+ if (realRelativePath === '..' ||
175
+ realRelativePath.startsWith(`..${path.sep}`) ||
176
+ path.isAbsolute(realRelativePath)) {
177
+ throw new Error('path resolves outside the content directory');
178
+ }
179
+ const schemaFile = await open(realSourcePath, 'r');
180
+ try {
181
+ const schemaStats = await schemaFile.stat();
182
+ if (schemaStats.size > MAX_GRAPHQL_SCHEMA_BYTES) {
183
+ throw new Error(`schema exceeds the ${MAX_GRAPHQL_SCHEMA_BYTES} byte limit`);
184
+ }
185
+ const decoder = new TextDecoder();
186
+ let schema = '';
187
+ let byteLength = 0;
188
+ for await (const chunk of schemaFile.createReadStream({ autoClose: false })) {
189
+ byteLength += chunk.length;
190
+ if (byteLength > MAX_GRAPHQL_SCHEMA_BYTES) {
191
+ throw new Error(`schema exceeds the ${MAX_GRAPHQL_SCHEMA_BYTES} byte limit`);
192
+ }
193
+ schema += decoder.decode(chunk, { stream: true });
194
+ }
195
+ return schema + decoder.decode();
196
+ }
197
+ finally {
198
+ await schemaFile.close();
199
+ }
200
+ }
201
+ catch (error) {
202
+ const detail = error instanceof Error ? `: ${error.message}` : '';
203
+ throw new Error(`Unable to load GraphQL schema ${source}${detail}`);
204
+ }
205
+ }
206
+ export const isRemoteGraphqlSource = (source) => {
207
+ try {
208
+ return new URL(source).protocol === 'https:';
209
+ }
210
+ catch {
211
+ return false;
212
+ }
213
+ };
214
+ function getContainedGraphqlPagePath(targetDir, page) {
215
+ const propsDirectory = path.resolve(targetDir ?? '', 'src', '_props');
216
+ const pagePath = path.resolve(propsDirectory, `${page}.mdx`);
217
+ const relativePath = path.relative(propsDirectory, pagePath);
218
+ if (relativePath.startsWith(`..${path.sep}`) ||
219
+ relativePath === '..' ||
220
+ path.isAbsolute(relativePath)) {
221
+ return undefined;
222
+ }
223
+ return pagePath;
224
+ }
225
+ export async function writeGraphqlArtifacts(result, targetDir) {
226
+ const propsDirectory = path.resolve(targetDir ?? '', 'src', '_props');
227
+ const artifactPath = path.join(propsDirectory, 'graphql-data.json');
228
+ try {
229
+ const previousArtifacts = JSON.parse(await fse.readFile(artifactPath, 'utf8'));
230
+ if (previousArtifacts.pages != null &&
231
+ typeof previousArtifacts.pages === 'object' &&
232
+ !Array.isArray(previousArtifacts.pages)) {
233
+ await Promise.all(Object.keys(previousArtifacts.pages).flatMap((page) => {
234
+ const pagePath = getContainedGraphqlPagePath(targetDir, page);
235
+ return pagePath ? [fse.remove(pagePath)] : [];
236
+ }));
237
+ }
238
+ }
239
+ catch { }
240
+ await fse.remove(artifactPath);
241
+ if (Object.keys(result.parsedReferences).length === 0 && result.generatedRoutes.length === 0) {
242
+ return;
243
+ }
244
+ const artifacts = {
245
+ references: result.parsedReferences,
246
+ pages: Object.fromEntries(result.generatedPages.map((page) => {
247
+ const directory = path.posix.dirname(path.posix.dirname(page.slug));
248
+ const routes = Object.fromEntries(result.generatedPages
249
+ .filter((generatedPage) => generatedPage.target.source === page.target.source &&
250
+ generatedPage.target.kind === 'type' &&
251
+ path.posix.dirname(path.posix.dirname(generatedPage.slug)) === directory)
252
+ .map((generatedPage) => [generatedPage.target.name, `/${generatedPage.slug}`]));
253
+ return [page.slug, { target: page.target, routes }];
254
+ })),
255
+ };
256
+ await fse.outputFile(artifactPath, JSON.stringify(artifacts), { flag: 'w' });
257
+ await Promise.all(result.generatedPages.map((page) => fse.outputFile(path.join(targetDir ?? '', 'src', '_props', `${page.slug}.mdx`), mdxStub(page), { flag: 'w' })));
258
+ }
259
+ export { loadRemoteGraphqlSdl } from './loadRemoteGraphqlSdl.js';
@@ -1,8 +1,9 @@
1
1
  import type { OpenApiFile, DecoratedNavigationPage } from '@mintlify/models';
2
2
  import { DocsConfig } from '@mintlify/validation';
3
3
  import type { InvalidSpecFile } from '../../invalidSpecFiles.js';
4
- export declare const generateOpenApiDivisions: (docsConfig: DocsConfig, openApiFiles: OpenApiFile[], targetDir?: string, localSchema?: boolean, invalidSpecFiles?: InvalidSpecFile[]) => Promise<{
4
+ export declare const generateOpenApiDivisions: (docsConfig: DocsConfig, openApiFiles: OpenApiFile[], targetDir?: string, localSchema?: boolean, invalidSpecFiles?: InvalidSpecFile[], graphqlPages?: Record<string, DecoratedNavigationPage>, deferWrites?: boolean) => Promise<{
5
5
  newDocsConfig: DocsConfig;
6
6
  pagesAcc: Record<string, DecoratedNavigationPage>;
7
7
  openApiFiles: OpenApiFile[];
8
+ flushWrites: () => Promise<void>;
8
9
  }>;
@@ -1,19 +1,39 @@
1
+ import fse from 'fs-extra';
1
2
  import { getOpenApiFilesFromConfig } from '../read/getOpenApiFilesFromConfig.js';
3
+ import { assertNoGeneratedRouteCollisions } from './generatedRouteCollisions.js';
2
4
  import { generateOpenApiFromDocsConfig } from './generateOpenApiFromDocsConfig.js';
3
- export const generateOpenApiDivisions = async (docsConfig, openApiFiles, targetDir, localSchema, invalidSpecFiles) => {
5
+ export const generateOpenApiDivisions = async (docsConfig, openApiFiles, targetDir, localSchema, invalidSpecFiles, graphqlPages, deferWrites = false) => {
4
6
  const openapiFilesFromDocsConfig = await getOpenApiFilesFromConfig('docs', docsConfig, localSchema);
5
7
  openApiFiles.push(...openapiFilesFromDocsConfig);
6
8
  const pagesAcc = {};
9
+ const writes = [];
10
+ const planWrites = deferWrites || (graphqlPages != null && Object.keys(graphqlPages).length > 0);
7
11
  const { newNav, newOpenApiFiles } = await generateOpenApiFromDocsConfig(docsConfig.navigation, openApiFiles, pagesAcc, {
8
12
  overwrite: true,
9
13
  writeFiles: true,
10
14
  targetDir,
11
15
  localSchema,
12
16
  invalidSpecFiles,
17
+ ...(planWrites
18
+ ? {
19
+ writeFile: (filename, content) => {
20
+ writes.push({ filename, content });
21
+ },
22
+ }
23
+ : {}),
13
24
  });
25
+ const flushWrites = async () => {
26
+ await Promise.all(writes.map(({ filename, content }) => fse.outputFile(filename, content)));
27
+ };
28
+ if (graphqlPages) {
29
+ assertNoGeneratedRouteCollisions({ label: 'GraphQL', pages: graphqlPages }, { label: 'OpenAPI', pages: pagesAcc });
30
+ }
31
+ if (!deferWrites)
32
+ await flushWrites();
14
33
  return {
15
34
  newDocsConfig: { ...docsConfig, navigation: newNav },
16
35
  pagesAcc,
17
36
  openApiFiles: [...openApiFiles, ...newOpenApiFiles],
37
+ flushWrites,
18
38
  };
19
39
  };
@@ -7,6 +7,7 @@ export declare const generateOpenApiFromDocsConfig: (navigation: NavigationConfi
7
7
  targetDir?: string;
8
8
  localSchema?: boolean;
9
9
  invalidSpecFiles?: InvalidSpecFile[];
10
+ writeFile?: (filename: string, content: string) => void | Promise<void>;
10
11
  }) => Promise<{
11
12
  newNav: NavigationConfig;
12
13
  newOpenApiFiles: OpenApiFile[];
@@ -6,7 +6,7 @@ import * as path from 'path';
6
6
  import { findInvalidSpecFile } from '../../invalidSpecFiles.js';
7
7
  const DEFAULT_OUTPUT_DIR = 'api-reference';
8
8
  export const generateOpenApiFromDocsConfig = async (navigation, openApiFiles, pagesAcc, opts) => {
9
- const { overwrite, writeFiles, targetDir, localSchema, invalidSpecFiles } = opts;
9
+ const { overwrite, writeFiles, targetDir, localSchema, invalidSpecFiles, writeFile } = opts;
10
10
  const newOpenApiFiles = [];
11
11
  const openApiFilePromises = new Map();
12
12
  async function processOpenApiInNav(nav) {
@@ -55,6 +55,7 @@ export const generateOpenApiFromDocsConfig = async (navigation, openApiFiles, pa
55
55
  outDirBasePath: path.join(targetDir ?? '', 'src', '_props'),
56
56
  overwrite,
57
57
  localSchema,
58
+ writeFile,
58
59
  });
59
60
  Object.entries(pagesAccFromGeneratedOpenApiPages).forEach(([key, value]) => {
60
61
  pagesAcc[key] = value;
@@ -173,6 +174,7 @@ export const generateOpenApiFromDocsConfig = async (navigation, openApiFiles, pa
173
174
  outDirBasePath: path.join(targetDir ?? '', 'src', '_props'),
174
175
  overwrite,
175
176
  localSchema,
177
+ writeFile,
176
178
  }, findNavGroup);
177
179
  }
178
180
  else {
@@ -192,6 +194,7 @@ export const generateOpenApiFromDocsConfig = async (navigation, openApiFiles, pa
192
194
  outDirBasePath: path.join(targetDir ?? '', 'src', '_props'),
193
195
  overwrite,
194
196
  localSchema,
197
+ writeFile,
195
198
  }, findNavGroup);
196
199
  }
197
200
  await Promise.all(writePromises);
@@ -0,0 +1,8 @@
1
+ import type { DecoratedNavigationPage } from '@mintlify/models';
2
+ export declare const getGeneratedRouteKey: (route: string) => string;
3
+ type GeneratedRoutes = {
4
+ label: string;
5
+ pages: Record<string, DecoratedNavigationPage>;
6
+ };
7
+ export declare function assertNoGeneratedRouteCollisions(first: GeneratedRoutes, second: GeneratedRoutes): void;
8
+ export {};
@@ -0,0 +1,10 @@
1
+ export const getGeneratedRouteKey = (route) => route.replaceAll('\\', '/').normalize('NFC').toLowerCase();
2
+ export function assertNoGeneratedRouteCollisions(first, second) {
3
+ const firstRoutes = new Map(Object.keys(first.pages).map((route) => [getGeneratedRouteKey(route), route]));
4
+ for (const secondRoute of Object.keys(second.pages)) {
5
+ const firstRoute = firstRoutes.get(getGeneratedRouteKey(secondRoute));
6
+ if (firstRoute) {
7
+ throw new Error(`Generated ${first.label} route "${firstRoute}" collides with generated ${second.label} route "${secondRoute}"`);
8
+ }
9
+ }
10
+ }
@@ -28,3 +28,6 @@ export { getOpenApiFilesFromConfig } from '../read/getOpenApiFilesFromConfig.js'
28
28
  export { generateAsyncApiDivisions } from './generateAsyncApiDivisions.js';
29
29
  export { generateAsyncApiFromDocsConfig } from './generateAsyncApiFromDocsConfig.js';
30
30
  export { getCustomLanguages } from './getCustomLanguages.js';
31
+ export { generateGraphqlDivisions, generateGraphqlDivisionsFromDocsConfig, getGraphqlRouteKey, isRemoteGraphqlSource, loadGraphqlSdlSource, loadRemoteGraphqlSdl, writeGraphqlArtifacts, } from './generateGraphqlDivisions.js';
32
+ export { assertNoGeneratedRouteCollisions, getGeneratedRouteKey, } from './generatedRouteCollisions.js';
33
+ export type { GeneratedGraphqlPage, GenerateGraphqlDivisionsResult, GraphqlSourceLoader, } from './generateGraphqlDivisions.js';
@@ -1,6 +1,7 @@
1
1
  import { getConfigPath } from '../../../utils.js';
2
2
  import { DocsConfigUpdater } from '../ConfigUpdater.js';
3
3
  import { generateAsyncApiDivisions } from './generateAsyncApiDivisions.js';
4
+ import { generateGraphqlDivisionsFromDocsConfig, loadGraphqlSdlSource, writeGraphqlArtifacts, } from './generateGraphqlDivisions.js';
4
5
  import { generateOpenApiDivisions } from './generateOpenApiDivisions.js';
5
6
  import { getCustomLanguages } from './getCustomLanguages.js';
6
7
  const NOT_CORRECT_PATH_ERROR = 'must be run in a directory where a docs.json file exists.';
@@ -18,14 +19,27 @@ export async function updateDocsConfigFile({ contentDirectoryPath, openApiFiles,
18
19
  throw Error(NOT_CORRECT_PATH_ERROR);
19
20
  }
20
21
  const customLanguages = await getCustomLanguages({ config: docsConfig, contentDirectoryPath });
21
- const { newDocsConfig: docsConfigWithOpenApiPages, pagesAcc: pagesAccWithOpenApiPages, openApiFiles: newOpenApiFiles, } = !disableOpenApi
22
- ? await generateOpenApiDivisions(docsConfig, openApiFiles, undefined, localSchema, invalidSpecFiles)
23
- : { newDocsConfig: docsConfig, pagesAcc: {}, openApiFiles: openApiFiles };
24
- const { newDocsConfig, pagesAcc: pagesAccWithAsyncApiPages, asyncApiFiles: newAsyncApiFiles, } = await generateAsyncApiDivisions(docsConfigWithOpenApiPages, asyncApiFiles, undefined, localSchema);
25
- const pagesAcc = { ...pagesAccWithOpenApiPages, ...pagesAccWithAsyncApiPages };
26
- await DocsConfigUpdater.writeConfigFile(newDocsConfig);
22
+ const graphqlResult = await generateGraphqlDivisionsFromDocsConfig(docsConfig, (source) => loadGraphqlSdlSource(source, contentDirectoryPath));
23
+ const { newDocsConfig: docsConfigWithGraphqlPages, pagesAcc: pagesAccWithGraphqlPages } = graphqlResult;
24
+ const { newDocsConfig: docsConfigWithOpenApiPages, pagesAcc: pagesAccWithOpenApiPages, openApiFiles: newOpenApiFiles, flushWrites: flushOpenApiWrites, } = !disableOpenApi
25
+ ? await generateOpenApiDivisions(docsConfigWithGraphqlPages, openApiFiles, undefined, localSchema, invalidSpecFiles, pagesAccWithGraphqlPages, true)
26
+ : {
27
+ newDocsConfig: docsConfigWithGraphqlPages,
28
+ pagesAcc: {},
29
+ openApiFiles: openApiFiles,
30
+ flushWrites: async () => { },
31
+ };
32
+ const { newDocsConfig: docsConfigWithAsyncApiPages, pagesAcc: pagesAccWithAsyncApiPages, asyncApiFiles: newAsyncApiFiles, flushWrites: flushAsyncApiWrites, } = await generateAsyncApiDivisions(docsConfigWithOpenApiPages, asyncApiFiles, undefined, localSchema, pagesAccWithGraphqlPages, true, true);
33
+ const pagesAcc = {
34
+ ...pagesAccWithOpenApiPages,
35
+ ...pagesAccWithAsyncApiPages,
36
+ ...pagesAccWithGraphqlPages,
37
+ };
38
+ await Promise.all([flushOpenApiWrites(), flushAsyncApiWrites()]);
39
+ await writeGraphqlArtifacts(graphqlResult);
40
+ await DocsConfigUpdater.writeConfigFile(docsConfigWithAsyncApiPages);
27
41
  return {
28
- docsConfig: newDocsConfig,
42
+ docsConfig: docsConfigWithAsyncApiPages,
29
43
  pagesAcc,
30
44
  newOpenApiFiles,
31
45
  newAsyncApiFiles,
@@ -38,3 +52,5 @@ export { getOpenApiFilesFromConfig } from '../read/getOpenApiFilesFromConfig.js'
38
52
  export { generateAsyncApiDivisions } from './generateAsyncApiDivisions.js';
39
53
  export { generateAsyncApiFromDocsConfig } from './generateAsyncApiFromDocsConfig.js';
40
54
  export { getCustomLanguages } from './getCustomLanguages.js';
55
+ export { generateGraphqlDivisions, generateGraphqlDivisionsFromDocsConfig, getGraphqlRouteKey, isRemoteGraphqlSource, loadGraphqlSdlSource, loadRemoteGraphqlSdl, writeGraphqlArtifacts, } from './generateGraphqlDivisions.js';
56
+ export { assertNoGeneratedRouteCollisions, getGeneratedRouteKey, } from './generatedRouteCollisions.js';
@@ -0,0 +1,18 @@
1
+ import { request } from 'node:https';
2
+ import type { LookupFunction } from 'node:net';
3
+ export declare const MAX_GRAPHQL_SCHEMA_BYTES: number;
4
+ export type ResolvedAddress = {
5
+ address: string;
6
+ family: 4 | 6;
7
+ };
8
+ type ResolveHostname = (hostname: string) => Promise<ResolvedAddress[]>;
9
+ type HttpsRequest = typeof request;
10
+ export declare const isGlobalIpAddress: (address: string) => boolean;
11
+ export declare function createPinnedLookup(resolved: ResolvedAddress): LookupFunction;
12
+ export declare function loadRemoteGraphqlSdl(source: string, options?: {
13
+ timeoutMs?: number;
14
+ maxBytes?: number;
15
+ resolveHostname?: ResolveHostname;
16
+ requestImpl?: HttpsRequest;
17
+ }): Promise<string>;
18
+ export {};