@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
123 lines (111 loc) • 3.97 kB
JavaScript
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createLoadServerPageIndex } from "../loadServerPageIndex/loadServerPageIndex.mjs";
import { parseCreateFactoryCall } from "../parseCreateFactoryCall/parseCreateFactoryCall.mjs";
/**
* Options for creating a loadServerSitemap function
*/
/**
* Function type for loading sitemap data from a sitemap index file URL
*/
/**
* Creates the default Orama schema for search indexing.
* See: <https://docs.orama.com/docs/orama-js/usage/create#schema-properties-and-types>
*/
export function createSitemapSchema() {
return {
slug: 'string',
path: 'string',
title: 'string',
description: 'string',
sections: 'string[]',
subsections: 'string[]',
keywords: 'string[]'
};
}
/**
* Default loadServerSitemap function that loads sitemap data from a sitemap index file.
* This function parses the sitemap index file to find createSitemap calls and resolves
* the page index paths from the imports.
*/
export const loadServerSitemap = createLoadServerSitemap();
/**
* Creates a loadServerSitemap function with custom options.
*
* This factory function creates a LoadServerSitemap implementation that:
* 1. Parses the sitemap index file to find createSitemap calls with page imports
* 2. Resolves all page index paths from the imports
* 3. Loads each page index using loadServerPageIndex
* 4. Returns a Sitemap object with schema and page data
*
* @param options - Configuration options for the loader
* @returns LoadServerSitemap function that takes a file URL and returns `Promise<Sitemap>`
*/
export function createLoadServerSitemap(options = {}) {
return async function loadSitemap(url) {
// Convert file:// URL to proper file system path for reading the file
// Using fileURLToPath handles Windows drive letters correctly (e.g., file:///C:/... → C:\...)
const filePath = url.startsWith('file://') ? fileURLToPath(url) : url;
// Determine root context from file path if not provided
const rootContext = options.rootContext ?? path.dirname(filePath);
// Create page index loader with root context
const loadPageIndex = createLoadServerPageIndex({
rootContext
});
// Read the source file to find createSitemap calls
const source = await readFile(filePath, 'utf-8');
// Parse the source to find createSitemap call with page imports
const sitemapCall = await parseCreateFactoryCall(source, filePath);
if (!sitemapCall || !sitemapCall.variants) {
// Return empty sitemap if no createSitemap call found
return {
schema: createSitemapSchema(),
data: {}
};
}
// Process all page index files in parallel
const entries = Object.entries(sitemapCall.variants);
const results = await Promise.all(entries.map(async ([key, importPath]) => {
try {
const metadata = await loadPageIndex(importPath);
return {
key,
metadata,
error: null
};
} catch (error) {
return {
key,
metadata: null,
error: error instanceof Error ? error : new Error(String(error))
};
}
}));
// Collect results and errors
const sitemapData = {};
const errors = [];
for (const result of results) {
if (result.error) {
errors.push({
key: result.key,
error: result.error
});
} else if (result.metadata) {
sitemapData[result.key] = result.metadata;
}
}
// Throw if any pages failed to load
if (errors.length > 0) {
const errorMessages = errors.map(({
key,
error
}) => ` ${key}: ${error.message}`).join('\n');
throw new Error(`Failed to load ${errors.length} page index(es):\n${errorMessages}`);
}
return {
schema: createSitemapSchema(),
data: sitemapData
};
};
}