@hydraharness/harness-client-modules 0.1.1-rc.6
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/LICENSE +21 -0
- package/README.md +26 -0
- package/lib/client.js +324 -0
- package/lib/index.js +493 -0
- package/lib/invariant.js +34 -0
- package/lib/types/client/index.d.ts +32 -0
- package/lib/types/client/manifest.d.ts +239 -0
- package/lib/types/client/system.d.ts +46 -0
- package/lib/types/index.d.ts +127 -0
- package/lib/types/invariant.d.ts +16 -0
- package/package.json +65 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client module system: the browser peer of Node's internal ESM loader, built
|
|
3
|
+
* as a lazy CJS table. The vendored cordis Loader consumes this object
|
|
4
|
+
* through its `internal` contract (the only call site is `EntryTree.import` →
|
|
5
|
+
* `internal.import`), which keeps entry governance (fiber lifecycle, inject
|
|
6
|
+
* waiting, update/refresh) entirely on the vendored side while this package
|
|
7
|
+
* owns code arrival.
|
|
8
|
+
*
|
|
9
|
+
* Lazy CJS model: executing a plugin bundle only REGISTERS its
|
|
10
|
+
* factory (`window.__ModuleLoader__.load({id, factory})`); every module body
|
|
11
|
+
* side effect — including CSS injection — lives inside the factory closure
|
|
12
|
+
* and runs at materialization, not at script execution. Materialization
|
|
13
|
+
* (factory(require) → exports) happens on first import/require and is
|
|
14
|
+
* memoized in {@link ClientModuleLoader.loadCache}; a factory that requires
|
|
15
|
+
* another registered-but-unmaterialized module materializes it recursively,
|
|
16
|
+
* so load order needs no external sequencing.
|
|
17
|
+
*
|
|
18
|
+
* Resolution branch order (import): seed word → shell instance; memoized
|
|
19
|
+
* record → exports; graph row → register its dependency factories and own
|
|
20
|
+
* factory; registered factory → materialize; anything else → throw (loud —
|
|
21
|
+
* the runtime mirror of the build-time bundle purity gate).
|
|
22
|
+
* The synchronous `require` handed to factories walks the same order minus
|
|
23
|
+
* the load branch. Loading is async, so a requested dynamic package must have
|
|
24
|
+
* registered its factory before a consumer materializes.
|
|
25
|
+
*
|
|
26
|
+
* This file is the browser-safe contract face (zero node imports): the
|
|
27
|
+
* `__HYDRA_BOOT__` wire types, the boot-manifest parser, and the boundaries around
|
|
28
|
+
* {@link ClientModuleSystem}. The package root is the host-side service that
|
|
29
|
+
* composes the wire.
|
|
30
|
+
*/
|
|
31
|
+
import type { ClientModuleSystem } from './system.ts';
|
|
32
|
+
declare module '@hydraharness/cordis' {
|
|
33
|
+
interface Context {
|
|
34
|
+
/** The client module system the web shell builds at boot (provided by the `./client` wrapper plugin). */
|
|
35
|
+
modules: ClientModuleLoader;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* One composed client entry pushed by the host (a graph row). Wire
|
|
40
|
+
* single source: the host node half (package root) produces this same shape.
|
|
41
|
+
* `immediately` marks stage-one prefetch; `inject` is informational graph
|
|
42
|
+
* metadata (the authoritative edges live in each package's `hydra.client`
|
|
43
|
+
* declaration and reach fibers through entry creation). `external` carries
|
|
44
|
+
* module-graph edges: unlike `inject`, they constrain code arrival because
|
|
45
|
+
* `require` is synchronous (see {@link WebBootGraph.entries}).
|
|
46
|
+
*/
|
|
47
|
+
export interface WebBootEntry {
|
|
48
|
+
/** Entry name == package name. */
|
|
49
|
+
id: string;
|
|
50
|
+
/** Bundle endpoint, '/plugins/<id>/client.js?rev=<rev>'. */
|
|
51
|
+
url: string;
|
|
52
|
+
/** Bundle content hash (cache-busting consistency anchor). */
|
|
53
|
+
rev: string;
|
|
54
|
+
/** Package-name dependency edges, informational (preflight display / HMR diffing). */
|
|
55
|
+
inject?: string[];
|
|
56
|
+
/** Stage-one prefetch mark: load the script for factory registration during module-face boot. */
|
|
57
|
+
immediately?: boolean;
|
|
58
|
+
/** Non-baseline module specifiers this row requests; omitted when it requests none. */
|
|
59
|
+
external?: string[];
|
|
60
|
+
}
|
|
61
|
+
/** The composed client entry graph the host injects as `window.__HYDRA_BOOT__`. */
|
|
62
|
+
export interface WebBootGraph {
|
|
63
|
+
/** Consistency anchor over the whole graph (content + bundle hashes). */
|
|
64
|
+
rev: string;
|
|
65
|
+
/**
|
|
66
|
+
* Composed entries in module-graph order — a dynamic package row precedes
|
|
67
|
+
* rows whose `external` requests that package. Cordis activation order is
|
|
68
|
+
* unrelated and remains owned by fiber service waiting.
|
|
69
|
+
*/
|
|
70
|
+
entries: WebBootEntry[];
|
|
71
|
+
}
|
|
72
|
+
/** The npm-package view of one boot row: what the module table needs to fetch the bundle. */
|
|
73
|
+
export interface BootModuleRow {
|
|
74
|
+
/** Entry name == package name (module-table key). */
|
|
75
|
+
id: string;
|
|
76
|
+
/** Bundle endpoint, '/plugins/<id>/client.js?rev=<rev>'. */
|
|
77
|
+
url: string;
|
|
78
|
+
/** Bundle content hash. */
|
|
79
|
+
rev: string;
|
|
80
|
+
/** Module specifiers this row requests from the module table ([] when the wire omits them). */
|
|
81
|
+
external: string[];
|
|
82
|
+
}
|
|
83
|
+
/** The cordis-plugin view of one boot row: what entry composition needs (optional wire fields normalized). */
|
|
84
|
+
export interface BootPluginRow {
|
|
85
|
+
/** Entry name == package name. */
|
|
86
|
+
id: string;
|
|
87
|
+
/** Package-name dependency edges ([] when the wire omits them). */
|
|
88
|
+
inject: string[];
|
|
89
|
+
/** Stage-one prefetch tier (false when the wire omits it). */
|
|
90
|
+
immediately: boolean;
|
|
91
|
+
}
|
|
92
|
+
/** The parsed boot manifest: one wire, two consumer views. */
|
|
93
|
+
export interface BootManifest {
|
|
94
|
+
/** Consistency anchor over the whole graph. */
|
|
95
|
+
rev: string;
|
|
96
|
+
/** Rows as the module table consumes them. */
|
|
97
|
+
modules: BootModuleRow[];
|
|
98
|
+
/** Rows as entry composition consumes them. */
|
|
99
|
+
plugins: BootPluginRow[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Validate an optional string-array field read from a `hydra.client` declaration
|
|
103
|
+
* or from the boot wire.
|
|
104
|
+
* @param subject - diagnostic prefix naming the package or the wire row.
|
|
105
|
+
* @param field - field name as it appears in the diagnostic.
|
|
106
|
+
* @param value - the raw field value.
|
|
107
|
+
* @returns the validated array, or undefined when the field is absent.
|
|
108
|
+
* @throws {Error} when the value is present but is not an array of strings.
|
|
109
|
+
*/
|
|
110
|
+
export declare function optionalStringArray(subject: string, field: string, value: unknown): string[] | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Normalize a module specifier onto the graph row that owns it: a plugin bundle
|
|
113
|
+
* IS its package's client half, so `<id>/client` (the exports subpath external
|
|
114
|
+
* bundles emit) and the bare package name resolve to the same exports. Both the
|
|
115
|
+
* require path and graph composition normalize here, which is what lets each
|
|
116
|
+
* importing package request the subpath its own code imports.
|
|
117
|
+
* @param spec - module specifier as a bundle requires it or a declaration spells it.
|
|
118
|
+
* @returns the specifier with a trailing `/client` removed.
|
|
119
|
+
*/
|
|
120
|
+
export declare function stripClientSuffix(spec: string): string;
|
|
121
|
+
/**
|
|
122
|
+
* Parse `window.__HYDRA_BOOT__` into the two consumer views. Wire boundary:
|
|
123
|
+
* a missing or malformed graph throws (the shell shows the loud failure —
|
|
124
|
+
* a page without a valid manifest cannot boot anything).
|
|
125
|
+
* @param wire - the raw `window.__HYDRA_BOOT__` value.
|
|
126
|
+
* @returns the manifest with optional plugin-view fields normalized.
|
|
127
|
+
*/
|
|
128
|
+
export declare function parseBootManifest(wire: unknown): BootManifest;
|
|
129
|
+
/** One client bundle's factory registration submitted through `window.__ModuleLoader__.load`. */
|
|
130
|
+
export interface ClientBundleRegistration {
|
|
131
|
+
/** Plugin id (package name) — the registration key; must match the graph row being executed. */
|
|
132
|
+
id: string;
|
|
133
|
+
/**
|
|
134
|
+
* Closure factory holding the whole bundle body: receives the synchronous
|
|
135
|
+
* require bound to the module table and returns the bundle's exports. Runs
|
|
136
|
+
* once, at materialization.
|
|
137
|
+
*/
|
|
138
|
+
factory: (require: (spec: string) => unknown) => Record<string, unknown>;
|
|
139
|
+
}
|
|
140
|
+
/** Inputs passed by the web entry when it creates the client module system. */
|
|
141
|
+
export interface ClientModuleCreateOptions {
|
|
142
|
+
/** Raw Host-injected boot graph; the modules bundle owns validation and projection. */
|
|
143
|
+
boot: unknown;
|
|
144
|
+
/** Module-table seed: platform-singleton specifier → shell instance. */
|
|
145
|
+
staticModules: Record<string, unknown>;
|
|
146
|
+
/** Bundle-load hook. Defaults to a same-origin classic `<script src>` element. */
|
|
147
|
+
loadBundle?: (url: string) => Promise<void>;
|
|
148
|
+
}
|
|
149
|
+
/** The modules bundle after its factory has been materialized by the HTML bootstrap facade. */
|
|
150
|
+
export interface ClientBootstrapModule {
|
|
151
|
+
/** Graph/module id carried by the modules bundle registration. */
|
|
152
|
+
id: string;
|
|
153
|
+
/** Materialized exports reused when Cordis later activates the modules entry. */
|
|
154
|
+
exports: Record<string, unknown>;
|
|
155
|
+
}
|
|
156
|
+
/** Stable page-global facade: queues early bundle registrations, then registers them live. */
|
|
157
|
+
export interface ClientModuleLoaderTarget {
|
|
158
|
+
/** Queue before {@link create}; live registration after it returns. */
|
|
159
|
+
mode: 'queue' | 'live';
|
|
160
|
+
/** Registrations submitted by parser-preloaded scripts before the module system exists. */
|
|
161
|
+
pendingQueue: ClientBundleRegistration[];
|
|
162
|
+
/** Queue or immediately register one bundle factory according to {@link mode}. */
|
|
163
|
+
load(registration: ClientBundleRegistration): void;
|
|
164
|
+
/** Create the module system exactly once from the parser-preloaded modules bundle. */
|
|
165
|
+
create(options: ClientModuleCreateOptions): ClientModuleSystem;
|
|
166
|
+
}
|
|
167
|
+
/** Window API of the web boot protocol: the host-injected graph and registration facade. */
|
|
168
|
+
export interface HydraWindow {
|
|
169
|
+
/** Host-composed entry graph, injected before the shell bundle runs; wire-boundary raw until {@link parseBootManifest}. */
|
|
170
|
+
__HYDRA_BOOT__?: unknown;
|
|
171
|
+
/** HTML-installed facade: a pending registration queue, then the live module-system target. */
|
|
172
|
+
__ModuleLoader__?: ClientModuleLoaderTarget;
|
|
173
|
+
}
|
|
174
|
+
/** Per-module bookkeeping in {@link ClientModuleLoader.loadCache} (module-graph boundary, flat today). */
|
|
175
|
+
export interface ClientModuleRecord {
|
|
176
|
+
/** Module id (entry name / package name). */
|
|
177
|
+
id: string;
|
|
178
|
+
/** Materialized exports (`module.exports` from a factory or bootstrap registration). */
|
|
179
|
+
exports: unknown;
|
|
180
|
+
/** Owned `<style data-plugin>` tag ids (`data-plugin-css` values) injected during materialization. */
|
|
181
|
+
styles: string[];
|
|
182
|
+
/** Observed `require()` edges (module-graph boundary; only table words can appear today). */
|
|
183
|
+
edges: Set<string>;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The internal-contract subset the vendored Loader and the client HMR plugin
|
|
187
|
+
* consume. Mounted on `ctx.loader.internal` by the shell boot and provided
|
|
188
|
+
* as `ctx.modules`.
|
|
189
|
+
*/
|
|
190
|
+
export interface ClientModuleLoader {
|
|
191
|
+
/** Discriminant against Node's internal loader shapes ('v1'/'v2'). */
|
|
192
|
+
version: 'client';
|
|
193
|
+
/** Parsed Host boot graph shared with the web entry after module-system creation. */
|
|
194
|
+
manifest: BootManifest;
|
|
195
|
+
/** Materialized-module registry: id → record. The governance-side read API for entry exports. */
|
|
196
|
+
loadCache: Map<string, ClientModuleRecord>;
|
|
197
|
+
/**
|
|
198
|
+
* Internal contract consumed by the vendored Loader's `tree.import`. Resolves
|
|
199
|
+
* `specifier` through the branch order documented on the module, fetching
|
|
200
|
+
* and executing a bundle when needed.
|
|
201
|
+
* @param specifier - module specifier (entry name or table word).
|
|
202
|
+
* @param parentURL - importer URL (unused — the client module graph is flat).
|
|
203
|
+
* @param attrs - Import attributes (unused; interface parity with Node's loader contract).
|
|
204
|
+
* @returns the module's exports.
|
|
205
|
+
*/
|
|
206
|
+
import(specifier: string, parentURL: string, attrs: Record<string, unknown>): Promise<unknown>;
|
|
207
|
+
/**
|
|
208
|
+
* Stage-one arrival: load the entry's declared dynamic requests, then its
|
|
209
|
+
* own script, to register their factories (no materialization — module side
|
|
210
|
+
* effects wait for import).
|
|
211
|
+
* No-op for materialized bootstrap ids. A registered graph row still
|
|
212
|
+
* registers any unresolved declared requests before skipping its own script;
|
|
213
|
+
* concurrent arrivals share one in-flight task. To force a fresh load (HMR),
|
|
214
|
+
* {@link invalidate} first.
|
|
215
|
+
* @param id - graph entry name.
|
|
216
|
+
*/
|
|
217
|
+
prefetch(id: string): Promise<void>;
|
|
218
|
+
/**
|
|
219
|
+
* Full reset of one non-bootstrap module: drop its registered factory and
|
|
220
|
+
* materialized record so the next prefetch/import reloads it (the HMR
|
|
221
|
+
* invalidation hook). The bootstrap module remains materialized.
|
|
222
|
+
* @param id - entry name to invalidate.
|
|
223
|
+
*/
|
|
224
|
+
invalidate(id: string): void;
|
|
225
|
+
}
|
|
226
|
+
/** Internal construction inputs assembled by the modules bundle's bootstrap export. */
|
|
227
|
+
export interface ClientModuleSystemOptions {
|
|
228
|
+
/** Parsed boot graph owned by the resulting module system. */
|
|
229
|
+
manifest: BootManifest;
|
|
230
|
+
/** Module-table seed: platform-singleton specifier → shell instance. */
|
|
231
|
+
staticModules: Record<string, unknown>;
|
|
232
|
+
/** Stable HTML-installed registration facade to switch from queue to live mode. */
|
|
233
|
+
registrationTarget: ClientModuleLoaderTarget;
|
|
234
|
+
/** Already-materialized modules bundle consumed while creating the system. */
|
|
235
|
+
bootstrapModule: ClientBootstrapModule;
|
|
236
|
+
/** Bundle-load hook. Defaults to a same-origin classic `<script src>` element. */
|
|
237
|
+
loadBundle?: (url: string) => Promise<void>;
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { BootManifest, ClientModuleLoader, ClientModuleRecord, ClientModuleSystemOptions } from './manifest.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The client module system: state tables plus the arrival/materialization
|
|
4
|
+
* machinery implementing {@link ClientModuleLoader} (whose members carry the
|
|
5
|
+
* contract documentation). Construction indexes the boot rows, retains the
|
|
6
|
+
* already-materialized bootstrap module, and switches the HTML-installed
|
|
7
|
+
* loader facade from its pending queue to live registration.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ClientModuleSystem implements ClientModuleLoader {
|
|
10
|
+
readonly version = "client";
|
|
11
|
+
readonly manifest: BootManifest;
|
|
12
|
+
readonly loadCache: Map<string, ClientModuleRecord>;
|
|
13
|
+
private readonly seed;
|
|
14
|
+
private readonly factories;
|
|
15
|
+
private readonly bootstrapIds;
|
|
16
|
+
/** In-flight prefetch (script load) per id; concurrent callers share it. */
|
|
17
|
+
private readonly pendingArrival;
|
|
18
|
+
/** Materialization re-entrancy guard: factory-form CJS cannot deliver partial exports, so a cycle is fatal. */
|
|
19
|
+
private readonly materializing;
|
|
20
|
+
private readonly graphRows;
|
|
21
|
+
private readonly loadBundle;
|
|
22
|
+
/**
|
|
23
|
+
* Build the module system over the parsed boot rows.
|
|
24
|
+
* @param options - Parsed graph, platform seed, bootstrap module, registration facade, and transport.
|
|
25
|
+
*/
|
|
26
|
+
constructor(options: ClientModuleSystemOptions);
|
|
27
|
+
/** Register one bundle factory, rejecting a script that executes twice without invalidation. */
|
|
28
|
+
private register;
|
|
29
|
+
/** Load one graph row so its factory is registered (idempotent per in-flight arrival). */
|
|
30
|
+
private arrive;
|
|
31
|
+
/** Register each unresolved dynamic request before registering its consumer. */
|
|
32
|
+
private arriveGraphRow;
|
|
33
|
+
/** Materialize a registered factory (synchronous; memoized in loadCache). */
|
|
34
|
+
private materialize;
|
|
35
|
+
/**
|
|
36
|
+
* The synchronous require answered to factories: seed → memoized record →
|
|
37
|
+
* registered factory. Fetching is async and therefore unreachable
|
|
38
|
+
* from here; an external dynamic package must have arrived before its
|
|
39
|
+
* consumer materializes.
|
|
40
|
+
*/
|
|
41
|
+
private makeRequire;
|
|
42
|
+
import(specifier: string): Promise<unknown>;
|
|
43
|
+
prefetch(id: string): Promise<void>;
|
|
44
|
+
invalidate(id: string): void;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=system.d.ts.map
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node half of the client module system (`hydra.client` dual-face package): scans
|
|
3
|
+
* the host Loader's entries for packages declaring `hydra.client`, composes the
|
|
4
|
+
* `window.__HYDRA_BOOT__` entry graph (wire single source: {@link WebBootEntry}
|
|
5
|
+
* in `./client/manifest.ts`) in module-graph order, serves
|
|
6
|
+
* `/plugins/<id>/client.js` and its source map, contributes the boot manifest
|
|
7
|
+
* plus the parser-blocking bootstrap preloads to the webserver's index
|
|
8
|
+
* injection table, and provides the `clientModuleHost` service (the HMR node
|
|
9
|
+
* half's registration/notification face).
|
|
10
|
+
*
|
|
11
|
+
* Scanning is incremental per package — there is no full-rescan code path.
|
|
12
|
+
* Every cordis `internal/plugin` emission (fiber construction/disposal) marks
|
|
13
|
+
* the fiber's entry name dirty; a microtask flush reconciles each dirty name
|
|
14
|
+
* against the live loader entries. The activation pass seeds the same dirty
|
|
15
|
+
* set with all current entries and flushes synchronously, so first scan and
|
|
16
|
+
* steady state share one implementation. Package metadata (including the
|
|
17
|
+
* negative "not a client package" verdict) is cached per name and never
|
|
18
|
+
* expires — plugin-set changes take effect on restart; bundle content
|
|
19
|
+
* changes reach the graph only through
|
|
20
|
+
* {@link ClientModuleRegistry.rebuilt}.
|
|
21
|
+
* @module @hydraharness/harness-client-modules
|
|
22
|
+
*/
|
|
23
|
+
import { Service } from '@hydraharness/cordis';
|
|
24
|
+
import type { Context } from '@hydraharness/cordis';
|
|
25
|
+
import type { IndexInjection } from '@hydraharness/harness-host-webserver';
|
|
26
|
+
import type { WebBootEntry, WebBootGraph } from './client/manifest.ts';
|
|
27
|
+
export { stripClientSuffix } from './client/manifest.ts';
|
|
28
|
+
export type { BootManifest, BootModuleRow, BootPluginRow, WebBootEntry, WebBootGraph, } from './client/manifest.ts';
|
|
29
|
+
declare module '@hydraharness/cordis' {
|
|
30
|
+
interface Context {
|
|
31
|
+
/** The web plugin table (provided by the client-modules node half). */
|
|
32
|
+
clientModules: ClientModuleRegistry;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Order composed rows so every requested dynamic package precedes its
|
|
37
|
+
* consumers. An `external` specifier is either the package row it names
|
|
38
|
+
* (`<pkg>/client` aliases the bare package) or a static-table name that adds no
|
|
39
|
+
* graph edge.
|
|
40
|
+
* @param entries - composed rows in scan order.
|
|
41
|
+
* @returns the same rows reordered; scan order breaks every tie.
|
|
42
|
+
* @throws {Error} when a row requests itself or when the module graph has a
|
|
43
|
+
* cycle; the message lists the packages on it.
|
|
44
|
+
*/
|
|
45
|
+
export declare function orderByModuleGraph(entries: readonly WebBootEntry[]): WebBootEntry[];
|
|
46
|
+
/**
|
|
47
|
+
* The boot protocol as index injection rows. The inline registration queue
|
|
48
|
+
* precedes blocking classic scripts for modules' and runtime's ordinary
|
|
49
|
+
* `lib/client.js` artifacts. Its `create()` method materializes the modules
|
|
50
|
+
* bundle, delegates construction to that bundle, and leaves the same facade
|
|
51
|
+
* in live-registration mode. The graph global follows before the shell reads
|
|
52
|
+
* it.
|
|
53
|
+
* @param graph - the composed entry graph.
|
|
54
|
+
* @returns head rows in execution order: queue script, preload scripts, graph global.
|
|
55
|
+
*/
|
|
56
|
+
export declare function bootInjections(graph: WebBootGraph): IndexInjection[];
|
|
57
|
+
/**
|
|
58
|
+
* The web plugin table service: incremental `hydra.client` scan + wire composition
|
|
59
|
+
* + bundle route + index injection rows. Construction runs the activation scan
|
|
60
|
+
* synchronously — a malformed declaration or missing bundle among the
|
|
61
|
+
* already-loaded entries aggregates into one loud throw (FAILED fiber; the
|
|
62
|
+
* boot activation audit reports it).
|
|
63
|
+
*/
|
|
64
|
+
export declare class ClientModuleRegistry extends Service {
|
|
65
|
+
static inject: string[];
|
|
66
|
+
private readonly table;
|
|
67
|
+
private readonly pkgMeta;
|
|
68
|
+
private readonly rebuildListeners;
|
|
69
|
+
private readonly graphListeners;
|
|
70
|
+
private readonly dirty;
|
|
71
|
+
private readonly resolvePkgJson;
|
|
72
|
+
private flushQueued;
|
|
73
|
+
private composed;
|
|
74
|
+
/**
|
|
75
|
+
* Build the service: subscribe, seed, and run the activation flush.
|
|
76
|
+
* @param ctx - plugin context carrying webServer and loader.
|
|
77
|
+
*/
|
|
78
|
+
constructor(ctx: Context);
|
|
79
|
+
/**
|
|
80
|
+
* Current composed entry graph (stable object between changes).
|
|
81
|
+
* @returns the graph served as `window.__HYDRA_BOOT__`.
|
|
82
|
+
*/
|
|
83
|
+
graph(): WebBootGraph;
|
|
84
|
+
/**
|
|
85
|
+
* Absolute path of an entry's client bundle.
|
|
86
|
+
* @param id - entry id (package name).
|
|
87
|
+
* @returns the path, or undefined for an unknown id.
|
|
88
|
+
*/
|
|
89
|
+
clientPath(id: string): string | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Re-hash one bundle (the HMR watch's registration hook — the only entry
|
|
92
|
+
* point through which bundle content changes reach the graph).
|
|
93
|
+
* @param id - entry id (package name).
|
|
94
|
+
* @returns the new rev, or undefined for an unknown id.
|
|
95
|
+
*/
|
|
96
|
+
rebuilt(id: string): string | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Subscribe to bundle rebuilds; fires only when the re-hash changed the rev.
|
|
99
|
+
* @param listener - receives the entry id and its new bundle rev.
|
|
100
|
+
* @returns the unsubscriber.
|
|
101
|
+
*/
|
|
102
|
+
onRebuilt(listener: (id: string, rev: string) => void): () => void;
|
|
103
|
+
/**
|
|
104
|
+
* Fires after any flush that recomposed the graph (row added/removed, or a
|
|
105
|
+
* rebuilt rev change). Pull model: listeners re-read {@link graph}.
|
|
106
|
+
* @param listener - notified with no payload.
|
|
107
|
+
* @returns the unsubscriber.
|
|
108
|
+
*/
|
|
109
|
+
onGraphChanged(listener: () => void): () => void;
|
|
110
|
+
private compose;
|
|
111
|
+
private notifyGraphChanged;
|
|
112
|
+
private resolveMeta;
|
|
113
|
+
/**
|
|
114
|
+
* Read the activation-time bundle revision.
|
|
115
|
+
* @param pkgName - package that declares the client bundle.
|
|
116
|
+
* @param clientPath - absolute path of the built client artifact.
|
|
117
|
+
* @returns the bundle content's short hash for use as its revision.
|
|
118
|
+
* @throws {MissingClientBundleError} when the read fails with `ENOENT`; other filesystem errors are rethrown unchanged.
|
|
119
|
+
*/
|
|
120
|
+
private initialBundleRevision;
|
|
121
|
+
/** Reconcile one entry name against the live loader entries. @returns whether the table changed. */
|
|
122
|
+
private processOne;
|
|
123
|
+
private flush;
|
|
124
|
+
private readonly serveBundle;
|
|
125
|
+
}
|
|
126
|
+
export default ClientModuleRegistry;
|
|
127
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned invariant companion for `@hydraharness/harness-client-modules`.
|
|
3
|
+
* @module @hydraharness/harness-client-modules/invariant
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@hydraharness/cordis';
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
export declare const name = "client-modules-invariant";
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Register this package's invariant companion.
|
|
12
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
13
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
14
|
+
*/
|
|
15
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
16
|
+
//# sourceMappingURL=invariant.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hydraharness/harness-client-modules",
|
|
3
|
+
"description": "Client module system, dual-face: node half composes the __HYDRA_BOOT__ entry graph (incremental hydra.client scan, bundle route, index tap, webPlugins service); browser half is the lazy-CJS module table the vendored cordis Loader consumes as its internal seam",
|
|
4
|
+
"version": "0.1.1-rc.6",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/MaiHongPhong1902/Hydra-Harness.git",
|
|
11
|
+
"directory": "packages/client/modules"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/types/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./client": {
|
|
22
|
+
"types": "./lib/types/client/index.d.ts",
|
|
23
|
+
"default": "./lib/client.js"
|
|
24
|
+
},
|
|
25
|
+
"./invariant": {
|
|
26
|
+
"types": "./lib/types/invariant.d.ts",
|
|
27
|
+
"default": "./lib/invariant.js"
|
|
28
|
+
},
|
|
29
|
+
"./src/*": "./src/*",
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"hydra": {
|
|
33
|
+
"plugin": {
|
|
34
|
+
"application": "Load the browser plugins declared by the active profile and serve their built code."
|
|
35
|
+
},
|
|
36
|
+
"client": {
|
|
37
|
+
"platform": "web",
|
|
38
|
+
"inject": [],
|
|
39
|
+
"immediately": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@hydraharness/harness-host-webserver": "^0.1.1-rc.6",
|
|
45
|
+
"@hydraharness/cordis-plugin-loader": "^1.0.3",
|
|
46
|
+
"@hydraharness/harness-invariants": "^0.1.1-rc.6",
|
|
47
|
+
"@hydraharness/cordis": "^4.0.2"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"lib/index.js",
|
|
51
|
+
"lib/invariant.js",
|
|
52
|
+
"lib/client.js",
|
|
53
|
+
"lib/types/**/*.d.ts"
|
|
54
|
+
],
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@hydraharness/cordis": "^4.0.2",
|
|
57
|
+
"@hydraharness/harness-invariants": "^0.1.1-rc.6",
|
|
58
|
+
"@hydraharness/cordis-plugin-loader": "^1.0.3",
|
|
59
|
+
"@hydraharness/harness-host-webserver": "^0.1.1-rc.6"
|
|
60
|
+
},
|
|
61
|
+
"scripts": {
|
|
62
|
+
"bundle": "tsdown",
|
|
63
|
+
"watch": "tsdown --watch"
|
|
64
|
+
}
|
|
65
|
+
}
|