@tanstack/start-plugin-core 1.120.4-alpha.9 → 1.121.0-alpha.2
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/cjs/constants.cjs +10 -0
- package/dist/cjs/constants.cjs.map +1 -0
- package/dist/cjs/constants.d.cts +4 -0
- package/dist/cjs/index.cjs +0 -6
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +0 -5
- package/dist/cjs/nitro/dev-server-plugin.cjs +11 -3
- package/dist/cjs/nitro/dev-server-plugin.cjs.map +1 -1
- package/dist/cjs/nitro/nitro-plugin.cjs +35 -5
- package/dist/cjs/nitro/nitro-plugin.cjs.map +1 -1
- package/dist/cjs/plugin.cjs +82 -15
- package/dist/cjs/plugin.cjs.map +1 -1
- package/dist/cjs/plugin.d.cts +766 -147
- package/dist/cjs/prerender.cjs +19 -15
- package/dist/cjs/prerender.cjs.map +1 -1
- package/dist/cjs/schema.cjs +21 -2
- package/dist/cjs/schema.cjs.map +1 -1
- package/dist/cjs/schema.d.cts +2362 -601
- package/dist/esm/constants.d.ts +4 -0
- package/dist/esm/constants.js +10 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/index.d.ts +0 -5
- package/dist/esm/index.js +0 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/nitro/dev-server-plugin.js +11 -3
- package/dist/esm/nitro/dev-server-plugin.js.map +1 -1
- package/dist/esm/nitro/nitro-plugin.js +35 -5
- package/dist/esm/nitro/nitro-plugin.js.map +1 -1
- package/dist/esm/plugin.d.ts +766 -147
- package/dist/esm/plugin.js +65 -15
- package/dist/esm/plugin.js.map +1 -1
- package/dist/esm/prerender.js +19 -15
- package/dist/esm/prerender.js.map +1 -1
- package/dist/esm/schema.d.ts +2362 -601
- package/dist/esm/schema.js +22 -3
- package/dist/esm/schema.js.map +1 -1
- package/package.json +6 -4
- package/src/constants.ts +6 -0
- package/src/index.ts +0 -8
- package/src/nitro/dev-server-plugin.ts +14 -4
- package/src/nitro/nitro-plugin.ts +42 -4
- package/src/plugin.ts +81 -15
- package/src/prerender.ts +26 -19
- package/src/schema.ts +26 -1
- package/dist/cjs/nitro/build-sitemap.cjs +0 -54
- package/dist/cjs/nitro/build-sitemap.cjs.map +0 -1
- package/dist/esm/nitro/build-sitemap.js +0 -54
- package/dist/esm/nitro/build-sitemap.js.map +0 -1
package/dist/esm/schema.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import {
|
|
4
|
+
import { configSchema, getConfig } from "@tanstack/router-generator";
|
|
5
5
|
const tsrConfig = configSchema.partial().extend({
|
|
6
6
|
srcDirectory: z.string().optional().default("src")
|
|
7
7
|
});
|
|
@@ -30,6 +30,12 @@ function createTanStackConfig(frameworkPlugin) {
|
|
|
30
30
|
if (existsSync(path.join(srcDirectory, "server.tsx"))) {
|
|
31
31
|
return path.join(srcDirectory, "server.tsx");
|
|
32
32
|
}
|
|
33
|
+
if (existsSync(path.join(srcDirectory, "server.ts"))) {
|
|
34
|
+
return path.join(srcDirectory, "server.ts");
|
|
35
|
+
}
|
|
36
|
+
if (existsSync(path.join(srcDirectory, "server.js"))) {
|
|
37
|
+
return path.join(srcDirectory, "server.js");
|
|
38
|
+
}
|
|
33
39
|
return "/~start/default-server-entry";
|
|
34
40
|
})();
|
|
35
41
|
return {
|
|
@@ -62,7 +68,7 @@ function createTanStackStartOptionsSchema(frameworkPlugin = {}) {
|
|
|
62
68
|
entry: z.string().optional()
|
|
63
69
|
}).optional().default({}),
|
|
64
70
|
serverFns: z.object({
|
|
65
|
-
base: z.string().optional().default("/
|
|
71
|
+
base: z.string().optional().default("/_serverFn")
|
|
66
72
|
}).optional().default({}),
|
|
67
73
|
public: z.object({
|
|
68
74
|
dir: z.string().optional().default("public"),
|
|
@@ -77,7 +83,8 @@ function createTanStackStartOptionsSchema(frameworkPlugin = {}) {
|
|
|
77
83
|
concurrency: z.number().optional(),
|
|
78
84
|
filter: z.function().args(pageSchema).returns(z.any()).optional(),
|
|
79
85
|
failOnError: z.boolean().optional()
|
|
80
|
-
}).and(pagePrerenderOptionsSchema.optional()).optional()
|
|
86
|
+
}).and(pagePrerenderOptionsSchema.optional()).optional(),
|
|
87
|
+
spa: spaSchema.optional()
|
|
81
88
|
}).optional().default({});
|
|
82
89
|
}
|
|
83
90
|
const pageSitemapOptionsSchema = z.object({
|
|
@@ -114,6 +121,7 @@ const pageBaseSchema = z.object({
|
|
|
114
121
|
});
|
|
115
122
|
const pagePrerenderOptionsSchema = z.object({
|
|
116
123
|
enabled: z.boolean().optional(),
|
|
124
|
+
outputPath: z.string().optional(),
|
|
117
125
|
autoSubfolderIndex: z.boolean().optional(),
|
|
118
126
|
crawlLinks: z.boolean().optional(),
|
|
119
127
|
retryCount: z.number().optional(),
|
|
@@ -125,6 +133,17 @@ const pagePrerenderOptionsSchema = z.object({
|
|
|
125
133
|
})
|
|
126
134
|
).returns(z.any()).optional()
|
|
127
135
|
});
|
|
136
|
+
const spaSchema = z.object({
|
|
137
|
+
enabled: z.boolean().optional().default(true),
|
|
138
|
+
maskPath: z.string().optional().default("/"),
|
|
139
|
+
prerender: pagePrerenderOptionsSchema.optional().default({}).transform((opts) => ({
|
|
140
|
+
outputPath: opts.outputPath ?? "/_shell",
|
|
141
|
+
crawlLinks: false,
|
|
142
|
+
retryCount: 0,
|
|
143
|
+
...opts,
|
|
144
|
+
enabled: true
|
|
145
|
+
}))
|
|
146
|
+
});
|
|
128
147
|
const pageSchema = pageBaseSchema.extend({
|
|
129
148
|
prerender: pagePrerenderOptionsSchema.optional()
|
|
130
149
|
});
|
package/dist/esm/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sources":["../../src/schema.ts"],"sourcesContent":["import path from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { z } from 'zod'\nimport { configSchema, getConfig } from '@tanstack/router-generator'\nimport type { NitroConfig } from 'nitropack'\n\nconst tsrConfig = configSchema.partial().extend({\n srcDirectory: z.string().optional().default('src'),\n})\n\nexport function createTanStackConfig<\n TFrameworkPlugin extends Record<string, unknown>,\n>(frameworkPlugin?: TFrameworkPlugin) {\n const schema = createTanStackStartOptionsSchema(frameworkPlugin)\n\n return {\n schema,\n parse: (opts?: z.input<typeof schema>) => {\n const options = schema.parse(opts)\n\n const srcDirectory = options.tsr.srcDirectory\n\n const routesDirectory =\n options.tsr.routesDirectory ?? path.join(srcDirectory, 'routes')\n\n const generatedRouteTree =\n options.tsr.generatedRouteTree ??\n path.join(srcDirectory, 'routeTree.gen.ts')\n\n const clientEntryPath = (() => {\n if (options.client.entry) {\n return path.join(srcDirectory, options.client.entry)\n }\n\n if (existsSync(path.join(srcDirectory, 'client.tsx'))) {\n return path.join(srcDirectory, 'client.tsx')\n }\n\n return '/~start/default-client-entry'\n })()\n\n const serverEntryPath = (() => {\n if (options.server.entry) {\n return path.join(srcDirectory, options.server.entry)\n }\n\n if (existsSync(path.join(srcDirectory, 'server.tsx'))) {\n return path.join(srcDirectory, 'server.tsx')\n }\n\n return '/~start/default-server-entry'\n })()\n\n return {\n ...options,\n tsr: {\n ...options.tsr,\n ...getConfig({\n ...options.tsr,\n routesDirectory,\n generatedRouteTree,\n }),\n },\n clientEntryPath,\n serverEntryPath,\n }\n },\n }\n}\n\nexport function createTanStackStartOptionsSchema(\n frameworkPlugin: Record<string, unknown> = {},\n) {\n return z\n .object({\n root: z.string().optional().default(process.cwd()),\n target: z.custom<NitroConfig['preset']>().optional(),\n ...frameworkPlugin,\n tsr: tsrConfig.optional().default({}),\n client: z\n .object({\n entry: z.string().optional(),\n base: z.string().optional().default('/_build'),\n })\n .optional()\n .default({}),\n server: z\n .object({\n entry: z.string().optional(),\n })\n .optional()\n .default({}),\n serverFns: z\n .object({\n base: z.string().optional().default('/_server'),\n })\n .optional()\n .default({}),\n public: z\n .object({\n dir: z.string().optional().default('public'),\n base: z.string().optional().default('/'),\n })\n .optional()\n .default({}),\n pages: z\n .array(z.union([z.string(), pageSchema]))\n .optional()\n .default([]),\n sitemap: pagePrerenderOptionsSchema\n .extend({\n host: z.string().optional(),\n })\n .optional(),\n prerender: z\n .object({\n enabled: z.boolean().optional(),\n concurrency: z.number().optional(),\n filter: z.function().args(pageSchema).returns(z.any()).optional(),\n failOnError: z.boolean().optional(),\n })\n .and(pagePrerenderOptionsSchema.optional())\n .optional(),\n })\n .optional()\n .default({})\n}\n\nconst pageSitemapOptionsSchema = z.object({\n exclude: z.boolean().optional(),\n priority: z.number().min(0).max(1).optional(),\n changefreq: z\n .enum(['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'])\n .optional(),\n lastmod: z.union([z.string(), z.date()]).optional(),\n alternateRefs: z\n .array(\n z.object({\n href: z.string(),\n hreflang: z.string(),\n }),\n )\n .optional(),\n images: z\n .array(\n z.object({\n loc: z.string(),\n caption: z.string().optional(),\n title: z.string().optional(),\n }),\n )\n .optional(),\n news: z\n .object({\n publication: z.object({\n name: z.string(),\n language: z.string(),\n }),\n publicationDate: z.union([z.string(), z.date()]),\n title: z.string(),\n })\n .optional(),\n})\n\nconst pageBaseSchema = z.object({\n path: z.string(),\n sitemap: pageSitemapOptionsSchema.optional(),\n fromCrawl: z.boolean().optional(),\n})\n\nconst pagePrerenderOptionsSchema = z.object({\n enabled: z.boolean().optional(),\n autoSubfolderIndex: z.boolean().optional(),\n crawlLinks: z.boolean().optional(),\n retryCount: z.number().optional(),\n retryDelay: z.number().optional(),\n onSuccess: z\n .function()\n .args(\n z.object({\n page: pageBaseSchema,\n html: z.string(),\n }),\n )\n .returns(z.any())\n .optional(),\n})\n\nexport const pageSchema = pageBaseSchema.extend({\n prerender: pagePrerenderOptionsSchema.optional(),\n})\n\nexport type Page = z.infer<typeof pageSchema>\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","sources":["../../src/schema.ts"],"sourcesContent":["import path from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { z } from 'zod'\nimport { configSchema, getConfig } from '@tanstack/router-generator'\nimport type { NitroConfig } from 'nitropack'\n\nconst tsrConfig = configSchema.partial().extend({\n srcDirectory: z.string().optional().default('src'),\n})\n\nexport function createTanStackConfig<\n TFrameworkPlugin extends Record<string, unknown>,\n>(frameworkPlugin?: TFrameworkPlugin) {\n const schema = createTanStackStartOptionsSchema(frameworkPlugin)\n\n return {\n schema,\n parse: (opts?: z.input<typeof schema>) => {\n const options = schema.parse(opts)\n\n const srcDirectory = options.tsr.srcDirectory\n\n const routesDirectory =\n options.tsr.routesDirectory ?? path.join(srcDirectory, 'routes')\n\n const generatedRouteTree =\n options.tsr.generatedRouteTree ??\n path.join(srcDirectory, 'routeTree.gen.ts')\n\n const clientEntryPath = (() => {\n if (options.client.entry) {\n return path.join(srcDirectory, options.client.entry)\n }\n\n if (existsSync(path.join(srcDirectory, 'client.tsx'))) {\n return path.join(srcDirectory, 'client.tsx')\n }\n\n return '/~start/default-client-entry'\n })()\n\n const serverEntryPath = (() => {\n if (options.server.entry) {\n return path.join(srcDirectory, options.server.entry)\n }\n\n if (existsSync(path.join(srcDirectory, 'server.tsx'))) {\n return path.join(srcDirectory, 'server.tsx')\n }\n\n if (existsSync(path.join(srcDirectory, 'server.ts'))) {\n return path.join(srcDirectory, 'server.ts')\n }\n\n if (existsSync(path.join(srcDirectory, 'server.js'))) {\n return path.join(srcDirectory, 'server.js')\n }\n\n return '/~start/default-server-entry'\n })()\n\n return {\n ...options,\n tsr: {\n ...options.tsr,\n ...getConfig({\n ...options.tsr,\n routesDirectory,\n generatedRouteTree,\n }),\n },\n clientEntryPath,\n serverEntryPath,\n }\n },\n }\n}\n\nexport function createTanStackStartOptionsSchema(\n frameworkPlugin: Record<string, unknown> = {},\n) {\n return z\n .object({\n root: z.string().optional().default(process.cwd()),\n target: z.custom<NitroConfig['preset']>().optional(),\n ...frameworkPlugin,\n tsr: tsrConfig.optional().default({}),\n client: z\n .object({\n entry: z.string().optional(),\n base: z.string().optional().default('/_build'),\n })\n .optional()\n .default({}),\n server: z\n .object({\n entry: z.string().optional(),\n })\n .optional()\n .default({}),\n serverFns: z\n .object({\n base: z.string().optional().default('/_serverFn'),\n })\n .optional()\n .default({}),\n public: z\n .object({\n dir: z.string().optional().default('public'),\n base: z.string().optional().default('/'),\n })\n .optional()\n .default({}),\n pages: z\n .array(z.union([z.string(), pageSchema]))\n .optional()\n .default([]),\n sitemap: pagePrerenderOptionsSchema\n .extend({\n host: z.string().optional(),\n })\n .optional(),\n prerender: z\n .object({\n enabled: z.boolean().optional(),\n concurrency: z.number().optional(),\n filter: z.function().args(pageSchema).returns(z.any()).optional(),\n failOnError: z.boolean().optional(),\n })\n .and(pagePrerenderOptionsSchema.optional())\n .optional(),\n spa: spaSchema.optional(),\n })\n .optional()\n .default({})\n}\n\nconst pageSitemapOptionsSchema = z.object({\n exclude: z.boolean().optional(),\n priority: z.number().min(0).max(1).optional(),\n changefreq: z\n .enum(['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'])\n .optional(),\n lastmod: z.union([z.string(), z.date()]).optional(),\n alternateRefs: z\n .array(\n z.object({\n href: z.string(),\n hreflang: z.string(),\n }),\n )\n .optional(),\n images: z\n .array(\n z.object({\n loc: z.string(),\n caption: z.string().optional(),\n title: z.string().optional(),\n }),\n )\n .optional(),\n news: z\n .object({\n publication: z.object({\n name: z.string(),\n language: z.string(),\n }),\n publicationDate: z.union([z.string(), z.date()]),\n title: z.string(),\n })\n .optional(),\n})\n\nconst pageBaseSchema = z.object({\n path: z.string(),\n sitemap: pageSitemapOptionsSchema.optional(),\n fromCrawl: z.boolean().optional(),\n})\n\nconst pagePrerenderOptionsSchema = z.object({\n enabled: z.boolean().optional(),\n outputPath: z.string().optional(),\n autoSubfolderIndex: z.boolean().optional(),\n crawlLinks: z.boolean().optional(),\n retryCount: z.number().optional(),\n retryDelay: z.number().optional(),\n onSuccess: z\n .function()\n .args(\n z.object({\n page: pageBaseSchema,\n html: z.string(),\n }),\n )\n .returns(z.any())\n .optional(),\n})\n\nconst spaSchema = z.object({\n enabled: z.boolean().optional().default(true),\n maskPath: z.string().optional().default('/'),\n prerender: pagePrerenderOptionsSchema\n .optional()\n .default({})\n .transform((opts) => ({\n outputPath: opts.outputPath ?? '/_shell',\n crawlLinks: false,\n retryCount: 0,\n ...opts,\n enabled: true,\n })),\n})\n\nexport const pageSchema = pageBaseSchema.extend({\n prerender: pagePrerenderOptionsSchema.optional(),\n})\n\nexport type Page = z.infer<typeof pageSchema>\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/start-plugin-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.121.0-alpha.2",
|
|
4
4
|
"description": "Modern and scalable routing for React applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -63,9 +63,11 @@
|
|
|
63
63
|
"ufo": "^1.5.4",
|
|
64
64
|
"xmlbuilder2": "^3.1.1",
|
|
65
65
|
"zod": "^3.24.2",
|
|
66
|
-
"@tanstack/router-core": "^1.
|
|
67
|
-
"@tanstack/router-
|
|
68
|
-
"@tanstack/router-
|
|
66
|
+
"@tanstack/router-core": "^1.121.0-alpha.1",
|
|
67
|
+
"@tanstack/router-generator": "^1.121.0-alpha.1",
|
|
68
|
+
"@tanstack/router-plugin": "^1.121.0-alpha.2",
|
|
69
|
+
"@tanstack/router-utils": "^1.121.0-alpha.2",
|
|
70
|
+
"@tanstack/server-functions-plugin": "^1.121.0-alpha.2"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
71
73
|
"vite": "^6.0.0"
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const VITE_ENVIRONMENT_NAMES = {
|
|
2
|
+
// 'ssr' is chosen as the name for the server environment to ensure backwards compatibility
|
|
3
|
+
// with vite plugins that are not compatible with the new vite environment API (e.g. tailwindcss)
|
|
4
|
+
server: 'ssr',
|
|
5
|
+
client: 'client',
|
|
6
|
+
} as const
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
export type { CompileOptions, IdentifierConfig } from './compilers'
|
|
2
|
-
|
|
3
|
-
export { compileStartOutputFactory } from './compilers'
|
|
4
|
-
|
|
5
|
-
export type { PagesJson } from './nitro/build-sitemap'
|
|
6
|
-
export { buildSitemap } from './nitro/build-sitemap'
|
|
7
|
-
|
|
8
1
|
export {
|
|
9
2
|
createTanStackConfig,
|
|
10
3
|
createTanStackStartOptionsSchema,
|
|
@@ -12,4 +5,3 @@ export {
|
|
|
12
5
|
} from './schema'
|
|
13
6
|
|
|
14
7
|
export { TanStackStartVitePluginCore } from './plugin'
|
|
15
|
-
export { TanStackStartServerRoutesVite } from './start-server-routes-plugin/plugin'
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createEvent, getHeader, sendWebResponse } from 'h3'
|
|
2
2
|
import { isRunnableDevEnvironment } from 'vite'
|
|
3
3
|
import { extractHtmlScripts } from '../extractHtmlScripts'
|
|
4
|
-
import
|
|
4
|
+
import { VITE_ENVIRONMENT_NAMES } from '../constants'
|
|
5
|
+
import type { Connect, DevEnvironment, Plugin, ViteDevServer } from 'vite'
|
|
5
6
|
|
|
6
7
|
declare global {
|
|
7
8
|
// eslint-disable-next-line no-var
|
|
@@ -30,11 +31,20 @@ export function devServerPlugin(): Plugin {
|
|
|
30
31
|
let cachedScripts: string | undefined
|
|
31
32
|
viteDevServer.middlewares.use(async (req, res) => {
|
|
32
33
|
const event = createEvent(req, res)
|
|
33
|
-
const serverEnv = viteDevServer.environments[
|
|
34
|
+
const serverEnv = viteDevServer.environments[
|
|
35
|
+
VITE_ENVIRONMENT_NAMES.server
|
|
36
|
+
] as DevEnvironment | undefined
|
|
34
37
|
|
|
35
38
|
try {
|
|
36
|
-
if (!serverEnv
|
|
37
|
-
throw new Error(
|
|
39
|
+
if (!serverEnv) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Server environment ${VITE_ENVIRONMENT_NAMES.server} not found`,
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
if (!isRunnableDevEnvironment(serverEnv)) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Expected server environment ${VITE_ENVIRONMENT_NAMES.server} to be a RunnableDevEnvironment. This can be caused by multiple vite versions being installed in the project.`,
|
|
47
|
+
)
|
|
38
48
|
}
|
|
39
49
|
if (cachedScripts === undefined) {
|
|
40
50
|
const templateHtml = `<html><head></head><body></body></html>`
|
|
@@ -4,6 +4,7 @@ import { build, createNitro } from 'nitropack'
|
|
|
4
4
|
import { dirname, resolve } from 'pathe'
|
|
5
5
|
import { clientDistDir, ssrEntryFile } from '../plugin'
|
|
6
6
|
import { prerender } from '../prerender'
|
|
7
|
+
import { VITE_ENVIRONMENT_NAMES } from '../constants'
|
|
7
8
|
import { devServerPlugin } from './dev-server-plugin'
|
|
8
9
|
import { buildNitroEnvironment } from './build-nitro'
|
|
9
10
|
import type { EnvironmentOptions, PluginOption, Rollup } from 'vite'
|
|
@@ -22,7 +23,7 @@ export function nitroPlugin(
|
|
|
22
23
|
{
|
|
23
24
|
name: 'tanstack-vite-plugin-nitro',
|
|
24
25
|
configEnvironment(name) {
|
|
25
|
-
if (name ===
|
|
26
|
+
if (name === VITE_ENVIRONMENT_NAMES.server) {
|
|
26
27
|
return {
|
|
27
28
|
build: {
|
|
28
29
|
commonjsOptions: {
|
|
@@ -44,8 +45,10 @@ export function nitroPlugin(
|
|
|
44
45
|
builder: {
|
|
45
46
|
sharedPlugins: true,
|
|
46
47
|
async buildApp(builder) {
|
|
47
|
-
const clientEnv =
|
|
48
|
-
|
|
48
|
+
const clientEnv =
|
|
49
|
+
builder.environments[VITE_ENVIRONMENT_NAMES.client]
|
|
50
|
+
const serverEnv =
|
|
51
|
+
builder.environments[VITE_ENVIRONMENT_NAMES.server]
|
|
49
52
|
|
|
50
53
|
if (!clientEnv) {
|
|
51
54
|
throw new Error('Client environment not found')
|
|
@@ -86,7 +89,42 @@ export function nitroPlugin(
|
|
|
86
89
|
|
|
87
90
|
await buildNitroEnvironment(nitro, () => build(nitro))
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
// If the user has not set a prerender option, we need to set it to true
|
|
93
|
+
// if the pages array is not empty and has sub options requiring for prerendering
|
|
94
|
+
if (options.prerender?.enabled !== false) {
|
|
95
|
+
options.prerender = {
|
|
96
|
+
...options.prerender,
|
|
97
|
+
enabled: options.pages.some((d) =>
|
|
98
|
+
typeof d === 'string' ? false : !!d.prerender?.enabled,
|
|
99
|
+
),
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Setup the options for prerendering the SPA shell (i.e `src/routes/__root.tsx`)
|
|
104
|
+
if (options.spa?.enabled) {
|
|
105
|
+
options.prerender = {
|
|
106
|
+
...options.prerender,
|
|
107
|
+
enabled: true,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const maskUrl = new URL(
|
|
111
|
+
options.spa.maskPath,
|
|
112
|
+
'http://localhost',
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
maskUrl.searchParams.set('__TSS_SHELL', 'true')
|
|
116
|
+
|
|
117
|
+
options.pages.push({
|
|
118
|
+
path: maskUrl.toString().replace('http://localhost', ''),
|
|
119
|
+
prerender: options.spa.prerender,
|
|
120
|
+
sitemap: {
|
|
121
|
+
exclude: true,
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Start prerendering!!!
|
|
127
|
+
if (options.prerender.enabled) {
|
|
90
128
|
await prerender({
|
|
91
129
|
options,
|
|
92
130
|
nitro,
|
package/src/plugin.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { createNitro } from 'nitropack'
|
|
3
|
+
import { tanstackRouter } from '@tanstack/router-plugin/vite'
|
|
4
|
+
import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin'
|
|
5
|
+
import * as vite from 'vite'
|
|
3
6
|
import {
|
|
4
7
|
createTanStackConfig,
|
|
5
8
|
createTanStackStartOptionsSchema,
|
|
@@ -7,6 +10,8 @@ import {
|
|
|
7
10
|
import { nitroPlugin } from './nitro/nitro-plugin'
|
|
8
11
|
import { startManifestPlugin } from './routesManifestPlugin'
|
|
9
12
|
import { TanStackStartCompilerPlugin } from './start-compiler-plugin'
|
|
13
|
+
import { VITE_ENVIRONMENT_NAMES } from './constants'
|
|
14
|
+
import { TanStackStartServerRoutesVite } from './start-server-routes-plugin/plugin'
|
|
10
15
|
import type { PluginOption, Rollup } from 'vite'
|
|
11
16
|
import type { z } from 'zod'
|
|
12
17
|
import type { CompileStartFrameworkOptions } from './compilers'
|
|
@@ -28,21 +33,31 @@ export type TanStackStartOutputConfig = ReturnType<
|
|
|
28
33
|
export const clientDistDir = '.tanstack-start/build/client-dist'
|
|
29
34
|
export const ssrEntryFile = 'ssr.mjs'
|
|
30
35
|
|
|
36
|
+
export interface TanStackStartVitePluginCoreOptions {
|
|
37
|
+
framework: CompileStartFrameworkOptions
|
|
38
|
+
}
|
|
31
39
|
// this needs to live outside of the TanStackStartVitePluginCore since it will be invoked multiple times by vite
|
|
32
40
|
let ssrBundle: Rollup.OutputBundle
|
|
33
41
|
|
|
34
42
|
export function TanStackStartVitePluginCore(
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
opts: TanStackStartVitePluginCoreOptions,
|
|
44
|
+
startConfig: TanStackStartOutputConfig,
|
|
37
45
|
): Array<PluginOption> {
|
|
38
46
|
return [
|
|
47
|
+
tanstackRouter({
|
|
48
|
+
verboseFileRoutes: false,
|
|
49
|
+
...startConfig.tsr,
|
|
50
|
+
target: opts.framework,
|
|
51
|
+
enableRouteGeneration: true,
|
|
52
|
+
autoCodeSplitting: true,
|
|
53
|
+
}),
|
|
39
54
|
{
|
|
40
55
|
name: 'tanstack-start-core:config-client',
|
|
41
56
|
async config() {
|
|
42
57
|
const nitroOutputPublicDir = await (async () => {
|
|
43
58
|
// Create a dummy nitro app to get the resolved public output path
|
|
44
59
|
const dummyNitroApp = await createNitro({
|
|
45
|
-
preset:
|
|
60
|
+
preset: startConfig.target,
|
|
46
61
|
compatibilityDate: '2024-12-01',
|
|
47
62
|
})
|
|
48
63
|
|
|
@@ -52,25 +67,41 @@ export function TanStackStartVitePluginCore(
|
|
|
52
67
|
return nitroOutputPublicDir
|
|
53
68
|
})()
|
|
54
69
|
|
|
70
|
+
const getClientEntryPath = (startConfig: TanStackStartOutputConfig) => {
|
|
71
|
+
// when the user specifies a custom client entry path, we need to resolve it
|
|
72
|
+
// relative to the root of the project, keeping in mind that if not specified
|
|
73
|
+
// it will be /~start/default-client-entry which is a virtual path
|
|
74
|
+
// that is resolved by vite to the actual client entry path
|
|
75
|
+
const entry = startConfig.clientEntryPath.startsWith(
|
|
76
|
+
'/~start/default-client-entry',
|
|
77
|
+
)
|
|
78
|
+
? startConfig.clientEntryPath
|
|
79
|
+
: vite.normalizePath(
|
|
80
|
+
path.resolve(startConfig.root, startConfig.clientEntryPath),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return entry
|
|
84
|
+
}
|
|
85
|
+
|
|
55
86
|
return {
|
|
56
87
|
environments: {
|
|
57
|
-
client: {
|
|
88
|
+
[VITE_ENVIRONMENT_NAMES.client]: {
|
|
58
89
|
consumer: 'client',
|
|
59
90
|
build: {
|
|
60
91
|
manifest: true,
|
|
61
92
|
rollupOptions: {
|
|
62
93
|
input: {
|
|
63
|
-
main:
|
|
94
|
+
main: getClientEntryPath(startConfig),
|
|
64
95
|
},
|
|
65
96
|
output: {
|
|
66
|
-
dir: path.resolve(
|
|
97
|
+
dir: path.resolve(startConfig.root, clientDistDir),
|
|
67
98
|
},
|
|
68
99
|
// TODO this should be removed
|
|
69
100
|
external: ['node:fs', 'node:path', 'node:os', 'node:crypto'],
|
|
70
101
|
},
|
|
71
102
|
},
|
|
72
103
|
},
|
|
73
|
-
server: {
|
|
104
|
+
[VITE_ENVIRONMENT_NAMES.server]: {
|
|
74
105
|
consumer: 'server',
|
|
75
106
|
build: {
|
|
76
107
|
ssr: true,
|
|
@@ -115,22 +146,57 @@ export function TanStackStartVitePluginCore(
|
|
|
115
146
|
'nitropack',
|
|
116
147
|
'@tanstack/**',
|
|
117
148
|
],
|
|
118
|
-
external: ['undici'],
|
|
119
149
|
},
|
|
120
150
|
/* prettier-ignore */
|
|
121
151
|
define: {
|
|
122
|
-
...injectDefineEnv('TSS_PUBLIC_BASE',
|
|
123
|
-
...injectDefineEnv('TSS_CLIENT_BASE',
|
|
124
|
-
...injectDefineEnv('TSS_CLIENT_ENTRY',
|
|
125
|
-
...injectDefineEnv('TSS_SERVER_FN_BASE',
|
|
152
|
+
...injectDefineEnv('TSS_PUBLIC_BASE', startConfig.public.base),
|
|
153
|
+
...injectDefineEnv('TSS_CLIENT_BASE', startConfig.client.base),
|
|
154
|
+
...injectDefineEnv('TSS_CLIENT_ENTRY', getClientEntryPath(startConfig)), // This is consumed by the router-manifest, where the entry point is imported after the dev refresh runtime is resolved
|
|
155
|
+
...injectDefineEnv('TSS_SERVER_FN_BASE', startConfig.serverFns.base),
|
|
126
156
|
...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir),
|
|
127
157
|
},
|
|
128
158
|
}
|
|
129
159
|
},
|
|
130
160
|
},
|
|
131
|
-
TanStackStartCompilerPlugin
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
// N.B. TanStackStartCompilerPlugin must be before the TanStackServerFnPluginEnv
|
|
162
|
+
TanStackStartCompilerPlugin(opts.framework, {
|
|
163
|
+
client: { envName: VITE_ENVIRONMENT_NAMES.client },
|
|
164
|
+
server: { envName: VITE_ENVIRONMENT_NAMES.server },
|
|
165
|
+
}),
|
|
166
|
+
TanStackServerFnPluginEnv({
|
|
167
|
+
// This is the ID that will be available to look up and import
|
|
168
|
+
// our server function manifest and resolve its module
|
|
169
|
+
manifestVirtualImportId: 'tanstack:server-fn-manifest',
|
|
170
|
+
client: {
|
|
171
|
+
getRuntimeCode: () =>
|
|
172
|
+
`import { createClientRpc } from '@tanstack/${opts.framework}-start/server-functions-client'`,
|
|
173
|
+
replacer: (d) =>
|
|
174
|
+
`createClientRpc('${d.functionId}', '${startConfig.serverFns.base}')`,
|
|
175
|
+
envName: VITE_ENVIRONMENT_NAMES.client,
|
|
176
|
+
},
|
|
177
|
+
server: {
|
|
178
|
+
getRuntimeCode: () =>
|
|
179
|
+
`import { createServerRpc } from '@tanstack/${opts.framework}-start/server-functions-server'`,
|
|
180
|
+
replacer: (d) =>
|
|
181
|
+
`createServerRpc('${d.functionId}', '${startConfig.serverFns.base}', ${d.fn})`,
|
|
182
|
+
envName: VITE_ENVIRONMENT_NAMES.server,
|
|
183
|
+
},
|
|
184
|
+
importer: (fn) => {
|
|
185
|
+
const serverEnv = (globalThis as any).viteDevServer.environments[
|
|
186
|
+
VITE_ENVIRONMENT_NAMES.server
|
|
187
|
+
]
|
|
188
|
+
if (!serverEnv) {
|
|
189
|
+
throw new Error(`'ssr' vite dev environment not found`)
|
|
190
|
+
}
|
|
191
|
+
return serverEnv.runner.import(fn.extractedFilename)
|
|
192
|
+
},
|
|
193
|
+
}),
|
|
194
|
+
startManifestPlugin(startConfig),
|
|
195
|
+
nitroPlugin(startConfig, () => ssrBundle),
|
|
196
|
+
TanStackStartServerRoutesVite({
|
|
197
|
+
...startConfig.tsr,
|
|
198
|
+
target: opts.framework,
|
|
199
|
+
}),
|
|
134
200
|
]
|
|
135
201
|
}
|
|
136
202
|
|
package/src/prerender.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { build as buildNitro, createNitro } from 'nitropack'
|
|
|
6
6
|
import { joinURL, withBase, withoutBase } from 'ufo'
|
|
7
7
|
import { Queue } from './queue'
|
|
8
8
|
import { buildNitroEnvironment } from './nitro/build-nitro'
|
|
9
|
+
import { VITE_ENVIRONMENT_NAMES } from './constants'
|
|
9
10
|
import type { ViteBuilder } from 'vite'
|
|
10
11
|
import type { $Fetch, Nitro } from 'nitropack'
|
|
11
12
|
import type { TanStackStartOutputConfig } from './plugin'
|
|
@@ -20,7 +21,7 @@ export async function prerender({
|
|
|
20
21
|
nitro: Nitro
|
|
21
22
|
builder: ViteBuilder
|
|
22
23
|
}) {
|
|
23
|
-
|
|
24
|
+
console.info('Prendering pages...')
|
|
24
25
|
|
|
25
26
|
// If prerender is enabled but no pages are provided, default to prerendering the root page
|
|
26
27
|
if (options.prerender?.enabled && !options.pages.length) {
|
|
@@ -31,10 +32,12 @@ export async function prerender({
|
|
|
31
32
|
]
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
const serverEnv = builder.environments[
|
|
35
|
+
const serverEnv = builder.environments[VITE_ENVIRONMENT_NAMES.server]
|
|
35
36
|
|
|
36
37
|
if (!serverEnv) {
|
|
37
|
-
throw new Error(
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Vite's "${VITE_ENVIRONMENT_NAMES.server}" environment not found`,
|
|
40
|
+
)
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
const prerenderOutputDir = path.resolve(
|
|
@@ -90,14 +93,14 @@ export async function prerender({
|
|
|
90
93
|
// Crawl all pages
|
|
91
94
|
const pages = await prerenderPages()
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
console.info(`Prerendered ${pages.length} pages:`)
|
|
94
97
|
pages.forEach((page) => {
|
|
95
|
-
|
|
98
|
+
console.info(`- ${page}`)
|
|
96
99
|
})
|
|
97
100
|
|
|
98
101
|
// TODO: Write the prerendered pages to the output directory
|
|
99
102
|
} catch (error) {
|
|
100
|
-
|
|
103
|
+
console.error(error)
|
|
101
104
|
} finally {
|
|
102
105
|
// Ensure server is always closed
|
|
103
106
|
// server.process.kill()
|
|
@@ -123,7 +126,7 @@ export async function prerender({
|
|
|
123
126
|
const seen = new Set<string>()
|
|
124
127
|
const retriesByPath = new Map<string, number>()
|
|
125
128
|
const concurrency = options.prerender?.concurrency ?? os.cpus().length
|
|
126
|
-
|
|
129
|
+
console.info(`Concurrency: ${concurrency}`)
|
|
127
130
|
const queue = new Queue({ concurrency })
|
|
128
131
|
|
|
129
132
|
options.pages.forEach((_page) => {
|
|
@@ -165,7 +168,7 @@ export async function prerender({
|
|
|
165
168
|
|
|
166
169
|
// Add the task
|
|
167
170
|
queue.add(async () => {
|
|
168
|
-
|
|
171
|
+
console.info(`Crawling: ${page.path}`)
|
|
169
172
|
const retries = retriesByPath.get(page.path) || 0
|
|
170
173
|
try {
|
|
171
174
|
// Fetch the route
|
|
@@ -179,23 +182,29 @@ export async function prerender({
|
|
|
179
182
|
)
|
|
180
183
|
|
|
181
184
|
if (!res.ok) {
|
|
182
|
-
throw new Error(`Failed to fetch ${page.path}: ${res.statusText}
|
|
185
|
+
throw new Error(`Failed to fetch ${page.path}: ${res.statusText}`, {
|
|
186
|
+
cause: res,
|
|
187
|
+
})
|
|
183
188
|
}
|
|
184
189
|
|
|
190
|
+
const cleanPagePath = (
|
|
191
|
+
prerenderOptions.outputPath || page.path
|
|
192
|
+
).split(/[?#]/)[0]!
|
|
193
|
+
|
|
185
194
|
// Guess route type and populate fileName
|
|
186
195
|
const contentType = res.headers.get('content-type') || ''
|
|
187
196
|
const isImplicitHTML =
|
|
188
|
-
!
|
|
197
|
+
!cleanPagePath.endsWith('.html') && contentType.includes('html')
|
|
189
198
|
// &&
|
|
190
199
|
// !JsonSigRx.test(dataBuff.subarray(0, 32).toString('utf8'))
|
|
191
|
-
const routeWithIndex =
|
|
192
|
-
?
|
|
193
|
-
:
|
|
200
|
+
const routeWithIndex = cleanPagePath.endsWith('/')
|
|
201
|
+
? cleanPagePath + 'index'
|
|
202
|
+
: cleanPagePath
|
|
194
203
|
|
|
195
204
|
const htmlPath =
|
|
196
|
-
|
|
197
|
-
? joinURL(
|
|
198
|
-
:
|
|
205
|
+
cleanPagePath.endsWith('/') || prerenderOptions.autoSubfolderIndex
|
|
206
|
+
? joinURL(cleanPagePath, 'index.html')
|
|
207
|
+
: cleanPagePath + '.html'
|
|
199
208
|
|
|
200
209
|
const filename = withoutBase(
|
|
201
210
|
isImplicitHTML ? htmlPath : routeWithIndex,
|
|
@@ -227,9 +236,7 @@ export async function prerender({
|
|
|
227
236
|
}
|
|
228
237
|
} catch (error) {
|
|
229
238
|
if (retries < (prerenderOptions.retryCount ?? 0)) {
|
|
230
|
-
|
|
231
|
-
`Encountered error, retrying: ${page.path} in 500ms`,
|
|
232
|
-
)
|
|
239
|
+
console.warn(`Encountered error, retrying: ${page.path} in 500ms`)
|
|
233
240
|
await new Promise((resolve) =>
|
|
234
241
|
setTimeout(resolve, prerenderOptions.retryDelay),
|
|
235
242
|
)
|
package/src/schema.ts
CHANGED
|
@@ -48,6 +48,14 @@ export function createTanStackConfig<
|
|
|
48
48
|
return path.join(srcDirectory, 'server.tsx')
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
if (existsSync(path.join(srcDirectory, 'server.ts'))) {
|
|
52
|
+
return path.join(srcDirectory, 'server.ts')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (existsSync(path.join(srcDirectory, 'server.js'))) {
|
|
56
|
+
return path.join(srcDirectory, 'server.js')
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
return '/~start/default-server-entry'
|
|
52
60
|
})()
|
|
53
61
|
|
|
@@ -92,7 +100,7 @@ export function createTanStackStartOptionsSchema(
|
|
|
92
100
|
.default({}),
|
|
93
101
|
serverFns: z
|
|
94
102
|
.object({
|
|
95
|
-
base: z.string().optional().default('/
|
|
103
|
+
base: z.string().optional().default('/_serverFn'),
|
|
96
104
|
})
|
|
97
105
|
.optional()
|
|
98
106
|
.default({}),
|
|
@@ -121,6 +129,7 @@ export function createTanStackStartOptionsSchema(
|
|
|
121
129
|
})
|
|
122
130
|
.and(pagePrerenderOptionsSchema.optional())
|
|
123
131
|
.optional(),
|
|
132
|
+
spa: spaSchema.optional(),
|
|
124
133
|
})
|
|
125
134
|
.optional()
|
|
126
135
|
.default({})
|
|
@@ -170,6 +179,7 @@ const pageBaseSchema = z.object({
|
|
|
170
179
|
|
|
171
180
|
const pagePrerenderOptionsSchema = z.object({
|
|
172
181
|
enabled: z.boolean().optional(),
|
|
182
|
+
outputPath: z.string().optional(),
|
|
173
183
|
autoSubfolderIndex: z.boolean().optional(),
|
|
174
184
|
crawlLinks: z.boolean().optional(),
|
|
175
185
|
retryCount: z.number().optional(),
|
|
@@ -186,6 +196,21 @@ const pagePrerenderOptionsSchema = z.object({
|
|
|
186
196
|
.optional(),
|
|
187
197
|
})
|
|
188
198
|
|
|
199
|
+
const spaSchema = z.object({
|
|
200
|
+
enabled: z.boolean().optional().default(true),
|
|
201
|
+
maskPath: z.string().optional().default('/'),
|
|
202
|
+
prerender: pagePrerenderOptionsSchema
|
|
203
|
+
.optional()
|
|
204
|
+
.default({})
|
|
205
|
+
.transform((opts) => ({
|
|
206
|
+
outputPath: opts.outputPath ?? '/_shell',
|
|
207
|
+
crawlLinks: false,
|
|
208
|
+
retryCount: 0,
|
|
209
|
+
...opts,
|
|
210
|
+
enabled: true,
|
|
211
|
+
})),
|
|
212
|
+
})
|
|
213
|
+
|
|
189
214
|
export const pageSchema = pageBaseSchema.extend({
|
|
190
215
|
prerender: pagePrerenderOptionsSchema.optional(),
|
|
191
216
|
})
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const fs = require("node:fs");
|
|
4
|
-
const path = require("node:path");
|
|
5
|
-
const xmlbuilder2 = require("xmlbuilder2");
|
|
6
|
-
async function buildSitemap({
|
|
7
|
-
host,
|
|
8
|
-
routes,
|
|
9
|
-
outputDir
|
|
10
|
-
}) {
|
|
11
|
-
const routeList = await optionHasRoutes(routes);
|
|
12
|
-
if (routeList.length) {
|
|
13
|
-
const slash = checkSlash(host);
|
|
14
|
-
const sitemapData = routeList.map((page) => ({
|
|
15
|
-
page: `${host}${slash}${page.replace(/^\/+/g, "")}`,
|
|
16
|
-
lastMod: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
|
|
17
|
-
}));
|
|
18
|
-
const sitemap = createXml("urlset");
|
|
19
|
-
for (const item of sitemapData) {
|
|
20
|
-
const page = sitemap.ele("url");
|
|
21
|
-
page.ele("loc").txt(item.page);
|
|
22
|
-
page.ele("lastmod").txt(item.lastMod);
|
|
23
|
-
}
|
|
24
|
-
const mapPath = `${path.resolve(outputDir)}/sitemap.xml`;
|
|
25
|
-
try {
|
|
26
|
-
console.log(`Writing sitemap at ${mapPath}`);
|
|
27
|
-
fs.writeFileSync(mapPath, sitemap.end({ prettyPrint: true }));
|
|
28
|
-
} catch (e) {
|
|
29
|
-
console.error(`Unable to write file at ${mapPath}`, e);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function createXml(elementName) {
|
|
34
|
-
return xmlbuilder2.create({ version: "1.0", encoding: "UTF-8" }).ele(elementName, {
|
|
35
|
-
xmlns: "https://www.sitemaps.org/schemas/sitemap/0.9"
|
|
36
|
-
}).com(`This file was automatically generated by Analog.`);
|
|
37
|
-
}
|
|
38
|
-
function checkSlash(host) {
|
|
39
|
-
const finalChar = host.slice(-1);
|
|
40
|
-
return finalChar === "/" ? "" : "/";
|
|
41
|
-
}
|
|
42
|
-
async function optionHasRoutes(routes) {
|
|
43
|
-
let routeList;
|
|
44
|
-
if (typeof routes === "function") {
|
|
45
|
-
routeList = await routes();
|
|
46
|
-
} else if (Array.isArray(routes)) {
|
|
47
|
-
routeList = routes;
|
|
48
|
-
} else {
|
|
49
|
-
routeList = [];
|
|
50
|
-
}
|
|
51
|
-
return routeList.filter(Boolean);
|
|
52
|
-
}
|
|
53
|
-
exports.buildSitemap = buildSitemap;
|
|
54
|
-
//# sourceMappingURL=build-sitemap.cjs.map
|