@onruntime/next-sitemap 0.6.2 → 0.7.0

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/app/index.js CHANGED
@@ -1,9 +1,168 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { createJiti } from 'jiti';
4
- import stripJsonComments from 'strip-json-comments';
1
+ import { existsSync, readdirSync } from 'fs';
2
+ import { dirname, join, isAbsolute, relative, delimiter } from 'path';
3
+ import * as childProcess from 'child_process';
4
+ import { fileURLToPath } from 'url';
5
5
 
6
6
  // src/app/index.ts
7
+ var NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
8
+ var spawnProcess = childProcess.spawn;
9
+ var __dirname$1 = dirname(fileURLToPath(import.meta.url));
10
+ var paramsCache = /* @__PURE__ */ new Map();
11
+ var isDev = process.env.NODE_ENV === "development";
12
+ async function executeWorker(directory, fileKey, debug) {
13
+ const absolutePath = join(directory, fileKey.replace("./", ""));
14
+ const projectRoot = process.cwd();
15
+ const distRoot = join(__dirname$1, "..");
16
+ const workerPath = join(distRoot, "worker.cjs");
17
+ const loaderPath = join(distRoot, "loader.js");
18
+ if (debug) {
19
+ console.log(`[next-sitemap] Worker path: ${workerPath}`);
20
+ console.log(`[next-sitemap] Worker exists: ${existsSync(workerPath)}`);
21
+ console.log(`[next-sitemap] Loader path: ${loaderPath}`);
22
+ console.log(`[next-sitemap] Loader exists: ${existsSync(loaderPath)}`);
23
+ }
24
+ return new Promise((resolve) => {
25
+ const nodePath = [
26
+ join(projectRoot, "node_modules"),
27
+ join(__dirname$1, "..", "node_modules")
28
+ ].join(delimiter);
29
+ const importFlag = ["--import", loaderPath];
30
+ const args = [...importFlag, workerPath, absolutePath, projectRoot];
31
+ const child = spawnProcess("node", args, {
32
+ cwd: projectRoot,
33
+ stdio: ["ignore", "pipe", "pipe"],
34
+ env: { ...process.env, NODE_PATH: nodePath }
35
+ });
36
+ let stdout = "";
37
+ let stderr = "";
38
+ child.stdout.on("data", (data) => {
39
+ stdout += data.toString();
40
+ });
41
+ child.stderr.on("data", (data) => {
42
+ stderr += data.toString();
43
+ });
44
+ child.on("close", (code) => {
45
+ if (debug && stderr) {
46
+ console.warn(`[next-sitemap] Worker stderr: ${stderr}`);
47
+ }
48
+ if (code !== 0 && code !== null) {
49
+ if (debug) console.warn(`[next-sitemap] Worker exited with code ${code}`);
50
+ resolve(null);
51
+ return;
52
+ }
53
+ try {
54
+ const lines = stdout.trim().split("\n");
55
+ const result = JSON.parse(lines[lines.length - 1]);
56
+ if (result.success) {
57
+ resolve(result.params);
58
+ } else {
59
+ if (result.error !== NO_STATIC_PARAMS && debug) {
60
+ console.warn(`[next-sitemap] Worker error: ${result.error}`);
61
+ }
62
+ resolve(null);
63
+ }
64
+ } catch {
65
+ if (debug) console.warn(`[next-sitemap] Failed to parse worker output: ${stdout}`);
66
+ resolve(null);
67
+ }
68
+ });
69
+ child.on("error", (err) => {
70
+ if (debug) console.warn(`[next-sitemap] Failed to spawn worker: ${err.message}`);
71
+ resolve(null);
72
+ });
73
+ });
74
+ }
75
+ async function getRouteParams(route, directory, debug) {
76
+ const cacheKey = route.fileKey;
77
+ if (paramsCache.has(cacheKey)) {
78
+ return paramsCache.get(cacheKey);
79
+ }
80
+ if (debug) {
81
+ console.log(`[next-sitemap] ${route.pathname}: executing static params via worker`);
82
+ }
83
+ const params = await executeWorker(directory, route.fileKey, debug);
84
+ paramsCache.set(cacheKey, params);
85
+ if (debug && params) {
86
+ console.log(`[next-sitemap] ${route.pathname}: got ${params.length} params`);
87
+ }
88
+ return params;
89
+ }
90
+ async function generateAllPaths(routes, directory, debug) {
91
+ const staticPaths = ["/"];
92
+ const dynamicRoutes = [];
93
+ for (const route of routes) {
94
+ if (route.dynamicSegments.length === 0) {
95
+ if (route.pathname !== "/") {
96
+ staticPaths.push(route.pathname);
97
+ }
98
+ } else {
99
+ dynamicRoutes.push(route);
100
+ }
101
+ }
102
+ const startTime = isDev ? Date.now() : 0;
103
+ if (isDev && dynamicRoutes.length > 0) {
104
+ console.log(`[next-sitemap] Generating sitemap for ${dynamicRoutes.length} dynamic routes (dev only, instant in production)...`);
105
+ }
106
+ const dynamicResults = await Promise.all(
107
+ dynamicRoutes.map(async (route) => {
108
+ const params = await getRouteParams(route, directory, debug);
109
+ if (!params || params.length === 0) {
110
+ if (debug) {
111
+ console.warn(`[next-sitemap] Skipping dynamic route ${route.pathname}: no static params or empty result.`);
112
+ }
113
+ return [];
114
+ }
115
+ const paths = [];
116
+ for (const param of params) {
117
+ let path = route.pathname;
118
+ let valid = true;
119
+ for (const segment of route.dynamicSegments) {
120
+ const value = param[segment];
121
+ if (value === void 0) {
122
+ if (debug) {
123
+ console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
124
+ }
125
+ valid = false;
126
+ break;
127
+ }
128
+ path = path.replace(`[${segment}]`, value);
129
+ }
130
+ if (valid) paths.push(path);
131
+ }
132
+ return paths;
133
+ })
134
+ );
135
+ const allPaths = new Set(staticPaths);
136
+ for (const paths of dynamicResults) {
137
+ for (const path of paths) {
138
+ allPaths.add(path);
139
+ }
140
+ }
141
+ if (isDev && dynamicRoutes.length > 0) {
142
+ const elapsed = Date.now() - startTime;
143
+ console.log(`[next-sitemap] Done! Found ${allPaths.size} total URLs in ${elapsed}ms.`);
144
+ }
145
+ return Array.from(allPaths);
146
+ }
147
+ function pathsToEntries(paths, config) {
148
+ const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
149
+ return paths.filter((pathname) => !shouldExclude(pathname, exclude)).map((pathname) => {
150
+ const entry = {
151
+ url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
152
+ lastModified: /* @__PURE__ */ new Date(),
153
+ changeFrequency: getChangeFreq(pathname, changeFreq),
154
+ priority: getPriority(pathname, priority)
155
+ };
156
+ if (locales.length > 0) {
157
+ entry.alternates = {
158
+ languages: Object.fromEntries(
159
+ locales.map((locale) => [locale, buildUrl(baseUrl, pathname, locale, defaultLocale)])
160
+ )
161
+ };
162
+ }
163
+ return entry;
164
+ });
165
+ }
7
166
 
