@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.
Files changed (53) hide show
  1. package/dist/cjs/constants.cjs +10 -0
  2. package/dist/cjs/constants.cjs.map +1 -0
  3. package/dist/cjs/constants.d.cts +4 -0
  4. package/dist/cjs/index.cjs +0 -6
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/cjs/index.d.cts +0 -5
  7. package/dist/cjs/nitro/dev-server-plugin.cjs +11 -3
  8. package/dist/cjs/nitro/dev-server-plugin.cjs.map +1 -1
  9. package/dist/cjs/nitro/nitro-plugin.cjs +35 -5
  10. package/dist/cjs/nitro/nitro-plugin.cjs.map +1 -1
  11. package/dist/cjs/plugin.cjs +82 -15
  12. package/dist/cjs/plugin.cjs.map +1 -1
  13. package/dist/cjs/plugin.d.cts +766 -147
  14. package/dist/cjs/prerender.cjs +19 -15
  15. package/dist/cjs/prerender.cjs.map +1 -1
  16. package/dist/cjs/schema.cjs +21 -2
  17. package/dist/cjs/schema.cjs.map +1 -1
  18. package/dist/cjs/schema.d.cts +2362 -601
  19. package/dist/cjs/start-server-routes-plugin/plugin.cjs +2 -1
  20. package/dist/cjs/start-server-routes-plugin/plugin.cjs.map +1 -1
  21. package/dist/esm/constants.d.ts +4 -0
  22. package/dist/esm/constants.js +10 -0
  23. package/dist/esm/constants.js.map +1 -0
  24. package/dist/esm/index.d.ts +0 -5
  25. package/dist/esm/index.js +0 -6
  26. package/dist/esm/index.js.map +1 -1
  27. package/dist/esm/nitro/dev-server-plugin.js +11 -3
  28. package/dist/esm/nitro/dev-server-plugin.js.map +1 -1
  29. package/dist/esm/nitro/nitro-plugin.js +35 -5
  30. package/dist/esm/nitro/nitro-plugin.js.map +1 -1
  31. package/dist/esm/plugin.d.ts +766 -147
  32. package/dist/esm/plugin.js +65 -15
  33. package/dist/esm/plugin.js.map +1 -1
  34. package/dist/esm/prerender.js +19 -15
  35. package/dist/esm/prerender.js.map +1 -1
  36. package/dist/esm/schema.d.ts +2362 -601
  37. package/dist/esm/schema.js +22 -3
  38. package/dist/esm/schema.js.map +1 -1
  39. package/dist/esm/start-server-routes-plugin/plugin.js +2 -1
  40. package/dist/esm/start-server-routes-plugin/plugin.js.map +1 -1
  41. package/package.json +6 -4
  42. package/src/constants.ts +6 -0
  43. package/src/index.ts +0 -8
  44. package/src/nitro/dev-server-plugin.ts +14 -4
  45. package/src/nitro/nitro-plugin.ts +42 -4
  46. package/src/plugin.ts +81 -15
  47. package/src/prerender.ts +26 -19
  48. package/src/schema.ts +26 -1
  49. package/src/start-server-routes-plugin/plugin.ts +2 -1
  50. package/dist/cjs/nitro/build-sitemap.cjs +0 -54
  51. package/dist/cjs/nitro/build-sitemap.cjs.map +0 -1
  52. package/dist/esm/nitro/build-sitemap.js +0 -54
  53. 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
- framework: CompileStartFrameworkOptions,
36
- opts: TanStackStartOutputConfig,
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: opts.target,
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: opts.clientEntryPath,
94
+ main: getClientEntryPath(startConfig),
64
95
  },
65
96
  output: {
66
- dir: path.resolve(opts.root, clientDistDir),
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', opts.public.base),
123
- ...injectDefineEnv('TSS_CLIENT_BASE', opts.client.base),
124
- ...injectDefineEnv('TSS_CLIENT_ENTRY', opts.clientEntryPath),
125
- ...injectDefineEnv('TSS_SERVER_FN_BASE', opts.serverFns.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(framework),
132
- startManifestPlugin(opts),
133
- nitroPlugin(opts, () => ssrBundle),
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
- nitro.logger.info('Prendering pages...')
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['server']
35
+ const serverEnv = builder.environments[VITE_ENVIRONMENT_NAMES.server]
35
36
 
36
37
  if (!serverEnv) {
37
- throw new Error(`Vite's "server" environment not found`)
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
- nitro.logger.info(`Prerendered ${pages.length} pages:`)
96
+ console.info(`Prerendered ${pages.length} pages:`)
94
97
  pages.forEach((page) => {
95
- nitro.logger.info(`- ${page}`)
98
+ console.info(`- ${page}`)
96
99
  })
97
100
 
98
101
  // TODO: Write the prerendered pages to the output directory
99
102
  } catch (error) {
100
- nitro.logger.error(error)
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
- nitro.logger.info(`Concurrency: ${concurrency}`)
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
- nitro.logger.info(`Crawling: ${page.path}`)
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
- !page.path.endsWith('.html') && contentType.includes('html')
197
+ !cleanPagePath.endsWith('.html') && contentType.includes('html')
189
198
  // &&
190
199
  // !JsonSigRx.test(dataBuff.subarray(0, 32).toString('utf8'))
191
- const routeWithIndex = page.path.endsWith('/')
192
- ? page.path + 'index'
193
- : page.path
200
+ const routeWithIndex = cleanPagePath.endsWith('/')
201
+ ? cleanPagePath + 'index'
202
+ : cleanPagePath
194
203
 
195
204
  const htmlPath =
196
- page.path.endsWith('/') || prerenderOptions.autoSubfolderIndex
197
- ? joinURL(page.path, 'index.html')
198
- : page.path + '.html'
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
- nitro.logger.warn(
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('/_server'),
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 '${serverRoutesRelativePath}'`,
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;"}