@mintlify/link-rot 3.0.819 → 3.0.821

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/dist/graph.d.ts CHANGED
@@ -67,9 +67,11 @@ export declare class Graph {
67
67
  private fileResolutionMap;
68
68
  private redirectMap;
69
69
  private mintIgnoreGlobs;
70
+ private virtualNodes;
70
71
  constructor(baseDir: string, mintIgnoreGlobs?: string[]);
71
72
  addNode(label: string): Node;
72
73
  addNodes(labels: string[]): void;
74
+ addVirtualNodes(labels: string[]): void;
73
75
  setRedirects(redirects: {
74
76
  source: string;
75
77
  destination: string;
package/dist/graph.js CHANGED
@@ -214,6 +214,7 @@ export class Graph {
214
214
  this.fileResolutionMap = new Map();
215
215
  this.redirectMap = new Map();
216
216
  this.mintIgnoreGlobs = [];
217
+ this.virtualNodes = new Set();
217
218
  this.baseDir = resolve(baseDir);
218
219
  this.mintIgnoreGlobs = mintIgnoreGlobs;
219
220
  }
@@ -228,6 +229,12 @@ export class Graph {
228
229
  this.addNode(label);
229
230
  }
230
231
  }
232
+ addVirtualNodes(labels) {
233
+ for (const label of labels) {
234
+ this.addNode(label);
235
+ this.virtualNodes.add(new Node(label).toString());
236
+ }
237
+ }
231
238
  setRedirects(redirects) {
232
239
  for (const redirect of redirects) {
233
240
  this.redirectMap.set(normalizePath(redirect.source), normalizePath(redirect.destination));
@@ -343,7 +350,8 @@ export class Graph {
343
350
  if (path.pathType === PathType.INTERNAL) {
344
351
  const pathString = path.toString();
345
352
  const resolvedFiles = this.fileResolutionMap.get(pathString);
346
- const hasExistingFile = resolvedFiles && [...resolvedFiles].some((file) => nodeSet.has(file));
353
+ const hasExistingFile = (resolvedFiles && [...resolvedFiles].some((file) => nodeSet.has(file))) ||
354
+ this.virtualNodes.has(pathString);
347
355
  let redirectDestination = this.redirectMap.get(pathString);
348
356
  let hasValidRedirect = redirectDestination &&
349
357
  (nodeSet.has(`${redirectDestination}.mdx`) || nodeSet.has(redirectDestination));
@@ -14,6 +14,7 @@ import path from 'path';
14
14
  import { visit } from 'unist-util-visit';
15
15
  import { Graph, Wrapper } from '../graph.js';
16
16
  import { getLinkPaths, getPagePaths } from '../prebuild.js';
17
+ import { getOpenApiPagePaths } from './getOpenApiPagePaths.js';
17
18
  import { getRedirects } from './getRedirects.js';
18
19
  export const decorateGraphNodeFromPageContent = (graphNode, content) => __awaiter(void 0, void 0, void 0, function* () {
19
20
  const visitLinks = () => {
@@ -69,6 +70,14 @@ export const getBrokenInternalLinks = (repoPath) => __awaiter(void 0, void 0, vo
69
70
  graph.setRedirects(redirectMappings);
70
71
  // add nodes for every link alias in the project
71
72
  graph.addAliasNodes();
73
+ // add virtual nodes for OpenAPI-generated pages
74
+ try {
75
+ const openApiPagePaths = yield getOpenApiPagePaths(baseDir);
76
+ graph.addVirtualNodes(openApiPagePaths);
77
+ }
78
+ catch (err) {
79
+ console.warn(`Warning: Failed to extract OpenAPI page paths: ${err}`);
80
+ }
72
81
  const allSitePages = getPagePaths(baseDir);
73
82
  const sitePages = allSitePages.filter((file) => !isMintIgnored(file, mintIgnoreGlobs));
74
83
  yield Promise.all(sitePages.map((filePath) => __awaiter(void 0, void 0, void 0, function* () {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Extract virtual page paths that would be generated from OpenAPI specs.
3
+ * These pages don't exist as files but are valid link targets.
4
+ *
5
+ * Note: Uses api.openapi.directory from docs.json, or falls back to 'api-reference'.
6
+ * Per-navigation directory configs are not currently supported.
7
+ */
8
+ export declare const getOpenApiPagePaths: (baseDir: string) => Promise<string[]>;
@@ -0,0 +1,68 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { categorizeFilePaths } from '@mintlify/prebuild';
11
+ import { generateOpenApiPagesForDocsConfig } from '@mintlify/scraping';
12
+ import { validateDocsConfig } from '@mintlify/validation';
13
+ import fs from 'fs-extra';
14
+ import path from 'path';
15
+ const DEFAULT_OUTPUT_DIR = 'api-reference';
16
+ const getOpenApiDirectory = (baseDir) => __awaiter(void 0, void 0, void 0, function* () {
17
+ var _a;
18
+ const docsJsonPath = path.join(baseDir, 'docs.json');
19
+ if (!fs.existsSync(docsJsonPath))
20
+ return DEFAULT_OUTPUT_DIR;
21
+ try {
22
+ const docsJson = yield fs.readJSON(docsJsonPath);
23
+ const result = validateDocsConfig(docsJson);
24
+ if (!result.success)
25
+ return DEFAULT_OUTPUT_DIR;
26
+ const openapi = (_a = result.data.api) === null || _a === void 0 ? void 0 : _a.openapi;
27
+ if (typeof openapi === 'object' && 'directory' in openapi && openapi.directory) {
28
+ return openapi.directory;
29
+ }
30
+ }
31
+ catch (_b) {
32
+ throw new Error('Unable to parse OpenAPI directory from docs.json');
33
+ }
34
+ return DEFAULT_OUTPUT_DIR;
35
+ });
36
+ /**
37
+ * Extract virtual page paths that would be generated from OpenAPI specs.
38
+ * These pages don't exist as files but are valid link targets.
39
+ *
40
+ * Note: Uses api.openapi.directory from docs.json, or falls back to 'api-reference'.
41
+ * Per-navigation directory configs are not currently supported.
42
+ */
43
+ export const getOpenApiPagePaths = (baseDir) => __awaiter(void 0, void 0, void 0, function* () {
44
+ const pagePaths = [];
45
+ try {
46
+ const [{ openApiFiles }, outDir] = yield Promise.all([
47
+ categorizeFilePaths(baseDir),
48
+ getOpenApiDirectory(baseDir),
49
+ ]);
50
+ for (const openApiFile of openApiFiles) {
51
+ try {
52
+ const { pagesAcc } = yield generateOpenApiPagesForDocsConfig(openApiFile.spec, {
53
+ openApiFilePath: openApiFile.originalFileLocation,
54
+ writeFiles: false,
55
+ outDir,
56
+ });
57
+ pagePaths.push(...Object.keys(pagesAcc));
58
+ }
59
+ catch (err) {
60
+ console.warn(`Warning: Failed to extract pages from OpenAPI spec ${openApiFile.originalFileLocation}: ${err}`);
61
+ }
62
+ }
63
+ }
64
+ catch (err) {
65
+ console.warn(`Warning: Failed to categorize files for OpenAPI extraction: ${err}`);
66
+ }
67
+ return [...new Set(pagePaths)];
68
+ });