@onruntime/next-sitemap 0.6.1 → 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 -208
- package/dist/app/index.d.cts +6 -11
- package/dist/app/index.d.ts +6 -11
- package/dist/app/index.js +194 -205
- 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 -200
- package/dist/pages/index.d.cts +9 -27
- package/dist/pages/index.d.ts +9 -27
- package/dist/pages/index.js +195 -197
- package/dist/worker.cjs +207 -0
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities, constants, and types for the sitemap package
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* File extensions that Node.js/jiti can actually process.
|
|
7
|
+
* Any other extension will be mocked as an empty module.
|
|
8
|
+
*/
|
|
9
|
+
declare const JS_EXTENSIONS: Set<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Special error code when a page doesn't export generateStaticParams or getStaticPaths
|
|
12
|
+
*/
|
|
13
|
+
declare const NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
|
|
14
|
+
/**
|
|
15
|
+
* Worker result types
|
|
16
|
+
*/
|
|
17
|
+
interface WorkerSuccess {
|
|
18
|
+
success: true;
|
|
19
|
+
params: Record<string, string>[];
|
|
20
|
+
}
|
|
21
|
+
interface WorkerFailure {
|
|
22
|
+
success: false;
|
|
23
|
+
error: string;
|
|
24
|
+
}
|
|
25
|
+
type WorkerOutput = WorkerSuccess | WorkerFailure;
|
|
26
|
+
declare const paramsCache: Map<string, Record<string, string>[] | null>;
|
|
27
|
+
declare const isDev: boolean;
|
|
28
|
+
interface RouteInfo$1 {
|
|
29
|
+
pathname: string;
|
|
30
|
+
dynamicSegments: string[];
|
|
31
|
+
fileKey: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Execute worker via child process to get static params
|
|
35
|
+
*/
|
|
36
|
+
declare function executeWorker(directory: string, fileKey: string, debug: boolean): Promise<Record<string, string>[] | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Get params for a dynamic route (with caching)
|
|
39
|
+
*/
|
|
40
|
+
declare function getRouteParams(route: RouteInfo$1, directory: string, debug: boolean): Promise<Record<string, string>[] | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Generate all URL paths from routes (parallel execution for dynamic routes)
|
|
43
|
+
*/
|
|
44
|
+
declare function generateAllPaths(routes: RouteInfo$1[], directory: string, debug: boolean): Promise<string[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Convert paths to sitemap entries
|
|
47
|
+
*/
|
|
48
|
+
declare function pathsToEntries(paths: string[], config: SitemapConfig): SitemapEntry[];
|
|
49
|
+
|
|
1
50
|
type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
51
|
+
|
|
2
52
|
interface SitemapConfig {
|
|
3
53
|
/**
|
|
4
54
|
* Base URL of the site (e.g., "https://example.com")
|
|
@@ -51,6 +101,11 @@ interface SitemapConfig {
|
|
|
51
101
|
* @example additionalSitemaps: ["/products-sitemap.xml", "/blog-sitemap.xml"]
|
|
52
102
|
*/
|
|
53
103
|
additionalSitemaps?: string[];
|
|
104
|
+
/**
|
|
105
|
+
* Enable debug logging to diagnose issues with route discovery
|
|
106
|
+
* @default false
|
|
107
|
+
*/
|
|
108
|
+
debug?: boolean;
|
|
54
109
|
}
|
|
55
110
|
interface SitemapEntry {
|
|
56
111
|
url: string;
|
|
@@ -107,4 +162,4 @@ declare function generateSitemapIndexXml(baseUrl: string, sitemapCount: number,
|
|
|
107
162
|
additionalSitemaps?: string[];
|
|
108
163
|
}): string;
|
|
109
164
|
|
|
110
|
-
export { type ChangeFrequency, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, normalizePath, shouldExclude };
|
|
165
|
+
export { type ChangeFrequency, JS_EXTENSIONS, NO_STATIC_PARAMS, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, type WorkerFailure, type WorkerOutput, type WorkerSuccess, buildUrl, calculateDepthPriority, executeWorker, generateAllPaths, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, getRouteParams, isDev, normalizePath, paramsCache, pathsToEntries, shouldExclude };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities, constants, and types for the sitemap package
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* File extensions that Node.js/jiti can actually process.
|
|
7
|
+
* Any other extension will be mocked as an empty module.
|
|
8
|
+
*/
|
|
9
|
+
declare const JS_EXTENSIONS: Set<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Special error code when a page doesn't export generateStaticParams or getStaticPaths
|
|
12
|
+
*/
|
|
13
|
+
declare const NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
|
|
14
|
+
/**
|
|
15
|
+
* Worker result types
|
|
16
|
+
*/
|
|
17
|
+
interface WorkerSuccess {
|
|
18
|
+
success: true;
|
|
19
|
+
params: Record<string, string>[];
|
|
20
|
+
}
|
|
21
|
+
interface WorkerFailure {
|
|
22
|
+
success: false;
|
|
23
|
+
error: string;
|
|
24
|
+
}
|
|
25
|
+
type WorkerOutput = WorkerSuccess | WorkerFailure;
|
|
26
|
+
declare const paramsCache: Map<string, Record<string, string>[] | null>;
|
|
27
|
+
declare const isDev: boolean;
|
|
28
|
+
interface RouteInfo$1 {
|
|
29
|
+
pathname: string;
|
|
30
|
+
dynamicSegments: string[];
|
|
31
|
+
fileKey: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Execute worker via child process to get static params
|
|
35
|
+
*/
|
|
36
|
+
declare function executeWorker(directory: string, fileKey: string, debug: boolean): Promise<Record<string, string>[] | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Get params for a dynamic route (with caching)
|
|
39
|
+
*/
|
|
40
|
+
declare function getRouteParams(route: RouteInfo$1, directory: string, debug: boolean): Promise<Record<string, string>[] | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Generate all URL paths from routes (parallel execution for dynamic routes)
|
|
43
|
+
*/
|
|
44
|
+
declare function generateAllPaths(routes: RouteInfo$1[], directory: string, debug: boolean): Promise<string[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Convert paths to sitemap entries
|
|
47
|
+
*/
|
|
48
|
+
declare function pathsToEntries(paths: string[], config: SitemapConfig): SitemapEntry[];
|
|
49
|
+
|
|
1
50
|
type ChangeFrequency = "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never";
|
|
51
|
+
|
|
2
52
|
interface SitemapConfig {
|
|
3
53
|
/**
|
|
4
54
|
* Base URL of the site (e.g., "https://example.com")
|
|
@@ -51,6 +101,11 @@ interface SitemapConfig {
|
|
|
51
101
|
* @example additionalSitemaps: ["/products-sitemap.xml", "/blog-sitemap.xml"]
|
|
52
102
|
*/
|
|
53
103
|
additionalSitemaps?: string[];
|
|
104
|
+
/**
|
|
105
|
+
* Enable debug logging to diagnose issues with route discovery
|
|
106
|
+
* @default false
|
|
107
|
+
*/
|
|
108
|
+
debug?: boolean;
|
|
54
109
|
}
|
|
55
110
|
interface SitemapEntry {
|
|
56
111
|
url: string;
|
|
@@ -107,4 +162,4 @@ declare function generateSitemapIndexXml(baseUrl: string, sitemapCount: number,
|
|
|
107
162
|
additionalSitemaps?: string[];
|
|
108
163
|
}): string;
|
|
109
164
|
|
|
110
|
-
export { type ChangeFrequency, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, normalizePath, shouldExclude };
|
|
165
|
+
export { type ChangeFrequency, JS_EXTENSIONS, NO_STATIC_PARAMS, type PageModule, type RouteInfo, type SitemapConfig, type SitemapEntry, type WorkerFailure, type WorkerOutput, type WorkerSuccess, buildUrl, calculateDepthPriority, executeWorker, generateAllPaths, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, getRouteParams, isDev, normalizePath, paramsCache, pathsToEntries, shouldExclude };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,181 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { dirname, join, delimiter } from 'path';
|
|
3
|
+
import * as childProcess from 'child_process';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
// src/shared.ts
|
|
7
|
+
var JS_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
8
|
+
".js",
|
|
9
|
+
".cjs",
|
|
10
|
+
".mjs",
|
|
11
|
+
".jsx",
|
|
12
|
+
".ts",
|
|
13
|
+
".cts",
|
|
14
|
+
".mts",
|
|
15
|
+
".tsx",
|
|
16
|
+
".json",
|
|
17
|
+
".node"
|
|
18
|
+
]);
|
|
19
|
+
var NO_STATIC_PARAMS = "NO_STATIC_PARAMS";
|
|
20
|
+
var spawnProcess = childProcess.spawn;
|
|
21
|
+
var __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
var paramsCache = /* @__PURE__ */ new Map();
|
|
23
|
+
var isDev = process.env.NODE_ENV === "development";
|
|
24
|
+
async function executeWorker(directory, fileKey, debug) {
|
|
25
|
+
const absolutePath = join(directory, fileKey.replace("./", ""));
|
|
26
|
+
const projectRoot = process.cwd();
|
|
27
|
+
const distRoot = join(__dirname$1, "..");
|
|
28
|
+
const workerPath = join(distRoot, "worker.cjs");
|
|
29
|
+
const loaderPath = join(distRoot, "loader.js");
|
|
30
|
+
if (debug) {
|
|
31
|
+
console.log(`[next-sitemap] Worker path: ${workerPath}`);
|
|
32
|
+
console.log(`[next-sitemap] Worker exists: ${existsSync(workerPath)}`);
|
|
33
|
+
console.log(`[next-sitemap] Loader path: ${loaderPath}`);
|
|
34
|
+
console.log(`[next-sitemap] Loader exists: ${existsSync(loaderPath)}`);
|
|
35
|
+
}
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
const nodePath = [
|
|
38
|
+
join(projectRoot, "node_modules"),
|
|
39
|
+
join(__dirname$1, "..", "node_modules")
|
|
40
|
+
].join(delimiter);
|
|
41
|
+
const importFlag = ["--import", loaderPath];
|
|
42
|
+
const args = [...importFlag, workerPath, absolutePath, projectRoot];
|
|
43
|
+
const child = spawnProcess("node", args, {
|
|
44
|
+
cwd: projectRoot,
|
|
45
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
46
|
+
env: { ...process.env, NODE_PATH: nodePath }
|
|
47
|
+
});
|
|
48
|
+
let stdout = "";
|
|
49
|
+
let stderr = "";
|
|
50
|
+
child.stdout.on("data", (data) => {
|
|
51
|
+
stdout += data.toString();
|
|
52
|
+
});
|
|
53
|
+
child.stderr.on("data", (data) => {
|
|
54
|
+
stderr += data.toString();
|
|
55
|
+
});
|
|
56
|
+
child.on("close", (code) => {
|
|
57
|
+
if (debug && stderr) {
|
|
58
|
+
console.warn(`[next-sitemap] Worker stderr: ${stderr}`);
|
|
59
|
+
}
|
|
60
|
+
if (code !== 0 && code !== null) {
|
|
61
|
+
if (debug) console.warn(`[next-sitemap] Worker exited with code ${code}`);
|
|
62
|
+
resolve(null);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const lines = stdout.trim().split("\n");
|
|
67
|
+
const result = JSON.parse(lines[lines.length - 1]);
|
|
68
|
+
if (result.success) {
|
|
69
|
+
resolve(result.params);
|
|
70
|
+
} else {
|
|
71
|
+
if (result.error !== NO_STATIC_PARAMS && debug) {
|
|
72
|
+
console.warn(`[next-sitemap] Worker error: ${result.error}`);
|
|
73
|
+
}
|
|
74
|
+
resolve(null);
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
if (debug) console.warn(`[next-sitemap] Failed to parse worker output: ${stdout}`);
|
|
78
|
+
resolve(null);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
child.on("error", (err) => {
|
|
82
|
+
if (debug) console.warn(`[next-sitemap] Failed to spawn worker: ${err.message}`);
|
|
83
|
+
resolve(null);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async function getRouteParams(route, directory, debug) {
|
|
88
|
+
const cacheKey = route.fileKey;
|
|
89
|
+
if (paramsCache.has(cacheKey)) {
|
|
90
|
+
return paramsCache.get(cacheKey);
|
|
91
|
+
}
|
|
92
|
+
if (debug) {
|
|
93
|
+
console.log(`[next-sitemap] ${route.pathname}: executing static params via worker`);
|
|
94
|
+
}
|
|
95
|
+
const params = await executeWorker(directory, route.fileKey, debug);
|
|
96
|
+
paramsCache.set(cacheKey, params);
|
|
97
|
+
if (debug && params) {
|
|
98
|
+
console.log(`[next-sitemap] ${route.pathname}: got ${params.length} params`);
|
|
99
|
+
}
|
|
100
|
+
return params;
|
|
101
|
+
}
|
|
102
|
+
async function generateAllPaths(routes, directory, debug) {
|
|
103
|
+
const staticPaths = ["/"];
|
|
104
|
+
const dynamicRoutes = [];
|
|
105
|
+
for (const route of routes) {
|
|
106
|
+
if (route.dynamicSegments.length === 0) {
|
|
107
|
+
if (route.pathname !== "/") {
|
|
108
|
+
staticPaths.push(route.pathname);
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
dynamicRoutes.push(route);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const startTime = isDev ? Date.now() : 0;
|
|
115
|
+
if (isDev && dynamicRoutes.length > 0) {
|
|
116
|
+
console.log(`[next-sitemap] Generating sitemap for ${dynamicRoutes.length} dynamic routes (dev only, instant in production)...`);
|
|
117
|
+
}
|
|
118
|
+
const dynamicResults = await Promise.all(
|
|
119
|
+
dynamicRoutes.map(async (route) => {
|
|
120
|
+
const params = await getRouteParams(route, directory, debug);
|
|
121
|
+
if (!params || params.length === 0) {
|
|
122
|
+
if (debug) {
|
|
123
|
+
console.warn(`[next-sitemap] Skipping dynamic route ${route.pathname}: no static params or empty result.`);
|
|
124
|
+
}
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
const paths = [];
|
|
128
|
+
for (const param of params) {
|
|
129
|
+
let path = route.pathname;
|
|
130
|
+
let valid = true;
|
|
131
|
+
for (const segment of route.dynamicSegments) {
|
|
132
|
+
const value = param[segment];
|
|
133
|
+
if (value === void 0) {
|
|
134
|
+
if (debug) {
|
|
135
|
+
console.warn(`[next-sitemap] ${route.pathname}: missing param "${segment}" in`, param);
|
|
136
|
+
}
|
|
137
|
+
valid = false;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
path = path.replace(`[${segment}]`, value);
|
|
141
|
+
}
|
|
142
|
+
if (valid) paths.push(path);
|
|
143
|
+
}
|
|
144
|
+
return paths;
|
|
145
|
+
})
|
|
146
|
+
);
|
|
147
|
+
const allPaths = new Set(staticPaths);
|
|
148
|
+
for (const paths of dynamicResults) {
|
|
149
|
+
for (const path of paths) {
|
|
150
|
+
allPaths.add(path);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (isDev && dynamicRoutes.length > 0) {
|
|
154
|
+
const elapsed = Date.now() - startTime;
|
|
155
|
+
console.log(`[next-sitemap] Done! Found ${allPaths.size} total URLs in ${elapsed}ms.`);
|
|
156
|
+
}
|
|
157
|
+
return Array.from(allPaths);
|
|
158
|
+
}
|
|
159
|
+
function pathsToEntries(paths, config) {
|
|
160
|
+
const { baseUrl, locales = [], defaultLocale, exclude, priority, changeFreq } = config;
|
|
161
|
+
return paths.filter((pathname) => !shouldExclude(pathname, exclude)).map((pathname) => {
|
|
162
|
+
const entry = {
|
|
163
|
+
url: buildUrl(baseUrl, pathname, defaultLocale, defaultLocale),
|
|
164
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
165
|
+
changeFrequency: getChangeFreq(pathname, changeFreq),
|
|
166
|
+
priority: getPriority(pathname, priority)
|
|
167
|
+
};
|
|
168
|
+
if (locales.length > 0) {
|
|
169
|
+
entry.alternates = {
|
|
170
|
+
languages: Object.fromEntries(
|
|
171
|
+
locales.map((locale) => [locale, buildUrl(baseUrl, pathname, locale, defaultLocale)])
|
|
172
|
+
)
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return entry;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
1
179
|
// src/index.ts
|
|
2
180
|
function calculateDepthPriority(pathname) {
|
|
3
181
|
if (pathname === "/") return 1;
|
|
@@ -98,4 +276,4 @@ ${allEntries}
|
|
|
98
276
|
</sitemapindex>`;
|
|
99
277
|
}
|
|
100
278
|
|
|
101
|
-
export { buildUrl, calculateDepthPriority, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, normalizePath, shouldExclude };
|
|
279
|
+
export { JS_EXTENSIONS, NO_STATIC_PARAMS, buildUrl, calculateDepthPriority, executeWorker, generateAllPaths, generateSitemapIndexXml, generateSitemapXml, getChangeFreq, getPriority, getRouteParams, isDev, normalizePath, paramsCache, pathsToEntries, shouldExclude };
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/shared.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { dirname, join, delimiter } from "path";
|
|
4
|
+
import * as childProcess from "child_process";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
var JS_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
7
|
+
".js",
|
|
8
|
+
".cjs",
|
|
9
|
+
".mjs",
|
|
10
|
+
".jsx",
|
|
11
|
+
".ts",
|
|
12
|
+
".cts",
|
|
13
|
+
".mts",
|
|
14
|
+
".tsx",
|
|
15
|
+
".json",
|
|
16
|
+
".node"
|
|
17
|
+
]);
|
|
18
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
var isDev = process.env.NODE_ENV === "development";
|
|
20
|
+
|
|
21
|
+
// src/loader.ts
|
|
22
|
+
function resolve(specifier, context, nextResolve) {
|
|
23
|
+
const ext = specifier.match(/\.[a-z0-9]+$/i)?.[0]?.toLowerCase();
|
|
24
|
+
if (ext && !JS_EXTENSIONS.has(ext)) {
|
|
25
|
+
return { shortCircuit: true, url: `mock:${specifier}` };
|
|
26
|
+
}
|
|
27
|
+
return nextResolve(specifier, context);
|
|
28
|
+
}
|
|
29
|
+
function load(url, context, nextLoad) {
|
|
30
|
+
if (url.startsWith("mock:")) {
|
|
31
|
+
return { shortCircuit: true, format: "module", source: "export default {};" };
|
|
32
|
+
}
|
|
33
|
+
return nextLoad(url, context);
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
load,
|
|
37
|
+
resolve
|
|
38
|
+
};
|