@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.cjs +193 -209
- package/dist/app/index.d.cts +6 -11
- package/dist/app/index.d.ts +6 -11
- package/dist/app/index.js +194 -206
- package/dist/index.cjs +207 -0
- package/dist/index.d.cts +56 -1
- package/dist/index.d.ts +56 -1
- package/dist/index.js +179 -1
- package/dist/loader.js +38 -0
- package/dist/pages/index.cjs +194 -201
- package/dist/pages/index.d.cts +9 -27
- package/dist/pages/index.d.ts +9 -27
- package/dist/pages/index.js +195 -198
- package/dist/worker.cjs +207 -0
- package/package.json +2 -2
package/dist/pages/index.cjs
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var fs = require('fs');
|
|
4
4
|
var path = require('path');
|
|
5
|
-
var
|
|
6
|
-
var
|
|
5
|
+
var childProcess = require('child_process');
|
|
6
|
+
var url = require('url');
|
|
7
7
|
|
|
8
8
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
-
|
|
11
9
|
function _interopNamespace(e) {
|
|
12
10
|
if (e && e.__esModule) return e;
|
|
13
11
|
var n = Object.create(null);
|
|
@@ -26,11 +24,168 @@ function _interopNamespace(e) {
|
|
|
26
24
|
return Object.freeze(n);
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
var
|
|
30
|
-
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
31
|
-
var stripJsonComments__default = /*#__PURE__*/_interopDefault(stripJsonComments);
|
|
27
|
+
var childProcess__namespace = /*#__PURE__*/_interopNamespace(childProcess);
|
|
32
28
|
|
|
33
29
|
// src/pages/index.ts
|
|
30
|
+
var NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
|
|
31
|
+
var spawnProcess = childProcess__namespace.spawn;
|
|
32
|
+
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))));
|
|
33
|
+
var paramsCache = /* @__PURE__ */ new Map();
|
|
34
|
+
var isDev = process.env.NODE_ENV === "development";
|
|
35
|
+
async function executeWorker(directory, fileKey, debug) {
|
|
36
|
+
const absolutePath = path.join(directory, fileKey.replace("./", ""));
|
|
37
|
+
const projectRoot = process.cwd();
|
|
38
|
+
const distRoot = path.join(__dirname$1, "..");
|
|
39
|
+
const workerPath = path.join(distRoot, "worker.cjs");
|
|
40
|
+
const loaderPath = path.join(distRoot, "loader.js");
|
|
41
|
+
if (debug) {
|
|
42
|
+
console.log(`[next-sitemap] Worker path: ${workerPath}`);
|
|
43
|
+
console.log(`[next-sitemap] Worker exists: ${fs.existsSync(workerPath)}`);
|
|
44
|
+
console.log(`[next-sitemap] Loader path: ${loaderPath}`);
|
|
45
|
+
console.log(`[next-sitemap] Loader exists: ${fs.existsSync(loaderPath)}`);
|
|
46
|
+
}
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const nodePath = [
|
|
49
|
+
path.join(projectRoot, "node_modules"),
|
|
50
|
+
path.join(__dirname$1, "..", "node_modules")
|
|
51
|
+
].join(path.delimiter);
|
|
52
|
+
const importFlag = ["--import", loaderPath];
|
|
53
|
+
const args = [...importFlag, workerPath, absolutePath, projectRoot];
|
|
54
|
+
const child = spawnProcess("node", args, {
|
|
55
|
+
cwd: projectRoot,
|
|
56
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
57
|
+
env: { ...process.env, NODE_PATH: nodePath }
|
|
58
|
+
});
|
|
59
|
+
let stdout = "";
|
|
60
|
+
let stderr = "";
|
|
61
|
+
child.stdout.on("data", (data) => {
|
|
62
|
+
stdout += data.toString();
|
|
63
|
+
});
|
|
64
|
+
child.stderr.on("data", (data) => {
|
|
65
|
+
stderr += data.toString();
|
|
66
|
+
});
|
|
67
|
+
child.on("close", (code) => {
|
|
68
|
+
if (debug && stderr) {
|
|
69
|
+
console.warn(`[next-sitemap] Worker stderr: ${stderr}`);
|
|
70
|
+
}
|
|
71
|
+
if (code !== 0 && code !== null) {
|
|
72
|
+
if (debug) console.warn(`[next-sitemap] Worker exited with code ${code}`);
|
|
73
|
+
resolve(null);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const lines = stdout.trim().split("\n");
|
|
78
|
+
const result = JSON.parse(lines[lines.length - 1]);
|
|
79
|
+
if (result.success) {
|
|
80
|
+
resolve(result.params);
|
|
81
|
+
} else {
|
|
82
|
+
if (result.error !== NO_STATIC_PARAMS && debug) {
|
|
83
|
+
console.warn(`[next-sitemap] Worker error: ${result.error}`);
|
|
84
|
+
}
|
|
85
|
+
resolve(null);
|
|
86
|
+
}
|
|
87
|
+
} catch {
|
|
88
|
+
if (debug) console.warn(`[next-sitemap] Failed to parse worker output: ${stdout}`);
|
|
89
|
+
resolve(null);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
child.on("error", (err) => {
|
|
93
|
+
if (debug) console.warn(`[next-sitemap] Failed to spawn worker: ${err.message}`);
|
|
94
|
+
resolve(null);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async function getRouteParams(route, directory, debug) {
|
|
99
|
+
const cacheKey = route.fileKey;
|
|
100
|
+
if (paramsCache.has(cacheKey)) {
|
|
101
|
+
return paramsCache.get(cacheKey);
|
|
102
|
+
}
|
|
103
|
+
if (debug) {
|
|
104
|
+
console.log(`[next-sitemap] ${route.pathname}: executing static params via worker`);
|
|
105
|
+
}
|
|
106
|
+
const params = await executeWorker(directory, route.fileKey, debug);
|
|
107
|
+
paramsCache.set(cacheKey, params);
|
|
108
|
+
if (debug && params) {
|
|
109
|
+
console.log(`[next-sitemap] ${route.pathname}: got ${params.length} params`);
|
|
110
|
+
}
|
|
111
|
+
return params;
|
|
112
|
+
}
|
|
113
|
+
async function generateAllPaths(routes, directory, debug) {
|
|
114
|
+
const staticPaths = ["/"];
|
|
115
|
+
const dynamicRoutes = [];
|
|
116
|
+
for (const route of routes) {
|
|
117
|
+
if (route.dynamicSegments.length === 0) {
|
|
118
|
+
if (route.pathname !== "/") {
|
|
119
|
+
staticPaths.push(route.pathname);
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
dynamicRoutes.push(route);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const startTime = isDev ? Date.now() : 0;
|
|
126
|
+
if (isDev && dynamicRoutes.length > 0) {
|
|
127
|
+
console.log(`[next-sitemap] Generating sitemap for ${dynamicRoutes.length} dynamic routes (dev only, instant in production)...`);
|
|
128
|
+
}
|
|
129
|
+
const dynamicResults = await Promise.all(
|
|
130
|
+
dynamicRoutes.map(async (route) => {
|
|
131
|
+
const params = await getRouteParams(route, directory, debug);
|
|
132
|
+
if (!params || params.length === 0) {
|
|
133
|
+
if (debug) {
|
|
134
|
+
console.warn(`[next-sitemap] Skipping dynamic route ${route.pathname}: no static params or empty result.`);
|
|
135
|
+
}
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
const paths = [];
|
|
139
|
+
for (const param of params) {
|
|
140
|
+
let path = route.pathname;
|
|
141
|
+
let valid = true;
|
|
142
|
+
for (const segment of route.dynamicSegments) {
|
|
143
|
+
const value = param[segment];
|
|
144
|
+
if (value === void 0) {
|
|
145
|
+
if (debug) {
|
|
146
|
+
console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
|
|
147
|
+
}
|
|
148
|
+
valid = false;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
path = path.replace(`[${segment}]`, value);
|
|
152
|
+
}
|
|
153
|
+
if (valid) paths.push(path);
|
|
154
|
+
}
|
|
155
|
+
return paths;
|
|
156
|
+
})
|
|
157
|
+
);
|
|
158
|
+
const allPaths = new Set(staticPaths);
|
|
159
|
+
for (const paths of dynamicResults) {
|
|
160
|
+
for (const path of paths) {
|
|
161
|
+
allPaths.add(path);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (isDev && dynamicRoutes.length > 0) {
|
|
165
|
+
const elapsed = Date.now() - startTime;
|
|
166
|
+
console.log(`[next-sitemap] Done! Found ${allPaths.size} total URLs in ${elapsed}ms.`);
|
|
167
|
+
}
|
|
168
|
+
return Array.from(allPaths);
|
|
169
|
+
}
|
|
170
|
+
function pathsToEntries(paths, config) {
|
|
171
|
+
const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
|
|
172
|
+
return paths.filter((pathname) => !shouldExclude(pathname, exclude)).map((pathname) => {
|
|
173
|
+
const entry = {
|
|
174
|
+
url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
|
|
175
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
176
|
+
changeFrequency: getChangeFreq(pathname, changeFreq),
|
|
177
|
+
priority: getPriority(pathname, priority)
|
|
178
|
+
};
|
|
179
|
+
if (locales.length > 0) {
|
|
180
|
+
entry.alternates = {
|
|
181
|
+
languages: Object.fromEntries(
|
|
182
|
+
locales.map((locale) => [locale, buildUrl(baseUrl, pathname, locale, defaultLocale)])
|
|
183
|
+
)
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
return entry;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
34
189
|
|
|
35
190
|
// src/index.ts
|
|
36
191
|
function calculateDepthPriority(pathname) {
|
|
@@ -171,18 +326,17 @@ function generateRobotsTxt(config) {
|
|
|
171
326
|
}
|
|
172
327
|
|
|
173
328
|
// src/pages/index.ts
|
|
174
|
-
var joinPath = (...segments) => path__namespace.join(...segments);
|
|
175
329
|
function findPageFiles(dir, baseDir = dir) {
|
|
176
330
|
const files = [];
|
|
177
331
|
try {
|
|
178
|
-
const entries =
|
|
332
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
179
333
|
for (const entry of entries) {
|
|
180
|
-
const fullPath =
|
|
334
|
+
const fullPath = path.join(dir, entry.name);
|
|
181
335
|
if (entry.isDirectory()) {
|
|
182
336
|
if (entry.name === "api") continue;
|
|
183
337
|
files.push(...findPageFiles(fullPath, baseDir));
|
|
184
338
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name) && !entry.name.startsWith("_")) {
|
|
185
|
-
const relativePath = "./" +
|
|
339
|
+
const relativePath = "./" + path.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
186
340
|
files.push(relativePath);
|
|
187
341
|
}
|
|
188
342
|
}
|
|
@@ -190,67 +344,12 @@ function findPageFiles(dir, baseDir = dir) {
|
|
|
190
344
|
}
|
|
191
345
|
return files;
|
|
192
346
|
}
|
|
193
|
-
function
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return srcPages;
|
|
197
|
-
}
|
|
198
|
-
return path__namespace.join(process.cwd(), "pages");
|
|
199
|
-
}
|
|
200
|
-
function resolvePagesDirectory(options) {
|
|
201
|
-
if (options.pagesDirectory) {
|
|
202
|
-
return path__namespace.isAbsolute(options.pagesDirectory) ? options.pagesDirectory : path__namespace.join(process.cwd(), options.pagesDirectory);
|
|
347
|
+
function resolvePagesDirectory(pagesDirectory) {
|
|
348
|
+
if (pagesDirectory) {
|
|
349
|
+
return path.isAbsolute(pagesDirectory) ? pagesDirectory : path.join(process.cwd(), pagesDirectory);
|
|
203
350
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
function getPageKeys(options) {
|
|
207
|
-
return findPageFiles(resolvePagesDirectory(options));
|
|
208
|
-
}
|
|
209
|
-
var jitiCache = /* @__PURE__ */ new Map();
|
|
210
|
-
function getTsconfigPaths(projectRoot) {
|
|
211
|
-
const alias = {};
|
|
212
|
-
try {
|
|
213
|
-
const tsconfigPath = path__namespace.join(projectRoot, "tsconfig.json");
|
|
214
|
-
if (fs__namespace.existsSync(tsconfigPath)) {
|
|
215
|
-
const content = fs__namespace.readFileSync(tsconfigPath, "utf-8");
|
|
216
|
-
const withoutComments = stripJsonComments__default.default(content);
|
|
217
|
-
const cleaned = withoutComments.replace(/,(\s*[}\]])/g, "$1");
|
|
218
|
-
const tsconfig = JSON.parse(cleaned);
|
|
219
|
-
const baseUrl = tsconfig.compilerOptions?.baseUrl || ".";
|
|
220
|
-
const paths = tsconfig.compilerOptions?.paths || {};
|
|
221
|
-
for (const [key, values] of Object.entries(paths)) {
|
|
222
|
-
if (values.length > 0) {
|
|
223
|
-
const aliasKey = key.replace(/\*$/, "");
|
|
224
|
-
const aliasValue = joinPath(projectRoot, baseUrl, values[0].replace(/\*$/, ""));
|
|
225
|
-
alias[aliasKey] = aliasValue;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
} catch {
|
|
230
|
-
}
|
|
231
|
-
return alias;
|
|
232
|
-
}
|
|
233
|
-
function getJiti(projectRoot) {
|
|
234
|
-
if (jitiCache.has(projectRoot)) {
|
|
235
|
-
return jitiCache.get(projectRoot);
|
|
236
|
-
}
|
|
237
|
-
const alias = getTsconfigPaths(projectRoot);
|
|
238
|
-
const jiti$1 = jiti.createJiti((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)), {
|
|
239
|
-
moduleCache: false,
|
|
240
|
-
interopDefault: true,
|
|
241
|
-
jsx: true,
|
|
242
|
-
alias
|
|
243
|
-
});
|
|
244
|
-
jitiCache.set(projectRoot, jiti$1);
|
|
245
|
-
return jiti$1;
|
|
246
|
-
}
|
|
247
|
-
async function importPage(pagesDirectory, key) {
|
|
248
|
-
const relativePath = key.replace("./", "");
|
|
249
|
-
const absolutePath = path__namespace.join(pagesDirectory, relativePath);
|
|
250
|
-
const projectRoot = process.cwd();
|
|
251
|
-
const jiti = getJiti(projectRoot);
|
|
252
|
-
const module = await jiti.import(absolutePath);
|
|
253
|
-
return module.default || module;
|
|
351
|
+
const srcPages = path.join(process.cwd(), "src/pages");
|
|
352
|
+
return fs.existsSync(srcPages) ? srcPages : path.join(process.cwd(), "pages");
|
|
254
353
|
}
|
|
255
354
|
function extractRoutes(pageKeys, localeSegment) {
|
|
256
355
|
const routes = [];
|
|
@@ -259,10 +358,8 @@ function extractRoutes(pageKeys, localeSegment) {
|
|
|
259
358
|
let pathname = key.replace(/^\.\//, "/").replace(/\.(tsx?|jsx?)$/, "").replace(/\/index$/, "/");
|
|
260
359
|
if (pathname === "") pathname = "/";
|
|
261
360
|
if (localeSegment) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
""
|
|
265
|
-
);
|
|
361
|
+
const escapedSegment = localeSegment.replace(/[[\]]/g, "\\$&");
|
|
362
|
+
pathname = pathname.replace(new RegExp(`^/${escapedSegment}`), "");
|
|
266
363
|
}
|
|
267
364
|
if (/(?:^|\/)(src|pages)(?:\/|$)/.test(pathname)) continue;
|
|
268
365
|
if (!pathname || pathname === "") {
|
|
@@ -270,160 +367,57 @@ function extractRoutes(pageKeys, localeSegment) {
|
|
|
270
367
|
} else if (!pathname.startsWith("/")) {
|
|
271
368
|
pathname = "/" + pathname;
|
|
272
369
|
}
|
|
273
|
-
const dynamicSegments = pathname.match(/\[([^\]]+)\]/g)?.map((s) => s.slice(1, -1))
|
|
274
|
-
routes.push({
|
|
275
|
-
pathname,
|
|
276
|
-
dynamicSegments,
|
|
277
|
-
key
|
|
278
|
-
});
|
|
370
|
+
const dynamicSegments = pathname.match(/\[([^\]]+)\]/g)?.map((s) => s.slice(1, -1)) ?? [];
|
|
371
|
+
routes.push({ pathname, dynamicSegments, fileKey: key });
|
|
279
372
|
}
|
|
280
373
|
return routes;
|
|
281
374
|
}
|
|
282
|
-
async function getAllPaths(routes, pagesDirectory, debug = false) {
|
|
283
|
-
const allPaths = ["/"];
|
|
284
|
-
const seenPaths = /* @__PURE__ */ new Set(["/"]);
|
|
285
|
-
for (const route of routes) {
|
|
286
|
-
if (route.dynamicSegments.length === 0) {
|
|
287
|
-
if (route.pathname !== "/" && !seenPaths.has(route.pathname)) {
|
|
288
|
-
allPaths.push(route.pathname);
|
|
289
|
-
seenPaths.add(route.pathname);
|
|
290
|
-
}
|
|
291
|
-
} else {
|
|
292
|
-
let getParams = null;
|
|
293
|
-
try {
|
|
294
|
-
if (debug) {
|
|
295
|
-
console.log(`[next-sitemap] ${route.pathname}: importing ${route.key}`);
|
|
296
|
-
}
|
|
297
|
-
const module = await importPage(pagesDirectory, route.key);
|
|
298
|
-
const getStaticPaths = module.getStaticPaths;
|
|
299
|
-
if (getStaticPaths) {
|
|
300
|
-
getParams = async () => {
|
|
301
|
-
const result = await getStaticPaths();
|
|
302
|
-
return result.paths.map((p) => p.params);
|
|
303
|
-
};
|
|
304
|
-
} else if (module.generateStaticParams) {
|
|
305
|
-
getParams = module.generateStaticParams;
|
|
306
|
-
}
|
|
307
|
-
} catch (error) {
|
|
308
|
-
if (debug) {
|
|
309
|
-
console.warn(`[next-sitemap] ${route.pathname}: import failed:`, error);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (getParams) {
|
|
313
|
-
try {
|
|
314
|
-
const params = await getParams();
|
|
315
|
-
if (debug) {
|
|
316
|
-
console.log(`[next-sitemap] ${route.pathname}: getStaticPaths returned ${params.length} params`);
|
|
317
|
-
}
|
|
318
|
-
for (const param of params) {
|
|
319
|
-
let dynamicPath = route.pathname;
|
|
320
|
-
for (const segment of route.dynamicSegments) {
|
|
321
|
-
const value = param[segment];
|
|
322
|
-
if (value === void 0) {
|
|
323
|
-
if (debug) {
|
|
324
|
-
console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
|
|
325
|
-
}
|
|
326
|
-
continue;
|
|
327
|
-
}
|
|
328
|
-
dynamicPath = dynamicPath.replace(`[${segment}]`, value);
|
|
329
|
-
}
|
|
330
|
-
if (!seenPaths.has(dynamicPath)) {
|
|
331
|
-
allPaths.push(dynamicPath);
|
|
332
|
-
seenPaths.add(dynamicPath);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
} catch (error) {
|
|
336
|
-
console.error(`[next-sitemap] Error calling getStaticPaths for ${route.pathname}:`, error);
|
|
337
|
-
}
|
|
338
|
-
} else {
|
|
339
|
-
if (debug) {
|
|
340
|
-
console.warn(
|
|
341
|
-
`[next-sitemap] Skipping dynamic route ${route.pathname}: no getStaticPaths exported. Use additionalSitemaps for routes that fetch data at runtime.`
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return allPaths;
|
|
348
|
-
}
|
|
349
|
-
function pathsToEntries(paths, config) {
|
|
350
|
-
const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
|
|
351
|
-
const filteredPaths = paths.filter((pathname) => !shouldExclude(pathname, exclude));
|
|
352
|
-
return filteredPaths.map((pathname) => {
|
|
353
|
-
const entry = {
|
|
354
|
-
url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
|
|
355
|
-
lastModified: /* @__PURE__ */ new Date(),
|
|
356
|
-
changeFrequency: getChangeFreq(pathname, changeFreq),
|
|
357
|
-
priority: getPriority(pathname, priority)
|
|
358
|
-
};
|
|
359
|
-
if (locales.length > 0) {
|
|
360
|
-
entry.alternates = {
|
|
361
|
-
languages: Object.fromEntries(
|
|
362
|
-
locales.map((locale) => [
|
|
363
|
-
locale,
|
|
364
|
-
buildUrl(baseUrl, pathname, locale, defaultLocale)
|
|
365
|
-
])
|
|
366
|
-
)
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
return entry;
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
375
|
function createSitemapIndexApiHandler(options) {
|
|
373
376
|
const { urlsPerSitemap = 5e3, additionalSitemaps, exclude, debug = false } = options;
|
|
374
377
|
const localeSegment = options.localeSegment ?? "";
|
|
375
|
-
const pagesDir = resolvePagesDirectory(options);
|
|
376
|
-
const pageKeys =
|
|
378
|
+
const pagesDir = resolvePagesDirectory(options.pagesDirectory);
|
|
379
|
+
const pageKeys = findPageFiles(pagesDir);
|
|
377
380
|
const routes = extractRoutes(pageKeys, localeSegment);
|
|
378
|
-
if (debug) {
|
|
379
|
-
console.log(`[next-sitemap] Found ${routes.length} routes:`);
|
|
380
|
-
routes.forEach((r) => {
|
|
381
|
-
const isDynamic = r.dynamicSegments.length > 0;
|
|
382
|
-
const segments = isDynamic ? ` [${r.dynamicSegments.join(", ")}]` : "";
|
|
383
|
-
console.log(` ${r.pathname}${segments}${isDynamic ? " (dynamic)" : ""}`);
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
381
|
return async function handler(_req, res) {
|
|
387
|
-
|
|
388
|
-
|
|
382
|
+
if (debug) {
|
|
383
|
+
console.log(`[next-sitemap] Found ${routes.length} routes`);
|
|
384
|
+
}
|
|
385
|
+
const allPaths = await generateAllPaths(routes, pagesDir, debug);
|
|
386
|
+
const filteredPaths = allPaths.filter((p) => !shouldExclude(p, exclude));
|
|
389
387
|
const sitemapCount = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
|
|
390
|
-
const xml = generateSitemapIndexXml(options.baseUrl, sitemapCount, {
|
|
391
|
-
additionalSitemaps
|
|
392
|
-
});
|
|
393
388
|
res.setHeader("Content-Type", "application/xml");
|
|
394
|
-
res.status(200).send(
|
|
389
|
+
res.status(200).send(
|
|
390
|
+
generateSitemapIndexXml(options.baseUrl, sitemapCount, { additionalSitemaps })
|
|
391
|
+
);
|
|
395
392
|
};
|
|
396
393
|
}
|
|
397
394
|
function createSitemapApiHandler(options) {
|
|
398
395
|
const { urlsPerSitemap = 5e3, exclude, debug = false } = options;
|
|
399
396
|
const localeSegment = options.localeSegment ?? "";
|
|
400
|
-
const pagesDir = resolvePagesDirectory(options);
|
|
401
|
-
const pageKeys =
|
|
397
|
+
const pagesDir = resolvePagesDirectory(options.pagesDirectory);
|
|
398
|
+
const pageKeys = findPageFiles(pagesDir);
|
|
402
399
|
const routes = extractRoutes(pageKeys, localeSegment);
|
|
403
400
|
const getFilteredPaths = async () => {
|
|
404
|
-
const allPaths = await
|
|
405
|
-
return allPaths.filter((
|
|
401
|
+
const allPaths = await generateAllPaths(routes, pagesDir, debug);
|
|
402
|
+
return allPaths.filter((p) => !shouldExclude(p, exclude));
|
|
406
403
|
};
|
|
407
404
|
return async function handler(req, res) {
|
|
408
405
|
const { id } = req.query;
|
|
409
406
|
const sitemapId = parseInt(Array.isArray(id) ? id[0] : id || "0", 10);
|
|
410
407
|
const filteredPaths = await getFilteredPaths();
|
|
411
|
-
const
|
|
412
|
-
const end = start + urlsPerSitemap;
|
|
413
|
-
const paths = filteredPaths.slice(start, end);
|
|
408
|
+
const paths = filteredPaths.slice(sitemapId * urlsPerSitemap, (sitemapId + 1) * urlsPerSitemap);
|
|
414
409
|
const entries = pathsToEntries(paths, { ...options, exclude: void 0 });
|
|
415
|
-
const xml = generateSitemapXml(entries);
|
|
416
410
|
res.setHeader("Content-Type", "application/xml");
|
|
417
|
-
res.status(200).send(
|
|
411
|
+
res.status(200).send(generateSitemapXml(entries));
|
|
418
412
|
};
|
|
419
413
|
}
|
|
420
414
|
async function getSitemapStaticPaths(options) {
|
|
421
415
|
const { urlsPerSitemap = 5e3, exclude, debug = false } = options;
|
|
422
416
|
const localeSegment = options.localeSegment ?? "";
|
|
423
|
-
const pagesDir = resolvePagesDirectory(options);
|
|
424
|
-
const pageKeys =
|
|
417
|
+
const pagesDir = resolvePagesDirectory(options.pagesDirectory);
|
|
418
|
+
const pageKeys = findPageFiles(pagesDir);
|
|
425
419
|
const routes = extractRoutes(pageKeys, localeSegment);
|
|
426
|
-
const allPaths = await
|
|
420
|
+
const allPaths = await generateAllPaths(routes, pagesDir, debug);
|
|
427
421
|
const filteredPaths = allPaths.filter((pathname) => !shouldExclude(pathname, exclude));
|
|
428
422
|
const sitemapCount = Math.max(1, Math.ceil(filteredPaths.length / urlsPerSitemap));
|
|
429
423
|
return {
|
|
@@ -435,9 +429,8 @@ async function getSitemapStaticPaths(options) {
|
|
|
435
429
|
}
|
|
436
430
|
function createRobotsApiHandler(config) {
|
|
437
431
|
return function handler(_req, res) {
|
|
438
|
-
const robotsTxt = generateRobotsTxt(config);
|
|
439
432
|
res.setHeader("Content-Type", "text/plain");
|
|
440
|
-
res.status(200).send(
|
|
433
|
+
res.status(200).send(generateRobotsTxt(config));
|
|
441
434
|
};
|
|
442
435
|
}
|
|
443
436
|
|
package/dist/pages/index.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import { MetadataRoute, NextApiRequest, NextApiResponse } from 'next';
|
|
|
2
2
|
export { MetadataRoute } from 'next';
|
|
3
3
|
|
|
4
4
|
type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
5
|
+
|
|
5
6
|
interface SitemapConfig {
|
|
6
7
|
/**
|
|
7
8
|
* Base URL of the site (e.g., "https://example.com")
|
|
@@ -54,6 +55,11 @@ interface SitemapConfig {
|
|
|
54
55
|
* @example additionalSitemaps: ["/products-sitemap.xml", "/blog-sitemap.xml"]
|
|
55
56
|
*/
|
|
56
57
|
additionalSitemaps?: string[];
|
|
58
|
+
/**
|
|
59
|
+
* Enable debug logging to diagnose issues with route discovery
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
debug?: boolean;
|
|
57
63
|
}
|
|
58
64
|
interface SitemapEntry {
|
|
59
65
|
url: string;
|
|
@@ -76,28 +82,17 @@ interface CreateSitemapApiHandlerOptions extends SitemapConfig {
|
|
|
76
82
|
* Path to the pages directory to scan for page files.
|
|
77
83
|
* Can be absolute or relative to process.cwd().
|
|
78
84
|
* If not provided, auto-detects src/pages or pages.
|
|
79
|
-
*
|
|
80
|
-
* Example:
|
|
81
|
-
* ```ts
|
|
82
|
-
* pagesDirectory: 'src/pages'
|
|
83
|
-
* ```
|
|
84
85
|
*/
|
|
85
86
|
pagesDirectory?: string;
|
|
86
|
-
/**
|
|
87
|
-
* Enable debug logging to diagnose issues with route discovery
|
|
88
|
-
* Logs info about getStaticPaths calls and skipped routes
|
|
89
|
-
* @default false
|
|
90
|
-
*/
|
|
91
|
-
debug?: boolean;
|
|
92
87
|
}
|
|
93
88
|
/**
|
|
94
89
|
* Create API handler for sitemap index route
|
|
95
|
-
* Use in: pages/api/sitemap.xml.ts
|
|
90
|
+
* Use in: pages/api/sitemap.xml.ts
|
|
96
91
|
*/
|
|
97
92
|
declare function createSitemapIndexApiHandler(options: CreateSitemapApiHandlerOptions): (_req: NextApiRequest, res: NextApiResponse) => Promise<void>;
|
|
98
93
|
/**
|
|
99
94
|
* Create API handler for individual sitemap routes
|
|
100
|
-
* Use in: pages/api/sitemap/[id].ts
|
|
95
|
+
* Use in: pages/api/sitemap/[id].ts
|
|
101
96
|
*/
|
|
102
97
|
declare function createSitemapApiHandler(options: CreateSitemapApiHandlerOptions): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
|
|
103
98
|
/**
|
|
@@ -114,20 +109,7 @@ declare function getSitemapStaticPaths(options: CreateSitemapApiHandlerOptions):
|
|
|
114
109
|
}>;
|
|
115
110
|
/**
|
|
116
111
|
* Create API handler for robots.txt
|
|
117
|
-
* Use in: pages/api/robots.txt.ts
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* // pages/api/robots.txt.ts
|
|
121
|
-
* import { createRobotsApiHandler } from "@onruntime/next-sitemap/pages";
|
|
122
|
-
*
|
|
123
|
-
* export default createRobotsApiHandler({
|
|
124
|
-
* rules: {
|
|
125
|
-
* userAgent: "*",
|
|
126
|
-
* allow: "/",
|
|
127
|
-
* disallow: ["/admin", "/private"],
|
|
128
|
-
* },
|
|
129
|
-
* sitemap: "https://example.com/sitemap.xml",
|
|
130
|
-
* });
|
|
112
|
+
* Use in: pages/api/robots.txt.ts
|
|
131
113
|
*/
|
|
132
114
|
declare function createRobotsApiHandler(config: MetadataRoute.Robots): (_req: NextApiRequest, res: NextApiResponse) => void;
|
|
133
115
|
|
package/dist/pages/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { MetadataRoute, NextApiRequest, NextApiResponse } from 'next';
|
|
|
2
2
|
export { MetadataRoute } from 'next';
|
|
3
3
|
|
|
4
4
|
type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
5
|
+
|
|
5
6
|
interface SitemapConfig {
|
|
6
7
|
/**
|
|
7
8
|
* Base URL of the site (e.g., "https://example.com")
|
|
@@ -54,6 +55,11 @@ interface SitemapConfig {
|
|
|
54
55
|
* @example additionalSitemaps: ["/products-sitemap.xml", "/blog-sitemap.xml"]
|
|
55
56
|
*/
|
|
56
57
|
additionalSitemaps?: string[];
|
|
58
|
+
/**
|
|
59
|
+
* Enable debug logging to diagnose issues with route discovery
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
debug?: boolean;
|
|
57
63
|
}
|
|
58
64
|
interface SitemapEntry {
|
|
59
65
|
url: string;
|
|
@@ -76,28 +82,17 @@ interface CreateSitemapApiHandlerOptions extends SitemapConfig {
|
|
|
76
82
|
* Path to the pages directory to scan for page files.
|
|
77
83
|
* Can be absolute or relative to process.cwd().
|
|
78
84
|
* If not provided, auto-detects src/pages or pages.
|
|
79
|
-
*
|
|
80
|
-
* Example:
|
|
81
|
-
* ```ts
|
|
82
|
-
* pagesDirectory: 'src/pages'
|
|
83
|
-
* ```
|
|
84
85
|
*/
|
|
85
86
|
pagesDirectory?: string;
|
|
86
|
-
/**
|
|
87
|
-
* Enable debug logging to diagnose issues with route discovery
|
|
88
|
-
* Logs info about getStaticPaths calls and skipped routes
|
|
89
|
-
* @default false
|
|
90
|
-
*/
|
|
91
|
-
debug?: boolean;
|
|
92
87
|
}
|
|
93
88
|
/**
|
|
94
89
|
* Create API handler for sitemap index route
|
|
95
|
-
* Use in: pages/api/sitemap.xml.ts
|
|
90
|
+
* Use in: pages/api/sitemap.xml.ts
|
|
96
91
|
*/
|
|
97
92
|
declare function createSitemapIndexApiHandler(options: CreateSitemapApiHandlerOptions): (_req: NextApiRequest, res: NextApiResponse) => Promise<void>;
|
|
98
93
|
/**
|
|
99
94
|
* Create API handler for individual sitemap routes
|
|
100
|
-
* Use in: pages/api/sitemap/[id].ts
|
|
95
|
+
* Use in: pages/api/sitemap/[id].ts
|
|
101
96
|
*/
|
|
102
97
|
declare function createSitemapApiHandler(options: CreateSitemapApiHandlerOptions): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
|
|
103
98
|
/**
|
|
@@ -114,20 +109,7 @@ declare function getSitemapStaticPaths(options: CreateSitemapApiHandlerOptions):
|
|
|
114
109
|
}>;
|
|
115
110
|
/**
|
|
116
111
|
* Create API handler for robots.txt
|
|
117
|
-
* Use in: pages/api/robots.txt.ts
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* // pages/api/robots.txt.ts
|
|
121
|
-
* import { createRobotsApiHandler } from "@onruntime/next-sitemap/pages";
|
|
122
|
-
*
|
|
123
|
-
* export default createRobotsApiHandler({
|
|
124
|
-
* rules: {
|
|
125
|
-
* userAgent: "*",
|
|
126
|
-
* allow: "/",
|
|
127
|
-
* disallow: ["/admin", "/private"],
|
|
128
|
-
* },
|
|
129
|
-
* sitemap: "https://example.com/sitemap.xml",
|
|
130
|
-
* });
|
|
112
|
+
* Use in: pages/api/robots.txt.ts
|
|
131
113
|
*/
|
|
132
114
|
declare function createRobotsApiHandler(config: MetadataRoute.Robots): (_req: NextApiRequest, res: NextApiResponse) => void;
|
|
133
115
|
|