@nifrajs/web-solid 2.10.0 → 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 CHANGED
@@ -1,4 +1,4 @@
1
- import { type MountRouterOptions, type RenderProps } from "@nifrajs/web";
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;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,WAAW,EAAiB,MAAM,cAAc,CAAA;AAgBvF,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"}
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
- import { searchOfChain } from "@nifrajs/web";
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
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
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
@@ -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;AAGjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AAUpC,6EAA6E;AAC7E,eAAO,MAAM,YAAY,EAAE,aAsB1B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAqBjE"}
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;AAEtC,MAAM,cAAc,GAAG,uBAAuB,EAAE,CAAA;AAEhD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,gGAAgG;IAChG,mFAAmF;IACnF,4FAA4F;IAC5F,iGAAiG;IACjG,kEAAkE;IAClE,cAAc,CAAC,KAAK,EAAE,KAAK;QACzB,OAAO,mBAAmB,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IACnD,CAAC;IACD,cAAc,CAAC,KAAK,EAAE,KAAK;QACzB,uFAAuF;QACvF,2FAA2F;QAC3F,6FAA6F;QAC7F,4FAA4F;QAC5F,iCAAiC;QACjC,MAAM,EAAE,GAAG,IAAI,eAAe,EAA0B,CAAA;QACxD,mBAAmB,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAA;QAC9D,OAAO,EAAE,CAAC,QAAQ,CAAA;IACpB,CAAC;IACD,aAAa;QACX,OAAO,cAAc,CAAA;IACvB,CAAC;CACF,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAuB;IACpD,OAAO;QACL,IAAI,EAAE,eAAe,QAAQ,EAAE;QAC/B,KAAK,CAAC,KAAK;YACT,0FAA0F;YAC1F,qDAAqD;YACrD,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,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;gBAC1C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE;oBAC1C,QAAQ,EAAE,IAAI;oBACd,+EAA+E;oBAC/E,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;iBACF,CAAC,CAAA;gBACF,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;YACvD,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
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":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAA;AASpC;sEACsE;AACtE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAmCpE"}
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;YACvD,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC"}
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 { type QueryClient, type QueryState } from "@nifrajs/web";
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`
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AACnF;;;;;;;;;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"}
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
- import { createQueryClient } from "@nifrajs/web";
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":"AAAA,OAAO,EAAE,iBAAiB,EAAqC,MAAM,cAAc,CAAA;AACnF;;;;;;;;;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"}
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":"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"}
@@ -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 { type Blocker, type BlockerFunction, type NavigateFunction } from "@nifrajs/web";
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 } from "@nifrajs/web";
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
@@ -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;AACzE,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,eAAe,EAGpB,KAAK,gBAAgB,EAKtB,MAAM,cAAc,CAAA;AACrB;;;;;;GAMG;AACH,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,OAAO,EAKb,MAAM,UAAU,CAAA;AAEjB,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAiB5F,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"}
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
- import { getBrowserNavigate, IDLE_BLOCKER, registerBlocker, resolveNavigate, } from "@nifrajs/web";
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`
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,kBAAkB,EAClB,YAAY,EAIZ,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAA;AACrB;;;;;;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"}
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.10.0",
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.10.0",
101
- "@nifrajs/i18n": "2.10.0",
102
- "@nifrajs/image": "2.10.0",
103
- "@nifrajs/web": "2.10.0",
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 { type MountRouterOptions, type RenderProps, searchOfChain } from "@nifrajs/web"
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 { createQueryClient, type QueryClient, type QueryState } from "@nifrajs/web"
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 } from "@nifrajs/web"
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({})