@pulse-js/core 0.2.0 → 0.2.1
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 +21 -5
- package/dist/index.d.cts +128 -113
- package/dist/index.d.ts +128 -113
- package/dist/index.js +21 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -259,11 +259,20 @@ function guard(nameOrFn, fn) {
|
|
|
259
259
|
lastDeps.forEach((dep) => {
|
|
260
260
|
const depName = dep._name || "unnamed";
|
|
261
261
|
const isG = "state" in dep;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
if (isG) {
|
|
263
|
+
const depState = dep.state();
|
|
264
|
+
deps.push({
|
|
265
|
+
name: depName,
|
|
266
|
+
type: "guard",
|
|
267
|
+
status: depState.status,
|
|
268
|
+
reason: depState.status === "fail" ? depState.reason : void 0
|
|
269
|
+
});
|
|
270
|
+
} else {
|
|
271
|
+
deps.push({
|
|
272
|
+
name: depName,
|
|
273
|
+
type: "source"
|
|
274
|
+
});
|
|
275
|
+
}
|
|
267
276
|
});
|
|
268
277
|
return {
|
|
269
278
|
name: name || "guard",
|
|
@@ -288,6 +297,13 @@ function guard(nameOrFn, fn) {
|
|
|
288
297
|
evaluate2();
|
|
289
298
|
return g;
|
|
290
299
|
}
|
|
300
|
+
guard.map = function(source2, mapper, name) {
|
|
301
|
+
const guardName = name || `map-${source2._name || "source"}`;
|
|
302
|
+
return guard(guardName, () => {
|
|
303
|
+
const value = source2();
|
|
304
|
+
return mapper(value);
|
|
305
|
+
});
|
|
306
|
+
};
|
|
291
307
|
|
|
292
308
|
// src/registry.ts
|
|
293
309
|
var Registry = class {
|
package/dist/index.d.cts
CHANGED
|
@@ -41,6 +41,118 @@ declare function runInContext<T>(guard: GuardNode, fn: () => T): T;
|
|
|
41
41
|
*/
|
|
42
42
|
declare function getCurrentGuard(): GuardNode | null;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Options for configuring a Pulse Source.
|
|
46
|
+
*
|
|
47
|
+
* @template T - The type of value stored in the source.
|
|
48
|
+
*/
|
|
49
|
+
interface SourceOptions<T> {
|
|
50
|
+
/**
|
|
51
|
+
* A descriptive name for the source.
|
|
52
|
+
* Required for SSR hydration and highly recommended for debugging in DevTools.
|
|
53
|
+
*/
|
|
54
|
+
name?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Custom equality function to determine if a value has changed.
|
|
57
|
+
* By default, Pulse uses strict equality (`===`).
|
|
58
|
+
*
|
|
59
|
+
* @param a - The current value.
|
|
60
|
+
* @param b - The new value.
|
|
61
|
+
* @returns `true` if the values are considered equal, `false` otherwise.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const list = source([1], {
|
|
66
|
+
* equals: (a, b) => a.length === b.length
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
equals?: (a: T, b: T) => boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A Pulse Source is a reactive container for a value.
|
|
74
|
+
* It tracks which Guards read its value and notifies them when it changes.
|
|
75
|
+
*
|
|
76
|
+
* @template T The type of the value held by the source.
|
|
77
|
+
*/
|
|
78
|
+
interface Source<T> {
|
|
79
|
+
/**
|
|
80
|
+
* Returns the current value of the source.
|
|
81
|
+
* If called within a Guard evaluation, it automatically registers that Guard as a dependent.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const count = source(0);
|
|
86
|
+
* console.log(count()); // 0
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
(): T;
|
|
90
|
+
/**
|
|
91
|
+
* Updates the source with a new value.
|
|
92
|
+
* If the value is different (based on strict equality or `options.equals`),
|
|
93
|
+
* all dependent Guards and subscribers will be notified.
|
|
94
|
+
*
|
|
95
|
+
* @param value The new value to set.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* const count = source(0);
|
|
100
|
+
* count.set(1); // Triggers re-evaluation of dependents
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @error
|
|
104
|
+
* Common error: Mutating an object property without setting a new object reference.
|
|
105
|
+
* Pulse uses reference equality by default. If you mutate a property, Pulse won't know it changed.
|
|
106
|
+
* Solution: Always provide a new object or implement a custom `equals`.
|
|
107
|
+
*/
|
|
108
|
+
set(value: T): void;
|
|
109
|
+
/**
|
|
110
|
+
* Updates the source value using a transformer function based on the current value.
|
|
111
|
+
* Useful for increments or toggles.
|
|
112
|
+
*
|
|
113
|
+
* @param updater A function that receives the current value and returns the new value.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const count = source(0);
|
|
118
|
+
* count.update(n => n + 1);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
update(updater: (current: T) => T): void;
|
|
122
|
+
/**
|
|
123
|
+
* Manually subscribes to changes in the source value.
|
|
124
|
+
*
|
|
125
|
+
* @param listener A callback that receives the new value.
|
|
126
|
+
* @returns An unsubscription function.
|
|
127
|
+
*
|
|
128
|
+
* @note Most users should use `guard()` or `usePulse()` instead of manual subscriptions.
|
|
129
|
+
*/
|
|
130
|
+
subscribe(listener: Subscriber<T>): () => void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Creates a new Pulse Source.
|
|
134
|
+
*
|
|
135
|
+
* Sources are the fundamental building blocks of state in Pulse. They hold a value
|
|
136
|
+
* and track which Guards depend on them.
|
|
137
|
+
*
|
|
138
|
+
* @template T - The type of value to store.
|
|
139
|
+
* @param initialValue - The initial state.
|
|
140
|
+
* @param options - Configuration options (name, equality).
|
|
141
|
+
* @returns A reactive Pulse Source.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* const user = source({ name: 'Alice' }, { name: 'user_state' });
|
|
146
|
+
*
|
|
147
|
+
* // Read value (auto-tracks if inside a guard)
|
|
148
|
+
* console.log(user());
|
|
149
|
+
*
|
|
150
|
+
* // Update value
|
|
151
|
+
* user.set({ name: 'Bob' });
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
155
|
+
|
|
44
156
|
/**
|
|
45
157
|
* Status of a Pulse Guard evaluation.
|
|
46
158
|
* - 'pending': Async evaluation is in progress.
|
|
@@ -86,6 +198,7 @@ interface GuardExplanation {
|
|
|
86
198
|
name: string;
|
|
87
199
|
type: 'source' | 'guard';
|
|
88
200
|
status?: GuardStatus;
|
|
201
|
+
reason?: string | GuardReason;
|
|
89
202
|
}>;
|
|
90
203
|
}
|
|
91
204
|
/**
|
|
@@ -187,6 +300,9 @@ declare function guardFail(reason: string | GuardReason): never;
|
|
|
187
300
|
*/
|
|
188
301
|
declare function guardOk<T>(value: T): T;
|
|
189
302
|
declare function guard<T = boolean>(nameOrFn?: string | (() => T | Promise<T>), fn?: () => T | Promise<T>): Guard<T>;
|
|
303
|
+
declare namespace guard {
|
|
304
|
+
var map: <T, U>(source: Source<T>, mapper: (value: T) => U | Promise<U>, name?: string) => Guard<U>;
|
|
305
|
+
}
|
|
190
306
|
|
|
191
307
|
/**
|
|
192
308
|
* Utility to transform reactive dependencies into a new derived value.
|
|
@@ -251,118 +367,6 @@ declare function guardAny(nameOrGuards: string | Guard<any>[], maybeGuards?: Gua
|
|
|
251
367
|
*/
|
|
252
368
|
declare function guardNot(nameOrTarget: string | Guard<any> | (() => any), maybeTarget?: Guard<any> | (() => any)): Guard<boolean>;
|
|
253
369
|
|
|
254
|
-
/**
|
|
255
|
-
* Options for configuring a Pulse Source.
|
|
256
|
-
*
|
|
257
|
-
* @template T - The type of value stored in the source.
|
|
258
|
-
*/
|
|
259
|
-
interface SourceOptions<T> {
|
|
260
|
-
/**
|
|
261
|
-
* A descriptive name for the source.
|
|
262
|
-
* Required for SSR hydration and highly recommended for debugging in DevTools.
|
|
263
|
-
*/
|
|
264
|
-
name?: string;
|
|
265
|
-
/**
|
|
266
|
-
* Custom equality function to determine if a value has changed.
|
|
267
|
-
* By default, Pulse uses strict equality (`===`).
|
|
268
|
-
*
|
|
269
|
-
* @param a - The current value.
|
|
270
|
-
* @param b - The new value.
|
|
271
|
-
* @returns `true` if the values are considered equal, `false` otherwise.
|
|
272
|
-
*
|
|
273
|
-
* @example
|
|
274
|
-
* ```ts
|
|
275
|
-
* const list = source([1], {
|
|
276
|
-
* equals: (a, b) => a.length === b.length
|
|
277
|
-
* });
|
|
278
|
-
* ```
|
|
279
|
-
*/
|
|
280
|
-
equals?: (a: T, b: T) => boolean;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* A Pulse Source is a reactive container for a value.
|
|
284
|
-
* It tracks which Guards read its value and notifies them when it changes.
|
|
285
|
-
*
|
|
286
|
-
* @template T The type of the value held by the source.
|
|
287
|
-
*/
|
|
288
|
-
interface Source<T> {
|
|
289
|
-
/**
|
|
290
|
-
* Returns the current value of the source.
|
|
291
|
-
* If called within a Guard evaluation, it automatically registers that Guard as a dependent.
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* ```ts
|
|
295
|
-
* const count = source(0);
|
|
296
|
-
* console.log(count()); // 0
|
|
297
|
-
* ```
|
|
298
|
-
*/
|
|
299
|
-
(): T;
|
|
300
|
-
/**
|
|
301
|
-
* Updates the source with a new value.
|
|
302
|
-
* If the value is different (based on strict equality or `options.equals`),
|
|
303
|
-
* all dependent Guards and subscribers will be notified.
|
|
304
|
-
*
|
|
305
|
-
* @param value The new value to set.
|
|
306
|
-
*
|
|
307
|
-
* @example
|
|
308
|
-
* ```ts
|
|
309
|
-
* const count = source(0);
|
|
310
|
-
* count.set(1); // Triggers re-evaluation of dependents
|
|
311
|
-
* ```
|
|
312
|
-
*
|
|
313
|
-
* @error
|
|
314
|
-
* Common error: Mutating an object property without setting a new object reference.
|
|
315
|
-
* Pulse uses reference equality by default. If you mutate a property, Pulse won't know it changed.
|
|
316
|
-
* Solution: Always provide a new object or implement a custom `equals`.
|
|
317
|
-
*/
|
|
318
|
-
set(value: T): void;
|
|
319
|
-
/**
|
|
320
|
-
* Updates the source value using a transformer function based on the current value.
|
|
321
|
-
* Useful for increments or toggles.
|
|
322
|
-
*
|
|
323
|
-
* @param updater A function that receives the current value and returns the new value.
|
|
324
|
-
*
|
|
325
|
-
* @example
|
|
326
|
-
* ```ts
|
|
327
|
-
* const count = source(0);
|
|
328
|
-
* count.update(n => n + 1);
|
|
329
|
-
* ```
|
|
330
|
-
*/
|
|
331
|
-
update(updater: (current: T) => T): void;
|
|
332
|
-
/**
|
|
333
|
-
* Manually subscribes to changes in the source value.
|
|
334
|
-
*
|
|
335
|
-
* @param listener A callback that receives the new value.
|
|
336
|
-
* @returns An unsubscription function.
|
|
337
|
-
*
|
|
338
|
-
* @note Most users should use `guard()` or `usePulse()` instead of manual subscriptions.
|
|
339
|
-
*/
|
|
340
|
-
subscribe(listener: Subscriber<T>): () => void;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Creates a new Pulse Source.
|
|
344
|
-
*
|
|
345
|
-
* Sources are the fundamental building blocks of state in Pulse. They hold a value
|
|
346
|
-
* and track which Guards depend on them.
|
|
347
|
-
*
|
|
348
|
-
* @template T - The type of value to store.
|
|
349
|
-
* @param initialValue - The initial state.
|
|
350
|
-
* @param options - Configuration options (name, equality).
|
|
351
|
-
* @returns A reactive Pulse Source.
|
|
352
|
-
*
|
|
353
|
-
* @example
|
|
354
|
-
* ```ts
|
|
355
|
-
* const user = source({ name: 'Alice' }, { name: 'user_state' });
|
|
356
|
-
*
|
|
357
|
-
* // Read value (auto-tracks if inside a guard)
|
|
358
|
-
* console.log(user());
|
|
359
|
-
*
|
|
360
|
-
* // Update value
|
|
361
|
-
* user.set({ name: 'Bob' });
|
|
362
|
-
* ```
|
|
363
|
-
*/
|
|
364
|
-
declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
365
|
-
|
|
366
370
|
/**
|
|
367
371
|
* Serialized state of guards for transfer from server to client.
|
|
368
372
|
*/
|
|
@@ -455,6 +459,17 @@ declare class Registry {
|
|
|
455
459
|
}
|
|
456
460
|
declare const PulseRegistry: Registry;
|
|
457
461
|
|
|
462
|
+
/**
|
|
463
|
+
* Extracts the result type T from a Guard<T>.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* const authGuard = guard('auth', async () => fetchUser());
|
|
468
|
+
* type AuthUser = InferGuardType<typeof authGuard>; // User
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
type InferGuardType<T> = T extends Guard<infer U> ? U : never;
|
|
472
|
+
|
|
458
473
|
/**
|
|
459
474
|
* Pulse Guard with integrated Composition Helpers.
|
|
460
475
|
*
|
|
@@ -474,4 +489,4 @@ declare const extendedGuard: typeof guard & {
|
|
|
474
489
|
compute: typeof compute;
|
|
475
490
|
};
|
|
476
491
|
|
|
477
|
-
export { type Guard, type GuardExplanation, type GuardNode, type GuardReason, type GuardState, type GuardStatus, type HydrationState, PulseRegistry, type PulseUnit, type Source, type SourceOptions, type Subscriber, type Trackable, compute, evaluate, getCurrentGuard, extendedGuard as guard, guardFail, guardOk, hydrate, registerGuardForHydration, runInContext, source };
|
|
492
|
+
export { type Guard, type GuardExplanation, type GuardNode, type GuardReason, type GuardState, type GuardStatus, type HydrationState, type InferGuardType, PulseRegistry, type PulseUnit, type Source, type SourceOptions, type Subscriber, type Trackable, compute, evaluate, getCurrentGuard, extendedGuard as guard, guardFail, guardOk, hydrate, registerGuardForHydration, runInContext, source };
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,118 @@ declare function runInContext<T>(guard: GuardNode, fn: () => T): T;
|
|
|
41
41
|
*/
|
|
42
42
|
declare function getCurrentGuard(): GuardNode | null;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Options for configuring a Pulse Source.
|
|
46
|
+
*
|
|
47
|
+
* @template T - The type of value stored in the source.
|
|
48
|
+
*/
|
|
49
|
+
interface SourceOptions<T> {
|
|
50
|
+
/**
|
|
51
|
+
* A descriptive name for the source.
|
|
52
|
+
* Required for SSR hydration and highly recommended for debugging in DevTools.
|
|
53
|
+
*/
|
|
54
|
+
name?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Custom equality function to determine if a value has changed.
|
|
57
|
+
* By default, Pulse uses strict equality (`===`).
|
|
58
|
+
*
|
|
59
|
+
* @param a - The current value.
|
|
60
|
+
* @param b - The new value.
|
|
61
|
+
* @returns `true` if the values are considered equal, `false` otherwise.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const list = source([1], {
|
|
66
|
+
* equals: (a, b) => a.length === b.length
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
equals?: (a: T, b: T) => boolean;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A Pulse Source is a reactive container for a value.
|
|
74
|
+
* It tracks which Guards read its value and notifies them when it changes.
|
|
75
|
+
*
|
|
76
|
+
* @template T The type of the value held by the source.
|
|
77
|
+
*/
|
|
78
|
+
interface Source<T> {
|
|
79
|
+
/**
|
|
80
|
+
* Returns the current value of the source.
|
|
81
|
+
* If called within a Guard evaluation, it automatically registers that Guard as a dependent.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const count = source(0);
|
|
86
|
+
* console.log(count()); // 0
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
(): T;
|
|
90
|
+
/**
|
|
91
|
+
* Updates the source with a new value.
|
|
92
|
+
* If the value is different (based on strict equality or `options.equals`),
|
|
93
|
+
* all dependent Guards and subscribers will be notified.
|
|
94
|
+
*
|
|
95
|
+
* @param value The new value to set.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* const count = source(0);
|
|
100
|
+
* count.set(1); // Triggers re-evaluation of dependents
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @error
|
|
104
|
+
* Common error: Mutating an object property without setting a new object reference.
|
|
105
|
+
* Pulse uses reference equality by default. If you mutate a property, Pulse won't know it changed.
|
|
106
|
+
* Solution: Always provide a new object or implement a custom `equals`.
|
|
107
|
+
*/
|
|
108
|
+
set(value: T): void;
|
|
109
|
+
/**
|
|
110
|
+
* Updates the source value using a transformer function based on the current value.
|
|
111
|
+
* Useful for increments or toggles.
|
|
112
|
+
*
|
|
113
|
+
* @param updater A function that receives the current value and returns the new value.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* const count = source(0);
|
|
118
|
+
* count.update(n => n + 1);
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
update(updater: (current: T) => T): void;
|
|
122
|
+
/**
|
|
123
|
+
* Manually subscribes to changes in the source value.
|
|
124
|
+
*
|
|
125
|
+
* @param listener A callback that receives the new value.
|
|
126
|
+
* @returns An unsubscription function.
|
|
127
|
+
*
|
|
128
|
+
* @note Most users should use `guard()` or `usePulse()` instead of manual subscriptions.
|
|
129
|
+
*/
|
|
130
|
+
subscribe(listener: Subscriber<T>): () => void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Creates a new Pulse Source.
|
|
134
|
+
*
|
|
135
|
+
* Sources are the fundamental building blocks of state in Pulse. They hold a value
|
|
136
|
+
* and track which Guards depend on them.
|
|
137
|
+
*
|
|
138
|
+
* @template T - The type of value to store.
|
|
139
|
+
* @param initialValue - The initial state.
|
|
140
|
+
* @param options - Configuration options (name, equality).
|
|
141
|
+
* @returns A reactive Pulse Source.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* const user = source({ name: 'Alice' }, { name: 'user_state' });
|
|
146
|
+
*
|
|
147
|
+
* // Read value (auto-tracks if inside a guard)
|
|
148
|
+
* console.log(user());
|
|
149
|
+
*
|
|
150
|
+
* // Update value
|
|
151
|
+
* user.set({ name: 'Bob' });
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
155
|
+
|
|
44
156
|
/**
|
|
45
157
|
* Status of a Pulse Guard evaluation.
|
|
46
158
|
* - 'pending': Async evaluation is in progress.
|
|
@@ -86,6 +198,7 @@ interface GuardExplanation {
|
|
|
86
198
|
name: string;
|
|
87
199
|
type: 'source' | 'guard';
|
|
88
200
|
status?: GuardStatus;
|
|
201
|
+
reason?: string | GuardReason;
|
|
89
202
|
}>;
|
|
90
203
|
}
|
|
91
204
|
/**
|
|
@@ -187,6 +300,9 @@ declare function guardFail(reason: string | GuardReason): never;
|
|
|
187
300
|
*/
|
|
188
301
|
declare function guardOk<T>(value: T): T;
|
|
189
302
|
declare function guard<T = boolean>(nameOrFn?: string | (() => T | Promise<T>), fn?: () => T | Promise<T>): Guard<T>;
|
|
303
|
+
declare namespace guard {
|
|
304
|
+
var map: <T, U>(source: Source<T>, mapper: (value: T) => U | Promise<U>, name?: string) => Guard<U>;
|
|
305
|
+
}
|
|
190
306
|
|
|
191
307
|
/**
|
|
192
308
|
* Utility to transform reactive dependencies into a new derived value.
|
|
@@ -251,118 +367,6 @@ declare function guardAny(nameOrGuards: string | Guard<any>[], maybeGuards?: Gua
|
|
|
251
367
|
*/
|
|
252
368
|
declare function guardNot(nameOrTarget: string | Guard<any> | (() => any), maybeTarget?: Guard<any> | (() => any)): Guard<boolean>;
|
|
253
369
|
|
|
254
|
-
/**
|
|
255
|
-
* Options for configuring a Pulse Source.
|
|
256
|
-
*
|
|
257
|
-
* @template T - The type of value stored in the source.
|
|
258
|
-
*/
|
|
259
|
-
interface SourceOptions<T> {
|
|
260
|
-
/**
|
|
261
|
-
* A descriptive name for the source.
|
|
262
|
-
* Required for SSR hydration and highly recommended for debugging in DevTools.
|
|
263
|
-
*/
|
|
264
|
-
name?: string;
|
|
265
|
-
/**
|
|
266
|
-
* Custom equality function to determine if a value has changed.
|
|
267
|
-
* By default, Pulse uses strict equality (`===`).
|
|
268
|
-
*
|
|
269
|
-
* @param a - The current value.
|
|
270
|
-
* @param b - The new value.
|
|
271
|
-
* @returns `true` if the values are considered equal, `false` otherwise.
|
|
272
|
-
*
|
|
273
|
-
* @example
|
|
274
|
-
* ```ts
|
|
275
|
-
* const list = source([1], {
|
|
276
|
-
* equals: (a, b) => a.length === b.length
|
|
277
|
-
* });
|
|
278
|
-
* ```
|
|
279
|
-
*/
|
|
280
|
-
equals?: (a: T, b: T) => boolean;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* A Pulse Source is a reactive container for a value.
|
|
284
|
-
* It tracks which Guards read its value and notifies them when it changes.
|
|
285
|
-
*
|
|
286
|
-
* @template T The type of the value held by the source.
|
|
287
|
-
*/
|
|
288
|
-
interface Source<T> {
|
|
289
|
-
/**
|
|
290
|
-
* Returns the current value of the source.
|
|
291
|
-
* If called within a Guard evaluation, it automatically registers that Guard as a dependent.
|
|
292
|
-
*
|
|
293
|
-
* @example
|
|
294
|
-
* ```ts
|
|
295
|
-
* const count = source(0);
|
|
296
|
-
* console.log(count()); // 0
|
|
297
|
-
* ```
|
|
298
|
-
*/
|
|
299
|
-
(): T;
|
|
300
|
-
/**
|
|
301
|
-
* Updates the source with a new value.
|
|
302
|
-
* If the value is different (based on strict equality or `options.equals`),
|
|
303
|
-
* all dependent Guards and subscribers will be notified.
|
|
304
|
-
*
|
|
305
|
-
* @param value The new value to set.
|
|
306
|
-
*
|
|
307
|
-
* @example
|
|
308
|
-
* ```ts
|
|
309
|
-
* const count = source(0);
|
|
310
|
-
* count.set(1); // Triggers re-evaluation of dependents
|
|
311
|
-
* ```
|
|
312
|
-
*
|
|
313
|
-
* @error
|
|
314
|
-
* Common error: Mutating an object property without setting a new object reference.
|
|
315
|
-
* Pulse uses reference equality by default. If you mutate a property, Pulse won't know it changed.
|
|
316
|
-
* Solution: Always provide a new object or implement a custom `equals`.
|
|
317
|
-
*/
|
|
318
|
-
set(value: T): void;
|
|
319
|
-
/**
|
|
320
|
-
* Updates the source value using a transformer function based on the current value.
|
|
321
|
-
* Useful for increments or toggles.
|
|
322
|
-
*
|
|
323
|
-
* @param updater A function that receives the current value and returns the new value.
|
|
324
|
-
*
|
|
325
|
-
* @example
|
|
326
|
-
* ```ts
|
|
327
|
-
* const count = source(0);
|
|
328
|
-
* count.update(n => n + 1);
|
|
329
|
-
* ```
|
|
330
|
-
*/
|
|
331
|
-
update(updater: (current: T) => T): void;
|
|
332
|
-
/**
|
|
333
|
-
* Manually subscribes to changes in the source value.
|
|
334
|
-
*
|
|
335
|
-
* @param listener A callback that receives the new value.
|
|
336
|
-
* @returns An unsubscription function.
|
|
337
|
-
*
|
|
338
|
-
* @note Most users should use `guard()` or `usePulse()` instead of manual subscriptions.
|
|
339
|
-
*/
|
|
340
|
-
subscribe(listener: Subscriber<T>): () => void;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Creates a new Pulse Source.
|
|
344
|
-
*
|
|
345
|
-
* Sources are the fundamental building blocks of state in Pulse. They hold a value
|
|
346
|
-
* and track which Guards depend on them.
|
|
347
|
-
*
|
|
348
|
-
* @template T - The type of value to store.
|
|
349
|
-
* @param initialValue - The initial state.
|
|
350
|
-
* @param options - Configuration options (name, equality).
|
|
351
|
-
* @returns A reactive Pulse Source.
|
|
352
|
-
*
|
|
353
|
-
* @example
|
|
354
|
-
* ```ts
|
|
355
|
-
* const user = source({ name: 'Alice' }, { name: 'user_state' });
|
|
356
|
-
*
|
|
357
|
-
* // Read value (auto-tracks if inside a guard)
|
|
358
|
-
* console.log(user());
|
|
359
|
-
*
|
|
360
|
-
* // Update value
|
|
361
|
-
* user.set({ name: 'Bob' });
|
|
362
|
-
* ```
|
|
363
|
-
*/
|
|
364
|
-
declare function source<T>(initialValue: T, options?: SourceOptions<T>): Source<T>;
|
|
365
|
-
|
|
366
370
|
/**
|
|
367
371
|
* Serialized state of guards for transfer from server to client.
|
|
368
372
|
*/
|
|
@@ -455,6 +459,17 @@ declare class Registry {
|
|
|
455
459
|
}
|
|
456
460
|
declare const PulseRegistry: Registry;
|
|
457
461
|
|
|
462
|
+
/**
|
|
463
|
+
* Extracts the result type T from a Guard<T>.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* const authGuard = guard('auth', async () => fetchUser());
|
|
468
|
+
* type AuthUser = InferGuardType<typeof authGuard>; // User
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
type InferGuardType<T> = T extends Guard<infer U> ? U : never;
|
|
472
|
+
|
|
458
473
|
/**
|
|
459
474
|
* Pulse Guard with integrated Composition Helpers.
|
|
460
475
|
*
|
|
@@ -474,4 +489,4 @@ declare const extendedGuard: typeof guard & {
|
|
|
474
489
|
compute: typeof compute;
|
|
475
490
|
};
|
|
476
491
|
|
|
477
|
-
export { type Guard, type GuardExplanation, type GuardNode, type GuardReason, type GuardState, type GuardStatus, type HydrationState, PulseRegistry, type PulseUnit, type Source, type SourceOptions, type Subscriber, type Trackable, compute, evaluate, getCurrentGuard, extendedGuard as guard, guardFail, guardOk, hydrate, registerGuardForHydration, runInContext, source };
|
|
492
|
+
export { type Guard, type GuardExplanation, type GuardNode, type GuardReason, type GuardState, type GuardStatus, type HydrationState, type InferGuardType, PulseRegistry, type PulseUnit, type Source, type SourceOptions, type Subscriber, type Trackable, compute, evaluate, getCurrentGuard, extendedGuard as guard, guardFail, guardOk, hydrate, registerGuardForHydration, runInContext, source };
|
package/dist/index.js
CHANGED
|
@@ -223,11 +223,20 @@ function guard(nameOrFn, fn) {
|
|
|
223
223
|
lastDeps.forEach((dep) => {
|
|
224
224
|
const depName = dep._name || "unnamed";
|
|
225
225
|
const isG = "state" in dep;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
226
|
+
if (isG) {
|
|
227
|
+
const depState = dep.state();
|
|
228
|
+
deps.push({
|
|
229
|
+
name: depName,
|
|
230
|
+
type: "guard",
|
|
231
|
+
status: depState.status,
|
|
232
|
+
reason: depState.status === "fail" ? depState.reason : void 0
|
|
233
|
+
});
|
|
234
|
+
} else {
|
|
235
|
+
deps.push({
|
|
236
|
+
name: depName,
|
|
237
|
+
type: "source"
|
|
238
|
+
});
|
|
239
|
+
}
|
|
231
240
|
});
|
|
232
241
|
return {
|
|
233
242
|
name: name || "guard",
|
|
@@ -252,6 +261,13 @@ function guard(nameOrFn, fn) {
|
|
|
252
261
|
evaluate2();
|
|
253
262
|
return g;
|
|
254
263
|
}
|
|
264
|
+
guard.map = function(source2, mapper, name) {
|
|
265
|
+
const guardName = name || `map-${source2._name || "source"}`;
|
|
266
|
+
return guard(guardName, () => {
|
|
267
|
+
const value = source2();
|
|
268
|
+
return mapper(value);
|
|
269
|
+
});
|
|
270
|
+
};
|
|
255
271
|
|
|
256
272
|
// src/registry.ts
|
|
257
273
|
var Registry = class {
|