@nifrajs/web-solid 2.9.1 → 2.11.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/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3 -1
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -1
- package/dist/index.js.map +1 -1
- package/dist/mdx.d.ts.map +1 -1
- package/dist/mdx.js +2 -1
- package/dist/mdx.js.map +1 -1
- package/dist/query.d.ts +1 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -1
- package/dist/query.js.map +1 -1
- package/dist/refresh-babel.d.ts +32 -0
- package/dist/refresh-babel.d.ts.map +1 -0
- package/dist/refresh-babel.js +84 -0
- package/dist/refresh-babel.js.map +1 -0
- package/dist/refresh-hot.d.ts +30 -0
- package/dist/refresh-hot.d.ts.map +1 -0
- package/dist/refresh-hot.js +62 -0
- package/dist/refresh-hot.js.map +1 -0
- package/dist/router.d.ts +2 -2
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +3 -1
- package/dist/router.js.map +1 -1
- package/package.json +7 -6
- package/src/client.ts +4 -1
- package/src/index.ts +55 -1
- package/src/mdx.ts +2 -1
- package/src/query.ts +4 -1
- package/src/refresh-babel.ts +133 -0
- package/src/refresh-hot.ts +81 -0
- package/src/router.ts +15 -7
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { MountRouterOptions, RenderProps } from "@nifrajs/web";
|
|
2
2
|
export { errorBoundary } from "./error.js";
|
|
3
3
|
/** Hydrate a server-rendered Solid layout `chain` (with the loader `props`) inside `container`. */
|
|
4
4
|
export declare function hydrate(chain: readonly unknown[], props: RenderProps, container: unknown): void;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAmBnE,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C,mGAAmG;AACnG,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CA+D7D"}
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// `/client`, not the root: the root's graph carries the server, and Vite's dev server evaluates it
|
|
2
|
+
// instead of tree-shaking it - which broke hydration before the browser ran a line of app code.
|
|
3
|
+
import { searchOfChain } from "@nifrajs/web/client";
|
|
2
4
|
/**
|
|
3
5
|
* @nifrajs/web-solid/client - Solid client runtime. `hydrate` hydrates a single SSR'd route;
|
|
4
6
|
* `mountRouter` hydrates the initial route then drives navigation through a Solid signal - so a
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ export declare const solidAdapter: RenderAdapter;
|
|
|
7
7
|
* for the server, `"dom"` for the client, `hydratable` so SSR and hydrate align. Solid's
|
|
8
8
|
* reactive-JSX compiler ships only as a Babel plugin (no swc/native port); this runs at
|
|
9
9
|
* build time, on `.tsx` files only.
|
|
10
|
+
*
|
|
11
|
+
* Under a dev server the client half additionally runs `solid-refresh`, which is what makes an edit
|
|
12
|
+
* patch the running component tree instead of reloading the page - see {@link setupSolidRefresh}.
|
|
10
13
|
*/
|
|
11
14
|
export declare function solidBunPlugin(generate: "dom" | "ssr"): BunPlugin;
|
|
12
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AAWpC,6EAA6E;AAC7E,eAAO,MAAM,YAAY,EAAE,aAsB1B,CAAA;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CA0BjE"}
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
import { transformAsync } from "@babel/core";
|
|
8
8
|
// @ts-expect-error - no type declarations published
|
|
9
9
|
import presetTypeScript from "@babel/preset-typescript";
|
|
10
|
+
import { devServerCompile, rewriteSsrImports } from "@nifrajs/web/plugins/kit";
|
|
10
11
|
// @ts-expect-error - no type declarations published
|
|
11
12
|
import presetSolid from "babel-preset-solid";
|
|
12
13
|
import { generateHydrationScript, renderToStream as solidRenderToStream, renderToString as solidRenderToString, } from "solid-js/web";
|
|
13
14
|
import { compose } from "./compose.js";
|
|
15
|
+
import solidRefreshBunHot, { SOLID_HOT_MODULE } from "./refresh-babel.js";
|
|
14
16
|
const HYDRATION_HEAD = generateHydrationScript();
|
|
15
17
|
/** The Solid server render adapter - pass to @nifrajs/web's `renderPage`. */
|
|
16
18
|
export const solidAdapter = {
|
|
@@ -41,11 +43,15 @@ export const solidAdapter = {
|
|
|
41
43
|
* for the server, `"dom"` for the client, `hydratable` so SSR and hydrate align. Solid's
|
|
42
44
|
* reactive-JSX compiler ships only as a Babel plugin (no swc/native port); this runs at
|
|
43
45
|
* build time, on `.tsx` files only.
|
|
46
|
+
*
|
|
47
|
+
* Under a dev server the client half additionally runs `solid-refresh`, which is what makes an edit
|
|
48
|
+
* patch the running component tree instead of reloading the page - see {@link setupSolidRefresh}.
|
|
44
49
|
*/
|
|
45
50
|
export function solidBunPlugin(generate) {
|
|
46
51
|
return {
|
|
47
52
|
name: `nifra-solid-${generate}`,
|
|
48
53
|
setup(build) {
|
|
54
|
+
const refresh = generate === "dom" && devServerCompile() ? setupSolidRefresh(build) : undefined;
|
|
49
55
|
// Match `.tsx`, tolerating a `?query` suffix (dev servers append one to bust Bun's import
|
|
50
56
|
// cache); strip it before reading the file off disk.
|
|
51
57
|
build.onLoad({ filter: /\.tsx(\?|$)/ }, async (args) => {
|
|
@@ -58,10 +64,53 @@ export function solidBunPlugin(generate) {
|
|
|
58
64
|
[presetSolid, { generate, hydratable: true }],
|
|
59
65
|
[presetTypeScript, { onlyRemoveTypeImports: true }],
|
|
60
66
|
],
|
|
67
|
+
...(refresh !== undefined
|
|
68
|
+
? { plugins: [[await refresh.babel(), REFRESH_OPTIONS], solidRefreshBunHot] }
|
|
69
|
+
: {}),
|
|
61
70
|
});
|
|
62
|
-
return { contents: result?.code ?? "", loader: "js" };
|
|
71
|
+
return { contents: rewriteSsrImports(result?.code ?? "", path, generate), loader: "js" };
|
|
63
72
|
});
|
|
64
73
|
},
|
|
65
74
|
};
|
|
66
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* `"esm"` is the closest of `solid-refresh`'s bundler modes to what Bun implements: one
|
|
78
|
+
* `accept(mod => …)` per module, falling back to `invalidate()` when a component's signature changed too
|
|
79
|
+
* much to patch in place. `"vite"` differs only by also calling a bare `accept()` first, which would make
|
|
80
|
+
* every module self-accepting twice over. The call it emits is still Vite-shaped, and
|
|
81
|
+
* `solidRefreshBunHot` translates it.
|
|
82
|
+
*
|
|
83
|
+
* `jsx: false` turns OFF the pass that lifts a component's returned JSX into a second, nested component.
|
|
84
|
+
* That extra component is an extra hydration level on the client and none on the server, so with it on,
|
|
85
|
+
* every hydratable page dies on `Unable to find DOM nodes for hydration key` before a single edit. It buys
|
|
86
|
+
* finer-grained patching of markup-only edits; correct hydration is worth more.
|
|
87
|
+
*/
|
|
88
|
+
const REFRESH_OPTIONS = { bundler: "esm", jsx: false };
|
|
89
|
+
/**
|
|
90
|
+
* Wire `solid-refresh` into a dev-server client compile.
|
|
91
|
+
*
|
|
92
|
+
* Solid components are compiled reactive closures, not functions re-run on render, so a new module
|
|
93
|
+
* version cannot simply replace the old one - `solid-refresh` wraps every component in a registry and, on
|
|
94
|
+
* an update, patches the live instances, keeping signal state. Without it the update finds no accepting
|
|
95
|
+
* module, bubbles up to the generated entry, and Bun reloads the whole page.
|
|
96
|
+
*
|
|
97
|
+
* The Babel half loads lazily: it is dev-only, and this module is the adapter root every Solid SSR
|
|
98
|
+
* server imports.
|
|
99
|
+
*
|
|
100
|
+
* Both runtime specifiers need pinning, because the transform emits them INTO the app's own files, where
|
|
101
|
+
* a bare specifier resolves against the app. `solid-refresh` is only a transitive dependency there and
|
|
102
|
+
* need not be hoisted; `nifra:solid-hot` is this package's own bridge module and has no app-side name at
|
|
103
|
+
* all. Resolving both here is what keeps the emitted imports working without an app depending on either.
|
|
104
|
+
*/
|
|
105
|
+
function setupSolidRefresh(build) {
|
|
106
|
+
const runtime = Bun.resolveSync("solid-refresh", import.meta.dir);
|
|
107
|
+
build.onResolve({ filter: /^solid-refresh$/ }, () => ({ path: runtime }));
|
|
108
|
+
// `.ts` from source (Bun takes the package's `bun` export condition), `.js` from the published build.
|
|
109
|
+
const bridge = `${import.meta.dir}/refresh-hot${import.meta.path.endsWith(".ts") ? ".ts" : ".js"}`;
|
|
110
|
+
build.onResolve({ filter: new RegExp(`^${SOLID_HOT_MODULE}$`) }, () => ({ path: bridge }));
|
|
111
|
+
let babel;
|
|
112
|
+
return {
|
|
113
|
+
babel: () => (babel ??= import("solid-refresh/babel").then((m) => m.default)),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
67
116
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,oDAAoD;AACpD,OAAO,gBAAgB,MAAM,0BAA0B,CAAA;AAEvD,oDAAoD;AACpD,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,OAAO,EACL,uBAAuB,EACvB,cAAc,IAAI,mBAAmB,EACrC,cAAc,IAAI,mBAAmB,GACtC,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/mdx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdx.d.ts","sourceRoot":"","sources":["../src/mdx.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mdx.d.ts","sourceRoot":"","sources":["../src/mdx.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AASpC;sEACsE;AACtE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAmCpE"}
|
package/dist/mdx.js
CHANGED
|
@@ -17,6 +17,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
17
17
|
import { transformAsync } from "@babel/core";
|
|
18
18
|
// @ts-expect-error - no type declarations published
|
|
19
19
|
import presetTypeScript from "@babel/preset-typescript";
|
|
20
|
+
import { rewriteSsrImports } from "@nifrajs/web/plugins/kit";
|
|
20
21
|
// @ts-expect-error - no type declarations published
|
|
21
22
|
import presetSolid from "babel-preset-solid";
|
|
22
23
|
// Non-literal so tsc/consumers don't need `@mdx-js/mdx`'s types to typecheck this file (optional peer).
|
|
@@ -51,7 +52,7 @@ export function solidMdxBunPlugin(generate) {
|
|
|
51
52
|
babelrc: false,
|
|
52
53
|
configFile: false,
|
|
53
54
|
});
|
|
54
|
-
return { contents: result?.code ?? "", loader: "js" };
|
|
55
|
+
return { contents: rewriteSsrImports(result?.code ?? "", path, generate), loader: "js" };
|
|
55
56
|
});
|
|
56
57
|
},
|
|
57
58
|
};
|
package/dist/mdx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdx.js","sourceRoot":"","sources":["../src/mdx.ts"],"names":[],"mappings":";;;;;;;;AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,oDAAoD;AACpD,OAAO,gBAAgB,MAAM,0BAA0B,CAAA;AACvD,oDAAoD;AACpD,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAG5C,wGAAwG;AACxG,MAAM,UAAU,GAAG,aAAa,CAAA;AAMhC;sEACsE;AACtE,MAAM,UAAU,iBAAiB,CAAC,QAAuB;IACvD,OAAO;QACL,IAAI,EAAE,mBAAmB,QAAQ,EAAE;QACnC,KAAK,CAAC,KAAK,CAAC,KAAK;YACf,IAAI,OAA+B,CAAA;YACnC,IAAI,CAAC;gBACH,OAAO,GAAI,CAAC,MAAM,MAAM,kCAAC,UAAU,EAAC,CAAiB,CAAC,OAAO,CAAA;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CACb,gHAAgH,CACjH,CAAA;YACH,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAA;gBACjD,0FAA0F;gBAC1F,MAAM,GAAG,GAAG,MAAM,CAChB,MAAM,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;oBACzC,GAAG,EAAE,IAAI;oBACT,oBAAoB,EAAE,gCAAgC;iBACvD,CAAC,CACH,CAAA;gBACD,4EAA4E;gBAC5E,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE;oBACvC,QAAQ,EAAE,GAAG,IAAI,MAAM;oBACvB,OAAO,EAAE;wBACP,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;wBAC7C,CAAC,gBAAgB,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC;qBACpD;oBACD,OAAO,EAAE,KAAK;oBACd,UAAU,EAAE,KAAK;iBAClB,CAAC,CAAA;gBACF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"mdx.js","sourceRoot":"","sources":["../src/mdx.ts"],"names":[],"mappings":";;;;;;;;AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,oDAAoD;AACpD,OAAO,gBAAgB,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,oDAAoD;AACpD,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAG5C,wGAAwG;AACxG,MAAM,UAAU,GAAG,aAAa,CAAA;AAMhC;sEACsE;AACtE,MAAM,UAAU,iBAAiB,CAAC,QAAuB;IACvD,OAAO;QACL,IAAI,EAAE,mBAAmB,QAAQ,EAAE;QACnC,KAAK,CAAC,KAAK,CAAC,KAAK;YACf,IAAI,OAA+B,CAAA;YACnC,IAAI,CAAC;gBACH,OAAO,GAAI,CAAC,MAAM,MAAM,kCAAC,UAAU,EAAC,CAAiB,CAAC,OAAO,CAAA;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CACb,gHAAgH,CACjH,CAAA;YACH,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAA;gBACjD,0FAA0F;gBAC1F,MAAM,GAAG,GAAG,MAAM,CAChB,MAAM,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;oBACzC,GAAG,EAAE,IAAI;oBACT,oBAAoB,EAAE,gCAAgC;iBACvD,CAAC,CACH,CAAA;gBACD,4EAA4E;gBAC5E,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE;oBACvC,QAAQ,EAAE,GAAG,IAAI,MAAM;oBACvB,OAAO,EAAE;wBACP,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;wBAC7C,CAAC,gBAAgB,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC;qBACpD;oBACD,OAAO,EAAE,KAAK;oBACd,UAAU,EAAE,KAAK;iBAClB,CAAC,CAAA;gBACF,OAAO,EAAE,QAAQ,EAAE,iBAAiB,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;YAC1F,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/dist/query.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QueryClient, QueryState } from "@nifrajs/web";
|
|
2
2
|
/**
|
|
3
3
|
* `@nifrajs/web-solid/query` - Solid bindings for the keyed query-cache. `createQuery(key, fn)` bridges a
|
|
4
4
|
* query's `subscribe`/`snapshot` store into a Solid signal and fetches on mount; `useQueryClient`
|
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAI3D;;;;;;;;;GASG;AACH,OAAO,EAAE,KAAK,QAAQ,EAAoC,MAAM,UAAU,CAAA;AAS1E,wGAAwG;AACxG,wBAAgB,cAAc,IAAI,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAEvE;AAUD,wDAAwD;AACxD,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,uGAAuG;IACvG,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;IACvC,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;CACnC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAgBvF"}
|
package/dist/query.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// `/client`, not the root - these are DOM values, and the root's graph carries the
|
|
2
|
+
// server, which Vite's dev server evaluates rather than tree-shakes.
|
|
3
|
+
import { createQueryClient } from "@nifrajs/web/client";
|
|
2
4
|
/**
|
|
3
5
|
* `@nifrajs/web-solid/query` - Solid bindings for the keyed query-cache. `createQuery(key, fn)` bridges a
|
|
4
6
|
* query's `subscribe`/`snapshot` store into a Solid signal and fetches on mount; `useQueryClient`
|
package/dist/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AACA,mFAAmF;AACnF,qEAAqE;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD;;;;;;;;;GASG;AACH,OAAO,EAAiB,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAE1E,IAAI,MAA+B,CAAA;AACnC,SAAS,SAAS;IAChB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,SAAS,CAAA,CAAC,wCAAwC;IAC5F,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,GAAG,iBAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC/E,OAAO,MAAM,CAAA;AACf,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,cAAc;IAC5B,OAAO,SAAS,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAA;AACvD,CAAC;AAED,MAAM,IAAI,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,MAAM,CAAC,iBAAiB;CACpC,CAAC,CAAA;AAUF;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAI,GAAY,EAAE,EAAoB;IAC/D,MAAM,MAAM,GAAG,SAAS,EAAE,EAAE,KAAK,CAAI,GAAG,EAAE,EAAE,CAAC,CAAA;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAgB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACxF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;QACpE,OAAO,CAAC,GAAG,EAAE;YACX,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAChC,CAAC,CAAC,CAAA;QACF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;IAC3C,CAAC;IACD,OAAO;QACL,KAAK;QACL,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAA;QAChG,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Babel pass that runs AFTER `solid-refresh` and rewrites the one call it emits into the dialect
|
|
3
|
+
* Bun's dev server speaks. Dev-server client compiles only (`solidBunPlugin("dom")`).
|
|
4
|
+
*
|
|
5
|
+
* `solid-refresh` ends every component module with
|
|
6
|
+
*
|
|
7
|
+
* if (import.meta.hot) { _$$refresh("esm", import.meta.hot, _REGISTRY) }
|
|
8
|
+
*
|
|
9
|
+
* which is a Vite assumption: that `import.meta.hot` is an object you can pass around. Bun's bundler
|
|
10
|
+
* instead rewrites `import.meta.hot.<prop>` where it can see it and substitutes, for every other use, a
|
|
11
|
+
* proxy that throws `import.meta.hot.<prop> cannot be used indirectly` on the first property read. So the
|
|
12
|
+
* argument has to become something built from member accesses Bun CAN see, and the rest of the
|
|
13
|
+
* adaptation moves into `./refresh-hot` (which also supplies the cross-version store and the reload that
|
|
14
|
+
* stands in for Bun's unimplemented `invalidate`):
|
|
15
|
+
*
|
|
16
|
+
* if (import.meta.hot) { _ref(import.meta.url, (cb) => import.meta.hot.accept(cb), _REGISTRY) }
|
|
17
|
+
*
|
|
18
|
+
* Rewriting rather than string-replacing matters: the identifier `solid-refresh` picks is uniquified
|
|
19
|
+
* against the module's own scope, so it is not a fixed string, and a silent miss would leave a module
|
|
20
|
+
* that throws on load.
|
|
21
|
+
*/
|
|
22
|
+
import type { types as BabelTypes, PluginObj, PluginPass } from "@babel/core";
|
|
23
|
+
/**
|
|
24
|
+
* The virtual specifier for `./refresh-hot`, resolved by `solidBunPlugin` against THIS package. The
|
|
25
|
+
* import lands in an app's own file, where a relative path would be wrong and a bare `@nifrajs/web-solid`
|
|
26
|
+
* subpath would depend on how the app's install happens to be laid out.
|
|
27
|
+
*/
|
|
28
|
+
export declare const SOLID_HOT_MODULE = "nifra:solid-hot";
|
|
29
|
+
export default function solidRefreshBunHot({ types: t, }: {
|
|
30
|
+
types: typeof BabelTypes;
|
|
31
|
+
}): PluginObj<PluginPass>;
|
|
32
|
+
//# sourceMappingURL=refresh-babel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-babel.d.ts","sourceRoot":"","sources":["../src/refresh-babel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAa,KAAK,IAAI,UAAU,EAAY,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAElG;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,oBAAoB,CAAA;AAgEjD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,KAAK,EAAE,CAAC,GACT,EAAE;IACD,KAAK,EAAE,OAAO,UAAU,CAAA;CACzB,GAAG,SAAS,CAAC,UAAU,CAAC,CAoCxB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The virtual specifier for `./refresh-hot`, resolved by `solidBunPlugin` against THIS package. The
|
|
3
|
+
* import lands in an app's own file, where a relative path would be wrong and a bare `@nifrajs/web-solid`
|
|
4
|
+
* subpath would depend on how the app's install happens to be laid out.
|
|
5
|
+
*/
|
|
6
|
+
export const SOLID_HOT_MODULE = "nifra:solid-hot";
|
|
7
|
+
/** `solid-refresh`'s call, under whatever uid Babel gave the import in this module's scope. */
|
|
8
|
+
const REFRESH_CALLEE = /^_*\$\$refresh\d*$/;
|
|
9
|
+
/** Per-file memo of the injected `refresh` import, so a module with many components imports it once. */
|
|
10
|
+
const injected = new WeakMap();
|
|
11
|
+
/**
|
|
12
|
+
* `import.meta`, in either of the two shapes it can arrive in: the `MetaProperty` a parser produces, and
|
|
13
|
+
* the plain `import` . `meta` member expression `solid-refresh` hand-builds. Matching only the former is
|
|
14
|
+
* what a first cut gets wrong - the emitted call reads `import.meta.hot` but is not a `MetaProperty`.
|
|
15
|
+
*/
|
|
16
|
+
const isImportMeta = (t, node) => (t.isMetaProperty(node) && node.meta.name === "import" && node.property.name === "meta") ||
|
|
17
|
+
(t.isMemberExpression(node) &&
|
|
18
|
+
!node.computed &&
|
|
19
|
+
t.isIdentifier(node.object, { name: "import" }) &&
|
|
20
|
+
t.isIdentifier(node.property, { name: "meta" }));
|
|
21
|
+
/** `import.meta.hot` exactly - the argument this pass replaces. */
|
|
22
|
+
const isImportMetaHot = (t, node) => t.isMemberExpression(node) &&
|
|
23
|
+
!node.computed &&
|
|
24
|
+
isImportMeta(t, node.object) &&
|
|
25
|
+
t.isIdentifier(node.property) &&
|
|
26
|
+
node.property.name === "hot";
|
|
27
|
+
const importMetaMember = (t, property) => t.memberExpression(t.metaProperty(t.identifier("import"), t.identifier("meta")), t.identifier(property));
|
|
28
|
+
/** `(cb) => import.meta.hot.accept(cb)` - `accept` reached the only way Bun's bundler recognizes. */
|
|
29
|
+
function acceptClosure(t) {
|
|
30
|
+
const callback = t.identifier("cb");
|
|
31
|
+
return t.arrowFunctionExpression([callback], t.callExpression(t.memberExpression(importMetaMember(t, "hot"), t.identifier("accept")), [
|
|
32
|
+
callback,
|
|
33
|
+
]));
|
|
34
|
+
}
|
|
35
|
+
function refreshImport(t, path, state) {
|
|
36
|
+
const existing = injected.get(state);
|
|
37
|
+
if (existing !== undefined)
|
|
38
|
+
return existing;
|
|
39
|
+
const program = path.scope.getProgramParent().path;
|
|
40
|
+
const local = program.scope.generateUidIdentifier("nifraSolidRefresh");
|
|
41
|
+
program.node.body.unshift(t.importDeclaration([t.importSpecifier(local, t.identifier("refresh"))], t.stringLiteral(SOLID_HOT_MODULE)));
|
|
42
|
+
injected.set(state, local);
|
|
43
|
+
return local;
|
|
44
|
+
}
|
|
45
|
+
export default function solidRefreshBunHot({ types: t, }) {
|
|
46
|
+
return {
|
|
47
|
+
name: "nifra-solid-refresh-bun-hot",
|
|
48
|
+
// Required by the plugin shape, and deliberately empty - see `post` below.
|
|
49
|
+
visitor: {},
|
|
50
|
+
// No visitor entries at all: the call this pass rewrites does not exist during the shared traversal.
|
|
51
|
+
// `solid-refresh` appends it with `pushContainer` from its own `Program` handler, and nodes added
|
|
52
|
+
// that way are never handed to the other plugins' visitors. `Program.exit` is no better - exit
|
|
53
|
+
// handlers fire in plugin order, so this one would run BEFORE the append. `post` runs once the
|
|
54
|
+
// file's whole traversal is finished, which is the first point at which the call is there to see.
|
|
55
|
+
post(file) {
|
|
56
|
+
const state = this;
|
|
57
|
+
file.path.traverse({
|
|
58
|
+
CallExpression(path) {
|
|
59
|
+
const callee = path.node.callee;
|
|
60
|
+
if (!t.isIdentifier(callee) || !REFRESH_CALLEE.test(callee.name))
|
|
61
|
+
return;
|
|
62
|
+
const args = path.node.arguments;
|
|
63
|
+
// ("esm", import.meta.hot, registry) - anything else is not the call this pass is for.
|
|
64
|
+
if (args.length !== 3)
|
|
65
|
+
return;
|
|
66
|
+
const hot = args[1];
|
|
67
|
+
const registry = args[2];
|
|
68
|
+
if (hot === undefined || registry === undefined || !isImportMetaHot(t, hot))
|
|
69
|
+
return;
|
|
70
|
+
if (!t.isExpression(registry))
|
|
71
|
+
return;
|
|
72
|
+
// The replacement's callee is the injected uid, which REFRESH_CALLEE never matches, so the
|
|
73
|
+
// re-traversal `replaceWith` triggers terminates here.
|
|
74
|
+
path.replaceWith(t.callExpression(refreshImport(t, path, state), [
|
|
75
|
+
importMetaMember(t, "url"),
|
|
76
|
+
acceptClosure(t),
|
|
77
|
+
registry,
|
|
78
|
+
]));
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=refresh-babel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-babel.js","sourceRoot":"","sources":["../src/refresh-babel.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAA;AAEjD,+FAA+F;AAC/F,MAAM,cAAc,GAAG,oBAAoB,CAAA;AAE3C,wGAAwG;AACxG,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAqC,CAAA;AAEjE;;;;GAIG;AACH,MAAM,YAAY,GAAG,CAAC,CAAoB,EAAE,IAAqB,EAAW,EAAE,CAC5E,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC;IACxF,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC;QACzB,CAAC,IAAI,CAAC,QAAQ;QACd,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC/C,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAEpD,mEAAmE;AACnE,MAAM,eAAe,GAAG,CAAC,CAAoB,EAAE,IAAqB,EAAW,EAAE,CAC/E,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC;IAC1B,CAAC,IAAI,CAAC,QAAQ;IACd,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC7B,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAA;AAE9B,MAAM,gBAAgB,GAAG,CAAC,CAAoB,EAAE,QAAgB,EAA+B,EAAE,CAC/F,CAAC,CAAC,gBAAgB,CAChB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAC5D,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CACvB,CAAA;AAEH,qGAAqG;AACrG,SAAS,aAAa,CAAC,CAAoB;IACzC,MAAM,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IACnC,OAAO,CAAC,CAAC,uBAAuB,CAC9B,CAAC,QAAQ,CAAC,EACV,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE;QACvF,QAAQ;KACT,CAAC,CACH,CAAA;AACH,CAAC;AAED,SAAS,aAAa,CACpB,CAAoB,EACpB,IAAyC,EACzC,KAAiB;IAEjB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACpC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAA;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,IAAoC,CAAA;IAClF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,CAAA;IACtE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CACvB,CAAC,CAAC,iBAAiB,CACjB,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EACnD,CAAC,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAClC,CACF,CAAA;IACD,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAC1B,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,KAAK,EAAE,CAAC,GAGT;IACC,OAAO;QACL,IAAI,EAAE,6BAA6B;QACnC,2EAA2E;QAC3E,OAAO,EAAE,EAAE;QACX,qGAAqG;QACrG,kGAAkG;QAClG,+FAA+F;QAC/F,+FAA+F;QAC/F,kGAAkG;QAClG,IAAI,CAAmB,IAAe;YACpC,MAAM,KAAK,GAAG,IAAI,CAAA;YAClB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACjB,cAAc,CAAC,IAAI;oBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;oBAC/B,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;wBAAE,OAAM;oBACxE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAA;oBAChC,uFAAuF;oBACvF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAM;oBAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;oBACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;oBACxB,IAAI,GAAG,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC;wBAAE,OAAM;oBACnF,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC;wBAAE,OAAM;oBACrC,2FAA2F;oBAC3F,uDAAuD;oBACvD,IAAI,CAAC,WAAW,CACd,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE;wBAC9C,gBAAgB,CAAC,CAAC,EAAE,KAAK,CAAC;wBAC1B,aAAa,CAAC,CAAC,CAAC;wBAChB,QAAQ;qBACT,CAAC,CACH,CAAA;gBACH,CAAC;aACF,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `solid-refresh` ↔ Bun-dev-server bridge, client-side. Loaded only by a dev-server client bundle
|
|
3
|
+
* (`solidBunPlugin("dom")` resolves the `nifra:solid-hot` specifier its Babel pass emits); never part of
|
|
4
|
+
* `nifra build` output.
|
|
5
|
+
*
|
|
6
|
+
* `solid-refresh` expects a Vite-shaped `import.meta.hot` handed to it as a VALUE. Bun does not have one:
|
|
7
|
+
* it rewrites `import.meta.hot.<prop>` at bundle time and substitutes a proxy that throws
|
|
8
|
+
* (`import.meta.hot.<prop> cannot be used indirectly`) for every other use - so passing the object to a
|
|
9
|
+
* library function fails on the first property read, whichever property it is. This module supplies the
|
|
10
|
+
* value-shaped object instead, built from direct member accesses the plugin emits at the call site.
|
|
11
|
+
*
|
|
12
|
+
* Two of the three pieces need more than a pass-through:
|
|
13
|
+
*
|
|
14
|
+
* - `data` is where `solid-refresh` keeps the previous version's component registry, so it has to be the
|
|
15
|
+
* SAME object across every version of a module. Bun's own `data` is a field on a per-version module
|
|
16
|
+
* record, so it is not usable for that; the store below is keyed by module URL and lives in this
|
|
17
|
+
* module, which no edit invalidates.
|
|
18
|
+
* - `invalidate` is not implemented in Bun's HMR runtime (it throws). It is the escape hatch
|
|
19
|
+
* `solid-refresh` takes when a component's shape changed too much to patch in place, and a full reload
|
|
20
|
+
* is exactly the right answer there - so that is what it does.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Run `solid-refresh`'s update handshake for one module.
|
|
24
|
+
*
|
|
25
|
+
* `moduleUrl` identifies the module across versions; `accept` is a closure the plugin emits around
|
|
26
|
+
* `import.meta.hot.accept`, which is the only form Bun's bundler will rewrite. `registry` is the
|
|
27
|
+
* component registry this version of the module built.
|
|
28
|
+
*/
|
|
29
|
+
export declare function refresh(moduleUrl: string, accept: (callback: (module: unknown) => void) => void, registry: unknown): void;
|
|
30
|
+
//# sourceMappingURL=refresh-hot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-hot.d.ts","sourceRoot":"","sources":["../src/refresh-hot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAuCH;;;;;;GAMG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,EACrD,QAAQ,EAAE,OAAO,GAChB,IAAI,CAUN"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `solid-refresh` ↔ Bun-dev-server bridge, client-side. Loaded only by a dev-server client bundle
|
|
3
|
+
* (`solidBunPlugin("dom")` resolves the `nifra:solid-hot` specifier its Babel pass emits); never part of
|
|
4
|
+
* `nifra build` output.
|
|
5
|
+
*
|
|
6
|
+
* `solid-refresh` expects a Vite-shaped `import.meta.hot` handed to it as a VALUE. Bun does not have one:
|
|
7
|
+
* it rewrites `import.meta.hot.<prop>` at bundle time and substitutes a proxy that throws
|
|
8
|
+
* (`import.meta.hot.<prop> cannot be used indirectly`) for every other use - so passing the object to a
|
|
9
|
+
* library function fails on the first property read, whichever property it is. This module supplies the
|
|
10
|
+
* value-shaped object instead, built from direct member accesses the plugin emits at the call site.
|
|
11
|
+
*
|
|
12
|
+
* Two of the three pieces need more than a pass-through:
|
|
13
|
+
*
|
|
14
|
+
* - `data` is where `solid-refresh` keeps the previous version's component registry, so it has to be the
|
|
15
|
+
* SAME object across every version of a module. Bun's own `data` is a field on a per-version module
|
|
16
|
+
* record, so it is not usable for that; the store below is keyed by module URL and lives in this
|
|
17
|
+
* module, which no edit invalidates.
|
|
18
|
+
* - `invalidate` is not implemented in Bun's HMR runtime (it throws). It is the escape hatch
|
|
19
|
+
* `solid-refresh` takes when a component's shape changed too much to patch in place, and a full reload
|
|
20
|
+
* is exactly the right answer there - so that is what it does.
|
|
21
|
+
*/
|
|
22
|
+
import { $$refresh } from "solid-refresh";
|
|
23
|
+
/**
|
|
24
|
+
* Registry store per module URL - see the note above on why Bun's own `hot.data` cannot serve.
|
|
25
|
+
*
|
|
26
|
+
* On `globalThis`, not in module scope: Bun re-evaluates an updated module's imports along with it, so
|
|
27
|
+
* this very module is re-instantiated during an update and a module-scoped Map would come back empty
|
|
28
|
+
* halfway through. The symptom of getting that wrong is not a lost registry but an infinite one -
|
|
29
|
+
* `patchRegistry` then compares a registry against itself, points a component's signal at its own proxy,
|
|
30
|
+
* and the next render recurses until the stack blows.
|
|
31
|
+
*/
|
|
32
|
+
const STORES = Symbol.for("nifra.solid-refresh.stores");
|
|
33
|
+
function store(moduleUrl) {
|
|
34
|
+
const host = globalThis;
|
|
35
|
+
host[STORES] ??= new Map();
|
|
36
|
+
const stores = host[STORES];
|
|
37
|
+
let data = stores.get(moduleUrl);
|
|
38
|
+
if (data === undefined) {
|
|
39
|
+
data = {};
|
|
40
|
+
stores.set(moduleUrl, data);
|
|
41
|
+
}
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Run `solid-refresh`'s update handshake for one module.
|
|
46
|
+
*
|
|
47
|
+
* `moduleUrl` identifies the module across versions; `accept` is a closure the plugin emits around
|
|
48
|
+
* `import.meta.hot.accept`, which is the only form Bun's bundler will rewrite. `registry` is the
|
|
49
|
+
* component registry this version of the module built.
|
|
50
|
+
*/
|
|
51
|
+
export function refresh(moduleUrl, accept, registry) {
|
|
52
|
+
const reload = () => {
|
|
53
|
+
location.reload();
|
|
54
|
+
};
|
|
55
|
+
const hot = { data: store(moduleUrl), accept, invalidate: reload, decline: reload };
|
|
56
|
+
// `$$refresh`'s published signature is a discriminated tuple over every bundler mode it supports, so
|
|
57
|
+
// the "esm" arm cannot be selected by a cast on the hot object alone. The mode string and the shape
|
|
58
|
+
// above are what pin it; the call itself is what has to be re-typed.
|
|
59
|
+
const esmRefresh = $$refresh;
|
|
60
|
+
esmRefresh("esm", hot, registry);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=refresh-hot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-hot.js","sourceRoot":"","sources":["../src/refresh-hot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAEzC;;;;;;;;GAQG;AACH,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AAMvD,SAAS,KAAK,CAAC,SAAiB;IAC9B,MAAM,IAAI,GAAG,UAAuB,CAAA;IACpC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG,EAAmC,CAAA;IAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3B,IAAI,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IAChC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,GAAG,EAAE,CAAA;QACT,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;IAC7B,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAUD;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,SAAiB,EACjB,MAAqD,EACrD,QAAiB;IAEjB,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,QAAQ,CAAC,MAAM,EAAE,CAAA;IACnB,CAAC,CAAA;IACD,MAAM,GAAG,GAAa,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IAC7F,qGAAqG;IACrG,oGAAoG;IACpG,qEAAqE;IACrE,MAAM,UAAU,GAAG,SAA+E,CAAA;IAClG,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAA;AAClC,CAAC"}
|
package/dist/router.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { InferOutput, StandardSchemaV1 } from "@nifrajs/core/server";
|
|
2
|
-
import {
|
|
2
|
+
import type { Blocker, BlockerFunction, BlockerState, NavigateFunction } from "@nifrajs/web";
|
|
3
3
|
/**
|
|
4
4
|
* `@nifrajs/web-solid/router` - Solid routing bindings over the agnostic `@nifrajs/web` history layer:
|
|
5
5
|
* `useNavigate` (programmatic navigation), `useBlocker` (the unsaved-changes guard), and `useSearch`
|
|
@@ -8,7 +8,7 @@ import { type Blocker, type BlockerFunction, type NavigateFunction } from "@nifr
|
|
|
8
8
|
* reads the accessor `compose` provides on SSR + client mount alike. Imports only `solid-js`. No JSX.
|
|
9
9
|
*/
|
|
10
10
|
import { type Accessor, type Context } from "solid-js";
|
|
11
|
-
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction }
|
|
11
|
+
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction };
|
|
12
12
|
export declare const SearchContext: Context<Accessor<Record<string, unknown>> | undefined>;
|
|
13
13
|
/**
|
|
14
14
|
* The route's typed, validated search params as a reactive accessor - the SAME value the loader received
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAIzE,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,YAAY,EACZ,gBAAgB,EAGjB,MAAM,cAAc,CAAA;AASrB;;;;;;GAMG;AACH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EAKb,MAAM,UAAU,CAAA;AAEjB,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAA;AAiBxE,eAAO,MAAM,aAAa,wDACoE,CAAA;AAG9F;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,MAAM,SAAS,gBAAgB,GAAG,SAAS,GAAG,SAAS,KAAK,QAAQ,CAC5F,MAAM,SAAS,gBAAgB,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAChF,CAIA;AAED;;kCAEkC;AAClC,wBAAgB,WAAW,IAAI,gBAAgB,CAO9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,OAAO,GAAG,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,CASpF"}
|
package/dist/router.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// `/client`, not the root - these are DOM values, and the root's graph carries the
|
|
2
|
+
// server, which Vite's dev server evaluates rather than tree-shakes.
|
|
3
|
+
import { getBrowserNavigate, IDLE_BLOCKER, registerBlocker, resolveNavigate, } from "@nifrajs/web/client";
|
|
2
4
|
/**
|
|
3
5
|
* `@nifrajs/web-solid/router` - Solid routing bindings over the agnostic `@nifrajs/web` history layer:
|
|
4
6
|
* `useNavigate` (programmatic navigation), `useBlocker` (the unsaved-changes guard), and `useSearch`
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAYA,mFAAmF;AACnF,qEAAqE;AACrE,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,qBAAqB,CAAA;AAC5B;;;;;;GAMG;AACH,OAAO,EAGL,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,GACX,MAAM,UAAU,CAAA;AAIjB,6FAA6F;AAC7F,MAAM,YAAY,GAAsC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AACzE,MAAM,qBAAqB,GAAsC,GAAG,EAAE,CAAC,YAAY,CAAA;AAEnF;;;;;;2BAM2B;AAC3B,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;AACxE,MAAM,iBAAiB,GAAG,UAEzB,CAAA;AACD,MAAM,CAAC,MAAM,aAAa,GACxB,iBAAiB,CAAC,mBAAmB,CAAC,IAAI,aAAa,EAAqC,CAAA;AAC9F,iBAAiB,CAAC,mBAAmB,CAAC,GAAG,aAAa,CAAA;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS;IAGvB,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAEzD,CAAA;AACH,CAAC;AAED;;kCAEkC;AAClC,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,CAAC,EAAyC,EAAE,OAAyB,EAAE,EAAE;QAC/E,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;QACrC,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAM;QAClC,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;QAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IACzC,CAAC,CAAqB,CAAA;AACxB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,WAAsC;IAC/D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAU,YAAY,CAAC,CAAA;IACjE,SAAS,CACP,eAAe,CACb,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAC/E,UAAU,CACX,CACF,CAAA;IACD,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nifrajs/web-solid",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Solid render adapter for @nifrajs/web - SSR + hydration + the Solid Babel build plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -97,11 +97,12 @@
|
|
|
97
97
|
"dependencies": {
|
|
98
98
|
"@babel/core": "^7.26.0",
|
|
99
99
|
"@babel/preset-typescript": "^7.26.0",
|
|
100
|
-
"@nifrajs/core": "2.
|
|
101
|
-
"@nifrajs/i18n": "2.
|
|
102
|
-
"@nifrajs/image": "2.
|
|
103
|
-
"@nifrajs/web": "2.
|
|
104
|
-
"babel-preset-solid": "^1.9.3"
|
|
100
|
+
"@nifrajs/core": "2.11.0",
|
|
101
|
+
"@nifrajs/i18n": "2.11.0",
|
|
102
|
+
"@nifrajs/image": "2.11.0",
|
|
103
|
+
"@nifrajs/web": "2.11.0",
|
|
104
|
+
"babel-preset-solid": "^1.9.3",
|
|
105
|
+
"solid-refresh": "^0.7.8"
|
|
105
106
|
},
|
|
106
107
|
"peerDependencies": {
|
|
107
108
|
"@mdx-js/mdx": "^3",
|
package/src/client.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { MountRouterOptions, RenderProps } from "@nifrajs/web"
|
|
2
|
+
// `/client`, not the root: the root's graph carries the server, and Vite's dev server evaluates it
|
|
3
|
+
// instead of tree-shaking it - which broke hydration before the browser ran a line of app code.
|
|
4
|
+
import { searchOfChain } from "@nifrajs/web/client"
|
|
2
5
|
/**
|
|
3
6
|
* @nifrajs/web-solid/client - Solid client runtime. `hydrate` hydrates a single SSR'd route;
|
|
4
7
|
* `mountRouter` hydrates the initial route then drives navigation through a Solid signal - so a
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { transformAsync } from "@babel/core"
|
|
|
8
8
|
// @ts-expect-error - no type declarations published
|
|
9
9
|
import presetTypeScript from "@babel/preset-typescript"
|
|
10
10
|
import type { RenderAdapter } from "@nifrajs/web"
|
|
11
|
+
import { devServerCompile, rewriteSsrImports } from "@nifrajs/web/plugins/kit"
|
|
11
12
|
// @ts-expect-error - no type declarations published
|
|
12
13
|
import presetSolid from "babel-preset-solid"
|
|
13
14
|
import type { BunPlugin } from "bun"
|
|
@@ -17,6 +18,7 @@ import {
|
|
|
17
18
|
renderToString as solidRenderToString,
|
|
18
19
|
} from "solid-js/web"
|
|
19
20
|
import { compose } from "./compose.ts"
|
|
21
|
+
import solidRefreshBunHot, { SOLID_HOT_MODULE } from "./refresh-babel.ts"
|
|
20
22
|
|
|
21
23
|
const HYDRATION_HEAD = generateHydrationScript()
|
|
22
24
|
|
|
@@ -50,11 +52,16 @@ export const solidAdapter: RenderAdapter = {
|
|
|
50
52
|
* for the server, `"dom"` for the client, `hydratable` so SSR and hydrate align. Solid's
|
|
51
53
|
* reactive-JSX compiler ships only as a Babel plugin (no swc/native port); this runs at
|
|
52
54
|
* build time, on `.tsx` files only.
|
|
55
|
+
*
|
|
56
|
+
* Under a dev server the client half additionally runs `solid-refresh`, which is what makes an edit
|
|
57
|
+
* patch the running component tree instead of reloading the page - see {@link setupSolidRefresh}.
|
|
53
58
|
*/
|
|
54
59
|
export function solidBunPlugin(generate: "dom" | "ssr"): BunPlugin {
|
|
55
60
|
return {
|
|
56
61
|
name: `nifra-solid-${generate}`,
|
|
57
62
|
setup(build) {
|
|
63
|
+
const refresh =
|
|
64
|
+
generate === "dom" && devServerCompile() ? setupSolidRefresh(build) : undefined
|
|
58
65
|
// Match `.tsx`, tolerating a `?query` suffix (dev servers append one to bust Bun's import
|
|
59
66
|
// cache); strip it before reading the file off disk.
|
|
60
67
|
build.onLoad({ filter: /\.tsx(\?|$)/ }, async (args) => {
|
|
@@ -67,9 +74,56 @@ export function solidBunPlugin(generate: "dom" | "ssr"): BunPlugin {
|
|
|
67
74
|
[presetSolid, { generate, hydratable: true }],
|
|
68
75
|
[presetTypeScript, { onlyRemoveTypeImports: true }],
|
|
69
76
|
],
|
|
77
|
+
...(refresh !== undefined
|
|
78
|
+
? { plugins: [[await refresh.babel(), REFRESH_OPTIONS], solidRefreshBunHot] }
|
|
79
|
+
: {}),
|
|
70
80
|
})
|
|
71
|
-
return { contents: result?.code ?? "", loader: "js" }
|
|
81
|
+
return { contents: rewriteSsrImports(result?.code ?? "", path, generate), loader: "js" }
|
|
72
82
|
})
|
|
73
83
|
},
|
|
74
84
|
}
|
|
75
85
|
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* `"esm"` is the closest of `solid-refresh`'s bundler modes to what Bun implements: one
|
|
89
|
+
* `accept(mod => …)` per module, falling back to `invalidate()` when a component's signature changed too
|
|
90
|
+
* much to patch in place. `"vite"` differs only by also calling a bare `accept()` first, which would make
|
|
91
|
+
* every module self-accepting twice over. The call it emits is still Vite-shaped, and
|
|
92
|
+
* `solidRefreshBunHot` translates it.
|
|
93
|
+
*
|
|
94
|
+
* `jsx: false` turns OFF the pass that lifts a component's returned JSX into a second, nested component.
|
|
95
|
+
* That extra component is an extra hydration level on the client and none on the server, so with it on,
|
|
96
|
+
* every hydratable page dies on `Unable to find DOM nodes for hydration key` before a single edit. It buys
|
|
97
|
+
* finer-grained patching of markup-only edits; correct hydration is worth more.
|
|
98
|
+
*/
|
|
99
|
+
const REFRESH_OPTIONS = { bundler: "esm", jsx: false } as const
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Wire `solid-refresh` into a dev-server client compile.
|
|
103
|
+
*
|
|
104
|
+
* Solid components are compiled reactive closures, not functions re-run on render, so a new module
|
|
105
|
+
* version cannot simply replace the old one - `solid-refresh` wraps every component in a registry and, on
|
|
106
|
+
* an update, patches the live instances, keeping signal state. Without it the update finds no accepting
|
|
107
|
+
* module, bubbles up to the generated entry, and Bun reloads the whole page.
|
|
108
|
+
*
|
|
109
|
+
* The Babel half loads lazily: it is dev-only, and this module is the adapter root every Solid SSR
|
|
110
|
+
* server imports.
|
|
111
|
+
*
|
|
112
|
+
* Both runtime specifiers need pinning, because the transform emits them INTO the app's own files, where
|
|
113
|
+
* a bare specifier resolves against the app. `solid-refresh` is only a transitive dependency there and
|
|
114
|
+
* need not be hoisted; `nifra:solid-hot` is this package's own bridge module and has no app-side name at
|
|
115
|
+
* all. Resolving both here is what keeps the emitted imports working without an app depending on either.
|
|
116
|
+
*/
|
|
117
|
+
function setupSolidRefresh(build: Parameters<BunPlugin["setup"]>[0]): {
|
|
118
|
+
babel: () => Promise<unknown>
|
|
119
|
+
} {
|
|
120
|
+
const runtime = Bun.resolveSync("solid-refresh", import.meta.dir)
|
|
121
|
+
build.onResolve({ filter: /^solid-refresh$/ }, () => ({ path: runtime }))
|
|
122
|
+
// `.ts` from source (Bun takes the package's `bun` export condition), `.js` from the published build.
|
|
123
|
+
const bridge = `${import.meta.dir}/refresh-hot${import.meta.path.endsWith(".ts") ? ".ts" : ".js"}`
|
|
124
|
+
build.onResolve({ filter: new RegExp(`^${SOLID_HOT_MODULE}$`) }, () => ({ path: bridge }))
|
|
125
|
+
let babel: Promise<unknown> | undefined
|
|
126
|
+
return {
|
|
127
|
+
babel: () => (babel ??= import("solid-refresh/babel").then((m) => m.default)),
|
|
128
|
+
}
|
|
129
|
+
}
|
package/src/mdx.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { transformAsync } from "@babel/core"
|
|
10
10
|
// @ts-expect-error - no type declarations published
|
|
11
11
|
import presetTypeScript from "@babel/preset-typescript"
|
|
12
|
+
import { rewriteSsrImports } from "@nifrajs/web/plugins/kit"
|
|
12
13
|
// @ts-expect-error - no type declarations published
|
|
13
14
|
import presetSolid from "babel-preset-solid"
|
|
14
15
|
import type { BunPlugin } from "bun"
|
|
@@ -53,7 +54,7 @@ export function solidMdxBunPlugin(generate: "dom" | "ssr"): BunPlugin {
|
|
|
53
54
|
babelrc: false,
|
|
54
55
|
configFile: false,
|
|
55
56
|
})
|
|
56
|
-
return { contents: result?.code ?? "", loader: "js" }
|
|
57
|
+
return { contents: rewriteSsrImports(result?.code ?? "", path, generate), loader: "js" }
|
|
57
58
|
})
|
|
58
59
|
},
|
|
59
60
|
}
|
package/src/query.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { QueryClient, QueryState } from "@nifrajs/web"
|
|
2
|
+
// `/client`, not the root - these are DOM values, and the root's graph carries the
|
|
3
|
+
// server, which Vite's dev server evaluates rather than tree-shakes.
|
|
4
|
+
import { createQueryClient } from "@nifrajs/web/client"
|
|
2
5
|
/**
|
|
3
6
|
* `@nifrajs/web-solid/query` - Solid bindings for the keyed query-cache. `createQuery(key, fn)` bridges a
|
|
4
7
|
* query's `subscribe`/`snapshot` store into a Solid signal and fetches on mount; `useQueryClient`
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Babel pass that runs AFTER `solid-refresh` and rewrites the one call it emits into the dialect
|
|
3
|
+
* Bun's dev server speaks. Dev-server client compiles only (`solidBunPlugin("dom")`).
|
|
4
|
+
*
|
|
5
|
+
* `solid-refresh` ends every component module with
|
|
6
|
+
*
|
|
7
|
+
* if (import.meta.hot) { _$$refresh("esm", import.meta.hot, _REGISTRY) }
|
|
8
|
+
*
|
|
9
|
+
* which is a Vite assumption: that `import.meta.hot` is an object you can pass around. Bun's bundler
|
|
10
|
+
* instead rewrites `import.meta.hot.<prop>` where it can see it and substitutes, for every other use, a
|
|
11
|
+
* proxy that throws `import.meta.hot.<prop> cannot be used indirectly` on the first property read. So the
|
|
12
|
+
* argument has to become something built from member accesses Bun CAN see, and the rest of the
|
|
13
|
+
* adaptation moves into `./refresh-hot` (which also supplies the cross-version store and the reload that
|
|
14
|
+
* stands in for Bun's unimplemented `invalidate`):
|
|
15
|
+
*
|
|
16
|
+
* if (import.meta.hot) { _ref(import.meta.url, (cb) => import.meta.hot.accept(cb), _REGISTRY) }
|
|
17
|
+
*
|
|
18
|
+
* Rewriting rather than string-replacing matters: the identifier `solid-refresh` picks is uniquified
|
|
19
|
+
* against the module's own scope, so it is not a fixed string, and a silent miss would leave a module
|
|
20
|
+
* that throws on load.
|
|
21
|
+
*/
|
|
22
|
+
import type { BabelFile, types as BabelTypes, NodePath, PluginObj, PluginPass } from "@babel/core"
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The virtual specifier for `./refresh-hot`, resolved by `solidBunPlugin` against THIS package. The
|
|
26
|
+
* import lands in an app's own file, where a relative path would be wrong and a bare `@nifrajs/web-solid`
|
|
27
|
+
* subpath would depend on how the app's install happens to be laid out.
|
|
28
|
+
*/
|
|
29
|
+
export const SOLID_HOT_MODULE = "nifra:solid-hot"
|
|
30
|
+
|
|
31
|
+
/** `solid-refresh`'s call, under whatever uid Babel gave the import in this module's scope. */
|
|
32
|
+
const REFRESH_CALLEE = /^_*\$\$refresh\d*$/
|
|
33
|
+
|
|
34
|
+
/** Per-file memo of the injected `refresh` import, so a module with many components imports it once. */
|
|
35
|
+
const injected = new WeakMap<PluginPass, BabelTypes.Identifier>()
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* `import.meta`, in either of the two shapes it can arrive in: the `MetaProperty` a parser produces, and
|
|
39
|
+
* the plain `import` . `meta` member expression `solid-refresh` hand-builds. Matching only the former is
|
|
40
|
+
* what a first cut gets wrong - the emitted call reads `import.meta.hot` but is not a `MetaProperty`.
|
|
41
|
+
*/
|
|
42
|
+
const isImportMeta = (t: typeof BabelTypes, node: BabelTypes.Node): boolean =>
|
|
43
|
+
(t.isMetaProperty(node) && node.meta.name === "import" && node.property.name === "meta") ||
|
|
44
|
+
(t.isMemberExpression(node) &&
|
|
45
|
+
!node.computed &&
|
|
46
|
+
t.isIdentifier(node.object, { name: "import" }) &&
|
|
47
|
+
t.isIdentifier(node.property, { name: "meta" }))
|
|
48
|
+
|
|
49
|
+
/** `import.meta.hot` exactly - the argument this pass replaces. */
|
|
50
|
+
const isImportMetaHot = (t: typeof BabelTypes, node: BabelTypes.Node): boolean =>
|
|
51
|
+
t.isMemberExpression(node) &&
|
|
52
|
+
!node.computed &&
|
|
53
|
+
isImportMeta(t, node.object) &&
|
|
54
|
+
t.isIdentifier(node.property) &&
|
|
55
|
+
node.property.name === "hot"
|
|
56
|
+
|
|
57
|
+
const importMetaMember = (t: typeof BabelTypes, property: string): BabelTypes.MemberExpression =>
|
|
58
|
+
t.memberExpression(
|
|
59
|
+
t.metaProperty(t.identifier("import"), t.identifier("meta")),
|
|
60
|
+
t.identifier(property),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
/** `(cb) => import.meta.hot.accept(cb)` - `accept` reached the only way Bun's bundler recognizes. */
|
|
64
|
+
function acceptClosure(t: typeof BabelTypes): BabelTypes.ArrowFunctionExpression {
|
|
65
|
+
const callback = t.identifier("cb")
|
|
66
|
+
return t.arrowFunctionExpression(
|
|
67
|
+
[callback],
|
|
68
|
+
t.callExpression(t.memberExpression(importMetaMember(t, "hot"), t.identifier("accept")), [
|
|
69
|
+
callback,
|
|
70
|
+
]),
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function refreshImport(
|
|
75
|
+
t: typeof BabelTypes,
|
|
76
|
+
path: NodePath<BabelTypes.CallExpression>,
|
|
77
|
+
state: PluginPass,
|
|
78
|
+
): BabelTypes.Identifier {
|
|
79
|
+
const existing = injected.get(state)
|
|
80
|
+
if (existing !== undefined) return existing
|
|
81
|
+
const program = path.scope.getProgramParent().path as NodePath<BabelTypes.Program>
|
|
82
|
+
const local = program.scope.generateUidIdentifier("nifraSolidRefresh")
|
|
83
|
+
program.node.body.unshift(
|
|
84
|
+
t.importDeclaration(
|
|
85
|
+
[t.importSpecifier(local, t.identifier("refresh"))],
|
|
86
|
+
t.stringLiteral(SOLID_HOT_MODULE),
|
|
87
|
+
),
|
|
88
|
+
)
|
|
89
|
+
injected.set(state, local)
|
|
90
|
+
return local
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default function solidRefreshBunHot({
|
|
94
|
+
types: t,
|
|
95
|
+
}: {
|
|
96
|
+
types: typeof BabelTypes
|
|
97
|
+
}): PluginObj<PluginPass> {
|
|
98
|
+
return {
|
|
99
|
+
name: "nifra-solid-refresh-bun-hot",
|
|
100
|
+
// Required by the plugin shape, and deliberately empty - see `post` below.
|
|
101
|
+
visitor: {},
|
|
102
|
+
// No visitor entries at all: the call this pass rewrites does not exist during the shared traversal.
|
|
103
|
+
// `solid-refresh` appends it with `pushContainer` from its own `Program` handler, and nodes added
|
|
104
|
+
// that way are never handed to the other plugins' visitors. `Program.exit` is no better - exit
|
|
105
|
+
// handlers fire in plugin order, so this one would run BEFORE the append. `post` runs once the
|
|
106
|
+
// file's whole traversal is finished, which is the first point at which the call is there to see.
|
|
107
|
+
post(this: PluginPass, file: BabelFile) {
|
|
108
|
+
const state = this
|
|
109
|
+
file.path.traverse({
|
|
110
|
+
CallExpression(path) {
|
|
111
|
+
const callee = path.node.callee
|
|
112
|
+
if (!t.isIdentifier(callee) || !REFRESH_CALLEE.test(callee.name)) return
|
|
113
|
+
const args = path.node.arguments
|
|
114
|
+
// ("esm", import.meta.hot, registry) - anything else is not the call this pass is for.
|
|
115
|
+
if (args.length !== 3) return
|
|
116
|
+
const hot = args[1]
|
|
117
|
+
const registry = args[2]
|
|
118
|
+
if (hot === undefined || registry === undefined || !isImportMetaHot(t, hot)) return
|
|
119
|
+
if (!t.isExpression(registry)) return
|
|
120
|
+
// The replacement's callee is the injected uid, which REFRESH_CALLEE never matches, so the
|
|
121
|
+
// re-traversal `replaceWith` triggers terminates here.
|
|
122
|
+
path.replaceWith(
|
|
123
|
+
t.callExpression(refreshImport(t, path, state), [
|
|
124
|
+
importMetaMember(t, "url"),
|
|
125
|
+
acceptClosure(t),
|
|
126
|
+
registry,
|
|
127
|
+
]),
|
|
128
|
+
)
|
|
129
|
+
},
|
|
130
|
+
})
|
|
131
|
+
},
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `solid-refresh` ↔ Bun-dev-server bridge, client-side. Loaded only by a dev-server client bundle
|
|
3
|
+
* (`solidBunPlugin("dom")` resolves the `nifra:solid-hot` specifier its Babel pass emits); never part of
|
|
4
|
+
* `nifra build` output.
|
|
5
|
+
*
|
|
6
|
+
* `solid-refresh` expects a Vite-shaped `import.meta.hot` handed to it as a VALUE. Bun does not have one:
|
|
7
|
+
* it rewrites `import.meta.hot.<prop>` at bundle time and substitutes a proxy that throws
|
|
8
|
+
* (`import.meta.hot.<prop> cannot be used indirectly`) for every other use - so passing the object to a
|
|
9
|
+
* library function fails on the first property read, whichever property it is. This module supplies the
|
|
10
|
+
* value-shaped object instead, built from direct member accesses the plugin emits at the call site.
|
|
11
|
+
*
|
|
12
|
+
* Two of the three pieces need more than a pass-through:
|
|
13
|
+
*
|
|
14
|
+
* - `data` is where `solid-refresh` keeps the previous version's component registry, so it has to be the
|
|
15
|
+
* SAME object across every version of a module. Bun's own `data` is a field on a per-version module
|
|
16
|
+
* record, so it is not usable for that; the store below is keyed by module URL and lives in this
|
|
17
|
+
* module, which no edit invalidates.
|
|
18
|
+
* - `invalidate` is not implemented in Bun's HMR runtime (it throws). It is the escape hatch
|
|
19
|
+
* `solid-refresh` takes when a component's shape changed too much to patch in place, and a full reload
|
|
20
|
+
* is exactly the right answer there - so that is what it does.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { $$refresh } from "solid-refresh"
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Registry store per module URL - see the note above on why Bun's own `hot.data` cannot serve.
|
|
27
|
+
*
|
|
28
|
+
* On `globalThis`, not in module scope: Bun re-evaluates an updated module's imports along with it, so
|
|
29
|
+
* this very module is re-instantiated during an update and a module-scoped Map would come back empty
|
|
30
|
+
* halfway through. The symptom of getting that wrong is not a lost registry but an infinite one -
|
|
31
|
+
* `patchRegistry` then compares a registry against itself, points a component's signal at its own proxy,
|
|
32
|
+
* and the next render recurses until the stack blows.
|
|
33
|
+
*/
|
|
34
|
+
const STORES = Symbol.for("nifra.solid-refresh.stores")
|
|
35
|
+
|
|
36
|
+
type StoreHost = typeof globalThis & {
|
|
37
|
+
[STORES]?: Map<string, Record<string, unknown>>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function store(moduleUrl: string): Record<string, unknown> {
|
|
41
|
+
const host = globalThis as StoreHost
|
|
42
|
+
host[STORES] ??= new Map<string, Record<string, unknown>>()
|
|
43
|
+
const stores = host[STORES]
|
|
44
|
+
let data = stores.get(moduleUrl)
|
|
45
|
+
if (data === undefined) {
|
|
46
|
+
data = {}
|
|
47
|
+
stores.set(moduleUrl, data)
|
|
48
|
+
}
|
|
49
|
+
return data
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The subset of `solid-refresh`'s hot interface its `"esm"` bundler mode actually touches. */
|
|
53
|
+
interface SolidHot {
|
|
54
|
+
readonly data: Record<string, unknown>
|
|
55
|
+
accept(callback: (module: unknown) => void): void
|
|
56
|
+
invalidate(): void
|
|
57
|
+
decline(): void
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Run `solid-refresh`'s update handshake for one module.
|
|
62
|
+
*
|
|
63
|
+
* `moduleUrl` identifies the module across versions; `accept` is a closure the plugin emits around
|
|
64
|
+
* `import.meta.hot.accept`, which is the only form Bun's bundler will rewrite. `registry` is the
|
|
65
|
+
* component registry this version of the module built.
|
|
66
|
+
*/
|
|
67
|
+
export function refresh(
|
|
68
|
+
moduleUrl: string,
|
|
69
|
+
accept: (callback: (module: unknown) => void) => void,
|
|
70
|
+
registry: unknown,
|
|
71
|
+
): void {
|
|
72
|
+
const reload = (): void => {
|
|
73
|
+
location.reload()
|
|
74
|
+
}
|
|
75
|
+
const hot: SolidHot = { data: store(moduleUrl), accept, invalidate: reload, decline: reload }
|
|
76
|
+
// `$$refresh`'s published signature is a discriminated tuple over every bundler mode it supports, so
|
|
77
|
+
// the "esm" arm cannot be selected by a cast on the hot object alone. The mode string and the shape
|
|
78
|
+
// above are what pin it; the call itself is what has to be re-typed.
|
|
79
|
+
const esmRefresh = $$refresh as unknown as (mode: "esm", hot: SolidHot, registry: unknown) => void
|
|
80
|
+
esmRefresh("esm", hot, registry)
|
|
81
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import type { InferOutput, StandardSchemaV1 } from "@nifrajs/core/server"
|
|
2
|
+
// `import type` + a local re-export, NOT `export type { … } from "@nifrajs/web"`: that form leaves a
|
|
3
|
+
// bare `import "@nifrajs/web"` in the output, which pulls the server graph into the browser under
|
|
4
|
+
// Vite's dev server. Sourced from the ROOT so the generated `RouteSearch` augmentation applies.
|
|
5
|
+
import type {
|
|
6
|
+
Blocker,
|
|
7
|
+
BlockerFunction,
|
|
8
|
+
BlockerState,
|
|
9
|
+
NavigateFunction,
|
|
10
|
+
NavigateOptions,
|
|
11
|
+
NavigateTargetInput,
|
|
12
|
+
} from "@nifrajs/web"
|
|
13
|
+
// `/client`, not the root - these are DOM values, and the root's graph carries the
|
|
14
|
+
// server, which Vite's dev server evaluates rather than tree-shakes.
|
|
2
15
|
import {
|
|
3
|
-
type Blocker,
|
|
4
|
-
type BlockerFunction,
|
|
5
16
|
getBrowserNavigate,
|
|
6
17
|
IDLE_BLOCKER,
|
|
7
|
-
type NavigateFunction,
|
|
8
|
-
type NavigateOptions,
|
|
9
|
-
type NavigateTargetInput,
|
|
10
18
|
registerBlocker,
|
|
11
19
|
resolveNavigate,
|
|
12
|
-
} from "@nifrajs/web"
|
|
20
|
+
} from "@nifrajs/web/client"
|
|
13
21
|
/**
|
|
14
22
|
* `@nifrajs/web-solid/router` - Solid routing bindings over the agnostic `@nifrajs/web` history layer:
|
|
15
23
|
* `useNavigate` (programmatic navigation), `useBlocker` (the unsaved-changes guard), and `useSearch`
|
|
@@ -26,7 +34,7 @@ import {
|
|
|
26
34
|
useContext,
|
|
27
35
|
} from "solid-js"
|
|
28
36
|
|
|
29
|
-
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction }
|
|
37
|
+
export type { Blocker, BlockerFunction, BlockerState, NavigateFunction }
|
|
30
38
|
|
|
31
39
|
// Frozen empty search + a stable accessor for a `useSearch` used outside a nifra route tree.
|
|
32
40
|
const EMPTY_SEARCH: Readonly<Record<string, unknown>> = Object.freeze({})
|