@mintlify/scraping 4.0.904 → 4.0.906

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mintlify/scraping",
3
- "version": "4.0.904",
3
+ "version": "4.0.906",
4
4
  "description": "Scrape documentation frameworks to Mintlify docs",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -43,9 +43,10 @@
43
43
  "format:check": "oxfmt --check"
44
44
  },
45
45
  "dependencies": {
46
- "@mintlify/common": "1.0.1039",
46
+ "@mintlify/common": "1.0.1041",
47
47
  "@mintlify/openapi-parser": "0.0.8",
48
48
  "fs-extra": "11.1.1",
49
+ "graphql": "16.11.0",
49
50
  "hast-util-to-mdast": "10.1.0",
50
51
  "js-yaml": "4.1.1",
51
52
  "mdast-util-mdx-jsx": "3.1.3",
@@ -62,9 +63,9 @@
62
63
  "zod": "3.24.0"
63
64
  },
64
65
  "devDependencies": {
65
- "@mintlify/models": "0.0.342",
66
+ "@mintlify/models": "0.0.343",
66
67
  "@mintlify/ts-config": "2.0.2",
67
- "@mintlify/validation": "0.1.796",
68
+ "@mintlify/validation": "0.1.798",
68
69
  "@tsconfig/recommended": "1.0.2",
69
70
  "@types/hast": "3.0.4",
70
71
  "@types/mdast": "4.0.4",
@@ -78,5 +79,5 @@
78
79
  "typescript": "5.5.3",
79
80
  "vitest": "2.1.9"
80
81
  },
81
- "gitHead": "48ebadbb106c4c5969cd83c048e660bc39955f3f"
82
+ "gitHead": "e6c3793e677c3aa79650fb9fbd31467ff1649d2e"
82
83
  }
@@ -14,6 +14,7 @@ type GenerateAsyncApiPagesOptions = {
14
14
  outDirBasePath?: string;
15
15
  overwrite?: boolean;
16
16
  localSchema?: boolean;
17
+ writeFile?: (filename: string, content: string) => void | Promise<void>;
17
18
  };
18
19
 
