@pulse-js/core 0.1.9 → 0.2.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/index.cjs +28 -65
- package/dist/index.d.cts +22 -30
- package/dist/index.d.ts +22 -30
- package/dist/index.js +28 -65
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -95,7 +95,7 @@ function guardFail(reason) {
|
|
|
95
95
|
function guardOk(value) {
|
|
96
96
|
return value;
|
|
97
97
|
}
|
|
98
|
-
function guard(nameOrFn, fn
|
|
98
|
+
function guard(nameOrFn, fn) {
|
|
99
99
|
const name = typeof nameOrFn === "string" ? nameOrFn : void 0;
|
|
100
100
|
const evaluator = typeof nameOrFn === "function" ? nameOrFn : fn;
|
|
101
101
|
if (!evaluator) {
|
|
@@ -295,53 +295,23 @@ var Registry = class {
|
|
|
295
295
|
listeners = /* @__PURE__ */ new Set();
|
|
296
296
|
currentGeneration = 0;
|
|
297
297
|
cleanupScheduled = false;
|
|
298
|
-
autoNameCache = /* @__PURE__ */ new Map();
|
|
299
298
|
/**
|
|
300
|
-
*
|
|
301
|
-
* Uses file path and line number to ensure the same location always gets the same name.
|
|
302
|
-
* Cached to avoid repeated stack trace parsing.
|
|
303
|
-
*/
|
|
304
|
-
generateAutoName(type, offset = 3) {
|
|
305
|
-
const err = new Error();
|
|
306
|
-
const stack = err.stack?.split("\n") || [];
|
|
307
|
-
let callSite = stack[offset]?.trim() || "";
|
|
308
|
-
const cacheKey = `${type}:${callSite}`;
|
|
309
|
-
if (this.autoNameCache.has(cacheKey)) {
|
|
310
|
-
return this.autoNameCache.get(cacheKey);
|
|
311
|
-
}
|
|
312
|
-
const match = callSite.match(/([^/\\]+)\.(?:ts|tsx|js|jsx):(\d+):\d+/);
|
|
313
|
-
let name;
|
|
314
|
-
if (match) {
|
|
315
|
-
const filename = match[1];
|
|
316
|
-
const line = match[2];
|
|
317
|
-
if (filename && line) {
|
|
318
|
-
name = `${type}@${filename}:${line}`;
|
|
319
|
-
} else {
|
|
320
|
-
name = `${type}#${Math.random().toString(36).substring(2, 7)}`;
|
|
321
|
-
}
|
|
322
|
-
} else {
|
|
323
|
-
name = `${type}#${Math.random().toString(36).substring(2, 7)}`;
|
|
324
|
-
}
|
|
325
|
-
this.autoNameCache.set(cacheKey, name);
|
|
326
|
-
return name;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Increments generation and schedules cleanup of old units.
|
|
330
|
-
* Called automatically when HMR is detected.
|
|
299
|
+
* Schedules cleanup of units that weren't re-registered (deleted from code).
|
|
331
300
|
*/
|
|
332
301
|
scheduleCleanup() {
|
|
333
302
|
if (this.cleanupScheduled) return;
|
|
334
303
|
this.cleanupScheduled = true;
|
|
335
|
-
this.currentGeneration++;
|
|
336
304
|
setTimeout(() => {
|
|
337
|
-
this.
|
|
305
|
+
this.cleanupDeadUnits();
|
|
338
306
|
this.cleanupScheduled = false;
|
|
339
307
|
}, 100);
|
|
340
308
|
}
|
|
341
309
|
/**
|
|
342
|
-
* Removes units
|
|
310
|
+
* Removes units that weren't re-registered in the current generation.
|
|
311
|
+
* Uses mark-and-sweep: units that were re-registered have current generation,
|
|
312
|
+
* units that weren't are from old generation and should be removed.
|
|
343
313
|
*/
|
|
344
|
-
|
|
314
|
+
cleanupDeadUnits() {
|
|
345
315
|
const toDelete = [];
|
|
346
316
|
this.units.forEach((unit, key) => {
|
|
347
317
|
const gen = unit._generation;
|
|
@@ -351,53 +321,46 @@ var Registry = class {
|
|
|
351
321
|
});
|
|
352
322
|
toDelete.forEach((key) => this.units.delete(key));
|
|
353
323
|
if (toDelete.length > 0) {
|
|
354
|
-
console.log(`[Pulse] Cleaned up ${toDelete.length}
|
|
324
|
+
console.log(`[Pulse] Cleaned up ${toDelete.length} deleted units after HMR`);
|
|
355
325
|
}
|
|
356
326
|
}
|
|
357
327
|
/**
|
|
358
|
-
* Registers a
|
|
359
|
-
* Auto-assigns stable names to unnamed units for HMR stability.
|
|
328
|
+
* Registers a unit (only if it has an explicit name).
|
|
360
329
|
*/
|
|
361
|
-
register(unit
|
|
330
|
+
register(unit) {
|
|
362
331
|
const unitWithMetadata = unit;
|
|
363
|
-
|
|
332
|
+
const name = unitWithMetadata._name;
|
|
364
333
|
if (!name) {
|
|
365
|
-
|
|
366
|
-
name = this.generateAutoName(isGuard2 ? "guard" : "source", offset);
|
|
367
|
-
unitWithMetadata._name = name;
|
|
334
|
+
return;
|
|
368
335
|
}
|
|
369
|
-
|
|
370
|
-
if (
|
|
336
|
+
const existingUnit = this.units.get(name);
|
|
337
|
+
if (existingUnit) {
|
|
338
|
+
const existingGen = existingUnit?._generation;
|
|
339
|
+
if (existingGen === this.currentGeneration) {
|
|
340
|
+
unitWithMetadata._generation = this.currentGeneration;
|
|
341
|
+
this.units.set(name, unit);
|
|
342
|
+
this.listeners.forEach((l) => l(unit));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
this.currentGeneration++;
|
|
371
346
|
this.scheduleCleanup();
|
|
372
347
|
}
|
|
348
|
+
unitWithMetadata._generation = this.currentGeneration;
|
|
373
349
|
this.units.set(name, unit);
|
|
374
350
|
this.listeners.forEach((l) => l(unit));
|
|
375
351
|
}
|
|
376
|
-
/**
|
|
377
|
-
* Retrieves all registered units.
|
|
378
|
-
*/
|
|
379
352
|
getAll() {
|
|
380
353
|
return Array.from(this.units.values());
|
|
381
354
|
}
|
|
382
|
-
/**
|
|
383
|
-
* Subscribes to new unit registrations.
|
|
384
|
-
*
|
|
385
|
-
* @param listener - Callback receiving the newly registered unit.
|
|
386
|
-
* @returns Unsubscribe function.
|
|
387
|
-
*/
|
|
388
355
|
onRegister(listener) {
|
|
389
356
|
this.listeners.add(listener);
|
|
390
357
|
return () => {
|
|
391
358
|
this.listeners.delete(listener);
|
|
392
359
|
};
|
|
393
360
|
}
|
|
394
|
-
/**
|
|
395
|
-
* Clears all registered units.
|
|
396
|
-
*/
|
|
397
361
|
reset() {
|
|
398
362
|
this.units.clear();
|
|
399
363
|
this.currentGeneration = 0;
|
|
400
|
-
this.autoNameCache.clear();
|
|
401
364
|
}
|
|
402
365
|
};
|
|
403
366
|
var GLOBAL_KEY = "__PULSE_REGISTRY__";
|
|
@@ -408,7 +371,7 @@ if (!globalSymbols[GLOBAL_KEY]) {
|
|
|
408
371
|
var PulseRegistry = globalSymbols[GLOBAL_KEY];
|
|
409
372
|
|
|
410
373
|
// src/source.ts
|
|
411
|
-
function source(initialValue, options = {}
|
|
374
|
+
function source(initialValue, options = {}) {
|
|
412
375
|
let value = initialValue;
|
|
413
376
|
const subscribers = /* @__PURE__ */ new Set();
|
|
414
377
|
const dependents = /* @__PURE__ */ new Set();
|
|
@@ -447,7 +410,7 @@ function compute(name, dependencies, processor) {
|
|
|
447
410
|
return guard(name, () => {
|
|
448
411
|
const values = dependencies.map((dep) => typeof dep === "function" ? dep() : dep);
|
|
449
412
|
return processor(...values);
|
|
450
|
-
}
|
|
413
|
+
});
|
|
451
414
|
}
|
|
452
415
|
|
|
453
416
|
// src/composition.ts
|
|
@@ -470,7 +433,7 @@ function guardAll(nameOrGuards, maybeGuards) {
|
|
|
470
433
|
throw new Error(message);
|
|
471
434
|
}
|
|
472
435
|
return true;
|
|
473
|
-
}
|
|
436
|
+
});
|
|
474
437
|
}
|
|
475
438
|
function guardAny(nameOrGuards, maybeGuards) {
|
|
476
439
|
const name = typeof nameOrGuards === "string" ? nameOrGuards : void 0;
|
|
@@ -484,7 +447,7 @@ function guardAny(nameOrGuards, maybeGuards) {
|
|
|
484
447
|
allFails.push(message);
|
|
485
448
|
}
|
|
486
449
|
throw new Error(allFails.length > 0 ? allFails.join(" and ") : "no conditions met");
|
|
487
|
-
}
|
|
450
|
+
});
|
|
488
451
|
}
|
|
489
452
|
function guardNot(nameOrTarget, maybeTarget) {
|
|
490
453
|
const name = typeof nameOrTarget === "string" ? nameOrTarget : void 0;
|
|
@@ -494,7 +457,7 @@ function guardNot(nameOrTarget, maybeTarget) {
|
|
|
494
457
|
return !target.ok();
|
|
495
458
|
}
|
|
496
459
|
return !target();
|
|
497
|
-
}
|
|
460
|
+
});
|
|
498
461
|
}
|
|
499
462
|
var guardExtensions = {
|
|
500
463
|
all: guardAll,
|
package/dist/index.d.cts
CHANGED
|
@@ -186,7 +186,7 @@ declare function guardFail(reason: string | GuardReason): never;
|
|
|
186
186
|
* Returns the value passed to it.
|
|
187
187
|
*/
|
|
188
188
|
declare function guardOk<T>(value: T): T;
|
|
189
|
-
declare function guard<T = boolean>(nameOrFn?: string | (() => T | Promise<T>), fn?: () => T | Promise<T
|
|
189
|
+
declare function guard<T = boolean>(nameOrFn?: string | (() => T | Promise<T>), fn?: () => T | Promise<T>): Guard<T>;
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* Utility to transform reactive dependencies into a new derived value.
|
|
@@ -361,7 +361,7 @@ interface Source<T> {
|
|
|
361
361
|
* user.set({ name: 'Bob' });
|
|
362
362
|
* ```
|
|
363
363
|
*/
|
|
364
|
-
declare function source<T>(initialValue: T, options?: SourceOptions<T
|
|
364
|
+
declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
365
365
|
|
|
366
366
|
/**
|
|
367
367
|
* Serialized state of guards for transfer from server to client.
|
|
@@ -416,49 +416,41 @@ type PulseUnit = Source<any> | Guard<any>;
|
|
|
416
416
|
/**
|
|
417
417
|
* Root Registry for Pulse.
|
|
418
418
|
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
419
|
+
* Tracks all registered Units (Sources and Guards) globally for DevTools.
|
|
420
|
+
*
|
|
421
|
+
* **IMPORTANT**: Only units with explicit names are registered and visible in DevTools.
|
|
422
|
+
* Unnamed units work perfectly but are not tracked to avoid HMR instability.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```ts
|
|
426
|
+
* // ✅ Visible in DevTools
|
|
427
|
+
* const count = source(0, { name: 'count' });
|
|
428
|
+
*
|
|
429
|
+
* // ❌ Not visible in DevTools (but works fine)
|
|
430
|
+
* const temp = source(0);
|
|
431
|
+
* ```
|
|
421
432
|
*/
|
|
422
433
|
declare class Registry {
|
|
423
434
|
private units;
|
|
424
435
|
private listeners;
|
|
425
436
|
private currentGeneration;
|
|
426
437
|
private cleanupScheduled;
|
|
427
|
-
private autoNameCache;
|
|
428
|
-
/**
|
|
429
|
-
* Generates a stable auto-name based on source code location.
|
|
430
|
-
* Uses file path and line number to ensure the same location always gets the same name.
|
|
431
|
-
* Cached to avoid repeated stack trace parsing.
|
|
432
|
-
*/
|
|
433
|
-
generateAutoName(type: 'source' | 'guard', offset?: number): string;
|
|
434
438
|
/**
|
|
435
|
-
*
|
|
436
|
-
* Called automatically when HMR is detected.
|
|
439
|
+
* Schedules cleanup of units that weren't re-registered (deleted from code).
|
|
437
440
|
*/
|
|
438
441
|
private scheduleCleanup;
|
|
439
442
|
/**
|
|
440
|
-
* Removes units
|
|
443
|
+
* Removes units that weren't re-registered in the current generation.
|
|
444
|
+
* Uses mark-and-sweep: units that were re-registered have current generation,
|
|
445
|
+
* units that weren't are from old generation and should be removed.
|
|
441
446
|
*/
|
|
442
|
-
private
|
|
447
|
+
private cleanupDeadUnits;
|
|
443
448
|
/**
|
|
444
|
-
* Registers a
|
|
445
|
-
* Auto-assigns stable names to unnamed units for HMR stability.
|
|
446
|
-
*/
|
|
447
|
-
register(unit: PulseUnit, offset?: number): void;
|
|
448
|
-
/**
|
|
449
|
-
* Retrieves all registered units.
|
|
449
|
+
* Registers a unit (only if it has an explicit name).
|
|
450
450
|
*/
|
|
451
|
+
register(unit: PulseUnit): void;
|
|
451
452
|
getAll(): PulseUnit[];
|
|
452
|
-
/**
|
|
453
|
-
* Subscribes to new unit registrations.
|
|
454
|
-
*
|
|
455
|
-
* @param listener - Callback receiving the newly registered unit.
|
|
456
|
-
* @returns Unsubscribe function.
|
|
457
|
-
*/
|
|
458
453
|
onRegister(listener: (unit: PulseUnit) => void): () => void;
|
|
459
|
-
/**
|
|
460
|
-
* Clears all registered units.
|
|
461
|
-
*/
|
|
462
454
|
reset(): void;
|
|
463
455
|
}
|
|
464
456
|
declare const PulseRegistry: Registry;
|
package/dist/index.d.ts
CHANGED
|
@@ -186,7 +186,7 @@ declare function guardFail(reason: string | GuardReason): never;
|
|
|
186
186
|
* Returns the value passed to it.
|
|
187
187
|
*/
|
|
188
188
|
declare function guardOk<T>(value: T): T;
|
|
189
|
-
declare function guard<T = boolean>(nameOrFn?: string | (() => T | Promise<T>), fn?: () => T | Promise<T
|
|
189
|
+
declare function guard<T = boolean>(nameOrFn?: string | (() => T | Promise<T>), fn?: () => T | Promise<T>): Guard<T>;
|
|
190
190
|
|
|
191
191
|
/**
|
|
192
192
|
* Utility to transform reactive dependencies into a new derived value.
|
|
@@ -361,7 +361,7 @@ interface Source<T> {
|
|
|
361
361
|
* user.set({ name: 'Bob' });
|
|
362
362
|
* ```
|
|
363
363
|
*/
|
|
364
|
-
declare function source<T>(initialValue: T, options?: SourceOptions<T
|
|
364
|
+
declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
365
365
|
|
|
366
366
|
/**
|
|
367
367
|
* Serialized state of guards for transfer from server to client.
|
|
@@ -416,49 +416,41 @@ type PulseUnit = Source<any> | Guard<any>;
|
|
|
416
416
|
/**
|
|
417
417
|
* Root Registry for Pulse.
|
|
418
418
|
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
419
|
+
* Tracks all registered Units (Sources and Guards) globally for DevTools.
|
|
420
|
+
*
|
|
421
|
+
* **IMPORTANT**: Only units with explicit names are registered and visible in DevTools.
|
|
422
|
+
* Unnamed units work perfectly but are not tracked to avoid HMR instability.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```ts
|
|
426
|
+
* // ✅ Visible in DevTools
|
|
427
|
+
* const count = source(0, { name: 'count' });
|
|
428
|
+
*
|
|
429
|
+
* // ❌ Not visible in DevTools (but works fine)
|
|
430
|
+
* const temp = source(0);
|
|
431
|
+
* ```
|
|
421
432
|
*/
|
|
422
433
|
declare class Registry {
|
|
423
434
|
private units;
|
|
424
435
|
private listeners;
|
|
425
436
|
private currentGeneration;
|
|
426
437
|
private cleanupScheduled;
|
|
427
|
-
private autoNameCache;
|
|
428
|
-
/**
|
|
429
|
-
* Generates a stable auto-name based on source code location.
|
|
430
|
-
* Uses file path and line number to ensure the same location always gets the same name.
|
|
431
|
-
* Cached to avoid repeated stack trace parsing.
|
|
432
|
-
*/
|
|
433
|
-
generateAutoName(type: 'source' | 'guard', offset?: number): string;
|
|
434
438
|
/**
|
|
435
|
-
*
|
|
436
|
-
* Called automatically when HMR is detected.
|
|
439
|
+
* Schedules cleanup of units that weren't re-registered (deleted from code).
|
|
437
440
|
*/
|
|
438
441
|
private scheduleCleanup;
|
|
439
442
|
/**
|
|
440
|
-
* Removes units
|
|
443
|
+
* Removes units that weren't re-registered in the current generation.
|
|
444
|
+
* Uses mark-and-sweep: units that were re-registered have current generation,
|
|
445
|
+
* units that weren't are from old generation and should be removed.
|
|
441
446
|
*/
|
|
442
|
-
private
|
|
447
|
+
private cleanupDeadUnits;
|
|
443
448
|
/**
|
|
444
|
-
* Registers a
|
|
445
|
-
* Auto-assigns stable names to unnamed units for HMR stability.
|
|
446
|
-
*/
|
|
447
|
-
register(unit: PulseUnit, offset?: number): void;
|
|
448
|
-
/**
|
|
449
|
-
* Retrieves all registered units.
|
|
449
|
+
* Registers a unit (only if it has an explicit name).
|
|
450
450
|
*/
|
|
451
|
+
register(unit: PulseUnit): void;
|
|
451
452
|
getAll(): PulseUnit[];
|
|
452
|
-
/**
|
|
453
|
-
* Subscribes to new unit registrations.
|
|
454
|
-
*
|
|
455
|
-
* @param listener - Callback receiving the newly registered unit.
|
|
456
|
-
* @returns Unsubscribe function.
|
|
457
|
-
*/
|
|
458
453
|
onRegister(listener: (unit: PulseUnit) => void): () => void;
|
|
459
|
-
/**
|
|
460
|
-
* Clears all registered units.
|
|
461
|
-
*/
|
|
462
454
|
reset(): void;
|
|
463
455
|
}
|
|
464
456
|
declare const PulseRegistry: Registry;
|
package/dist/index.js
CHANGED
|
@@ -59,7 +59,7 @@ function guardFail(reason) {
|
|
|
59
59
|
function guardOk(value) {
|
|
60
60
|
return value;
|
|
61
61
|
}
|
|
62
|
-
function guard(nameOrFn, fn
|
|
62
|
+
function guard(nameOrFn, fn) {
|
|
63
63
|
const name = typeof nameOrFn === "string" ? nameOrFn : void 0;
|
|
64
64
|
const evaluator = typeof nameOrFn === "function" ? nameOrFn : fn;
|
|
65
65
|
if (!evaluator) {
|
|
@@ -259,53 +259,23 @@ var Registry = class {
|
|
|
259
259
|
listeners = /* @__PURE__ */ new Set();
|
|
260
260
|
currentGeneration = 0;
|
|
261
261
|
cleanupScheduled = false;
|
|
262
|
-
autoNameCache = /* @__PURE__ */ new Map();
|
|
263
262
|
/**
|
|
264
|
-
*
|
|
265
|
-
* Uses file path and line number to ensure the same location always gets the same name.
|
|
266
|
-
* Cached to avoid repeated stack trace parsing.
|
|
267
|
-
*/
|
|
268
|
-
generateAutoName(type, offset = 3) {
|
|
269
|
-
const err = new Error();
|
|
270
|
-
const stack = err.stack?.split("\n") || [];
|
|
271
|
-
let callSite = stack[offset]?.trim() || "";
|
|
272
|
-
const cacheKey = `${type}:${callSite}`;
|
|
273
|
-
if (this.autoNameCache.has(cacheKey)) {
|
|
274
|
-
return this.autoNameCache.get(cacheKey);
|
|
275
|
-
}
|
|
276
|
-
const match = callSite.match(/([^/\\]+)\.(?:ts|tsx|js|jsx):(\d+):\d+/);
|
|
277
|
-
let name;
|
|
278
|
-
if (match) {
|
|
279
|
-
const filename = match[1];
|
|
280
|
-
const line = match[2];
|
|
281
|
-
if (filename && line) {
|
|
282
|
-
name = `${type}@${filename}:${line}`;
|
|
283
|
-
} else {
|
|
284
|
-
name = `${type}#${Math.random().toString(36).substring(2, 7)}`;
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
name = `${type}#${Math.random().toString(36).substring(2, 7)}`;
|
|
288
|
-
}
|
|
289
|
-
this.autoNameCache.set(cacheKey, name);
|
|
290
|
-
return name;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Increments generation and schedules cleanup of old units.
|
|
294
|
-
* Called automatically when HMR is detected.
|
|
263
|
+
* Schedules cleanup of units that weren't re-registered (deleted from code).
|
|
295
264
|
*/
|
|
296
265
|
scheduleCleanup() {
|
|
297
266
|
if (this.cleanupScheduled) return;
|
|
298
267
|
this.cleanupScheduled = true;
|
|
299
|
-
this.currentGeneration++;
|
|
300
268
|
setTimeout(() => {
|
|
301
|
-
this.
|
|
269
|
+
this.cleanupDeadUnits();
|
|
302
270
|
this.cleanupScheduled = false;
|
|
303
271
|
}, 100);
|
|
304
272
|
}
|
|
305
273
|
/**
|
|
306
|
-
* Removes units
|
|
274
|
+
* Removes units that weren't re-registered in the current generation.
|
|
275
|
+
* Uses mark-and-sweep: units that were re-registered have current generation,
|
|
276
|
+
* units that weren't are from old generation and should be removed.
|
|
307
277
|
*/
|
|
308
|
-
|
|
278
|
+
cleanupDeadUnits() {
|
|
309
279
|
const toDelete = [];
|
|
310
280
|
this.units.forEach((unit, key) => {
|
|
311
281
|
const gen = unit._generation;
|
|
@@ -315,53 +285,46 @@ var Registry = class {
|
|
|
315
285
|
});
|
|
316
286
|
toDelete.forEach((key) => this.units.delete(key));
|
|
317
287
|
if (toDelete.length > 0) {
|
|
318
|
-
console.log(`[Pulse] Cleaned up ${toDelete.length}
|
|
288
|
+
console.log(`[Pulse] Cleaned up ${toDelete.length} deleted units after HMR`);
|
|
319
289
|
}
|
|
320
290
|
}
|
|
321
291
|
/**
|
|
322
|
-
* Registers a
|
|
323
|
-
* Auto-assigns stable names to unnamed units for HMR stability.
|
|
292
|
+
* Registers a unit (only if it has an explicit name).
|
|
324
293
|
*/
|
|
325
|
-
register(unit
|
|
294
|
+
register(unit) {
|
|
326
295
|
const unitWithMetadata = unit;
|
|
327
|
-
|
|
296
|
+
const name = unitWithMetadata._name;
|
|
328
297
|
if (!name) {
|
|
329
|
-
|
|
330
|
-
name = this.generateAutoName(isGuard2 ? "guard" : "source", offset);
|
|
331
|
-
unitWithMetadata._name = name;
|
|
298
|
+
return;
|
|
332
299
|
}
|
|
333
|
-
|
|
334
|
-
if (
|
|
300
|
+
const existingUnit = this.units.get(name);
|
|
301
|
+
if (existingUnit) {
|
|
302
|
+
const existingGen = existingUnit?._generation;
|
|
303
|
+
if (existingGen === this.currentGeneration) {
|
|
304
|
+
unitWithMetadata._generation = this.currentGeneration;
|
|
305
|
+
this.units.set(name, unit);
|
|
306
|
+
this.listeners.forEach((l) => l(unit));
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
this.currentGeneration++;
|
|
335
310
|
this.scheduleCleanup();
|
|
336
311
|
}
|
|
312
|
+
unitWithMetadata._generation = this.currentGeneration;
|
|
337
313
|
this.units.set(name, unit);
|
|
338
314
|
this.listeners.forEach((l) => l(unit));
|
|
339
315
|
}
|
|
340
|
-
/**
|
|
341
|
-
* Retrieves all registered units.
|
|
342
|
-
*/
|
|
343
316
|
getAll() {
|
|
344
317
|
return Array.from(this.units.values());
|
|
345
318
|
}
|
|
346
|
-
/**
|
|
347
|
-
* Subscribes to new unit registrations.
|
|
348
|
-
*
|
|
349
|
-
* @param listener - Callback receiving the newly registered unit.
|
|
350
|
-
* @returns Unsubscribe function.
|
|
351
|
-
*/
|
|
352
319
|
onRegister(listener) {
|
|
353
320
|
this.listeners.add(listener);
|
|
354
321
|
return () => {
|
|
355
322
|
this.listeners.delete(listener);
|
|
356
323
|
};
|
|
357
324
|
}
|
|
358
|
-
/**
|
|
359
|
-
* Clears all registered units.
|
|
360
|
-
*/
|
|
361
325
|
reset() {
|
|
362
326
|
this.units.clear();
|
|
363
327
|
this.currentGeneration = 0;
|
|
364
|
-
this.autoNameCache.clear();
|
|
365
328
|
}
|
|
366
329
|
};
|
|
367
330
|
var GLOBAL_KEY = "__PULSE_REGISTRY__";
|
|
@@ -372,7 +335,7 @@ if (!globalSymbols[GLOBAL_KEY]) {
|
|
|
372
335
|
var PulseRegistry = globalSymbols[GLOBAL_KEY];
|
|
373
336
|
|
|
374
337
|
// src/source.ts
|
|
375
|
-
function source(initialValue, options = {}
|
|
338
|
+
function source(initialValue, options = {}) {
|
|
376
339
|
let value = initialValue;
|
|
377
340
|
const subscribers = /* @__PURE__ */ new Set();
|
|
378
341
|
const dependents = /* @__PURE__ */ new Set();
|
|
@@ -411,7 +374,7 @@ function compute(name, dependencies, processor) {
|
|
|
411
374
|
return guard(name, () => {
|
|
412
375
|
const values = dependencies.map((dep) => typeof dep === "function" ? dep() : dep);
|
|
413
376
|
return processor(...values);
|
|
414
|
-
}
|
|
377
|
+
});
|
|
415
378
|
}
|
|
416
379
|
|
|
417
380
|
// src/composition.ts
|
|
@@ -434,7 +397,7 @@ function guardAll(nameOrGuards, maybeGuards) {
|
|
|
434
397
|
throw new Error(message);
|
|
435
398
|
}
|
|
436
399
|
return true;
|
|
437
|
-
}
|
|
400
|
+
});
|
|
438
401
|
}
|
|
439
402
|
function guardAny(nameOrGuards, maybeGuards) {
|
|
440
403
|
const name = typeof nameOrGuards === "string" ? nameOrGuards : void 0;
|
|
@@ -448,7 +411,7 @@ function guardAny(nameOrGuards, maybeGuards) {
|
|
|
448
411
|
allFails.push(message);
|
|
449
412
|
}
|
|
450
413
|
throw new Error(allFails.length > 0 ? allFails.join(" and ") : "no conditions met");
|
|
451
|
-
}
|
|
414
|
+
});
|
|
452
415
|
}
|
|
453
416
|
function guardNot(nameOrTarget, maybeTarget) {
|
|
454
417
|
const name = typeof nameOrTarget === "string" ? nameOrTarget : void 0;
|
|
@@ -458,7 +421,7 @@ function guardNot(nameOrTarget, maybeTarget) {
|
|
|
458
421
|
return !target.ok();
|
|
459
422
|
}
|
|
460
423
|
return !target();
|
|
461
|
-
}
|
|
424
|
+
});
|
|
462
425
|
}
|
|
463
426
|
var guardExtensions = {
|
|
464
427
|
all: guardAll,
|