8
167
  // src/index.ts
9
168
  function calculateDepthPriority(pathname) {
@@ -106,17 +265,16 @@ ${allEntries}
106
265
  }
107
266
 
108
267
  // src/app/index.ts
109
- var joinPath = (...segments) => path.join(...segments);
110
268
  function findPageFiles(dir, baseDir = dir) {
111
269
  const files = [];
112
270
  try {
113
- const entries = fs.readdirSync(dir, { withFileTypes: true });
271
+ const entries = readdirSync(dir, { withFileTypes: true });
114
272
  for (const entry of entries) {
115
- const fullPath = path.join(dir, entry.name);
273
+ const fullPath = join(dir, entry.name);
116
274
  if (entry.isDirectory()) {
117
275
  files.push(...findPageFiles(fullPath, baseDir));
118
276
  } else if (/^page\.(tsx?|jsx?)$/.test(entry.name)) {
119
- const relativePath = "./" + path.relative(baseDir, fullPath).replace(/\\/g, "/");
277
+ const relativePath = "./" + relative(baseDir, fullPath).replace(/\\/g, "/");
120
278
  files.push(relativePath);
121
279
  }
122
280
  }
@@ -124,83 +282,12 @@ function findPageFiles(dir, baseDir = dir) {
124
282
  }
125
283
  return files;
126
284
  }
127
- function detectAppDirectory() {
128
- const srcApp = path.join(process.cwd(), "src/app");
129
- if (fs.existsSync(srcApp)) {
130
- return srcApp;
131
- }
132
- return path.join(process.cwd(), "app");
133
- }
134
- function resolveAppDirectory(options) {
135
- if (options.appDirectory) {
136
- return path.isAbsolute(options.appDirectory) ? options.appDirectory : path.join(process.cwd(), options.appDirectory);
285
+ function resolveAppDirectory(appDirectory) {
286
+ if (appDirectory) {
287
+ return isAbsolute(appDirectory) ? appDirectory : join(process.cwd(), appDirectory);
137
288
  }
138
- return detectAppDirectory();
139
- }
140
- function getPageKeys(options) {
141
- return findPageFiles(resolveAppDirectory(options));
142
- }
143
- var jitiCache = /* @__PURE__ */ new Map();
144
- function getTsconfigPaths(projectRoot, debug = false) {
145
- const alias = {};
146
- try {
147
- const tsconfigPath = path.join(projectRoot, "tsconfig.json");
148
- if (debug) {
149
- console.log("[next-sitemap] Looking for tsconfig at:", tsconfigPath);
150
- console.log("[next-sitemap] tsconfig exists:", fs.existsSync(tsconfigPath));
151
- }
152
- if (fs.existsSync(tsconfigPath)) {
153
- const content = fs.readFileSync(tsconfigPath, "utf-8");
154
- const withoutComments = stripJsonComments(content);
155
- const cleaned = withoutComments.replace(/,(\s*[}\]])/g, "$1");
156
- if (debug) {
157
- console.log("[next-sitemap] Cleaned tsconfig (first 500 chars):", cleaned.slice(0, 500));
158
- }
159
- const tsconfig = JSON.parse(cleaned);
160
- if (debug) {
161
- console.log("[next-sitemap] Parsed tsconfig paths:", tsconfig.compilerOptions?.paths);
162
- }
163
- const baseUrl = tsconfig.compilerOptions?.baseUrl || ".";
164
- const paths = tsconfig.compilerOptions?.paths || {};
165
- for (const [key, values] of Object.entries(paths)) {
166
- if (values.length > 0) {
167
- const aliasKey = key.replace(/\*$/, "");
168
- const aliasValue = joinPath(projectRoot, baseUrl, values[0].replace(/\*$/, ""));
169
- alias[aliasKey] = aliasValue;
170
- }
171
- }
172
- }
173
- } catch (error) {
174
- if (debug) {
175
- console.error("[next-sitemap] Error parsing tsconfig:", error);
176
- }
177
- }
178
- return alias;
179
- }
180
- function getJiti(projectRoot, debug = false) {
181
- if (jitiCache.has(projectRoot)) {
182
- return jitiCache.get(projectRoot);
183
- }
184
- const alias = getTsconfigPaths(projectRoot, debug);
185
- if (debug) {
186
- console.log("[next-sitemap] Final alias config:", JSON.stringify(alias));
187
- }
188
- const jiti = createJiti(import.meta.url, {
189
- moduleCache: false,
190
- interopDefault: true,
191
- jsx: true,
192
- alias
193
- });
194
- jitiCache.set(projectRoot, jiti);
195
- return jiti;
196
- }
197
- async function importPage(appDirectory, key, debug = false) {
198
- const relativePath = key.replace("./", "");
199
- const absolutePath = path.join(appDirectory, relativePath);
200
- const projectRoot = process.cwd();
201
- const jiti = getJiti(projectRoot, debug);
202
- const module = await jiti.import(absolutePath);
203
- return module.default || module;
289
+ const srcApp = join(process.cwd(), "src/app");
290
+ return existsSync(srcApp) ? srcApp : join(process.cwd(), "app");
204
291
  }
205
292
  function extractRoutes(pageKeys, localeSegment) {
206
293
  const routes = [];
@@ -208,163 +295,64 @@ function extractRoutes(pageKeys, localeSegment) {
208
295
  if (key.includes("[...")) continue;
209
296
  let pathname = key.replace("./", "/").replace(/\/page\.(tsx?|jsx?)$/, "");
210
297
  if (localeSegment) {
211
- pathname = pathname.replace(
212
- new RegExp(`^/${localeSegment.replace(/[[\]]/g, "\\$&")}`),
213
- ""
214
- );
298
+ const escapedSegment = localeSegment.replace(/[[\]]/g, "\\$&");
299
+ pathname = pathname.replace(new RegExp(`^/${escapedSegment}`), "");
215
300
  }
216
301
  pathname = pathname.replace(/\/\([^)]+\)/g, "");
217
302
  if (/(?:^|\/)(src|app)(?:\/|$)/.test(pathname)) continue;
218
- if (!pathname || pathname === "") {
219
- pathname = "/";
220
- } else if (!pathname.startsWith("/")) {
303
+ pathname = pathname || "/";
304
+ if (pathname !== "/" && !pathname.startsWith("/")) {
221
305
  pathname = "/" + pathname;
222
306
  }
223
- const dynamicSegments = pathname.match(/\[([^\]]+)\]/g)?.map((s) => s.slice(1, -1)) || [];
224
- routes.push({
225
- pathname,
226
- dynamicSegments,
227
- key
228
- });
307
+ const dynamicSegments = pathname.match(/\[([^\]]+)\]/g)?.map((s) => s.slice(1, -1)) ?? [];
308
+ routes.push({ pathname, dynamicSegments, fileKey: key });
229
309
  }
