@nisli/core 0.50.0 → 0.51.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/hmr/registry.d.ts +2 -2
- package/dist/hmr/registry.js +3 -3
- package/dist/hmr/transform.d.ts +1 -1
- package/dist/hmr/transform.js +1 -1
- package/dist/vite-hmr/plugin.js +1 -1
- package/dist/vite-hmr/runtime.d.ts +1 -1
- package/dist/vite-hmr/runtime.js +1 -1
- package/package.json +2 -23
- package/dist/esbuild-hmr/plugin.d.ts +0 -154
- package/dist/esbuild-hmr/plugin.js +0 -183
- package/dist/esbuild-hmr/plugin.js.map +0 -1
- package/dist/esbuild-hmr/runtime.d.ts +0 -86
- package/dist/esbuild-hmr/runtime.js +0 -163
- package/dist/esbuild-hmr/runtime.js.map +0 -1
- package/dist/esbuild-hmr/server.d.ts +0 -51
- package/dist/esbuild-hmr/server.js +0 -87
- package/dist/esbuild-hmr/server.js.map +0 -1
package/dist/hmr/registry.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The tag→setup registry, the stable indirection thunk, and the in-place
|
|
5
5
|
* re-mount through the custom-element lifecycle. This is the part that is
|
|
6
|
-
* IDENTICAL regardless of how change notifications arrive —
|
|
6
|
+
* IDENTICAL regardless of how change notifications arrive — change
|
|
7
7
|
* (`../esbuild-hmr/*`) or Vite `import.meta.hot` (`../vite-hmr/*`) both drive
|
|
8
8
|
* the same registry. Keeping it here means one implementation, one set of
|
|
9
9
|
* correctness guarantees (ADR 0008.1 disposal), and no duplication.
|
|
@@ -17,7 +17,7 @@ export type HmrSetup = (props: unknown, host: HTMLElement) => unknown;
|
|
|
17
17
|
* Begin a caller-owned drain window: suppress auto-scheduling AND cancel any
|
|
18
18
|
* pending microtask drain, so the caller can re-evaluate a whole bundle and
|
|
19
19
|
* register ALL changed tags before a single explicit `drainRemounts()`. Used by
|
|
20
|
-
* the
|
|
20
|
+
* the Vite path drains per-module.
|
|
21
21
|
*/
|
|
22
22
|
export declare function beginManualDrain(): void;
|
|
23
23
|
/** End a caller-owned drain window (re-enable auto-scheduling). */
|
package/dist/hmr/registry.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The tag→setup registry, the stable indirection thunk, and the in-place
|
|
5
5
|
* re-mount through the custom-element lifecycle. This is the part that is
|
|
6
|
-
* IDENTICAL regardless of how change notifications arrive —
|
|
6
|
+
* IDENTICAL regardless of how change notifications arrive — change
|
|
7
7
|
* (`../esbuild-hmr/*`) or Vite `import.meta.hot` (`../vite-hmr/*`) both drive
|
|
8
8
|
* the same registry. Keeping it here means one implementation, one set of
|
|
9
9
|
* correctness guarantees (ADR 0008.1 disposal), and no duplication.
|
|
@@ -19,7 +19,7 @@ let remountScheduled = false;
|
|
|
19
19
|
/**
|
|
20
20
|
* When true, `__register` accumulates pending tags but does NOT auto-schedule a
|
|
21
21
|
* microtask drain — the caller owns the drain so it can wait for a full module
|
|
22
|
-
* re-eval to register ALL changed tags first
|
|
22
|
+
* re-eval to register ALL changed tags first.
|
|
23
23
|
* The Vite path leaves this false and drains explicitly from its accept hook.
|
|
24
24
|
*/
|
|
25
25
|
let suppressAutoDrain = false;
|
|
@@ -27,7 +27,7 @@ let suppressAutoDrain = false;
|
|
|
27
27
|
* Begin a caller-owned drain window: suppress auto-scheduling AND cancel any
|
|
28
28
|
* pending microtask drain, so the caller can re-evaluate a whole bundle and
|
|
29
29
|
* register ALL changed tags before a single explicit `drainRemounts()`. Used by
|
|
30
|
-
* the
|
|
30
|
+
* the Vite path drains per-module.
|
|
31
31
|
*/
|
|
32
32
|
export function beginManualDrain() {
|
|
33
33
|
suppressAutoDrain = true;
|
package/dist/hmr/transform.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Wraps the `component` a module imports from `@nisli/core` with the registry
|
|
5
5
|
* indirection so a rebuilt module's `component()` calls re-register their setup
|
|
6
6
|
* and trigger an in-place re-mount. Transport-agnostic and pure — used by both
|
|
7
|
-
* the
|
|
7
|
+
* the Vite `transform` hook.
|
|
8
8
|
*/
|
|
9
9
|
/**
|
|
10
10
|
* Rewrite a module's source so the `component` it imports from `coreSpecifier`
|
package/dist/hmr/transform.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Wraps the `component` a module imports from `@nisli/core` with the registry
|
|
5
5
|
* indirection so a rebuilt module's `component()` calls re-register their setup
|
|
6
6
|
* and trigger an in-place re-mount. Transport-agnostic and pure — used by both
|
|
7
|
-
* the
|
|
7
|
+
* the Vite `transform` hook.
|
|
8
8
|
*/
|
|
9
9
|
function escapeRegExp(s) {
|
|
10
10
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
package/dist/vite-hmr/plugin.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* vite-hmr/plugin.ts — Dev-only Vite plugin for Nisli HMR (ADR 0110).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Vite plugin that wraps component() calls (shared `transformSource`),
|
|
5
5
|
* but drives re-mount through Vite's native `import.meta.hot` instead of an SSE
|
|
6
6
|
* hub + whole-bundle re-import. For each source module that imports `component`
|
|
7
7
|
* from `@nisli/core`, it:
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - `__drain()` is called from the module's `import.meta.hot.accept` hook to
|
|
9
9
|
* apply the queued re-mounts.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Vite re-evaluates ONLY the changed module against a
|
|
12
12
|
* STABLE framework module — so there is exactly one `@nisli/core` instance and
|
|
13
13
|
* no lifecycle/reactive split-brain. This module just re-exports the
|
|
14
14
|
* transport-agnostic registry core.
|
package/dist/vite-hmr/runtime.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - `__drain()` is called from the module's `import.meta.hot.accept` hook to
|
|
9
9
|
* apply the queued re-mounts.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* Vite re-evaluates ONLY the changed module against a
|
|
12
12
|
* STABLE framework module — so there is exactly one `@nisli/core` instance and
|
|
13
13
|
* no lifecycle/reactive split-brain. This module just re-exports the
|
|
14
14
|
* transport-agnostic registry core.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nisli/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "A reactive web component framework. Signals, templates, dependency injection — no build step, no virtual DOM, no dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,18 +22,6 @@
|
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
23
|
"default": "./dist/index.js"
|
|
24
24
|
},
|
|
25
|
-
"./esbuild-hmr": {
|
|
26
|
-
"types": "./dist/esbuild-hmr/plugin.d.ts",
|
|
27
|
-
"default": "./dist/esbuild-hmr/plugin.js"
|
|
28
|
-
},
|
|
29
|
-
"./esbuild-hmr/runtime": {
|
|
30
|
-
"types": "./dist/esbuild-hmr/runtime.d.ts",
|
|
31
|
-
"default": "./dist/esbuild-hmr/runtime.js"
|
|
32
|
-
},
|
|
33
|
-
"./esbuild-hmr/server": {
|
|
34
|
-
"types": "./dist/esbuild-hmr/server.d.ts",
|
|
35
|
-
"default": "./dist/esbuild-hmr/server.js"
|
|
36
|
-
},
|
|
37
25
|
"./vite-hmr": {
|
|
38
26
|
"types": "./dist/vite-hmr/plugin.d.ts",
|
|
39
27
|
"default": "./dist/vite-hmr/plugin.js"
|
|
@@ -43,17 +31,8 @@
|
|
|
43
31
|
"default": "./dist/vite-hmr/runtime.js"
|
|
44
32
|
}
|
|
45
33
|
},
|
|
46
|
-
"peerDependencies": {
|
|
47
|
-
"esbuild": "*"
|
|
48
|
-
},
|
|
49
|
-
"peerDependenciesMeta": {
|
|
50
|
-
"esbuild": {
|
|
51
|
-
"optional": true
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
34
|
"devDependencies": {
|
|
55
|
-
"@types/node": "^22.0.0"
|
|
56
|
-
"esbuild": "^0.28.1"
|
|
35
|
+
"@types/node": "^22.0.0"
|
|
57
36
|
},
|
|
58
37
|
"files": [
|
|
59
38
|
"dist",
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* esbuild-hmr/plugin.ts — Dev-only esbuild plugin for Nisli component HMR.
|
|
3
|
-
*
|
|
4
|
-
* DEV-ONLY, build-time (Node). Reachable only via `@nisli/core/esbuild-hmr`,
|
|
5
|
-
* never from the runtime `.` entry (ADR 0021, Ruling 1). It is added to the
|
|
6
|
-
* esbuild plugin list ONLY on the `--watch` path; `pnpm build` (no watch) never
|
|
7
|
-
* sees it, so prod is byte-identical by construction (Ruling 5).
|
|
8
|
-
*
|
|
9
|
-
* `esbuild` is an OPTIONAL peerDependency. To keep `@nisli/core` dependency-free
|
|
10
|
-
* we do NOT `import` esbuild here — we type the plugin against a minimal local
|
|
11
|
-
* structural surface. The host build script supplies the real esbuild.
|
|
12
|
-
*
|
|
13
|
-
* What it does:
|
|
14
|
-
* 1. onLoad (Ruling 2): for author modules that import `component` from
|
|
15
|
-
* `@nisli/core`, rewrite the import so `component(tag, setup, opts)` routes
|
|
16
|
-
* `setup` through the runtime tag-keyed registry's STABLE indirection thunk.
|
|
17
|
-
* The real `FrameworkComponent` thus captures a thunk that always reads the
|
|
18
|
-
* current setup — no class swap, no tag re-definition.
|
|
19
|
-
* 2. onEnd (Ruling 4 transport): diff the metafile outputs against the previous
|
|
20
|
-
* build and broadcast a `change` payload ({added, removed, updated}) over
|
|
21
|
-
* SSE so the browser client can escalate (css/js/reload).
|
|
22
|
-
* 3. Inject the browser dev client (`@nisli/core/esbuild-hmr/runtime` +
|
|
23
|
-
* `connect({ path })`) via esbuild's `inject` option pointed at a VIRTUAL
|
|
24
|
-
* shim module, so the runtime is RESOLVED + BUNDLED into the output (no
|
|
25
|
-
* author HTML/JS change needed). We deliberately do NOT use `banner`: a
|
|
26
|
-
* banner is raw passthrough text that esbuild neither resolves nor bundles,
|
|
27
|
-
* so a bare `import … from "@nisli/core/esbuild-hmr/runtime"` would leak
|
|
28
|
-
* verbatim into the output and the browser would throw
|
|
29
|
-
* `Failed to resolve module specifier` (no import map). `inject` runs the
|
|
30
|
-
* shim through onResolve/onLoad so the runtime is inlined at build time, and
|
|
31
|
-
* esbuild applies `inject` ONLY to JS modules — never to file/copy-loaded
|
|
32
|
-
* entries (e.g. the viewer's `logo.svg`). Verified empirically against
|
|
33
|
-
* esbuild 0.28.1.
|
|
34
|
-
*/
|
|
35
|
-
import type { ChangeBroadcaster } from './server.js';
|
|
36
|
-
/** A subset of esbuild's `OnLoadArgs` we rely on. */
|
|
37
|
-
interface OnLoadArgs {
|
|
38
|
-
path: string;
|
|
39
|
-
}
|
|
40
|
-
/** A subset of esbuild's `OnLoadResult`. */
|
|
41
|
-
interface OnLoadResult {
|
|
42
|
-
contents: string;
|
|
43
|
-
loader?: 'ts' | 'tsx' | 'js' | 'jsx';
|
|
44
|
-
/** Directory used to resolve imports from a virtual module (the client shim). */
|
|
45
|
-
resolveDir?: string;
|
|
46
|
-
}
|
|
47
|
-
/** A subset of esbuild's `OnResolveArgs`. */
|
|
48
|
-
interface OnResolveArgs {
|
|
49
|
-
path: string;
|
|
50
|
-
}
|
|
51
|
-
/** A subset of esbuild's `OnResolveResult`. */
|
|
52
|
-
interface OnResolveResult {
|
|
53
|
-
path: string;
|
|
54
|
-
namespace?: string;
|
|
55
|
-
}
|
|
56
|
-
/** A subset of esbuild's metafile. */
|
|
57
|
-
interface Metafile {
|
|
58
|
-
outputs: Record<string, {
|
|
59
|
-
bytes: number;
|
|
60
|
-
hash?: string;
|
|
61
|
-
}>;
|
|
62
|
-
}
|
|
63
|
-
/** A subset of esbuild's `BuildResult`. */
|
|
64
|
-
interface BuildResult {
|
|
65
|
-
metafile?: Metafile;
|
|
66
|
-
}
|
|
67
|
-
/** The hooks surface of esbuild's `PluginBuild` we use. */
|
|
68
|
-
interface PluginBuild {
|
|
69
|
-
initialOptions: {
|
|
70
|
-
banner?: {
|
|
71
|
-
js?: string;
|
|
72
|
-
} & Record<string, string | undefined>;
|
|
73
|
-
/** Files esbuild injects into every JS module (never file/copy entries). */
|
|
74
|
-
inject?: string[];
|
|
75
|
-
/** esbuild's working directory; anchors virtual-module resolution. */
|
|
76
|
-
absWorkingDir?: string;
|
|
77
|
-
[key: string]: unknown;
|
|
78
|
-
};
|
|
79
|
-
onResolve(options: {
|
|
80
|
-
filter: RegExp;
|
|
81
|
-
namespace?: string;
|
|
82
|
-
}, callback: (args: OnResolveArgs) => OnResolveResult | undefined): void;
|
|
83
|
-
onLoad(options: {
|
|
84
|
-
filter: RegExp;
|
|
85
|
-
namespace?: string;
|
|
86
|
-
}, callback: (args: OnLoadArgs) => OnLoadResult | undefined): void;
|
|
87
|
-
onEnd(callback: (result: BuildResult) => void): void;
|
|
88
|
-
}
|
|
89
|
-
/** esbuild's `Plugin` shape (structural). */
|
|
90
|
-
export interface EsbuildPlugin {
|
|
91
|
-
name: string;
|
|
92
|
-
setup(build: PluginBuild): void;
|
|
93
|
-
}
|
|
94
|
-
export interface NisliHmrPluginOptions {
|
|
95
|
-
/**
|
|
96
|
-
* Broadcaster used to push `change` events to connected clients. Supply the
|
|
97
|
-
* one returned by `createHmrServer()` (server.ts), or any object with a
|
|
98
|
-
* `broadcast(payload)` method (e.g. an esbuild `serve` adapter).
|
|
99
|
-
*/
|
|
100
|
-
broadcaster: ChangeBroadcaster;
|
|
101
|
-
/**
|
|
102
|
-
* The module specifier author code imports `component` from.
|
|
103
|
-
* Defaults to `@nisli/core`.
|
|
104
|
-
*/
|
|
105
|
-
coreSpecifier?: string;
|
|
106
|
-
/**
|
|
107
|
-
* The specifier of the browser dev runtime, inlined into the bundle via the
|
|
108
|
-
* injected client shim. Defaults to `@nisli/core/esbuild-hmr/runtime`.
|
|
109
|
-
*/
|
|
110
|
-
runtimeSpecifier?: string;
|
|
111
|
-
/**
|
|
112
|
-
* The SSE endpoint the browser dev client connects to. Baked into the injected
|
|
113
|
-
* shim as `connect({ path: clientUrl })`. Defaults to `/esbuild` (esbuild's
|
|
114
|
-
* client convention, same-origin).
|
|
115
|
-
*
|
|
116
|
-
* Set this to an ABSOLUTE URL when the SSE hub (server.ts) runs on a different
|
|
117
|
-
* origin than the page server — e.g. `http://localhost:3031/esbuild` when the
|
|
118
|
-
* hub listens on :3031 and the page is served by Hono on :3040. The hub already
|
|
119
|
-
* sends `Access-Control-Allow-Origin: '*'`, so cross-origin SSE works.
|
|
120
|
-
*/
|
|
121
|
-
clientUrl?: string;
|
|
122
|
-
/** Files to transform. Defaults to TS/JS sources (excludes node_modules). */
|
|
123
|
-
filter?: RegExp;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* `transformSource` (wrap `component()` call sites) now lives in the shared
|
|
127
|
-
* `../hmr/transform.js` and is re-exported here so this module's surface — and
|
|
128
|
-
* the tests that import it from './plugin.js' — are unchanged (ADR 0110).
|
|
129
|
-
*/
|
|
130
|
-
import { transformSource } from '../hmr/transform.js';
|
|
131
|
-
export { transformSource };
|
|
132
|
-
/**
|
|
133
|
-
* Source of the virtual client shim that esbuild's `inject` pulls into every JS
|
|
134
|
-
* module. Because it is `inject`ed (not a `banner`), esbuild RESOLVES the
|
|
135
|
-
* `runtimeSpecifier` import and BUNDLES `connect` inline — no bare specifier
|
|
136
|
-
* survives in the output (the 0.49.0 bug). `clientUrl` is baked in so the
|
|
137
|
-
* client targets the right SSE origin. Pure function — exported for testing.
|
|
138
|
-
*/
|
|
139
|
-
export declare function clientShimSource(runtimeSpecifier: string, clientUrl: string): string;
|
|
140
|
-
/**
|
|
141
|
-
* Create the dev-only Nisli HMR esbuild plugin. Add it to `plugins` ONLY when
|
|
142
|
-
* building with `--watch`; never on the prod build path.
|
|
143
|
-
*/
|
|
144
|
-
export declare function nisliHmrPlugin(options: NisliHmrPluginOptions): EsbuildPlugin;
|
|
145
|
-
/**
|
|
146
|
-
* Diff two output-hash maps into an esbuild-shaped change payload.
|
|
147
|
-
* Returns `null` for the very first build (no previous baseline).
|
|
148
|
-
* Exported for testing.
|
|
149
|
-
*/
|
|
150
|
-
export declare function diffOutputs(prev: Map<string, string> | null, next: Map<string, string>): {
|
|
151
|
-
added: string[];
|
|
152
|
-
removed: string[];
|
|
153
|
-
updated: string[];
|
|
154
|
-
} | null;
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* esbuild-hmr/plugin.ts — Dev-only esbuild plugin for Nisli component HMR.
|
|
3
|
-
*
|
|
4
|
-
* DEV-ONLY, build-time (Node). Reachable only via `@nisli/core/esbuild-hmr`,
|
|
5
|
-
* never from the runtime `.` entry (ADR 0021, Ruling 1). It is added to the
|
|
6
|
-
* esbuild plugin list ONLY on the `--watch` path; `pnpm build` (no watch) never
|
|
7
|
-
* sees it, so prod is byte-identical by construction (Ruling 5).
|
|
8
|
-
*
|
|
9
|
-
* `esbuild` is an OPTIONAL peerDependency. To keep `@nisli/core` dependency-free
|
|
10
|
-
* we do NOT `import` esbuild here — we type the plugin against a minimal local
|
|
11
|
-
* structural surface. The host build script supplies the real esbuild.
|
|
12
|
-
*
|
|
13
|
-
* What it does:
|
|
14
|
-
* 1. onLoad (Ruling 2): for author modules that import `component` from
|
|
15
|
-
* `@nisli/core`, rewrite the import so `component(tag, setup, opts)` routes
|
|
16
|
-
* `setup` through the runtime tag-keyed registry's STABLE indirection thunk.
|
|
17
|
-
* The real `FrameworkComponent` thus captures a thunk that always reads the
|
|
18
|
-
* current setup — no class swap, no tag re-definition.
|
|
19
|
-
* 2. onEnd (Ruling 4 transport): diff the metafile outputs against the previous
|
|
20
|
-
* build and broadcast a `change` payload ({added, removed, updated}) over
|
|
21
|
-
* SSE so the browser client can escalate (css/js/reload).
|
|
22
|
-
* 3. Inject the browser dev client (`@nisli/core/esbuild-hmr/runtime` +
|
|
23
|
-
* `connect({ path })`) via esbuild's `inject` option pointed at a VIRTUAL
|
|
24
|
-
* shim module, so the runtime is RESOLVED + BUNDLED into the output (no
|
|
25
|
-
* author HTML/JS change needed). We deliberately do NOT use `banner`: a
|
|
26
|
-
* banner is raw passthrough text that esbuild neither resolves nor bundles,
|
|
27
|
-
* so a bare `import … from "@nisli/core/esbuild-hmr/runtime"` would leak
|
|
28
|
-
* verbatim into the output and the browser would throw
|
|
29
|
-
* `Failed to resolve module specifier` (no import map). `inject` runs the
|
|
30
|
-
* shim through onResolve/onLoad so the runtime is inlined at build time, and
|
|
31
|
-
* esbuild applies `inject` ONLY to JS modules — never to file/copy-loaded
|
|
32
|
-
* entries (e.g. the viewer's `logo.svg`). Verified empirically against
|
|
33
|
-
* esbuild 0.28.1.
|
|
34
|
-
*/
|
|
35
|
-
/// <reference types="node" />
|
|
36
|
-
import { readFileSync } from 'node:fs';
|
|
37
|
-
// ── Source transform (Ruling 2) ─────────────────────────────────────
|
|
38
|
-
const DEFAULT_FILTER = /\.[mc]?[jt]sx?$/;
|
|
39
|
-
/**
|
|
40
|
-
* Virtual path + namespace for the injected client shim. The path is a bare
|
|
41
|
-
* sentinel (not a real file); onResolve claims it into a private namespace and
|
|
42
|
-
* onLoad supplies its generated source, so esbuild bundles the runtime inline.
|
|
43
|
-
*/
|
|
44
|
-
const CLIENT_SHIM_PATH = 'nisli-hmr-client-shim';
|
|
45
|
-
const CLIENT_SHIM_NAMESPACE = 'nisli-hmr-shim';
|
|
46
|
-
const CLIENT_SHIM_FILTER = /^nisli-hmr-client-shim$/;
|
|
47
|
-
/**
|
|
48
|
-
* `transformSource` (wrap `component()` call sites) now lives in the shared
|
|
49
|
-
* `../hmr/transform.js` and is re-exported here so this module's surface — and
|
|
50
|
-
* the tests that import it from './plugin.js' — are unchanged (ADR 0110).
|
|
51
|
-
*/
|
|
52
|
-
import { transformSource } from '../hmr/transform.js';
|
|
53
|
-
export { transformSource };
|
|
54
|
-
/**
|
|
55
|
-
* Source of the virtual client shim that esbuild's `inject` pulls into every JS
|
|
56
|
-
* module. Because it is `inject`ed (not a `banner`), esbuild RESOLVES the
|
|
57
|
-
* `runtimeSpecifier` import and BUNDLES `connect` inline — no bare specifier
|
|
58
|
-
* survives in the output (the 0.49.0 bug). `clientUrl` is baked in so the
|
|
59
|
-
* client targets the right SSE origin. Pure function — exported for testing.
|
|
60
|
-
*/
|
|
61
|
-
export function clientShimSource(runtimeSpecifier, clientUrl) {
|
|
62
|
-
return (`import { connect as __nisliConnect } from '${runtimeSpecifier}';\n` +
|
|
63
|
-
`__nisliConnect({ path: ${JSON.stringify(clientUrl)} });\n`);
|
|
64
|
-
}
|
|
65
|
-
// ── The plugin ──────────────────────────────────────────────────────
|
|
66
|
-
/**
|
|
67
|
-
* Create the dev-only Nisli HMR esbuild plugin. Add it to `plugins` ONLY when
|
|
68
|
-
* building with `--watch`; never on the prod build path.
|
|
69
|
-
*/
|
|
70
|
-
export function nisliHmrPlugin(options) {
|
|
71
|
-
const coreSpecifier = options.coreSpecifier ?? '@nisli/core';
|
|
72
|
-
const runtimeSpecifier = options.runtimeSpecifier ?? '@nisli/core/esbuild-hmr/runtime';
|
|
73
|
-
const clientUrl = options.clientUrl ?? '/esbuild';
|
|
74
|
-
const filter = options.filter ?? DEFAULT_FILTER;
|
|
75
|
-
const { broadcaster } = options;
|
|
76
|
-
let prevHashes = null;
|
|
77
|
-
return {
|
|
78
|
-
name: 'nisli-hmr',
|
|
79
|
-
setup(build) {
|
|
80
|
-
// Inject the browser dev client via esbuild's `inject` (NOT `banner`).
|
|
81
|
-
// A banner is raw passthrough text — its bare `import` would leak into the
|
|
82
|
-
// output and the browser could not resolve it. `inject` points at a
|
|
83
|
-
// virtual shim that esbuild resolves + bundles, inlining the runtime so no
|
|
84
|
-
// bare specifier survives. esbuild applies `inject` only to JS modules, so
|
|
85
|
-
// the viewer's file/copy-loaded `logo.svg` entry is never touched.
|
|
86
|
-
build.initialOptions.inject = [
|
|
87
|
-
...(build.initialOptions.inject ?? []),
|
|
88
|
-
CLIENT_SHIM_PATH,
|
|
89
|
-
];
|
|
90
|
-
build.onResolve({ filter: CLIENT_SHIM_FILTER }, (args) => {
|
|
91
|
-
if (args.path !== CLIENT_SHIM_PATH)
|
|
92
|
-
return undefined;
|
|
93
|
-
return { path: CLIENT_SHIM_PATH, namespace: CLIENT_SHIM_NAMESPACE };
|
|
94
|
-
});
|
|
95
|
-
build.onLoad({ filter: /.*/, namespace: CLIENT_SHIM_NAMESPACE }, () => ({
|
|
96
|
-
contents: clientShimSource(runtimeSpecifier, clientUrl),
|
|
97
|
-
loader: 'js',
|
|
98
|
-
// A virtual module has no on-disk location, so esbuild won't know where
|
|
99
|
-
// to resolve the runtime import from. Anchor it to the build's working
|
|
100
|
-
// directory (where the consumer's `@nisli/core` resolves).
|
|
101
|
-
resolveDir: build.initialOptions.absWorkingDir ?? process.cwd(),
|
|
102
|
-
}));
|
|
103
|
-
// 1. Transform: wrap component() call sites (Ruling 2).
|
|
104
|
-
build.onLoad({ filter }, (args) => {
|
|
105
|
-
if (args.path.includes('node_modules'))
|
|
106
|
-
return undefined;
|
|
107
|
-
const code = readFileSafe(args.path);
|
|
108
|
-
if (code === null)
|
|
109
|
-
return undefined;
|
|
110
|
-
const contents = transformSource(code, coreSpecifier, runtimeSpecifier);
|
|
111
|
-
if (contents === code)
|
|
112
|
-
return undefined; // nothing to wrap; let esbuild load it
|
|
113
|
-
return { contents, loader: loaderFor(args.path) };
|
|
114
|
-
});
|
|
115
|
-
// 2. Diff outputs and broadcast a change payload (Ruling 4 transport).
|
|
116
|
-
build.onEnd((result) => {
|
|
117
|
-
const outputs = result.metafile?.outputs;
|
|
118
|
-
if (!outputs) {
|
|
119
|
-
// No metafile -> cannot diff -> signal a reload-worthy change.
|
|
120
|
-
broadcaster.broadcast({ added: [], removed: [], updated: [] });
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const nextHashes = new Map();
|
|
124
|
-
for (const [path, meta] of Object.entries(outputs)) {
|
|
125
|
-
nextHashes.set(path, meta.hash ?? String(meta.bytes));
|
|
126
|
-
}
|
|
127
|
-
const payload = diffOutputs(prevHashes, nextHashes);
|
|
128
|
-
prevHashes = nextHashes;
|
|
129
|
-
// First build establishes the baseline; don't broadcast on it.
|
|
130
|
-
if (payload)
|
|
131
|
-
broadcaster.broadcast(payload);
|
|
132
|
-
});
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Diff two output-hash maps into an esbuild-shaped change payload.
|
|
138
|
-
* Returns `null` for the very first build (no previous baseline).
|
|
139
|
-
* Exported for testing.
|
|
140
|
-
*/
|
|
141
|
-
export function diffOutputs(prev, next) {
|
|
142
|
-
if (prev === null)
|
|
143
|
-
return null;
|
|
144
|
-
const added = [];
|
|
145
|
-
const removed = [];
|
|
146
|
-
const updated = [];
|
|
147
|
-
for (const [path, hash] of next) {
|
|
148
|
-
const before = prev.get(path);
|
|
149
|
-
if (before === undefined)
|
|
150
|
-
added.push(path);
|
|
151
|
-
else if (before !== hash)
|
|
152
|
-
updated.push(path);
|
|
153
|
-
}
|
|
154
|
-
for (const path of prev.keys()) {
|
|
155
|
-
if (!next.has(path))
|
|
156
|
-
removed.push(path);
|
|
157
|
-
}
|
|
158
|
-
return { added, removed, updated };
|
|
159
|
-
}
|
|
160
|
-
// ── helpers ─────────────────────────────────────────────────────────
|
|
161
|
-
function loaderFor(path) {
|
|
162
|
-
if (path.endsWith('.tsx'))
|
|
163
|
-
return 'tsx';
|
|
164
|
-
if (path.endsWith('.jsx'))
|
|
165
|
-
return 'jsx';
|
|
166
|
-
if (/\.[mc]?ts$/.test(path))
|
|
167
|
-
return 'ts';
|
|
168
|
-
return 'js';
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Read a file synchronously. Build-time only (Node); returns null on failure so
|
|
172
|
-
* esbuild falls back to its own loader. `node:fs` is fine here — this module is
|
|
173
|
-
* never reachable from the `.` runtime graph (ADR 0021, Ruling 1).
|
|
174
|
-
*/
|
|
175
|
-
function readFileSafe(path) {
|
|
176
|
-
try {
|
|
177
|
-
return readFileSync(path, 'utf8');
|
|
178
|
-
}
|
|
179
|
-
catch {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
//# sourceMappingURL=plugin.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/esbuild-hmr/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* esbuild-hmr/runtime.ts — Browser dev client for Nisli HMR.
|
|
3
|
-
*
|
|
4
|
-
* DEV-ONLY. Reachable only via the `@nisli/core/esbuild-hmr/runtime` subpath,
|
|
5
|
-
* which the esbuild plugin injects on the `--watch` path. It is NEVER imported
|
|
6
|
-
* by the `@nisli/core` runtime `.` entry, so it contributes zero production
|
|
7
|
-
* bytes (ADR 0021, Ruling 1 & 5).
|
|
8
|
-
*
|
|
9
|
-
* Responsibilities (ADR 0021):
|
|
10
|
-
* - A tag -> setup registry with a STABLE indirection thunk (Ruling 2).
|
|
11
|
-
* - remount() of live elements through the existing custom-element lifecycle:
|
|
12
|
-
* disconnectedCallback() -> replaceChildren() -> connectedCallback() (Ruling 3).
|
|
13
|
-
* - An EventSource client that classifies an esbuild `change` payload and
|
|
14
|
-
* escalates: CSS hot-swap -> component re-mount -> full reload (Ruling 4).
|
|
15
|
-
*
|
|
16
|
-
* The class is NEVER swapped and the tag is NEVER re-defined; we swap only the
|
|
17
|
-
* `setup` behind the registry, working *with* the `customElements.get` guard in
|
|
18
|
-
* component.ts rather than against it.
|
|
19
|
-
*/
|
|
20
|
-
export { __register, pendingRemountCount, drainRemounts, remount, __resetRegistry, type HmrSetup, } from '../hmr/registry.js';
|
|
21
|
-
/** esbuild's `change` event payload shape (added/removed/updated paths). */
|
|
22
|
-
export interface EsbuildChangePayload {
|
|
23
|
-
added: string[];
|
|
24
|
-
removed: string[];
|
|
25
|
-
updated: string[];
|
|
26
|
-
}
|
|
27
|
-
/** What to do with a change, decided from the output diff (Ruling 4). */
|
|
28
|
-
export type HmrAction = 'css' | 'js' | 'reload';
|
|
29
|
-
/** Minimal structural EventSource (avoids depending on DOM lib EventSource). */
|
|
30
|
-
interface EventSourceLike {
|
|
31
|
-
addEventListener(type: string, listener: (ev: {
|
|
32
|
-
data?: string;
|
|
33
|
-
}) => void): void;
|
|
34
|
-
close?(): void;
|
|
35
|
-
}
|
|
36
|
-
/** Options for {@link connect}. Seams kept injectable for tests. */
|
|
37
|
-
export interface ConnectOptions {
|
|
38
|
-
/** SSE endpoint. Defaults to esbuild's `/esbuild`. */
|
|
39
|
-
path?: string;
|
|
40
|
-
/**
|
|
41
|
-
* Factory for the EventSource. Defaults to the global `EventSource`.
|
|
42
|
-
* Injectable so the client logic is testable without a live SSE server.
|
|
43
|
-
*/
|
|
44
|
-
eventSourceFactory?: (url: string) => EventSourceLike;
|
|
45
|
-
/**
|
|
46
|
-
* Re-import the rebuilt JS so the wrapper re-runs `__register` for changed
|
|
47
|
-
* tags. Defaults to a cache-busted dynamic import of the page's module
|
|
48
|
-
* scripts. Returns a promise resolving when re-evaluation is done.
|
|
49
|
-
*/
|
|
50
|
-
reimport?: () => Promise<void>;
|
|
51
|
-
/** Force a full reload. Defaults to `location.reload()`. */
|
|
52
|
-
reload?: () => void;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Decide the action for an esbuild output diff:
|
|
56
|
-
* - every changed output is CSS -> 'css' (hot-swap, preserves everything)
|
|
57
|
-
* - any JS output changed -> 'js' (re-import; re-mount changed tags
|
|
58
|
-
* or escalate to reload if none)
|
|
59
|
-
* - nothing actionable -> 'reload'
|
|
60
|
-
*/
|
|
61
|
-
export declare function classifyChange(payload: EsbuildChangePayload): HmrAction;
|
|
62
|
-
/**
|
|
63
|
-
* Hot-swap stylesheets in place by re-pointing matching `<link>` hrefs with a
|
|
64
|
-
* cache-busting query — no reload, no state loss (esbuild's documented CSS
|
|
65
|
-
* technique). Returns the number of links swapped.
|
|
66
|
-
*/
|
|
67
|
-
export declare function hotSwapCss(updated: string[]): number;
|
|
68
|
-
/**
|
|
69
|
-
* Connect to the SSE change channel and apply updates with escalation.
|
|
70
|
-
* Safe to call once from the dev client; injected by the plugin in watch builds.
|
|
71
|
-
*/
|
|
72
|
-
export declare function connect(options?: ConnectOptions): EventSourceLike;
|
|
73
|
-
/** Close the active SSE connection (test/teardown). */
|
|
74
|
-
export declare function disconnect(): void;
|
|
75
|
-
/**
|
|
76
|
-
* Apply a classified change. Exposed for tests so the escalation ladder is
|
|
77
|
-
* verifiable without a live EventSource.
|
|
78
|
-
*
|
|
79
|
-
* For a JS change we re-import (re-runs the wrapper's `__register` calls); if no
|
|
80
|
-
* tag's setup actually changed, the edit was a non-component module (util/
|
|
81
|
-
* service) and we escalate to a full reload — the correct, safe fallback.
|
|
82
|
-
*/
|
|
83
|
-
export declare function applyChange(payload: EsbuildChangePayload, deps: {
|
|
84
|
-
reimport: () => Promise<void>;
|
|
85
|
-
reload: () => void;
|
|
86
|
-
}): Promise<HmrAction>;
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* esbuild-hmr/runtime.ts — Browser dev client for Nisli HMR.
|
|
3
|
-
*
|
|
4
|
-
* DEV-ONLY. Reachable only via the `@nisli/core/esbuild-hmr/runtime` subpath,
|
|
5
|
-
* which the esbuild plugin injects on the `--watch` path. It is NEVER imported
|
|
6
|
-
* by the `@nisli/core` runtime `.` entry, so it contributes zero production
|
|
7
|
-
* bytes (ADR 0021, Ruling 1 & 5).
|
|
8
|
-
*
|
|
9
|
-
* Responsibilities (ADR 0021):
|
|
10
|
-
* - A tag -> setup registry with a STABLE indirection thunk (Ruling 2).
|
|
11
|
-
* - remount() of live elements through the existing custom-element lifecycle:
|
|
12
|
-
* disconnectedCallback() -> replaceChildren() -> connectedCallback() (Ruling 3).
|
|
13
|
-
* - An EventSource client that classifies an esbuild `change` payload and
|
|
14
|
-
* escalates: CSS hot-swap -> component re-mount -> full reload (Ruling 4).
|
|
15
|
-
*
|
|
16
|
-
* The class is NEVER swapped and the tag is NEVER re-defined; we swap only the
|
|
17
|
-
* `setup` behind the registry, working *with* the `customElements.get` guard in
|
|
18
|
-
* component.ts rather than against it.
|
|
19
|
-
*/
|
|
20
|
-
// ── Types ───────────────────────────────────────────────────────────
|
|
21
|
-
// Transport-agnostic registry/remount core lives in ../hmr/registry.js and is
|
|
22
|
-
// shared with the Vite adapter (ADR 0110). Re-exported here so this module's
|
|
23
|
-
// public surface — and the tests that import from './runtime.js' — are
|
|
24
|
-
// unchanged by the extraction.
|
|
25
|
-
export { __register, pendingRemountCount, drainRemounts, remount, __resetRegistry, } from '../hmr/registry.js';
|
|
26
|
-
import { beginManualDrain, drainRemounts, endManualDrain, pendingRemountCount } from '../hmr/registry.js';
|
|
27
|
-
// ── Change classification + escalation (Ruling 4) ───────────────────
|
|
28
|
-
const CSS_RE = /\.css($|\?)/;
|
|
29
|
-
/**
|
|
30
|
-
* Decide the action for an esbuild output diff:
|
|
31
|
-
* - every changed output is CSS -> 'css' (hot-swap, preserves everything)
|
|
32
|
-
* - any JS output changed -> 'js' (re-import; re-mount changed tags
|
|
33
|
-
* or escalate to reload if none)
|
|
34
|
-
* - nothing actionable -> 'reload'
|
|
35
|
-
*/
|
|
36
|
-
export function classifyChange(payload) {
|
|
37
|
-
const touched = [...payload.added, ...payload.removed, ...payload.updated];
|
|
38
|
-
if (touched.length === 0)
|
|
39
|
-
return 'reload';
|
|
40
|
-
if (touched.every((p) => CSS_RE.test(p)))
|
|
41
|
-
return 'css';
|
|
42
|
-
if (touched.some((p) => /\.[mc]?js($|\?)/.test(p)))
|
|
43
|
-
return 'js';
|
|
44
|
-
return 'reload';
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Hot-swap stylesheets in place by re-pointing matching `<link>` hrefs with a
|
|
48
|
-
* cache-busting query — no reload, no state loss (esbuild's documented CSS
|
|
49
|
-
* technique). Returns the number of links swapped.
|
|
50
|
-
*/
|
|
51
|
-
export function hotSwapCss(updated) {
|
|
52
|
-
let swapped = 0;
|
|
53
|
-
const links = document.querySelectorAll('link[rel="stylesheet"]');
|
|
54
|
-
links.forEach((node) => {
|
|
55
|
-
const link = node;
|
|
56
|
-
const href = link.getAttribute('href');
|
|
57
|
-
if (!href)
|
|
58
|
-
return;
|
|
59
|
-
const base = href.split('?')[0] ?? href;
|
|
60
|
-
const matches = updated.some((u) => {
|
|
61
|
-
const uBase = (u.split('?')[0] ?? u).replace(/^\.?\//, '');
|
|
62
|
-
return uBase.endsWith(base.replace(/^\.?\//, ''));
|
|
63
|
-
});
|
|
64
|
-
if (matches) {
|
|
65
|
-
link.setAttribute('href', `${base}?t=${Date.now()}`);
|
|
66
|
-
swapped++;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
return swapped;
|
|
70
|
-
}
|
|
71
|
-
// ── EventSource client (transport) ──────────────────────────────────
|
|
72
|
-
let connected = null;
|
|
73
|
-
/**
|
|
74
|
-
* Connect to the SSE change channel and apply updates with escalation.
|
|
75
|
-
* Safe to call once from the dev client; injected by the plugin in watch builds.
|
|
76
|
-
*/
|
|
77
|
-
export function connect(options = {}) {
|
|
78
|
-
// Idempotency guard (critical for the bundled re-import model). The plugin
|
|
79
|
-
// injects `connect()` at the entry's top level, and a JS update re-evaluates
|
|
80
|
-
// the entry (so `__register` re-runs for changed tags). That re-eval also
|
|
81
|
-
// re-runs this `connect()` call. Because `connected` lives in the persistent
|
|
82
|
-
// HMR runtime chunk (re-imported entries reuse it by name, un-busted), the
|
|
83
|
-
// guard survives across re-imports and keeps EXACTLY ONE EventSource + change
|
|
84
|
-
// listener alive — otherwise listeners stack and each edit fans out into N
|
|
85
|
-
// compounding re-imports.
|
|
86
|
-
if (connected)
|
|
87
|
-
return connected;
|
|
88
|
-
const path = options.path ?? '/esbuild';
|
|
89
|
-
const reload = options.reload ?? (() => location.reload());
|
|
90
|
-
const reimport = options.reimport ?? defaultReimport;
|
|
91
|
-
const factory = options.eventSourceFactory ??
|
|
92
|
-
((url) => new globalThis.EventSource(url));
|
|
93
|
-
const source = factory(path);
|
|
94
|
-
connected = source;
|
|
95
|
-
source.addEventListener('change', (ev) => {
|
|
96
|
-
let payload;
|
|
97
|
-
try {
|
|
98
|
-
payload = ev.data ? JSON.parse(ev.data) : { added: [], removed: [], updated: [] };
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
reload();
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
void applyChange(payload, { reimport, reload });
|
|
105
|
-
});
|
|
106
|
-
return source;
|
|
107
|
-
}
|
|
108
|
-
/** Close the active SSE connection (test/teardown). */
|
|
109
|
-
export function disconnect() {
|
|
110
|
-
connected?.close?.();
|
|
111
|
-
connected = null;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Apply a classified change. Exposed for tests so the escalation ladder is
|
|
115
|
-
* verifiable without a live EventSource.
|
|
116
|
-
*
|
|
117
|
-
* For a JS change we re-import (re-runs the wrapper's `__register` calls); if no
|
|
118
|
-
* tag's setup actually changed, the edit was a non-component module (util/
|
|
119
|
-
* service) and we escalate to a full reload — the correct, safe fallback.
|
|
120
|
-
*/
|
|
121
|
-
export async function applyChange(payload, deps) {
|
|
122
|
-
const action = classifyChange(payload);
|
|
123
|
-
if (action === 'css') {
|
|
124
|
-
hotSwapCss(payload.updated);
|
|
125
|
-
return 'css';
|
|
126
|
-
}
|
|
127
|
-
if (action === 'js') {
|
|
128
|
-
// Own the drain: suppress the auto microtask so ALL changed tags register
|
|
129
|
-
// during re-import before any re-mount runs.
|
|
130
|
-
beginManualDrain();
|
|
131
|
-
try {
|
|
132
|
-
await deps.reimport();
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
endManualDrain();
|
|
136
|
-
}
|
|
137
|
-
if (pendingRemountCount() > 0) {
|
|
138
|
-
drainRemounts();
|
|
139
|
-
return 'js';
|
|
140
|
-
}
|
|
141
|
-
// JS changed but no component setup changed -> non-component edit -> reload.
|
|
142
|
-
deps.reload();
|
|
143
|
-
return 'reload';
|
|
144
|
-
}
|
|
145
|
-
deps.reload();
|
|
146
|
-
return 'reload';
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Default re-import: re-fetch every module `<script type="module">` with a
|
|
150
|
-
* cache-busting query so the bundle re-evaluates and the wrapper re-runs
|
|
151
|
-
* `__register` for changed tags.
|
|
152
|
-
*/
|
|
153
|
-
async function defaultReimport() {
|
|
154
|
-
const scripts = document.querySelectorAll('script[type="module"][src]');
|
|
155
|
-
const imports = [];
|
|
156
|
-
scripts.forEach((node) => {
|
|
157
|
-
const src = node.getAttribute('src');
|
|
158
|
-
if (src)
|
|
159
|
-
imports.push(import(/* @vite-ignore */ `${src.split('?')[0]}?t=${Date.now()}`));
|
|
160
|
-
});
|
|
161
|
-
await Promise.all(imports);
|
|
162
|
-
}
|
|
163
|
-
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/esbuild-hmr/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* esbuild-hmr/server.ts — Tiny SSE hub for the Nisli HMR change channel.
|
|
3
|
-
*
|
|
4
|
-
* DEV-ONLY, Node, build-time. Reachable only via `@nisli/core/esbuild-hmr`,
|
|
5
|
-
* never the runtime `.` entry (ADR 0021, Ruling 1). Uses only `node:http`
|
|
6
|
-
* (a Node built-in, not a package dependency), so the zero-dep posture of the
|
|
7
|
-
* `.` entry is preserved.
|
|
8
|
-
*
|
|
9
|
-
* Two ways to wire transport (ADR 0021 Engineering Plan §1):
|
|
10
|
-
* (a) Standalone: `createHmrServer()` starts a minimal `node:http` SSE hub at
|
|
11
|
-
* `/esbuild` (matching esbuild's own client convention) and returns a
|
|
12
|
-
* broadcaster the plugin pushes `change` payloads to.
|
|
13
|
-
* (b) BYO: any object implementing {@link ChangeBroadcaster} (e.g. an esbuild
|
|
14
|
-
* `serve` adapter that owns the `/esbuild` endpoint) can be handed to the
|
|
15
|
-
* plugin instead.
|
|
16
|
-
*/
|
|
17
|
-
import { type Server } from 'node:http';
|
|
18
|
-
/** esbuild-shaped change payload broadcast to dev clients. */
|
|
19
|
-
export interface ChangePayload {
|
|
20
|
-
added: string[];
|
|
21
|
-
removed: string[];
|
|
22
|
-
updated: string[];
|
|
23
|
-
}
|
|
24
|
-
/** Anything that can push a `change` event to connected dev clients. */
|
|
25
|
-
export interface ChangeBroadcaster {
|
|
26
|
-
/** Broadcast a change to every connected client. */
|
|
27
|
-
broadcast(payload: ChangePayload): void;
|
|
28
|
-
/** Current number of connected clients (for diagnostics/tests). */
|
|
29
|
-
readonly clientCount: number;
|
|
30
|
-
}
|
|
31
|
-
/** Handle for the standalone SSE hub. */
|
|
32
|
-
export interface HmrServer extends ChangeBroadcaster {
|
|
33
|
-
/** The underlying `node:http` server (for `.address()`, lifecycle, tests). */
|
|
34
|
-
readonly server: Server;
|
|
35
|
-
/** Start listening. Resolves once bound. */
|
|
36
|
-
listen(port?: number, host?: string): Promise<{
|
|
37
|
-
port: number;
|
|
38
|
-
host: string;
|
|
39
|
-
}>;
|
|
40
|
-
/** Close all client connections and stop the server. */
|
|
41
|
-
close(): Promise<void>;
|
|
42
|
-
}
|
|
43
|
-
export interface CreateHmrServerOptions {
|
|
44
|
-
/** SSE route. Defaults to `/esbuild` (esbuild's client convention). */
|
|
45
|
-
path?: string;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Create a standalone SSE hub. Returns immediately; call `listen()` to bind.
|
|
49
|
-
* The plugin calls `broadcast()` from its `onEnd` after each watch rebuild.
|
|
50
|
-
*/
|
|
51
|
-
export declare function createHmrServer(options?: CreateHmrServerOptions): HmrServer;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* esbuild-hmr/server.ts — Tiny SSE hub for the Nisli HMR change channel.
|
|
3
|
-
*
|
|
4
|
-
* DEV-ONLY, Node, build-time. Reachable only via `@nisli/core/esbuild-hmr`,
|
|
5
|
-
* never the runtime `.` entry (ADR 0021, Ruling 1). Uses only `node:http`
|
|
6
|
-
* (a Node built-in, not a package dependency), so the zero-dep posture of the
|
|
7
|
-
* `.` entry is preserved.
|
|
8
|
-
*
|
|
9
|
-
* Two ways to wire transport (ADR 0021 Engineering Plan §1):
|
|
10
|
-
* (a) Standalone: `createHmrServer()` starts a minimal `node:http` SSE hub at
|
|
11
|
-
* `/esbuild` (matching esbuild's own client convention) and returns a
|
|
12
|
-
* broadcaster the plugin pushes `change` payloads to.
|
|
13
|
-
* (b) BYO: any object implementing {@link ChangeBroadcaster} (e.g. an esbuild
|
|
14
|
-
* `serve` adapter that owns the `/esbuild` endpoint) can be handed to the
|
|
15
|
-
* plugin instead.
|
|
16
|
-
*/
|
|
17
|
-
/// <reference types="node" />
|
|
18
|
-
import { createServer } from 'node:http';
|
|
19
|
-
/**
|
|
20
|
-
* Create a standalone SSE hub. Returns immediately; call `listen()` to bind.
|
|
21
|
-
* The plugin calls `broadcast()` from its `onEnd` after each watch rebuild.
|
|
22
|
-
*/
|
|
23
|
-
export function createHmrServer(options = {}) {
|
|
24
|
-
const path = options.path ?? '/esbuild';
|
|
25
|
-
const clients = new Set();
|
|
26
|
-
const server = createServer((req, res) => {
|
|
27
|
-
if (req.url !== path) {
|
|
28
|
-
res.statusCode = 404;
|
|
29
|
-
res.end();
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
// SSE handshake.
|
|
33
|
-
res.writeHead(200, {
|
|
34
|
-
'Content-Type': 'text/event-stream',
|
|
35
|
-
'Cache-Control': 'no-cache',
|
|
36
|
-
Connection: 'keep-alive',
|
|
37
|
-
'Access-Control-Allow-Origin': '*',
|
|
38
|
-
});
|
|
39
|
-
res.write('retry: 500\n\n');
|
|
40
|
-
clients.add(res);
|
|
41
|
-
req.on('close', () => {
|
|
42
|
-
clients.delete(res);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
const broadcast = (payload) => {
|
|
46
|
-
const frame = `event: change\ndata: ${JSON.stringify(payload)}\n\n`;
|
|
47
|
-
for (const res of clients) {
|
|
48
|
-
try {
|
|
49
|
-
res.write(frame);
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
clients.delete(res);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
return {
|
|
57
|
-
server,
|
|
58
|
-
broadcast,
|
|
59
|
-
get clientCount() {
|
|
60
|
-
return clients.size;
|
|
61
|
-
},
|
|
62
|
-
listen(port = 0, host = '127.0.0.1') {
|
|
63
|
-
return new Promise((resolve) => {
|
|
64
|
-
server.listen(port, host, () => {
|
|
65
|
-
const addr = server.address();
|
|
66
|
-
const boundPort = typeof addr === 'object' && addr ? addr.port : port;
|
|
67
|
-
resolve({ port: boundPort, host });
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
close() {
|
|
72
|
-
return new Promise((resolve) => {
|
|
73
|
-
for (const res of clients) {
|
|
74
|
-
try {
|
|
75
|
-
res.end();
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
/* ignore */
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
clients.clear();
|
|
82
|
-
server.close(() => resolve());
|
|
83
|
-
});
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
//# sourceMappingURL=server.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/esbuild-hmr/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8BAA8B;AAC9B,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AAgCjG;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,UAAkC,EAAE;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;QACxE,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;YACrB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,iBAAiB;QACjB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;YACjB,cAAc,EAAE,mBAAmB;YACnC,eAAe,EAAE,UAAU;YAC3B,UAAU,EAAE,YAAY;YACxB,6BAA6B,EAAE,GAAG;SACnC,CAAC,CAAC;QACH,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,CAAC,OAAsB,EAAQ,EAAE;QACjD,MAAM,KAAK,GAAG,wBAAwB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;QACpE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,MAAM;QACN,SAAS;QACT,IAAI,WAAW;YACb,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;QACD,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,WAAW;YACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;oBAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC9B,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;oBACtE,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACrC,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;oBAC1B,IAAI,CAAC;wBACH,GAAG,CAAC,GAAG,EAAE,CAAC;oBACZ,CAAC;oBAAC,MAAM,CAAC;wBACP,YAAY;oBACd,CAAC;gBACH,CAAC;gBACD,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|