@blac/core 2.0.19 → 2.1.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/StateContainerRegistry-8zNFMAf7.js +1067 -0
- package/dist/StateContainerRegistry-8zNFMAf7.js.map +1 -0
- package/dist/StateContainerRegistry-Bx2ly-ba.cjs +1162 -0
- package/dist/StateContainerRegistry-Bx2ly-ba.cjs.map +1 -0
- package/dist/StateContainerRegistry-C75QpeaO.cjs +1260 -0
- package/dist/StateContainerRegistry-C75QpeaO.cjs.map +1 -0
- package/dist/StateContainerRegistry-CS18y4au.cjs +1163 -0
- package/dist/StateContainerRegistry-CS18y4au.cjs.map +1 -0
- package/dist/StateContainerRegistry-D8nu7Z0T.js +1068 -0
- package/dist/StateContainerRegistry-D8nu7Z0T.js.map +1 -0
- package/dist/StateContainerRegistry-DL5Ai7wh.js +1153 -0
- package/dist/StateContainerRegistry-DL5Ai7wh.js.map +1 -0
- package/dist/StateContainerRegistry-DWOzx7Gd.js +1154 -0
- package/dist/StateContainerRegistry-DWOzx7Gd.js.map +1 -0
- package/dist/StateContainerRegistry-G81GcCRm.cjs +1261 -0
- package/dist/StateContainerRegistry-G81GcCRm.cjs.map +1 -0
- package/dist/acquire-B1LYXSGj.js +35 -0
- package/dist/acquire-B1LYXSGj.js.map +1 -0
- package/dist/acquire-BJ3xUEmh.cjs +46 -0
- package/dist/acquire-BJ3xUEmh.cjs.map +1 -0
- package/dist/acquire-B_p1fNEh.cjs +46 -0
- package/dist/acquire-B_p1fNEh.cjs.map +1 -0
- package/dist/acquire-BdsVZBSe.js +35 -0
- package/dist/acquire-BdsVZBSe.js.map +1 -0
- package/dist/acquire-CE0uq0Dx.cjs +46 -0
- package/dist/acquire-CE0uq0Dx.cjs.map +1 -0
- package/dist/acquire-CU0u8BMn.js +35 -0
- package/dist/acquire-CU0u8BMn.js.map +1 -0
- package/dist/acquire-CkgLJ8WL.cjs +46 -0
- package/dist/acquire-CkgLJ8WL.cjs.map +1 -0
- package/dist/acquire-DTvfYJ0y.js +35 -0
- package/dist/acquire-DTvfYJ0y.js.map +1 -0
- package/dist/config-C1T6Jw7n.cjs +32 -0
- package/dist/config-C1T6Jw7n.cjs.map +1 -0
- package/dist/config-D2A8ZYRM.js +16 -0
- package/dist/config-D2A8ZYRM.js.map +1 -0
- package/dist/config-D34BkraU.cjs +32 -0
- package/dist/config-D34BkraU.cjs.map +1 -0
- package/dist/config-DOO82lbZ.js +16 -0
- package/dist/config-DOO82lbZ.js.map +1 -0
- package/dist/config-DWUq7zEQ.cjs +32 -0
- package/dist/config-DWUq7zEQ.cjs.map +1 -0
- package/dist/config-DXI3kzmA.js +16 -0
- package/dist/config-DXI3kzmA.js.map +1 -0
- package/dist/config-ZVy_yFZ3.js +16 -0
- package/dist/config-ZVy_yFZ3.js.map +1 -0
- package/dist/config-cwaTn5oy.cjs +32 -0
- package/dist/config-cwaTn5oy.cjs.map +1 -0
- package/dist/config.d.cts +7 -3
- package/dist/config.d.ts +7 -3
- package/dist/constants.d.cts +2 -13
- package/dist/constants.d.ts +2 -13
- package/dist/core/StateContainer.d.ts +28 -1
- package/dist/core/StateContainerRegistry.d.ts +72 -2
- package/dist/core/symbols.d.ts +6 -0
- package/dist/debug.cjs +3 -3
- package/dist/debug.js +3 -3
- package/dist/decorators/blac.d.ts +2 -0
- package/dist/ensure-11-asM1e.js +677 -0
- package/dist/ensure-11-asM1e.js.map +1 -0
- package/dist/ensure-B2DYCbbI.cjs +578 -0
- package/dist/ensure-B2DYCbbI.cjs.map +1 -0
- package/dist/ensure-B59ri8oo.js +555 -0
- package/dist/ensure-B59ri8oo.js.map +1 -0
- package/dist/ensure-BEeY5Ab7.js +673 -0
- package/dist/ensure-BEeY5Ab7.js.map +1 -0
- package/dist/ensure-BKdq5xsY.cjs +578 -0
- package/dist/ensure-BKdq5xsY.cjs.map +1 -0
- package/dist/ensure-BSJHkUNX.js +555 -0
- package/dist/ensure-BSJHkUNX.js.map +1 -0
- package/dist/ensure-D3WWWwMo.cjs +714 -0
- package/dist/ensure-D3WWWwMo.cjs.map +1 -0
- package/dist/ensure-r1C_7K6_.cjs +718 -0
- package/dist/ensure-r1C_7K6_.cjs.map +1 -0
- package/dist/events.d.cts +42 -0
- package/dist/events.d.ts +42 -0
- package/dist/index.cjs +61 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +56 -8
- package/dist/index.js.map +1 -1
- package/dist/management-8x1OVMi6.js +38 -0
- package/dist/management-8x1OVMi6.js.map +1 -0
- package/dist/management-BZgsi29F.js +38 -0
- package/dist/management-BZgsi29F.js.map +1 -0
- package/dist/management-C-WGcwPD.js +38 -0
- package/dist/management-C-WGcwPD.js.map +1 -0
- package/dist/management-Dg2SxUb6.cjs +85 -0
- package/dist/management-Dg2SxUb6.cjs.map +1 -0
- package/dist/management-P_Vi_cvw.js +38 -0
- package/dist/management-P_Vi_cvw.js.map +1 -0
- package/dist/management-QWLpbXlW.cjs +85 -0
- package/dist/management-QWLpbXlW.cjs.map +1 -0
- package/dist/management-hkY13log.cjs +85 -0
- package/dist/management-hkY13log.cjs.map +1 -0
- package/dist/management-iE4x6IQY.cjs +85 -0
- package/dist/management-iE4x6IQY.cjs.map +1 -0
- package/dist/plugin/PluginManager.d.ts +11 -0
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/release.d.ts +17 -1
- package/dist/testing.cjs +4 -4
- package/dist/testing.js +4 -4
- package/dist/utils/idGenerator.d.ts +0 -36
- package/dist/utils/static-props.d.ts +5 -0
- package/dist/utils/structural-key.d.ts +11 -1
- package/dist/watch/index.d.ts +1 -0
- package/dist/watch/observe.d.ts +13 -0
- package/dist/watch-B0pUfh-v.cjs +119 -0
- package/dist/watch-B0pUfh-v.cjs.map +1 -0
- package/dist/watch-BDiwCPmb.js +108 -0
- package/dist/watch-BDiwCPmb.js.map +1 -0
- package/dist/watch-BW7gYiDf.js +108 -0
- package/dist/watch-BW7gYiDf.js.map +1 -0
- package/dist/watch-Bx0y-Kcc.js +108 -0
- package/dist/watch-Bx0y-Kcc.js.map +1 -0
- package/dist/watch-DttHqefn.js +108 -0
- package/dist/watch-DttHqefn.js.map +1 -0
- package/dist/watch-DxdIZjpt.cjs +119 -0
- package/dist/watch-DxdIZjpt.cjs.map +1 -0
- package/dist/watch-aoNLQAXp.cjs +119 -0
- package/dist/watch-aoNLQAXp.cjs.map +1 -0
- package/dist/watch-entry.cjs +1 -1
- package/dist/watch-entry.js +1 -1
- package/dist/watch-lEco5Tbl.cjs +119 -0
- package/dist/watch-lEco5Tbl.cjs.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,718 @@
|
|
|
1
|
+
const require_StateContainerRegistry = require("./StateContainerRegistry-G81GcCRm.cjs");
|
|
2
|
+
const require_config = require("./config-C1T6Jw7n.cjs");
|
|
3
|
+
let _dirtytalk_structural = require("@dirtytalk/structural");
|
|
4
|
+
//#region src/utils/idGenerator.ts
|
|
5
|
+
/**
|
|
6
|
+
* Centralized ID Generation
|
|
7
|
+
*
|
|
8
|
+
* Provides consistent, collision-resistant ID generation for all BlaC subsystems.
|
|
9
|
+
* Uses timestamp + counter + random suffix for uniqueness.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Generate simple ID with timestamp and random (no counter tracking)
|
|
13
|
+
*
|
|
14
|
+
* Format: `${prefix}:${timestamp}_${random}`
|
|
15
|
+
*
|
|
16
|
+
* @param prefix - Prefix for the ID
|
|
17
|
+
* @returns Branded ID string
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const id = generateSimpleId('CounterBloc');
|
|
22
|
+
* // Returns: "CounterBloc:1698765432100_a3k9d7f2q"
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function generateSimpleId(prefix, affix) {
|
|
26
|
+
if (affix) return `${prefix}:${affix}`;
|
|
27
|
+
return `${prefix}:${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/events.ts
|
|
31
|
+
/**
|
|
32
|
+
* Subscriber storage, keyed by REGISTRY INSTANCE rather than a field on
|
|
33
|
+
* `StateContainerRegistry`. This gives registry-swap isolation (a test's
|
|
34
|
+
* `withTestRegistry`/`blacTestSetup` scope gets an independent subscriber
|
|
35
|
+
* set) for free, through machinery that already exists, with zero new
|
|
36
|
+
* public surface on `StateContainerRegistry`.
|
|
37
|
+
*/
|
|
38
|
+
const busByRegistry = /* @__PURE__ */ new WeakMap();
|
|
39
|
+
function defineEvent(name) {
|
|
40
|
+
return { name };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @internal Bus scoped to an explicit registry — used by `StateContainer#on`
|
|
44
|
+
* so a container always listens on the bus of the registry it belongs to,
|
|
45
|
+
* not the ambient one. Not part of the public API.
|
|
46
|
+
*/
|
|
47
|
+
function onEventFor(registry, token, handler) {
|
|
48
|
+
let bus = busByRegistry.get(registry);
|
|
49
|
+
if (!bus) {
|
|
50
|
+
bus = /* @__PURE__ */ new Map();
|
|
51
|
+
busByRegistry.set(registry, bus);
|
|
52
|
+
}
|
|
53
|
+
let handlers = bus.get(token);
|
|
54
|
+
if (!handlers) {
|
|
55
|
+
handlers = /* @__PURE__ */ new Set();
|
|
56
|
+
bus.set(token, handlers);
|
|
57
|
+
}
|
|
58
|
+
handlers.add(handler);
|
|
59
|
+
const tokenMap = bus;
|
|
60
|
+
const handlerSet = handlers;
|
|
61
|
+
let removed = false;
|
|
62
|
+
return () => {
|
|
63
|
+
if (removed) return;
|
|
64
|
+
removed = true;
|
|
65
|
+
handlerSet.delete(handler);
|
|
66
|
+
if (handlerSet.size === 0) tokenMap.delete(token);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Subscribe on the ambient registry (`getRegistry()`). */
|
|
70
|
+
function onEvent(token, handler) {
|
|
71
|
+
return onEventFor(require_config.getRegistry(), token, handler);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Dispatch `token` to every current subscriber on the ambient registry, in
|
|
75
|
+
* registration order.
|
|
76
|
+
*
|
|
77
|
+
* Cost is O(subscribers for this token) — a token with no subscribers (or no
|
|
78
|
+
* bus yet on this registry) returns immediately, never touching live
|
|
79
|
+
* instances.
|
|
80
|
+
*
|
|
81
|
+
* Dispatch iterates a SNAPSHOT of the handler `Set`, so it is safe for a
|
|
82
|
+
* handler to synchronously call `emitEvent`/`onEvent` re-entrantly: a nested
|
|
83
|
+
* `emitEvent` for the same token completes against its own snapshot, and a
|
|
84
|
+
* handler registered via `onEvent` during dispatch is NOT invoked for the
|
|
85
|
+
* in-flight emit (it only sees emits that start after it subscribed).
|
|
86
|
+
*
|
|
87
|
+
* The variadic tuple means a `void`-payload token needs no second argument,
|
|
88
|
+
* and a typed-payload token requires one. It wraps both sides in a tuple
|
|
89
|
+
* (`[P] extends [void]`, not `void extends P`) because the naive form is true
|
|
90
|
+
* for every `P` that `void` is assignable to — `unknown`, `any`, `number |
|
|
91
|
+
* void` — which collapsed the tuple to `[]` and made their payload
|
|
92
|
+
* un-passable. `any` is special-cased first so it accepts either form.
|
|
93
|
+
*/
|
|
94
|
+
function emitEvent(token, ...payload) {
|
|
95
|
+
const handlers = busByRegistry.get(require_config.getRegistry())?.get(token);
|
|
96
|
+
if (!handlers) return;
|
|
97
|
+
const value = payload[0];
|
|
98
|
+
for (const handler of Array.from(handlers)) try {
|
|
99
|
+
handler(value);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error(`${require_StateContainerRegistry.BLAC_ERROR_PREFIX} event handler error for '${token.name}':`, error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/core/meta.ts
|
|
106
|
+
/**
|
|
107
|
+
* Non-enumerable brand carried on every `$blac` object produced by
|
|
108
|
+
* {@link createMeta}. Used by the clobber guard in `StateContainer` to detect
|
|
109
|
+
* a subclass class-field shadowing the base's own `$blac` property, and by the
|
|
110
|
+
* meta tests. Intentionally NOT re-exported from the package barrel.
|
|
111
|
+
*/
|
|
112
|
+
const META_BRAND = Symbol("blac.meta");
|
|
113
|
+
const EMPTY_DEPS = /* @__PURE__ */ new Map();
|
|
114
|
+
/**
|
|
115
|
+
* Build the frozen, branded `$blac` meta object for a container.
|
|
116
|
+
*
|
|
117
|
+
* Called from a `StateContainer` field initializer (`$blac = createMeta(this)`).
|
|
118
|
+
* Only the back-reference is captured at this point; every getter/method reads
|
|
119
|
+
* the container's `_`-private fields lazily on access, so field-initializer
|
|
120
|
+
* ordering relative to those private fields is irrelevant.
|
|
121
|
+
*
|
|
122
|
+
* The getters close over `container` (the real instance), never over a
|
|
123
|
+
* `this`-receiver — this is what keeps `$blac` reads safe through
|
|
124
|
+
* `buildTrackedProxy`.
|
|
125
|
+
*/
|
|
126
|
+
function createMeta(container) {
|
|
127
|
+
const c = container;
|
|
128
|
+
const meta = {
|
|
129
|
+
get name() {
|
|
130
|
+
return c._name;
|
|
131
|
+
},
|
|
132
|
+
get id() {
|
|
133
|
+
return c._instanceId;
|
|
134
|
+
},
|
|
135
|
+
get debug() {
|
|
136
|
+
return c._debug;
|
|
137
|
+
},
|
|
138
|
+
get createdAt() {
|
|
139
|
+
return c._createdAt;
|
|
140
|
+
},
|
|
141
|
+
get disposed() {
|
|
142
|
+
return c._disposed;
|
|
143
|
+
},
|
|
144
|
+
get dependencies() {
|
|
145
|
+
return c._dependencies ?? EMPTY_DEPS;
|
|
146
|
+
},
|
|
147
|
+
hydration: Object.freeze({
|
|
148
|
+
get status() {
|
|
149
|
+
return c._hydrationStatus;
|
|
150
|
+
},
|
|
151
|
+
get error() {
|
|
152
|
+
return c._hydrationError;
|
|
153
|
+
},
|
|
154
|
+
get isHydrated() {
|
|
155
|
+
return c._hydrationStatus === "hydrated";
|
|
156
|
+
},
|
|
157
|
+
get changedWhileHydrating() {
|
|
158
|
+
return c._changedWhileHydrating;
|
|
159
|
+
},
|
|
160
|
+
begin() {
|
|
161
|
+
c._beginHydration();
|
|
162
|
+
},
|
|
163
|
+
apply(next) {
|
|
164
|
+
return c._applyHydratedState(next);
|
|
165
|
+
},
|
|
166
|
+
finish() {
|
|
167
|
+
c._finishHydration();
|
|
168
|
+
},
|
|
169
|
+
fail(error) {
|
|
170
|
+
c._failHydration(error);
|
|
171
|
+
},
|
|
172
|
+
wait() {
|
|
173
|
+
return c._waitForHydration();
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
};
|
|
177
|
+
Object.defineProperty(meta, META_BRAND, {
|
|
178
|
+
value: true,
|
|
179
|
+
enumerable: false,
|
|
180
|
+
writable: false,
|
|
181
|
+
configurable: false
|
|
182
|
+
});
|
|
183
|
+
return Object.freeze(meta);
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region src/core/StateContainer.ts
|
|
187
|
+
/**
|
|
188
|
+
* Brand symbol carried (non-enumerable) on every handle returned by
|
|
189
|
+
* `depend()`. Framework adapters (`@blac/react`) use this to detect handles
|
|
190
|
+
* inside a tracked-proxy and swap in a session-bound wrapper.
|
|
191
|
+
*
|
|
192
|
+
* @internal — exported for `@blac/react`; not part of the public API.
|
|
193
|
+
*/
|
|
194
|
+
const DEP_BRAND = Symbol("blac.depHandle");
|
|
195
|
+
/**
|
|
196
|
+
* Shallow per-key `Object.is` comparison of two plain records. Keys are
|
|
197
|
+
* considered: a key present in one but not the other (regardless of value)
|
|
198
|
+
* makes the records unequal. Used to detect real deps changes.
|
|
199
|
+
*/
|
|
200
|
+
function shallowEqualRecord(a, b) {
|
|
201
|
+
if (a === b) return true;
|
|
202
|
+
const aKeys = Object.keys(a);
|
|
203
|
+
if (aKeys.length !== Object.keys(b).length) return false;
|
|
204
|
+
for (const key of aKeys) {
|
|
205
|
+
if (!(key in b)) return false;
|
|
206
|
+
if (!Object.is(a[key], b[key])) return false;
|
|
207
|
+
}
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* BlaC's lifecycle/identity/dependency layer on top of `StructuralContainer`.
|
|
212
|
+
*
|
|
213
|
+
* StructuralContainer provides:
|
|
214
|
+
* - `state` getter
|
|
215
|
+
* - `emit` / `patch` / `update` (path-tracked, microtask-flushed)
|
|
216
|
+
* - `channel` (the underlying `DirtyChannel`)
|
|
217
|
+
* - `registerConsumerPaths` / `unregisterConsumer` (for fine-grained consumers)
|
|
218
|
+
* - per-class `PathInterner`
|
|
219
|
+
*
|
|
220
|
+
* StateContainer layers on:
|
|
221
|
+
* - identity / lifecycle / hydration (exposed via `$blac: BlacMeta`)
|
|
222
|
+
* - cross-bloc deps (`depend()`, `$blac.dependencies`)
|
|
223
|
+
* - per-consumer deps slices (`APPLY_DEPS` / `REMOVE_DEPS_OWNER` / `onDepsChanged`)
|
|
224
|
+
* - registry integration (config-driven equality, emit-rate circuit breaker)
|
|
225
|
+
*
|
|
226
|
+
* Subscribers can attach via:
|
|
227
|
+
* - `onSystemEvent('stateChanged' | 'dispose' | 'hydrationChanged', cb)` —
|
|
228
|
+
* coarse lifecycle events.
|
|
229
|
+
* - `this.channel.subscribe(interest, cb)` — path-scoped.
|
|
230
|
+
*/
|
|
231
|
+
var StateContainer = class extends _dirtytalk_structural.StructuralContainer {
|
|
232
|
+
static {
|
|
233
|
+
this.__excludeFromDevTools = false;
|
|
234
|
+
}
|
|
235
|
+
get deps() {
|
|
236
|
+
return this._deps;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* @internal Apply one owner's (consumer's) deps slice. Shallow-merges the
|
|
240
|
+
* slice, reconciles keys the owner dropped since its last apply (other
|
|
241
|
+
* owners' keys untouched), dev-warns on cross-owner key collisions, then
|
|
242
|
+
* recomputes the merged view and fires onDepsChanged if it changed.
|
|
243
|
+
*
|
|
244
|
+
* Idempotent: re-applying an identical slice for the same owner is a no-op.
|
|
245
|
+
*/
|
|
246
|
+
[require_StateContainerRegistry.APPLY_DEPS](ownerId, slice) {
|
|
247
|
+
if (this._disposed) return;
|
|
248
|
+
const owners = this._depsByOwner ??= /* @__PURE__ */ new Map();
|
|
249
|
+
const prevSlice = owners.get(ownerId);
|
|
250
|
+
if (prevSlice && shallowEqualRecord(prevSlice, slice)) return;
|
|
251
|
+
if (process.env.NODE_ENV !== "production") for (const key of Object.keys(slice)) for (const [otherOwner, otherSlice] of owners) {
|
|
252
|
+
if (otherOwner === ownerId) continue;
|
|
253
|
+
if (key in otherSlice && otherSlice[key] !== slice[key]) console.warn(`[${this._name}] multiple owners writing dep \`${String(key)}\`; last write wins`);
|
|
254
|
+
}
|
|
255
|
+
owners.set(ownerId, { ...slice });
|
|
256
|
+
this.reconcileDeps();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* @internal Withdraw an owner's entire deps slice (consumer unmounted).
|
|
260
|
+
*/
|
|
261
|
+
[require_StateContainerRegistry.REMOVE_DEPS_OWNER](ownerId) {
|
|
262
|
+
if (this._disposed) return;
|
|
263
|
+
if (!this._depsByOwner?.delete(ownerId)) return;
|
|
264
|
+
this.reconcileDeps();
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* @internal Subscribe to this instance's own disposal. Delegates to the
|
|
268
|
+
* per-instance `'dispose'` system event — used by `watch()` in place of
|
|
269
|
+
* filtering the global registry `'disposed'` event.
|
|
270
|
+
*/
|
|
271
|
+
[require_StateContainerRegistry.ON_DISPOSE](handler) {
|
|
272
|
+
return this.onSystemEvent("dispose", handler);
|
|
273
|
+
}
|
|
274
|
+
reconcileDeps() {
|
|
275
|
+
const prev = this._deps;
|
|
276
|
+
const next = {};
|
|
277
|
+
if (this._depsByOwner) for (const slice of this._depsByOwner.values()) Object.assign(next, slice);
|
|
278
|
+
for (const key of Object.keys(prev)) if (!(key in next)) next[key] = void 0;
|
|
279
|
+
if (shallowEqualRecord(prev, next)) return;
|
|
280
|
+
this._deps = next;
|
|
281
|
+
this.onDepsChanged(next, prev);
|
|
282
|
+
this._registry.emit("depsChanged", this, prev, next);
|
|
283
|
+
}
|
|
284
|
+
onDepsChanged(_next, _prev) {}
|
|
285
|
+
get args() {
|
|
286
|
+
return this._config.args;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Declare a cross-bloc dependency. Returns a branded handle with two
|
|
290
|
+
* accessors — the dep instance is resolved against the registry on each call,
|
|
291
|
+
* which keeps the surface immune to dep-instance churn:
|
|
292
|
+
*
|
|
293
|
+
* - `handle.track(options?)` — reactive read. Returns `[state, instance]`.
|
|
294
|
+
* Inside a getter reached through the React proxy this subscribes the
|
|
295
|
+
* reading component to the dep's changes (base impl: live, no subscription).
|
|
296
|
+
* - `handle.untracked(options?)` — returns the live instance with no tracking,
|
|
297
|
+
* for imperative method calls and one-off reads.
|
|
298
|
+
*
|
|
299
|
+
* `defaultArgs` resolves the dep instance when an accessor is called without
|
|
300
|
+
* its own `args`; per-call `options.args` overrides it and can derive from
|
|
301
|
+
* current state. This does NOT auto-resubscribe outside the React proxy;
|
|
302
|
+
* non-React consumers needing updates should subscribe explicitly.
|
|
303
|
+
*/
|
|
304
|
+
depend(Type, defaultArgs) {
|
|
305
|
+
if (!this._dependencies) this._dependencies = /* @__PURE__ */ new Map();
|
|
306
|
+
this._dependencies.set(Type, this._registry.resolveKey(Type, void 0, defaultArgs));
|
|
307
|
+
const resolve = (args) => {
|
|
308
|
+
const effectiveArgs = args ?? defaultArgs;
|
|
309
|
+
const key = this._registry.resolveKey(Type, void 0, effectiveArgs);
|
|
310
|
+
const edges = this._depEdges ??= /* @__PURE__ */ new Map();
|
|
311
|
+
let resolvedKeys = edges.get(Type);
|
|
312
|
+
if (resolvedKeys === void 0) {
|
|
313
|
+
resolvedKeys = /* @__PURE__ */ new Set();
|
|
314
|
+
edges.set(Type, resolvedKeys);
|
|
315
|
+
}
|
|
316
|
+
resolvedKeys.add(key);
|
|
317
|
+
return this._registry.acquire(Type, key, {
|
|
318
|
+
canCreate: true,
|
|
319
|
+
countRef: false,
|
|
320
|
+
args: effectiveArgs,
|
|
321
|
+
dependent: this
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
const handle = {
|
|
325
|
+
track: (options) => {
|
|
326
|
+
const instance = resolve(options?.args);
|
|
327
|
+
return [instance.state, instance];
|
|
328
|
+
},
|
|
329
|
+
untracked: (options) => resolve(options?.args)
|
|
330
|
+
};
|
|
331
|
+
Object.defineProperty(handle, DEP_BRAND, {
|
|
332
|
+
value: {
|
|
333
|
+
Type,
|
|
334
|
+
defaultArgs
|
|
335
|
+
},
|
|
336
|
+
enumerable: false,
|
|
337
|
+
writable: false,
|
|
338
|
+
configurable: false
|
|
339
|
+
});
|
|
340
|
+
return handle;
|
|
341
|
+
}
|
|
342
|
+
constructor(initialState, options) {
|
|
343
|
+
super(initialState, options);
|
|
344
|
+
this._depsByOwner = null;
|
|
345
|
+
this._deps = {};
|
|
346
|
+
this._disposed = false;
|
|
347
|
+
this._hydrationStatus = "idle";
|
|
348
|
+
this._changedWhileHydrating = false;
|
|
349
|
+
this._hydrationPromise = null;
|
|
350
|
+
this._hydrationPromiseSettled = false;
|
|
351
|
+
this._config = {};
|
|
352
|
+
this._initCalled = false;
|
|
353
|
+
this._emitWindowStart = 0;
|
|
354
|
+
this._emitCount = 0;
|
|
355
|
+
this._emitRateWarned = false;
|
|
356
|
+
this._systemEventHandlers = /* @__PURE__ */ new Map();
|
|
357
|
+
this._dependencies = null;
|
|
358
|
+
this._depEdges = null;
|
|
359
|
+
this._pendingChange = null;
|
|
360
|
+
this._bridgeUnsub = null;
|
|
361
|
+
this._registry = require_config.getRegistry();
|
|
362
|
+
this._equalityFn = require_StateContainerRegistry.getBlacConfig().equality;
|
|
363
|
+
this._name = this.constructor.name;
|
|
364
|
+
this._debug = false;
|
|
365
|
+
this._instanceId = generateSimpleId(this.constructor.name, "main");
|
|
366
|
+
this._createdAt = Date.now();
|
|
367
|
+
this.$blac = createMeta(this);
|
|
368
|
+
this.onSystemEvent = (event, handler) => {
|
|
369
|
+
let handlers = this._systemEventHandlers.get(event);
|
|
370
|
+
if (!handlers) {
|
|
371
|
+
handlers = /* @__PURE__ */ new Set();
|
|
372
|
+
this._systemEventHandlers.set(event, handlers);
|
|
373
|
+
}
|
|
374
|
+
const wasFirst = event === "stateChanged" && handlers.size === 0;
|
|
375
|
+
handlers.add(handler);
|
|
376
|
+
if (wasFirst) this._subscribeBridge();
|
|
377
|
+
let removed = false;
|
|
378
|
+
return () => {
|
|
379
|
+
if (removed) return;
|
|
380
|
+
removed = true;
|
|
381
|
+
handlers?.delete(handler);
|
|
382
|
+
if (event === "stateChanged" && (!handlers || handlers.size === 0)) {
|
|
383
|
+
this._bridgeUnsub?.();
|
|
384
|
+
this._bridgeUnsub = null;
|
|
385
|
+
this._pendingChange = null;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
this.on = (token, handler) => {
|
|
390
|
+
if (this._disposed) return () => {};
|
|
391
|
+
const unsub = onEventFor(this._registry, token, handler);
|
|
392
|
+
this.onSystemEvent("dispose", unsub);
|
|
393
|
+
return unsub;
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* @internal Subscribe the channel bridge that turns flushes into
|
|
398
|
+
* 'stateChanged' system events. Interest is ALL_PATHS so we wake on every
|
|
399
|
+
* flush. Coalesced via `_pendingChange`: if no emit happened (e.g. a no-op
|
|
400
|
+
* patch), the bridge sees null and skips. Lazy: only subscribed while at
|
|
401
|
+
* least one 'stateChanged' handler exists.
|
|
402
|
+
*/
|
|
403
|
+
_subscribeBridge() {
|
|
404
|
+
if (this._bridgeUnsub) return;
|
|
405
|
+
this._bridgeUnsub = this.channel.subscribe(() => _dirtytalk_structural.ALL_PATHS, () => this._drainPending());
|
|
406
|
+
}
|
|
407
|
+
_hasStateChangedHandlers() {
|
|
408
|
+
const handlers = this._systemEventHandlers.get("stateChanged");
|
|
409
|
+
return !!handlers && handlers.size > 0;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Called once after construction with the args passed at acquire time, before the first
|
|
413
|
+
* state snapshot is read by any consumer. Override to seed args-derived state (via
|
|
414
|
+
* this.emit(...)) or kick off loads.
|
|
415
|
+
*/
|
|
416
|
+
init(_args) {}
|
|
417
|
+
/**
|
|
418
|
+
* @internal Framework-only configuration entry point (registry + testing
|
|
419
|
+
* helpers). Writes the `_`-private identity fields directly, resolves
|
|
420
|
+
* per-class equality, emits the registry `created` event, and runs `init()`
|
|
421
|
+
* once. See {@link INIT_CONFIG}.
|
|
422
|
+
*/
|
|
423
|
+
[require_StateContainerRegistry.INIT_CONFIG](config) {
|
|
424
|
+
this._config = { ...config };
|
|
425
|
+
this._name = this._config.name || this.constructor.name;
|
|
426
|
+
this._debug = this._config.debug ?? false;
|
|
427
|
+
this._instanceId = generateSimpleId(this.constructor.name, this._config.instanceId);
|
|
428
|
+
const perClass = require_StateContainerRegistry.getClassEquality(this.constructor);
|
|
429
|
+
this._equalityFn = perClass ?? require_StateContainerRegistry.getBlacConfig().equality;
|
|
430
|
+
this._registry.emit("created", this);
|
|
431
|
+
if (!this._initCalled) {
|
|
432
|
+
this._initCalled = true;
|
|
433
|
+
this.init(this._config.args);
|
|
434
|
+
}
|
|
435
|
+
if (process.env.NODE_ENV !== "production") {
|
|
436
|
+
if (!this.$blac?.[META_BRAND]) console.warn(`[blac] ${this.constructor.name} appears to declare its own \`$blac\` member, which shadows the reserved meta namespace. \`$blac\` is reserved by StateContainer — remove the subclass field.`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
dispose() {
|
|
440
|
+
if (this._disposed) return;
|
|
441
|
+
if (this._debug) console.log(`[${this._name}] Disposing...`);
|
|
442
|
+
if (this._depsByOwner) {
|
|
443
|
+
this._depsByOwner.clear();
|
|
444
|
+
this.reconcileDeps();
|
|
445
|
+
}
|
|
446
|
+
this._disposed = true;
|
|
447
|
+
if (this._hydrationStatus === "hydrating") this._failHydration(/* @__PURE__ */ new Error(`Hydration cancelled because ${this._name} was disposed`));
|
|
448
|
+
this.emitSystemEvent("dispose", void 0);
|
|
449
|
+
this._bridgeUnsub?.();
|
|
450
|
+
this._bridgeUnsub = null;
|
|
451
|
+
this._systemEventHandlers.clear();
|
|
452
|
+
this._pendingChange = null;
|
|
453
|
+
this._registry.emit("disposed", this);
|
|
454
|
+
if (this._debug) console.log(`[${this._name}] Disposed successfully`);
|
|
455
|
+
super.dispose();
|
|
456
|
+
}
|
|
457
|
+
emit(next) {
|
|
458
|
+
this.applyState(next, "default");
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Override of `StructuralContainer.patch` that routes through the
|
|
462
|
+
* StateContainer concerns: disposed guard, dev-only emit-rate check,
|
|
463
|
+
* `_changedWhileHydrating` flag, pending-change capture (so `stateChanged`
|
|
464
|
+
* system events see the merged prev/next), and the registry-level
|
|
465
|
+
* `stateChanged` notification. We still call
|
|
466
|
+
* `super.patch` so path-marking semantics (the whole point of patch) are
|
|
467
|
+
* preserved.
|
|
468
|
+
*/
|
|
469
|
+
patch(partial) {
|
|
470
|
+
if (this._disposed) throw new Error(`Cannot emit state from disposed container ${this._name}`);
|
|
471
|
+
const prev = this.state;
|
|
472
|
+
let hasKeys = false;
|
|
473
|
+
let allEqual = true;
|
|
474
|
+
for (const key in partial) {
|
|
475
|
+
hasKeys = true;
|
|
476
|
+
if (!Object.is(prev[key], partial[key])) {
|
|
477
|
+
allEqual = false;
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (!hasKeys) return;
|
|
482
|
+
if (allEqual) return;
|
|
483
|
+
if (process.env.NODE_ENV !== "production") this._checkEmitRate();
|
|
484
|
+
super.patch(partial);
|
|
485
|
+
const next = this.state;
|
|
486
|
+
if (Object.is(prev, next)) return;
|
|
487
|
+
if (this._hydrationStatus === "hydrating") this._changedWhileHydrating = true;
|
|
488
|
+
if (this._hasStateChangedHandlers()) if (this._pendingChange) this._pendingChange.next = next;
|
|
489
|
+
else this._pendingChange = {
|
|
490
|
+
prev,
|
|
491
|
+
next
|
|
492
|
+
};
|
|
493
|
+
if (this._registry.hasStateChangedListeners) this._registry.notifyStateChanged(this, prev, next);
|
|
494
|
+
}
|
|
495
|
+
applyState(next, source) {
|
|
496
|
+
if (this._disposed) throw new Error(`Cannot emit state from disposed container ${this._name}`);
|
|
497
|
+
const prev = this.state;
|
|
498
|
+
if (prev === next) return;
|
|
499
|
+
if (this._equalityFn(prev, next)) return;
|
|
500
|
+
if (process.env.NODE_ENV !== "production") this._checkEmitRate();
|
|
501
|
+
if (this._hydrationStatus === "hydrating" && source !== "hydration") this._changedWhileHydrating = true;
|
|
502
|
+
if (this._hasStateChangedHandlers()) if (this._pendingChange) this._pendingChange.next = next;
|
|
503
|
+
else this._pendingChange = {
|
|
504
|
+
prev,
|
|
505
|
+
next
|
|
506
|
+
};
|
|
507
|
+
super.emit(next);
|
|
508
|
+
if (this._registry.hasStateChangedListeners) this._registry.notifyStateChanged(this, prev, next);
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Called by the channel-bridge subscriber on each flush. Drains the
|
|
512
|
+
* pending change (if any) into the 'stateChanged' system event.
|
|
513
|
+
* No pending change == flush from a no-op patch == skip.
|
|
514
|
+
*/
|
|
515
|
+
_drainPending() {
|
|
516
|
+
const pending = this._pendingChange;
|
|
517
|
+
if (!pending) return;
|
|
518
|
+
this._pendingChange = null;
|
|
519
|
+
const handlers = this._systemEventHandlers.get("stateChanged");
|
|
520
|
+
if (handlers && handlers.size > 0) {
|
|
521
|
+
const payload = {
|
|
522
|
+
state: pending.next,
|
|
523
|
+
previousState: pending.prev
|
|
524
|
+
};
|
|
525
|
+
let count = 0;
|
|
526
|
+
const size = handlers.size;
|
|
527
|
+
for (const handler of handlers) {
|
|
528
|
+
if (++count > size) break;
|
|
529
|
+
try {
|
|
530
|
+
handler(payload);
|
|
531
|
+
} catch (error) {
|
|
532
|
+
console.error(`[${this._name}] Error in system event handler:`, error);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
_beginHydration() {
|
|
538
|
+
if (this._disposed) throw new Error(`Cannot begin hydration for disposed container ${this._name}`);
|
|
539
|
+
this._changedWhileHydrating = false;
|
|
540
|
+
this._hydrationError = void 0;
|
|
541
|
+
this._hydrationPromise = null;
|
|
542
|
+
this._resolveHydrationPromise = void 0;
|
|
543
|
+
this._rejectHydrationPromise = void 0;
|
|
544
|
+
this._hydrationPromiseSettled = false;
|
|
545
|
+
this.ensureHydrationPromise();
|
|
546
|
+
this.setHydrationStatus("hydrating");
|
|
547
|
+
}
|
|
548
|
+
_applyHydratedState(next) {
|
|
549
|
+
if (this._disposed) return false;
|
|
550
|
+
if (this._hydrationStatus !== "hydrating" || this._changedWhileHydrating) return false;
|
|
551
|
+
this.applyState(next, "hydration");
|
|
552
|
+
return true;
|
|
553
|
+
}
|
|
554
|
+
_finishHydration() {
|
|
555
|
+
if (this._hydrationStatus !== "hydrating") {
|
|
556
|
+
if (this._hydrationStatus === "hydrated") return;
|
|
557
|
+
if (this._hydrationStatus === "error") this.ensureHydrationPromise();
|
|
558
|
+
}
|
|
559
|
+
this.setHydrationStatus("hydrated");
|
|
560
|
+
this.resolveHydration();
|
|
561
|
+
}
|
|
562
|
+
_failHydration(error) {
|
|
563
|
+
const err = error instanceof Error ? error : /* @__PURE__ */ new Error(`Hydration failed: ${String(error)}`);
|
|
564
|
+
this._hydrationError = err;
|
|
565
|
+
this.setHydrationStatus("error", err);
|
|
566
|
+
this.rejectHydration(err);
|
|
567
|
+
}
|
|
568
|
+
_waitForHydration() {
|
|
569
|
+
if (this._hydrationStatus === "idle" || this._hydrationStatus === "hydrated") return Promise.resolve();
|
|
570
|
+
if (this._hydrationStatus === "error") return Promise.reject(this._hydrationError ?? /* @__PURE__ */ new Error(`Hydration failed for container ${this._name}`));
|
|
571
|
+
return this.ensureHydrationPromise();
|
|
572
|
+
}
|
|
573
|
+
setHydrationStatus(status, error) {
|
|
574
|
+
const previousStatus = this._hydrationStatus;
|
|
575
|
+
this._hydrationStatus = status;
|
|
576
|
+
this._hydrationError = error;
|
|
577
|
+
this.emitSystemEvent("hydrationChanged", {
|
|
578
|
+
status,
|
|
579
|
+
previousStatus,
|
|
580
|
+
error,
|
|
581
|
+
changedWhileHydrating: this._changedWhileHydrating
|
|
582
|
+
});
|
|
583
|
+
this._registry.emit("hydrationChanged", this, status, previousStatus);
|
|
584
|
+
}
|
|
585
|
+
ensureHydrationPromise() {
|
|
586
|
+
if (!this._hydrationPromise || this._hydrationPromiseSettled) {
|
|
587
|
+
this._hydrationPromiseSettled = false;
|
|
588
|
+
this._hydrationPromise = new Promise((resolve, reject) => {
|
|
589
|
+
this._resolveHydrationPromise = () => {
|
|
590
|
+
if (this._hydrationPromiseSettled) return;
|
|
591
|
+
this._hydrationPromiseSettled = true;
|
|
592
|
+
resolve();
|
|
593
|
+
};
|
|
594
|
+
this._rejectHydrationPromise = (error) => {
|
|
595
|
+
if (this._hydrationPromiseSettled) return;
|
|
596
|
+
this._hydrationPromiseSettled = true;
|
|
597
|
+
reject(error);
|
|
598
|
+
};
|
|
599
|
+
});
|
|
600
|
+
this._hydrationPromise.catch(() => {});
|
|
601
|
+
}
|
|
602
|
+
return this._hydrationPromise;
|
|
603
|
+
}
|
|
604
|
+
resolveHydration() {
|
|
605
|
+
this._resolveHydrationPromise?.();
|
|
606
|
+
}
|
|
607
|
+
rejectHydration(error) {
|
|
608
|
+
this.ensureHydrationPromise();
|
|
609
|
+
this._rejectHydrationPromise?.(error);
|
|
610
|
+
}
|
|
611
|
+
emitSystemEvent(event, payload) {
|
|
612
|
+
const handlers = this._systemEventHandlers.get(event);
|
|
613
|
+
if (!handlers) return;
|
|
614
|
+
const size = handlers.size;
|
|
615
|
+
let count = 0;
|
|
616
|
+
for (const handler of handlers) {
|
|
617
|
+
if (++count > size) break;
|
|
618
|
+
try {
|
|
619
|
+
handler(payload);
|
|
620
|
+
} catch (error) {
|
|
621
|
+
console.error(`[${this._name}] Error in system event handler:`, error);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Dev-only soft circuit breaker. Counts real state changes in a rolling 1s
|
|
627
|
+
* window and warns once if the rate exceeds `maxEmitsPerSecond` — the
|
|
628
|
+
* signature of a runaway loop (RAF/animation or emit-on-every-commit) pushing
|
|
629
|
+
* high-frequency data through state, which freezes subscribers/plugins.
|
|
630
|
+
*/
|
|
631
|
+
_checkEmitRate() {
|
|
632
|
+
const limit = require_StateContainerRegistry.getBlacConfig().maxEmitsPerSecond;
|
|
633
|
+
if (!(limit > 0) || !Number.isFinite(limit) || this._emitRateWarned) return;
|
|
634
|
+
const now = Date.now();
|
|
635
|
+
if (now - this._emitWindowStart >= 1e3) {
|
|
636
|
+
this._emitWindowStart = now;
|
|
637
|
+
this._emitCount = 1;
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
this._emitCount++;
|
|
641
|
+
if (this._emitCount > limit) {
|
|
642
|
+
this._emitRateWarned = true;
|
|
643
|
+
console.warn(`[${this._name}] emitted more than ${limit} state changes in under a second. This is usually a runaway loop pushing high-frequency data through state (e.g. \`emit\`/\`patch\` inside a requestAnimationFrame loop, or an effect that emits on every render). It can freeze the app by saturating subscribers and plugins (logging/devtools). Keep high-frequency work imperative and emit only coarse/throttled state, or raise \`configureBlac({ maxEmitsPerSecond })\`. (This warning fires once.)`);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
};
|
|
647
|
+
//#endregion
|
|
648
|
+
//#region src/core/Cubit.ts
|
|
649
|
+
/**
|
|
650
|
+
* `Cubit<S>` is a `StateContainer<S>` with `emit` / `patch` exposed as
|
|
651
|
+
* public mutation surface. Today it adds nothing structurally beyond
|
|
652
|
+
* `StateContainer` — both are inherited from the underlying
|
|
653
|
+
* `StructuralContainer<S>`. Kept as a real class (not a type alias) because
|
|
654
|
+
* downstream code does `instance instanceof Cubit` checks.
|
|
655
|
+
*
|
|
656
|
+
* The class body is intentionally empty: a no-op `emit` override would
|
|
657
|
+
* still go through `applyState`, and `patch` is inherited from
|
|
658
|
+
* `StructuralContainer` (path-diffed, microtask-flushed). A caller that
|
|
659
|
+
* wants "skip if no real change" patch semantics can wrap `patch`
|
|
660
|
+
* themselves or call `emit` after a manual equality check.
|
|
661
|
+
*/
|
|
662
|
+
var Cubit = class extends StateContainer {};
|
|
663
|
+
//#endregion
|
|
664
|
+
//#region src/registry/ensure.ts
|
|
665
|
+
/**
|
|
666
|
+
* Ensure an instance exists without taking ownership (no ref added). Instance
|
|
667
|
+
* identity is derived purely from `args`, matching `acquire`.
|
|
668
|
+
*/
|
|
669
|
+
function ensure(BlocClass, opts) {
|
|
670
|
+
const registry = require_config.getRegistry();
|
|
671
|
+
const key = registry.resolveKey(BlocClass, void 0, opts?.args);
|
|
672
|
+
return registry.ensure(BlocClass, key, opts?.args);
|
|
673
|
+
}
|
|
674
|
+
//#endregion
|
|
675
|
+
Object.defineProperty(exports, "Cubit", {
|
|
676
|
+
enumerable: true,
|
|
677
|
+
get: function() {
|
|
678
|
+
return Cubit;
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
Object.defineProperty(exports, "DEP_BRAND", {
|
|
682
|
+
enumerable: true,
|
|
683
|
+
get: function() {
|
|
684
|
+
return DEP_BRAND;
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
Object.defineProperty(exports, "StateContainer", {
|
|
688
|
+
enumerable: true,
|
|
689
|
+
get: function() {
|
|
690
|
+
return StateContainer;
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
Object.defineProperty(exports, "defineEvent", {
|
|
694
|
+
enumerable: true,
|
|
695
|
+
get: function() {
|
|
696
|
+
return defineEvent;
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
Object.defineProperty(exports, "emitEvent", {
|
|
700
|
+
enumerable: true,
|
|
701
|
+
get: function() {
|
|
702
|
+
return emitEvent;
|
|
703
|
+
}
|
|
704
|
+
});
|
|
705
|
+
Object.defineProperty(exports, "ensure", {
|
|
706
|
+
enumerable: true,
|
|
707
|
+
get: function() {
|
|
708
|
+
return ensure;
|
|
709
|
+
}
|
|
710
|
+
});
|
|
711
|
+
Object.defineProperty(exports, "onEvent", {
|
|
712
|
+
enumerable: true,
|
|
713
|
+
get: function() {
|
|
714
|
+
return onEvent;
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
//# sourceMappingURL=ensure-r1C_7K6_.cjs.map
|