one 1.21.1 → 1.21.3
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 +9 -8
- package/dist/cjs/cli/build.native.js +17 -16
- package/dist/cjs/cli/build.native.js.map +1 -1
- package/dist/cjs/cli/buildPage.cjs +1 -1
- package/dist/cjs/cli/buildPage.native.js +1 -1
- package/dist/cjs/cli/buildPage.native.js.map +1 -1
- package/dist/cjs/daemon/ipc.cjs +21 -3
- package/dist/cjs/daemon/ipc.native.js +21 -3
- package/dist/cjs/daemon/ipc.native.js.map +1 -1
- package/dist/cjs/router/getRoutes.cjs +1 -2
- package/dist/cjs/router/getRoutes.native.js +1 -2
- package/dist/cjs/router/getRoutes.native.js.map +1 -1
- package/dist/cjs/router/hmrImport.native.js +13 -2
- package/dist/cjs/router/hmrImport.native.js.map +1 -1
- package/dist/cjs/router/hmrImport.native.test.cjs +52 -0
- package/dist/cjs/router/hmrImport.native.test.native.js +61 -0
- package/dist/cjs/router/hmrImport.native.test.native.js.map +1 -0
- package/dist/cjs/router/matchers.cjs +7 -0
- package/dist/cjs/router/matchers.native.js +8 -0
- package/dist/cjs/router/matchers.native.js.map +1 -1
- package/dist/cjs/router/routeHmr.cjs +32 -0
- package/dist/cjs/router/routeHmr.native.js +57 -0
- package/dist/cjs/router/routeHmr.native.js.map +1 -0
- package/dist/cjs/router/routeHmr.native.test.cjs +83 -0
- package/dist/cjs/router/routeHmr.native.test.native.js +95 -0
- package/dist/cjs/router/routeHmr.native.test.native.js.map +1 -0
- package/dist/cjs/router/useScreens.cjs +2 -0
- package/dist/cjs/router/useScreens.native.js +2 -0
- package/dist/cjs/router/useScreens.native.js.map +1 -1
- package/dist/cjs/router/useViteRoutes.cjs +7 -17
- package/dist/cjs/router/useViteRoutes.native.js +8 -18
- package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
- package/dist/cjs/router/useViteRoutes.test.cjs +42 -0
- package/dist/cjs/router/useViteRoutes.test.native.js +55 -0
- package/dist/cjs/router/useViteRoutes.test.native.js.map +1 -0
- package/dist/cjs/utils/cleanUrl.cjs +12 -2
- package/dist/cjs/utils/cleanUrl.native.js +15 -3
- package/dist/cjs/utils/cleanUrl.native.js.map +1 -1
- package/dist/cjs/utils/cleanUrl.test.cjs +37 -0
- package/dist/cjs/utils/cleanUrl.test.native.js +37 -0
- package/dist/cjs/utils/cleanUrl.test.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +37 -2
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +70 -8
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.test.cjs +58 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js +62 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
- package/dist/esm/cli/build.mjs +9 -8
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +17 -16
- package/dist/esm/cli/build.native.js.map +1 -1
- package/dist/esm/cli/buildPage.mjs +2 -2
- package/dist/esm/cli/buildPage.mjs.map +1 -1
- package/dist/esm/cli/buildPage.native.js +2 -2
- package/dist/esm/cli/buildPage.native.js.map +1 -1
- package/dist/esm/daemon/ipc.mjs +21 -3
- package/dist/esm/daemon/ipc.mjs.map +1 -1
- package/dist/esm/daemon/ipc.native.js +21 -3
- package/dist/esm/daemon/ipc.native.js.map +1 -1
- package/dist/esm/getURL.native.test.mjs +1 -1
- package/dist/esm/router/getRoutes.mjs +2 -3
- package/dist/esm/router/getRoutes.mjs.map +1 -1
- package/dist/esm/router/getRoutes.native.js +2 -3
- package/dist/esm/router/getRoutes.native.js.map +1 -1
- package/dist/esm/router/hmrImport.native.js +13 -2
- package/dist/esm/router/hmrImport.native.js.map +1 -1
- package/dist/esm/router/hmrImport.native.test.js +51 -0
- package/dist/esm/router/hmrImport.native.test.js.map +6 -0
- package/dist/esm/router/hmrImport.native.test.mjs +53 -0
- package/dist/esm/router/hmrImport.native.test.mjs.map +1 -0
- package/dist/esm/router/hmrImport.native.test.native.js +59 -0
- package/dist/esm/router/hmrImport.native.test.native.js.map +1 -0
- package/dist/esm/router/matchers.mjs +7 -1
- package/dist/esm/router/matchers.mjs.map +1 -1
- package/dist/esm/router/matchers.native.js +8 -1
- package/dist/esm/router/matchers.native.js.map +1 -1
- package/dist/esm/router/routeHmr.mjs +6 -0
- package/dist/esm/router/routeHmr.mjs.map +1 -0
- package/dist/esm/router/routeHmr.native.js +28 -0
- package/dist/esm/router/routeHmr.native.js.map +1 -0
- package/dist/esm/router/routeHmr.native.test.js +58 -0
- package/dist/esm/router/routeHmr.native.test.js.map +6 -0
- package/dist/esm/router/routeHmr.native.test.mjs +60 -0
- package/dist/esm/router/routeHmr.native.test.mjs.map +1 -0
- package/dist/esm/router/routeHmr.native.test.native.js +69 -0
- package/dist/esm/router/routeHmr.native.test.native.js.map +1 -0
- package/dist/esm/router/useScreens.mjs +1 -0
- package/dist/esm/router/useScreens.mjs.map +1 -1
- package/dist/esm/router/useScreens.native.js +2 -0
- package/dist/esm/router/useScreens.native.js.map +1 -1
- package/dist/esm/router/useViteRoutes.mjs +7 -17
- package/dist/esm/router/useViteRoutes.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.native.js +8 -18
- package/dist/esm/router/useViteRoutes.native.js.map +1 -1
- package/dist/esm/router/useViteRoutes.test.mjs +43 -0
- package/dist/esm/router/useViteRoutes.test.mjs.map +1 -0
- package/dist/esm/router/useViteRoutes.test.native.js +53 -0
- package/dist/esm/router/useViteRoutes.test.native.js.map +1 -0
- package/dist/esm/utils/cleanUrl.mjs +11 -3
- package/dist/esm/utils/cleanUrl.mjs.map +1 -1
- package/dist/esm/utils/cleanUrl.native.js +14 -4
- package/dist/esm/utils/cleanUrl.native.js.map +1 -1
- package/dist/esm/utils/cleanUrl.test.mjs +38 -1
- package/dist/esm/utils/cleanUrl.test.mjs.map +1 -1
- package/dist/esm/utils/cleanUrl.test.native.js +38 -1
- package/dist/esm/utils/cleanUrl.test.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +26 -2
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +59 -8
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.mjs +58 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.native.js +62 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
- package/package.json +9 -9
- package/src/cli/build.ts +18 -11
- package/src/cli/buildPage.ts +12 -2
- package/src/daemon/ipc.ts +46 -4
- package/src/router/getRoutes.ts +2 -3
- package/src/router/hmrImport.native.test.ts +55 -0
- package/src/router/hmrImport.native.ts +25 -5
- package/src/router/matchers.ts +10 -0
- package/src/router/routeHmr.native.test.ts +71 -0
- package/src/router/routeHmr.native.ts +37 -0
- package/src/router/routeHmr.ts +8 -0
- package/src/router/useScreens.tsx +12 -0
- package/src/router/useViteRoutes.test.ts +49 -0
- package/src/router/useViteRoutes.tsx +12 -21
- package/src/utils/cleanUrl.test.ts +63 -1
- package/src/utils/cleanUrl.ts +25 -3
- package/src/vite/plugins/virtualEntryPlugin.test.ts +70 -0
- package/src/vite/plugins/virtualEntryPlugin.ts +48 -2
- package/src/vite/types.ts +9 -0
- package/types/cli/build.d.ts.map +1 -1
- package/types/cli/buildPage.d.ts.map +1 -1
- package/types/daemon/ipc.d.ts.map +1 -1
- package/types/router/getRoutes.d.ts.map +1 -1
- package/types/router/hmrImport.native.d.ts +8 -3
- package/types/router/hmrImport.native.d.ts.map +1 -1
- package/types/router/hmrImport.native.test.d.ts +2 -0
- package/types/router/hmrImport.native.test.d.ts.map +1 -0
- package/types/router/matchers.d.ts +2 -0
- package/types/router/matchers.d.ts.map +1 -1
- package/types/router/routeHmr.d.ts +3 -0
- package/types/router/routeHmr.d.ts.map +1 -0
- package/types/router/routeHmr.native.d.ts +6 -0
- package/types/router/routeHmr.native.d.ts.map +1 -0
- package/types/router/routeHmr.native.test.d.ts +2 -0
- package/types/router/routeHmr.native.test.d.ts.map +1 -0
- package/types/router/useScreens.d.ts.map +1 -1
- package/types/router/useViteRoutes.d.ts.map +1 -1
- package/types/router/useViteRoutes.test.d.ts +2 -0
- package/types/router/useViteRoutes.test.d.ts.map +1 -0
- package/types/utils/cleanUrl.d.ts +2 -0
- package/types/utils/cleanUrl.d.ts.map +1 -1
- package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
- package/types/vite/types.d.ts +8 -0
- package/types/vite/types.d.ts.map +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { hmrImport } from './hmrImport.native'
|
|
3
|
+
|
|
4
|
+
const realRuntime = (globalThis as any).__rolldown_runtime__
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
;(globalThis as any).__rolldown_runtime__ = realRuntime
|
|
7
|
+
vi.restoreAllMocks()
|
|
8
|
+
})
|
|
9
|
+
const setRuntime = (runtime: unknown) => {
|
|
10
|
+
;(globalThis as any).__rolldown_runtime__ = runtime
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('hmrImport (native)', () => {
|
|
14
|
+
it('rejects when no runtime is present', async () => {
|
|
15
|
+
setRuntime(undefined)
|
|
16
|
+
await expect(hmrImport('foo.tsx')).rejects.toThrow(
|
|
17
|
+
'HMR import not supported on native'
|
|
18
|
+
)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('rejects when loadExports is missing', async () => {
|
|
22
|
+
setRuntime({})
|
|
23
|
+
await expect(hmrImport('foo.tsx')).rejects.toThrow(
|
|
24
|
+
'HMR import not supported on native'
|
|
25
|
+
)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('resolves with the runtime exports and strips ./ and / prefixes', async () => {
|
|
29
|
+
const exports = { default: () => null }
|
|
30
|
+
const loadExports = vi.fn(() => exports)
|
|
31
|
+
setRuntime({ loadExports })
|
|
32
|
+
|
|
33
|
+
await expect(hmrImport('./foo.tsx')).resolves.toBe(exports)
|
|
34
|
+
await expect(hmrImport('/foo.tsx')).resolves.toBe(exports)
|
|
35
|
+
await expect(hmrImport('foo.tsx')).resolves.toBe(exports)
|
|
36
|
+
expect(loadExports).toHaveBeenNthCalledWith(1, 'foo.tsx')
|
|
37
|
+
expect(loadExports).toHaveBeenNthCalledWith(2, 'foo.tsx')
|
|
38
|
+
expect(loadExports).toHaveBeenNthCalledWith(3, 'foo.tsx')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('rejects when loadExports returns null', async () => {
|
|
42
|
+
setRuntime({ loadExports: () => null })
|
|
43
|
+
await expect(hmrImport('foo.tsx')).rejects.toThrow('no exports for foo.tsx')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('rejects when loadExports throws', async () => {
|
|
47
|
+
const boom = new Error('boom')
|
|
48
|
+
setRuntime({
|
|
49
|
+
loadExports: () => {
|
|
50
|
+
throw boom
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
await expect(hmrImport('foo.tsx')).rejects.toBe(boom)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* native HMR re-import
|
|
3
|
+
*
|
|
4
|
+
* vxrn's native dev runtime re-registers the edited module into
|
|
5
|
+
* `globalThis.__rolldown_runtime__` before One evicts its route cache, so the
|
|
6
|
+
* fresh exports can be pulled straight from the runtime without dynamic `import()`
|
|
7
|
+
* (which Hermes cannot parse). Rejects when the runtime is unavailable so a
|
|
8
|
+
* broken development runtime is visible instead of serving a stale route.
|
|
4
9
|
*/
|
|
5
|
-
export function hmrImport(
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
export function hmrImport(path: string): Promise<any> {
|
|
11
|
+
const runtime = (
|
|
12
|
+
globalThis as typeof globalThis & {
|
|
13
|
+
__rolldown_runtime__?: { loadExports(id: string): unknown }
|
|
14
|
+
}
|
|
15
|
+
).__rolldown_runtime__
|
|
16
|
+
if (!runtime || typeof runtime.loadExports !== 'function') {
|
|
17
|
+
return Promise.reject(new Error('HMR import not supported on native'))
|
|
18
|
+
}
|
|
19
|
+
// route paths arrive as `./foo.tsx` / `/foo.tsx`; rolldown ids are bare (`foo.tsx`)
|
|
20
|
+
const id = path.replace(/^\.\//, '').replace(/^\//, '')
|
|
21
|
+
return Promise.resolve().then(() => {
|
|
22
|
+
const mod = runtime.loadExports(id)
|
|
23
|
+
if (mod == null) {
|
|
24
|
+
throw new Error(`no exports for ${id}`)
|
|
25
|
+
}
|
|
26
|
+
return mod
|
|
27
|
+
})
|
|
8
28
|
}
|
package/src/router/matchers.ts
CHANGED
|
@@ -169,6 +169,16 @@ export interface DirectoryRenderModeMatch {
|
|
|
169
169
|
renderMode: One.RouteRenderMode | 'api'
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/** match file render mode suffixes: index+ssr.tsx, feed+spa.web.tsx, etc. */
|
|
173
|
+
export function matchFileRenderMode(
|
|
174
|
+
name: string
|
|
175
|
+
): One.RouteRenderMode | 'api' | undefined {
|
|
176
|
+
const mode = name.match(/\+(api|ssg|ssr|spa)\.(?:\w+\.)?[jt]sx?$/)?.[1]
|
|
177
|
+
if (mode === 'api' || mode === 'ssg' || mode === 'ssr' || mode === 'spa') {
|
|
178
|
+
return mode
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
172
182
|
/**
|
|
173
183
|
* Match directory render mode suffixes
|
|
174
184
|
*
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
type RouteHmrModule = typeof import('./routeHmr.native')
|
|
4
|
+
|
|
5
|
+
describe('routeHmr.native', () => {
|
|
6
|
+
let routeHmr: RouteHmrModule
|
|
7
|
+
const realWindow = (globalThis as any).window
|
|
8
|
+
const realModuleUpdatedHook = globalThis.__VXRN_ON_MODULE_UPDATED__
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
// the __VXRN_ON_MODULE_UPDATED__ registration is dev-gated and runs at module
|
|
12
|
+
// load, so stub NODE_ENV then re-import to exercise it
|
|
13
|
+
vi.stubEnv('NODE_ENV', 'development')
|
|
14
|
+
vi.resetModules()
|
|
15
|
+
routeHmr = await import('./routeHmr.native')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
vi.unstubAllEnvs()
|
|
20
|
+
globalThis.__VXRN_ON_MODULE_UPDATED__ = realModuleUpdatedHook
|
|
21
|
+
;(globalThis as any).window = realWindow
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('registers globalThis.__VXRN_ON_MODULE_UPDATED__ in development', () => {
|
|
25
|
+
expect(typeof globalThis.__VXRN_ON_MODULE_UPDATED__).toBe('function')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('bumps the epoch and notifies subscribers, and stops after unsubscribe', () => {
|
|
29
|
+
const before = routeHmr.getRouteHmrEpoch()
|
|
30
|
+
const listener = vi.fn()
|
|
31
|
+
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
|
|
32
|
+
|
|
33
|
+
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')
|
|
34
|
+
expect(routeHmr.getRouteHmrEpoch()).toBe(before + 1)
|
|
35
|
+
expect(listener).toHaveBeenCalledTimes(1)
|
|
36
|
+
|
|
37
|
+
unsubscribe()
|
|
38
|
+
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')
|
|
39
|
+
expect(listener).toHaveBeenCalledTimes(1)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('evicts the route cache for the updated file when window.__oneRouteCache is present', () => {
|
|
43
|
+
const clearFile = vi.fn()
|
|
44
|
+
;(globalThis as any).window = { __oneRouteCache: { clearFile } }
|
|
45
|
+
globalThis.__VXRN_ON_MODULE_UPDATED__!('app/_layout.tsx')
|
|
46
|
+
expect(clearFile).toHaveBeenCalledWith('app/_layout.tsx')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('does not throw when window / route cache is absent', () => {
|
|
50
|
+
;(globalThis as any).window = undefined
|
|
51
|
+
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('x.tsx')).not.toThrow()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('still notifies subscribers when route-cache eviction throws', () => {
|
|
55
|
+
const listener = vi.fn()
|
|
56
|
+
const unsubscribe = routeHmr.subscribeRouteHmr(listener)
|
|
57
|
+
;(globalThis as any).window = {
|
|
58
|
+
__oneRouteCache: {
|
|
59
|
+
clearFile() {
|
|
60
|
+
throw new Error('cache eviction failed')
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
expect(() => globalThis.__VXRN_ON_MODULE_UPDATED__!('app/index.tsx')).toThrow(
|
|
66
|
+
'cache eviction failed'
|
|
67
|
+
)
|
|
68
|
+
expect(listener).toHaveBeenCalledOnce()
|
|
69
|
+
unsubscribe()
|
|
70
|
+
})
|
|
71
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// native Fast Refresh for One routes
|
|
2
|
+
//
|
|
3
|
+
// vxrn calls the global hook after committing an updated module. One evicts that
|
|
4
|
+
// route and bumps this external-store epoch so mounted screens load fresh exports.
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
// vxrn's native HMR runtime invokes this (when defined) with each committed
|
|
8
|
+
// module id, so a framework can react to a hot update.
|
|
9
|
+
var __VXRN_ON_MODULE_UPDATED__: ((moduleId: string) => void) | undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let routeHmrEpoch = 0
|
|
13
|
+
const routeHmrListeners = new Set<() => void>()
|
|
14
|
+
|
|
15
|
+
export const subscribeRouteHmr = (onStoreChange: () => void) => {
|
|
16
|
+
routeHmrListeners.add(onStoreChange)
|
|
17
|
+
return () => {
|
|
18
|
+
routeHmrListeners.delete(onStoreChange)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const getRouteHmrEpoch = () => routeHmrEpoch
|
|
23
|
+
|
|
24
|
+
if (process.env.NODE_ENV === 'development') {
|
|
25
|
+
globalThis.__VXRN_ON_MODULE_UPDATED__ = (id: string) => {
|
|
26
|
+
try {
|
|
27
|
+
const routeCache =
|
|
28
|
+
typeof window === 'undefined' ? undefined : (window as any).__oneRouteCache
|
|
29
|
+
if (typeof routeCache?.clearFile === 'function') {
|
|
30
|
+
routeCache.clearFile(id)
|
|
31
|
+
}
|
|
32
|
+
} finally {
|
|
33
|
+
routeHmrEpoch++
|
|
34
|
+
routeHmrListeners.forEach((listener) => listener())
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// web counterpart of routeHmr.native.ts. Web route Fast Refresh happens through
|
|
2
|
+
// the `one-hmr-update` event (see useScreens' web block), so this is a no-op store
|
|
3
|
+
// whose exports let useScreens import `./routeHmr` on either platform.
|
|
4
|
+
export const subscribeRouteHmr = (_onStoreChange: () => void): (() => void) => {
|
|
5
|
+
return () => {}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getRouteHmrEpoch = () => 0
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
import { SpaShellContext } from './SpaShellContext'
|
|
29
29
|
import { NamedSlot } from '../views/Navigator'
|
|
30
30
|
import { sortRoutesWithInitial } from './sortRoutes'
|
|
31
|
+
import { getRouteHmrEpoch, subscribeRouteHmr } from './routeHmr'
|
|
31
32
|
import { getClientMatchesSnapshot } from '../useMatches'
|
|
32
33
|
|
|
33
34
|
// `@react-navigation/core` does not expose the Screen or Group components directly, so we have to
|
|
@@ -395,6 +396,17 @@ export function getQualifiedRouteComponent(value: RouteNode) {
|
|
|
395
396
|
}, [])
|
|
396
397
|
}
|
|
397
398
|
|
|
399
|
+
// native Fast Refresh: subscribe to the route-hot epoch (the routeHmr.native
|
|
400
|
+
// store bumps it when vxrn reports a route module update) so this component
|
|
401
|
+
// re-renders and re-runs loadRoute() to pick up the edited module's exports
|
|
402
|
+
if (
|
|
403
|
+
process.env.NODE_ENV === 'development' &&
|
|
404
|
+
process.env.TAMAGUI_TARGET === 'native'
|
|
405
|
+
) {
|
|
406
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
407
|
+
React.useSyncExternalStore(subscribeRouteHmr, getRouteHmrEpoch, getRouteHmrEpoch)
|
|
408
|
+
}
|
|
409
|
+
|
|
398
410
|
// in spa-shell mode, only SSG/SSR layouts render on the server.
|
|
399
411
|
// SPA layouts and leaf pages get a placeholder, swapped for real
|
|
400
412
|
// content after hydration.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
|
|
3
|
+
const mocks = vi.hoisted(() => ({
|
|
4
|
+
hmrImport: vi.fn(),
|
|
5
|
+
}))
|
|
6
|
+
|
|
7
|
+
vi.mock('./hmrImport', () => ({
|
|
8
|
+
hmrImport: mocks.hmrImport,
|
|
9
|
+
}))
|
|
10
|
+
|
|
11
|
+
import { globbedRoutesToRouteContext } from './useViteRoutes'
|
|
12
|
+
|
|
13
|
+
const realWindow = (globalThis as any).window
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
vi.unstubAllEnvs()
|
|
17
|
+
mocks.hmrImport.mockReset()
|
|
18
|
+
;(globalThis as any).window = realWindow
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
async function resolveRoute(context: ReturnType<typeof globbedRoutesToRouteContext>) {
|
|
22
|
+
try {
|
|
23
|
+
return context('./index.tsx')
|
|
24
|
+
} catch (pending) {
|
|
25
|
+
await pending
|
|
26
|
+
return context('./index.tsx')
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('globbedRoutesToRouteContext HMR', () => {
|
|
31
|
+
it('evicts and reloads a route under a custom router root', async () => {
|
|
32
|
+
vi.stubEnv('NODE_ENV', 'development')
|
|
33
|
+
;(globalThis as any).window = {}
|
|
34
|
+
const initialRoute = { default: () => 'initial' }
|
|
35
|
+
const updatedRoute = { default: () => 'updated' }
|
|
36
|
+
const context = globbedRoutesToRouteContext(
|
|
37
|
+
{ '/routes/index.tsx': () => Promise.resolve(initialRoute) },
|
|
38
|
+
'routes'
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
await expect(resolveRoute(context)).resolves.toBe(initialRoute)
|
|
42
|
+
|
|
43
|
+
mocks.hmrImport.mockResolvedValue(updatedRoute)
|
|
44
|
+
;(globalThis as any).window.__oneRouteCache.clearFile('routes/index.tsx')
|
|
45
|
+
|
|
46
|
+
await expect(resolveRoute(context)).resolves.toBe(updatedRoute)
|
|
47
|
+
expect(mocks.hmrImport).toHaveBeenCalledWith('/routes/index.tsx')
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -221,24 +221,16 @@ export function globbedRoutesToRouteContext(
|
|
|
221
221
|
},
|
|
222
222
|
clearFile: (file: string) => {
|
|
223
223
|
hmrVersion++
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
delete promises[key]
|
|
235
|
-
}
|
|
236
|
-
})
|
|
237
|
-
Object.keys(preloadedModules).forEach((key) => {
|
|
238
|
-
if (key.includes(file)) {
|
|
239
|
-
delete preloadedModules[key]
|
|
240
|
-
}
|
|
241
|
-
})
|
|
224
|
+
const normalizedFile = file.replace(/\\/g, '/').replace(/^\//, '')
|
|
225
|
+
const routeId = moduleKeys.find(
|
|
226
|
+
(key) =>
|
|
227
|
+
routePaths[key].replace(/\\/g, '/').replace(/^\//, '') === normalizedFile
|
|
228
|
+
)
|
|
229
|
+
if (!routeId) return
|
|
230
|
+
|
|
231
|
+
delete loadedRoutes[routeId]
|
|
232
|
+
delete promises[routeId]
|
|
233
|
+
delete preloadedModules[routePaths[routeId]]
|
|
242
234
|
},
|
|
243
235
|
getVersion: () => hmrVersion,
|
|
244
236
|
}
|
|
@@ -264,11 +256,10 @@ export function globbedRoutesToRouteContext(
|
|
|
264
256
|
}
|
|
265
257
|
|
|
266
258
|
if (!promises[id]) {
|
|
267
|
-
//
|
|
268
|
-
// hmrImport is platform-specific: .native.ts returns rejected promise, base uses dynamic import()
|
|
259
|
+
// in dev mode after HMR, load the fresh module through the platform runtime
|
|
269
260
|
let importPromise: Promise<any>
|
|
270
261
|
if (process.env.NODE_ENV === 'development' && hmrVersion > 0 && routePaths[id]) {
|
|
271
|
-
importPromise = hmrImport(routePaths[id])
|
|
262
|
+
importPromise = hmrImport(routePaths[id])
|
|
272
263
|
} else {
|
|
273
264
|
importPromise = routesSync[id]()
|
|
274
265
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
encodeReservedFilenameChars,
|
|
4
|
+
getLoaderPath,
|
|
5
|
+
getPathFromLoaderPath,
|
|
6
|
+
getPreloadPath,
|
|
7
|
+
} from './cleanUrl'
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
* tests the cleanUrl encode/decode roundtrip used for loader URLs.
|
|
@@ -91,6 +96,63 @@ describe('getLoaderPath format', () => {
|
|
|
91
96
|
})
|
|
92
97
|
})
|
|
93
98
|
|
|
99
|
+
describe('NTFS-reserved characters in route-derived names', () => {
|
|
100
|
+
// route patterns reach these functions verbatim when a dynamic route has no
|
|
101
|
+
// generateStaticParams (every dynamic +ssr/+spa route at build time)
|
|
102
|
+
it('roundtrips a root dynamic route pattern', () => {
|
|
103
|
+
expect(roundtrip('/:param')).toBe('/:param')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('roundtrips a nested dynamic route pattern', () => {
|
|
107
|
+
expect(roundtrip('/dashboard/:appId')).toBe('/dashboard/:appId')
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
it('roundtrips a catch-all pattern', () => {
|
|
111
|
+
expect(roundtrip('/*')).toBe('/*')
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('roundtrips hostile concrete param values (chars that survive URL parsing raw)', () => {
|
|
115
|
+
// getLoaderPath URL-parses its input; WHATWG URL percent-encodes " < > |
|
|
116
|
+
// in pathnames but passes : and * through raw — those two are the ones
|
|
117
|
+
// that reach generated filenames verbatim (and are the NTFS killers)
|
|
118
|
+
expect(roundtrip('/blog/a:b*c')).toBe('/blog/a:b*c')
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('emits filesystem-legal names for the full reserved set via preload paths', () => {
|
|
122
|
+
// getPreloadPath does not URL-parse, so every reserved char reaches the
|
|
123
|
+
// encoder raw — assert none survive into the filename
|
|
124
|
+
expect(getPreloadPath('/blog/a:b*c"d<e>f|g?h')).not.toMatch(/[<>:"|?*]/)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('roundtrips literal equals signs (self-escape)', () => {
|
|
128
|
+
expect(roundtrip('/foo=bar')).toBe('/foo=bar')
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('roundtrips equals followed by hex-looking characters', () => {
|
|
132
|
+
expect(roundtrip('/x=3ay')).toBe('/x=3ay')
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('emits no NTFS-reserved characters in loader filenames', () => {
|
|
136
|
+
expect(getLoaderPath('/dashboard/:appId', false)).not.toMatch(/[<>:"|?*]/)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('emits no NTFS-reserved characters in preload filenames', () => {
|
|
140
|
+
expect(getPreloadPath('/:param')).not.toMatch(/[<>:"|?*]/)
|
|
141
|
+
expect(getPreloadPath('/*')).not.toMatch(/[<>:"|?*]/)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
it('encodeReservedFilenameChars is identity for clean paths', () => {
|
|
145
|
+
expect(encodeReservedFilenameChars('/blog/my-slug.html')).toBe('/blog/my-slug.html')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('encodes the html artifact path for non-prerendered dynamic routes', () => {
|
|
149
|
+
expect(encodeReservedFilenameChars('/dashboard/:appId.html')).toBe(
|
|
150
|
+
'/dashboard/=3aappId.html'
|
|
151
|
+
)
|
|
152
|
+
expect(encodeReservedFilenameChars('/*.html')).toBe('/=2a.html')
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
94
156
|
describe('getPathFromLoaderPath', () => {
|
|
95
157
|
it('strips /_one/assets prefix', () => {
|
|
96
158
|
expect(getPathFromLoaderPath('/_one/assets/docs_intro_999_vxrn_loader.js')).toBe(
|
package/src/utils/cleanUrl.ts
CHANGED
|
@@ -8,9 +8,31 @@ import {
|
|
|
8
8
|
import { getURL } from '../getURL'
|
|
9
9
|
import { removeSearch } from './removeSearch'
|
|
10
10
|
|
|
11
|
+
// Route patterns (`/:param`, `/*`) and concrete param values flow into
|
|
12
|
+
// generated artifact filenames. `< > : " | ? *` are reserved on Windows
|
|
13
|
+
// filesystems — a leading `:` segment fails outright and a mid-name `:`
|
|
14
|
+
// silently writes an NTFS alternate data stream — so encode them as `=hh`
|
|
15
|
+
// (hex char code), with literal `=` self-escaped first so decoding is
|
|
16
|
+
// unambiguous. Identity for paths without reserved characters.
|
|
17
|
+
export function encodeReservedFilenameChars(path: string) {
|
|
18
|
+
return path
|
|
19
|
+
.replaceAll('=', '=3d')
|
|
20
|
+
.replace(
|
|
21
|
+
/[<>:"|?*]/g,
|
|
22
|
+
(char) => `=${char.charCodeAt(0).toString(16).padStart(2, '0')}`
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function decodeReservedFilenameChars(path: string) {
|
|
27
|
+
return path.replace(/=([0-9a-f]{2})/g, (_match, hexCode) =>
|
|
28
|
+
String.fromCharCode(Number.parseInt(hexCode, 16))
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
11
32
|
function cleanUrl(path: string) {
|
|
12
|
-
return
|
|
13
|
-
.replace(/\/$/, '') // remove trailing slash before encoding
|
|
33
|
+
return encodeReservedFilenameChars(
|
|
34
|
+
removeSearch(path).replace(/\/$/, '') // remove trailing slash before encoding
|
|
35
|
+
)
|
|
14
36
|
.replaceAll('_', '__') // escape existing underscores
|
|
15
37
|
.replaceAll('/', '_') // use underscore as path separator
|
|
16
38
|
}
|
|
@@ -43,7 +65,7 @@ export function getLoaderPath(
|
|
|
43
65
|
}
|
|
44
66
|
|
|
45
67
|
export function getPathFromLoaderPath(loaderPath: string) {
|
|
46
|
-
return (
|
|
68
|
+
return decodeReservedFilenameChars(
|
|
47
69
|
loaderPath
|
|
48
70
|
.replace(LOADER_JS_POSTFIX_REGEX, '')
|
|
49
71
|
.replace(/^(\/_one)?\/assets/, '')
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer'
|
|
2
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { join, resolve } from 'node:path'
|
|
1
5
|
import { describe, expect, it, vi } from 'vitest'
|
|
6
|
+
import { build } from 'vite'
|
|
2
7
|
import { createVirtualEntry } from './virtualEntryPlugin'
|
|
3
8
|
|
|
4
9
|
// mock isNativeEnvironment
|
|
@@ -22,6 +27,71 @@ function loadEntry(plugin: any, envName: string, command: 'serve' | 'build' = 'b
|
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
describe('virtualEntryPlugin', () => {
|
|
30
|
+
it('keeps spa route matching without bundling the client module on the server', async () => {
|
|
31
|
+
const root = mkdtempSync(join(tmpdir(), 'one-spa-server-'))
|
|
32
|
+
const appDir = join(root, 'app')
|
|
33
|
+
mkdirSync(appDir)
|
|
34
|
+
const spaRoute = join(appDir, 'client-only+spa.tsx')
|
|
35
|
+
writeFileSync(
|
|
36
|
+
spaRoute,
|
|
37
|
+
`export const browserPayload = 'must-not-enter-server-graph'
|
|
38
|
+
export default function ClientOnlyPage() { return null }
|
|
39
|
+
`
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const result = await build({
|
|
44
|
+
root,
|
|
45
|
+
configFile: false,
|
|
46
|
+
logLevel: 'silent',
|
|
47
|
+
plugins: [
|
|
48
|
+
{
|
|
49
|
+
name: 'test-one-entry',
|
|
50
|
+
enforce: 'pre',
|
|
51
|
+
resolveId(id) {
|
|
52
|
+
if (id === 'one') return '\0test-one-entry'
|
|
53
|
+
},
|
|
54
|
+
load(id) {
|
|
55
|
+
if (id === '\0test-one-entry') {
|
|
56
|
+
return `export const createApp = (options) => options
|
|
57
|
+
export const registerPreloadedRoute = () => {}`
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
createVirtualEntry({ root: 'app', flags: {} }),
|
|
62
|
+
],
|
|
63
|
+
build: {
|
|
64
|
+
ssr: true,
|
|
65
|
+
write: false,
|
|
66
|
+
rolldownOptions: {
|
|
67
|
+
input: 'virtual:one-entry',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
if (Array.isArray(result)) throw new Error('expected one server build output')
|
|
72
|
+
if (!('output' in result)) throw new Error('expected completed server build')
|
|
73
|
+
|
|
74
|
+
const moduleIds = result.output.flatMap((output) =>
|
|
75
|
+
output.type === 'chunk' ? output.moduleIds : []
|
|
76
|
+
)
|
|
77
|
+
expect(moduleIds).not.toContain(resolve(spaRoute))
|
|
78
|
+
|
|
79
|
+
const entry = result.output.find(
|
|
80
|
+
(output) => output.type === 'chunk' && output.isEntry
|
|
81
|
+
)
|
|
82
|
+
if (!entry || entry.type !== 'chunk') throw new Error('missing server entry chunk')
|
|
83
|
+
const built = await import(
|
|
84
|
+
`data:text/javascript;base64,${Buffer.from(entry.code).toString('base64')}`
|
|
85
|
+
)
|
|
86
|
+
expect(Object.keys(built.default.routes)).toContain('/app/client-only+spa.tsx')
|
|
87
|
+
await expect(built.default.routes['/app/client-only+spa.tsx']()).resolves.toEqual(
|
|
88
|
+
{}
|
|
89
|
+
)
|
|
90
|
+
} finally {
|
|
91
|
+
rmSync(root, { recursive: true, force: true })
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
25
95
|
describe('setupFile', () => {
|
|
26
96
|
const base = {
|
|
27
97
|
root: 'app',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'node:path'
|
|
2
2
|
import { pathToFileURL } from 'node:url'
|
|
3
3
|
import { configuration } from '@vxrn/compiler'
|
|
4
|
+
import Glob from 'fast-glob'
|
|
4
5
|
import type { Plugin } from 'vite'
|
|
5
6
|
import { isNativeEnvironment } from 'vxrn'
|
|
6
7
|
import {
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
ROUTE_NATIVE_EXCLUSION_GLOB_PATTERNS,
|
|
10
11
|
ROUTE_WEB_EXCLUSION_GLOB_PATTERNS,
|
|
11
12
|
} from '../../router/glob-patterns'
|
|
13
|
+
import { matchDirectoryRenderMode, matchFileRenderMode } from '../../router/matchers'
|
|
12
14
|
import type { One } from '../types'
|
|
13
15
|
import {
|
|
14
16
|
resolvedVirtualEntryId,
|
|
@@ -151,6 +153,47 @@ export function createVirtualEntry(options: {
|
|
|
151
153
|
if (id === resolvedVirtualEntryId) {
|
|
152
154
|
const isNative = isNativeEnvironment(this.environment)
|
|
153
155
|
const isSSR = this.environment.name === 'ssr'
|
|
156
|
+
const serverSpaRouteFiles = isSSR
|
|
157
|
+
? Glob.sync('**/*.{ts,tsx}', {
|
|
158
|
+
cwd: resolve(viteRoot, options.root),
|
|
159
|
+
ignore: [
|
|
160
|
+
...ROUTE_WEB_EXCLUSION_GLOB_PATTERNS,
|
|
161
|
+
...(options.router?.ignoredRouteFiles || []),
|
|
162
|
+
],
|
|
163
|
+
})
|
|
164
|
+
.map((file) => file.replaceAll('\\', '/'))
|
|
165
|
+
.filter((file) => {
|
|
166
|
+
const parts = file.split('/')
|
|
167
|
+
const filename = parts.at(-1) || ''
|
|
168
|
+
if (
|
|
169
|
+
filename.startsWith('_layout') ||
|
|
170
|
+
filename.startsWith('_middleware')
|
|
171
|
+
) {
|
|
172
|
+
return false
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const fileMode = matchFileRenderMode(filename)
|
|
176
|
+
if (fileMode) return fileMode === 'spa'
|
|
177
|
+
|
|
178
|
+
let parentMode: One.RouteRenderMode | 'api' | undefined
|
|
179
|
+
for (const directory of parts.slice(0, -1)) {
|
|
180
|
+
parentMode =
|
|
181
|
+
matchDirectoryRenderMode(directory)?.renderMode ?? parentMode
|
|
182
|
+
}
|
|
183
|
+
return parentMode === 'spa'
|
|
184
|
+
})
|
|
185
|
+
: []
|
|
186
|
+
const serverSpaRouteStubs = serverSpaRouteFiles
|
|
187
|
+
.map(
|
|
188
|
+
(file) =>
|
|
189
|
+
`${JSON.stringify(`/${options.root}/${file}`)}: () => Promise.resolve({})`
|
|
190
|
+
)
|
|
191
|
+
.join(',\n ')
|
|
192
|
+
const webRouteGlobs = [
|
|
193
|
+
...routeGlobs,
|
|
194
|
+
...ROUTE_WEB_EXCLUSION_GLOB_PATTERNS.map((pattern) => `!${pattern}`),
|
|
195
|
+
...serverSpaRouteFiles.map((file) => `!/${options.root}/${file}`),
|
|
196
|
+
]
|
|
154
197
|
// native always needs static import. SSR in dev mode uses static import
|
|
155
198
|
// so Vite crawls the setupFile's dep tree (including react) and pre-bundles
|
|
156
199
|
// them before the first request. SSR in build mode uses lazy import so the
|
|
@@ -191,10 +234,13 @@ if (typeof window !== 'undefined') {
|
|
|
191
234
|
window.__oneRegisterPreloadedRoute = registerPreloadedRoute
|
|
192
235
|
}
|
|
193
236
|
|
|
194
|
-
// globbing ${JSON.stringify(
|
|
237
|
+
// globbing ${JSON.stringify(webRouteGlobs)}
|
|
195
238
|
export default createApp({
|
|
196
239
|
${setupPromiseArg}
|
|
197
|
-
routes:
|
|
240
|
+
routes: {
|
|
241
|
+
...import.meta.glob(${JSON.stringify(webRouteGlobs)}, { exhaustive: true }),
|
|
242
|
+
${serverSpaRouteStubs}
|
|
243
|
+
},
|
|
198
244
|
routerRoot: ${JSON.stringify(options.root)},
|
|
199
245
|
flags: ${JSON.stringify(options.flags)},
|
|
200
246
|
${linkingArg}
|
package/src/vite/types.ts
CHANGED
|
@@ -599,6 +599,15 @@ export namespace One {
|
|
|
599
599
|
server?: VXRNBuildOptions | false
|
|
600
600
|
api?: VXRNBuildOptions
|
|
601
601
|
|
|
602
|
+
/**
|
|
603
|
+
* maximum number of static pages to build concurrently.
|
|
604
|
+
* lower this when builds share a machine with other CPU-heavy work.
|
|
605
|
+
* `ONE_BUILD_CONCURRENCY` overrides this value.
|
|
606
|
+
*
|
|
607
|
+
* @default Math.min(available CPU cores, 8)
|
|
608
|
+
*/
|
|
609
|
+
concurrency?: number
|
|
610
|
+
|
|
602
611
|
/**
|
|
603
612
|
* Use worker threads for parallel static page generation during build.
|
|
604
613
|
* This utilizes multiple CPU cores for faster builds.
|
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":"AAmXA,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;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,iBA4wCA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildPage.d.ts","sourceRoot":"","sources":["../../src/cli/buildPage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"buildPage.d.ts","sourceRoot":"","sources":["../../src/cli/buildPage.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAkBnD,wBAAgB,iBAAiB,SAUhC;AAED,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,EAC7B,mBAAmB,EAAE,GAAG,EACxB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EAAE,EAChB,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,cAAc,CAAC,EAAE,MAAM,EAAE,EACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,WAAW,CAAC,EAAE,OAAO,EACrB,qBAAqB,CAAC,EAAE,OAAO,GAC9B,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAua7B"}
|