one 1.2.35 → 1.2.36
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/cli/build.cjs +16 -2
- package/dist/cjs/cli/build.js +14 -3
- package/dist/cjs/cli/build.js.map +1 -1
- package/dist/cjs/cli/build.native.js +20 -5
- package/dist/cjs/cli/build.native.js.map +1 -1
- package/dist/cjs/cli/generateSitemap.cjs +86 -0
- package/dist/cjs/cli/generateSitemap.js +69 -0
- package/dist/cjs/cli/generateSitemap.js.map +6 -0
- package/dist/cjs/cli/generateSitemap.native.js +112 -0
- package/dist/cjs/cli/generateSitemap.native.js.map +1 -0
- package/dist/cjs/cli/generateSitemap.test.cjs +156 -0
- package/dist/cjs/cli/generateSitemap.test.js +103 -0
- package/dist/cjs/cli/generateSitemap.test.js.map +6 -0
- package/dist/cjs/cli/generateSitemap.test.native.js +200 -0
- package/dist/cjs/cli/generateSitemap.test.native.js.map +1 -0
- package/dist/cjs/vite/one.cjs +30 -14
- package/dist/cjs/vite/one.js +30 -14
- package/dist/cjs/vite/one.js.map +1 -1
- package/dist/cjs/vite/one.native.js +30 -14
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/esm/cli/build.js +14 -2
- package/dist/esm/cli/build.js.map +1 -1
- package/dist/esm/cli/build.mjs +16 -2
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +20 -5
- package/dist/esm/cli/build.native.js.map +1 -1
- package/dist/esm/cli/generateSitemap.js +45 -0
- package/dist/esm/cli/generateSitemap.js.map +6 -0
- package/dist/esm/cli/generateSitemap.mjs +52 -0
- package/dist/esm/cli/generateSitemap.mjs.map +1 -0
- package/dist/esm/cli/generateSitemap.native.js +75 -0
- package/dist/esm/cli/generateSitemap.native.js.map +1 -0
- package/dist/esm/cli/generateSitemap.test.js +104 -0
- package/dist/esm/cli/generateSitemap.test.js.map +6 -0
- package/dist/esm/cli/generateSitemap.test.mjs +157 -0
- package/dist/esm/cli/generateSitemap.test.mjs.map +1 -0
- package/dist/esm/cli/generateSitemap.test.native.js +198 -0
- package/dist/esm/cli/generateSitemap.test.native.js.map +1 -0
- package/dist/esm/vite/one.js +30 -14
- package/dist/esm/vite/one.js.map +1 -1
- package/dist/esm/vite/one.mjs +30 -14
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +30 -14
- package/dist/esm/vite/one.native.js.map +1 -1
- package/package.json +13 -10
- package/src/cli/build.ts +31 -0
- package/src/cli/generateSitemap.test.ts +207 -0
- package/src/cli/generateSitemap.ts +93 -0
- package/src/vite/one.ts +28 -11
- package/src/vite/types.ts +73 -0
- package/types/cli/build.d.ts.map +1 -1
- package/types/cli/generateSitemap.d.ts +13 -0
- package/types/cli/generateSitemap.d.ts.map +1 -0
- package/types/cli/generateSitemap.test.d.ts +2 -0
- package/types/cli/generateSitemap.test.d.ts.map +1 -0
- package/types/env.d.ts +43 -0
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/types.d.ts +62 -0
- package/types/vite/types.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "one",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.36",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"setup.mjs",
|
|
@@ -78,6 +78,9 @@
|
|
|
78
78
|
"./metro-entry": {
|
|
79
79
|
"require": "./metro-entry.js",
|
|
80
80
|
"import": "./metro-entry.js"
|
|
81
|
+
},
|
|
82
|
+
"./env": {
|
|
83
|
+
"types": "./types/env.d.ts"
|
|
81
84
|
}
|
|
82
85
|
},
|
|
83
86
|
"main": "dist/cjs",
|
|
@@ -121,17 +124,17 @@
|
|
|
121
124
|
"@react-navigation/routers": "~7.5.1",
|
|
122
125
|
"@swc/core": "^1.14.0",
|
|
123
126
|
"@ungap/structured-clone": "^1.2.0",
|
|
124
|
-
"@vxrn/color-scheme": "1.2.
|
|
125
|
-
"@vxrn/compiler": "1.2.
|
|
126
|
-
"@vxrn/resolve": "1.2.
|
|
127
|
-
"@vxrn/tslib-lite": "1.2.
|
|
128
|
-
"@vxrn/use-isomorphic-layout-effect": "1.2.
|
|
129
|
-
"@vxrn/vite-plugin-metro": "1.2.
|
|
127
|
+
"@vxrn/color-scheme": "1.2.36",
|
|
128
|
+
"@vxrn/compiler": "1.2.36",
|
|
129
|
+
"@vxrn/resolve": "1.2.36",
|
|
130
|
+
"@vxrn/tslib-lite": "1.2.36",
|
|
131
|
+
"@vxrn/use-isomorphic-layout-effect": "1.2.36",
|
|
132
|
+
"@vxrn/vite-plugin-metro": "1.2.36",
|
|
130
133
|
"babel-dead-code-elimination": "^1.0.10",
|
|
131
134
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
132
135
|
"citty": "^0.1.6",
|
|
133
136
|
"core-js": "^3.38.1",
|
|
134
|
-
"create-vxrn": "1.2.
|
|
137
|
+
"create-vxrn": "1.2.36",
|
|
135
138
|
"escape-string-regexp": "^5.0.0",
|
|
136
139
|
"expo-linking": "~8.0.8",
|
|
137
140
|
"expo-modules-core": "~3.0.24",
|
|
@@ -157,7 +160,7 @@
|
|
|
157
160
|
"vite": "^7.1.12",
|
|
158
161
|
"vite-plugin-barrel": "^0.4.1",
|
|
159
162
|
"vite-tsconfig-paths": "^5.1.4",
|
|
160
|
-
"vxrn": "1.2.
|
|
163
|
+
"vxrn": "1.2.36",
|
|
161
164
|
"ws": "^8.18.0",
|
|
162
165
|
"xxhashjs": "^0.2.2"
|
|
163
166
|
},
|
|
@@ -175,7 +178,7 @@
|
|
|
175
178
|
"devDependencies": {
|
|
176
179
|
"@react-navigation/core": "^7.13.0",
|
|
177
180
|
"@react-navigation/native": "~7.1.19",
|
|
178
|
-
"@tamagui/build": "^1.
|
|
181
|
+
"@tamagui/build": "^1.141.0",
|
|
179
182
|
"@types/node": "^24.10.0",
|
|
180
183
|
"@types/react-dom": "^19.2.2",
|
|
181
184
|
"@types/xxhashjs": "^0.2.4",
|
package/src/cli/build.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { runWithAsyncLocalContext } from '../vite/one-server-only'
|
|
|
25
25
|
import type { One, RouteInfo } from '../vite/types'
|
|
26
26
|
import { buildPage } from './buildPage'
|
|
27
27
|
import { checkNodeVersion } from './checkNodeVersion'
|
|
28
|
+
import { generateSitemap, type RouteSitemapData } from './generateSitemap'
|
|
28
29
|
import { labelProcess } from './label-process'
|
|
29
30
|
|
|
30
31
|
const { ensureDir, writeJSON } = FSExtra
|
|
@@ -219,6 +220,7 @@ export async function build(args: {
|
|
|
219
220
|
const assets: OutputAsset[] = []
|
|
220
221
|
|
|
221
222
|
const builtRoutes: One.RouteBuildInfo[] = []
|
|
223
|
+
const sitemapData: RouteSitemapData[] = []
|
|
222
224
|
|
|
223
225
|
console.info(`\n 🔨 build static routes\n`)
|
|
224
226
|
|
|
@@ -466,6 +468,9 @@ export async function build(args: {
|
|
|
466
468
|
console.info(`paramsList`, JSON.stringify(paramsList, null, 2))
|
|
467
469
|
}
|
|
468
470
|
|
|
471
|
+
// Get route-level sitemap export if present
|
|
472
|
+
const routeSitemapExport = exported.sitemap as One.RouteSitemapExport | undefined
|
|
473
|
+
|
|
469
474
|
for (const params of paramsList) {
|
|
470
475
|
const path = getPathnameFromFilePath(relativeId, params, foundRoute.type === 'ssg')
|
|
471
476
|
console.info(` ↦ route ${path}`)
|
|
@@ -490,6 +495,20 @@ export async function build(args: {
|
|
|
490
495
|
})
|
|
491
496
|
|
|
492
497
|
builtRoutes.push(built)
|
|
498
|
+
|
|
499
|
+
// Collect sitemap data for page routes (exclude API, not-found, layouts)
|
|
500
|
+
if (
|
|
501
|
+
foundRoute.type !== 'api' &&
|
|
502
|
+
foundRoute.type !== 'layout' &&
|
|
503
|
+
!foundRoute.isNotFound &&
|
|
504
|
+
!foundRoute.page.includes('+not-found') &&
|
|
505
|
+
!foundRoute.page.includes('_sitemap')
|
|
506
|
+
) {
|
|
507
|
+
sitemapData.push({
|
|
508
|
+
path,
|
|
509
|
+
routeExport: routeSitemapExport,
|
|
510
|
+
})
|
|
511
|
+
}
|
|
493
512
|
}
|
|
494
513
|
}
|
|
495
514
|
|
|
@@ -562,6 +581,18 @@ export async function build(args: {
|
|
|
562
581
|
|
|
563
582
|
await writeJSON(toAbsolute(`dist/buildInfo.json`), buildInfoForWriting)
|
|
564
583
|
|
|
584
|
+
// Generate sitemap.xml if enabled
|
|
585
|
+
const sitemapConfig = oneOptions.web?.sitemap
|
|
586
|
+
if (sitemapConfig) {
|
|
587
|
+
const sitemapOptions: One.SitemapOptions =
|
|
588
|
+
typeof sitemapConfig === 'boolean' ? {} : sitemapConfig
|
|
589
|
+
|
|
590
|
+
const sitemapXml = generateSitemap(sitemapData, sitemapOptions)
|
|
591
|
+
const sitemapPath = join(clientDir, 'sitemap.xml')
|
|
592
|
+
await FSExtra.writeFile(sitemapPath, sitemapXml)
|
|
593
|
+
console.info(`\n 📄 generated sitemap.xml (${sitemapData.length} URLs)\n`)
|
|
594
|
+
}
|
|
595
|
+
|
|
565
596
|
let postBuildLogs: string[] = []
|
|
566
597
|
|
|
567
598
|
const platform = oneOptions.web?.deploy
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { generateSitemap, type RouteSitemapData } from './generateSitemap'
|
|
3
|
+
import type { One } from '../vite/types'
|
|
4
|
+
|
|
5
|
+
describe('generateSitemap', () => {
|
|
6
|
+
it('generates basic sitemap XML', () => {
|
|
7
|
+
const routes: RouteSitemapData[] = [{ path: '/' }, { path: '/about' }, { path: '/blog' }]
|
|
8
|
+
const options: One.SitemapOptions = {}
|
|
9
|
+
|
|
10
|
+
const result = generateSitemap(routes, options)
|
|
11
|
+
|
|
12
|
+
expect(result).toContain('<?xml version="1.0" encoding="UTF-8"?>')
|
|
13
|
+
expect(result).toContain('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">')
|
|
14
|
+
expect(result).toContain('<loc>/</loc>')
|
|
15
|
+
expect(result).toContain('<loc>/about</loc>')
|
|
16
|
+
expect(result).toContain('<loc>/blog</loc>')
|
|
17
|
+
expect(result).toContain('</urlset>')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('uses baseUrl when provided', () => {
|
|
21
|
+
const routes: RouteSitemapData[] = [{ path: '/' }, { path: '/about' }]
|
|
22
|
+
const options: One.SitemapOptions = {
|
|
23
|
+
baseUrl: 'https://example.com',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const result = generateSitemap(routes, options)
|
|
27
|
+
|
|
28
|
+
expect(result).toContain('<loc>https://example.com/</loc>')
|
|
29
|
+
expect(result).toContain('<loc>https://example.com/about</loc>')
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('strips trailing slash from baseUrl', () => {
|
|
33
|
+
const routes: RouteSitemapData[] = [{ path: '/about' }]
|
|
34
|
+
const options: One.SitemapOptions = {
|
|
35
|
+
baseUrl: 'https://example.com/',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const result = generateSitemap(routes, options)
|
|
39
|
+
|
|
40
|
+
expect(result).toContain('<loc>https://example.com/about</loc>')
|
|
41
|
+
expect(result).not.toContain('https://example.com//about')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('uses ONE_SERVER_URL env var when baseUrl not provided', () => {
|
|
45
|
+
const originalEnv = process.env.ONE_SERVER_URL
|
|
46
|
+
process.env.ONE_SERVER_URL = 'https://env-url.com'
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const routes: RouteSitemapData[] = [{ path: '/test' }]
|
|
50
|
+
const options: One.SitemapOptions = {}
|
|
51
|
+
|
|
52
|
+
const result = generateSitemap(routes, options)
|
|
53
|
+
|
|
54
|
+
expect(result).toContain('<loc>https://env-url.com/test</loc>')
|
|
55
|
+
} finally {
|
|
56
|
+
process.env.ONE_SERVER_URL = originalEnv
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('applies default priority to all routes', () => {
|
|
61
|
+
const routes: RouteSitemapData[] = [{ path: '/' }, { path: '/about' }]
|
|
62
|
+
const options: One.SitemapOptions = {
|
|
63
|
+
priority: 0.8,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const result = generateSitemap(routes, options)
|
|
67
|
+
|
|
68
|
+
expect(result).toMatch(/<url>\s*<loc>\/about<\/loc>\s*<priority>0\.8<\/priority>\s*<\/url>/s)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('applies default changefreq to all routes', () => {
|
|
72
|
+
const routes: RouteSitemapData[] = [{ path: '/' }, { path: '/about' }]
|
|
73
|
+
const options: One.SitemapOptions = {
|
|
74
|
+
changefreq: 'weekly',
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const result = generateSitemap(routes, options)
|
|
78
|
+
|
|
79
|
+
expect(result).toContain('<changefreq>weekly</changefreq>')
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('respects route-level sitemap exports', () => {
|
|
83
|
+
const routes: RouteSitemapData[] = [
|
|
84
|
+
{ path: '/', routeExport: { priority: 1.0, changefreq: 'daily' } },
|
|
85
|
+
{ path: '/about', routeExport: { priority: 0.5, changefreq: 'monthly' } },
|
|
86
|
+
]
|
|
87
|
+
const options: One.SitemapOptions = {
|
|
88
|
+
priority: 0.7,
|
|
89
|
+
changefreq: 'weekly',
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const result = generateSitemap(routes, options)
|
|
93
|
+
|
|
94
|
+
// Route exports should override defaults
|
|
95
|
+
expect(result).toMatch(
|
|
96
|
+
/<url>\s*<loc>\/<\/loc>\s*<changefreq>daily<\/changefreq>\s*<priority>1\.0<\/priority>\s*<\/url>/s
|
|
97
|
+
)
|
|
98
|
+
expect(result).toMatch(
|
|
99
|
+
/<url>\s*<loc>\/about<\/loc>\s*<changefreq>monthly<\/changefreq>\s*<priority>0\.5<\/priority>\s*<\/url>/s
|
|
100
|
+
)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('excludes routes with routeExport.exclude = true', () => {
|
|
104
|
+
const routes: RouteSitemapData[] = [
|
|
105
|
+
{ path: '/' },
|
|
106
|
+
{ path: '/admin', routeExport: { exclude: true } },
|
|
107
|
+
{ path: '/about' },
|
|
108
|
+
]
|
|
109
|
+
const options: One.SitemapOptions = {}
|
|
110
|
+
|
|
111
|
+
const result = generateSitemap(routes, options)
|
|
112
|
+
|
|
113
|
+
expect(result).toContain('<loc>/</loc>')
|
|
114
|
+
expect(result).toContain('<loc>/about</loc>')
|
|
115
|
+
expect(result).not.toContain('/admin')
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('excludes routes matching exclude glob patterns', () => {
|
|
119
|
+
const routes: RouteSitemapData[] = [
|
|
120
|
+
{ path: '/' },
|
|
121
|
+
{ path: '/admin/dashboard' },
|
|
122
|
+
{ path: '/admin/users' },
|
|
123
|
+
{ path: '/about' },
|
|
124
|
+
{ path: '/api/health' },
|
|
125
|
+
]
|
|
126
|
+
const options: One.SitemapOptions = {
|
|
127
|
+
exclude: ['/admin/*', '/api/*'],
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const result = generateSitemap(routes, options)
|
|
131
|
+
|
|
132
|
+
expect(result).toContain('<loc>/</loc>')
|
|
133
|
+
expect(result).toContain('<loc>/about</loc>')
|
|
134
|
+
expect(result).not.toContain('/admin')
|
|
135
|
+
expect(result).not.toContain('/api')
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('includes lastmod when provided in route export', () => {
|
|
139
|
+
const routes: RouteSitemapData[] = [
|
|
140
|
+
{ path: '/', routeExport: { lastmod: '2024-01-15' } },
|
|
141
|
+
{ path: '/about', routeExport: { lastmod: new Date('2024-06-20') } },
|
|
142
|
+
]
|
|
143
|
+
const options: One.SitemapOptions = {}
|
|
144
|
+
|
|
145
|
+
const result = generateSitemap(routes, options)
|
|
146
|
+
|
|
147
|
+
expect(result).toContain('<lastmod>2024-01-15</lastmod>')
|
|
148
|
+
expect(result).toContain('<lastmod>2024-06-20</lastmod>')
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it('escapes XML special characters in URLs', () => {
|
|
152
|
+
const routes: RouteSitemapData[] = [{ path: '/search?q=foo&bar=baz' }]
|
|
153
|
+
const options: One.SitemapOptions = {
|
|
154
|
+
baseUrl: 'https://example.com',
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const result = generateSitemap(routes, options)
|
|
158
|
+
|
|
159
|
+
expect(result).toContain('&')
|
|
160
|
+
expect(result).not.toContain('&bar')
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('generates empty sitemap when no routes', () => {
|
|
164
|
+
const routes: RouteSitemapData[] = []
|
|
165
|
+
const options: One.SitemapOptions = {}
|
|
166
|
+
|
|
167
|
+
const result = generateSitemap(routes, options)
|
|
168
|
+
|
|
169
|
+
expect(result).toContain('<?xml version="1.0" encoding="UTF-8"?>')
|
|
170
|
+
expect(result).toContain('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">')
|
|
171
|
+
expect(result).toContain('</urlset>')
|
|
172
|
+
expect(result).not.toContain('<url>')
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('handles all valid changefreq values', () => {
|
|
176
|
+
const changefreqs: One.SitemapChangefreq[] = [
|
|
177
|
+
'always',
|
|
178
|
+
'hourly',
|
|
179
|
+
'daily',
|
|
180
|
+
'weekly',
|
|
181
|
+
'monthly',
|
|
182
|
+
'yearly',
|
|
183
|
+
'never',
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
for (const changefreq of changefreqs) {
|
|
187
|
+
const routes: RouteSitemapData[] = [{ path: '/', routeExport: { changefreq } }]
|
|
188
|
+
const result = generateSitemap(routes, {})
|
|
189
|
+
expect(result).toContain(`<changefreq>${changefreq}</changefreq>`)
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('formats priority with one decimal place', () => {
|
|
194
|
+
const routes: RouteSitemapData[] = [
|
|
195
|
+
{ path: '/', routeExport: { priority: 1 } },
|
|
196
|
+
{ path: '/about', routeExport: { priority: 0.5 } },
|
|
197
|
+
{ path: '/blog', routeExport: { priority: 0.75 } },
|
|
198
|
+
]
|
|
199
|
+
const options: One.SitemapOptions = {}
|
|
200
|
+
|
|
201
|
+
const result = generateSitemap(routes, options)
|
|
202
|
+
|
|
203
|
+
expect(result).toContain('<priority>1.0</priority>')
|
|
204
|
+
expect(result).toContain('<priority>0.5</priority>')
|
|
205
|
+
expect(result).toContain('<priority>0.8</priority>') // 0.75 rounds to 0.8
|
|
206
|
+
})
|
|
207
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import MicroMatch from 'micromatch'
|
|
2
|
+
import type { One } from '../vite/types'
|
|
3
|
+
|
|
4
|
+
export type SitemapEntry = {
|
|
5
|
+
path: string
|
|
6
|
+
priority?: number
|
|
7
|
+
changefreq?: One.SitemapChangefreq
|
|
8
|
+
lastmod?: string | Date
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type RouteSitemapData = {
|
|
12
|
+
path: string
|
|
13
|
+
routeExport?: One.RouteSitemapExport
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function generateSitemap(routes: RouteSitemapData[], options: One.SitemapOptions): string {
|
|
17
|
+
const envUrl = process.env.ONE_SERVER_URL
|
|
18
|
+
const baseUrl = options.baseUrl ?? (envUrl && envUrl !== 'undefined' ? envUrl : '')
|
|
19
|
+
const defaultPriority = options.priority ?? 0.5
|
|
20
|
+
const defaultChangefreq = options.changefreq
|
|
21
|
+
const excludePatterns = options.exclude || []
|
|
22
|
+
|
|
23
|
+
const entries: SitemapEntry[] = []
|
|
24
|
+
|
|
25
|
+
for (const route of routes) {
|
|
26
|
+
const { path, routeExport } = route
|
|
27
|
+
|
|
28
|
+
// Skip if route exports exclude: true
|
|
29
|
+
if (routeExport?.exclude) {
|
|
30
|
+
continue
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Skip if path matches any exclude pattern
|
|
34
|
+
if (excludePatterns.length > 0 && MicroMatch.isMatch(path, excludePatterns)) {
|
|
35
|
+
continue
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const priority = routeExport?.priority ?? defaultPriority
|
|
39
|
+
const changefreq = routeExport?.changefreq ?? defaultChangefreq
|
|
40
|
+
const lastmod = routeExport?.lastmod
|
|
41
|
+
|
|
42
|
+
entries.push({
|
|
43
|
+
path,
|
|
44
|
+
priority,
|
|
45
|
+
changefreq,
|
|
46
|
+
lastmod,
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return buildSitemapXml(entries, baseUrl)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function buildSitemapXml(entries: SitemapEntry[], baseUrl: string): string {
|
|
54
|
+
const urlEntries = entries
|
|
55
|
+
.map((entry) => {
|
|
56
|
+
const loc = baseUrl ? `${baseUrl.replace(/\/$/, '')}${entry.path}` : entry.path
|
|
57
|
+
|
|
58
|
+
let xml = ` <url>\n <loc>${escapeXml(loc)}</loc>`
|
|
59
|
+
|
|
60
|
+
if (entry.lastmod) {
|
|
61
|
+
const date =
|
|
62
|
+
entry.lastmod instanceof Date ? entry.lastmod.toISOString().split('T')[0] : entry.lastmod
|
|
63
|
+
xml += `\n <lastmod>${escapeXml(date)}</lastmod>`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (entry.changefreq) {
|
|
67
|
+
xml += `\n <changefreq>${entry.changefreq}</changefreq>`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (entry.priority !== undefined) {
|
|
71
|
+
xml += `\n <priority>${entry.priority.toFixed(1)}</priority>`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
xml += '\n </url>'
|
|
75
|
+
return xml
|
|
76
|
+
})
|
|
77
|
+
.join('\n')
|
|
78
|
+
|
|
79
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
80
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
81
|
+
${urlEntries}
|
|
82
|
+
</urlset>
|
|
83
|
+
`
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function escapeXml(str: string): string {
|
|
87
|
+
return str
|
|
88
|
+
.replace(/&/g, '&')
|
|
89
|
+
.replace(/</g, '<')
|
|
90
|
+
.replace(/>/g, '>')
|
|
91
|
+
.replace(/"/g, '"')
|
|
92
|
+
.replace(/'/g, ''')
|
|
93
|
+
}
|
package/src/vite/one.ts
CHANGED
|
@@ -284,6 +284,16 @@ export function one(options: One.PluginOptions = {}): PluginOption {
|
|
|
284
284
|
config() {
|
|
285
285
|
return {
|
|
286
286
|
define: {
|
|
287
|
+
// we define this not in environment.client because there must be a bug in vite
|
|
288
|
+
// it doesnt define the import.meta.env at all if you do that
|
|
289
|
+
'process.env.TAMAGUI_ENVIRONMENT': '"client"',
|
|
290
|
+
'process.env.VITE_ENVIRONMENT': '"client"',
|
|
291
|
+
'import.meta.env.VITE_ENVIRONMENT': '"client"',
|
|
292
|
+
'process.env.VITE_PLATFORM': '"web"',
|
|
293
|
+
'import.meta.env.VITE_PLATFORM': '"web"',
|
|
294
|
+
'process.env.EXPO_OS': '"web"',
|
|
295
|
+
'import.meta.env.EXPO_OS': '"web"',
|
|
296
|
+
|
|
287
297
|
...(options.web?.defaultRenderMode && {
|
|
288
298
|
'process.env.ONE_DEFAULT_RENDER_MODE': JSON.stringify(options.web.defaultRenderMode),
|
|
289
299
|
'import.meta.env.ONE_DEFAULT_RENDER_MODE': JSON.stringify(
|
|
@@ -344,39 +354,46 @@ export function one(options: One.PluginOptions = {}): PluginOption {
|
|
|
344
354
|
},
|
|
345
355
|
|
|
346
356
|
environments: {
|
|
347
|
-
client
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
},
|
|
354
|
-
},
|
|
357
|
+
// we define client vars not in environment.client because there must be a bug in vite
|
|
358
|
+
// it doesnt define the import.meta.env at all if you do that
|
|
359
|
+
// client: {
|
|
360
|
+
// define: {
|
|
361
|
+
// },
|
|
362
|
+
// },
|
|
355
363
|
|
|
356
364
|
ssr: {
|
|
357
365
|
define: {
|
|
358
|
-
'process.env.VITE_ENVIRONMENT': '"ssr"', // Note that we are also setting `process.env.VITE_ENVIRONMENT = 'ssr'` for this current process. See `setServerGlobals()` and `setupServerGlobals.ts`.
|
|
359
366
|
'process.env.TAMAGUI_ENVIRONMENT': '"ssr"',
|
|
367
|
+
'process.env.VITE_ENVIRONMENT': '"ssr"', // Note that we are also setting `process.env.VITE_ENVIRONMENT = 'ssr'` for this current process. See `setServerGlobals()` and `setupServerGlobals.ts`.
|
|
360
368
|
'import.meta.env.VITE_ENVIRONMENT': '"ssr"',
|
|
369
|
+
'process.env.VITE_PLATFORM': '"web"',
|
|
370
|
+
'import.meta.env.VITE_PLATFORM': '"web"',
|
|
361
371
|
'process.env.EXPO_OS': '"web"',
|
|
372
|
+
'import.meta.env.EXPO_OS': '"web"',
|
|
362
373
|
},
|
|
363
374
|
},
|
|
364
375
|
|
|
365
376
|
ios: {
|
|
366
377
|
define: {
|
|
367
|
-
'process.env.VITE_ENVIRONMENT': '"ios"',
|
|
368
378
|
'process.env.TAMAGUI_ENVIRONMENT': '"ios"',
|
|
379
|
+
'process.env.VITE_ENVIRONMENT': '"ios"',
|
|
369
380
|
'import.meta.env.VITE_ENVIRONMENT': '"ios"',
|
|
381
|
+
'process.env.VITE_PLATFORM': '"native"',
|
|
382
|
+
'import.meta.env.VITE_PLATFORM': '"native"',
|
|
370
383
|
'process.env.EXPO_OS': '"ios"',
|
|
384
|
+
'import.meta.env.EXPO_OS': '"ios"',
|
|
371
385
|
},
|
|
372
386
|
},
|
|
373
387
|
|
|
374
388
|
android: {
|
|
375
389
|
define: {
|
|
376
|
-
'process.env.VITE_ENVIRONMENT': '"android"',
|
|
377
390
|
'process.env.TAMAGUI_ENVIRONMENT': '"android"',
|
|
391
|
+
'process.env.VITE_ENVIRONMENT': '"android"',
|
|
378
392
|
'import.meta.env.VITE_ENVIRONMENT': '"android"',
|
|
393
|
+
'process.env.VITE_PLATFORM': '"native"',
|
|
394
|
+
'import.meta.env.VITE_PLATFORM': '"native"',
|
|
379
395
|
'process.env.EXPO_OS': '"android"',
|
|
396
|
+
'import.meta.env.EXPO_OS': '"android"',
|
|
380
397
|
},
|
|
381
398
|
},
|
|
382
399
|
},
|
package/src/vite/types.ts
CHANGED
|
@@ -342,6 +342,30 @@ export namespace One {
|
|
|
342
342
|
* @default false
|
|
343
343
|
*/
|
|
344
344
|
inlineLayoutCSS?: boolean
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Generate a sitemap.xml file during build.
|
|
348
|
+
*
|
|
349
|
+
* Set to `true` for default behavior, or pass an object to configure:
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* sitemap: true
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* sitemap: {
|
|
356
|
+
* baseUrl: 'https://example.com', // defaults to ONE_SERVER_URL env var
|
|
357
|
+
* priority: 0.7, // default priority for all routes
|
|
358
|
+
* changefreq: 'weekly', // default changefreq for all routes
|
|
359
|
+
* exclude: ['/admin/*', '/api/*'], // glob patterns to exclude
|
|
360
|
+
* }
|
|
361
|
+
*
|
|
362
|
+
* Routes can also export sitemap metadata:
|
|
363
|
+
* ```ts
|
|
364
|
+
* export const sitemap = { priority: 0.9, changefreq: 'daily' }
|
|
365
|
+
* // or exclude: export const sitemap = { exclude: true }
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
sitemap?: boolean | SitemapOptions
|
|
345
369
|
}
|
|
346
370
|
|
|
347
371
|
server?: VXRNOptions['server']
|
|
@@ -442,4 +466,53 @@ export namespace One {
|
|
|
442
466
|
/** See PluginOptions.router.experimental.PreventLayoutRemounting */
|
|
443
467
|
experimentalPreventLayoutRemounting?: boolean
|
|
444
468
|
}
|
|
469
|
+
|
|
470
|
+
export type SitemapChangefreq =
|
|
471
|
+
| 'always'
|
|
472
|
+
| 'hourly'
|
|
473
|
+
| 'daily'
|
|
474
|
+
| 'weekly'
|
|
475
|
+
| 'monthly'
|
|
476
|
+
| 'yearly'
|
|
477
|
+
| 'never'
|
|
478
|
+
|
|
479
|
+
export type SitemapOptions = {
|
|
480
|
+
/**
|
|
481
|
+
* Base URL for the sitemap. Defaults to ONE_SERVER_URL environment variable.
|
|
482
|
+
*/
|
|
483
|
+
baseUrl?: string
|
|
484
|
+
/**
|
|
485
|
+
* Default priority for all routes (0.0 to 1.0).
|
|
486
|
+
* @default 0.5
|
|
487
|
+
*/
|
|
488
|
+
priority?: number
|
|
489
|
+
/**
|
|
490
|
+
* Default change frequency for all routes.
|
|
491
|
+
*/
|
|
492
|
+
changefreq?: SitemapChangefreq
|
|
493
|
+
/**
|
|
494
|
+
* Glob patterns for routes to exclude from the sitemap.
|
|
495
|
+
* API routes and not-found routes are always excluded.
|
|
496
|
+
*/
|
|
497
|
+
exclude?: string[]
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
export type RouteSitemapExport = {
|
|
501
|
+
/**
|
|
502
|
+
* Priority for this route (0.0 to 1.0).
|
|
503
|
+
*/
|
|
504
|
+
priority?: number
|
|
505
|
+
/**
|
|
506
|
+
* Change frequency for this route.
|
|
507
|
+
*/
|
|
508
|
+
changefreq?: SitemapChangefreq
|
|
509
|
+
/**
|
|
510
|
+
* Last modification date for this route.
|
|
511
|
+
*/
|
|
512
|
+
lastmod?: string | Date
|
|
513
|
+
/**
|
|
514
|
+
* Exclude this route from the sitemap.
|
|
515
|
+
*/
|
|
516
|
+
exclude?: boolean
|
|
517
|
+
}
|
|
445
518
|
}
|
package/types/cli/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAoCA,wBAAsB,KAAK,CAAC,IAAI,EAAE;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAA;CACrC,iBAqmBA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { One } from '../vite/types';
|
|
2
|
+
export type SitemapEntry = {
|
|
3
|
+
path: string;
|
|
4
|
+
priority?: number;
|
|
5
|
+
changefreq?: One.SitemapChangefreq;
|
|
6
|
+
lastmod?: string | Date;
|
|
7
|
+
};
|
|
8
|
+
export type RouteSitemapData = {
|
|
9
|
+
path: string;
|
|
10
|
+
routeExport?: One.RouteSitemapExport;
|
|
11
|
+
};
|
|
12
|
+
export declare function generateSitemap(routes: RouteSitemapData[], options: One.SitemapOptions): string;
|
|
13
|
+
//# sourceMappingURL=generateSitemap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSitemap.d.ts","sourceRoot":"","sources":["../../src/cli/generateSitemap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAA;IAClC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,GAAG,CAAC,kBAAkB,CAAA;CACrC,CAAA;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,cAAc,GAAG,MAAM,CAmC/F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSitemap.test.d.ts","sourceRoot":"","sources":["../../src/cli/generateSitemap.test.ts"],"names":[],"mappings":""}
|
package/types/env.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
interface OneEnvVariables {
|
|
4
|
+
// Core One variables
|
|
5
|
+
/** Random number for each production build, or stable per dev server run. Useful for cache keys. */
|
|
6
|
+
ONE_CACHE_KEY: string
|
|
7
|
+
/** Your app.key setting from vite.config */
|
|
8
|
+
ONE_APP_NAME: string
|
|
9
|
+
/** Current running server URL in development, e.g. "http://0.0.0.0:8081". Set this yourself for production. */
|
|
10
|
+
ONE_SERVER_URL: string
|
|
11
|
+
/** "ssr", "ssg", or "spa" based on your defaultRenderMode setting */
|
|
12
|
+
ONE_DEFAULT_RENDER_MODE: 'ssr' | 'ssg' | 'spa'
|
|
13
|
+
|
|
14
|
+
// Platform detection
|
|
15
|
+
/** "client" for client-side web, "ssr" for server-side web, "ios" or "android" for native */
|
|
16
|
+
VITE_ENVIRONMENT: 'client' | 'ssr' | 'ios' | 'android'
|
|
17
|
+
/** "web" for all web builds (client and SSR), "native" for native platforms (iOS and Android) */
|
|
18
|
+
VITE_PLATFORM: 'web' | 'native'
|
|
19
|
+
/** "web" for web builds, "ios" or "android" for native. Matches Expo convention. */
|
|
20
|
+
EXPO_OS: 'web' | 'ios' | 'android'
|
|
21
|
+
|
|
22
|
+
// React Native (available in native builds)
|
|
23
|
+
/** The React Native version string */
|
|
24
|
+
REACT_NATIVE_VERSION: string
|
|
25
|
+
/** "ios" or "android" in native builds */
|
|
26
|
+
REACT_NATIVE_PLATFORM: 'ios' | 'android'
|
|
27
|
+
/** Dev server port for React Native */
|
|
28
|
+
REACT_NATIVE_SERVER_PUBLIC_PORT: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare global {
|
|
32
|
+
namespace NodeJS {
|
|
33
|
+
interface ProcessEnv extends Partial<OneEnvVariables> {}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface ImportMetaEnv extends Partial<OneEnvVariables> {}
|
|
38
|
+
|
|
39
|
+
interface ImportMeta {
|
|
40
|
+
readonly env: ImportMetaEnv
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export {}
|
package/types/vite/one.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"one.d.ts","sourceRoot":"","sources":["../../src/vite/one.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,MAAM,CAAA;AAOhD,OAAO,qBAAqB,CAAA;AAW5B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAoBlC,wBAAgB,GAAG,CAAC,OAAO,GAAE,GAAG,CAAC,aAAkB,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"one.d.ts","sourceRoot":"","sources":["../../src/vite/one.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,MAAM,CAAA;AAOhD,OAAO,qBAAqB,CAAA;AAW5B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAoBlC,wBAAgB,GAAG,CAAC,OAAO,GAAE,GAAG,CAAC,aAAkB,GAAG,YAAY,CA8jBjE"}
|