230
310
  return routes;
231
311
  }
232
- async function getAllPaths(routes, appDirectory, debug = false) {
233
- const allPaths = ["/"];
234
- const seenPaths = /* @__PURE__ */ new Set(["/"]);
235
- for (const route of routes) {
236
- if (route.dynamicSegments.length === 0) {
237
- if (route.pathname !== "/" && !seenPaths.has(route.pathname)) {
238
- allPaths.push(route.pathname);
239
- seenPaths.add(route.pathname);
240
- }
241
- } else {
242
- let getParams = null;
243
- try {
244
- if (debug) {
245
- console.log(`[next-sitemap] ${route.pathname}: importing ${route.key}`);
246
- }
247
- const module = await importPage(appDirectory, route.key, debug);
248
- getParams = module.generateStaticParams || null;
249
- } catch (error) {
250
- if (debug) {
251
- console.warn(`[next-sitemap] ${route.pathname}: import failed:`, error);
252
- }
253
- }
254
- if (getParams) {
255
- try {
256
- const params = await getParams();
257
- if (debug) {
258
- console.log(`[next-sitemap] ${route.pathname}: generateStaticParams returned ${params.length} params`);
259
- }
260
- for (const param of params) {
261
- let dynamicPath = route.pathname;
262
- for (const segment of route.dynamicSegments) {
263
- const value = param[segment];
264
- if (value === void 0) {
265
- if (debug) {
266
- console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
267
- }
268
- continue;
269
- }
270
- dynamicPath = dynamicPath.replace(`[${segment}]`, value);
271
- }
272
- if (!seenPaths.has(dynamicPath)) {
273
- allPaths.push(dynamicPath);
274
- seenPaths.add(dynamicPath);
275
- }
276
- }
277
- } catch (error) {
278
- console.error(`[next-sitemap] Error calling generateStaticParams for ${route.pathname}:`, error);
279
- }
280
- } else {
281
- if (debug) {
282
- console.warn(
283
- `[next-sitemap] Skipping dynamic route ${route.pathname}: no generateStaticParams exported. Use additionalSitemaps for routes that fetch data at runtime.`
284
- );
285
- }
286
- }
287
- }
288
- }
289
- return allPaths;
290
- }
291
- function pathsToEntries(paths, config) {
292
- const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
293
- const filteredPaths = paths.filter((pathname) => !shouldExclude(pathname, exclude));
294
- return filteredPaths.map((pathname) => {
295
- const entry = {
296
- url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
297
- lastModified: /* @__PURE__ */ new Date(),
298
- changeFrequency: getChangeFreq(pathname, changeFreq),
299
- priority: getPriority(pathname, priority)
300
- };
301
- if (locales.length > 0) {
302
- entry.alternates = {
303
- languages: Object.fromEntries(
304
- locales.map((locale) => [
305
- locale,
306
- buildUrl(baseUrl, pathname, locale, defaultLocale)
307
- ])
308
- )
309
- };
310
- }
311
- return entry;
312
- });
313
- }
314
312
  function createSitemapIndexHandler(options) {
315
313
  const { urlsPerSitemap = 5e3, locales = [], defaultLocale, additionalSitemaps, exclude, debug = false } = options;
316
314
  const localeSegment = options.localeSegment ?? (locales.length > 0 || defaultLocale ? "[locale]" : "");
317
- const appDir = resolveAppDirectory(options);
318
- const pageKeys = getPageKeys(options);
315
+ const appDir = resolveAppDirectory(options.appDirectory);
316
+ const pageKeys = findPageFiles(appDir);
319
317
  const routes = extractRoutes(pageKeys, localeSegment);
320
318
  return {
321
319
  GET: async () => {
322
320
  if (debug) {
323
- console.log(`[next-sitemap] Found ${routes.length} routes:`);
324
- routes.forEach((r) => {
325
- const isDynamic = r.dynamicSegments.length > 0;
326
- const segments = isDynamic ? ` [${r.dynamicSegments.join(", ")}]` : "";
327
- console.log(` ${r.pathname}${segments}${isDynamic ? " (dynamic)" : ""}`);
328
- });
321
+ console.log(`[next-sitemap] Found ${routes.length} routes`);
329
322
  }
330
- const allPaths = await getAllPaths(routes, appDir, debug);
331
- const filteredPaths = allPaths.filter((pathname) => !shouldExclude(pathname, exclude));
323
+ const allPaths = await generateAllPaths(routes, appDir, debug);
324
+ const filteredPaths = allPaths.filter((p) => !shouldExclude(p, exclude));
332
325
  const sitemapCount = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
333
- const xml = generateSitemapIndexXml(options.baseUrl, sitemapCount, {
334
- additionalSitemaps
335
- });
336
- return new Response(xml, {
337
- headers: { "Content-Type": "application/xml" }
338
- });
326
+ return new Response(
327
+ generateSitemapIndexXml(options.baseUrl, sitemapCount, { additionalSitemaps }),
328
+ { headers: { "Content-Type": "application/xml" } }
329
+ );
339
330
  }
340
331
  };
341
332
  }
