@mintlify/previewing 4.0.1357 → 4.0.1359

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.
@@ -1,4 +1,5 @@
1
1
  import { categorizeFilePaths, createPage, generateDecoratedDocsNavigationFromPages, getMintIgnore, } from '@mintlify/prebuild';
2
+ import { collectOpenApiOverlayConfig, } from '@mintlify/validation';
2
3
  import { promises as _promises } from 'fs';
3
4
  import { join } from 'path';
4
5
  import { CMD_EXEC_PATH } from '../../constants.js';
@@ -21,7 +22,7 @@ const createFilenamePageMetadataMap = async ({ contentDirectoryPath, contentFile
21
22
  };
22
23
  export const generateNav = async (pagesAcc, docsConfig) => {
23
24
  const mintIgnore = await getMintIgnore(CMD_EXEC_PATH);
24
- const { contentFilenames, openApiFiles, asyncApiFiles } = await categorizeFilePaths(CMD_EXEC_PATH, mintIgnore);
25
+ const { contentFilenames, openApiFiles, asyncApiFiles } = await categorizeFilePaths(CMD_EXEC_PATH, mintIgnore, undefined, undefined, { explicitOverlays: collectOpenApiOverlayConfig(docsConfig) });
25
26
  const filenamePageMetadataMap = await createFilenamePageMetadataMap({
26
27
  contentDirectoryPath: CMD_EXEC_PATH,
27
28
  contentFilenames,
@@ -1,11 +1,17 @@
1
- import { generateOpenApiAnchorsOrTabs, categorizeFilePaths, generateOpenApiDivisions, generateAsyncApiDivisions, generateGraphqlDivisionsFromDocsConfig, getMintIgnore, MintConfigUpdater, DocsConfigUpdater, warnInvalidSpecFiles, loadGraphqlSdlSource, writeGraphqlArtifacts, } from '@mintlify/prebuild';
1
+ import { generateOpenApiAnchorsOrTabs, categorizeFilePaths, generateOpenApiDivisions, generateAsyncApiDivisions, generateGraphqlDivisionsFromDocsConfig, getMintIgnore, MintConfigUpdater, DocsConfigUpdater, readExplicitOverlayConfig, warnInvalidSpecFiles, loadGraphqlSdlSource, writeGraphqlArtifacts, } from '@mintlify/prebuild';
2
2
  import { upgradeToDocsConfig } from '@mintlify/validation';
3
3
  import fse from 'fs-extra';
4
4
  import { join } from 'path';
5
5
  import { CMD_EXEC_PATH, CLIENT_PATH } from '../../constants.js';
6
6
  export const getDocsState = async (onError, { contentDirectory = CMD_EXEC_PATH, clientDirectory = CLIENT_PATH, } = {}) => {
7
7
  const mintIgnore = await getMintIgnore(contentDirectory);
8
- const { openApiFiles, asyncApiFiles, invalidSpecFiles } = await categorizeFilePaths(contentDirectory, mintIgnore);
8
+ const docsJsonConfigPath = join(contentDirectory, 'docs.json');
9
+ const explicitOverlays = await readExplicitOverlayConfig((await fse.pathExists(docsJsonConfigPath))
10
+ ? docsJsonConfigPath
11
+ : join(contentDirectory, 'mint.json'));
12
+ const { openApiFiles, asyncApiFiles, invalidSpecFiles, overlayRegistry } = await categorizeFilePaths(contentDirectory, mintIgnore, undefined, undefined, {
13
+ explicitOverlays,
14
+ });
9
15
  let mintConfig;
10
16
  let docsConfig;
11
17
  let loadedMintConfig;
@@ -29,7 +35,7 @@ export const getDocsState = async (onError, { contentDirectory = CMD_EXEC_PATH,
29
35
  throw new Error('No config found');
30
36
  const graphqlResult = await generateGraphqlDivisionsFromDocsConfig(docsConfig, (source) => loadGraphqlSdlSource(source, contentDirectory));
31
37
  const { newDocsConfig: docsConfigWithGraphqlPages, pagesAcc: pagesAccWithGraphqlPages } = graphqlResult;
32
- const { newDocsConfig, pagesAcc: pagesAccWithOpenApiPages, openApiFiles: newOpenApiFiles, flushWrites: flushOpenApiWrites, } = await generateOpenApiDivisions(docsConfigWithGraphqlPages, openApiFiles, clientDirectory, undefined, invalidSpecFiles, pagesAccWithGraphqlPages, true);
38
+ const { newDocsConfig, pagesAcc: pagesAccWithOpenApiPages, openApiFiles: newOpenApiFiles, flushWrites: flushOpenApiWrites, } = await generateOpenApiDivisions(docsConfigWithGraphqlPages, openApiFiles, clientDirectory, undefined, invalidSpecFiles, pagesAccWithGraphqlPages, true, overlayRegistry);
33
39
  const { flushWrites: flushAsyncApiWrites } = await generateAsyncApiDivisions(newDocsConfig, asyncApiFiles, clientDirectory, undefined, pagesAccWithGraphqlPages, false, true);
34
40
  await Promise.all([flushOpenApiWrites(), flushAsyncApiWrites()]);
35
41
  await writeGraphqlArtifacts(graphqlResult, clientDirectory);
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { findAndRemoveImports, hasImports, getFileCategory, validate, stringifyTree, isMintIgnored, replaceVariables, } from '@mintlify/common';
3
- import { createPage, getFileListSync, MintConfigUpdater, DocsConfigUpdater, preparseMdxTree, prebuild, } from '@mintlify/prebuild';
2
+ import { findAndRemoveImports, hasImports, getFileCategory, normalizeOverlayKey, toPosixPath, validate, stringifyTree, isMintIgnored, replaceVariables, } from '@mintlify/common';
3
+ import { createPage, discoverOverlayFiles, getFileListSync, getMintIgnore, MintConfigUpdater, DocsConfigUpdater, preparseMdxTree, prebuild, } from '@mintlify/prebuild';
4
+ import { isOverlayDocument } from '@mintlify/validation';
4
5
  import Chalk from 'chalk';
5
6
  import chokidar from 'chokidar';
6
7
  import { promises as _promises } from 'fs';
@@ -27,6 +28,29 @@ import { getCurrentVariables, getMintIgnoreGlobs, handleParseError, isFileSizeVa
27
28
  const { readFile } = _promises;
28
29
  const frontmatterHashes = new Map();
29
30
  const SLOW_UPDATE_LOG_THRESHOLD_MS = 1000;
31
+ /**
32
+ * Overlay files seen by the watcher, so an edit that makes an overlay unparsable (or
33
+ * removes its `overlay` field) still triggers a rebuild instead of leaving its previous
34
+ * effects in the preview.
35
+ */
36
+ let knownOverlayFiles;
37
+ const getKnownOverlayFiles = async () => {
38
+ if (knownOverlayFiles == undefined) {
39
+ const files = new Set();
40
+ try {
41
+ const mintIgnore = await getMintIgnore(CMD_EXEC_PATH);
42
+ const discovered = await discoverOverlayFiles(CMD_EXEC_PATH, mintIgnore);
43
+ for (const overlay of discovered) {
44
+ files.add(overlay.location);
45
+ }
46
+ }
47
+ catch {
48
+ // Best effort; the set self-corrects as overlay files change.
49
+ }
50
+ knownOverlayFiles = files;
51
+ }
52
+ return knownOverlayFiles;
53
+ };
30
54
  const getCurrentDocsConfig = async () => {
31
55
  const propsDocsJsonPath = pathUtil.join(NEXT_PROPS_PATH, 'docs.json');
32
56
  try {
@@ -215,6 +239,28 @@ const onUnlinkEvent = async (filename, triggerRefresh, options) => {
215
239
  console.error('docs.json has been deleted.');
216
240
  await validateConfigFiles();
217
241
  break;
242
+ case 'potentialYamlOpenApiSpec':
243
+ case 'potentialJsonOpenApiSpec': {
244
+ // A deleted spec or overlay changes the effective OpenAPI documents and any
245
+ // navigation generated from them.
246
+ knownOverlayFiles?.delete(normalizeOverlayKey(toPosixPath(filename)));
247
+ try {
248
+ const { mintConfig, openApiFiles, docsConfig } = await getDocsState(handleParseError);
249
+ if (mintConfig) {
250
+ await MintConfigUpdater.writeConfigFile(mintConfig, CLIENT_PATH);
251
+ }
252
+ await DocsConfigUpdater.writeConfigFile(docsConfig, CLIENT_PATH);
253
+ await updateOpenApiFiles(openApiFiles, suppressParseError);
254
+ await updateGeneratedNav(suppressParseError);
255
+ triggerRefresh();
256
+ }
257
+ catch (err) {
258
+ if (getCurrentErrorLogs().length === 0) {
259
+ console.error(err);
260
+ }
261
+ }
262
+ break;
263
+ }
218
264
  case 'mintIgnore':
219
265
  addChangeLog(_jsx(WarningLog, { message: ".mintignore has been deleted. Rebuilding..." }));
220
266
  try {
@@ -543,21 +589,50 @@ const onUpdateEvent = async (filename, triggerRefresh, options = {}) => {
543
589
  }
544
590
  case 'potentialYamlOpenApiSpec':
545
591
  case 'potentialJsonOpenApiSpec': {
592
+ let raw;
593
+ try {
594
+ raw = yaml.load(await fs.readFile(filePath, 'utf-8'));
595
+ }
596
+ catch {
597
+ raw = undefined;
598
+ }
599
+ const knownOverlays = await getKnownOverlayFiles();
600
+ // chokidar reports platform-native separators; discovery locations are posix.
601
+ const overlayKey = normalizeOverlayKey(toPosixPath(filename));
602
+ if (isOverlayDocument(raw)) {
603
+ // Rebuild all specs so the overlay's targets pick up the change.
604
+ knownOverlays.add(overlayKey);
605
+ await updateOpenApiFiles();
606
+ regenerateNav = true;
607
+ category = 'openApi';
608
+ break;
609
+ }
610
+ if (knownOverlays.has(overlayKey)) {
611
+ // A previously valid overlay is now malformed or no longer an overlay, so its
612
+ // earlier effects must not linger in the generated documents.
613
+ knownOverlays.delete(overlayKey);
614
+ await updateOpenApiFiles();
615
+ regenerateNav = true;
616
+ category = 'openApi';
617
+ break;
618
+ }
619
+ const isOpenApiCandidate = typeof raw === 'object' && raw !== null && 'openapi' in raw;
546
620
  let doc;
547
621
  try {
548
- const file = await fs.readFile(filePath, 'utf-8');
549
- const { schema } = await validate(yaml.load(file));
622
+ const { schema } = await validate(raw);
550
623
  doc = schema;
551
624
  }
552
625
  catch {
553
626
  doc = undefined;
554
627
  }
555
- if (doc) {
556
- await upsertOpenApiFile({
557
- filename: pathUtil.parse(filename).name,
558
- originalFileLocation: '/' + filename,
559
- spec: doc,
560
- });
628
+ if (doc || isOpenApiCandidate) {
629
+ if (doc) {
630
+ await upsertOpenApiFile({
631
+ filename: pathUtil.parse(filename).name,
632
+ originalFileLocation: '/' + filename,
633
+ spec: doc,
634
+ });
635
+ }
561
636
  await updateOpenApiFiles();
562
637
  regenerateNav = true;
563
638
  category = 'openApi';