19
20
  type AsyncApiPageGenerationResult = {
@@ -24,6 +24,7 @@ type GenerateAsyncApiPagesOptions = {
24
24
  outDir?: string;
25
25
  outDirBasePath?: string;
26
26
  overwrite?: boolean;
27
+ writeFile?: (filename: string, content: string) => void | Promise<void>;
27
28
  };
28
29
 
29
30
  type ProcessAsyncApiChannelArgs = {
@@ -90,18 +91,15 @@ export const processAsyncApiChannel = ({
90
91
  ? join(opts.outDirBasePath, `${filenameWithoutExtension}.mdx`)
91
92
  : `${filenameWithoutExtension}.mdx`;
92
93
  if (opts?.writeFiles && (!fse.pathExistsSync(targetPath) || opts.overwrite)) {
93
- writePromises.push(createAsyncApiFrontmatter(targetPath, asyncApiMetaTag, opts.version));
94
+ const content = createAsyncApiFrontmatterContent(asyncApiMetaTag, opts.version);
95
+ writePromises.push(
96
+ opts.writeFile
97
+ ? Promise.resolve(opts.writeFile(targetPath, content))
98
+ : outputFile(targetPath, content)
99
+ );
94
100
  }
95
101
  };
96
102
 
97
- const createAsyncApiFrontmatter = async (
98
- filename: string,
99
- asyncApiMetaTag: string,
100
- version?: string
101
- ) => {
102
- const data = `---
103
+ const createAsyncApiFrontmatterContent = (asyncApiMetaTag: string, version?: string) => `---
103
104
  asyncapi: ${asyncApiMetaTag}${version ? `\nversion: ${version}` : ''}
104
105
  ---`;
105
-
106
- await outputFile(filename, data);
107
- };
@@ -0,0 +1,146 @@
1
+ import type {
2
+ GraphqlField,
3
+ GraphqlInputValue,
4
+ GraphqlReference,
5
+ GraphqlType,
6
+ GraphqlTypeRef,
7
+ } from '@mintlify/models';
8
+ import {
9
+ buildSchema,
10
+ isEnumType,
11
+ isInputObjectType,
12
+ isInterfaceType,
13
+ isListType,
14
+ isNonNullType,
15
+ isObjectType,
16
+ isScalarType,
17
+ isSpecifiedScalarType,
18
+ isUnionType,
19
+ print,
20
+ validateSchema,
21
+ valueFromASTUntyped,
22
+ type GraphQLArgument,
23
+ type GraphQLField,
24
+ type GraphQLInputField,
25
+ type GraphQLType,
26
+ } from 'graphql';
27
+
28
+ const isVisibleName = (name: string) => !name.startsWith('__');
29
+
30
+ const withDescription = (description: string | undefined | null) =>
31
+ description === undefined || description === null ? {} : { description };
32
+
33
+ const withDeprecation = (deprecationReason: string | undefined | null) =>
34
+ deprecationReason === undefined || deprecationReason === null ? {} : { deprecationReason };
35
+
36
+ function normalizeGraphqlTypeRef(type: GraphQLType): GraphqlTypeRef {
37
+ if (isNonNullType(type)) {
38
+ return { kind: 'nonNull', ofType: normalizeGraphqlTypeRef(type.ofType) };
39
+ }
40
+ if (isListType(type)) {
41
+ return { kind: 'list', ofType: normalizeGraphqlTypeRef(type.ofType) };
42
+ }
43
+ return { kind: 'named', name: type.name };
44
+ }
45
+
46
+ function normalizeInputValue(field: GraphQLArgument | GraphQLInputField): GraphqlInputValue {
47
+ const defaultValue = field.astNode?.defaultValue;
48
+ return {
49
+ name: field.name,
50
+ type: normalizeGraphqlTypeRef(field.type),
51
+ ...withDescription(field.description),
52
+ ...(defaultValue === undefined
53
+ ? {}
54
+ : {
55
+ defaultValue: valueFromASTUntyped(defaultValue),
56
+ defaultValueLiteral: print(defaultValue),
57
+ }),
58
+ ...withDeprecation(field.deprecationReason),
59
+ };
60
+ }
61
+
62
+ function normalizeField(field: GraphQLField<unknown, unknown>): GraphqlField {
63
+ return {
64
+ name: field.name,
65
+ type: normalizeGraphqlTypeRef(field.type),
66
+ ...withDescription(field.description),
67
+ arguments: field.args.filter(({ name }) => isVisibleName(name)).map(normalizeInputValue),
68
+ ...withDeprecation(field.deprecationReason),
69
+ };
70
+ }
71
+
72
+ export function parseGraphqlSdl(sdl: string): GraphqlReference {
73
+ const schema = buildSchema(sdl);
74
+ const validationErrors = validateSchema(schema);
75
+ if (validationErrors.length > 0) {
76
+ throw new Error(validationErrors.map(({ message }) => message).join('\n'));
77
+ }
78
+
79
+ const types: GraphqlType[] = [];
80
+ for (const type of Object.values(schema.getTypeMap())) {
81
+ if (!isVisibleName(type.name) || (isScalarType(type) && isSpecifiedScalarType(type))) {
82
+ continue;
83
+ }
84
+
85
+ const named = { name: type.name, ...withDescription(type.description) };
86
+ if (isObjectType(type)) {
87
+ types.push({
88
+ kind: 'object',
89
+ ...named,
90
+ fields: Object.values(type.getFields())
91
+ .filter(({ name }) => isVisibleName(name))
92
+ .map(normalizeField),
93
+ interfaces: type.getInterfaces().map(({ name }) => name),
94
+ });
95
+ } else if (isInputObjectType(type)) {
96
+ types.push({
97
+ kind: 'input',
98
+ ...named,
99
+ fields: Object.values(type.getFields())
100
+ .filter(({ name }) => isVisibleName(name))
101
+ .map(normalizeInputValue),
102
+ });
103
+ } else if (isEnumType(type)) {
104
+ types.push({
105
+ kind: 'enum',
106
+ ...named,
107
+ values: type
108
+ .getValues()
109
+ .filter(({ name }) => isVisibleName(name))
110
+ .map((value) => ({
111
+ name: value.name,
112
+ ...withDescription(value.description),
113
+ ...withDeprecation(value.deprecationReason),
114
+ })),
115
+ });
116
+ } else if (isInterfaceType(type)) {
117
+ types.push({
118
+ kind: 'interface',
119
+ ...named,
120
+ fields: Object.values(type.getFields())
121
+ .filter(({ name }) => isVisibleName(name))
122
+ .map(normalizeField),
123
+ interfaces: type.getInterfaces().map(({ name }) => name),
124
+ possibleTypes: schema.getPossibleTypes(type).map(({ name }) => name),
125
+ });
126
+ } else if (isUnionType(type)) {
127
+ types.push({
128
+ kind: 'union',
129
+ ...named,
130
+ possibleTypes: type.getTypes().map(({ name }) => name),
131
+ });
132
+ } else if (isScalarType(type)) {
133
+ types.push({ kind: 'scalar', ...named });
134
+ }
135
+ }
136
+
137
+ const queryType = schema.getQueryType();
138
+ const mutationType = schema.getMutationType();
139
+ const subscriptionType = schema.getSubscriptionType();
140
+ return {
141
+ ...(queryType == null ? {} : { queryType: queryType.name }),
142
+ ...(mutationType == null ? {} : { mutationType: mutationType.name }),
143
+ ...(subscriptionType == null ? {} : { subscriptionType: subscriptionType.name }),
144
+ types,
145
+ };
146
+ }
package/src/index.ts CHANGED
@@ -12,3 +12,4 @@ export { write } from './utils/file.js';
12
12
  export { getErrorMessage } from './utils/errors.js';
13
13
  export { checkUrl } from './utils/url.js';
14
14
  export { FINAL_SUCCESS_MESSAGE } from './constants.js';
15
+ export { parseGraphqlSdl } from './graphql/parseGraphqlSdl.js';
@@ -62,21 +62,19 @@ export const getOpenApiDefinition = async (
62
62
  return { document: pathOrDocumentOrUrl, isUrl };
63
63
  };
64
64
 
65
- export const createOpenApiFrontmatter = async ({
66
- filename,
65
+ export const createOpenApiFrontmatterContent = ({
67
66
  openApiMetaTag,
68
67
  version,
69
68
  deprecated,
70
69
  metadata,
71
70
  extraContent,
72
71
  }: {
73
- filename: string;
74
72
  openApiMetaTag: string;
75
73
  version?: string;
76
74
  deprecated?: boolean;
77
75
  metadata?: PageMetaTags;
78
76
  extraContent?: string;
79
- }) => {
77
+ }): string => {
80
78
  let frontmatter = `---\nopenapi: ${openApiMetaTag}`;
81
79
  if (metadata && 'version' in metadata) {
82
80
  frontmatter += `\nversion: ${metadata.version}`;
@@ -99,10 +97,21 @@ export const createOpenApiFrontmatter = async ({
99
97
  }
100
98
 
101
99
  frontmatter += `\n---`;
100
+ return extraContent ? `${frontmatter}\n\n${extraContent}` : frontmatter;
101
+ };
102
102
 
103
- const data = extraContent ? `${frontmatter}\n\n${extraContent}` : frontmatter;
104
-
105
- await outputFile(filename, data);
103
+ export const createOpenApiFrontmatter = async ({
104
+ filename,
105
+ ...input
106
+ }: {
107
+ filename: string;
108
+ openApiMetaTag: string;
109
+ version?: string;
110
+ deprecated?: boolean;
111
+ metadata?: PageMetaTags;
112
+ extraContent?: string;
113
+ }) => {
114
+ await outputFile(filename, createOpenApiFrontmatterContent(input));
106
115
  };
107
116
 
108
117
  export type GenerateOpenApiPagesOptions = {
@@ -113,6 +122,7 @@ export type GenerateOpenApiPagesOptions = {
113
122
  outDirBasePath?: string;
114
123
  overwrite?: boolean;
115
124
  localSchema?: boolean;
125
+ writeFile?: (filename: string, content: string) => void | Promise<void>;
116
126
  };
117
127
 
118
128
  export type OpenApiPageGenerationResult<N, DN> = {
@@ -248,15 +258,17 @@ export function processOpenApiPath<N, DN>(
248
258
  ? join(options.outDirBasePath, `${filenameWithoutExtension}.mdx`)
249
259
  : `${filenameWithoutExtension}.mdx`;
250
260
  if (options.writeFiles && (!fse.pathExistsSync(targetPath) || options.overwrite)) {
261
+ const input = {
262
+ openApiMetaTag: openapiMetaTag,
263
+ version: options.version,
264
+ deprecated: operation?.deprecated,
265
+ metadata: xMintMetadata,
266
+ extraContent: xMint?.content,
267
+ };
251
268
  writePromises.push(
252
- createOpenApiFrontmatter({
253
- filename: targetPath,
254
- openApiMetaTag: openapiMetaTag,
255
- version: options.version,
256
- deprecated: operation?.deprecated,
257
- metadata: xMintMetadata,
258
- extraContent: xMint?.content,
259
- })
269
+ options.writeFile
270
+ ? Promise.resolve(options.writeFile(targetPath, createOpenApiFrontmatterContent(input)))
271
+ : createOpenApiFrontmatter({ filename: targetPath, ...input })
260
272
  );
261
273
  }
262
274
  }
@@ -341,15 +353,17 @@ export function processOpenApiWebhook<N, DN>(
341
353
  ? join(options.outDirBasePath, `${filenameWithoutExtension}.mdx`)
342
354
  : `${filenameWithoutExtension}.mdx`;
343
355
  if (options.writeFiles && (!fse.pathExistsSync(targetPath) || options.overwrite)) {
356
+ const input = {
357
+ openApiMetaTag: openapiMetaTag,
358
+ version: options.version,
359
+ deprecated: operation?.deprecated,
360
+ metadata: xMint?.metadata,
361
+ extraContent: xMint?.content,
362
+ };
344
363
  writePromises.push(
345
- createOpenApiFrontmatter({
346
- filename: targetPath,
347
- openApiMetaTag: openapiMetaTag,
348
- version: options.version,
349
- deprecated: operation?.deprecated,
350
- metadata: xMint?.metadata,
351
- extraContent: xMint?.content,
352
- })
364
+ options.writeFile
365
+ ? Promise.resolve(options.writeFile(targetPath, createOpenApiFrontmatterContent(input)))
366
+ : createOpenApiFrontmatter({ filename: targetPath, ...input })
353
367
  );
354
368
  }
355
369
  }