@mintlify/previewing 4.0.1256 → 4.0.1257

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,5 +1,5 @@
1
1
  import { beforeEach, describe, expect, it } from 'vitest';
2
- import { clearDocsConfigCaches, getDocsConfigApiHash, getDocsConfigNavigationHash, getVariablesHash, hasDocsConfigApiChanged, hasDocsConfigNavigationChanged, hasNavigationApiReference, hasDocsConfigVariablesChanged, updateDocsConfigHashCache, } from '../local-preview/listener/docs-config-cache.js';
2
+ import { clearDocsConfigCaches, getDocsConfigApiHash, getDocsConfigNavigationHash, getVariablesHash, hasDocsConfigApiChanged, hasDocsConfigNavigationChanged, hasNavigationApiReference, hadDocsConfigApiReference, hasDocsConfigVariablesChanged, updateDocsConfigHashCache, } from '../local-preview/listener/docs-config-cache.js';
3
3
  const createDocsConfig = (page) => ({
4
4
  $schema: 'https://mintlify.com/docs.json',
5
5
  name: 'Mintlify',
@@ -33,7 +33,7 @@ describe('docsConfigCache', () => {
33
33
  expect(hasDocsConfigNavigationChanged(getDocsConfigNavigationHash(createDocsConfig('new-page')))).toBe(true);
34
34
  expect(hasDocsConfigVariablesChanged(getVariablesHash({ product: 'Mint' }))).toBe(true);
35
35
  });
36
- it('detects openapi and asyncapi references anywhere in navigation', () => {
36
+ it('detects API references anywhere in navigation', () => {
37
37
  expect(hasNavigationApiReference({
38
38
  groups: [
39
39
  {
@@ -69,6 +69,14 @@ describe('docsConfigCache', () => {
69
69
  },
70
70
  ],
71
71
  })).toBe(true);
72
+ expect(hasNavigationApiReference({
73
+ tabs: [
74
+ {
75
+ tab: 'GraphQL',
76
+ graphql: { source: 'schema.graphql', directory: 'reference' },
77
+ },
78
+ ],
79
+ })).toBe(true);
72
80
  });
73
81
  it('allows plain MDX navigation through the navigation fast path', () => {
74
82
  expect(hasNavigationApiReference({
@@ -80,4 +88,12 @@ describe('docsConfigCache', () => {
80
88
  ],
81
89
  })).toBe(false);
82
90
  });
91
+ it('remembers API references so removing the last generated source triggers cleanup', () => {
92
+ const docsConfig = {
93
+ ...createDocsConfig('raw-page'),
94
+ navigation: { tabs: [{ tab: 'GraphQL', graphql: 'schema.graphql' }] },
95
+ };
96
+ updateDocsConfigHashCache(docsConfig);
97
+ expect(hadDocsConfigApiReference()).toBe(true);
98
+ });
83
99
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ import { access, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { getDocsState } from '../local-preview/listener/getDocsState.js';
5
+ describe('getDocsState', () => {
6
+ let contentDirectory;
7
+ let clientDirectory;
8
+ beforeEach(async () => {
9
+ contentDirectory = await mkdtemp(path.join(os.tmpdir(), 'preview-content-'));
10
+ clientDirectory = await mkdtemp(path.join(os.tmpdir(), 'preview-client-'));
11
+ });
12
+ afterEach(async () => {
13
+ await Promise.all([
14
+ rm(contentDirectory, { recursive: true, force: true }),
15
+ rm(clientDirectory, { recursive: true, force: true }),
16
+ ]);
17
+ });
18
+ it('rejects case-insensitive GraphQL and AsyncAPI collisions before overwriting either page', async () => {
19
+ await writeFile(path.join(contentDirectory, 'schema.graphql'), 'type Query { ping: String }');
20
+ await writeFile(path.join(contentDirectory, 'asyncapi.json'), JSON.stringify({
21
+ asyncapi: '3.0.0',
22
+ info: { title: 'Events', version: '1.0.0' },
23
+ channels: {
24
+ ping: {
25
+ address: 'ping',
26
+ tags: [{ name: 'Queries' }],
27
+ messages: { ping: { payload: { type: 'string' } } },
28
+ },
29
+ },
30
+ operations: {
31
+ ping: {
32
+ action: 'send',
33
+ channel: { $ref: '#/channels/ping' },
34
+ messages: [{ $ref: '#/channels/ping/messages/ping' }],
35
+ },
36
+ },
37
+ }));
38
+ await writeFile(path.join(contentDirectory, 'docs.json'), JSON.stringify({
39
+ theme: 'mint',
40
+ name: 'Preview collision',
41
+ colors: { primary: '#000000' },
42
+ navigation: {
43
+ tabs: [
44
+ {
45
+ tab: 'GraphQL',
46
+ graphql: { source: 'schema.graphql', directory: 'API' },
47
+ },
48
+ {
49
+ tab: 'AsyncAPI',
50
+ asyncapi: { source: 'asyncapi.json', directory: 'api' },
51
+ },
52
+ ],
53
+ },
54
+ }));
55
+ const graphqlPath = path.join(clientDirectory, 'src/_props/API/queries/ping.mdx');
56
+ const asyncApiPath = path.join(clientDirectory, 'src/_props/api/queries/ping.mdx');
57
+ await Promise.all([
58
+ mkdir(path.dirname(graphqlPath), { recursive: true }),
59
+ mkdir(path.dirname(asyncApiPath), { recursive: true }),
60
+ ]);
61
+ await Promise.all([
62
+ writeFile(graphqlPath, 'existing page'),
63
+ writeFile(asyncApiPath, 'existing page'),
64
+ ]);
65
+ await expect(getDocsState(undefined, { contentDirectory, clientDirectory })).rejects.toThrow('Generated GraphQL route');
66
+ await expect(readFile(graphqlPath, 'utf8')).resolves.toBe('existing page');
67
+ await expect(readFile(asyncApiPath, 'utf8')).resolves.toBe('existing page');
68
+ await expect(access(path.join(clientDirectory, 'src/_props/graphql-data.json'))).rejects.toMatchObject({ code: 'ENOENT' });
69
+ });
70
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import path from 'path';
2
+ import { getLocalGraphqlSources, shouldRegenerateGraphqlSource, } from '../local-preview/listener/referencedFiles.js';
3
+ describe('getLocalGraphqlSources', () => {
4
+ it('tracks configured local schema paths regardless of extension', () => {
5
+ expect(getLocalGraphqlSources({
6
+ navigation: {
7
+ tabs: [
8
+ {
9
+ tab: 'API',
10
+ graphql: { source: '/schemas/./nested/../schema.custom', directory: 'api' },
11
+ },
12
+ { tab: 'Remote', graphql: 'HTTPS://example.com/schema.graphql' },
13
+ ],
14
+ },
15
+ })).toEqual([path.normalize('schemas/schema.custom')]);
16
+ });
17
+ it('rebuilds only configured GraphQL sources', () => {
18
+ const configuredSources = new Set([path.normalize('schemas/schema.custom')]);
19
+ expect(shouldRegenerateGraphqlSource('/schemas/./schema.custom', configuredSources)).toBe(true);
20
+ expect(shouldRegenerateGraphqlSource('schema.graphql', configuredSources)).toBe(false);
21
+ expect(shouldRegenerateGraphqlSource('unrelated.txt', configuredSources)).toBe(false);
22
+ });
23
+ });
@@ -3,6 +3,7 @@ export declare const getVariablesHash: (variables: Record<string, string> | unde
3
3
  export declare const getDocsConfigApiHash: (docsConfig: DocsConfig) => string;
4
4
  export declare const getDocsConfigNavigationHash: (docsConfig: DocsConfig) => string;
5
5
  export declare const updateDocsConfigHashCache: (docsConfig: DocsConfig) => void;
6
+ export declare const hadDocsConfigApiReference: () => boolean;
6
7
  export declare const hasNavigationApiReference: (value: unknown) => boolean;
7
8
  export declare const hasDocsConfigApiChanged: (newApiHash: string) => boolean;
8
9
  export declare const hasDocsConfigNavigationChanged: (newNavigationHash: string) => boolean;
@@ -1,6 +1,7 @@
1
1
  let docsConfigVariablesHash;
2
2
  let docsConfigApiHash;
3
3
  let docsConfigNavigationHash;
4
+ let docsConfigHadApiReference = false;
4
5
  const getJsonHash = (value) => {
5
6
  return JSON.stringify(value ?? {});
6
7
  };
@@ -17,13 +18,17 @@ export const updateDocsConfigHashCache = (docsConfig) => {
17
18
  docsConfigVariablesHash = getVariablesHash(docsConfig.variables);
18
19
  docsConfigApiHash = getDocsConfigApiHash(docsConfig);
19
20
  docsConfigNavigationHash = getDocsConfigNavigationHash(docsConfig);
21
+ docsConfigHadApiReference =
22
+ docsConfig.api != null || hasNavigationApiReference(docsConfig.navigation);
20
23
  };
24
+ export const hadDocsConfigApiReference = () => docsConfigHadApiReference;
21
25
  export const hasNavigationApiReference = (value) => {
22
26
  if (value == null || typeof value !== 'object') {
23
27
  return false;
24
28
  }
25
29
  if (Object.prototype.hasOwnProperty.call(value, 'openapi') ||
26
- Object.prototype.hasOwnProperty.call(value, 'asyncapi')) {
30
+ Object.prototype.hasOwnProperty.call(value, 'asyncapi') ||
31
+ Object.prototype.hasOwnProperty.call(value, 'graphql')) {
27
32
  return true;
28
33
  }
29
34
  return Object.values(value).some(hasNavigationApiReference);
@@ -41,4 +46,5 @@ export const clearDocsConfigCaches = () => {
41
46
  docsConfigVariablesHash = undefined;
42
47
  docsConfigApiHash = undefined;
43
48
  docsConfigNavigationHash = undefined;
49
+ docsConfigHadApiReference = false;
44
50
  };
@@ -1,6 +1,9 @@
1
1
  import type { DecoratedNavigationPage, MintConfig, OpenApiFile } from '@mintlify/models';
2
2
  import { DocsConfig } from '@mintlify/validation';
3
- export declare const getDocsState: (onError?: (message: string) => void) => Promise<{
3
+ export declare const getDocsState: (onError?: (message: string) => void, { contentDirectory, clientDirectory, }?: {
4
+ contentDirectory?: string;
5
+ clientDirectory?: string;
6
+ }) => Promise<{
4
7
  mintConfig?: MintConfig;
5
8
  pagesAcc: Record<string, DecoratedNavigationPage>;
6
9
  openApiFiles: OpenApiFile[];
@@ -1,31 +1,43 @@
1
- import { generateOpenApiAnchorsOrTabs, categorizeFilePaths, generateOpenApiDivisions, getMintIgnore, MintConfigUpdater, DocsConfigUpdater, warnInvalidSpecFiles, } from '@mintlify/prebuild';
1
+ import { generateOpenApiAnchorsOrTabs, categorizeFilePaths, generateOpenApiDivisions, generateAsyncApiDivisions, generateGraphqlDivisionsFromDocsConfig, getMintIgnore, MintConfigUpdater, DocsConfigUpdater, 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
- export const getDocsState = async (onError) => {
7
- const mintIgnore = await getMintIgnore(CMD_EXEC_PATH);
8
- const { openApiFiles, invalidSpecFiles } = await categorizeFilePaths(CMD_EXEC_PATH, mintIgnore);
6
+ export const getDocsState = async (onError, { contentDirectory = CMD_EXEC_PATH, clientDirectory = CLIENT_PATH, } = {}) => {
7
+ const mintIgnore = await getMintIgnore(contentDirectory);
8
+ const { openApiFiles, asyncApiFiles, invalidSpecFiles } = await categorizeFilePaths(contentDirectory, mintIgnore);
9
+ let mintConfig;
10
+ let docsConfig;
11
+ let loadedMintConfig;
9
12
  try {
10
- const mintConfig = await MintConfigUpdater.getConfig(join(CMD_EXEC_PATH, 'mint.json'), false, CMD_EXEC_PATH, onError);
11
- const docsConfig = upgradeToDocsConfig(mintConfig);
12
- const { mintConfig: newMintConfig } = await generateOpenApiAnchorsOrTabs(mintConfig, openApiFiles, CLIENT_PATH, undefined, invalidSpecFiles);
13
- const { newDocsConfig, pagesAcc, openApiFiles: newOpenApiFiles, } = await generateOpenApiDivisions(docsConfig, openApiFiles, CLIENT_PATH, undefined, invalidSpecFiles);
14
- warnInvalidSpecFiles(invalidSpecFiles);
15
- return {
16
- mintConfig: newMintConfig,
17
- pagesAcc,
18
- openApiFiles: newOpenApiFiles,
19
- docsConfig: newDocsConfig,
20
- };
13
+ loadedMintConfig = await MintConfigUpdater.getConfig(join(contentDirectory, 'mint.json'), false, contentDirectory, onError);
21
14
  }
22
15
  catch {
23
- const docsJsonPath = join(CMD_EXEC_PATH, 'docs.json');
16
+ const docsJsonPath = join(contentDirectory, 'docs.json');
24
17
  if (!(await fse.pathExists(docsJsonPath)))
25
18
  throw new Error('No config found');
26
- const docsConfig = await DocsConfigUpdater.getConfig(docsJsonPath, false, CMD_EXEC_PATH, onError, { allowSourceRefs: true });
27
- const { newDocsConfig, pagesAcc, openApiFiles: newOpenApiFiles, } = await generateOpenApiDivisions(docsConfig, openApiFiles, CLIENT_PATH, undefined, invalidSpecFiles);
28
- warnInvalidSpecFiles(invalidSpecFiles);
29
- return { pagesAcc, openApiFiles: newOpenApiFiles, docsConfig: newDocsConfig };
19
+ docsConfig = await DocsConfigUpdater.getConfig(docsJsonPath, false, contentDirectory, onError, {
20
+ allowSourceRefs: true,
21
+ });
30
22
  }
23
+ if (loadedMintConfig) {
24
+ docsConfig = upgradeToDocsConfig(loadedMintConfig);
25
+ const result = await generateOpenApiAnchorsOrTabs(loadedMintConfig, openApiFiles, clientDirectory, undefined, invalidSpecFiles);
26
+ mintConfig = result.mintConfig;
27
+ }
28
+ if (!docsConfig)
29
+ throw new Error('No config found');
30
+ const graphqlResult = await generateGraphqlDivisionsFromDocsConfig(docsConfig, (source) => loadGraphqlSdlSource(source, contentDirectory));
31
+ const { newDocsConfig: docsConfigWithGraphqlPages, pagesAcc: pagesAccWithGraphqlPages } = graphqlResult;
32
+ const { newDocsConfig, pagesAcc: pagesAccWithOpenApiPages, openApiFiles: newOpenApiFiles, flushWrites: flushOpenApiWrites, } = await generateOpenApiDivisions(docsConfigWithGraphqlPages, openApiFiles, clientDirectory, undefined, invalidSpecFiles, pagesAccWithGraphqlPages, true);
33
+ const { flushWrites: flushAsyncApiWrites } = await generateAsyncApiDivisions(newDocsConfig, asyncApiFiles, clientDirectory, undefined, pagesAccWithGraphqlPages, false, true);
34
+ await Promise.all([flushOpenApiWrites(), flushAsyncApiWrites()]);
35
+ await writeGraphqlArtifacts(graphqlResult, clientDirectory);
36
+ warnInvalidSpecFiles(invalidSpecFiles);
37
+ return {
38
+ mintConfig,
39
+ pagesAcc: { ...pagesAccWithOpenApiPages, ...pagesAccWithGraphqlPages },
40
+ openApiFiles: newOpenApiFiles,
41
+ docsConfig: newDocsConfig,
42
+ };
31
43
  };
@@ -2,7 +2,9 @@ import { initializeImportCache } from './importCache.js';
2
2
  type LocalPreviewOptions = {
3
3
  localSchema?: boolean;
4
4
  groups?: string[];
5
+ disableOpenApi?: boolean;
5
6
  allowSourceRefs?: boolean;
7
+ lazyPages?: boolean;
6
8
  };
7
9
  declare const listener: (triggerRefresh: () => void, options?: LocalPreviewOptions, gate?: Promise<void>) => void;
8
10
  declare const initializeFrontmatterHashCache: () => Promise<void>;
@@ -12,13 +12,13 @@ import { CMD_EXEC_PATH, NEXT_PROPS_PATH, NEXT_PUBLIC_PATH, CLIENT_PATH } from '.
12
12
  import { addChangeLog, addErrorLog, clearErrorLogs, getCurrentErrorLogs, } from '../../logging-state.js';
13
13
  import { AddedLog, DeletedLog, EditedLog, WarningLog, InfoLog, ErrorLog } from '../../logs.js';
14
14
  import { reportPageCompileError, reportPageCompileSuccess } from '../on-demand-page.js';
15
- import { clearDocsConfigCaches, getDocsConfigApiHash, getDocsConfigNavigationHash, getVariablesHash, hasDocsConfigApiChanged, hasDocsConfigNavigationChanged, hasNavigationApiReference, hasDocsConfigVariablesChanged, updateDocsConfigHashCache, } from './docs-config-cache.js';
15
+ import { clearDocsConfigCaches, getDocsConfigApiHash, getDocsConfigNavigationHash, getVariablesHash, hasDocsConfigApiChanged, hasDocsConfigNavigationChanged, hasNavigationApiReference, hadDocsConfigApiReference, hasDocsConfigVariablesChanged, updateDocsConfigHashCache, } from './docs-config-cache.js';
16
16
  import { generateDependentSnippets } from './generateDependentSnippets.js';
17
17
  import { generatePagesWithImports } from './generatePagesWithImports.js';
18
18
  import { getDocsState } from './getDocsState.js';
19
19
  import { initializeImportCache, updateImportCacheForFile, removeFromImportCache, getImportedFilesFromCache, syncImportedFileLocations, } from './importCache.js';
20
20
  import { clearPageMetadataCache, removePageMetadataCacheEntryForFile, upsertPageMetadataCacheEntry, upsertPageMetadataCacheEntryForFile, } from './page-metadata-cache.js';
21
- import { hasTrackedReferencedFile, refreshTrackedReferencedFiles } from './referencedFiles.js';
21
+ import { hasTrackedReferencedFile, refreshTrackedReferencedFiles, shouldRegenerateGraphqlSource, } from './referencedFiles.js';
22
22
  import { regenerateAllSnippets } from './regenerateAllSnippets.js';
23
23
  import { resolveImportsFromImportClosure } from './resolve-imports-from-import-closure.js';
24
24
  import { resolvePageImports } from './resolve-page-imports.js';
@@ -158,6 +158,11 @@ const onUnlinkEvent = async (filename, triggerRefresh, options) => {
158
158
  if (potentialCategory === 'page') {
159
159
  reportPageCompileSuccess(filename);
160
160
  }
161
+ if (shouldRegenerateGraphqlSource(filename)) {
162
+ await rebuildGraphqlSchema(triggerRefresh, options);
163
+ addChangeLog(_jsx(DeletedLog, { filename: filename }));
164
+ return;
165
+ }
161
166
  if (hasTrackedReferencedFile(filename)) {
162
167
  try {
163
168
  const { mintConfig, openApiFiles, docsConfig } = await getDocsState(handleParseError);
@@ -308,6 +313,14 @@ const initializeDocsConfigHashCache = async () => {
308
313
  }
309
314
  catch { }
310
315
  };
316
+ const rebuildGraphqlSchema = async (triggerRefresh, options) => {
317
+ const prebuildResult = await prebuild(CMD_EXEC_PATH, options);
318
+ await initializeImportCache(CMD_EXEC_PATH, prebuildResult?.fileImportsMap);
319
+ await initializeFrontmatterHashCache();
320
+ await initializeDocsConfigHashCache();
321
+ await refreshTrackedReferencedFiles();
322
+ triggerRefresh();
323
+ };
311
324
  /**
312
325
  * This function is called when a file is added or changed
313
326
  * @param filename
@@ -316,6 +329,10 @@ const initializeDocsConfigHashCache = async () => {
316
329
  const onUpdateEvent = async (filename, triggerRefresh, options = {}) => {
317
330
  clearErrorLogs();
318
331
  const filePath = pathUtil.join(CMD_EXEC_PATH, filename);
332
+ if (shouldRegenerateGraphqlSource(filename)) {
333
+ await rebuildGraphqlSchema(triggerRefresh, options);
334
+ return null;
335
+ }
319
336
  const importChanges = await updateImportCacheForFile(CMD_EXEC_PATH, filename);
320
337
  await syncImportedFileLocations(importChanges);
321
338
  const importedFiles = getImportedFilesFromCache();
@@ -431,8 +448,13 @@ const onUpdateEvent = async (filename, triggerRefresh, options = {}) => {
431
448
  const navigationChanged = hasDocsConfigNavigationChanged(newNavigationHash);
432
449
  const newVariablesHash = getVariablesHash(docsConfig.variables);
433
450
  const variablesChanged = hasDocsConfigVariablesChanged(newVariablesHash);
434
- const shouldUseNavigationFastPath = navigationChanged && !apiChanged && !hasDocsConfigApiRoutes(docsConfig);
435
- const shouldRegenerateGeneratedData = apiChanged || (navigationChanged && hasDocsConfigApiRoutes(docsConfig));
451
+ const shouldUseNavigationFastPath = navigationChanged &&
452
+ !apiChanged &&
453
+ !hasDocsConfigApiRoutes(docsConfig) &&
454
+ !hadDocsConfigApiReference();
455
+ const shouldRegenerateGeneratedData = apiChanged ||
456
+ (navigationChanged &&
457
+ (hasDocsConfigApiRoutes(docsConfig) || hadDocsConfigApiReference()));
436
458
  await refreshTrackedReferencedFiles();
437
459
  if (shouldUseNavigationFastPath) {
438
460
  // Plain MDX navigation changed without API changes: regenerate
@@ -484,8 +506,8 @@ const onUpdateEvent = async (filename, triggerRefresh, options = {}) => {
484
506
  // mint.json: preserve the original full-rebuild behavior.
485
507
  regenerateNav = true;
486
508
  try {
487
- const { mintConfig, openApiFiles, docsConfig } = await getDocsState(handleParseError);
488
509
  await refreshTrackedReferencedFiles();
510
+ const { mintConfig, openApiFiles, docsConfig } = await getDocsState(handleParseError);
489
511
  if (mintConfig) {
490
512
  await MintConfigUpdater.writeConfigFile(mintConfig, CLIENT_PATH);
491
513
  }
@@ -1,2 +1,4 @@
1
+ export declare const getLocalGraphqlSources: (value: unknown) => string[];
1
2
  export declare const refreshTrackedReferencedFiles: () => Promise<void>;
2
3
  export declare const hasTrackedReferencedFile: (filePath: string) => boolean;
4
+ export declare const shouldRegenerateGraphqlSource: (filePath: string, configuredSources?: ReadonlySet<string>) => boolean;
@@ -1,21 +1,50 @@
1
- import { getConfigPath, resolveFileRefs } from '@mintlify/prebuild';
1
+ import { normalizeRelativePath } from '@mintlify/common';
2
+ import { getConfigPath, isRemoteGraphqlSource, resolveFileRefs } from '@mintlify/prebuild';
2
3
  import { readFile } from 'fs/promises';
4
+ import path from 'path';
3
5
  import { CMD_EXEC_PATH } from '../../constants.js';
4
6
  let trackedReferencedFiles = new Set();
7
+ let trackedGraphqlSources = new Set();
8
+ const normalizeTrackedPath = (filePath) => path.normalize(normalizeRelativePath(filePath));
9
+ export const getLocalGraphqlSources = (value) => {
10
+ if (Array.isArray(value))
11
+ return value.flatMap(getLocalGraphqlSources);
12
+ if (value == null || typeof value !== 'object')
13
+ return [];
14
+ const node = value;
15
+ const graphql = node.graphql;
16
+ const source = typeof graphql === 'string'
17
+ ? graphql
18
+ : graphql != null && typeof graphql === 'object' && 'source' in graphql
19
+ ? graphql.source
20
+ : undefined;
21
+ const sources = typeof source === 'string' && !isRemoteGraphqlSource(source)
22
+ ? [normalizeTrackedPath(source)]
23
+ : [];
24
+ return [...sources, ...Object.values(node).flatMap(getLocalGraphqlSources)];
25
+ };
5
26
  export const refreshTrackedReferencedFiles = async () => {
6
27
  try {
7
28
  const configPath = (await getConfigPath(CMD_EXEC_PATH, 'docs')) ?? (await getConfigPath(CMD_EXEC_PATH, 'mint'));
8
29
  if (!configPath) {
9
30
  trackedReferencedFiles = new Set();
31
+ trackedGraphqlSources = new Set();
10
32
  return;
11
33
  }
12
34
  const content = await readFile(configPath, 'utf-8');
13
35
  const parsed = JSON.parse(content);
14
- const { referencedFiles } = await resolveFileRefs(parsed, CMD_EXEC_PATH);
15
- trackedReferencedFiles = new Set(referencedFiles);
36
+ const { referencedFiles, resolved } = await resolveFileRefs(parsed, CMD_EXEC_PATH);
37
+ const graphqlSources = getLocalGraphqlSources(resolved);
38
+ trackedReferencedFiles = new Set([
39
+ ...referencedFiles.map(normalizeTrackedPath),
40
+ ...graphqlSources,
41
+ ]);
42
+ trackedGraphqlSources = new Set(graphqlSources);
16
43
  }
17
44
  catch {
18
45
  trackedReferencedFiles = new Set();
46
+ trackedGraphqlSources = new Set();
19
47
  }
20
48
  };
21
- export const hasTrackedReferencedFile = (filePath) => trackedReferencedFiles.has(filePath);
49
+ export const hasTrackedReferencedFile = (filePath) => trackedReferencedFiles.has(normalizeTrackedPath(filePath));
50
+ export const shouldRegenerateGraphqlSource = (filePath, configuredSources = trackedGraphqlSources) => configuredSources.has(normalizeTrackedPath(filePath));
@@ -173,7 +173,13 @@ export const run = async (argv) => {
173
173
  releaseWatcherGate = resolve;
174
174
  });
175
175
  addDevTimingLog('watching for file changes');
176
- listener(onChange, {}, watcherGate);
176
+ listener(onChange, {
177
+ localSchema: argv['local-schema'],
178
+ groups: argv.groups,
179
+ disableOpenApi: argv.disableOpenapi,
180
+ allowSourceRefs: true,
181
+ lazyPages: true,
182
+ }, watcherGate);
177
183
  await timeDev('initialize import cache', () => initializeImportCache(CMD_EXEC_PATH, argv.fileImportsMap));
178
184
  markOnDemandPagesReady();
179
185
  await timeDev('initialize frontmatter cache', () => initializeFrontmatterHashCache());