one 1.25.6 → 1.25.8
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/prebuild.cjs +2 -0
- package/dist/cjs/cli/prebuild.native.js +2 -0
- package/dist/cjs/cli/prebuild.native.js.map +1 -1
- package/dist/cjs/cli/prebuild.test.cjs +45 -0
- package/dist/cjs/cli/prebuild.test.native.js +54 -0
- package/dist/cjs/cli/prebuild.test.native.js.map +1 -0
- package/dist/cjs/createHandleRequest.cjs +5 -1
- package/dist/cjs/createHandleRequest.native.js +5 -1
- package/dist/cjs/createHandleRequest.native.js.map +1 -1
- package/dist/cjs/createHandleRequest.test.cjs +59 -1
- package/dist/cjs/createHandleRequest.test.native.js +70 -0
- package/dist/cjs/createHandleRequest.test.native.js.map +1 -1
- package/dist/cjs/router/diagnoseRouteLoadFailure.cjs +95 -0
- package/dist/cjs/router/diagnoseRouteLoadFailure.native.js +202 -0
- package/dist/cjs/router/diagnoseRouteLoadFailure.native.js.map +1 -0
- package/dist/cjs/router/useViteRoutes.cjs +6 -0
- package/dist/cjs/router/useViteRoutes.native.js +6 -0
- package/dist/cjs/router/useViteRoutes.native.js.map +1 -1
- package/dist/cjs/server/oneServe.cjs +0 -2
- package/dist/cjs/server/oneServe.native.js +0 -2
- package/dist/cjs/server/oneServe.native.js.map +1 -1
- package/dist/cjs/server/workerHandler.cjs +1 -1
- package/dist/cjs/server/workerHandler.native.js +1 -1
- package/dist/cjs/server/workerHandler.native.js.map +1 -1
- package/dist/cjs/server/workerHandler.test.cjs +117 -0
- package/dist/cjs/server/workerHandler.test.native.js +137 -0
- package/dist/cjs/server/workerHandler.test.native.js.map +1 -0
- package/dist/cjs/views/ScrollBehavior.cjs +10 -6
- package/dist/cjs/views/ScrollBehavior.native.js +10 -6
- package/dist/cjs/views/ScrollBehavior.native.js.map +1 -1
- package/dist/cjs/views/ScrollBehavior.test.cjs +132 -0
- package/dist/cjs/views/ScrollBehavior.test.native.js +184 -0
- package/dist/cjs/views/ScrollBehavior.test.native.js.map +1 -0
- package/dist/esm/cli/prebuild.mjs +2 -0
- package/dist/esm/cli/prebuild.mjs.map +1 -1
- package/dist/esm/cli/prebuild.native.js +2 -0
- package/dist/esm/cli/prebuild.native.js.map +1 -1
- package/dist/esm/cli/prebuild.test.mjs +46 -0
- package/dist/esm/cli/prebuild.test.mjs.map +1 -0
- package/dist/esm/cli/prebuild.test.native.js +52 -0
- package/dist/esm/cli/prebuild.test.native.js.map +1 -0
- package/dist/esm/createHandleRequest.mjs +5 -2
- package/dist/esm/createHandleRequest.mjs.map +1 -1
- package/dist/esm/createHandleRequest.native.js +5 -2
- package/dist/esm/createHandleRequest.native.js.map +1 -1
- package/dist/esm/createHandleRequest.test.mjs +59 -1
- package/dist/esm/createHandleRequest.test.mjs.map +1 -1
- package/dist/esm/createHandleRequest.test.native.js +70 -0
- package/dist/esm/createHandleRequest.test.native.js.map +1 -1
- package/dist/esm/router/diagnoseRouteLoadFailure.mjs +69 -0
- package/dist/esm/router/diagnoseRouteLoadFailure.mjs.map +1 -0
- package/dist/esm/router/diagnoseRouteLoadFailure.native.js +173 -0
- package/dist/esm/router/diagnoseRouteLoadFailure.native.js.map +1 -0
- package/dist/esm/router/useViteRoutes.mjs +6 -0
- package/dist/esm/router/useViteRoutes.mjs.map +1 -1
- package/dist/esm/router/useViteRoutes.native.js +6 -0
- package/dist/esm/router/useViteRoutes.native.js.map +1 -1
- package/dist/esm/server/oneServe.mjs +0 -2
- package/dist/esm/server/oneServe.mjs.map +1 -1
- package/dist/esm/server/oneServe.native.js +0 -2
- package/dist/esm/server/oneServe.native.js.map +1 -1
- package/dist/esm/server/workerHandler.mjs +2 -2
- package/dist/esm/server/workerHandler.mjs.map +1 -1
- package/dist/esm/server/workerHandler.native.js +2 -2
- package/dist/esm/server/workerHandler.native.js.map +1 -1
- package/dist/esm/server/workerHandler.test.mjs +118 -0
- package/dist/esm/server/workerHandler.test.mjs.map +1 -0
- package/dist/esm/server/workerHandler.test.native.js +135 -0
- package/dist/esm/server/workerHandler.test.native.js.map +1 -0
- package/dist/esm/views/ScrollBehavior.mjs +10 -6
- package/dist/esm/views/ScrollBehavior.mjs.map +1 -1
- package/dist/esm/views/ScrollBehavior.native.js +10 -6
- package/dist/esm/views/ScrollBehavior.native.js.map +1 -1
- package/dist/esm/views/ScrollBehavior.test.mjs +109 -0
- package/dist/esm/views/ScrollBehavior.test.mjs.map +1 -0
- package/dist/esm/views/ScrollBehavior.test.native.js +158 -0
- package/dist/esm/views/ScrollBehavior.test.native.js.map +1 -0
- package/package.json +9 -9
- package/src/cli/prebuild.test.ts +48 -0
- package/src/cli/prebuild.ts +3 -0
- package/src/createHandleRequest.test.ts +55 -1
- package/src/createHandleRequest.ts +8 -1
- package/src/router/diagnoseRouteLoadFailure.ts +108 -0
- package/src/router/useViteRoutes.tsx +10 -0
- package/src/server/oneServe.ts +0 -2
- package/src/server/workerHandler.test.ts +125 -0
- package/src/server/workerHandler.ts +3 -2
- package/src/views/ScrollBehavior.test.tsx +137 -0
- package/src/views/ScrollBehavior.tsx +18 -8
- package/types/cli/prebuild.d.ts.map +1 -1
- package/types/cli/prebuild.test.d.ts +2 -0
- package/types/cli/prebuild.test.d.ts.map +1 -0
- package/types/createHandleRequest.d.ts +1 -0
- package/types/createHandleRequest.d.ts.map +1 -1
- package/types/router/diagnoseRouteLoadFailure.d.ts +14 -0
- package/types/router/diagnoseRouteLoadFailure.d.ts.map +1 -0
- package/types/router/useViteRoutes.d.ts.map +1 -1
- package/types/server/oneServe.d.ts.map +1 -1
- package/types/server/workerHandler.d.ts.map +1 -1
- package/types/server/workerHandler.test.d.ts +2 -0
- package/types/server/workerHandler.test.d.ts.map +1 -0
- package/types/views/ScrollBehavior.d.ts.map +1 -1
- package/types/views/ScrollBehavior.test.d.ts +2 -0
- package/types/views/ScrollBehavior.test.d.ts.map +1 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import TestRenderer, { act } from "react-test-renderer";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { registerScrollGroup, ScrollBehavior } from "./ScrollBehavior.native.js";
|
|
6
|
+
var subscriptions = vi.hoisted(function () {
|
|
7
|
+
return {
|
|
8
|
+
loading: void 0,
|
|
9
|
+
root: void 0
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
vi.mock("../router/lastAction", function () {
|
|
13
|
+
return {
|
|
14
|
+
setLastAction: vi.fn()
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
vi.mock("../router/router", function () {
|
|
18
|
+
return {
|
|
19
|
+
subscribeToLoadingState: function (subscriber) {
|
|
20
|
+
subscriptions.loading = subscriber;
|
|
21
|
+
return function () {
|
|
22
|
+
subscriptions.loading = void 0;
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
subscribeToRootState: function (subscriber) {
|
|
26
|
+
subscriptions.root = subscriber;
|
|
27
|
+
return function () {
|
|
28
|
+
subscriptions.root = void 0;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
34
|
+
var renderer;
|
|
35
|
+
var location;
|
|
36
|
+
var scrollTo;
|
|
37
|
+
beforeEach(function () {
|
|
38
|
+
process.env.VITE_ENVIRONMENT = "client";
|
|
39
|
+
location = {
|
|
40
|
+
pathname: "/",
|
|
41
|
+
search: "",
|
|
42
|
+
hash: ""
|
|
43
|
+
};
|
|
44
|
+
scrollTo = vi.fn();
|
|
45
|
+
var windowMock = Object.assign(new EventTarget(), {
|
|
46
|
+
location,
|
|
47
|
+
scrollTo,
|
|
48
|
+
scrollY: 500
|
|
49
|
+
});
|
|
50
|
+
var storage = /* @__PURE__ */new Map();
|
|
51
|
+
vi.stubGlobal("window", windowMock);
|
|
52
|
+
vi.stubGlobal("document", {
|
|
53
|
+
getElementById: vi.fn()
|
|
54
|
+
});
|
|
55
|
+
vi.stubGlobal("sessionStorage", {
|
|
56
|
+
getItem: function (key) {
|
|
57
|
+
var _storage_get;
|
|
58
|
+
return (_storage_get = storage.get(key)) !== null && _storage_get !== void 0 ? _storage_get : null;
|
|
59
|
+
},
|
|
60
|
+
setItem: function (key, value) {
|
|
61
|
+
return storage.set(key, value);
|
|
62
|
+
},
|
|
63
|
+
removeItem: function (key) {
|
|
64
|
+
return storage.delete(key);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
act(function () {
|
|
68
|
+
renderer = TestRenderer.create(/* @__PURE__ */_jsx(ScrollBehavior, {}));
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
afterEach(function () {
|
|
72
|
+
act(function () {
|
|
73
|
+
return renderer === null || renderer === void 0 ? void 0 : renderer.unmount();
|
|
74
|
+
});
|
|
75
|
+
renderer = void 0;
|
|
76
|
+
vi.useRealTimers();
|
|
77
|
+
vi.unstubAllGlobals();
|
|
78
|
+
delete process.env.VITE_ENVIRONMENT;
|
|
79
|
+
});
|
|
80
|
+
describe("ScrollBehavior initial navigation", function () {
|
|
81
|
+
it("does not scroll when the navigator publishes its initial state after mount", function () {
|
|
82
|
+
act(function () {
|
|
83
|
+
var _subscriptions_root;
|
|
84
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
85
|
+
});
|
|
86
|
+
expect(scrollTo).not.toHaveBeenCalled();
|
|
87
|
+
});
|
|
88
|
+
it("scrolls to the top when the first state notification is a real navigation", function () {
|
|
89
|
+
location.pathname = "/compat/react-native-gesture-handler";
|
|
90
|
+
act(function () {
|
|
91
|
+
var _subscriptions_root;
|
|
92
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
93
|
+
});
|
|
94
|
+
expect(scrollTo).toHaveBeenCalledWith(0, 0);
|
|
95
|
+
});
|
|
96
|
+
it("handles a query change as a first navigation", function () {
|
|
97
|
+
location.search = "?platform=ios";
|
|
98
|
+
act(function () {
|
|
99
|
+
var _subscriptions_root;
|
|
100
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
101
|
+
});
|
|
102
|
+
expect(scrollTo).toHaveBeenCalledWith(0, 0);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe("ScrollBehavior groups", function () {
|
|
106
|
+
it("preserves position between routes in the same group", function () {
|
|
107
|
+
vi.useFakeTimers();
|
|
108
|
+
var unregister = registerScrollGroup("/compat/react-native-gesture-handler");
|
|
109
|
+
act(function () {
|
|
110
|
+
var _subscriptions_root;
|
|
111
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
112
|
+
});
|
|
113
|
+
location.pathname = "/compat/react-native-gesture-handler";
|
|
114
|
+
act(function () {
|
|
115
|
+
var _subscriptions_root;
|
|
116
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
117
|
+
});
|
|
118
|
+
scrollTo.mockClear();
|
|
119
|
+
act(function () {
|
|
120
|
+
var _subscriptions_loading;
|
|
121
|
+
return (_subscriptions_loading = subscriptions.loading) === null || _subscriptions_loading === void 0 ? void 0 : _subscriptions_loading.call(subscriptions, "loading");
|
|
122
|
+
});
|
|
123
|
+
location.pathname = "/compat/react-native-gesture-handler/pan-gesture";
|
|
124
|
+
act(function () {
|
|
125
|
+
var _subscriptions_root;
|
|
126
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
127
|
+
});
|
|
128
|
+
vi.runAllTimers();
|
|
129
|
+
expect(scrollTo).toHaveBeenCalledWith(0, 500);
|
|
130
|
+
unregister();
|
|
131
|
+
vi.useRealTimers();
|
|
132
|
+
});
|
|
133
|
+
it("does not match a different route whose slug has the same prefix", function () {
|
|
134
|
+
var unregister = registerScrollGroup("/compat/react-native");
|
|
135
|
+
act(function () {
|
|
136
|
+
var _subscriptions_root;
|
|
137
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
138
|
+
});
|
|
139
|
+
location.pathname = "/compat/react-native/core";
|
|
140
|
+
act(function () {
|
|
141
|
+
var _subscriptions_root;
|
|
142
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
143
|
+
});
|
|
144
|
+
scrollTo.mockClear();
|
|
145
|
+
act(function () {
|
|
146
|
+
var _subscriptions_loading;
|
|
147
|
+
return (_subscriptions_loading = subscriptions.loading) === null || _subscriptions_loading === void 0 ? void 0 : _subscriptions_loading.call(subscriptions, "loading");
|
|
148
|
+
});
|
|
149
|
+
location.pathname = "/compat/react-native-gesture-handler";
|
|
150
|
+
act(function () {
|
|
151
|
+
var _subscriptions_root;
|
|
152
|
+
return (_subscriptions_root = subscriptions.root) === null || _subscriptions_root === void 0 ? void 0 : _subscriptions_root.call(subscriptions, {});
|
|
153
|
+
});
|
|
154
|
+
expect(scrollTo).toHaveBeenCalledWith(0, 0);
|
|
155
|
+
unregister();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
//# sourceMappingURL=ScrollBehavior.test.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["jsx","_jsx","React","TestRenderer","act","afterEach","beforeEach","describe","expect","it","vi","registerScrollGroup","ScrollBehavior","subscriptions","hoisted","loading","root","mock","setLastAction","fn","subscribeToLoadingState","subscriber","subscribeToRootState","globalThis","IS_REACT_ACT_ENVIRONMENT","renderer","location","scrollTo","process","env","VITE_ENVIRONMENT","pathname","search","hash","windowMock","Object","assign","EventTarget","scrollY","storage","Map","stubGlobal","getElementById","getItem","key","_storage_get","get","setItem","value","set","removeItem","delete","create","unmount","useRealTimers","unstubAllGlobals","_subscriptions_root","call","not","toHaveBeenCalled","toHaveBeenCalledWith"],"sources":["../../../src/views/ScrollBehavior.test.tsx"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "one",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.8",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"setup.mjs",
|
|
@@ -193,18 +193,18 @@
|
|
|
193
193
|
"@cloudflare/vite-plugin": "^1.33.1",
|
|
194
194
|
"@swc/core": "^1.14.0",
|
|
195
195
|
"@ungap/structured-clone": "^1.2.0",
|
|
196
|
-
"@vxrn/color-scheme": "1.25.
|
|
197
|
-
"@vxrn/compiler": "1.25.
|
|
198
|
-
"@vxrn/resolve": "1.25.
|
|
199
|
-
"@vxrn/tslib-lite": "1.25.
|
|
200
|
-
"@vxrn/use-isomorphic-layout-effect": "1.25.
|
|
201
|
-
"@vxrn/vite-plugin-metro": "1.25.
|
|
196
|
+
"@vxrn/color-scheme": "1.25.8",
|
|
197
|
+
"@vxrn/compiler": "1.25.8",
|
|
198
|
+
"@vxrn/resolve": "1.25.8",
|
|
199
|
+
"@vxrn/tslib-lite": "1.25.8",
|
|
200
|
+
"@vxrn/use-isomorphic-layout-effect": "1.25.8",
|
|
201
|
+
"@vxrn/vite-plugin-metro": "1.25.8",
|
|
202
202
|
"babel-dead-code-elimination": "1.0.10",
|
|
203
203
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
204
204
|
"babel-preset-expo": "~57.0.5",
|
|
205
205
|
"citty": "^0.1.6",
|
|
206
206
|
"core-js": "^3.38.1",
|
|
207
|
-
"create-vxrn": "1.25.
|
|
207
|
+
"create-vxrn": "1.25.8",
|
|
208
208
|
"escape-string-regexp": "^5.0.0",
|
|
209
209
|
"expo-linking": "~57.0.5",
|
|
210
210
|
"expo-modules-core": "~57.0.10",
|
|
@@ -224,7 +224,7 @@
|
|
|
224
224
|
"tsconfig-paths": "^4",
|
|
225
225
|
"use-latest-callback": "^0.2.3",
|
|
226
226
|
"vite": "^8.2.2",
|
|
227
|
-
"vxrn": "1.25.
|
|
227
|
+
"vxrn": "1.25.8",
|
|
228
228
|
"web-streams-polyfill": "^4.3.0",
|
|
229
229
|
"ws": "^8.21.0",
|
|
230
230
|
"xxhashjs": "^0.2.2"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { run } from './prebuild'
|
|
3
|
+
|
|
4
|
+
const { loadUserOneOptionsMock, prebuildMock } = vi.hoisted(() => ({
|
|
5
|
+
loadUserOneOptionsMock: vi.fn(),
|
|
6
|
+
prebuildMock: vi.fn(),
|
|
7
|
+
}))
|
|
8
|
+
|
|
9
|
+
vi.mock('../vite/loadConfig', () => ({
|
|
10
|
+
loadUserOneOptions: loadUserOneOptionsMock,
|
|
11
|
+
}))
|
|
12
|
+
|
|
13
|
+
vi.mock('vxrn', () => ({
|
|
14
|
+
prebuild: prebuildMock,
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
describe('one prebuild', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
loadUserOneOptionsMock.mockReset()
|
|
20
|
+
prebuildMock.mockReset()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('loads the app bundler configuration before native prebuild', async () => {
|
|
24
|
+
loadUserOneOptionsMock.mockResolvedValueOnce({})
|
|
25
|
+
|
|
26
|
+
await run({ platform: 'ios', expo: true, 'no-install': true })
|
|
27
|
+
|
|
28
|
+
expect(loadUserOneOptionsMock).toHaveBeenCalledWith('build', true)
|
|
29
|
+
expect(loadUserOneOptionsMock.mock.invocationCallOrder[0]).toBeLessThan(
|
|
30
|
+
prebuildMock.mock.invocationCallOrder[0]
|
|
31
|
+
)
|
|
32
|
+
expect(prebuildMock).toHaveBeenCalledWith({
|
|
33
|
+
root: process.cwd(),
|
|
34
|
+
platform: 'ios',
|
|
35
|
+
expo: true,
|
|
36
|
+
'no-install': true,
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('does not prebuild when the app configuration fails to load', async () => {
|
|
41
|
+
loadUserOneOptionsMock.mockRejectedValueOnce(new Error('invalid vite config'))
|
|
42
|
+
|
|
43
|
+
await expect(run({ platform: 'ios', expo: true })).rejects.toThrow(
|
|
44
|
+
'invalid vite config'
|
|
45
|
+
)
|
|
46
|
+
expect(prebuildMock).not.toHaveBeenCalled()
|
|
47
|
+
})
|
|
48
|
+
})
|
package/src/cli/prebuild.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { loadUserOneOptions } from '../vite/loadConfig'
|
|
2
|
+
|
|
1
3
|
export async function run(args: {
|
|
2
4
|
platform?: string
|
|
3
5
|
expo: boolean
|
|
4
6
|
'no-install'?: boolean
|
|
5
7
|
}) {
|
|
8
|
+
await loadUserOneOptions('build', true)
|
|
6
9
|
const { prebuild } = await import('vxrn')
|
|
7
10
|
|
|
8
11
|
await prebuild({
|
|
@@ -62,8 +62,9 @@ vi.mock('./vite/getManifest', () => ({
|
|
|
62
62
|
}),
|
|
63
63
|
}))
|
|
64
64
|
|
|
65
|
-
function createRequest(path: string) {
|
|
65
|
+
function createRequest(path: string, method = 'GET') {
|
|
66
66
|
return new Request(`http://localhost:3000${path}`, {
|
|
67
|
+
method,
|
|
67
68
|
headers: {
|
|
68
69
|
host: 'localhost:3000',
|
|
69
70
|
},
|
|
@@ -262,6 +263,59 @@ describe('createHandleRequest', () => {
|
|
|
262
263
|
})
|
|
263
264
|
})
|
|
264
265
|
|
|
266
|
+
describe('request method dispatch', () => {
|
|
267
|
+
it('answers HEAD page requests exactly like GET', async () => {
|
|
268
|
+
const handlePage = vi.fn(
|
|
269
|
+
async () =>
|
|
270
|
+
new Response('<html></html>', { headers: { 'content-type': 'text/html' } })
|
|
271
|
+
)
|
|
272
|
+
const { handler } = createHandleRequest({ handlePage }, { routerRoot: '/app' })
|
|
273
|
+
|
|
274
|
+
const get = await handler(createRequest('/my-page', 'GET'))
|
|
275
|
+
const head = await handler(createRequest('/my-page', 'HEAD'))
|
|
276
|
+
|
|
277
|
+
if (!(get instanceof Response) || !(head instanceof Response)) {
|
|
278
|
+
throw new Error('expected both GET and HEAD to return a Response')
|
|
279
|
+
}
|
|
280
|
+
// the transport drops the body for HEAD, so the handler layer must agree
|
|
281
|
+
// with GET on everything else: status and content type.
|
|
282
|
+
expect(head.status).toBe(get.status)
|
|
283
|
+
expect(head.headers.get('content-type')).toBe(get.headers.get('content-type'))
|
|
284
|
+
expect(handlePage).toHaveBeenCalledTimes(2)
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
it('continues routing HEAD requests to API handlers', async () => {
|
|
288
|
+
const mockHandlersWithAPI = {
|
|
289
|
+
handlePage: vi.fn().mockResolvedValue('<html></html>'),
|
|
290
|
+
handleAPI: vi.fn().mockResolvedValue({
|
|
291
|
+
HEAD: () => new Response(null, { status: 204 }),
|
|
292
|
+
}),
|
|
293
|
+
}
|
|
294
|
+
const { handler } = createHandleRequest(mockHandlersWithAPI, {
|
|
295
|
+
routerRoot: '/app',
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
const result = await handler(createRequest('/api/github/agent/run.sh', 'HEAD'))
|
|
299
|
+
|
|
300
|
+
expect(result).toBeInstanceOf(Response)
|
|
301
|
+
if (!(result instanceof Response)) {
|
|
302
|
+
throw new Error('expected HEAD API request to return a Response')
|
|
303
|
+
}
|
|
304
|
+
expect(result.status).toBe(204)
|
|
305
|
+
expect(mockHandlersWithAPI.handleAPI).toHaveBeenCalledOnce()
|
|
306
|
+
expect(mockHandlersWithAPI.handlePage).not.toHaveBeenCalled()
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it('does not route POST requests to page handlers', async () => {
|
|
310
|
+
const { handler } = createHandleRequest(mockHandlers, { routerRoot: '/app' })
|
|
311
|
+
|
|
312
|
+
const result = await handler(createRequest('/my-page', 'POST'))
|
|
313
|
+
|
|
314
|
+
expect(result).toBeNull()
|
|
315
|
+
expect(mockHandlers.handlePage).not.toHaveBeenCalled()
|
|
316
|
+
})
|
|
317
|
+
})
|
|
318
|
+
|
|
265
319
|
describe('special paths', () => {
|
|
266
320
|
it('should skip __vxrnhmr path', async () => {
|
|
267
321
|
const { handler } = createHandleRequest(mockHandlers, { routerRoot: '/app' })
|
|
@@ -35,6 +35,13 @@ function isStaticAssetRequestPath(pathname: string): boolean {
|
|
|
35
35
|
)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// page (document) routes answer HEAD exactly like GET. the transport drops the
|
|
39
|
+
// body: node's ServerResponse suppresses it for HEAD and workerd does the same.
|
|
40
|
+
// without this a HEAD document request falls through to a bare 404 while GET is 200.
|
|
41
|
+
export function isPageRequestMethod(method: string) {
|
|
42
|
+
return method === 'GET' || method === 'HEAD'
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
// ensure handler results are always a proper Response so middleware
|
|
39
46
|
// can safely use response.body / response.headers / new Response(response.body, ...)
|
|
40
47
|
function ensureResponse(value: any): Response {
|
|
@@ -425,7 +432,7 @@ export function createHandleRequest(
|
|
|
425
432
|
}
|
|
426
433
|
}
|
|
427
434
|
|
|
428
|
-
if (request.method
|
|
435
|
+
if (!isPageRequestMethod(request.method)) {
|
|
429
436
|
return null
|
|
430
437
|
}
|
|
431
438
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// a browser content blocker (safari's built-in blockers, ublock, adguard,
|
|
2
|
+
// brave shields) matches filter rules against the request url. in dev the
|
|
3
|
+
// vite module url mirrors the source path, so an ordinary app file can match
|
|
4
|
+
// a tracking rule purely by where it lives — easylist, easyprivacy and
|
|
5
|
+
// adguard all ship the plain substring rule `/analytics/pageview`, which is
|
|
6
|
+
// enough to refuse `src/features/site/analytics/PageviewTracker.tsx`.
|
|
7
|
+
//
|
|
8
|
+
// one blocked module fails the whole dynamic import, and the browser reports
|
|
9
|
+
// only `TypeError: Importing a module script failed` pointing at one's own
|
|
10
|
+
// route loader. nothing in that names the file, the app, or the blocker, so
|
|
11
|
+
// it reads as a framework or vite bug and sends people restarting dev servers
|
|
12
|
+
// and clearing caches.
|
|
13
|
+
//
|
|
14
|
+
// a blocked request also fails `fetch()`, so walking the route's module graph
|
|
15
|
+
// from the browser finds the exact module the blocker refused. dev only, and
|
|
16
|
+
// only after a route has already failed to load.
|
|
17
|
+
|
|
18
|
+
const MAX_MODULES = 500
|
|
19
|
+
const TIMEOUT_MS = 5000
|
|
20
|
+
|
|
21
|
+
// vite rewrites bare specifiers to absolute paths, so most of these are
|
|
22
|
+
// already root-relative; the rest resolve against the importing module.
|
|
23
|
+
function collectImports(source: string, base: string): string[] {
|
|
24
|
+
const out: string[] = []
|
|
25
|
+
const add = (spec: string) => {
|
|
26
|
+
if (!/^[./]|^https?:/.test(spec)) return
|
|
27
|
+
try {
|
|
28
|
+
out.push(new URL(spec, base).href)
|
|
29
|
+
} catch {}
|
|
30
|
+
}
|
|
31
|
+
for (const m of source.matchAll(/(?:^|[\s;}])(?:import|export)[^'"]{0,300}?from\s*["']([^"']+)["']/g))
|
|
32
|
+
add(m[1])
|
|
33
|
+
for (const m of source.matchAll(/\bimport\s*\(\s*["']([^"']+)["']\s*\)/g)) add(m[1])
|
|
34
|
+
for (const m of source.matchAll(/(?:^|[\s;}])import\s*["']([^"']+)["']/g)) add(m[1])
|
|
35
|
+
return out
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Walks the module graph under `entryUrl` looking for a module the browser
|
|
40
|
+
* refuses to fetch. Returns the blocked module's url, or null when every
|
|
41
|
+
* module in the graph is reachable (which means the import failed for some
|
|
42
|
+
* other reason, such as a syntax error inside one of them).
|
|
43
|
+
*/
|
|
44
|
+
export async function findBlockedModule(entryUrl: string): Promise<string | null> {
|
|
45
|
+
const deadline = Date.now() + TIMEOUT_MS
|
|
46
|
+
const seen = new Set<string>()
|
|
47
|
+
let frontier = [new URL(entryUrl, window.location.href).href]
|
|
48
|
+
|
|
49
|
+
while (frontier.length && seen.size < MAX_MODULES && Date.now() < deadline) {
|
|
50
|
+
const batch = frontier.filter((url) => !seen.has(url)).slice(0, 32)
|
|
51
|
+
if (!batch.length) break
|
|
52
|
+
frontier = frontier.slice(batch.length)
|
|
53
|
+
|
|
54
|
+
const results = await Promise.all(
|
|
55
|
+
batch.map(async (url) => {
|
|
56
|
+
seen.add(url)
|
|
57
|
+
let res: Response
|
|
58
|
+
try {
|
|
59
|
+
res = await fetch(url)
|
|
60
|
+
} catch {
|
|
61
|
+
// the request never reached the server. in dev the server is
|
|
62
|
+
// demonstrably up (the page and one's own runtime loaded from it),
|
|
63
|
+
// so this is the browser refusing to make the request.
|
|
64
|
+
return { url, blocked: true, imports: [] as string[] }
|
|
65
|
+
}
|
|
66
|
+
if (!res.ok) return { url, blocked: false, imports: [] }
|
|
67
|
+
const type = res.headers.get('content-type') ?? ''
|
|
68
|
+
if (!type.includes('javascript')) return { url, blocked: false, imports: [] }
|
|
69
|
+
return { url, blocked: false, imports: collectImports(await res.text(), url) }
|
|
70
|
+
})
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
for (const result of results) {
|
|
74
|
+
if (result.blocked) return result.url
|
|
75
|
+
for (const next of result.imports) {
|
|
76
|
+
if (!seen.has(next)) frontier.push(next)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Turns a failed route import into a message that names the responsible file.
|
|
86
|
+
* Returns null when the graph is fully reachable, leaving the original error
|
|
87
|
+
* as the only report.
|
|
88
|
+
*/
|
|
89
|
+
export async function diagnoseRouteLoadFailure(
|
|
90
|
+
routeId: string,
|
|
91
|
+
routeUrl: string
|
|
92
|
+
): Promise<string | null> {
|
|
93
|
+
const blocked = await findBlockedModule(routeUrl)
|
|
94
|
+
if (!blocked) return null
|
|
95
|
+
|
|
96
|
+
const path = blocked.replace(window.location.origin, '')
|
|
97
|
+
return [
|
|
98
|
+
`Route "${routeId}" failed to load because this browser refused to fetch ${path}`,
|
|
99
|
+
``,
|
|
100
|
+
`That request never reached the dev server, so a content blocker or privacy`,
|
|
101
|
+
`extension is blocking it. In dev the module URL is the source path, and a`,
|
|
102
|
+
`path containing a word like "analytics", "pageview" or "track" matches the`,
|
|
103
|
+
`tracking rules those blockers ship.`,
|
|
104
|
+
``,
|
|
105
|
+
`Rename the file or the directory so its path no longer matches, or allow`,
|
|
106
|
+
`${window.location.origin} in the blocker.`,
|
|
107
|
+
].join('\n')
|
|
108
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GlobbedRouteImports } from '../types'
|
|
2
2
|
import type { One } from '../vite/types'
|
|
3
|
+
import { diagnoseRouteLoadFailure } from './diagnoseRouteLoadFailure'
|
|
3
4
|
import { hmrImport } from './hmrImport'
|
|
4
5
|
|
|
5
6
|
// essentially a development helper
|
|
@@ -303,6 +304,15 @@ export function globbedRoutesToRouteContext(
|
|
|
303
304
|
message: err instanceof Error ? err.message : String(err),
|
|
304
305
|
stack: err instanceof Error ? err.stack : undefined,
|
|
305
306
|
})
|
|
307
|
+
|
|
308
|
+
// `Importing a module script failed` names neither the module nor
|
|
309
|
+
// the reason. when a browser content blocker refused one of the
|
|
310
|
+
// route's imports, walking the graph finds the exact file.
|
|
311
|
+
if (process.env.NODE_ENV === 'development' && routePaths[id]) {
|
|
312
|
+
diagnoseRouteLoadFailure(id, routePaths[id]).then((message) => {
|
|
313
|
+
if (message) console.error(message)
|
|
314
|
+
})
|
|
315
|
+
}
|
|
306
316
|
}
|
|
307
317
|
loadedRoutes[id] = {
|
|
308
318
|
default: () => null,
|
package/src/server/oneServe.ts
CHANGED
|
@@ -924,7 +924,6 @@ url: ${url}`)
|
|
|
924
924
|
|
|
925
925
|
for (const route of compiledManifest.apiRoutes) {
|
|
926
926
|
app.get(route.urlPath, createHonoHandler(route))
|
|
927
|
-
app.on('HEAD', route.urlPath, createHonoHandler(route))
|
|
928
927
|
app.put(route.urlPath, createHonoHandler(route))
|
|
929
928
|
app.post(route.urlPath, createHonoHandler(route))
|
|
930
929
|
app.delete(route.urlPath, createHonoHandler(route))
|
|
@@ -933,7 +932,6 @@ url: ${url}`)
|
|
|
933
932
|
|
|
934
933
|
if (route.urlPath !== route.urlCleanPath) {
|
|
935
934
|
app.get(route.urlCleanPath, createHonoHandler(route))
|
|
936
|
-
app.on('HEAD', route.urlCleanPath, createHonoHandler(route))
|
|
937
935
|
app.put(route.urlCleanPath, createHonoHandler(route))
|
|
938
936
|
app.post(route.urlCleanPath, createHonoHandler(route))
|
|
939
937
|
app.delete(route.urlCleanPath, createHonoHandler(route))
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import type { One } from '../vite/types'
|
|
3
|
+
import { createWorkerHandler, type LazyRoutes } from './workerHandler'
|
|
4
|
+
|
|
5
|
+
const pageRoute = {
|
|
6
|
+
file: 'app/some-page.tsx',
|
|
7
|
+
page: '/some-page',
|
|
8
|
+
namedRegex: '^/some-page(?:/)?$',
|
|
9
|
+
urlPath: '/some-page',
|
|
10
|
+
urlCleanPath: '/some-page',
|
|
11
|
+
routeKeys: {},
|
|
12
|
+
type: 'ssr',
|
|
13
|
+
middlewares: [],
|
|
14
|
+
} satisfies One.BuildInfo['manifest']['pageRoutes'][number]
|
|
15
|
+
|
|
16
|
+
const apiRoute = {
|
|
17
|
+
file: 'app/api/status+api.ts',
|
|
18
|
+
page: '/api/status',
|
|
19
|
+
namedRegex: '^/api/status(?:/)?$',
|
|
20
|
+
urlPath: '/api/status',
|
|
21
|
+
urlCleanPath: '/api/status',
|
|
22
|
+
routeKeys: {},
|
|
23
|
+
type: 'api',
|
|
24
|
+
middlewares: [],
|
|
25
|
+
} satisfies One.BuildInfo['manifest']['apiRoutes'][number]
|
|
26
|
+
|
|
27
|
+
const buildInfo = {
|
|
28
|
+
constants: { CACHE_KEY: 'test' },
|
|
29
|
+
routeToBuildInfo: {
|
|
30
|
+
[pageRoute.file]: {
|
|
31
|
+
type: 'ssr',
|
|
32
|
+
path: pageRoute.page,
|
|
33
|
+
routeFile: pageRoute.file,
|
|
34
|
+
middlewares: [],
|
|
35
|
+
preloadPath: '',
|
|
36
|
+
cssPreloadPath: '',
|
|
37
|
+
loaderPath: '',
|
|
38
|
+
cleanPath: pageRoute.page,
|
|
39
|
+
htmlPath: '',
|
|
40
|
+
clientJsPath: '',
|
|
41
|
+
serverJsPath: '',
|
|
42
|
+
params: {},
|
|
43
|
+
preloads: [],
|
|
44
|
+
css: [],
|
|
45
|
+
layoutCSS: [],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
pathToRoute: {},
|
|
49
|
+
routeMap: {},
|
|
50
|
+
manifest: {
|
|
51
|
+
pageRoutes: [pageRoute],
|
|
52
|
+
apiRoutes: [apiRoute],
|
|
53
|
+
allRoutes: [pageRoute, apiRoute],
|
|
54
|
+
},
|
|
55
|
+
preloads: {},
|
|
56
|
+
cssPreloads: {},
|
|
57
|
+
loaders: {},
|
|
58
|
+
} satisfies One.BuildInfo
|
|
59
|
+
|
|
60
|
+
const lazyRoutes = {
|
|
61
|
+
serverEntry: async () => ({
|
|
62
|
+
default: {
|
|
63
|
+
render: () => '<html></html>',
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
pages: {
|
|
67
|
+
[pageRoute.file]: async () => ({}),
|
|
68
|
+
},
|
|
69
|
+
api: {
|
|
70
|
+
[apiRoute.page]: async () => ({
|
|
71
|
+
HEAD: () => new Response(null, { status: 204 }),
|
|
72
|
+
}),
|
|
73
|
+
},
|
|
74
|
+
middlewares: {},
|
|
75
|
+
} satisfies LazyRoutes
|
|
76
|
+
|
|
77
|
+
function createHandler() {
|
|
78
|
+
vi.stubEnv('ONE_BUFFERED_SSR', '1')
|
|
79
|
+
return createWorkerHandler({
|
|
80
|
+
oneOptions: { web: { defaultRenderMode: 'ssr' } },
|
|
81
|
+
buildInfo,
|
|
82
|
+
lazyRoutes,
|
|
83
|
+
}).handleRequest
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
afterEach(() => {
|
|
87
|
+
vi.unstubAllEnvs()
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
describe('createWorkerHandler', () => {
|
|
91
|
+
it('answers HEAD page requests exactly like GET', async () => {
|
|
92
|
+
const handleRequest = createHandler()
|
|
93
|
+
const get = await handleRequest(new Request('https://example.com/some-page'))
|
|
94
|
+
const head = await handleRequest(
|
|
95
|
+
new Request('https://example.com/some-page', { method: 'HEAD' })
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
if (!(get instanceof Response) || !(head instanceof Response)) {
|
|
99
|
+
throw new Error('expected both GET and HEAD to return a Response')
|
|
100
|
+
}
|
|
101
|
+
// workerd drops the body for HEAD, so the handler must agree with GET on
|
|
102
|
+
// status and content type. asserting an empty body here would only be
|
|
103
|
+
// asserting the transport's job.
|
|
104
|
+
expect(get.status).toBe(200)
|
|
105
|
+
expect(head.status).toBe(get.status)
|
|
106
|
+
expect(head.headers.get('content-type')).toBe(get.headers.get('content-type'))
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('does not route POST requests to page handlers', async () => {
|
|
110
|
+
const response = await createHandler()(
|
|
111
|
+
new Request('https://example.com/some-page', { method: 'POST' })
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
expect(response).toBeNull()
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('continues routing HEAD requests to API handlers', async () => {
|
|
118
|
+
const response = await createHandler()(
|
|
119
|
+
new Request('https://example.com/api/status', { method: 'HEAD' })
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
expect(response).toBeInstanceOf(Response)
|
|
123
|
+
expect(response?.status).toBe(204)
|
|
124
|
+
})
|
|
125
|
+
})
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
compileManifest,
|
|
8
8
|
getSubdomain,
|
|
9
9
|
getURLfromRequestURL,
|
|
10
|
+
isPageRequestMethod,
|
|
10
11
|
type RequestHandlers,
|
|
11
12
|
resolveAPIRoute,
|
|
12
13
|
resolveLoaderRoute,
|
|
@@ -706,8 +707,8 @@ export function createWorkerHandler(options: WorkerHandlerOptions) {
|
|
|
706
707
|
}
|
|
707
708
|
}
|
|
708
709
|
|
|
709
|
-
// 6. page routes
|
|
710
|
-
if (method
|
|
710
|
+
// 6. page routes
|
|
711
|
+
if (isPageRequestMethod(method)) {
|
|
711
712
|
for (const route of compiledManifest.pageRoutes) {
|
|
712
713
|
if (!route.compiledRegex.test(pathname)) continue
|
|
713
714
|
|