@tanstack/start-plugin-core 1.120.4-alpha.6 → 1.121.0-alpha.1
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/cjs/start-server-routes-plugin/plugin.cjs +2 -1
- package/dist/cjs/start-server-routes-plugin/plugin.cjs.map +1 -1
- 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/dist/esm/start-server-routes-plugin/plugin.js +2 -1
- package/dist/esm/start-server-routes-plugin/plugin.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/src/start-server-routes-plugin/plugin.ts +2 -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/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
|
})
|
|
@@ -684,10 +684,11 @@ function buildStartDeclarationFile({
|
|
|
684
684
|
}: {
|
|
685
685
|
serverRoutesRelativePath: string
|
|
686
686
|
}) {
|
|
687
|
+
const serverRoutesPath = replaceBackslash(serverRoutesRelativePath)
|
|
687
688
|
return (
|
|
688
689
|
[
|
|
689
690
|
'/// <reference types="vite/client" />',
|
|
690
|
-
`import '${
|
|
691
|
+
`import '${serverRoutesPath}'`,
|
|
691
692
|
].join('\n') + '\n'
|
|
692
693
|
)
|
|
693
694
|
}
|
|
@@ -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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-sitemap.cjs","sources":["../../../src/nitro/build-sitemap.ts"],"sourcesContent":["import { writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { create } from 'xmlbuilder2'\nimport type { XMLBuilder } from 'xmlbuilder2/lib/interfaces'\n\nexport type PagesJson = {\n page: string\n lastMod: string\n}\n\nexport async function buildSitemap({\n host,\n routes,\n outputDir,\n}: {\n host: string\n routes: Array<string | undefined> | (() => Promise<Array<string | undefined>>)\n outputDir: string\n}) {\n const routeList: Array<string> = await optionHasRoutes(routes)\n\n if (routeList.length) {\n const slash = checkSlash(host)\n const sitemapData: Array<PagesJson> = routeList.map((page: string) => ({\n page: `${host}${slash}${page.replace(/^\\/+/g, '')}`,\n lastMod: new Date().toISOString().split('T')[0]!,\n }))\n\n const sitemap = createXml('urlset')\n\n for (const item of sitemapData) {\n const page = sitemap.ele('url')\n page.ele('loc').txt(item.page)\n page.ele('lastmod').txt(item.lastMod)\n }\n\n const mapPath = `${resolve(outputDir)}/sitemap.xml`\n try {\n console.log(`Writing sitemap at ${mapPath}`)\n writeFileSync(mapPath, sitemap.end({ prettyPrint: true }))\n } catch (e) {\n console.error(`Unable to write file at ${mapPath}`, e)\n }\n }\n}\n\nfunction createXml(elementName: 'urlset' | 'sitemapindex'): XMLBuilder {\n return create({ version: '1.0', encoding: 'UTF-8' })\n .ele(elementName, {\n xmlns: 'https://www.sitemaps.org/schemas/sitemap/0.9',\n })\n .com(`This file was automatically generated by Analog.`)\n}\n\nfunction checkSlash(host: string): string {\n const finalChar = host.slice(-1)\n return finalChar === '/' ? '' : '/'\n}\n\nasync function optionHasRoutes(\n routes:\n | Array<string | undefined>\n | (() => Promise<Array<string | undefined>>),\n): Promise<Array<string>> {\n let routeList: Array<string | undefined>\n\n if (typeof routes === 'function') {\n // returns an array or undefined\n routeList = await routes()\n } else if (Array.isArray(routes)) {\n // returns an array of strings\n routeList = routes\n } else {\n // default it to an empty of array\n routeList = []\n }\n\n return routeList.filter(Boolean) as Array<string>\n}\n"],"names":["resolve","writeFileSync","create"],"mappings":";;;;;AAUA,eAAsB,aAAa;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACK,QAAA,YAA2B,MAAM,gBAAgB,MAAM;AAE7D,MAAI,UAAU,QAAQ;AACd,UAAA,QAAQ,WAAW,IAAI;AAC7B,UAAM,cAAgC,UAAU,IAAI,CAAC,UAAkB;AAAA,MACrE,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,QAAQ,SAAS,EAAE,CAAC;AAAA,MACjD,8BAAa,KAAK,GAAE,cAAc,MAAM,GAAG,EAAE,CAAC;AAAA,IAAA,EAC9C;AAEI,UAAA,UAAU,UAAU,QAAQ;AAElC,eAAW,QAAQ,aAAa;AACxB,YAAA,OAAO,QAAQ,IAAI,KAAK;AAC9B,WAAK,IAAI,KAAK,EAAE,IAAI,KAAK,IAAI;AAC7B,WAAK,IAAI,SAAS,EAAE,IAAI,KAAK,OAAO;AAAA,IAAA;AAGtC,UAAM,UAAU,GAAGA,KAAQ,QAAA,SAAS,CAAC;AACjC,QAAA;AACM,cAAA,IAAI,sBAAsB,OAAO,EAAE;AAC3CC,SAAA,cAAc,SAAS,QAAQ,IAAI,EAAE,aAAa,KAAA,CAAM,CAAC;AAAA,aAClD,GAAG;AACV,cAAQ,MAAM,2BAA2B,OAAO,IAAI,CAAC;AAAA,IAAA;AAAA,EACvD;AAEJ;AAEA,SAAS,UAAU,aAAoD;AAC9D,SAAAC,YAAA,OAAO,EAAE,SAAS,OAAO,UAAU,QAAS,CAAA,EAChD,IAAI,aAAa;AAAA,IAChB,OAAO;AAAA,EAAA,CACR,EACA,IAAI,kDAAkD;AAC3D;AAEA,SAAS,WAAW,MAAsB;AAClC,QAAA,YAAY,KAAK,MAAM,EAAE;AACxB,SAAA,cAAc,MAAM,KAAK;AAClC;AAEA,eAAe,gBACb,QAGwB;AACpB,MAAA;AAEA,MAAA,OAAO,WAAW,YAAY;AAEhC,gBAAY,MAAM,OAAO;AAAA,EAChB,WAAA,MAAM,QAAQ,MAAM,GAAG;AAEpB,gBAAA;AAAA,EAAA,OACP;AAEL,gBAAY,CAAC;AAAA,EAAA;AAGR,SAAA,UAAU,OAAO,OAAO;AACjC;;"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from "node:fs";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { create } from "xmlbuilder2";
|
|
4
|
-
async function buildSitemap({
|
|
5
|
-
host,
|
|
6
|
-
routes,
|
|
7
|
-
outputDir
|
|
8
|
-
}) {
|
|
9
|
-
const routeList = await optionHasRoutes(routes);
|
|
10
|
-
if (routeList.length) {
|
|
11
|
-
const slash = checkSlash(host);
|
|
12
|
-
const sitemapData = routeList.map((page) => ({
|
|
13
|
-
page: `${host}${slash}${page.replace(/^\/+/g, "")}`,
|
|
14
|
-
lastMod: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
|
|
15
|
-
}));
|
|
16
|
-
const sitemap = createXml("urlset");
|
|
17
|
-
for (const item of sitemapData) {
|
|
18
|
-
const page = sitemap.ele("url");
|
|
19
|
-
page.ele("loc").txt(item.page);
|
|
20
|
-
page.ele("lastmod").txt(item.lastMod);
|
|
21
|
-
}
|
|
22
|
-
const mapPath = `${resolve(outputDir)}/sitemap.xml`;
|
|
23
|
-
try {
|
|
24
|
-
console.log(`Writing sitemap at ${mapPath}`);
|
|
25
|
-
writeFileSync(mapPath, sitemap.end({ prettyPrint: true }));
|
|
26
|
-
} catch (e) {
|
|
27
|
-
console.error(`Unable to write file at ${mapPath}`, e);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function createXml(elementName) {
|
|
32
|
-
return create({ version: "1.0", encoding: "UTF-8" }).ele(elementName, {
|
|
33
|
-
xmlns: "https://www.sitemaps.org/schemas/sitemap/0.9"
|
|
34
|
-
}).com(`This file was automatically generated by Analog.`);
|
|
35
|
-
}
|
|
36
|
-
function checkSlash(host) {
|
|
37
|
-
const finalChar = host.slice(-1);
|
|
38
|
-
return finalChar === "/" ? "" : "/";
|
|
39
|
-
}
|
|
40
|
-
async function optionHasRoutes(routes) {
|
|
41
|
-
let routeList;
|
|
42
|
-
if (typeof routes === "function") {
|
|
43
|
-
routeList = await routes();
|
|
44
|
-
} else if (Array.isArray(routes)) {
|
|
45
|
-
routeList = routes;
|
|
46
|
-
} else {
|
|
47
|
-
routeList = [];
|
|
48
|
-
}
|
|
49
|
-
return routeList.filter(Boolean);
|
|
50
|
-
}
|
|
51
|
-
export {
|
|
52
|
-
buildSitemap
|
|
53
|
-
};
|
|
54
|
-
//# sourceMappingURL=build-sitemap.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"build-sitemap.js","sources":["../../../src/nitro/build-sitemap.ts"],"sourcesContent":["import { writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { create } from 'xmlbuilder2'\nimport type { XMLBuilder } from 'xmlbuilder2/lib/interfaces'\n\nexport type PagesJson = {\n page: string\n lastMod: string\n}\n\nexport async function buildSitemap({\n host,\n routes,\n outputDir,\n}: {\n host: string\n routes: Array<string | undefined> | (() => Promise<Array<string | undefined>>)\n outputDir: string\n}) {\n const routeList: Array<string> = await optionHasRoutes(routes)\n\n if (routeList.length) {\n const slash = checkSlash(host)\n const sitemapData: Array<PagesJson> = routeList.map((page: string) => ({\n page: `${host}${slash}${page.replace(/^\\/+/g, '')}`,\n lastMod: new Date().toISOString().split('T')[0]!,\n }))\n\n const sitemap = createXml('urlset')\n\n for (const item of sitemapData) {\n const page = sitemap.ele('url')\n page.ele('loc').txt(item.page)\n page.ele('lastmod').txt(item.lastMod)\n }\n\n const mapPath = `${resolve(outputDir)}/sitemap.xml`\n try {\n console.log(`Writing sitemap at ${mapPath}`)\n writeFileSync(mapPath, sitemap.end({ prettyPrint: true }))\n } catch (e) {\n console.error(`Unable to write file at ${mapPath}`, e)\n }\n }\n}\n\nfunction createXml(elementName: 'urlset' | 'sitemapindex'): XMLBuilder {\n return create({ version: '1.0', encoding: 'UTF-8' })\n .ele(elementName, {\n xmlns: 'https://www.sitemaps.org/schemas/sitemap/0.9',\n })\n .com(`This file was automatically generated by Analog.`)\n}\n\nfunction checkSlash(host: string): string {\n const finalChar = host.slice(-1)\n return finalChar === '/' ? '' : '/'\n}\n\nasync function optionHasRoutes(\n routes:\n | Array<string | undefined>\n | (() => Promise<Array<string | undefined>>),\n): Promise<Array<string>> {\n let routeList: Array<string | undefined>\n\n if (typeof routes === 'function') {\n // returns an array or undefined\n routeList = await routes()\n } else if (Array.isArray(routes)) {\n // returns an array of strings\n routeList = routes\n } else {\n // default it to an empty of array\n routeList = []\n }\n\n return routeList.filter(Boolean) as Array<string>\n}\n"],"names":[],"mappings":";;;AAUA,eAAsB,aAAa;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACK,QAAA,YAA2B,MAAM,gBAAgB,MAAM;AAE7D,MAAI,UAAU,QAAQ;AACd,UAAA,QAAQ,WAAW,IAAI;AAC7B,UAAM,cAAgC,UAAU,IAAI,CAAC,UAAkB;AAAA,MACrE,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,QAAQ,SAAS,EAAE,CAAC;AAAA,MACjD,8BAAa,KAAK,GAAE,cAAc,MAAM,GAAG,EAAE,CAAC;AAAA,IAAA,EAC9C;AAEI,UAAA,UAAU,UAAU,QAAQ;AAElC,eAAW,QAAQ,aAAa;AACxB,YAAA,OAAO,QAAQ,IAAI,KAAK;AAC9B,WAAK,IAAI,KAAK,EAAE,IAAI,KAAK,IAAI;AAC7B,WAAK,IAAI,SAAS,EAAE,IAAI,KAAK,OAAO;AAAA,IAAA;AAGtC,UAAM,UAAU,GAAG,QAAQ,SAAS,CAAC;AACjC,QAAA;AACM,cAAA,IAAI,sBAAsB,OAAO,EAAE;AAC3C,oBAAc,SAAS,QAAQ,IAAI,EAAE,aAAa,KAAA,CAAM,CAAC;AAAA,aAClD,GAAG;AACV,cAAQ,MAAM,2BAA2B,OAAO,IAAI,CAAC;AAAA,IAAA;AAAA,EACvD;AAEJ;AAEA,SAAS,UAAU,aAAoD;AAC9D,SAAA,OAAO,EAAE,SAAS,OAAO,UAAU,QAAS,CAAA,EAChD,IAAI,aAAa;AAAA,IAChB,OAAO;AAAA,EAAA,CACR,EACA,IAAI,kDAAkD;AAC3D;AAEA,SAAS,WAAW,MAAsB;AAClC,QAAA,YAAY,KAAK,MAAM,EAAE;AACxB,SAAA,cAAc,MAAM,KAAK;AAClC;AAEA,eAAe,gBACb,QAGwB;AACpB,MAAA;AAEA,MAAA,OAAO,WAAW,YAAY;AAEhC,gBAAY,MAAM,OAAO;AAAA,EAChB,WAAA,MAAM,QAAQ,MAAM,GAAG;AAEpB,gBAAA;AAAA,EAAA,OACP;AAEL,gBAAY,CAAC;AAAA,EAAA;AAGR,SAAA,UAAU,OAAO,OAAO;AACjC;"}
|