one 1.21.1 → 1.21.2
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 +1 -4
- package/dist/cjs/cli/build.native.js +1 -4
- 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/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/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/esm/cli/build.mjs +1 -4
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +1 -4
- 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/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/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/package.json +9 -9
- package/src/cli/build.ts +1 -1
- package/src/cli/buildPage.ts +12 -2
- package/src/daemon/ipc.ts +46 -4
- package/src/router/hmrImport.native.test.ts +55 -0
- package/src/router/hmrImport.native.ts +25 -5
- 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/types/cli/buildPage.d.ts.map +1 -1
- package/types/daemon/ipc.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/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
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { globbedRoutesToRouteContext } from "./useViteRoutes.mjs";
|
|
3
|
+
const mocks = vi.hoisted(() => ({
|
|
4
|
+
hmrImport: vi.fn()
|
|
5
|
+
}));
|
|
6
|
+
vi.mock("./hmrImport", () => ({
|
|
7
|
+
hmrImport: mocks.hmrImport
|
|
8
|
+
}));
|
|
9
|
+
const realWindow = globalThis.window;
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.unstubAllEnvs();
|
|
12
|
+
mocks.hmrImport.mockReset();
|
|
13
|
+
globalThis.window = realWindow;
|
|
14
|
+
});
|
|
15
|
+
async function resolveRoute(context) {
|
|
16
|
+
try {
|
|
17
|
+
return context("./index.tsx");
|
|
18
|
+
} catch (pending) {
|
|
19
|
+
await pending;
|
|
20
|
+
return context("./index.tsx");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
describe("globbedRoutesToRouteContext HMR", () => {
|
|
24
|
+
it("evicts and reloads a route under a custom router root", async () => {
|
|
25
|
+
vi.stubEnv("NODE_ENV", "development");
|
|
26
|
+
globalThis.window = {};
|
|
27
|
+
const initialRoute = {
|
|
28
|
+
default: () => "initial"
|
|
29
|
+
};
|
|
30
|
+
const updatedRoute = {
|
|
31
|
+
default: () => "updated"
|
|
32
|
+
};
|
|
33
|
+
const context = globbedRoutesToRouteContext({
|
|
34
|
+
"/routes/index.tsx": () => Promise.resolve(initialRoute)
|
|
35
|
+
}, "routes");
|
|
36
|
+
await expect(resolveRoute(context)).resolves.toBe(initialRoute);
|
|
37
|
+
mocks.hmrImport.mockResolvedValue(updatedRoute);
|
|
38
|
+
globalThis.window.__oneRouteCache.clearFile("routes/index.tsx");
|
|
39
|
+
await expect(resolveRoute(context)).resolves.toBe(updatedRoute);
|
|
40
|
+
expect(mocks.hmrImport).toHaveBeenCalledWith("/routes/index.tsx");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=useViteRoutes.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["afterEach","describe","expect","it","vi","globbedRoutesToRouteContext","mocks","hoisted","hmrImport","fn","mock","realWindow","globalThis","window","unstubAllEnvs","mockReset","resolveRoute","context","pending","stubEnv","initialRoute","default","updatedRoute","/routes/index.tsx","Promise","resolve","resolves","toBe","mockResolvedValue","__oneRouteCache","clearFile","toHaveBeenCalledWith"],"sources":["../../../src/router/useViteRoutes.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,SAAA,EAAWC,QAAA,EAAUC,MAAA,EAAQC,EAAA,EAAIC,EAAA,QAAU;AAUpD,SAASC,2BAAA,QAAmC;AAR5C,MAAMC,KAAA,GAAQF,EAAA,CAAGG,OAAA,CAAQ,OAAO;EAC9BC,SAAA,EAAWJ,EAAA,CAAGK,EAAA,CAAG;AACnB,EAAE;AAEFL,EAAA,CAAGM,IAAA,CAAK,eAAe,OAAO;EAC5BF,SAAA,EAAWF,KAAA,CAAME;AACnB,EAAE;AAIF,MAAMG,UAAA,GAAcC,UAAA,CAAmBC,MAAA;AAEvCb,SAAA,CAAU,MAAM;EACdI,EAAA,CAAGU,aAAA,CAAc;EACjBR,KAAA,CAAME,SAAA,CAAUO,SAAA,CAAU;EACxBH,UAAA,CAAmBC,MAAA,GAASF,UAAA;AAChC,CAAC;AAED,eAAeK,aAAaC,OAAA,EAAyD;EACnF,IAAI;IACF,OAAOA,OAAA,CAAQ,aAAa;EAC9B,SAASC,OAAA,EAAS;IAChB,MAAMA,OAAA;IACN,OAAOD,OAAA,CAAQ,aAAa;EAC9B;AACF;AAEAhB,QAAA,CAAS,mCAAmC,MAAM;EAChDE,EAAA,CAAG,yDAAyD,YAAY;IACtEC,EAAA,CAAGe,OAAA,CAAQ,YAAY,aAAa;IAClCP,UAAA,CAAmBC,MAAA,GAAS,CAAC;IAC/B,MAAMO,YAAA,GAAe;MAAEC,OAAA,EAASA,CAAA,KAAM;IAAU;IAChD,MAAMC,YAAA,GAAe;MAAED,OAAA,EAASA,CAAA,KAAM;IAAU;IAChD,MAAMJ,OAAA,GAAUZ,2BAAA,CACd;MAAE,qBAAqBkB,CAAA,KAAMC,OAAA,CAAQC,OAAA,CAAQL,YAAY;IAAE,GAC3D,QACF;IAEA,MAAMlB,MAAA,CAAOc,YAAA,CAAaC,OAAO,CAAC,EAAES,QAAA,CAASC,IAAA,CAAKP,YAAY;IAE9Dd,KAAA,CAAME,SAAA,CAAUoB,iBAAA,CAAkBN,YAAY;IAC5CV,UAAA,CAAmBC,MAAA,CAAOgB,eAAA,CAAgBC,SAAA,CAAU,kBAAkB;IAExE,MAAM5B,MAAA,CAAOc,YAAA,CAAaC,OAAO,CAAC,EAAES,QAAA,CAASC,IAAA,CAAKL,YAAY;IAC9DpB,MAAA,CAAOI,KAAA,CAAME,SAAS,EAAEuB,oBAAA,CAAqB,mBAAmB;EAClE,CAAC;AACH,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { globbedRoutesToRouteContext } from "./useViteRoutes.native.js";
|
|
3
|
+
var mocks = vi.hoisted(function () {
|
|
4
|
+
return {
|
|
5
|
+
hmrImport: vi.fn()
|
|
6
|
+
};
|
|
7
|
+
});
|
|
8
|
+
vi.mock("./hmrImport", function () {
|
|
9
|
+
return {
|
|
10
|
+
hmrImport: mocks.hmrImport
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
var realWindow = globalThis.window;
|
|
14
|
+
afterEach(function () {
|
|
15
|
+
vi.unstubAllEnvs();
|
|
16
|
+
mocks.hmrImport.mockReset();
|
|
17
|
+
globalThis.window = realWindow;
|
|
18
|
+
});
|
|
19
|
+
async function resolveRoute(context) {
|
|
20
|
+
try {
|
|
21
|
+
return context("./index.tsx");
|
|
22
|
+
} catch (pending) {
|
|
23
|
+
await pending;
|
|
24
|
+
return context("./index.tsx");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
describe("globbedRoutesToRouteContext HMR", function () {
|
|
28
|
+
it("evicts and reloads a route under a custom router root", async function () {
|
|
29
|
+
vi.stubEnv("NODE_ENV", "development");
|
|
30
|
+
globalThis.window = {};
|
|
31
|
+
var initialRoute = {
|
|
32
|
+
default: function () {
|
|
33
|
+
return "initial";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var updatedRoute = {
|
|
37
|
+
default: function () {
|
|
38
|
+
return "updated";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var context = globbedRoutesToRouteContext({
|
|
42
|
+
"/routes/index.tsx": function () {
|
|
43
|
+
return Promise.resolve(initialRoute);
|
|
44
|
+
}
|
|
45
|
+
}, "routes");
|
|
46
|
+
await expect(resolveRoute(context)).resolves.toBe(initialRoute);
|
|
47
|
+
mocks.hmrImport.mockResolvedValue(updatedRoute);
|
|
48
|
+
globalThis.window.__oneRouteCache.clearFile("routes/index.tsx");
|
|
49
|
+
await expect(resolveRoute(context)).resolves.toBe(updatedRoute);
|
|
50
|
+
expect(mocks.hmrImport).toHaveBeenCalledWith("/routes/index.tsx");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=useViteRoutes.test.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["afterEach","describe","expect","it","vi","globbedRoutesToRouteContext","mocks","hoisted","hmrImport","fn","mock","realWindow","globalThis","window","unstubAllEnvs","mockReset","resolveRoute","context","pending","stubEnv","initialRoute","default","updatedRoute"],"sources":["../../../src/router/useViteRoutes.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,SAAA,EAAWC,QAAA,EAAUC,MAAA,EAAQC,EAAA,EAAIC,EAAA,QAAU;AAUpD,SAASC,2BAAA,QAAmC;AAR5C,IAAAC,KAAM,GAAAF,EAAQ,CAAAG,OAAG,aAAe;EAC9B;IACAC,SAAA,EAAAJ,EAAA,CAAAK,EAAA;EAEF,CAAG;AAA2B,EAC5B;AACFL,EAAE,CAAAM,IAAA;EAIF,OAAM;IAENF,SAAU,EAAAF,KAAM,CAAAE;EACd;AACA;AACC,IAACG,UAAmB,GAAAC,UAAS,CAAAC,MAAA;AAChCb,SAAC;EAEDI,EAAA,CAAAU,aAAe;EACbR,KAAI,CAAAE,SAAA,CAAAO,SAAA;EACFH,UAAO,CAAAC,MAAQ,GAAAF,UAAa;AAAA,EAC9B;AACE,eAAMK,aAAAC,OAAA;EACN;IACF,OAAAA,OAAA;EACF,SAAAC,OAAA;IAEA,MAASA,OAAA;IACP,OAAGD,OAAA;EACD;AACC;AACDhB,QAAA,kCAAsC,cAAU;EAChDE,EAAA,wDAAgD;IAChDC,EAAA,CAAAe,OAAM,WAAU;IAAAP,UACZ,CAAAC,MAAA;IAAyD,IAC3DO,YAAA;MACFC,OAAA,WAAAA,CAAA;QAEA,OAAM,SAAO;MAEb;IACE;IAEF,IAAAC,YAAa;MACbD,OAAO,WAAAA,CAAA,EAAe;QACvB;MACF","ignoreList":[]}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { CSS_PRELOAD_JS_POSTFIX, isNative, LOADER_JS_POSTFIX, LOADER_JS_POSTFIX_REGEX, PRELOAD_JS_POSTFIX } from "../constants.mjs";
|
|
2
2
|
import { getURL } from "../getURL.mjs";
|
|
3
3
|
import { removeSearch } from "./removeSearch.mjs";
|
|
4
|
+
function encodeReservedFilenameChars(path) {
|
|
5
|
+
return path.replaceAll("=", "=3d").replace(/[<>:"|?*]/g, char => `=${char.charCodeAt(0).toString(16).padStart(2, "0")}`);
|
|
6
|
+
}
|
|
7
|
+
function decodeReservedFilenameChars(path) {
|
|
8
|
+
return path.replace(/=([0-9a-f]{2})/g, (_match, hexCode) => String.fromCharCode(Number.parseInt(hexCode, 16)));
|
|
9
|
+
}
|
|
4
10
|
function cleanUrl(path) {
|
|
5
|
-
return removeSearch(path).replace(/\/$/, "")
|
|
11
|
+
return encodeReservedFilenameChars(removeSearch(path).replace(/\/$/, "")
|
|
12
|
+
// remove trailing slash before encoding
|
|
13
|
+
).replaceAll("_", "__").replaceAll("/", "_");
|
|
6
14
|
}
|
|
7
15
|
const isClient = typeof window !== "undefined";
|
|
8
16
|
const clientSideURL = isClient ? getURL() : "";
|
|
@@ -21,7 +29,7 @@ function getLoaderPath(currentPath, includeUrl = isNative, cacheBust) {
|
|
|
21
29
|
return `${baseURL}${devPath}/assets/${cleanedUrl}${cacheBustSegment}${LOADER_JS_POSTFIX}`;
|
|
22
30
|
}
|
|
23
31
|
function getPathFromLoaderPath(loaderPath) {
|
|
24
|
-
return loaderPath.replace(LOADER_JS_POSTFIX_REGEX, "").replace(/^(\/_one)?\/assets/, "").replace(/_refetch_\d+_?/, "").replace(/__|_/g, match => match === "__" ? "_" : "/");
|
|
32
|
+
return decodeReservedFilenameChars(loaderPath.replace(LOADER_JS_POSTFIX_REGEX, "").replace(/^(\/_one)?\/assets/, "").replace(/_refetch_\d+_?/, "").replace(/__|_/g, match => match === "__" ? "_" : "/"));
|
|
25
33
|
}
|
|
26
|
-
export { getLoaderPath, getPathFromLoaderPath, getPreloadCSSPath, getPreloadPath };
|
|
34
|
+
export { decodeReservedFilenameChars, encodeReservedFilenameChars, getLoaderPath, getPathFromLoaderPath, getPreloadCSSPath, getPreloadPath };
|
|
27
35
|
//# sourceMappingURL=cleanUrl.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CSS_PRELOAD_JS_POSTFIX","isNative","LOADER_JS_POSTFIX","LOADER_JS_POSTFIX_REGEX","PRELOAD_JS_POSTFIX","getURL","removeSearch","
|
|
1
|
+
{"version":3,"names":["CSS_PRELOAD_JS_POSTFIX","isNative","LOADER_JS_POSTFIX","LOADER_JS_POSTFIX_REGEX","PRELOAD_JS_POSTFIX","getURL","removeSearch","encodeReservedFilenameChars","path","replaceAll","replace","char","charCodeAt","toString","padStart","decodeReservedFilenameChars","_match","hexCode","String","fromCharCode","Number","parseInt","cleanUrl","isClient","window","clientSideURL","getPreloadPath","currentPath","slice","getPreloadCSSPath","getLoaderPath","includeUrl","cacheBust","baseURL","devPath","process","env","NODE_ENV","currentPathUrl","URL","cleanedUrl","pathname","cacheBustSegment","getPathFromLoaderPath","loaderPath","match"],"sources":["../../../src/utils/cleanUrl.ts"],"sourcesContent":[null],"mappings":"AAAA,SACEA,sBAAA,EACAC,QAAA,EACAC,iBAAA,EACAC,uBAAA,EACAC,kBAAA,QACK;AACP,SAASC,MAAA,QAAc;AACvB,SAASC,YAAA,QAAoB;AAQtB,SAASC,4BAA4BC,IAAA,EAAc;EACxD,OAAOA,IAAA,CACJC,UAAA,CAAW,KAAK,KAAK,EACrBC,OAAA,CACC,cACCC,IAAA,IAAS,IAAIA,IAAA,CAAKC,UAAA,CAAW,CAAC,EAAEC,QAAA,CAAS,EAAE,EAAEC,QAAA,CAAS,GAAG,GAAG,CAAC,EAChE;AACJ;AAEO,SAASC,4BAA4BP,IAAA,EAAc;EACxD,OAAOA,IAAA,CAAKE,OAAA,CAAQ,mBAAmB,CAACM,MAAA,EAAQC,OAAA,KAC9CC,MAAA,CAAOC,YAAA,CAAaC,MAAA,CAAOC,QAAA,CAASJ,OAAA,EAAS,EAAE,CAAC,CAClD;AACF;AAEA,SAASK,SAASd,IAAA,EAAc;EAC9B,OAAOD,2BAAA,CACLD,YAAA,CAAaE,IAAI,EAAEE,OAAA,CAAQ,OAAO,EAAE;EAAA;EACtC,EACGD,UAAA,CAAW,KAAK,IAAI,EACpBA,UAAA,CAAW,KAAK,GAAG;AACxB;AAEA,MAAMc,QAAA,GAAW,OAAOC,MAAA,KAAW;AACnC,MAAMC,aAAA,GAAgBF,QAAA,GAAWlB,MAAA,CAAO,IAAI;AAErC,SAASqB,eAAeC,WAAA,EAAqB;EAClD,OAAO,GAAGF,aAAa,WAAWH,QAAA,CAASK,WAAA,CAAYC,KAAA,CAAM,CAAC,CAAC,CAAC,GAAGxB,kBAAkB;AACvF;AAEO,SAASyB,kBAAkBF,WAAA,EAAqB;EACrD,OAAO,GAAGF,aAAa,WAAWH,QAAA,CAASK,WAAA,CAAYC,KAAA,CAAM,CAAC,CAAC,CAAC,GAAG5B,sBAAsB;AAC3F;AAEO,SAAS8B,cACdH,WAAA,EACAI,UAAA,GAAa9B,QAAA,EACb+B,SAAA,EACA;EACA,MAAMC,OAAA,GAAUF,UAAA,GAAa1B,MAAA,CAAO,IAAI;EACxC,MAAM6B,OAAA,GAAUC,OAAA,CAAQC,GAAA,CAAIC,QAAA,KAAa,gBAAgB,UAAU;EAEnE,MAAMC,cAAA,GAAiB,IAAIC,GAAA,CAAIZ,WAAA,EAAa,oBAAoB;EAEhE,MAAMa,UAAA,GAAalB,QAAA,CAASgB,cAAA,CAAeG,QAAA,CAASb,KAAA,CAAM,CAAC,CAAC;EAC5D,MAAMc,gBAAA,GAAmBV,SAAA,GAAY,YAAYA,SAAS,MAAM;EAEhE,OAAO,GAAGC,OAAO,GAAGC,OAAO,WAAWM,UAAU,GAAGE,gBAAgB,GAAGxC,iBAAiB;AACzF;AAEO,SAASyC,sBAAsBC,UAAA,EAAoB;EACxD,OAAO7B,2BAAA,CACL6B,UAAA,CACGlC,OAAA,CAAQP,uBAAA,EAAyB,EAAE,EACnCO,OAAA,CAAQ,sBAAsB,EAAE,EAChCA,OAAA,CAAQ,kBAAkB,EAAE,EAE5BA,OAAA,CAAQ,SAAUmC,KAAA,IAAWA,KAAA,KAAU,OAAO,MAAM,GAAI,CAC7D;AACF","ignoreList":[]}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { CSS_PRELOAD_JS_POSTFIX, isNative, LOADER_JS_POSTFIX, LOADER_JS_POSTFIX_REGEX, PRELOAD_JS_POSTFIX } from "../constants.native.js";
|
|
2
2
|
import { getURL } from "../getURL.native.js";
|
|
3
3
|
import { removeSearch } from "./removeSearch.native.js";
|
|
4
|
+
function encodeReservedFilenameChars(path) {
|
|
5
|
+
return path.replaceAll("=", "=3d").replace(/[<>:"|?*]/g, function (char) {
|
|
6
|
+
return `=${char.charCodeAt(0).toString(16).padStart(2, "0")}`;
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
function decodeReservedFilenameChars(path) {
|
|
10
|
+
return path.replace(/=([0-9a-f]{2})/g, function (_match, hexCode) {
|
|
11
|
+
return String.fromCharCode(Number.parseInt(hexCode, 16));
|
|
12
|
+
});
|
|
13
|
+
}
|
|
4
14
|
function cleanUrl(path) {
|
|
5
|
-
return removeSearch(path).replace(/\/$/, "").replaceAll("_", "__").replaceAll("/", "_");
|
|
15
|
+
return encodeReservedFilenameChars(removeSearch(path).replace(/\/$/, "")).replaceAll("_", "__").replaceAll("/", "_");
|
|
6
16
|
}
|
|
7
17
|
var isClient = typeof window !== "undefined";
|
|
8
18
|
var clientSideURL = isClient ? getURL() : "";
|
|
@@ -23,9 +33,9 @@ function getLoaderPath(currentPath) {
|
|
|
23
33
|
return `${baseURL}${devPath}/assets/${cleanedUrl}${cacheBustSegment}${LOADER_JS_POSTFIX}`;
|
|
24
34
|
}
|
|
25
35
|
function getPathFromLoaderPath(loaderPath) {
|
|
26
|
-
return loaderPath.replace(LOADER_JS_POSTFIX_REGEX, "").replace(/^(\/_one)?\/assets/, "").replace(/_refetch_\d+_?/, "").replace(/__|_/g, function (match) {
|
|
36
|
+
return decodeReservedFilenameChars(loaderPath.replace(LOADER_JS_POSTFIX_REGEX, "").replace(/^(\/_one)?\/assets/, "").replace(/_refetch_\d+_?/, "").replace(/__|_/g, function (match) {
|
|
27
37
|
return match === "__" ? "_" : "/";
|
|
28
|
-
});
|
|
38
|
+
}));
|
|
29
39
|
}
|
|
30
|
-
export { getLoaderPath, getPathFromLoaderPath, getPreloadCSSPath, getPreloadPath };
|
|
40
|
+
export { decodeReservedFilenameChars, encodeReservedFilenameChars, getLoaderPath, getPathFromLoaderPath, getPreloadCSSPath, getPreloadPath };
|
|
31
41
|
//# sourceMappingURL=cleanUrl.native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CSS_PRELOAD_JS_POSTFIX","isNative","LOADER_JS_POSTFIX","LOADER_JS_POSTFIX_REGEX","PRELOAD_JS_POSTFIX","getURL","removeSearch","
|
|
1
|
+
{"version":3,"names":["CSS_PRELOAD_JS_POSTFIX","isNative","LOADER_JS_POSTFIX","LOADER_JS_POSTFIX_REGEX","PRELOAD_JS_POSTFIX","getURL","removeSearch","encodeReservedFilenameChars","path","replaceAll","replace","char","charCodeAt","toString","padStart","decodeReservedFilenameChars","_match","hexCode","String","fromCharCode","Number","parseInt","cleanUrl","isClient","window","clientSideURL","getPreloadPath","currentPath","slice","getPreloadCSSPath","getLoaderPath","includeUrl","arguments","length","cacheBust","baseURL","devPath","process","env","NODE_ENV","currentPathUrl","URL","cleanedUrl","pathname","cacheBustSegment","getPathFromLoaderPath","loaderPath","match"],"sources":["../../../src/utils/cleanUrl.ts"],"sourcesContent":[null],"mappings":"AAAA,SAAAA,sBAAA,EAAAC,QAAA,EAAAC,iBAAA,EAAAC,uBAAA,EAAAC,kBAAA;AAAA,SACEC,MAAA;AAAA,SACAC,YAAA;AAAA,SACAC,4BAAAC,IAAA;EACA,OAAAA,IAAA,CAAAC,UAAA,aAAAC,OAAA,yBAAAC,IAAA;IACA,WAAAA,IAAA,CAAAC,UAAA,IAAAC,QAAA,KAAAC,QAAA;EAAA;AAEF;AACA,SAASC,2BAAoBA,CAAAP,IAAA;EAQtB,OAASA,IAAA,CAAAE,OAAA,kBAA4B,YAAcM,MAAA,EAAAC,OAAA;IACxD,OAAOC,MACJ,CAAAC,YAAgB,CAAAC,MAChB,CAAAC,QAAA,CAAAJ,OAAA;EAAA,EACC;AAAA;AAC8D,SAChEK,SAAAd,IAAA;EACJ,OAAAD,2BAAA,CAAAD,YAAA,CAAAE,IAAA,EAAAE,OAAA,aAAAD,UAAA,YAAAA,UAAA;AAEO;AACL,IAAAc,QAAO,GAAK,OAAAC,MAAA;AAAA,IAAQC,aAAA,GAAAF,QAAA,GAAAlB,MAAA;AAAA,SAAoBqB,cAAQA,CAAAC,WACvC;EACT,UAAAF,aAAA,WAAAH,QAAA,CAAAK,WAAA,CAAAC,KAAA,OAAAxB,kBAAA;AACF;AAEA,SAASyB,iBAAuBA,CAAAF,WAAA;EAC9B,OAAO,GAAAF,aAAA,WAAAH,QAAA,CAAAK,WAAA,CAAAC,KAAA,OAAA5B,sBAAA;AAAA;AAC+B,SAAA8B,cAAAH,WAAA;EACtC,IACGI,UAAW,GAAAC,SACX,CAAAC,MAAA,GAAW,KAAKD,SAAG,iBAAAA,SAAA,MAAA/B,QAAA;IAAAiC,SAAA,GAAAF,SAAA,CAAAC,MAAA,OAAAD,SAAA;EACxB,IAAAG,OAAA,GAAAJ,UAAA,GAAA1B,MAAA;EAEA,IAAM+B,OAAA,GAAAC,OAAW,CAAOC,GAAA,CAAAC,QAAW;EACnC,IAAMC,cAAA,GAAgB,IAAAC,GAAA,CAAAd,WAAkB,EAAI;EAErC,IAAAe,UAAS,GAAApB,QAAe,CAAAkB,cAAqB,CAAAG,QAAA,CAAAf,KAAA;EAClD,IAAAgB,gBAAU,GAAaV,SAAA,GAAW,YAASA,SAAY,MAAO,EAAE;EAClE,UAAAC,OAAA,GAAAC,OAAA,WAAAM,UAAA,GAAAE,gBAAA,GAAA1C,iBAAA;AAEO;AACL,SAAO2C,qBAAgBA,CAAAC,UAAW;EACpC,OAAA/B,2BAAA,CAAA+B,UAAA,CAAApC,OAAA,CAAAP,uBAAA,MAAAO,OAAA,2BAAAA,OAAA,uBAAAA,OAAA,oBAAAqC,KAAA;IAEO,OAASA,KAAA,SACd,YACA;EAGA;AACA;AAEA,SAEAhC,2BAAmB,EACnBR,2BAAyB,EAEzBuB,aAAU,EACZe,qBAAA,EAEOhB,iBAAS,EACdH,cAAO","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getLoaderPath, getPathFromLoaderPath } from "./cleanUrl.mjs";
|
|
2
|
+
import { encodeReservedFilenameChars, getLoaderPath, getPathFromLoaderPath, getPreloadPath } from "./cleanUrl.mjs";
|
|
3
3
|
function roundtrip(path) {
|
|
4
4
|
const loaderPath = getLoaderPath(path, false);
|
|
5
5
|
return getPathFromLoaderPath(loaderPath);
|
|
@@ -63,6 +63,43 @@ describe("getLoaderPath format", () => {
|
|
|
63
63
|
expect(result).toContain("_refetch_12345_");
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
+
describe("NTFS-reserved characters in route-derived names", () => {
|
|
67
|
+
it("roundtrips a root dynamic route pattern", () => {
|
|
68
|
+
expect(roundtrip("/:param")).toBe("/:param");
|
|
69
|
+
});
|
|
70
|
+
it("roundtrips a nested dynamic route pattern", () => {
|
|
71
|
+
expect(roundtrip("/dashboard/:appId")).toBe("/dashboard/:appId");
|
|
72
|
+
});
|
|
73
|
+
it("roundtrips a catch-all pattern", () => {
|
|
74
|
+
expect(roundtrip("/*")).toBe("/*");
|
|
75
|
+
});
|
|
76
|
+
it("roundtrips hostile concrete param values (chars that survive URL parsing raw)", () => {
|
|
77
|
+
expect(roundtrip("/blog/a:b*c")).toBe("/blog/a:b*c");
|
|
78
|
+
});
|
|
79
|
+
it("emits filesystem-legal names for the full reserved set via preload paths", () => {
|
|
80
|
+
expect(getPreloadPath('/blog/a:b*c"d<e>f|g?h')).not.toMatch(/[<>:"|?*]/);
|
|
81
|
+
});
|
|
82
|
+
it("roundtrips literal equals signs (self-escape)", () => {
|
|
83
|
+
expect(roundtrip("/foo=bar")).toBe("/foo=bar");
|
|
84
|
+
});
|
|
85
|
+
it("roundtrips equals followed by hex-looking characters", () => {
|
|
86
|
+
expect(roundtrip("/x=3ay")).toBe("/x=3ay");
|
|
87
|
+
});
|
|
88
|
+
it("emits no NTFS-reserved characters in loader filenames", () => {
|
|
89
|
+
expect(getLoaderPath("/dashboard/:appId", false)).not.toMatch(/[<>:"|?*]/);
|
|
90
|
+
});
|
|
91
|
+
it("emits no NTFS-reserved characters in preload filenames", () => {
|
|
92
|
+
expect(getPreloadPath("/:param")).not.toMatch(/[<>:"|?*]/);
|
|
93
|
+
expect(getPreloadPath("/*")).not.toMatch(/[<>:"|?*]/);
|
|
94
|
+
});
|
|
95
|
+
it("encodeReservedFilenameChars is identity for clean paths", () => {
|
|
96
|
+
expect(encodeReservedFilenameChars("/blog/my-slug.html")).toBe("/blog/my-slug.html");
|
|
97
|
+
});
|
|
98
|
+
it("encodes the html artifact path for non-prerendered dynamic routes", () => {
|
|
99
|
+
expect(encodeReservedFilenameChars("/dashboard/:appId.html")).toBe("/dashboard/=3aappId.html");
|
|
100
|
+
expect(encodeReservedFilenameChars("/*.html")).toBe("/=2a.html");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
66
103
|
describe("getPathFromLoaderPath", () => {
|
|
67
104
|
it("strips /_one/assets prefix", () => {
|
|
68
105
|
expect(getPathFromLoaderPath("/_one/assets/docs_intro_999_vxrn_loader.js")).toBe("/docs/intro");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["describe","expect","it","getLoaderPath","getPathFromLoaderPath","roundtrip","path","loaderPath","toBe","result","toMatch","originalEnv","process","env","NODE_ENV","toContain"],"sources":["../../../src/utils/cleanUrl.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AACrC,
|
|
1
|
+
{"version":3,"names":["describe","expect","it","encodeReservedFilenameChars","getLoaderPath","getPathFromLoaderPath","getPreloadPath","roundtrip","path","loaderPath","toBe","result","toMatch","originalEnv","process","env","NODE_ENV","toContain","not"],"sources":["../../../src/utils/cleanUrl.test.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getLoaderPath, getPathFromLoaderPath } from "./cleanUrl.native.js";
|
|
2
|
+
import { encodeReservedFilenameChars, getLoaderPath, getPathFromLoaderPath, getPreloadPath } from "./cleanUrl.native.js";
|
|
3
3
|
function roundtrip(path) {
|
|
4
4
|
var loaderPath = getLoaderPath(path, false);
|
|
5
5
|
return getPathFromLoaderPath(loaderPath);
|
|
@@ -63,6 +63,43 @@ describe("getLoaderPath format", function () {
|
|
|
63
63
|
expect(result).toContain("_refetch_12345_");
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
+
describe("NTFS-reserved characters in route-derived names", function () {
|
|
67
|
+
it("roundtrips a root dynamic route pattern", function () {
|
|
68
|
+
expect(roundtrip("/:param")).toBe("/:param");
|
|
69
|
+
});
|
|
70
|
+
it("roundtrips a nested dynamic route pattern", function () {
|
|
71
|
+
expect(roundtrip("/dashboard/:appId")).toBe("/dashboard/:appId");
|
|
72
|
+
});
|
|
73
|
+
it("roundtrips a catch-all pattern", function () {
|
|
74
|
+
expect(roundtrip("/*")).toBe("/*");
|
|
75
|
+
});
|
|
76
|
+
it("roundtrips hostile concrete param values (chars that survive URL parsing raw)", function () {
|
|
77
|
+
expect(roundtrip("/blog/a:b*c")).toBe("/blog/a:b*c");
|
|
78
|
+
});
|
|
79
|
+
it("emits filesystem-legal names for the full reserved set via preload paths", function () {
|
|
80
|
+
expect(getPreloadPath('/blog/a:b*c"d<e>f|g?h')).not.toMatch(/[<>:"|?*]/);
|
|
81
|
+
});
|
|
82
|
+
it("roundtrips literal equals signs (self-escape)", function () {
|
|
83
|
+
expect(roundtrip("/foo=bar")).toBe("/foo=bar");
|
|
84
|
+
});
|
|
85
|
+
it("roundtrips equals followed by hex-looking characters", function () {
|
|
86
|
+
expect(roundtrip("/x=3ay")).toBe("/x=3ay");
|
|
87
|
+
});
|
|
88
|
+
it("emits no NTFS-reserved characters in loader filenames", function () {
|
|
89
|
+
expect(getLoaderPath("/dashboard/:appId", false)).not.toMatch(/[<>:"|?*]/);
|
|
90
|
+
});
|
|
91
|
+
it("emits no NTFS-reserved characters in preload filenames", function () {
|
|
92
|
+
expect(getPreloadPath("/:param")).not.toMatch(/[<>:"|?*]/);
|
|
93
|
+
expect(getPreloadPath("/*")).not.toMatch(/[<>:"|?*]/);
|
|
94
|
+
});
|
|
95
|
+
it("encodeReservedFilenameChars is identity for clean paths", function () {
|
|
96
|
+
expect(encodeReservedFilenameChars("/blog/my-slug.html")).toBe("/blog/my-slug.html");
|
|
97
|
+
});
|
|
98
|
+
it("encodes the html artifact path for non-prerendered dynamic routes", function () {
|
|
99
|
+
expect(encodeReservedFilenameChars("/dashboard/:appId.html")).toBe("/dashboard/=3aappId.html");
|
|
100
|
+
expect(encodeReservedFilenameChars("/*.html")).toBe("/=2a.html");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
66
103
|
describe("getPathFromLoaderPath", function () {
|
|
67
104
|
it("strips /_one/assets prefix", function () {
|
|
68
105
|
expect(getPathFromLoaderPath("/_one/assets/docs_intro_999_vxrn_loader.js")).toBe("/docs/intro");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["describe","expect","it","getLoaderPath","getPathFromLoaderPath","roundtrip","path","loaderPath","toBe","result","toMatch","originalEnv","process","env","NODE_ENV","toContain"],"sources":["../../../src/utils/cleanUrl.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AACrC,
|
|
1
|
+
{"version":3,"names":["describe","expect","it","encodeReservedFilenameChars","getLoaderPath","getPathFromLoaderPath","getPreloadPath","roundtrip","path","loaderPath","toBe","result","toMatch","originalEnv","process","env","NODE_ENV","toContain","not"],"sources":["../../../src/utils/cleanUrl.test.ts"],"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.21.
|
|
3
|
+
"version": "1.21.2",
|
|
4
4
|
"license": "BSD-3-Clause",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"setup.mjs",
|
|
@@ -181,18 +181,18 @@
|
|
|
181
181
|
"@cloudflare/vite-plugin": "^1.33.1",
|
|
182
182
|
"@swc/core": "^1.14.0",
|
|
183
183
|
"@ungap/structured-clone": "^1.2.0",
|
|
184
|
-
"@vxrn/color-scheme": "1.21.
|
|
185
|
-
"@vxrn/compiler": "1.21.
|
|
186
|
-
"@vxrn/resolve": "1.21.
|
|
187
|
-
"@vxrn/tslib-lite": "1.21.
|
|
188
|
-
"@vxrn/use-isomorphic-layout-effect": "1.21.
|
|
189
|
-
"@vxrn/vite-plugin-metro": "1.21.
|
|
184
|
+
"@vxrn/color-scheme": "1.21.2",
|
|
185
|
+
"@vxrn/compiler": "1.21.2",
|
|
186
|
+
"@vxrn/resolve": "1.21.2",
|
|
187
|
+
"@vxrn/tslib-lite": "1.21.2",
|
|
188
|
+
"@vxrn/use-isomorphic-layout-effect": "1.21.2",
|
|
189
|
+
"@vxrn/vite-plugin-metro": "1.21.2",
|
|
190
190
|
"babel-dead-code-elimination": "1.0.10",
|
|
191
191
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
192
192
|
"babel-preset-expo": "~55.0.0",
|
|
193
193
|
"citty": "^0.1.6",
|
|
194
194
|
"core-js": "^3.38.1",
|
|
195
|
-
"create-vxrn": "1.21.
|
|
195
|
+
"create-vxrn": "1.21.2",
|
|
196
196
|
"escape-string-regexp": "^5.0.0",
|
|
197
197
|
"expo-linking": "~55.0.7",
|
|
198
198
|
"expo-modules-core": "~55.0.16",
|
|
@@ -212,7 +212,7 @@
|
|
|
212
212
|
"tsconfig-paths": "^4",
|
|
213
213
|
"use-latest-callback": "^0.2.3",
|
|
214
214
|
"vite": "^8.0.13",
|
|
215
|
-
"vxrn": "1.21.
|
|
215
|
+
"vxrn": "1.21.2",
|
|
216
216
|
"ws": "^8.21.0",
|
|
217
217
|
"xxhashjs": "^0.2.2"
|
|
218
218
|
},
|
package/src/cli/build.ts
CHANGED
|
@@ -1251,7 +1251,7 @@ export async function build(args: {
|
|
|
1251
1251
|
|
|
1252
1252
|
// once done building static we can move it to client dir:
|
|
1253
1253
|
await moveAllFiles(staticDir, clientDir)
|
|
1254
|
-
await FSExtra.
|
|
1254
|
+
await FSExtra.remove(staticDir)
|
|
1255
1255
|
|
|
1256
1256
|
// write out the static paths (pathname => html) for the server
|
|
1257
1257
|
const routeMap: Record<string, string> = {}
|
package/src/cli/buildPage.ts
CHANGED
|
@@ -4,7 +4,12 @@ import { normalizePath } from 'vite'
|
|
|
4
4
|
import * as constants from '../constants'
|
|
5
5
|
import { LOADER_JS_POSTFIX_UNCACHED } from '../constants'
|
|
6
6
|
import type { LoaderProps } from '../types'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
encodeReservedFilenameChars,
|
|
9
|
+
getLoaderPath,
|
|
10
|
+
getPreloadCSSPath,
|
|
11
|
+
getPreloadPath,
|
|
12
|
+
} from '../utils/cleanUrl'
|
|
8
13
|
import { isResponse } from '../utils/isResponse'
|
|
9
14
|
import { toAbsolute, toAbsoluteUrl } from '../utils/toAbsolute'
|
|
10
15
|
import { replaceLoader } from '../vite/replaceLoader'
|
|
@@ -64,7 +69,12 @@ export async function buildPage(
|
|
|
64
69
|
const render = await getRender(serverEntry)
|
|
65
70
|
recordTiming('getRender', performance.now() - t0)
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
// encode NTFS-reserved characters (`:` from `/:param` patterns, `*` from
|
|
73
|
+
// catch-alls, hostile param values) so the artifact is writable on Windows;
|
|
74
|
+
// routeMap stores this same string, so serve-side lookups stay consistent
|
|
75
|
+
const htmlPath = encodeReservedFilenameChars(
|
|
76
|
+
`${path.endsWith('/') ? `${removeTrailingSlash(path)}/index` : path}.html`
|
|
77
|
+
)
|
|
68
78
|
// forward-slash for cross-platform manifest hygiene (matches serverJsPath)
|
|
69
79
|
const clientJsPath = clientManifestEntry
|
|
70
80
|
? normalizePath(join(clientDir, clientManifestEntry.file))
|
package/src/daemon/ipc.ts
CHANGED
|
@@ -4,6 +4,7 @@ import * as net from 'node:net'
|
|
|
4
4
|
import * as fs from 'node:fs'
|
|
5
5
|
import * as path from 'node:path'
|
|
6
6
|
import * as os from 'node:os'
|
|
7
|
+
import { createHash } from 'node:crypto'
|
|
7
8
|
import type { IPCMessage, IPCResponse, DaemonState } from './types'
|
|
8
9
|
import {
|
|
9
10
|
registerServer,
|
|
@@ -18,9 +19,32 @@ import {
|
|
|
18
19
|
} from './registry'
|
|
19
20
|
|
|
20
21
|
const SOCKET_DIR = path.join(os.homedir(), '.one')
|
|
21
|
-
const SOCKET_PATH = path.join(SOCKET_DIR, 'daemon.sock')
|
|
22
22
|
const SERVERS_FILE = path.join(SOCKET_DIR, 'servers.json')
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the daemon IPC endpoint for the current platform.
|
|
26
|
+
*
|
|
27
|
+
* Node's `net` implements local IPC as a Unix domain socket on POSIX and a named
|
|
28
|
+
* pipe on Windows — the same `listen(path)`/`connect(path)` API, but on Windows
|
|
29
|
+
* the name must live under `\\.\pipe\` (a flat, machine-global namespace) rather
|
|
30
|
+
* than the filesystem. So we select each platform's native primitive: an AF_UNIX
|
|
31
|
+
* socket file inside the owner-only `~/.one` dir on POSIX, a named pipe on
|
|
32
|
+
* Windows. The Windows name is a deterministic per-user hash so the daemon and
|
|
33
|
+
* the CLI derive the same pipe independently, and so distinct users on one
|
|
34
|
+
* machine don't collide in the shared pipe namespace.
|
|
35
|
+
*
|
|
36
|
+
* @see https://nodejs.org/api/net.html#identifying-paths-for-ipc-connections
|
|
37
|
+
*/
|
|
38
|
+
function resolveSocketPath(): string {
|
|
39
|
+
if (process.platform === 'win32') {
|
|
40
|
+
const scope = createHash('sha256').update(SOCKET_DIR).digest('hex').slice(0, 8)
|
|
41
|
+
return path.win32.join(String.raw`\\.\pipe`, `one-daemon-${scope}`)
|
|
42
|
+
}
|
|
43
|
+
return path.join(SOCKET_DIR, 'daemon.sock')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const SOCKET_PATH = resolveSocketPath()
|
|
47
|
+
|
|
24
48
|
export function getSocketPath(): string {
|
|
25
49
|
return SOCKET_PATH
|
|
26
50
|
}
|
|
@@ -124,9 +148,24 @@ export function createIPCServer(
|
|
|
124
148
|
})
|
|
125
149
|
})
|
|
126
150
|
|
|
151
|
+
// surface a bind failure as an actionable message rather than an uncaught
|
|
152
|
+
// 'error' event that crashes the process (e.g. another daemon already owns the
|
|
153
|
+
// socket/pipe).
|
|
154
|
+
server.on('error', (err: NodeJS.ErrnoException) => {
|
|
155
|
+
if (err.code === 'EADDRINUSE') {
|
|
156
|
+
console.error(`[daemon] Another daemon is already listening at ${SOCKET_PATH}`)
|
|
157
|
+
} else {
|
|
158
|
+
console.error('[daemon] IPC server error:', err.message)
|
|
159
|
+
}
|
|
160
|
+
process.exit(1)
|
|
161
|
+
})
|
|
162
|
+
|
|
127
163
|
server.listen(SOCKET_PATH, () => {
|
|
128
|
-
// owner-only permissions
|
|
129
|
-
|
|
164
|
+
// owner-only permissions on POSIX; the Windows named pipe is not a filesystem
|
|
165
|
+
// entry, so chmod does not apply there (and would throw).
|
|
166
|
+
if (process.platform !== 'win32') {
|
|
167
|
+
fs.chmodSync(SOCKET_PATH, 0o600)
|
|
168
|
+
}
|
|
130
169
|
})
|
|
131
170
|
|
|
132
171
|
return server
|
|
@@ -205,7 +244,10 @@ function handleMessage(
|
|
|
205
244
|
|
|
206
245
|
export async function isDaemonRunning(): Promise<boolean> {
|
|
207
246
|
return new Promise((resolve) => {
|
|
208
|
-
|
|
247
|
+
// On POSIX a stale socket file may linger, so a cheap existence check avoids a
|
|
248
|
+
// needless connect. On Windows the endpoint is a named pipe — not a filesystem
|
|
249
|
+
// entry — so existsSync is always false there; probe by connecting instead.
|
|
250
|
+
if (process.platform !== 'win32' && !fs.existsSync(SOCKET_PATH)) {
|
|
209
251
|
resolve(false)
|
|
210
252
|
return
|
|
211
253
|
}
|
|
@@ -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
|
}
|