342
333
  function createSitemapHandler(options) {
343
334
  const { urlsPerSitemap = 5e3, locales = [], defaultLocale, exclude, debug = false } = options;
344
335
  const localeSegment = options.localeSegment ?? (locales.length > 0 || defaultLocale ? "[locale]" : "");
345
- const appDir = resolveAppDirectory(options);
346
- const pageKeys = getPageKeys(options);
336
+ const appDir = resolveAppDirectory(options.appDirectory);
337
+ const pageKeys = findPageFiles(appDir);
347
338
  const routes = extractRoutes(pageKeys, localeSegment);
348
339
  const getFilteredPaths = async () => {
349
- const allPaths = await getAllPaths(routes, appDir, debug);
350
- return allPaths.filter((pathname) => !shouldExclude(pathname, exclude));
340
+ const allPaths = await generateAllPaths(routes, appDir, debug);
341
+ return allPaths.filter((p) => !shouldExclude(p, exclude));
351
342
  };
352
343
  return {
353
344
  generateStaticParams: async () => {
354
345
  const filteredPaths = await getFilteredPaths();
355
- const sitemapCount = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
356
- return Array.from({ length: sitemapCount }, (_, i) => ({ id: String(i) }));
346
+ const count = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
347
+ return Array.from({ length: count }, (_, i) => ({ id: String(i) }));
357
348
  },
358
349
  GET: async (_request, { params }) => {
359
350
  const { id } = await params;
360
351
  const sitemapId = parseInt(id, 10);
361
352
  const filteredPaths = await getFilteredPaths();
362
- const start = sitemapId * urlsPerSitemap;
363
- const end = start + urlsPerSitemap;
364
- const paths = filteredPaths.slice(start, end);
353
+ const paths = filteredPaths.slice(sitemapId * urlsPerSitemap, (sitemapId + 1) * urlsPerSitemap);
365
354
  const entries = pathsToEntries(paths, { ...options, exclude: void 0 });
366
- const xml = generateSitemapXml(entries);
367
- return new Response(xml, {
355
+ return new Response(generateSitemapXml(entries), {
368
356
  headers: { "Content-Type": "application/xml" }
369
357
  });
370
358
  }
package/dist/index.cjs CHANGED
@@ -1,5 +1,204 @@
1
1
  'use strict';
2
2
 
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+ var childProcess = require('child_process');
6
+ var url = require('url');
7
+
8
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
28
+
29
+ // src/shared.ts
30
+ var JS_EXTENSIONS = /* @__PURE__ */ new Set([
31
+ ".js",
32
+ ".cjs",
33
+ ".mjs",
34
+ ".jsx",
35
+ ".ts",
36
+ ".cts",
37
+ ".mts",
38
+ ".tsx",
39
+ ".json",
40
+ ".node"
41
+ ]);
42
+ var NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
43
+ var spawnProcess = childProcess__namespace.spawn;
44
+ var __dirname$1 = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
45
+ var paramsCache = /* @__PURE__ */ new Map();
46
+ var isDev = process.env.NODE_ENV === "development";
47
+ async function executeWorker(directory, fileKey, debug) {
48
+ const absolutePath = path.join(directory, fileKey.replace("./", ""));
49
+ const projectRoot = process.cwd();
50
+ const distRoot = path.join(__dirname$1, "..");
51
+ const workerPath = path.join(distRoot, "worker.cjs");
52
+ const loaderPath = path.join(distRoot, "loader.js");
53
+ if (debug) {
54
+ console.log(`[next-sitemap] Worker path: ${workerPath}`);
55
+ console.log(`[next-sitemap] Worker exists: ${fs.existsSync(workerPath)}`);
56
+ console.log(`[next-sitemap] Loader path: ${loaderPath}`);
57
+ console.log(`[next-sitemap] Loader exists: ${fs.existsSync(loaderPath)}`);
58
+ }
59
+ return new Promise((resolve) => {
60
+ const nodePath = [
61
+ path.join(projectRoot, "node_modules"),
62
+ path.join(__dirname$1, "..", "node_modules")
63
+ ].join(path.delimiter);
64
+ const importFlag = ["--import", loaderPath];
65
+ const args = [...importFlag, workerPath, absolutePath, projectRoot];
66
+ const child = spawnProcess("node", args, {
67
+ cwd: projectRoot,
68
+ stdio: ["ignore", "pipe", "pipe"],
69
+ env: { ...process.env, NODE_PATH: nodePath }
70
+ });
71
+ let stdout = "";
72
+ let stderr = "";
73
+ child.stdout.on("data", (data) => {
74
+ stdout += data.toString();
75
+ });
76
+ child.stderr.on("data", (data) => {
77
+ stderr += data.toString();
78
+ });
79
+ child.on("close", (code) => {
80
+ if (debug && stderr) {
81
+ console.warn(`[next-sitemap] Worker stderr: ${stderr}`);
82
+ }
83
+ if (code !== 0 && code !== null) {
84
+ if (debug) console.warn(`[next-sitemap] Worker exited with code ${code}`);
85
+ resolve(null);
86
+ return;
87
+ }
88
+ try {
89
+ const lines = stdout.trim().split("\n");
90
+ const result = JSON.parse(lines[lines.length - 1]);
91
+ if (result.success) {
92
+ resolve(result.params);
93
+ } else {
94
+ if (result.error !== NO_STATIC_PARAMS && debug) {
95
+ console.warn(`[next-sitemap] Worker error: ${result.error}`);
96
+ }
97
+ resolve(null);
98
+ }
99
+ } catch {
100
+ if (debug) console.warn(`[next-sitemap] Failed to parse worker output: ${stdout}`);
101
+ resolve(null);
102
+ }
103
+ });
104
+ child.on("error", (err) => {
105
+ if (debug) console.warn(`[next-sitemap] Failed to spawn worker: ${err.message}`);
106
+ resolve(null);
107
+ });
108
+ });
109
+ }
110
+ async function getRouteParams(route, directory, debug) {
111
+ const cacheKey = route.fileKey;
112
+ if (paramsCache.has(cacheKey)) {
113
+ return paramsCache.get(cacheKey);
114
+ }
115
+ if (debug) {
116
+ console.log(`[next-sitemap] ${route.pathname}: executing static params via worker`);
117
+ }
118
+ const params = await executeWorker(directory, route.fileKey, debug);
119
+ paramsCache.set(cacheKey, params);
120
+ if (debug && params) {
121
+ console.log(`[next-sitemap] ${route.pathname}: got ${params.length} params`);
122
+ }
123
+ return params;
124
+ }
125
+ async function generateAllPaths(routes, directory, debug) {
126
+ const staticPaths = ["/"];
127
+ const dynamicRoutes = [];
128
+ for (const route of routes) {
129
+ if (route.dynamicSegments.length === 0) {
130
+ if (route.pathname !== "/") {
131
+ staticPaths.push(route.pathname);
132
+ }
133
+ } else {
134
+ dynamicRoutes.push(route);
135
+ }
136
+ }
137
+ const startTime = isDev ? Date.now() : 0;
138
+ if (isDev && dynamicRoutes.length > 0) {
139
+ console.log(`[next-sitemap] Generating sitemap for ${dynamicRoutes.length} dynamic routes (dev only, instant in production)...`);
140
+ }
141
+ const dynamicResults = await Promise.all(
142
+ dynamicRoutes.map(async (route) => {
143
+ const params = await getRouteParams(route, directory, debug);
144
+ if (!params || params.length === 0) {
145
+ if (debug) {
146
+ console.warn(`[next-sitemap] Skipping dynamic route ${route.pathname}: no static params or empty result.`);
147
+ }
148
+ return [];
149
+ }
150
+ const paths = [];
151
+ for (const param of params) {
152
+ let path = route.pathname;
153
+ let valid = true;
154
+ for (const segment of route.dynamicSegments) {
155
+ const value = param[segment];
156
+ if (value === void 0) {
157
+ if (debug) {
158
+ console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
159
+ }
160
+ valid = false;
161
+ break;
162
+ }
163
+ path = path.replace(`[${segment}]`, value);
164
+ }
165
+ if (valid) paths.push(path);
166
+ }
167
+ return paths;
168
+ })
169
+ );
170
+ const allPaths = new Set(staticPaths);
171
+ for (const paths of dynamicResults) {
172
+ for (const path of paths) {
173
+ allPaths.add(path);
174
+ }
175
+ }
176
+ if (isDev && dynamicRoutes.length > 0) {
177
+ const elapsed = Date.now() - startTime;
178
+ console.log(`[next-sitemap] Done! Found ${allPaths.size} total URLs in ${elapsed}ms.`);
179
+ }
180
+ return Array.from(allPaths);
181
+ }
182
+ function pathsToEntries(paths, config) {
183
+ const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
184
+ return paths.filter((pathname) => !shouldExclude(pathname, exclude)).map((pathname) => {
185
+ const entry = {
186
+ url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
187
+ lastModified: /* @__PURE__ */ new Date(),
188
+ changeFrequency: getChangeFreq(pathname, changeFreq),
189
+ priority: getPriority(pathname, priority)
190
+ };
191
+ if (locales.length > 0) {
192
+ entry.alternates = {
193
+ languages: Object.fromEntries(
194
+ locales.map((locale) => [locale, buildUrl(baseUrl, pathname, locale, defaultLocale)])
195
+ )
196
+ };
197
+ }
198
+ return entry;
199
+ });
200
+ }
201
+
3
202
  // src/index.ts
4
203
  function calculateDepthPriority(pathname) {
5
204
  if (pathname === "/") return 1;
@@ -100,11 +299,19 @@ ${allEntries}
100
299
  </sitemapindex>`;
101
300
  }
102
301
 
302
+ exports.JS_EXTENSIONS = JS_EXTENSIONS;
303
+ exports.NO_STATIC_PARAMS = NO_STATIC_PARAMS;
103
304
  exports.buildUrl = buildUrl;
104
305
  exports.calculateDepthPriority = calculateDepthPriority;
306
+ exports.executeWorker = executeWorker;
307
+ exports.generateAllPaths = generateAllPaths;
105
308
  exports.generateSitemapIndexXml = generateSitemapIndexXml;
106
309
  exports.generateSitemapXml = generateSitemapXml;
107
310
  exports.getChangeFreq = getChangeFreq;
108
311
  exports.getPriority = getPriority;
312
+ exports.getRouteParams = getRouteParams;
313
+ exports.isDev = isDev;
109
314
  exports.normalizePath = normalizePath;
315
+ exports.paramsCache = paramsCache;
316
+ exports.pathsToEntries = pathsToEntries;
110
317
  exports.shouldExclude = shouldExclude;