@uniflowed/vite 0.0.0-alpha.41 → 0.0.0-alpha.42
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/driver.js +11 -1
- package/index.js +16 -4
- package/internal/flight.js +19 -6
- package/internal/instrumentation.js +23 -0
- package/internal/routes.js +26 -6
- package/package.json +7 -6
package/driver.js
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
import { randomUUID } from "node:crypto";
|
|
43
43
|
import { createServer as createHttpServer } from "node:http";
|
|
44
44
|
import { builtinModules, register } from "node:module";
|
|
45
|
+
import { esmExternalRequirePlugin } from "rolldown/plugins";
|
|
45
46
|
import { installFlowHooks } from "@uniflowed/host/internal/sync-hooks.js";
|
|
46
47
|
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
47
48
|
import path from "node:path";
|
|
@@ -1579,7 +1580,12 @@ async function deploy() {
|
|
|
1579
1580
|
plugins: [
|
|
1580
1581
|
...inline.plugins,
|
|
1581
1582
|
nativeAddonGuard(),
|
|
1582
|
-
...(shape.workerBuiltins === true
|
|
1583
|
+
...(shape.workerBuiltins === true
|
|
1584
|
+
? [
|
|
1585
|
+
workerBuiltinGuard(),
|
|
1586
|
+
esmExternalRequirePlugin({ external: [...builtinModules, /^node:/] }),
|
|
1587
|
+
]
|
|
1588
|
+
: []),
|
|
1583
1589
|
],
|
|
1584
1590
|
// Fixed, because this bundle inlines every dependency and so both of each
|
|
1585
1591
|
// React package's builds, and a runtime lookup of `NODE_ENV` in a worker
|
|
@@ -1610,6 +1616,10 @@ async function deploy() {
|
|
|
1610
1616
|
emptyOutDir: false,
|
|
1611
1617
|
rollupOptions: {
|
|
1612
1618
|
input,
|
|
1619
|
+
// Workers provide the selected built-ins, but cannot use Node's
|
|
1620
|
+
// createRequire(import.meta.url) runtime helper. External requires
|
|
1621
|
+
// above become ESM imports; the remaining helpers are platform neutral.
|
|
1622
|
+
...(shape.workerBuiltins === true ? { platform: "neutral" } : {}),
|
|
1613
1623
|
output: {
|
|
1614
1624
|
entryFileNames: "[name].js",
|
|
1615
1625
|
// Route modules are lazy `import()`s, so the server bundle splits
|
package/index.js
CHANGED
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
// `uniflowed(options)` returns the array; a project that wants to add a plugin
|
|
45
45
|
// declares it in `uf.config.js` and the driver appends it after these.
|
|
46
46
|
|
|
47
|
+
import { instrumentationFile } from "./internal/instrumentation.js";
|
|
48
|
+
|
|
47
49
|
import path from "node:path";
|
|
48
50
|
import { nativeWebPlugin } from "./internal/native-web.js";
|
|
49
51
|
|
|
@@ -579,6 +581,7 @@ function flowPlugin({
|
|
|
579
581
|
// looking at. See `clientModuleSource`.
|
|
580
582
|
if (id === resolved(VIRTUAL.client) && flightState != null) {
|
|
581
583
|
return flightClientSource(entryPath, {
|
|
584
|
+
instrumentation: instrumentationFile(appRoot, true),
|
|
582
585
|
strictMode: strictMode && !isProduction,
|
|
583
586
|
navigation,
|
|
584
587
|
staleTime,
|
|
@@ -587,6 +590,7 @@ function flowPlugin({
|
|
|
587
590
|
}
|
|
588
591
|
if (id === resolved(VIRTUAL.client)) {
|
|
589
592
|
return clientModuleSource(entryPath, {
|
|
593
|
+
instrumentation: instrumentationFile(appRoot, true),
|
|
590
594
|
strictMode: strictMode && !isProduction,
|
|
591
595
|
navigation,
|
|
592
596
|
staleTime,
|
|
@@ -596,8 +600,14 @@ function flowPlugin({
|
|
|
596
600
|
}
|
|
597
601
|
if (id === resolved(VIRTUAL.server)) {
|
|
598
602
|
return flightState == null
|
|
599
|
-
? serverModuleSource(entryPath, routing)
|
|
600
|
-
: flightServerSource(
|
|
603
|
+
? serverModuleSource(entryPath, routing, instrumentationFile(appRoot))
|
|
604
|
+
: flightServerSource(
|
|
605
|
+
entryPath,
|
|
606
|
+
VIRTUAL.routes,
|
|
607
|
+
VIRTUAL.actions,
|
|
608
|
+
routing,
|
|
609
|
+
instrumentationFile(appRoot),
|
|
610
|
+
);
|
|
601
611
|
}
|
|
602
612
|
if (flightState != null) {
|
|
603
613
|
if (id === resolved(FLIGHT_VIRTUAL.entry)) return rscEntrySource(VIRTUAL.routes, routing);
|
|
@@ -864,8 +874,10 @@ function flowPlugin({
|
|
|
864
874
|
const reserved = new RegExp(`/(${stems})(\\.[a-z]+)?\\.(js|jsx|mdx)$`);
|
|
865
875
|
const onRouteFile = (file) => {
|
|
866
876
|
if (!reserved.test(file) || !file.startsWith(appRoot)) return;
|
|
867
|
-
const
|
|
868
|
-
|
|
877
|
+
for (const id of [VIRTUAL.routes, VIRTUAL.server, VIRTUAL.client]) {
|
|
878
|
+
const module = devServer.moduleGraph.getModuleById(resolved(id));
|
|
879
|
+
if (module) devServer.moduleGraph.invalidateModule(module);
|
|
880
|
+
}
|
|
869
881
|
devServer.ws.send({ type: "full-reload", path: "*" });
|
|
870
882
|
};
|
|
871
883
|
devServer.watcher.on("add", onRouteFile);
|
package/internal/flight.js
CHANGED
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
// In development the rsc environment's module graph is read instead, once the
|
|
50
50
|
// route's modules have been imported.
|
|
51
51
|
|
|
52
|
+
import { clientInstrumentationSource } from "./instrumentation.js";
|
|
53
|
+
|
|
52
54
|
import path from "node:path";
|
|
53
55
|
import { relayDependencies } from "./relay.js";
|
|
54
56
|
|
|
@@ -666,7 +668,7 @@ export function flightClientSource(appEntry, options = {}) {
|
|
|
666
668
|
options.staleTime > 0 ? `, staleTime: ${JSON.stringify(options.staleTime)}` : "";
|
|
667
669
|
return `import { hydrateFlight } from "@uniflowed/router/rsc/client";
|
|
668
670
|
import App from ${JSON.stringify(appEntry)};
|
|
669
|
-
hydrateFlight({ App${strictMode}${navigation}${staleTime}${routing} });
|
|
671
|
+
${clientInstrumentationSource(options.instrumentation)}hydrateFlight({ App${strictMode}${navigation}${staleTime}${routing} });
|
|
670
672
|
`;
|
|
671
673
|
}
|
|
672
674
|
|
|
@@ -687,9 +689,13 @@ export function flightServerSource(
|
|
|
687
689
|
routesId,
|
|
688
690
|
actionsId,
|
|
689
691
|
routing = { redirects: [], rewrites: [], headers: [], basePath: "", trailingSlash: "ignore" },
|
|
692
|
+
instrumentation = null,
|
|
690
693
|
) {
|
|
691
694
|
return `import {
|
|
692
695
|
createActionDispatcher,
|
|
696
|
+
createInstrumentation,
|
|
697
|
+
instrumentRender,
|
|
698
|
+
traceRequestPhase,
|
|
693
699
|
createDispatcher,
|
|
694
700
|
createMiddlewareRunner,
|
|
695
701
|
installRouting,
|
|
@@ -703,15 +709,22 @@ import App from ${JSON.stringify(appEntry)};
|
|
|
703
709
|
export const routing = ${JSON.stringify(routing)};
|
|
704
710
|
installRouting(routing);
|
|
705
711
|
export { routes, handlers, middleware, notFound, errors };
|
|
706
|
-
|
|
712
|
+
${instrumentation == null ? "" : `import * as hooks from ${JSON.stringify(instrumentation)};`}
|
|
713
|
+
export const { beginRequest } = createInstrumentation(${instrumentation == null ? "" : "hooks"});
|
|
707
714
|
const renderer = createDocumentRenderer({ App, renderFlight, loadClientModule });
|
|
708
|
-
export const render =
|
|
715
|
+
export const render = (url, assets, options = {}) => instrumentRender(
|
|
716
|
+
(onError) => renderer.render(url, assets, { ...options, onError }), options.onError,
|
|
717
|
+
);
|
|
709
718
|
export const prerender = renderer.prerender;
|
|
710
|
-
export const flight =
|
|
719
|
+
export const flight = (url, options = {}) => instrumentRender(
|
|
720
|
+
(onError) => renderer.flight(url, { ...options, onError }), options.onError,
|
|
721
|
+
);
|
|
711
722
|
export { shellDocument } from "@uniflowed/router/server";
|
|
712
|
-
|
|
723
|
+
const dispatchRoute = createDispatcher({ handlers });
|
|
724
|
+
export const dispatch = (request) => traceRequestPhase("route", () => dispatchRoute(request));
|
|
713
725
|
export const callAction = createActionDispatcher({ actions });
|
|
714
|
-
|
|
726
|
+
const guard = createMiddlewareRunner({ middleware });
|
|
727
|
+
export const runMiddleware = (request) => traceRequestPhase("middleware", () => guard(request));
|
|
715
728
|
`;
|
|
716
729
|
}
|
|
717
730
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @noflow
|
|
2
|
+
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
export function instrumentationFile(root, client = false) {
|
|
7
|
+
const stem = client ? "$instrumentation.client" : "$instrumentation";
|
|
8
|
+
const files = [".js", ".jsx"]
|
|
9
|
+
.map((extension) => path.join(root, stem + extension))
|
|
10
|
+
.filter(existsSync);
|
|
11
|
+
if (files.length > 1)
|
|
12
|
+
throw new Error(`uf: choose one instrumentation module: ${files.join(", ")}`);
|
|
13
|
+
return files[0] ?? null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function clientInstrumentationSource(file) {
|
|
17
|
+
if (file == null) return "";
|
|
18
|
+
return `import * as instrumentation from ${JSON.stringify(file)};
|
|
19
|
+
import { installClientInstrumentation } from "@uniflowed/router/instrumentation";
|
|
20
|
+
const disposeInstrumentation = await installClientInstrumentation(instrumentation);
|
|
21
|
+
if (import.meta.hot) import.meta.hot.dispose(disposeInstrumentation);
|
|
22
|
+
`;
|
|
23
|
+
}
|
package/internal/routes.js
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
// route table imports every page and layout lazily, so a route is a chunk of
|
|
15
15
|
// its own and the client only downloads what it navigates to.
|
|
16
16
|
|
|
17
|
+
import { clientInstrumentationSource } from "./instrumentation.js";
|
|
18
|
+
|
|
17
19
|
import { readdirSync, statSync } from "node:fs";
|
|
18
20
|
import path from "node:path";
|
|
19
21
|
|
|
@@ -28,6 +30,7 @@ export const RESERVED = Object.freeze({
|
|
|
28
30
|
error: "$error",
|
|
29
31
|
loading: "$loading",
|
|
30
32
|
route: "$route",
|
|
33
|
+
instrumentation: "$instrumentation",
|
|
31
34
|
});
|
|
32
35
|
|
|
33
36
|
/**
|
|
@@ -381,6 +384,15 @@ export function scanRoutes(appRoot, options = {}) {
|
|
|
381
384
|
);
|
|
382
385
|
|
|
383
386
|
refuseUnsupportedTemplateFiles(directory, entries);
|
|
387
|
+
for (const entry of entries) {
|
|
388
|
+
if (entry.name.startsWith("$instrumentation") && !/\.test\.jsx?$/.test(entry.name)) {
|
|
389
|
+
if (depth !== 0 || !/^\$instrumentation(?:\.client)?\.jsx?$/.test(entry.name)) {
|
|
390
|
+
throw new Error(
|
|
391
|
+
`uf: ${path.join(directory, entry.name)} must be $instrumentation.js or $instrumentation.client.js at the router root`,
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
384
396
|
|
|
385
397
|
// A `$default.js` answers one question — what a slot renders when the
|
|
386
398
|
// URL says nothing about it — and this walk is everywhere a slot is not,
|
|
@@ -1660,7 +1672,7 @@ export function clientModuleSource(appEntry, options = {}) {
|
|
|
1660
1672
|
return `import { ${mount} } from "@uniflowed/router/client";
|
|
1661
1673
|
import { routes, notFound, errors } from ${JSON.stringify(VIRTUAL.routes)};
|
|
1662
1674
|
import App from ${JSON.stringify(appEntry)};
|
|
1663
|
-
${mount}({ App, routes, notFound, errors${strictMode}${navigation}${staleTime}${routing} });
|
|
1675
|
+
${clientInstrumentationSource(options.instrumentation)}${mount}({ App, routes, notFound, errors${strictMode}${navigation}${staleTime}${routing} });
|
|
1664
1676
|
`;
|
|
1665
1677
|
}
|
|
1666
1678
|
|
|
@@ -1718,9 +1730,12 @@ ${mount}({ App, routes, notFound, errors${strictMode}${navigation}${staleTime}${
|
|
|
1718
1730
|
* shorter proof of the paragraph above: the copy the router dispatches and
|
|
1719
1731
|
* renders with is by construction the copy the host is handed.
|
|
1720
1732
|
*/
|
|
1721
|
-
export function serverModuleSource(appEntry, routing = routingRulesOf({})) {
|
|
1733
|
+
export function serverModuleSource(appEntry, routing = routingRulesOf({}), instrumentation = null) {
|
|
1722
1734
|
return `import {
|
|
1723
1735
|
createActionDispatcher,
|
|
1736
|
+
createInstrumentation,
|
|
1737
|
+
instrumentRender,
|
|
1738
|
+
traceRequestPhase,
|
|
1724
1739
|
createDispatcher,
|
|
1725
1740
|
createMiddlewareRunner,
|
|
1726
1741
|
createRenderer,
|
|
@@ -1731,14 +1746,19 @@ import { actions } from ${JSON.stringify(VIRTUAL.actions)};
|
|
|
1731
1746
|
import App from ${JSON.stringify(appEntry)};
|
|
1732
1747
|
${routingExportSource(routing)}installRouting(routing);
|
|
1733
1748
|
export { routes, handlers, middleware, notFound, errors };
|
|
1734
|
-
|
|
1749
|
+
${instrumentation == null ? "" : `import * as hooks from ${JSON.stringify(instrumentation)};`}
|
|
1750
|
+
export const { beginRequest } = createInstrumentation(${instrumentation == null ? "" : "hooks"});
|
|
1735
1751
|
const renderer = createRenderer({ App, routes, notFound, errors });
|
|
1736
|
-
export const render =
|
|
1752
|
+
export const render = (url, assets, options = {}) => instrumentRender(
|
|
1753
|
+
(onError) => renderer.render(url, assets, { ...options, onError }), options.onError,
|
|
1754
|
+
);
|
|
1737
1755
|
export const prerender = renderer.prerender;
|
|
1738
1756
|
export { shellDocument } from "@uniflowed/router/server";
|
|
1739
|
-
|
|
1757
|
+
const dispatchRoute = createDispatcher({ handlers });
|
|
1758
|
+
export const dispatch = (request) => traceRequestPhase("route", () => dispatchRoute(request));
|
|
1740
1759
|
export const callAction = createActionDispatcher({ actions });
|
|
1741
|
-
|
|
1760
|
+
const guard = createMiddlewareRunner({ middleware });
|
|
1761
|
+
export const runMiddleware = (request) => traceRequestPhase("middleware", () => guard(request));
|
|
1742
1762
|
`;
|
|
1743
1763
|
}
|
|
1744
1764
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniflowed/vite",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.42",
|
|
4
4
|
"description": "Vite, driven by uf.config.js: every Flow module through `uf transform`, MDX, the file-system router and static rendering as Vite plugins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"@babel/core": "^7.29.7",
|
|
36
36
|
"@mdx-js/rollup": "^3.1.1",
|
|
37
37
|
"@shikijs/rehype": "^3.23.0",
|
|
38
|
-
"@uniflowed/host": "0.0.0-alpha.
|
|
39
|
-
"@uniflowed/router": "0.0.0-alpha.
|
|
40
|
-
"@uniflowed/server": "0.0.0-alpha.
|
|
41
|
-
"@uniflowed/validator": "0.0.0-alpha.
|
|
38
|
+
"@uniflowed/host": "0.0.0-alpha.42",
|
|
39
|
+
"@uniflowed/router": "0.0.0-alpha.42",
|
|
40
|
+
"@uniflowed/server": "0.0.0-alpha.42",
|
|
41
|
+
"@uniflowed/validator": "0.0.0-alpha.42",
|
|
42
42
|
"babel-plugin-relay": "^21.0.1",
|
|
43
43
|
"estree-util-value-to-estree": "^3.5.0",
|
|
44
44
|
"rehype-slug": "^6.0.0",
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"shiki": "^3.23.0",
|
|
48
48
|
"unist-util-mdx-define": "^1.1.2",
|
|
49
49
|
"vite": "^8.2.2",
|
|
50
|
-
"yaml": "^2.9.1"
|
|
50
|
+
"yaml": "^2.9.1",
|
|
51
|
+
"rolldown": "^1.2.7"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
54
|
"axe-core": ">=4",
|