one 1.25.16 → 1.26.0
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/native-transforms.cjs +28 -0
- package/dist/cjs/native-transforms.native.js +31 -0
- package/dist/cjs/native-transforms.native.js.map +1 -0
- package/dist/cjs/router/useViteRoutes.cjs +3 -2
- package/dist/cjs/router/useViteRoutes.native.js +3 -2
- package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
- package/dist/cjs/router/useViteRoutes.test.cjs +101 -1
- package/dist/cjs/router/useViteRoutes.test.native.js +109 -1
- package/dist/cjs/router/useViteRoutes.test.native.js.map +1 -1
- package/dist/cjs/vercel/build/generate/createApiServerlessFunction.cjs +45 -44
- package/dist/cjs/vercel/build/generate/createApiServerlessFunction.native.js +64 -39
- package/dist/cjs/vercel/build/generate/createApiServerlessFunction.native.js.map +1 -1
- package/dist/cjs/vite/one.cjs +10 -2
- package/dist/cjs/vite/one.native.js +13 -4
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.cjs +597 -92
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.native.js +1358 -113
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.cjs +185 -0
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.native.js +185 -0
- package/dist/cjs/vite/plugins/clientTreeShakePlugin.test.native.js.map +1 -1
- package/dist/cjs/vite/plugins/useDomPlugin.cjs +14 -37
- package/dist/cjs/vite/plugins/useDomPlugin.native.js +14 -36
- package/dist/cjs/vite/plugins/useDomPlugin.native.js.map +1 -1
- package/dist/esm/native-transforms.mjs +3 -0
- package/dist/esm/native-transforms.mjs.map +1 -0
- package/dist/esm/native-transforms.native.js +3 -0
- package/dist/esm/native-transforms.native.js.map +1 -0
- package/dist/esm/router/useViteRoutes.mjs +3 -2
- package/dist/esm/router/useViteRoutes.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.native.js +3 -2
- package/dist/esm/router/useViteRoutes.native.js.map +1 -1
- package/dist/esm/router/useViteRoutes.test.mjs +77 -1
- package/dist/esm/router/useViteRoutes.test.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.test.native.js +85 -1
- package/dist/esm/router/useViteRoutes.test.native.js.map +1 -1
- package/dist/esm/vercel/build/generate/createApiServerlessFunction.mjs +45 -44
- package/dist/esm/vercel/build/generate/createApiServerlessFunction.mjs.map +1 -1
- package/dist/esm/vercel/build/generate/createApiServerlessFunction.native.js +64 -39
- package/dist/esm/vercel/build/generate/createApiServerlessFunction.native.js.map +1 -1
- package/dist/esm/vite/one.mjs +10 -2
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +13 -4
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.mjs +597 -92
- package/dist/esm/vite/plugins/clientTreeShakePlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.native.js +1358 -113
- package/dist/esm/vite/plugins/clientTreeShakePlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.mjs +185 -0
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.mjs.map +1 -1
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.native.js +185 -0
- package/dist/esm/vite/plugins/clientTreeShakePlugin.test.native.js.map +1 -1
- package/dist/esm/vite/plugins/useDomPlugin.mjs +13 -25
- package/dist/esm/vite/plugins/useDomPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/useDomPlugin.native.js +14 -25
- package/dist/esm/vite/plugins/useDomPlugin.native.js.map +1 -1
- package/package.json +15 -10
- package/src/createApp.tsx +0 -1
- package/src/headless.tsx +0 -1
- package/src/native-transforms.ts +11 -0
- package/src/router/useViteRoutes.test.ts +91 -0
- package/src/router/useViteRoutes.tsx +7 -4
- package/src/vercel/build/generate/createApiServerlessFunction.ts +65 -112
- package/src/vite/one.ts +22 -2
- package/src/vite/plugins/clientTreeShakePlugin.test.ts +201 -0
- package/src/vite/plugins/clientTreeShakePlugin.ts +732 -152
- package/src/vite/plugins/useDomPlugin.ts +20 -32
- package/src/vite/types.ts +60 -5
- package/types/native-transforms.d.ts +11 -0
- package/types/native-transforms.d.ts.map +1 -0
- package/types/router/useViteRoutes.d.ts.map +1 -1
- package/types/vercel/build/generate/createApiServerlessFunction.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/clientTreeShakePlugin.d.ts +1 -9
- package/types/vite/plugins/clientTreeShakePlugin.d.ts.map +1 -1
- package/types/vite/plugins/useDomPlugin.d.ts.map +1 -1
- package/types/vite/types.d.ts +57 -5
- package/types/vite/types.d.ts.map +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import * as swc from "@swc/core";
|
|
1
|
+
import { parseSync } from "oxc-parser";
|
|
3
2
|
function useDOMPlugin() {
|
|
4
3
|
return {
|
|
5
4
|
name: "one-vite-dom-plugin",
|
|
@@ -7,37 +6,27 @@ function useDOMPlugin() {
|
|
|
7
6
|
if (!code.includes("use dom")) {
|
|
8
7
|
return;
|
|
9
8
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (item.expression.value === "use dom") {
|
|
9
|
+
try {
|
|
10
|
+
var parsed = parseSync(id, code);
|
|
11
|
+
var hasUseDom = false;
|
|
12
|
+
for (var i = 0; i < parsed.program.body.length; ++i) {
|
|
13
|
+
var item = parsed.program.body[i];
|
|
14
|
+
if (item.type === "ExpressionStatement") {
|
|
15
|
+
var _item_expression, _item_expression1, _item_expression2, _item_expression3;
|
|
16
|
+
if (item.directive === "use dom" || ((_item_expression = item.expression) === null || _item_expression === void 0 ? void 0 : _item_expression.type) === "Literal" && ((_item_expression1 = item.expression) === null || _item_expression1 === void 0 ? void 0 : _item_expression1.value) === "use dom" || ((_item_expression2 = item.expression) === null || _item_expression2 === void 0 ? void 0 : _item_expression2.type) === "StringLiteral" && ((_item_expression3 = item.expression) === null || _item_expression3 === void 0 ? void 0 : _item_expression3.value) === "use dom") {
|
|
18
17
|
hasUseDom = true;
|
|
19
18
|
break;
|
|
20
19
|
}
|
|
21
20
|
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
}
|
|
22
|
+
if (!hasUseDom) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
} catch (unused) {
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
var parseOpts = function (ext) {
|
|
31
|
-
if (ext === ".ts" || ext === ".tsx") {
|
|
32
|
-
return {
|
|
33
|
-
syntax: "typescript",
|
|
34
|
-
tsx: ext.endsWith("x")
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
syntax: "ecmascript",
|
|
39
|
-
jsx: ext.endsWith("x")
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
31
|
export { useDOMPlugin };
|
|
43
32
|
//# sourceMappingURL=useDomPlugin.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["parseSync","useDOMPlugin","name","transform","code","id","options","includes","parsed","hasUseDom","i","program","body","length","item","type","_item_expression","_item_expression1","_item_expression2","_item_expression3","directive","expression","value","unused"],"sources":["../../../../src/vite/plugins/useDomPlugin.ts"],"sourcesContent":[null],"mappings":"AAyBA,SAASA,SAAA,QAAiB;AAOnB,SAASC,aAAA,EAAuB;EACrC,OAAO;IACLC,IAAA,EAAM;IAEN,MAAMC,UAAUC,IAAA,EAAMC,EAAA,EAAIC,OAAA,EAAS;MACjC,IAAI,CAACF,IAAA,CAAKG,QAAA,CAAS,SAAS,GAAG;QAC7B;MACF;MAEA,IAAI;QACF,IAAAC,MAAM,GAAAR,SAAS,CAAAK,EAAU,EAAAD,IAAI;QAC7B,IAAIK,SAAA,GAAY;QAEhB,SAASC,CAAA,GAAI,GAAGA,CAAA,GAAIF,MAAA,CAAOG,OAAA,CAAQC,IAAA,CAAKC,MAAA,EAAQ,EAAEH,CAAA,EAAG;UACnD,IAAAI,IAAM,GAAAN,MAAO,CAAAG,OAAO,CAAAC,IAAQ,CAAAF,CAAA,CAAK;UACjC,IAAII,IAAA,CAAKC,IAAA,KAAS,uBAAuB;YACvC,IACGC,gBAAa,EAAAC,iBACZ,EAAaC,iBAAY,EAAAC,iBACxB;YAIH,IAAAL,IAAA,CAAAM,SAAY,oBAAAJ,gBAAA,GAAAF,IAAA,CAAAO,UAAA,cAAAL,gBAAA,uBAAAA,gBAAA,CAAAD,IAAA,qBAAAE,iBAAA,GAAAH,IAAA,CAAAO,UAAA,cAAAJ,iBAAA,uBAAAA,iBAAA,CAAAK,KAAA,qBAAAJ,iBAAA,GAAAJ,IAAA,CAAAO,UAAA,cAAAH,iBAAA,uBAAAA,iBAAA,CAAAH,IAAA,2BAAAI,iBAAA,GAAAL,IAAA,CAAAO,UAAA,cAAAF,iBAAA,uBAAAA,iBAAA,CAAAG,KAAA;cACZb,SAAA;cACF;YACF;UACF;QAEA;QACE,KAAAA,SAAA;UACF;QAGF;MACE,SAAAc,MAAA;QACF;MACF;IACF;EACF","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "one",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"setup.mjs",
|
|
@@ -91,6 +91,11 @@
|
|
|
91
91
|
"import": "./dist/esm/babel-preset/index.mjs",
|
|
92
92
|
"require": "./dist/cjs/babel-preset/index.cjs"
|
|
93
93
|
},
|
|
94
|
+
"./native-transforms": {
|
|
95
|
+
"types": "./types/native-transforms.d.ts",
|
|
96
|
+
"import": "./dist/esm/native-transforms.mjs",
|
|
97
|
+
"require": "./dist/cjs/native-transforms.cjs"
|
|
98
|
+
},
|
|
94
99
|
"./metro-config": {
|
|
95
100
|
"types": "./types/metro-config/withOne.d.ts",
|
|
96
101
|
"import": "./dist/esm/metro-config/withOne.mjs",
|
|
@@ -191,20 +196,19 @@
|
|
|
191
196
|
"@react-navigation/native-stack": "~7.18.8",
|
|
192
197
|
"@react-navigation/routers": "~7.6.4",
|
|
193
198
|
"@cloudflare/vite-plugin": "^1.33.1",
|
|
194
|
-
"@swc/core": "^1.14.0",
|
|
195
199
|
"@ungap/structured-clone": "^1.2.0",
|
|
196
|
-
"@vxrn/color-scheme": "1.
|
|
197
|
-
"@vxrn/compiler": "1.
|
|
198
|
-
"@vxrn/resolve": "1.
|
|
199
|
-
"@vxrn/tslib-lite": "1.
|
|
200
|
-
"@vxrn/use-isomorphic-layout-effect": "1.
|
|
201
|
-
"@vxrn/vite-plugin-metro": "1.
|
|
200
|
+
"@vxrn/color-scheme": "1.26.0",
|
|
201
|
+
"@vxrn/compiler": "1.26.0",
|
|
202
|
+
"@vxrn/resolve": "1.26.0",
|
|
203
|
+
"@vxrn/tslib-lite": "1.26.0",
|
|
204
|
+
"@vxrn/use-isomorphic-layout-effect": "1.26.0",
|
|
205
|
+
"@vxrn/vite-plugin-metro": "1.26.0",
|
|
202
206
|
"babel-dead-code-elimination": "1.0.10",
|
|
203
207
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
204
208
|
"babel-preset-expo": "~57.0.5",
|
|
205
209
|
"citty": "^0.1.6",
|
|
206
210
|
"core-js": "^3.38.1",
|
|
207
|
-
"create-vxrn": "1.
|
|
211
|
+
"create-vxrn": "1.26.0",
|
|
208
212
|
"escape-string-regexp": "^5.0.0",
|
|
209
213
|
"expo-linking": "~57.0.5",
|
|
210
214
|
"expo-modules-core": "~57.0.10",
|
|
@@ -213,6 +217,7 @@
|
|
|
213
217
|
"fs-extra": "^11.2.0",
|
|
214
218
|
"hono": "^4.12.8",
|
|
215
219
|
"lightningcss": "^1.30.1",
|
|
220
|
+
"magic-string": "^0.30.21",
|
|
216
221
|
"micromatch": "^4.0.8",
|
|
217
222
|
"nanoid": "^3.3.18",
|
|
218
223
|
"oxc-parser": "^0.112.0",
|
|
@@ -224,7 +229,7 @@
|
|
|
224
229
|
"tsconfig-paths": "^4",
|
|
225
230
|
"use-latest-callback": "^0.2.3",
|
|
226
231
|
"vite": "^8.2.2",
|
|
227
|
-
"vxrn": "1.
|
|
232
|
+
"vxrn": "1.26.0",
|
|
228
233
|
"web-streams-polyfill": "^4.3.0",
|
|
229
234
|
"ws": "^8.21.0",
|
|
230
235
|
"xxhashjs": "^0.2.2"
|
package/src/createApp.tsx
CHANGED
package/src/headless.tsx
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The transforms one needs applied to native bundles, in a form the metro
|
|
3
|
+
* transformer worker can reach.
|
|
4
|
+
*
|
|
5
|
+
* The worker lives in `@vxrn/vite-plugin-metro`, which one depends on, so it
|
|
6
|
+
* cannot import from here directly — it resolves this subpath out of the user's
|
|
7
|
+
* own `one` install instead. Everything re-exported here must stay free of
|
|
8
|
+
* vite: the worker runs in a bare node process.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { transformTreeShakeClient } from './vite/plugins/clientTreeShakePlugin'
|
|
@@ -2,22 +2,113 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
|
2
2
|
|
|
3
3
|
const mocks = vi.hoisted(() => ({
|
|
4
4
|
hmrImport: vi.fn(),
|
|
5
|
+
diagnoseRouteLoadFailure: vi.fn(),
|
|
5
6
|
}))
|
|
6
7
|
|
|
7
8
|
vi.mock('./hmrImport', () => ({
|
|
8
9
|
hmrImport: mocks.hmrImport,
|
|
9
10
|
}))
|
|
10
11
|
|
|
12
|
+
vi.mock('./diagnoseRouteLoadFailure', () => ({
|
|
13
|
+
diagnoseRouteLoadFailure: mocks.diagnoseRouteLoadFailure,
|
|
14
|
+
}))
|
|
15
|
+
|
|
11
16
|
import { globbedRoutesToRouteContext } from './useViteRoutes'
|
|
12
17
|
|
|
13
18
|
const realWindow = (globalThis as any).window
|
|
14
19
|
|
|
15
20
|
afterEach(() => {
|
|
16
21
|
vi.unstubAllEnvs()
|
|
22
|
+
vi.unstubAllGlobals()
|
|
23
|
+
vi.restoreAllMocks()
|
|
17
24
|
mocks.hmrImport.mockReset()
|
|
25
|
+
mocks.diagnoseRouteLoadFailure.mockReset()
|
|
18
26
|
;(globalThis as any).window = realWindow
|
|
19
27
|
})
|
|
20
28
|
|
|
29
|
+
describe('route load error diagnostics', () => {
|
|
30
|
+
it.each(['native', 'server', 'web shim', 'browser'])(
|
|
31
|
+
'%s preserves the original route error',
|
|
32
|
+
async (environment) => {
|
|
33
|
+
vi.stubEnv('NODE_ENV', 'development')
|
|
34
|
+
vi.stubEnv('TAMAGUI_TARGET', environment === 'native' ? 'native' : 'web')
|
|
35
|
+
vi.stubGlobal(
|
|
36
|
+
'window',
|
|
37
|
+
environment === 'server'
|
|
38
|
+
? undefined
|
|
39
|
+
: environment === 'browser'
|
|
40
|
+
? {
|
|
41
|
+
history: {},
|
|
42
|
+
location: { href: 'http://localhost/', origin: 'http://localhost' },
|
|
43
|
+
}
|
|
44
|
+
: {}
|
|
45
|
+
)
|
|
46
|
+
const report = vi.fn()
|
|
47
|
+
vi.stubGlobal('__oneReportRouteLoadError', report)
|
|
48
|
+
vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
49
|
+
mocks.diagnoseRouteLoadFailure.mockResolvedValue(null)
|
|
50
|
+
vi.resetModules()
|
|
51
|
+
const { globbedRoutesToRouteContext } = await import('./useViteRoutes')
|
|
52
|
+
const error = new Error('original route failure')
|
|
53
|
+
const context = globbedRoutesToRouteContext(
|
|
54
|
+
{ '/app/index.tsx': () => Promise.reject(error) },
|
|
55
|
+
'app'
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
const route = await resolveRoute(context)
|
|
59
|
+
|
|
60
|
+
expect(route.default()).toBeNull()
|
|
61
|
+
expect(report).toHaveBeenCalledExactlyOnceWith({
|
|
62
|
+
id: './index.tsx',
|
|
63
|
+
message: error.message,
|
|
64
|
+
stack: error.stack,
|
|
65
|
+
})
|
|
66
|
+
if (environment === 'browser') {
|
|
67
|
+
expect(mocks.diagnoseRouteLoadFailure).toHaveBeenCalledExactlyOnceWith(
|
|
68
|
+
'./index.tsx',
|
|
69
|
+
'/app/index.tsx'
|
|
70
|
+
)
|
|
71
|
+
} else {
|
|
72
|
+
expect(mocks.diagnoseRouteLoadFailure).not.toHaveBeenCalled()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
it('keeps the original report when a browser diagnostic rejects', async () => {
|
|
78
|
+
vi.stubEnv('NODE_ENV', 'development')
|
|
79
|
+
vi.stubEnv('TAMAGUI_TARGET', 'web')
|
|
80
|
+
vi.stubGlobal('window', {
|
|
81
|
+
history: {},
|
|
82
|
+
location: { href: 'http://localhost/', origin: 'http://localhost' },
|
|
83
|
+
})
|
|
84
|
+
const report = vi.fn()
|
|
85
|
+
vi.stubGlobal('__oneReportRouteLoadError', report)
|
|
86
|
+
vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
87
|
+
mocks.diagnoseRouteLoadFailure.mockRejectedValue(new Error('diagnostic failed'))
|
|
88
|
+
vi.resetModules()
|
|
89
|
+
const { globbedRoutesToRouteContext } = await import('./useViteRoutes')
|
|
90
|
+
const error = new Error('original route failure')
|
|
91
|
+
const context = globbedRoutesToRouteContext(
|
|
92
|
+
{ '/app/index.tsx': () => Promise.reject(error) },
|
|
93
|
+
'app'
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const route = await resolveRoute(context)
|
|
97
|
+
await new Promise((resolve) => setImmediate(resolve))
|
|
98
|
+
|
|
99
|
+
expect(route.default()).toBeNull()
|
|
100
|
+
expect(report).toHaveBeenCalledExactlyOnceWith({
|
|
101
|
+
id: './index.tsx',
|
|
102
|
+
message: error.message,
|
|
103
|
+
stack: error.stack,
|
|
104
|
+
})
|
|
105
|
+
expect(mocks.diagnoseRouteLoadFailure).toHaveBeenCalledExactlyOnceWith(
|
|
106
|
+
'./index.tsx',
|
|
107
|
+
'/app/index.tsx'
|
|
108
|
+
)
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
|
|
21
112
|
async function resolveRoute(context: ReturnType<typeof globbedRoutesToRouteContext>) {
|
|
22
113
|
try {
|
|
23
114
|
return context('./index.tsx')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GlobbedRouteImports } from '../types'
|
|
2
2
|
import type { One } from '../vite/types'
|
|
3
|
+
import { hasWebHistory } from '../constants'
|
|
3
4
|
import { handleSkewError, isChunkLoadError } from '../utils/dynamicImport'
|
|
4
5
|
import { diagnoseRouteLoadFailure } from './diagnoseRouteLoadFailure'
|
|
5
6
|
import { hmrImport } from './hmrImport'
|
|
@@ -316,10 +317,12 @@ export function globbedRoutesToRouteContext(
|
|
|
316
317
|
// `Importing a module script failed` names neither the module nor
|
|
317
318
|
// the reason. when a browser content blocker refused one of the
|
|
318
319
|
// route's imports, walking the graph finds the exact file.
|
|
319
|
-
if (
|
|
320
|
-
diagnoseRouteLoadFailure(id, routePaths[id])
|
|
321
|
-
|
|
322
|
-
|
|
320
|
+
if (hasWebHistory && routePaths[id]) {
|
|
321
|
+
diagnoseRouteLoadFailure(id, routePaths[id])
|
|
322
|
+
.then((message) => {
|
|
323
|
+
if (message) console.error(message)
|
|
324
|
+
})
|
|
325
|
+
.catch(() => {})
|
|
323
326
|
}
|
|
324
327
|
}
|
|
325
328
|
loadedRoutes[id] = {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { dirname, join, resolve } from 'node:path'
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import traverse from '@babel/traverse'
|
|
5
|
-
import t from '@babel/types'
|
|
2
|
+
import { parseSync } from 'oxc-parser'
|
|
3
|
+
import MagicString from 'magic-string'
|
|
6
4
|
import { resolvePath } from '@vxrn/resolve'
|
|
7
5
|
import FSExtra from 'fs-extra'
|
|
8
6
|
|
|
@@ -86,114 +84,69 @@ export async function createApiServerlessFunction(
|
|
|
86
84
|
* So we need to wrap the handler function to parse the params from the request,
|
|
87
85
|
* and pass them to the handler function.
|
|
88
86
|
*/
|
|
89
|
-
function wrapHandlerFunctions(code) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
FunctionDeclaration(path) {
|
|
97
|
-
const { node } = path
|
|
98
|
-
|
|
99
|
-
const functionNamesToHandle = [
|
|
100
|
-
'GET',
|
|
101
|
-
'POST',
|
|
102
|
-
'PUT',
|
|
103
|
-
'PATCH',
|
|
104
|
-
'DELETE',
|
|
105
|
-
'HEAD',
|
|
106
|
-
'OPTIONS',
|
|
107
|
-
// TODO: more possibilities?
|
|
108
|
-
]
|
|
109
|
-
|
|
110
|
-
if (!node.id || !functionNamesToHandle.includes(node.id.name)) return
|
|
111
|
-
// TODO: may need to also check if the function is export in any way, if
|
|
112
|
-
// the isn't exported at all, we can skip.
|
|
113
|
-
if (node.extra && node.extra.isWrapper) return
|
|
114
|
-
if (node.extra && node.extra.isWrapped) return
|
|
115
|
-
|
|
116
|
-
const originalName = `orig_${node.id.name}`
|
|
117
|
-
|
|
118
|
-
const originalFunction = t.functionDeclaration(
|
|
119
|
-
t.identifier(originalName),
|
|
120
|
-
node.params,
|
|
121
|
-
node.body,
|
|
122
|
-
node.generator,
|
|
123
|
-
node.async
|
|
124
|
-
)
|
|
87
|
+
function wrapHandlerFunctions(code: string): string {
|
|
88
|
+
let parsed: any
|
|
89
|
+
try {
|
|
90
|
+
parsed = parseSync('api.js', code)
|
|
91
|
+
} catch {
|
|
92
|
+
return code
|
|
93
|
+
}
|
|
125
94
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
95
|
+
if (!parsed?.program) return code
|
|
96
|
+
|
|
97
|
+
const functionNamesToHandle = new Set([
|
|
98
|
+
'GET',
|
|
99
|
+
'POST',
|
|
100
|
+
'PUT',
|
|
101
|
+
'PATCH',
|
|
102
|
+
'DELETE',
|
|
103
|
+
'HEAD',
|
|
104
|
+
'OPTIONS',
|
|
105
|
+
])
|
|
106
|
+
|
|
107
|
+
const ms = new MagicString(code)
|
|
108
|
+
const wrappersToAppend: string[] = []
|
|
109
|
+
|
|
110
|
+
for (const item of parsed.program.body || []) {
|
|
111
|
+
let fnDecl: any = null
|
|
112
|
+
let isExported = false
|
|
113
|
+
let exportNode: any = null
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
item.type === 'ExportNamedDeclaration' &&
|
|
117
|
+
item.declaration?.type === 'FunctionDeclaration'
|
|
118
|
+
) {
|
|
119
|
+
fnDecl = item.declaration
|
|
120
|
+
isExported = true
|
|
121
|
+
exportNode = item
|
|
122
|
+
} else if (item.type === 'FunctionDeclaration') {
|
|
123
|
+
fnDecl = item
|
|
124
|
+
isExported = false
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!fnDecl || !fnDecl.id?.name || !functionNamesToHandle.has(fnDecl.id.name)) {
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const name = fnDecl.id.name
|
|
132
|
+
const originalName = `orig_${name}`
|
|
133
|
+
|
|
134
|
+
if (isExported) {
|
|
135
|
+
ms.remove(exportNode.start, fnDecl.start)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
ms.overwrite(fnDecl.id.start, fnDecl.id.end, originalName)
|
|
139
|
+
|
|
140
|
+
const exportPrefix = isExported ? 'export ' : ''
|
|
141
|
+
wrappersToAppend.push(
|
|
142
|
+
`\n${exportPrefix}function ${name}(request) {\n const url = new URL(request.url);\n const params = Object.fromEntries(url.searchParams.entries());\n return ${originalName}(request, { params });\n}`
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (wrappersToAppend.length > 0) {
|
|
147
|
+
ms.append(wrappersToAppend.join('\n'))
|
|
148
|
+
return ms.toString()
|
|
149
|
+
}
|
|
178
150
|
|
|
179
|
-
|
|
180
|
-
node.extra.isWrapped = true
|
|
181
|
-
|
|
182
|
-
wrapperFunction.extra = wrapperFunction.extra || {}
|
|
183
|
-
wrapperFunction.extra.isWrapper = true
|
|
184
|
-
|
|
185
|
-
if (path.parentPath.isExportNamedDeclaration()) {
|
|
186
|
-
path.replaceWithMultiple([
|
|
187
|
-
originalFunction,
|
|
188
|
-
t.exportNamedDeclaration(wrapperFunction, []),
|
|
189
|
-
])
|
|
190
|
-
} else {
|
|
191
|
-
path.replaceWithMultiple([originalFunction, wrapperFunction])
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
// TODO: idk why the TypeScript type does not match the actual type. Seems that we should use `generator.default`, but TypeScript thinks we should use `generator` directly.
|
|
197
|
-
const output = ((generator as any).default as typeof generator)(ast, {}).code
|
|
198
|
-
return output
|
|
151
|
+
return code
|
|
199
152
|
}
|
package/src/vite/one.ts
CHANGED
|
@@ -87,7 +87,19 @@ export function one(options: One.PluginOptions = {}): PluginOption {
|
|
|
87
87
|
| (MetroOptions & ExpoManifestRequestHandlerPluginPluginOptions)
|
|
88
88
|
| null = (() => {
|
|
89
89
|
if (nativeDisabled) return null
|
|
90
|
-
if (nativeOptions?.bundler !== 'metro' && !process.env.ONE_METRO_MODE)
|
|
90
|
+
if (nativeOptions?.bundler !== 'metro' && !process.env.ONE_METRO_MODE) {
|
|
91
|
+
// the vite native bundler runs no babel and has nowhere to put a babel
|
|
92
|
+
// plugin, so anything configured here is dropped. that is silent by
|
|
93
|
+
// default, and a dropped plugin usually means a broken bundle rather than
|
|
94
|
+
// a missing optimization, so name it.
|
|
95
|
+
const dropped = nativeOptions?.bundlerOptions as any
|
|
96
|
+
if (dropped?.babelConfig || dropped?.babelConfigOverrides) {
|
|
97
|
+
console.warn(
|
|
98
|
+
`[one] native.bundlerOptions configures babel plugins, but native.bundler is "${nativeOptions?.bundler}", which runs no babel. Those plugins will not run and whatever they were rewriting will reach the bundle untransformed.`
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
91
103
|
|
|
92
104
|
if (process.env.ONE_METRO_MODE) {
|
|
93
105
|
console.info('ONE_METRO_MODE environment variable is set, enabling Metro mode')
|
|
@@ -842,11 +854,19 @@ export function one(options: One.PluginOptions = {}): PluginOption {
|
|
|
842
854
|
// TODO move to single config and through environments
|
|
843
855
|
const nativeWebDevAndProdPlugsin: Plugin[] = [clientTreeShakePlugin({ routerRoot })]
|
|
844
856
|
|
|
845
|
-
// TODO
|
|
857
|
+
// TODO move this handoff off globalThis, like the other one -> vxrn options
|
|
846
858
|
if (!nativeDisabled) {
|
|
859
|
+
// the native bundler is its own rolldown instance rather than a vite
|
|
860
|
+
// environment, so nothing in `config.plugins` reaches it. one's own plugins
|
|
861
|
+
// go first, then whatever the app opted in through native.bundlerOptions.
|
|
862
|
+
const viteBundlerOptions =
|
|
863
|
+
nativeOptions?.bundler === 'metro' ? undefined : (nativeOptions?.bundlerOptions as any)
|
|
864
|
+
|
|
847
865
|
globalThis.__vxrnAddNativePlugins = [
|
|
848
866
|
clientTreeShakePlugin({ runtime: 'rolldown', routerRoot }),
|
|
867
|
+
...(viteBundlerOptions?.plugins ?? []),
|
|
849
868
|
]
|
|
869
|
+
;(globalThis as any).__vxrnNativeUserDefine = viteBundlerOptions?.define
|
|
850
870
|
}
|
|
851
871
|
globalThis.__vxrnAddWebPluginsProd = devAndProdPlugins
|
|
852
872
|
|