@bodil/signal 0.2.2 → 0.3.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.d.ts CHANGED
@@ -1,31 +1,38 @@
1
1
  import { Signal } from "signal-polyfill";
2
2
  import { type Disposifiable } from "@bodil/disposable";
3
- interface ReadableSignal<A> {
3
+ interface ISignal<A> {
4
4
  readonly value: A;
5
5
  map<B>(fn: (value: A) => B): ComputedSignal<B>;
6
6
  on(callback: (value: A) => void): Disposable;
7
7
  }
8
- export declare class StateSignal<A> extends Signal.State<A> implements ReadableSignal<A> {
8
+ declare class StateSignal<A> extends Signal.State<A> implements ISignal<A> {
9
9
  get value(): A;
10
10
  set value(value: A);
11
11
  update(fn: (value: A) => A): void;
12
12
  readOnly(): ComputedSignal<A>;
13
13
  map<B>(fn: (value: A) => B): ComputedSignal<B>;
14
14
  on(callback: (value: A) => void): Disposable;
15
+ static is(v: unknown): v is StateSignal<unknown>;
15
16
  }
16
- export declare class ComputedSignal<A> extends Signal.Computed<A> implements ReadableSignal<A> {
17
+ declare class ComputedSignal<A> extends Signal.Computed<A> implements ISignal<A> {
17
18
  get value(): A;
18
19
  map<B>(fn: (value: A) => B): ComputedSignal<B>;
19
20
  on(callback: (value: A) => void): Disposable;
21
+ static is(v: unknown): v is ComputedSignal<unknown>;
20
22
  }
21
- type AnySignal<A> = StateSignal<A> | ComputedSignal<A>;
22
- export type { AnySignal as Signal };
23
- export declare const subtle: typeof Signal.subtle;
24
- export declare function isStateSignal(v: unknown): v is StateSignal<unknown>;
25
- export declare function isComputedSignal(v: unknown): v is ComputedSignal<unknown>;
26
- export declare function isSignal(v: unknown): v is AnySignal<unknown>;
27
- export declare function signal<A>(value: A, options?: Signal.Options<A>): StateSignal<A>;
28
- export declare function computed<A>(fn: (this: ComputedSignal<A>) => A, options?: Signal.Options<A>): ComputedSignal<A>;
29
- export declare function effect(fn: () => Disposifiable | void): Disposable;
30
- export declare function subscribe<A>(signal: ReadableSignal<A>, callback: (value: A) => void): Disposable;
31
- export declare function asyncComputed<A>(fn: (abort: AbortSignal) => Promise<A>, options?: Signal.Options<A>): Promise<ComputedSignal<A>>;
23
+ type SignalGlobal<A> = StateSignal<A> | ComputedSignal<A>;
24
+ declare const SignalGlobal: (<A>(value: A, options?: Signal.Options<A>) => SignalGlobal.State<A>) & {
25
+ is(v: unknown): v is SignalGlobal<unknown>;
26
+ computed<A>(fn: (this: ComputedSignal<A>) => A, options?: Signal.Options<A>): SignalGlobal.Computed<A>;
27
+ subscribe<A>(signal: ISignal<A>, callback: (value: A) => void): Disposable;
28
+ effect(fn: () => Disposifiable | void): Disposable;
29
+ asyncComputed<A>(fn: (abort: AbortSignal) => Promise<A>, options?: Signal.Options<A>): Promise<SignalGlobal.Computed<A>>;
30
+ State: typeof StateSignal;
31
+ Computed: typeof ComputedSignal;
32
+ subtle: typeof Signal.subtle;
33
+ };
34
+ declare namespace SignalGlobal {
35
+ type State<A> = StateSignal<A>;
36
+ type Computed<A> = ComputedSignal<A>;
37
+ }
38
+ export { SignalGlobal as Signal };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Signal } from "signal-polyfill";
2
2
  import { toDisposable } from "@bodil/disposable";
3
3
  import { Err, Ok, Async } from "@bodil/core";
4
- export class StateSignal extends Signal.State {
4
+ class StateSignal extends Signal.State {
5
5
  get value() {
6
6
  return this.get();
7
7
  }
@@ -12,41 +12,31 @@ export class StateSignal extends Signal.State {
12
12
  this.set(Signal.subtle.untrack(() => fn(this.get())));
13
13
  }
14
14
  readOnly() {
15
- return computed(() => this.get());
15
+ return SignalGlobal.computed(() => this.get());
16
16
  }
17
17
  map(fn) {
18
- return computed(() => fn(this.get()));
18
+ return SignalGlobal.computed(() => fn(this.get()));
19
19
  }
20
20
  on(callback) {
21
- return subscribe(this, callback);
21
+ return SignalGlobal.subscribe(this, callback);
22
+ }
23
+ static is(v) {
24
+ return v instanceof StateSignal;
22
25
  }
23
26
  }
24
- export class ComputedSignal extends Signal.Computed {
27
+ class ComputedSignal extends Signal.Computed {
25
28
  get value() {
26
29
  return this.get();
27
30
  }
28
31
  map(fn) {
29
- return computed(() => fn(this.get()));
32
+ return SignalGlobal.computed(() => fn(this.get()));
30
33
  }
31
34
  on(callback) {
32
- return subscribe(this, callback);
35
+ return SignalGlobal.subscribe(this, callback);
36
+ }
37
+ static is(v) {
38
+ return v instanceof ComputedSignal;
33
39
  }
34
- }
35
- export const subtle = Signal.subtle;
36
- export function isStateSignal(v) {
37
- return v instanceof StateSignal;
38
- }
39
- export function isComputedSignal(v) {
40
- return v instanceof ComputedSignal;
41
- }
42
- export function isSignal(v) {
43
- return isStateSignal(v) || isComputedSignal(v);
44
- }
45
- export function signal(value, options) {
46
- return new StateSignal(value, options);
47
- }
48
- export function computed(fn, options) {
49
- return new ComputedSignal(fn, options);
50
40
  }
51
41
  let effectNeedsEnqueue = true;
52
42
  const effectWatcher = new Signal.subtle.Watcher(() => {
@@ -62,55 +52,69 @@ function effectProcess() {
62
52
  }
63
53
  effectWatcher.watch();
64
54
  }
65
- export function effect(fn) {
66
- let cleanup;
67
- const computed = new ComputedSignal(() => {
68
- if (cleanup !== undefined) {
69
- cleanup[Symbol.dispose]();
70
- }
71
- const result = fn();
72
- cleanup = result !== undefined ? toDisposable(result) : undefined;
73
- });
74
- effectWatcher.watch(computed);
75
- computed.get();
76
- return toDisposable(() => {
77
- effectWatcher.unwatch(computed);
78
- if (cleanup !== undefined) {
79
- cleanup[Symbol.dispose]();
80
- }
81
- });
82
- }
83
- export function subscribe(signal, callback) {
84
- return effect(() => callback(signal.value));
85
- }
86
- export function asyncComputed(fn, options) {
87
- const result = Promise.withResolvers();
88
- const stream = computed(() => Async.abortable(fn));
89
- const sig = signal(Err(new Error()));
90
- let job = undefined;
91
- let resolved = false;
92
- const resolve = () => {
93
- if (!resolved) {
94
- resolved = true;
95
- result.resolve(computed(() => sig.get().unwrapExact(), options));
96
- }
97
- };
98
- effect(() => {
99
- if (job !== undefined) {
100
- job.abort();
101
- }
102
- job = stream.get();
103
- job.result.then((next) => {
104
- sig.set(Ok(next));
105
- resolve();
106
- }, (error) => {
107
- if (job?.signal.aborted === true) {
108
- return;
55
+ const SignalGlobal = Object.assign(function (value, options) {
56
+ return new StateSignal(value, options);
57
+ }, {
58
+ is(v) {
59
+ return StateSignal.is(v) || ComputedSignal.is(v);
60
+ },
61
+ computed(fn, options) {
62
+ return new ComputedSignal(fn, options);
63
+ },
64
+ subscribe(signal, callback) {
65
+ return SignalGlobal.effect(() => callback(signal.value));
66
+ },
67
+ effect(fn) {
68
+ let cleanup;
69
+ const computed = new ComputedSignal(() => {
70
+ if (cleanup !== undefined) {
71
+ cleanup[Symbol.dispose]();
109
72
  }
110
- sig.set(Err(error));
111
- resolve();
73
+ const result = fn();
74
+ cleanup = result !== undefined ? toDisposable(result) : undefined;
112
75
  });
113
- });
114
- return result.promise;
115
- }
76
+ effectWatcher.watch(computed);
77
+ computed.get();
78
+ return toDisposable(() => {
79
+ effectWatcher.unwatch(computed);
80
+ if (cleanup !== undefined) {
81
+ cleanup[Symbol.dispose]();
82
+ }
83
+ });
84
+ },
85
+ asyncComputed(fn, options) {
86
+ const result = Promise.withResolvers();
87
+ const stream = SignalGlobal.computed(() => Async.abortable(fn));
88
+ const sig = SignalGlobal(Err(new Error()));
89
+ let job = undefined;
90
+ let resolved = false;
91
+ const resolve = () => {
92
+ if (!resolved) {
93
+ resolved = true;
94
+ result.resolve(SignalGlobal.computed(() => sig.get().unwrapExact(), options));
95
+ }
96
+ };
97
+ SignalGlobal.effect(() => {
98
+ if (job !== undefined) {
99
+ job.abort();
100
+ }
101
+ job = stream.get();
102
+ job.result.then((next) => {
103
+ sig.set(Ok(next));
104
+ resolve();
105
+ }, (error) => {
106
+ if (job?.signal.aborted === true) {
107
+ return;
108
+ }
109
+ sig.set(Err(error));
110
+ resolve();
111
+ });
112
+ });
113
+ return result.promise;
114
+ },
115
+ State: StateSignal,
116
+ Computed: ComputedSignal,
117
+ subtle: Signal.subtle,
118
+ });
119
+ export { SignalGlobal as Signal };
116
120
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAsB,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,KAAK,EAAE,MAAM,aAAa,CAAC;AAQ1D,MAAM,OAAO,WAAe,SAAQ,MAAM,CAAC,KAAQ;IAC/C,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,IAAI,KAAK,CAAC,KAAQ;QACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,EAAmB;QACtB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,QAAQ;QACJ,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,GAAG,CAAI,EAAmB;QACtB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,EAAE,CAAC,QAA4B;QAC3B,OAAO,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;CACJ;AAED,MAAM,OAAO,cAAkB,SAAQ,MAAM,CAAC,QAAW;IACrD,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,CAAC;IAED,GAAG,CAAI,EAAmB;QACtB,OAAO,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,EAAE,CAAC,QAA4B;QAC3B,OAAO,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;CACJ;AAMD,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AAEpC,MAAM,UAAU,aAAa,CAAC,CAAU;IACpC,OAAO,CAAC,YAAY,WAAW,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAU;IACvC,OAAO,CAAC,YAAY,cAAc,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAU;IAC/B,OAAO,aAAa,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,MAAM,CAAI,KAAQ,EAAE,OAA2B;IAC3D,OAAO,IAAI,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,QAAQ,CACpB,EAAkC,EAClC,OAA2B;IAE3B,OAAO,IAAI,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,IAAI,kBAAkB,GAAG,IAAI,CAAC;AAC9B,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;IACjD,IAAI,kBAAkB,EAAE,CAAC;QACrB,kBAAkB,GAAG,KAAK,CAAC;QAC3B,cAAc,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,SAAS,aAAa;IAClB,kBAAkB,GAAG,IAAI,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC;QAC3C,GAAG,CAAC,GAAG,EAAE,CAAC;IACd,CAAC;IACD,aAAa,CAAC,KAAK,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EAA8B;IACjD,IAAI,OAA+B,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE;QACrC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;QACpB,OAAO,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,CAAC,CAAC,CAAC;IACH,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,CAAC;IACf,OAAO,YAAY,CAAC,GAAG,EAAE;QACrB,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,MAAyB,EAAE,QAA4B;IAChF,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,aAAa,CACzB,EAAsC,EACtC,OAA2B;IAE3B,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,EAAqB,CAAC;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,MAAM,GAAG,GAAkC,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;IACpE,IAAI,GAAG,GAAsC,SAAS,CAAC;IACvD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,OAAO,GAAG,GAAG,EAAE;QACjB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,QAAQ,GAAG,IAAI,CAAC;YAChB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACrE,CAAC;IACL,CAAC,CAAC;IACF,MAAM,CAAC,GAAG,EAAE;QACR,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACpB,GAAG,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;QACD,GAAG,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;QACnB,GAAG,CAAC,MAAM,CAAC,IAAI,CACX,CAAC,IAAI,EAAE,EAAE;YACL,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;YAClB,OAAO,EAAE,CAAC;QACd,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACN,IAAI,GAAG,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC/B,OAAO;YACX,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YACpB,OAAO,EAAE,CAAC;QACd,CAAC,CACJ,CAAC;IACN,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,OAAO,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { sleep } from "@bodil/core/async";
2
2
  import { expect, test } from "vitest";
3
- import { asyncComputed, computed, effect, isComputedSignal, isSignal, isStateSignal, signal, } from ".";
3
+ import { Signal } from ".";
4
4
  test("Signal", async () => {
5
- const sig = signal(0);
5
+ const sig = Signal(0);
6
6
  const result = [];
7
- effect(() => void result.push(sig.value));
7
+ Signal.effect(() => void result.push(sig.value));
8
8
  expect(result).toEqual([0]);
9
9
  sig.value = 1;
10
10
  sig.value = 2;
@@ -24,8 +24,8 @@ test("Signal", async () => {
24
24
  });
25
25
  test("signal equality", async () => {
26
26
  const result = [];
27
- const sig = signal(0);
28
- effect(() => void result.push(sig.value));
27
+ const sig = Signal(0);
28
+ Signal.effect(() => void result.push(sig.value));
29
29
  expect(result).toEqual([0]);
30
30
  sig.value = 1;
31
31
  await sleep(1);
@@ -50,11 +50,11 @@ test("signal equality", async () => {
50
50
  expect(result).toEqual([0, 1, 2, 3, 2]);
51
51
  });
52
52
  test("asyncComputed", async () => {
53
- const s = signal(1);
54
- const c = await asyncComputed(() => Promise.resolve(s.value + 1));
53
+ const s = Signal(1);
54
+ const c = await Signal.asyncComputed(() => Promise.resolve(s.value + 1));
55
55
  expect(c.value).toEqual(2);
56
56
  try {
57
- await asyncComputed(() => {
57
+ await Signal.asyncComputed(() => {
58
58
  throw new Error("welp!");
59
59
  });
60
60
  throw new Error("computed error failed to throw");
@@ -75,14 +75,24 @@ test("asyncComputed", async () => {
75
75
  expect(c.value).toEqual(4);
76
76
  });
77
77
  test("isSignal", () => {
78
- const s1 = signal(1);
79
- expect(isSignal(s1)).toBeTruthy();
80
- expect(isStateSignal(s1)).toBeTruthy();
81
- expect(isComputedSignal(s1)).toBeFalsy();
82
- const s2 = computed(() => 2);
83
- expect(isSignal(s2)).toBeTruthy();
84
- expect(isStateSignal(s2)).toBeFalsy();
85
- expect(isComputedSignal(s2)).toBeTruthy();
86
- expect(isSignal("wibble")).toBeFalsy();
78
+ const s1 = Signal(1);
79
+ expect(Signal.is(s1)).toBeTruthy();
80
+ expect(Signal.State.is(s1)).toBeTruthy();
81
+ expect(Signal.Computed.is(s1)).toBeFalsy();
82
+ const s2 = Signal.computed(() => 2);
83
+ expect(Signal.is(s2)).toBeTruthy();
84
+ expect(Signal.State.is(s2)).toBeFalsy();
85
+ expect(Signal.Computed.is(s2)).toBeTruthy();
86
+ expect(Signal.is("wibble")).toBeFalsy();
87
+ });
88
+ test("Signal types", () => {
89
+ const s1 = Signal(1);
90
+ const s2 = Signal.computed(() => s1.get());
91
+ function foo(_signal) {
92
+ // ensure Signal<A> is an accessible type
93
+ // and that it accepts both concrete signal types.
94
+ }
95
+ foo(s1);
96
+ foo(s2);
87
97
  });
88
98
  //# sourceMappingURL=signal.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signal.test.js","sourceRoot":"","sources":["../src/signal.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signal.test.js","sourceRoot":"","sources":["../src/signal.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAgB,IAAI,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC;AAE3B,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IACtB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAC3C,UAAU,CAAC,GAAG,EAAE;QACZ,IAAI,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,CAAU,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC,EAAE,CAAC,CAAC,CAAC;IACN,MAAM,IAAI,CAAC,OAAO,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iBAAiB,EAAE,KAAK,IAAI,EAAE;IAC/B,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC;QACD,MAAM,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE;YAC5B,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IACD,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IACZ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IACZ,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IACZ,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;IACZ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;IACf,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;IAClB,MAAM,EAAE,GAAyB,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IACzC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAE3C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IACxC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IAE5C,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE;IACtB,MAAM,EAAE,GAAyB,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,EAAE,GAA4B,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IAEpE,SAAS,GAAG,CAAC,OAAwB;QACjC,yCAAyC;QACzC,kDAAkD;IACtD,CAAC;IACD,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,GAAG,CAAC,EAAE,CAAC,CAAC;AACZ,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bodil/signal",
3
- "version": "0.2.2",
4
- "description": "Preact Signals like signal implementation built on the TC39 Signals Proposal",
3
+ "version": "0.3.1",
4
+ "description": "Signal implementation built on the TC39 Signals Proposal",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/bodil/signal.git"
package/src/index.ts CHANGED
@@ -2,13 +2,13 @@ import { Signal } from "signal-polyfill";
2
2
  import { toDisposable, type Disposifiable } from "@bodil/disposable";
3
3
  import { Err, Ok, type Result, Async } from "@bodil/core";
4
4
 
5
- interface ReadableSignal<A> {
5
+ interface ISignal<A> {
6
6
  readonly value: A;
7
7
  map<B>(fn: (value: A) => B): ComputedSignal<B>;
8
8
  on(callback: (value: A) => void): Disposable;
9
9
  }
10
10
 
11
- export class StateSignal<A> extends Signal.State<A> implements ReadableSignal<A> {
11
+ class StateSignal<A> extends Signal.State<A> implements ISignal<A> {
12
12
  get value(): A {
13
13
  return this.get();
14
14
  }
@@ -22,59 +22,38 @@ export class StateSignal<A> extends Signal.State<A> implements ReadableSignal<A>
22
22
  }
23
23
 
24
24
  readOnly(): ComputedSignal<A> {
25
- return computed(() => this.get());
25
+ return SignalGlobal.computed(() => this.get());
26
26
  }
27
27
 
28
28
  map<B>(fn: (value: A) => B): ComputedSignal<B> {
29
- return computed(() => fn(this.get()));
29
+ return SignalGlobal.computed(() => fn(this.get()));
30
30
  }
31
31
 
32
32
  on(callback: (value: A) => void): Disposable {
33
- return subscribe(this, callback);
33
+ return SignalGlobal.subscribe(this, callback);
34
+ }
35
+
36
+ static is(v: unknown): v is StateSignal<unknown> {
37
+ return v instanceof StateSignal;
34
38
  }
35
39
  }
36
40
 
37
- export class ComputedSignal<A> extends Signal.Computed<A> implements ReadableSignal<A> {
41
+ class ComputedSignal<A> extends Signal.Computed<A> implements ISignal<A> {
38
42
  get value(): A {
39
43
  return this.get();
40
44
  }
41
45
 
42
46
  map<B>(fn: (value: A) => B): ComputedSignal<B> {
43
- return computed(() => fn(this.get()));
47
+ return SignalGlobal.computed(() => fn(this.get()));
44
48
  }
45
49
 
46
50
  on(callback: (value: A) => void): Disposable {
47
- return subscribe(this, callback);
51
+ return SignalGlobal.subscribe(this, callback);
48
52
  }
49
- }
50
-
51
- type AnySignal<A> = StateSignal<A> | ComputedSignal<A>;
52
-
53
- export type { AnySignal as Signal };
54
-
55
- export const subtle = Signal.subtle;
56
-
57
- export function isStateSignal(v: unknown): v is StateSignal<unknown> {
58
- return v instanceof StateSignal;
59
- }
60
-
61
- export function isComputedSignal(v: unknown): v is ComputedSignal<unknown> {
62
- return v instanceof ComputedSignal;
63
- }
64
-
65
- export function isSignal(v: unknown): v is AnySignal<unknown> {
66
- return isStateSignal(v) || isComputedSignal(v);
67
- }
68
53
 
69
- export function signal<A>(value: A, options?: Signal.Options<A>): StateSignal<A> {
70
- return new StateSignal(value, options);
71
- }
72
-
73
- export function computed<A>(
74
- fn: (this: ComputedSignal<A>) => A,
75
- options?: Signal.Options<A>
76
- ): ComputedSignal<A> {
77
- return new ComputedSignal(fn, options);
54
+ static is(v: unknown): v is ComputedSignal<unknown> {
55
+ return v instanceof ComputedSignal;
56
+ }
78
57
  }
79
58
 
80
59
  let effectNeedsEnqueue = true;
@@ -93,62 +72,93 @@ function effectProcess(): void {
93
72
  effectWatcher.watch();
94
73
  }
95
74
 
96
- export function effect(fn: () => Disposifiable | void): Disposable {
97
- let cleanup: Disposable | undefined;
98
- const computed = new ComputedSignal(() => {
99
- if (cleanup !== undefined) {
100
- cleanup[Symbol.dispose]();
101
- }
102
- const result = fn();
103
- cleanup = result !== undefined ? toDisposable(result) : undefined;
104
- });
105
- effectWatcher.watch(computed);
106
- computed.get();
107
- return toDisposable(() => {
108
- effectWatcher.unwatch(computed);
109
- if (cleanup !== undefined) {
110
- cleanup[Symbol.dispose]();
111
- }
112
- });
113
- }
75
+ type SignalGlobal<A> = StateSignal<A> | ComputedSignal<A>;
76
+
77
+ const SignalGlobal = Object.assign(
78
+ function <A>(value: A, options?: Signal.Options<A>): SignalGlobal.State<A> {
79
+ return new StateSignal(value, options);
80
+ },
81
+ {
82
+ is(v: unknown): v is SignalGlobal<unknown> {
83
+ return StateSignal.is(v) || ComputedSignal.is(v);
84
+ },
85
+
86
+ computed<A>(
87
+ fn: (this: ComputedSignal<A>) => A,
88
+ options?: Signal.Options<A>
89
+ ): SignalGlobal.Computed<A> {
90
+ return new ComputedSignal(fn, options);
91
+ },
92
+
93
+ subscribe<A>(signal: ISignal<A>, callback: (value: A) => void): Disposable {
94
+ return SignalGlobal.effect(() => callback(signal.value));
95
+ },
96
+
97
+ effect(fn: () => Disposifiable | void): Disposable {
98
+ let cleanup: Disposable | undefined;
99
+ const computed = new ComputedSignal(() => {
100
+ if (cleanup !== undefined) {
101
+ cleanup[Symbol.dispose]();
102
+ }
103
+ const result = fn();
104
+ cleanup = result !== undefined ? toDisposable(result) : undefined;
105
+ });
106
+ effectWatcher.watch(computed);
107
+ computed.get();
108
+ return toDisposable(() => {
109
+ effectWatcher.unwatch(computed);
110
+ if (cleanup !== undefined) {
111
+ cleanup[Symbol.dispose]();
112
+ }
113
+ });
114
+ },
115
+
116
+ asyncComputed<A>(
117
+ fn: (abort: AbortSignal) => Promise<A>,
118
+ options?: Signal.Options<A>
119
+ ): Promise<SignalGlobal.Computed<A>> {
120
+ const result = Promise.withResolvers<ComputedSignal<A>>();
121
+ const stream = SignalGlobal.computed(() => Async.abortable(fn));
122
+ const sig: StateSignal<Result<A, Error>> = SignalGlobal(Err(new Error()));
123
+ let job: Async.AbortableJob<A> | undefined = undefined;
124
+ let resolved = false;
125
+ const resolve = () => {
126
+ if (!resolved) {
127
+ resolved = true;
128
+ result.resolve(SignalGlobal.computed(() => sig.get().unwrapExact(), options));
129
+ }
130
+ };
131
+ SignalGlobal.effect(() => {
132
+ if (job !== undefined) {
133
+ job.abort();
134
+ }
135
+ job = stream.get();
136
+ job.result.then(
137
+ (next) => {
138
+ sig.set(Ok(next));
139
+ resolve();
140
+ },
141
+ (error) => {
142
+ if (job?.signal.aborted === true) {
143
+ return;
144
+ }
145
+ sig.set(Err(error));
146
+ resolve();
147
+ }
148
+ );
149
+ });
150
+ return result.promise;
151
+ },
152
+
153
+ State: StateSignal,
154
+ Computed: ComputedSignal,
155
+ subtle: Signal.subtle,
156
+ }
157
+ );
114
158
 
115
- export function subscribe<A>(signal: ReadableSignal<A>, callback: (value: A) => void): Disposable {
116
- return effect(() => callback(signal.value));
159
+ declare namespace SignalGlobal {
160
+ export type State<A> = StateSignal<A>;
161
+ export type Computed<A> = ComputedSignal<A>;
117
162
  }
118
163
 
119
- export function asyncComputed<A>(
120
- fn: (abort: AbortSignal) => Promise<A>,
121
- options?: Signal.Options<A>
122
- ): Promise<ComputedSignal<A>> {
123
- const result = Promise.withResolvers<ComputedSignal<A>>();
124
- const stream = computed(() => Async.abortable(fn));
125
- const sig: StateSignal<Result<A, Error>> = signal(Err(new Error()));
126
- let job: Async.AbortableJob<A> | undefined = undefined;
127
- let resolved = false;
128
- const resolve = () => {
129
- if (!resolved) {
130
- resolved = true;
131
- result.resolve(computed(() => sig.get().unwrapExact(), options));
132
- }
133
- };
134
- effect(() => {
135
- if (job !== undefined) {
136
- job.abort();
137
- }
138
- job = stream.get();
139
- job.result.then(
140
- (next) => {
141
- sig.set(Ok(next));
142
- resolve();
143
- },
144
- (error) => {
145
- if (job?.signal.aborted === true) {
146
- return;
147
- }
148
- sig.set(Err(error));
149
- resolve();
150
- }
151
- );
152
- });
153
- return result.promise;
154
- }
164
+ export { SignalGlobal as Signal };
@@ -1,19 +1,11 @@
1
1
  import { sleep } from "@bodil/core/async";
2
- import { expect, test } from "vitest";
3
- import {
4
- asyncComputed,
5
- computed,
6
- effect,
7
- isComputedSignal,
8
- isSignal,
9
- isStateSignal,
10
- signal,
11
- } from ".";
2
+ import { expect, expectTypeOf, test } from "vitest";
3
+ import { Signal } from ".";
12
4
 
13
5
  test("Signal", async () => {
14
- const sig = signal(0);
6
+ const sig = Signal(0);
15
7
  const result: Array<number> = [];
16
- effect(() => void result.push(sig.value));
8
+ Signal.effect(() => void result.push(sig.value));
17
9
  expect(result).toEqual([0]);
18
10
  sig.value = 1;
19
11
  sig.value = 2;
@@ -33,8 +25,8 @@ test("Signal", async () => {
33
25
 
34
26
  test("signal equality", async () => {
35
27
  const result: Array<number> = [];
36
- const sig = signal(0);
37
- effect(() => void result.push(sig.value));
28
+ const sig = Signal(0);
29
+ Signal.effect(() => void result.push(sig.value));
38
30
  expect(result).toEqual([0]);
39
31
  sig.value = 1;
40
32
  await sleep(1);
@@ -60,11 +52,11 @@ test("signal equality", async () => {
60
52
  });
61
53
 
62
54
  test("asyncComputed", async () => {
63
- const s = signal(1);
64
- const c = await asyncComputed(() => Promise.resolve(s.value + 1));
55
+ const s = Signal(1);
56
+ const c = await Signal.asyncComputed(() => Promise.resolve(s.value + 1));
65
57
  expect(c.value).toEqual(2);
66
58
  try {
67
- await asyncComputed(() => {
59
+ await Signal.asyncComputed(() => {
68
60
  throw new Error("welp!");
69
61
  });
70
62
  throw new Error("computed error failed to throw");
@@ -85,15 +77,27 @@ test("asyncComputed", async () => {
85
77
  });
86
78
 
87
79
  test("isSignal", () => {
88
- const s1 = signal(1);
89
- expect(isSignal(s1)).toBeTruthy();
90
- expect(isStateSignal(s1)).toBeTruthy();
91
- expect(isComputedSignal(s1)).toBeFalsy();
80
+ const s1: Signal.State<number> = Signal(1);
81
+ expect(Signal.is(s1)).toBeTruthy();
82
+ expect(Signal.State.is(s1)).toBeTruthy();
83
+ expect(Signal.Computed.is(s1)).toBeFalsy();
92
84
 
93
- const s2 = computed(() => 2);
94
- expect(isSignal(s2)).toBeTruthy();
95
- expect(isStateSignal(s2)).toBeFalsy();
96
- expect(isComputedSignal(s2)).toBeTruthy();
85
+ const s2 = Signal.computed(() => 2);
86
+ expect(Signal.is(s2)).toBeTruthy();
87
+ expect(Signal.State.is(s2)).toBeFalsy();
88
+ expect(Signal.Computed.is(s2)).toBeTruthy();
97
89
 
98
- expect(isSignal("wibble")).toBeFalsy();
90
+ expect(Signal.is("wibble")).toBeFalsy();
91
+ });
92
+
93
+ test("Signal types", () => {
94
+ const s1: Signal.State<number> = Signal(1);
95
+ const s2: Signal.Computed<number> = Signal.computed(() => s1.get());
96
+
97
+ function foo(_signal: Signal<unknown>) {
98
+ // ensure Signal<A> is an accessible type
99
+ // and that it accepts both concrete signal types.
100
+ }
101
+ foo(s1);
102
+ foo(s2);
99
103
  });