@owanturist/signal 0.0.0 → 0.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/LICENSE +29 -0
- package/dist/chunk-BE3J7QIW.js +1 -0
- package/dist/chunk-BE3J7QIW.js.map +1 -0
- package/dist/chunk-NRM2F6O5.cjs +1 -0
- package/dist/chunk-NRM2F6O5.cjs.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +285 -0
- package/dist/index.d.ts +285 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/monitor-BQJbbQ1I.d.cts +69 -0
- package/dist/monitor-BQJbbQ1I.d.ts +69 -0
- package/dist/monitor-factory.cjs +1 -0
- package/dist/monitor-factory.cjs.map +1 -0
- package/dist/monitor-factory.d.cts +28 -0
- package/dist/monitor-factory.d.ts +28 -0
- package/dist/monitor-factory.js +1 -0
- package/dist/monitor-factory.js.map +1 -0
- package/package.json +6 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021, Anton Ovechkin
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function noop(){}var MonitorEmitQueue=class{constructor(){this.$=new Set,this.m=t=>{for(const o of Array.from(t)){const t=o.deref();t&&(t.T(),t.R?t.p():this.$.add(t))}}}N(){for(const t of this.$)t.p()}},Queue=null;function enqueue(t){if(Queue)return t(Queue.m);const o=t((Queue=new MonitorEmitQueue).m),i=Queue;return Queue=null,i.N(),o}var MONITOR_KEY=Symbol("monitor"),UNTRACKED_MONITOR={[MONITOR_KEY]:null};function attachToMonitor(t,o){t[MONITOR_KEY]?.I(o)}var implicitMonitor=UNTRACKED_MONITOR;function injectMonitor(t,o){const i=implicitMonitor;implicitMonitor=o;const n=t(o);return implicitMonitor=i,n}function extractMonitor(){return implicitMonitor}var MonitorEmitter=class{constructor(t,o){this.p=t,this.R=o,this.K=new Set,this.v=new WeakRef(this),this.M=()=>this.A()}Y(){for(const t of this.K)t.delete(this.v);this.K.clear()}A(){return this.Y(),t=this,{[MONITOR_KEY]:t};var t}I(t){t.add(this.v),this.K.add(t)}T(){this.M=()=>this.A(),this.Y()}},MonitorFactory=class{constructor(){this.p=noop,this.q=new MonitorEmitter(()=>{enqueue(this.p)},!1)}connect(t){return this.p=t,()=>{this.p=noop,this.q.T()}}get create(){return this.q.M}};export{enqueue,UNTRACKED_MONITOR,attachToMonitor,injectMonitor,extractMonitor,MonitorEmitter,MonitorFactory};//# sourceMappingURL=chunk-BE3J7QIW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../tools/src/noop.ts","../src/_internal/enqueue.ts","../src/_internal/monitor.ts","../src/_internal/monitor-emitter.ts","../src/monitor-factory.ts"],"sourcesContent":["function noop(): void {\n // no operation\n}\n\nexport { noop }\n","import type { DerivedSignal } from \"./derived-signal\"\nimport type { MonitorEmitter } from \"./monitor-emitter\"\n\n/**\n * Orchestrates invalidation and emission of {@link MonitorEmitter}s to prevent\n * re-subscription loops while ensuring {@link DerivedSignal}s observe the latest\n * state before downstream updates. Derived emitters are emitted immediately to\n * leverage their comparison logic, whereas direct emitters are batched and\n * flushed later via {@link MonitorEmitQueue._process}, avoiding redundant\n * scheduling while maintaining consistent propagation order.\n */\nclass MonitorEmitQueue {\n private readonly _emitters = new Set<MonitorEmitter>()\n\n /**\n * Adds the provided emitters to the queue for later processing.\n *\n * @remarks Invalidates each emitter immediately so that {@link DerivedSignal}s observe the latest version,\n * then triggers derived emitters synchronously to leverage their comparison logic, while\n * queueing non-derived emitters for deferred emission.\n *\n * @param emitters - The captured set of weak references to {@link MonitorEmitter}s awaiting processing.\n */\n public readonly _push = (emitters: ReadonlySet<WeakRef<MonitorEmitter>>): void => {\n /**\n * Calling the {@link MonitorEmitter._emit} might cause the same {@link Signal} (host of the {@link emitters})\n * to be scheduled again for the same monitor ({@link DerivedSignal} when source sets the comparably equal value).\n * It causes infinite loop, where the {@link MonitorEmitter._invalidate} first unsubscribes from the source {@link Signal} but\n * the {@link DerivedSignal}'s {@link MonitorEmitter._emit} subscribes it back.\n *\n * To prevent this, the _push should only iterate over the emitters present at the moment of the call.\n */\n for (const ref of Array.from(emitters)) {\n const emitter = ref.deref()\n\n if (emitter) {\n /**\n * Invalidate the emitter as soon as it is scheduled\n * so the {@link DerivedSignal}s can read a fresh value due to version increment.\n */\n emitter._invalidate()\n\n if (emitter._derived) {\n /**\n * Emit immediately so {@link DerivedSignal}s utilize the equals function to either:\n * 1. NOT CHANGED: resubscribe to sources\n * 2. CHANGED: marks as stale and _push's its._emitters so they end up here either emitting ({@link DerivedSignal}) or scheduling ({@link Signal}).\n */\n emitter._emit()\n } else {\n // Schedule the emit when all the emitters are collected.\n this._emitters.add(emitter)\n }\n }\n }\n }\n\n /**\n * Iterates through all registered emitters and triggers their emission cycle.\n */\n public _process(): void {\n for (const emitter of this._emitters) {\n emitter._emit()\n }\n }\n}\n\nlet Queue: null | MonitorEmitQueue = null\n\n/**\n * Runs a queue-backed execution block, ensuring that nested enqueue calls share\n * the same monitor emit queue and that queued emitters are processed exactly once.\n *\n * @template TResult - The value returned by the execution block.\n * @param execute - Callback invoked with the active monitor emit queue.\n *\n * @returns The value produced by the provided execution block.\n */\nfunction enqueue<TResult>(\n execute: (push: (emitters: ReadonlySet<WeakRef<MonitorEmitter>>) => void) => TResult,\n): TResult {\n // Continue the execution if the queue is already initialized.\n if (Queue) {\n return execute(Queue._push)\n }\n\n // Initialize the queue and start the execution sequence.\n Queue = new MonitorEmitQueue()\n\n /**\n * The execution might lead to other {@link enqueue} calls,\n * so they all will collect the emitters in the same queue\n * ensuring that an emitter is emitted only once.\n */\n const result = execute(Queue._push)\n\n const tmp = Queue\n\n /**\n * Drop the global queue before processing to allow nested scheduling,\n * when {@link MonitorEmitter._emit} enqueues new emitters for the next tick.\n */\n Queue = null\n\n tmp._process()\n\n return result\n}\n\nexport { enqueue }\n","import type { MonitorEmitter } from \"./monitor-emitter\"\n\nconst MONITOR_KEY = Symbol(\"monitor\")\n\n/**\n * @version 1.0.0\n */\ninterface Monitor {\n readonly [MONITOR_KEY]: null | MonitorEmitter\n}\n\nconst UNTRACKED_MONITOR = {\n [MONITOR_KEY]: null,\n} satisfies Monitor\n\nfunction createMonitor(emitter: MonitorEmitter): Monitor {\n return {\n [MONITOR_KEY]: emitter,\n }\n}\n\nfunction attachToMonitor(monitor: Monitor, emitters: Set<WeakRef<MonitorEmitter>>): void {\n monitor[MONITOR_KEY]?._attachTo(emitters)\n}\n\nlet implicitMonitor: Monitor = UNTRACKED_MONITOR\n\nfunction injectMonitor<TResult>(\n execute: (_monitor: Monitor) => TResult,\n monitor: Monitor,\n): TResult {\n const prevMonitor = implicitMonitor\n\n implicitMonitor = monitor\n const result = execute(monitor)\n implicitMonitor = prevMonitor\n\n return result\n}\n\nfunction extractMonitor(): Monitor {\n return implicitMonitor\n}\n\nexport type { Monitor }\nexport { UNTRACKED_MONITOR, createMonitor, attachToMonitor, injectMonitor, extractMonitor }\n","import type { Signal } from \"../signal\"\n\nimport type { DerivedSignal } from \"./derived-signal\"\nimport { type Monitor, createMonitor } from \"./monitor\"\n\n/**\n * Manages the lifecycle of monitor emitters, providing creation, attachment, and invalidation\n * mechanisms for reactivity tracking within the {@link Signal} system.\n *\n * @remarks\n * Each instance maintains weak references to all emitters it is attached to, ensuring proper\n * teardown when monitors are recreated or invalidated to avoid leaking subscriptions.\n */\nclass MonitorEmitter {\n /**\n * Maintains the collections of monitor emitters this instance has been attached to, using nested\n * sets of weak references so that attachments can be tracked without preventing garbage collection.\n */\n private readonly _attachedTo = new Set<Set<WeakRef<MonitorEmitter>>>()\n\n /**\n * Maintains a weak reference to the current monitor emitter instance, allowing listeners to access it without preventing garbage collection.\n */\n private readonly _ref = new WeakRef(this)\n\n /**\n * Initializes and returns a new instance of the {@link MonitorEmitter} class.\n *\n * @param _emit - Callback invoked via the internal queue whenever the {@link Monitor} needs to broadcast an update.\n * @param _derived - Indicates whether the emitter originates from a {@link DerivedSignal}, deferring subscription until first access.\n */\n public constructor(\n public readonly _emit: VoidFunction,\n public readonly _derived: boolean,\n ) {}\n\n /**\n * Detaches the current {@link Monitor} reference from every emitter it is attached to\n * and clears the internal tracking set to prevent stale subscriptions.\n */\n private _detachFromAll(): void {\n for (const emitters of this._attachedTo) {\n emitters.delete(this._ref)\n }\n\n this._attachedTo.clear()\n }\n\n /**\n * Resets the current {@link Monitor} by detaching from all tracked emitters and returning a fresh {@link Monitor} instance bound to this emitter.\n *\n * @remarks\n * A {@link Monitor} is always created on a new reading cycle, so all previous subscriptions must be cleared.\n *\n * @returns The newly created {@link Monitor} that references this emitter.\n */\n private _renew(): Monitor {\n this._detachFromAll()\n\n return createMonitor(this)\n }\n\n /**\n * Registers this monitor emitter with the provided collection of emitters,\n * ensuring the weak reference is tracked for future coordination or cleanup.\n *\n * @param emitters - Set of weak references to monitor emitters that this instance should join.\n */\n public _attachTo(emitters: Set<WeakRef<MonitorEmitter>>): void {\n emitters.add(this._ref)\n this._attachedTo.add(emitters)\n }\n\n /**\n * Creates a new {@link Monitor} associated with this emitter after clearing any existing attachments.\n *\n * @returns A fresh {@link Monitor} instance.\n */\n public _create = (): Monitor => this._renew()\n\n /**\n * Resets the emitter state to ensure it detaches from all current dependencies and reinitializes its factory.\n */\n public _invalidate(): void {\n this._create = () => this._renew()\n\n this._detachFromAll()\n }\n}\n\nexport { MonitorEmitter }\n","import { noop } from \"~/tools/noop\"\n\nimport { enqueue } from \"./_internal/enqueue\"\nimport type { Monitor } from \"./_internal/monitor\"\nimport { MonitorEmitter } from \"./_internal/monitor-emitter\"\n\n/**\n * Factory responsible for creating and managing {@link Monitor} instances through a shared\n * internal {@link MonitorEmitter}. Use {@link MonitorFactory.create} to obtain a constructor for\n * new monitors, and {@link MonitorFactory.connect} to subscribe an invalidation callback that\n * will be invoked when the factory requests an emission.\n */\nclass MonitorFactory {\n private _emit = noop\n\n private readonly _emitter = new MonitorEmitter(() => {\n enqueue(this._emit)\n }, false)\n\n /**\n * Registers an emission callback for the monitor emitter and returns a disposer.\n *\n * @param emit - Callback to invoke when the monitor emits changes.\n *\n * @returns A cleanup function that invalidates the underlying emitter when invoked.\n */\n public connect(emit: VoidFunction): VoidFunction {\n this._emit = emit\n\n return () => {\n this._emit = noop\n this._emitter._invalidate()\n }\n }\n\n /**\n * Retrieves the factory function used to instantiate new {@link Monitor} objects.\n *\n * @returns A function that creates and returns a fresh {@link Monitor}.\n */\n public get create(): () => Monitor {\n return this._emitter._create\n }\n}\n\nexport { MonitorFactory }\n"],"mappings":";AAAA,SAAS,OAAa;AAEtB;;;ACSA,IAAM,mBAAN,MAAuB;AAAA,EAAvB;AACE,SAAiB,YAAY,oBAAI,IAAoB;AAWrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAgB,QAAQ,CAAC,aAAyD;AAShF,iBAAW,OAAO,MAAM,KAAK,QAAQ,GAAG;AACtC,cAAM,UAAU,IAAI,MAAM;AAE1B,YAAI,SAAS;AAKX,kBAAQ,YAAY;AAEpB,cAAI,QAAQ,UAAU;AAMpB,oBAAQ,MAAM;AAAA,UAChB,OAAO;AAEL,iBAAK,UAAU,IAAI,OAAO;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAKO,WAAiB;AACtB,eAAW,WAAW,KAAK,WAAW;AACpC,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AACF;AAEA,IAAI,QAAiC;AAWrC,SAAS,QACP,SACS;AAET,MAAI,OAAO;AACT,WAAO,QAAQ,MAAM,KAAK;AAAA,EAC5B;AAGA,UAAQ,IAAI,iBAAiB;AAO7B,QAAM,SAAS,QAAQ,MAAM,KAAK;AAElC,QAAM,MAAM;AAMZ,UAAQ;AAER,MAAI,SAAS;AAEb,SAAO;AACT;;;ACzGA,IAAM,cAAc,uBAAO,SAAS;AASpC,IAAM,oBAAoB;AAAA,EACxB,CAAC,WAAW,GAAG;AACjB;AAEA,SAAS,cAAc,SAAkC;AACvD,SAAO;AAAA,IACL,CAAC,WAAW,GAAG;AAAA,EACjB;AACF;AAEA,SAAS,gBAAgB,SAAkB,UAA8C;AACvF,UAAQ,WAAW,GAAG,UAAU,QAAQ;AAC1C;AAEA,IAAI,kBAA2B;AAE/B,SAAS,cACP,SACA,SACS;AACT,QAAM,cAAc;AAEpB,oBAAkB;AAClB,QAAM,SAAS,QAAQ,OAAO;AAC9B,oBAAkB;AAElB,SAAO;AACT;AAEA,SAAS,iBAA0B;AACjC,SAAO;AACT;;;AC7BA,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBZ,YACW,OACA,UAChB;AAFgB;AACA;AAflB;AAAA;AAAA;AAAA;AAAA,SAAiB,cAAc,oBAAI,IAAkC;AAKrE;AAAA;AAAA;AAAA,SAAiB,OAAO,IAAI,QAAQ,IAAI;AAuDxC;AAAA;AAAA;AAAA;AAAA;AAAA,SAAO,UAAU,MAAe,KAAK,OAAO;AAAA,EA5CzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMK,iBAAuB;AAC7B,eAAW,YAAY,KAAK,aAAa;AACvC,eAAS,OAAO,KAAK,IAAI;AAAA,IAC3B;AAEA,SAAK,YAAY,MAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,SAAkB;AACxB,SAAK,eAAe;AAEpB,WAAO,cAAc,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,UAAU,UAA8C;AAC7D,aAAS,IAAI,KAAK,IAAI;AACtB,SAAK,YAAY,IAAI,QAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAYO,cAAoB;AACzB,SAAK,UAAU,MAAM,KAAK,OAAO;AAEjC,SAAK,eAAe;AAAA,EACtB;AACF;;;AC5EA,IAAM,iBAAN,MAAqB;AAAA,EAArB;AACE,SAAQ,QAAQ;AAEhB,SAAiB,WAAW,IAAI,eAAe,MAAM;AACnD,cAAQ,KAAK,KAAK;AAAA,IACpB,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASD,QAAQ,MAAkC;AAC/C,SAAK,QAAQ;AAEb,WAAO,MAAM;AACX,WAAK,QAAQ;AACb,WAAK,SAAS,YAAY;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAW,SAAwB;AACjC,WAAO,KAAK,SAAS;AAAA,EACvB;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function t(){}Object.defineProperty(exports,"__esModule",{value:!0});var s=class{constructor(){this.$=new Set,this.m=t=>{for(const s of Array.from(t)){const t=s.deref();t&&(t.T(),t.R?t.p():this.$.add(t))}}}N(){for(const t of this.$)t.p()}},o=null;function n(t){if(o)return t(o.m);const n=t((o=new s).m),r=o;return o=null,r.N(),n}var r=Symbol("monitor"),i={[r]:null};var e=i;var c=class{constructor(t,s){this.p=t,this.R=s,this.K=new Set,this.v=new WeakRef(this),this.M=()=>this.A()}Y(){for(const t of this.K)t.delete(this.v);this.K.clear()}A(){return this.Y(),t=this,{[r]:t};var t}I(t){t.add(this.v),this.K.add(t)}T(){this.M=()=>this.A(),this.Y()}};exports.enqueue=n,exports.UNTRACKED_MONITOR=i,exports.attachToMonitor=function(t,s){!function(t){let s,o=t[0],n=1;for(;n<t.length;){const r=t[n],i=t[n+1];if(n+=2,("optionalAccess"===r||"optionalCall"===r)&&null==o)return;"access"===r||"optionalAccess"===r?(s=o,o=i(o)):"call"!==r&&"optionalCall"!==r||(o=i((...t)=>o.call(s,...t)),s=void 0)}}([t,"access",t=>t[r],"optionalAccess",t=>t.I,"call",t=>t(s)])},exports.injectMonitor=function(t,s){const o=e;e=s;const n=t(s);return e=o,n},exports.extractMonitor=function(){return e},exports.MonitorEmitter=c,exports.MonitorFactory=class{constructor(){this.p=t,this.q=new c(()=>{n(this.p)},!1)}connect(s){return this.p=s,()=>{this.p=t,this.q.T()}}get create(){return this.q.M}};//# sourceMappingURL=chunk-NRM2F6O5.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/signal/signal/packages/signal/dist/chunk-NRM2F6O5.cjs","../../tools/src/noop.ts","../src/_internal/enqueue.ts","../src/_internal/monitor.ts","../src/_internal/monitor-emitter.ts","../src/monitor-factory.ts"],"names":[],"mappings":"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","file":"/home/runner/work/signal/signal/packages/signal/dist/chunk-NRM2F6O5.cjs","sourcesContent":[null,"function noop(): void {\n // no operation\n}\n\nexport { noop }\n","import type { DerivedSignal } from \"./derived-signal\"\nimport type { MonitorEmitter } from \"./monitor-emitter\"\n\n/**\n * Orchestrates invalidation and emission of {@link MonitorEmitter}s to prevent\n * re-subscription loops while ensuring {@link DerivedSignal}s observe the latest\n * state before downstream updates. Derived emitters are emitted immediately to\n * leverage their comparison logic, whereas direct emitters are batched and\n * flushed later via {@link MonitorEmitQueue._process}, avoiding redundant\n * scheduling while maintaining consistent propagation order.\n */\nclass MonitorEmitQueue {\n private readonly _emitters = new Set<MonitorEmitter>()\n\n /**\n * Adds the provided emitters to the queue for later processing.\n *\n * @remarks Invalidates each emitter immediately so that {@link DerivedSignal}s observe the latest version,\n * then triggers derived emitters synchronously to leverage their comparison logic, while\n * queueing non-derived emitters for deferred emission.\n *\n * @param emitters - The captured set of weak references to {@link MonitorEmitter}s awaiting processing.\n */\n public readonly _push = (emitters: ReadonlySet<WeakRef<MonitorEmitter>>): void => {\n /**\n * Calling the {@link MonitorEmitter._emit} might cause the same {@link Signal} (host of the {@link emitters})\n * to be scheduled again for the same monitor ({@link DerivedSignal} when source sets the comparably equal value).\n * It causes infinite loop, where the {@link MonitorEmitter._invalidate} first unsubscribes from the source {@link Signal} but\n * the {@link DerivedSignal}'s {@link MonitorEmitter._emit} subscribes it back.\n *\n * To prevent this, the _push should only iterate over the emitters present at the moment of the call.\n */\n for (const ref of Array.from(emitters)) {\n const emitter = ref.deref()\n\n if (emitter) {\n /**\n * Invalidate the emitter as soon as it is scheduled\n * so the {@link DerivedSignal}s can read a fresh value due to version increment.\n */\n emitter._invalidate()\n\n if (emitter._derived) {\n /**\n * Emit immediately so {@link DerivedSignal}s utilize the equals function to either:\n * 1. NOT CHANGED: resubscribe to sources\n * 2. CHANGED: marks as stale and _push's its._emitters so they end up here either emitting ({@link DerivedSignal}) or scheduling ({@link Signal}).\n */\n emitter._emit()\n } else {\n // Schedule the emit when all the emitters are collected.\n this._emitters.add(emitter)\n }\n }\n }\n }\n\n /**\n * Iterates through all registered emitters and triggers their emission cycle.\n */\n public _process(): void {\n for (const emitter of this._emitters) {\n emitter._emit()\n }\n }\n}\n\nlet Queue: null | MonitorEmitQueue = null\n\n/**\n * Runs a queue-backed execution block, ensuring that nested enqueue calls share\n * the same monitor emit queue and that queued emitters are processed exactly once.\n *\n * @template TResult - The value returned by the execution block.\n * @param execute - Callback invoked with the active monitor emit queue.\n *\n * @returns The value produced by the provided execution block.\n */\nfunction enqueue<TResult>(\n execute: (push: (emitters: ReadonlySet<WeakRef<MonitorEmitter>>) => void) => TResult,\n): TResult {\n // Continue the execution if the queue is already initialized.\n if (Queue) {\n return execute(Queue._push)\n }\n\n // Initialize the queue and start the execution sequence.\n Queue = new MonitorEmitQueue()\n\n /**\n * The execution might lead to other {@link enqueue} calls,\n * so they all will collect the emitters in the same queue\n * ensuring that an emitter is emitted only once.\n */\n const result = execute(Queue._push)\n\n const tmp = Queue\n\n /**\n * Drop the global queue before processing to allow nested scheduling,\n * when {@link MonitorEmitter._emit} enqueues new emitters for the next tick.\n */\n Queue = null\n\n tmp._process()\n\n return result\n}\n\nexport { enqueue }\n","import type { MonitorEmitter } from \"./monitor-emitter\"\n\nconst MONITOR_KEY = Symbol(\"monitor\")\n\n/**\n * @version 1.0.0\n */\ninterface Monitor {\n readonly [MONITOR_KEY]: null | MonitorEmitter\n}\n\nconst UNTRACKED_MONITOR = {\n [MONITOR_KEY]: null,\n} satisfies Monitor\n\nfunction createMonitor(emitter: MonitorEmitter): Monitor {\n return {\n [MONITOR_KEY]: emitter,\n }\n}\n\nfunction attachToMonitor(monitor: Monitor, emitters: Set<WeakRef<MonitorEmitter>>): void {\n monitor[MONITOR_KEY]?._attachTo(emitters)\n}\n\nlet implicitMonitor: Monitor = UNTRACKED_MONITOR\n\nfunction injectMonitor<TResult>(\n execute: (_monitor: Monitor) => TResult,\n monitor: Monitor,\n): TResult {\n const prevMonitor = implicitMonitor\n\n implicitMonitor = monitor\n const result = execute(monitor)\n implicitMonitor = prevMonitor\n\n return result\n}\n\nfunction extractMonitor(): Monitor {\n return implicitMonitor\n}\n\nexport type { Monitor }\nexport { UNTRACKED_MONITOR, createMonitor, attachToMonitor, injectMonitor, extractMonitor }\n","import type { Signal } from \"../signal\"\n\nimport type { DerivedSignal } from \"./derived-signal\"\nimport { type Monitor, createMonitor } from \"./monitor\"\n\n/**\n * Manages the lifecycle of monitor emitters, providing creation, attachment, and invalidation\n * mechanisms for reactivity tracking within the {@link Signal} system.\n *\n * @remarks\n * Each instance maintains weak references to all emitters it is attached to, ensuring proper\n * teardown when monitors are recreated or invalidated to avoid leaking subscriptions.\n */\nclass MonitorEmitter {\n /**\n * Maintains the collections of monitor emitters this instance has been attached to, using nested\n * sets of weak references so that attachments can be tracked without preventing garbage collection.\n */\n private readonly _attachedTo = new Set<Set<WeakRef<MonitorEmitter>>>()\n\n /**\n * Maintains a weak reference to the current monitor emitter instance, allowing listeners to access it without preventing garbage collection.\n */\n private readonly _ref = new WeakRef(this)\n\n /**\n * Initializes and returns a new instance of the {@link MonitorEmitter} class.\n *\n * @param _emit - Callback invoked via the internal queue whenever the {@link Monitor} needs to broadcast an update.\n * @param _derived - Indicates whether the emitter originates from a {@link DerivedSignal}, deferring subscription until first access.\n */\n public constructor(\n public readonly _emit: VoidFunction,\n public readonly _derived: boolean,\n ) {}\n\n /**\n * Detaches the current {@link Monitor} reference from every emitter it is attached to\n * and clears the internal tracking set to prevent stale subscriptions.\n */\n private _detachFromAll(): void {\n for (const emitters of this._attachedTo) {\n emitters.delete(this._ref)\n }\n\n this._attachedTo.clear()\n }\n\n /**\n * Resets the current {@link Monitor} by detaching from all tracked emitters and returning a fresh {@link Monitor} instance bound to this emitter.\n *\n * @remarks\n * A {@link Monitor} is always created on a new reading cycle, so all previous subscriptions must be cleared.\n *\n * @returns The newly created {@link Monitor} that references this emitter.\n */\n private _renew(): Monitor {\n this._detachFromAll()\n\n return createMonitor(this)\n }\n\n /**\n * Registers this monitor emitter with the provided collection of emitters,\n * ensuring the weak reference is tracked for future coordination or cleanup.\n *\n * @param emitters - Set of weak references to monitor emitters that this instance should join.\n */\n public _attachTo(emitters: Set<WeakRef<MonitorEmitter>>): void {\n emitters.add(this._ref)\n this._attachedTo.add(emitters)\n }\n\n /**\n * Creates a new {@link Monitor} associated with this emitter after clearing any existing attachments.\n *\n * @returns A fresh {@link Monitor} instance.\n */\n public _create = (): Monitor => this._renew()\n\n /**\n * Resets the emitter state to ensure it detaches from all current dependencies and reinitializes its factory.\n */\n public _invalidate(): void {\n this._create = () => this._renew()\n\n this._detachFromAll()\n }\n}\n\nexport { MonitorEmitter }\n","import { noop } from \"~/tools/noop\"\n\nimport { enqueue } from \"./_internal/enqueue\"\nimport type { Monitor } from \"./_internal/monitor\"\nimport { MonitorEmitter } from \"./_internal/monitor-emitter\"\n\n/**\n * Factory responsible for creating and managing {@link Monitor} instances through a shared\n * internal {@link MonitorEmitter}. Use {@link MonitorFactory.create} to obtain a constructor for\n * new monitors, and {@link MonitorFactory.connect} to subscribe an invalidation callback that\n * will be invoked when the factory requests an emission.\n */\nclass MonitorFactory {\n private _emit = noop\n\n private readonly _emitter = new MonitorEmitter(() => {\n enqueue(this._emit)\n }, false)\n\n /**\n * Registers an emission callback for the monitor emitter and returns a disposer.\n *\n * @param emit - Callback to invoke when the monitor emits changes.\n *\n * @returns A cleanup function that invalidates the underlying emitter when invoked.\n */\n public connect(emit: VoidFunction): VoidFunction {\n this._emit = emit\n\n return () => {\n this._emit = noop\n this._emitter._invalidate()\n }\n }\n\n /**\n * Retrieves the factory function used to instantiate new {@link Monitor} objects.\n *\n * @returns A function that creates and returns a fresh {@link Monitor}.\n */\n public get create(): () => Monitor {\n return this._emitter._create\n }\n}\n\nexport { MonitorFactory }\n"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function t(t,n){return null!=t?t:n()}function n(t){let n,s=t[0],e=1;for(;e<t.length;){const i=t[e],r=t[e+1];if(e+=2,("optionalAccess"===i||"optionalCall"===i)&&null==s)return;"access"===i||"optionalAccess"===i?(n=s,s=r(s)):"call"!==i&&"optionalCall"!==i||(s=r((...t)=>s.call(n,...t)),n=void 0)}return s}Object.defineProperty(exports,"__esModule",{value:!0});var s=require("./chunk-NRM2F6O5.cjs");function e(t){s.enqueue.call(void 0,()=>{t(s.UNTRACKED_MONITOR)})}function i(t){return(...[n,s,e])=>{if(!s)return t(n);if(t(e)){return s(e.read(n))}return!1}}function r(t){return"function"==typeof t}function o(t,n){return Object.is(t,n)}var c=class{constructor(t){this.t=t,this.$=new Set}toJSON(){const t=s.extractMonitor.call(void 0);return this.read(t)}toString(){const t=s.extractMonitor.call(void 0);return String(this.read(t))}read(t){return s.attachToMonitor.call(void 0,t,this.$),this.i()}write(t){s.enqueue.call(void 0,n=>{const e=r(t)?t(this.i(),s.UNTRACKED_MONITOR):t;this.o(e)&&n(this.$)})}clone(n,e){const i=this.i(),[c,{equals:u=this.t}={}]=r(n)?[n(i,s.UNTRACKED_MONITOR),e]:[i,n];return this.u(c,t(u,()=>o))}},u=class t extends c{constructor(t,n){super(n),this._=t}i(){return this._}o(t){return!this.t(this._,t)&&(this._=t,!0)}u(n,s){return new t(n,s)}},l=class extends c{constructor(t,n,e){super(e),this.h=t,this.l=n,this.S=new(0,s.MonitorEmitter)(()=>{this.t(this._,this.h(s.UNTRACKED_MONITOR))?s.injectMonitor.call(void 0,this.h,this.S):(this.O=!0,s.enqueue.call(void 0,t=>t(this.$)))},!0).M(),this._=null,this.O=!0}i(){const t=this.h(this.S);return this.O&&(this._=t,this.O=!1),this._}o(t){return this.l(t,s.UNTRACKED_MONITOR),!1}u(t,n){return new u(t,n)}},h=i(t=>t instanceof l),a=i(t=>t instanceof c);function f(t,n){return"object"==typeof t&&null!=t&&n in t}exports.Signal=function(s,e,i){const c=r(s);if(!c&&!f(s,"read")){return new u(s,t(n([e,"optionalAccess",t=>t.equals]),()=>o))}const[h,a]=r(e)||f(e,"write")?[e,i]:[void 0,e];return new l(c?s:t=>s.read(t),r(h)?h:t=>n([h,"optionalAccess",t=>t.write,"call",n=>n(t)]),t(n([a,"optionalAccess",t=>t.equals]),()=>o))},exports.batch=e,exports.effect=function(t){let i;const r=new(0,s.MonitorFactory),o=()=>{n([i,"optionalCall",t=>t()]),i=s.injectMonitor.call(void 0,t,r.create())},c=r.connect(o);return o(),()=>{e(()=>{c(),n([i,"optionalCall",t=>t()])})}},exports.isDerivedSignal=h,exports.isSignal=a,exports.untracked=function(t){return s.enqueue.call(void 0,()=>r(t)?t(s.UNTRACKED_MONITOR):t.read(s.UNTRACKED_MONITOR))};//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/signal/signal/packages/signal/dist/index.cjs","../src/batch.ts","../src/effect.ts","../src/_internal/create-is-signal.ts","../../tools/src/is-function.ts","../../tools/src/is-strict-equal.ts","../src/_internal/base-signal.ts","../src/_internal/signal.ts","../src/_internal/derived-signal.ts","../src/is-derived-signal.ts","../src/is-signal.ts","../../tools/src/has-property.ts","../src/signal.ts","../src/untracked.ts"],"names":["isSignal","Signal"],"mappings":"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","file":"/home/runner/work/signal/signal/packages/signal/dist/index.cjs","sourcesContent":[null,"import type { Signal } from \"./signal\"\nimport { enqueue } from \"./_internal/enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR } from \"./_internal/monitor\"\n\n/**\n * A helper to optimize multiple {@link Signal}s updates.\n *\n * @param execute a function that executes multiple {@link Signal.write} calls at ones.\n * It provides {@link Monitor} to the {@link execute} function so it is useful when an async operation accesses the {@link Signal}s' values.\n *\n * @version 1.0.0\n */\nfunction batch(execute: (monitor: Monitor) => void): void {\n enqueue(() => {\n execute(UNTRACKED_MONITOR)\n })\n}\n\nexport { batch }\n","import { batch } from \"./batch\"\nimport type { Destructor } from \"./destructor\"\nimport { MonitorFactory } from \"./monitor-factory\"\nimport type { Signal } from \"./signal\"\nimport { type Monitor, injectMonitor } from \"./_internal/monitor\"\n\n/**\n * A function that provides {@link Monitor} as the first argument subscribes to changes of all {@link Signal} instances that call the {@link Signal.read} method inside the {@link listener}.\n *\n * @param listener Function that will be called on each {@link Signal} change, involved in the {@link listener} execution.\n * Calls first time synchronously when {@link effect} is called.\n * If {@link listener} returns a function then it will be called before the next {@link listener} call.\n *\n * @returns Dispose function that unsubscribes the {@link listener} from all involved {@link Signal} instances.\n *\n * @version 1.0.0\n */\nfunction effect(listener: (monitor: Monitor) => Destructor): VoidFunction {\n let dispose: Destructor\n\n const factory = new MonitorFactory()\n\n const emit = (): void => {\n dispose?.()\n dispose = injectMonitor(listener, factory.create())\n }\n\n const disconnect = factory.connect(emit)\n\n emit()\n\n return () => {\n batch(() => {\n disconnect()\n dispose?.()\n })\n }\n}\n\nexport { effect }\n","import type { BaseSignal } from \"./base-signal\"\nimport type { Monitor } from \"./monitor\"\n\nfunction createIsSignal(isSignal: (input: unknown) => input is BaseSignal<unknown>) {\n return (\n ...[inputOrMonitor, maybeCheck, maybeInput]:\n | [input: unknown]\n | [monitor: Monitor, check: (input: unknown) => boolean, input: unknown]\n ): boolean => {\n if (!maybeCheck) {\n return isSignal(inputOrMonitor)\n }\n\n if (isSignal(maybeInput)) {\n const value = maybeInput.read(inputOrMonitor as Monitor)\n\n return maybeCheck(value)\n }\n\n return false\n }\n}\n\nexport { createIsSignal }\n","type DefinitelyFunction<T> =\n // biome-ignore lint/complexity/noBannedTypes: use Function to ensure correct typing\n Extract<T, Function> extends never ? Function : Extract<T, Function>\n\nfunction isFunction<T>(\n // biome-ignore lint/complexity/noBannedTypes: use Function to ensure correct typing\n data: Function | T,\n): data is DefinitelyFunction<T> {\n return typeof data === \"function\"\n}\n\nexport { isFunction }\n","function isStrictEqual<T>(left: T, right: T): boolean {\n return Object.is(left, right)\n}\n\nexport { isStrictEqual }\n","import { isFunction } from \"~/tools/is-function\"\nimport { isStrictEqual } from \"~/tools/is-strict-equal\"\n\nimport type { Equal } from \"../equal\"\nimport type { ReadableSignal } from \"../readable-signal\"\nimport type { Signal } from \"../signal\"\nimport type { SignalOptions } from \"../signal-options\"\nimport type { WritableSignal } from \"../writable-signal\"\n\nimport { enqueue } from \"./enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR, attachToMonitor, extractMonitor } from \"./monitor\"\nimport type { MonitorEmitter } from \"./monitor-emitter\"\n\nabstract class BaseSignal<T> implements ReadableSignal<T>, WritableSignal<T> {\n protected readonly _emitters = new Set<WeakRef<MonitorEmitter>>()\n\n protected constructor(protected readonly _equals: Equal<T>) {}\n\n protected abstract _getter(): T\n\n protected abstract _setter(value: T): boolean\n\n protected abstract _clone(value: T, equals: Equal<T>): Signal<T>\n\n /**\n * Return the value when serializing to JSON.\n * It does not encode the instance for decoding it back due to runtime parts of the class,\n * that cannot be serialized as JSON.\n *\n * The method is protected in order to make it impossible to make the implicit call.\n *\n * @version 1.0.0\n */\n protected toJSON(): unknown {\n const monitor = extractMonitor()\n\n return this.read(monitor)\n }\n\n /**\n * Return the stringified value when the instance converts to a string.\n *\n * The method is protected in order to make it impossible to make the implicit call.\n * @version 1.0.0\n */\n protected toString(): string {\n const monitor = extractMonitor()\n\n return String(this.read(monitor))\n }\n\n /**\n * Reads the instance's value.\n *\n * @param monitor the {@link Monitor} that tracks the instance value changes.\n *\n * @returns the instance value.\n *\n * @version 1.0.0\n */\n public read(monitor: Monitor): T {\n attachToMonitor(monitor, this._emitters)\n\n return this._getter()\n }\n\n /**\n * Updates the value.\n *\n * @param valueOrTransform either the new value or a function that transforms the current value.\n *\n * @returns `void` to emphasize that {@link Signal}s are mutable.\n *\n * @version 1.0.0\n */\n public write(valueOrTransform: T | ((currentValue: T, monitor: Monitor) => T)): void {\n enqueue((push) => {\n const nextValue = isFunction(valueOrTransform)\n ? valueOrTransform(this._getter(), UNTRACKED_MONITOR)\n : valueOrTransform\n\n if (this._setter(nextValue)) {\n push(this._emitters)\n }\n })\n }\n\n /**\n * Creates a new {@link Signal} instance out of the current one with the same value.\n *\n * @param options optional {@link SignalOptions}.\n * @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.\n *\n * @returns a new {@link Signal} instance with the same value.\n *\n * @version 1.0.0\n */\n public clone(options?: SignalOptions<T>): Signal<T>\n\n /**\n * Creates a new {@link Signal} instance out of the current one with the transformed value. Transforming might be handy when cloning mutable values (such as a {@link Signal}).\n *\n * @param transform an optional function that applies to the current value before cloning. It might be handy when cloning mutable values.\n * @param options optional {@link SignalOptions}.\n * @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.\n *\n * @return a new {@link Signal} instance with the transformed value.\n *\n * @version 1.0.0\n */\n public clone(transform: (value: T, monitor: Monitor) => T, options?: SignalOptions<T>): Signal<T>\n\n public clone(\n transformOrOptions?: ((value: T, monitor: Monitor) => T) | SignalOptions<T>,\n maybeOptions?: SignalOptions<T>,\n ): Signal<T> {\n const value = this._getter()\n\n const [clonedValue, { equals = this._equals } = {}] = isFunction(transformOrOptions)\n ? [transformOrOptions(value, UNTRACKED_MONITOR), maybeOptions]\n : [value, transformOrOptions]\n\n return this._clone(clonedValue, equals ?? isStrictEqual)\n }\n}\n\nexport { BaseSignal }\n","import type { Equal } from \"../equal\"\n\nimport { BaseSignal } from \"./base-signal\"\n\nclass Signal<T> extends BaseSignal<T> {\n public constructor(\n private _value: T,\n equals: Equal<T>,\n ) {\n super(equals)\n }\n\n protected _getter(): T {\n return this._value\n }\n\n protected _setter(value: T): boolean {\n if (!this._equals(this._value, value)) {\n this._value = value\n\n return true\n }\n\n return false\n }\n\n protected _clone(value: T, equals: Equal<T>): Signal<T> {\n return new Signal(value, equals)\n }\n}\n\nexport { Signal }\n","import type { Equal } from \"../equal\"\n\nimport { BaseSignal } from \"./base-signal\"\nimport { enqueue } from \"./enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR, injectMonitor } from \"./monitor\"\nimport { MonitorEmitter } from \"./monitor-emitter\"\nimport { Signal } from \"./signal\"\n\nclass DerivedSignal<T> extends BaseSignal<T> {\n // the inner monitor proxies the setters to the outer monitor\n private readonly _monitor = new MonitorEmitter(() => {\n if (this._equals(this._value, this._getValue(UNTRACKED_MONITOR))) {\n // subscribe back to the dependencies\n injectMonitor(this._getValue, this._monitor)\n } else {\n this._stale = true\n enqueue((push) => push(this._emitters))\n }\n }, true)._create()\n\n // biome-ignore lint/style/noNonNullAssertion: the value is never null because it assigns the value from the _getValue on the first _getter call\n private _value: T = null!\n private _stale = true\n\n public constructor(\n private readonly _getValue: (monitor: Monitor) => T,\n private readonly _setValue: (value: T, monitor: Monitor) => void,\n equals: Equal<T>,\n ) {\n super(equals)\n }\n\n protected _getter(): T {\n const value = this._getValue(this._monitor)\n\n if (this._stale) {\n this._value = value\n this._stale = false\n }\n\n return this._value\n }\n\n protected _setter(value: T): boolean {\n this._setValue(value, UNTRACKED_MONITOR)\n\n return false\n }\n\n protected _clone(value: T, equals: Equal<T>): Signal<T> {\n return new Signal(value, equals)\n }\n}\n\nexport { DerivedSignal }\n","import type { ReadonlySignal, Signal } from \"./signal\"\nimport { createIsSignal } from \"./_internal/create-is-signal\"\nimport { DerivedSignal } from \"./_internal/derived-signal\"\nimport type { Monitor } from \"./_internal/monitor\"\n\nconst isDerivedSignal = createIsSignal((input) => input instanceof DerivedSignal) as {\n /**\n * A function to check whether or not the input is a Derived {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>\n\n /**\n * A function to check whether or not the input is a Derived {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>\n\n /**\n * A function to check whether or not a Derived {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | Signal<T>,\n ): input is Signal<T>\n\n /**\n * A function to check whether or not a Derived {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | ReadonlySignal<T>,\n ): input is ReadonlySignal<T>\n}\n\nexport { isDerivedSignal }\n","import type { ReadonlySignal, Signal } from \"./signal\"\nimport { BaseSignal } from \"./_internal/base-signal\"\nimport { createIsSignal } from \"./_internal/create-is-signal\"\nimport type { Monitor } from \"./_internal/monitor\"\n\nconst isSignal = createIsSignal((input) => input instanceof BaseSignal) as {\n /**\n * A function to check whether or not the input is a {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>\n\n /**\n * A function to check whether or not the input is a {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>\n\n /**\n * A function to check whether or not a {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | Signal<T>,\n ): input is Signal<T>\n\n /**\n * A function to check whether or not a {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | ReadonlySignal<T>,\n ): input is ReadonlySignal<T>\n}\n\nexport { isSignal }\n","function hasProperty<TKey extends PropertyKey>(\n input: unknown,\n key: TKey,\n): input is Record<TKey, unknown> {\n return typeof input === \"object\" && input != null && key in input\n}\n\nexport { hasProperty }\n","import { hasProperty } from \"~/tools/has-property\"\nimport { isFunction } from \"~/tools/is-function\"\nimport { isStrictEqual } from \"~/tools/is-strict-equal\"\n\nimport type { Equal } from \"./equal\"\nimport type { ReadableSignal } from \"./readable-signal\"\nimport type { SignalOptions } from \"./signal-options\"\nimport type { WritableSignal } from \"./writable-signal\"\nimport type { BaseSignal } from \"./_internal/base-signal\"\nimport { DerivedSignal } from \"./_internal/derived-signal\"\nimport type { Monitor } from \"./_internal/monitor\"\nimport { Signal as SignalImpl } from \"./_internal/signal\"\n\n/**\n * @version 1.0.0\n */\ntype Signal<T> = BaseSignal<T>\n\n/**\n * @version 1.0.0\n */\ntype ReadonlySignal<T> = Omit<Signal<T>, \"write\">\n\n/**\n * Creates a new {@link Signal} without an initial value.\n *\n * @template TValue the type of the {@link Signal} value.\n *\n * @version 1.0.0\n *\n * @example\n * const signal = Signal<string>()\n * const initiallyUndefined = signal.read(monitor) === undefined\n */\nfunction Signal<TValue = undefined>(): Signal<undefined | TValue>\n\n/**\n * Creates a new Derived {@link ReadonlySignal}.\n * A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.\n *\n * @template TDerivedValue the type of the derived {@link Signal} value.\n *\n * @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.\n * @param options optional {@link SignalOptions}.\n * @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.\n *\n * @returns a new {@link ReadonlySignal}.\n *\n * @version 1.0.0\n */\nfunction Signal<TDerivedValue>(\n getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue),\n options?: SignalOptions<TDerivedValue>,\n): ReadonlySignal<TDerivedValue>\n\n/**\n * Creates a new derived {@link Signal}.\n * A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.\n *\n * @template TDerivedValue the type of the derived {@link Signal} value.\n *\n * @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.\n * @param setter either anything that implements the {@link WritableSignal} interface or a function to write the derived value back to the source.\n * @param options optional {@link SignalOptions}.\n * @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.\n *\n * @returns a new {@link Signal}.\n *\n * @version 1.0.0\n */\nfunction Signal<TDerivedValue>(\n getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue),\n setter: WritableSignal<TDerivedValue> | ((value: TDerivedValue, monitor: Monitor) => void),\n options?: SignalOptions<TDerivedValue>,\n): Signal<TDerivedValue>\n\n/**\n * Creates a new {@link Signal}.\n *\n * @template TValue the type of the {@link Signal} value.\n *\n * @param initialValue the initial value.\n * @param options optional {@link SignalOptions}.\n * @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.\n *\n * @version 1.0.0\n */\nfunction Signal<TValue>(initialValue: TValue, options?: SignalOptions<TValue>): Signal<TValue>\n\nfunction Signal<T>(\n initialValueOrReadableSignal?: T | ReadableSignal<T> | ((monitor: Monitor) => T),\n optionsOrWritableSignal?:\n | SignalOptions<T>\n | WritableSignal<T>\n | ((value: T, monitor: Monitor) => void),\n optionsOrNothing?: SignalOptions<T>,\n): Signal<undefined | T> | Signal<T> {\n const isGetterFunction = isFunction(initialValueOrReadableSignal)\n\n if (!(isGetterFunction || hasProperty(initialValueOrReadableSignal, \"read\"))) {\n const directOptions = optionsOrWritableSignal as undefined | SignalOptions<undefined | T>\n\n return new SignalImpl(initialValueOrReadableSignal, directOptions?.equals ?? isStrictEqual)\n }\n\n const [setter, derivedOptions] =\n isFunction(optionsOrWritableSignal) || hasProperty(optionsOrWritableSignal, \"write\")\n ? [optionsOrWritableSignal, optionsOrNothing]\n : [undefined, optionsOrWritableSignal]\n\n return new DerivedSignal(\n isGetterFunction\n ? initialValueOrReadableSignal\n : (monitor) => initialValueOrReadableSignal.read(monitor),\n isFunction(setter) ? setter : (value) => setter?.write(value),\n derivedOptions?.equals ?? isStrictEqual,\n )\n}\n\nexport type { ReadonlySignal }\nexport { Signal }\n","import { isFunction } from \"~/tools/is-function\"\n\nimport type { batch } from \"./batch\"\nimport type { ReadableSignal } from \"./readable-signal\"\nimport type { Signal } from \"./signal\"\nimport { enqueue } from \"./_internal/enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR } from \"./_internal/monitor\"\n\n/**\n * Ignores tracking any of the {@link Signal} attached to the provided {@link Monitor}.\n * Acts like {@link batch} but returns the {@link factory} function result.\n *\n * @param factory a function that provides {@link Monitor} as the first argument and returns a result.\n *\n * @returns the {@link factory} function result.\n *\n * @version 1.0.0\n */\nfunction untracked<TResult>(factory: (monitor: Monitor) => TResult): TResult\n\n/**\n * Extracts the value from the provided {@link signal} without tracking it.\n *\n * @param signal anything that implements the {@link ReadableSignal} interface.\n *\n * @returns the {@link signal} value.\n *\n * @version 1.0.0\n */\nfunction untracked<TValue>(signal: ReadableSignal<TValue>): TValue\n\nfunction untracked<T>(factoryOrReadableSignal: ((monitor: Monitor) => T) | ReadableSignal<T>): T {\n return enqueue(() => {\n if (isFunction(factoryOrReadableSignal)) {\n return factoryOrReadableSignal(UNTRACKED_MONITOR)\n }\n\n return factoryOrReadableSignal.read(UNTRACKED_MONITOR)\n })\n}\n\nexport { untracked }\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { M as Monitor, a as MonitorEmitter } from './monitor-BQJbbQ1I.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A helper to optimize multiple {@link Signal}s updates.
|
|
5
|
+
*
|
|
6
|
+
* @param execute a function that executes multiple {@link Signal.write} calls at ones.
|
|
7
|
+
* It provides {@link Monitor} to the {@link execute} function so it is useful when an async operation accesses the {@link Signal}s' values.
|
|
8
|
+
*
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
declare function batch(execute: (monitor: Monitor) => void): void;
|
|
12
|
+
|
|
13
|
+
declare const UNDEFINED_VOID_ONLY: unique symbol;
|
|
14
|
+
/**
|
|
15
|
+
* @version 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
type Destructor = void | (() => void | {
|
|
18
|
+
[UNDEFINED_VOID_ONLY]: never;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A function that provides {@link Monitor} as the first argument subscribes to changes of all {@link Signal} instances that call the {@link Signal.read} method inside the {@link listener}.
|
|
23
|
+
*
|
|
24
|
+
* @param listener Function that will be called on each {@link Signal} change, involved in the {@link listener} execution.
|
|
25
|
+
* Calls first time synchronously when {@link effect} is called.
|
|
26
|
+
* If {@link listener} returns a function then it will be called before the next {@link listener} call.
|
|
27
|
+
*
|
|
28
|
+
* @returns Dispose function that unsubscribes the {@link listener} from all involved {@link Signal} instances.
|
|
29
|
+
*
|
|
30
|
+
* @version 1.0.0
|
|
31
|
+
*/
|
|
32
|
+
declare function effect(listener: (monitor: Monitor) => Destructor): VoidFunction;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The equality check function.
|
|
36
|
+
*
|
|
37
|
+
*
|
|
38
|
+
* @template T the type of values to compare.
|
|
39
|
+
* @param left the first value to compare.
|
|
40
|
+
* @param right the second value to compare.
|
|
41
|
+
* @returns `true` if the two values are considered equal, otherwise `false`.
|
|
42
|
+
*
|
|
43
|
+
* @version 1.0.0
|
|
44
|
+
*/
|
|
45
|
+
type Equal<T> = (left: T, right: T) => boolean;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @version 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
interface ReadableSignal<T> {
|
|
51
|
+
read(monitor: Monitor): T;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The options for creating and cloning a {@link Signal}.
|
|
56
|
+
*
|
|
57
|
+
* @template T the type of the {@link Signal} value.
|
|
58
|
+
*
|
|
59
|
+
* @version 1.0.0
|
|
60
|
+
*/
|
|
61
|
+
interface SignalOptions<T> {
|
|
62
|
+
/**
|
|
63
|
+
* The equality function determines whether or not a new {@link Signal}'s value replaces the current one.
|
|
64
|
+
* In some cases specifying the function leads to better performance because it prevents unnecessary updates.
|
|
65
|
+
*/
|
|
66
|
+
readonly equals?: null | Equal<T>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @version 1.0.0
|
|
71
|
+
*/
|
|
72
|
+
interface WritableSignal<T> {
|
|
73
|
+
write(value: T): void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
declare abstract class BaseSignal<T> implements ReadableSignal<T>, WritableSignal<T> {
|
|
77
|
+
protected readonly _equals: Equal<T>;
|
|
78
|
+
protected readonly _emitters: Set<WeakRef<MonitorEmitter>>;
|
|
79
|
+
protected constructor(_equals: Equal<T>);
|
|
80
|
+
protected abstract _getter(): T;
|
|
81
|
+
protected abstract _setter(value: T): boolean;
|
|
82
|
+
protected abstract _clone(value: T, equals: Equal<T>): Signal<T>;
|
|
83
|
+
/**
|
|
84
|
+
* Return the value when serializing to JSON.
|
|
85
|
+
* It does not encode the instance for decoding it back due to runtime parts of the class,
|
|
86
|
+
* that cannot be serialized as JSON.
|
|
87
|
+
*
|
|
88
|
+
* The method is protected in order to make it impossible to make the implicit call.
|
|
89
|
+
*
|
|
90
|
+
* @version 1.0.0
|
|
91
|
+
*/
|
|
92
|
+
protected toJSON(): unknown;
|
|
93
|
+
/**
|
|
94
|
+
* Return the stringified value when the instance converts to a string.
|
|
95
|
+
*
|
|
96
|
+
* The method is protected in order to make it impossible to make the implicit call.
|
|
97
|
+
* @version 1.0.0
|
|
98
|
+
*/
|
|
99
|
+
protected toString(): string;
|
|
100
|
+
/**
|
|
101
|
+
* Reads the instance's value.
|
|
102
|
+
*
|
|
103
|
+
* @param monitor the {@link Monitor} that tracks the instance value changes.
|
|
104
|
+
*
|
|
105
|
+
* @returns the instance value.
|
|
106
|
+
*
|
|
107
|
+
* @version 1.0.0
|
|
108
|
+
*/
|
|
109
|
+
read(monitor: Monitor): T;
|
|
110
|
+
/**
|
|
111
|
+
* Updates the value.
|
|
112
|
+
*
|
|
113
|
+
* @param valueOrTransform either the new value or a function that transforms the current value.
|
|
114
|
+
*
|
|
115
|
+
* @returns `void` to emphasize that {@link Signal}s are mutable.
|
|
116
|
+
*
|
|
117
|
+
* @version 1.0.0
|
|
118
|
+
*/
|
|
119
|
+
write(valueOrTransform: T | ((currentValue: T, monitor: Monitor) => T)): void;
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new {@link Signal} instance out of the current one with the same value.
|
|
122
|
+
*
|
|
123
|
+
* @param options optional {@link SignalOptions}.
|
|
124
|
+
* @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.
|
|
125
|
+
*
|
|
126
|
+
* @returns a new {@link Signal} instance with the same value.
|
|
127
|
+
*
|
|
128
|
+
* @version 1.0.0
|
|
129
|
+
*/
|
|
130
|
+
clone(options?: SignalOptions<T>): Signal<T>;
|
|
131
|
+
/**
|
|
132
|
+
* Creates a new {@link Signal} instance out of the current one with the transformed value. Transforming might be handy when cloning mutable values (such as a {@link Signal}).
|
|
133
|
+
*
|
|
134
|
+
* @param transform an optional function that applies to the current value before cloning. It might be handy when cloning mutable values.
|
|
135
|
+
* @param options optional {@link SignalOptions}.
|
|
136
|
+
* @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.
|
|
137
|
+
*
|
|
138
|
+
* @return a new {@link Signal} instance with the transformed value.
|
|
139
|
+
*
|
|
140
|
+
* @version 1.0.0
|
|
141
|
+
*/
|
|
142
|
+
clone(transform: (value: T, monitor: Monitor) => T, options?: SignalOptions<T>): Signal<T>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @version 1.0.0
|
|
147
|
+
*/
|
|
148
|
+
type ReadonlySignal<T> = Omit<Signal<T>, "write">;
|
|
149
|
+
/**
|
|
150
|
+
* @version 1.0.0
|
|
151
|
+
*/
|
|
152
|
+
type Signal<T> = BaseSignal<T>;
|
|
153
|
+
/**
|
|
154
|
+
* Creates a new {@link Signal} without an initial value.
|
|
155
|
+
*
|
|
156
|
+
* @template TValue the type of the {@link Signal} value.
|
|
157
|
+
*
|
|
158
|
+
* @version 1.0.0
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* const signal = Signal<string>()
|
|
162
|
+
* const initiallyUndefined = signal.read(monitor) === undefined
|
|
163
|
+
*/
|
|
164
|
+
declare function Signal<TValue = undefined>(): Signal<undefined | TValue>;
|
|
165
|
+
/**
|
|
166
|
+
* Creates a new Derived {@link ReadonlySignal}.
|
|
167
|
+
* A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.
|
|
168
|
+
*
|
|
169
|
+
* @template TDerivedValue the type of the derived {@link Signal} value.
|
|
170
|
+
*
|
|
171
|
+
* @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.
|
|
172
|
+
* @param options optional {@link SignalOptions}.
|
|
173
|
+
* @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.
|
|
174
|
+
*
|
|
175
|
+
* @returns a new {@link ReadonlySignal}.
|
|
176
|
+
*
|
|
177
|
+
* @version 1.0.0
|
|
178
|
+
*/
|
|
179
|
+
declare function Signal<TDerivedValue>(getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue), options?: SignalOptions<TDerivedValue>): ReadonlySignal<TDerivedValue>;
|
|
180
|
+
/**
|
|
181
|
+
* Creates a new derived {@link Signal}.
|
|
182
|
+
* A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.
|
|
183
|
+
*
|
|
184
|
+
* @template TDerivedValue the type of the derived {@link Signal} value.
|
|
185
|
+
*
|
|
186
|
+
* @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.
|
|
187
|
+
* @param setter either anything that implements the {@link WritableSignal} interface or a function to write the derived value back to the source.
|
|
188
|
+
* @param options optional {@link SignalOptions}.
|
|
189
|
+
* @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.
|
|
190
|
+
*
|
|
191
|
+
* @returns a new {@link Signal}.
|
|
192
|
+
*
|
|
193
|
+
* @version 1.0.0
|
|
194
|
+
*/
|
|
195
|
+
declare function Signal<TDerivedValue>(getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue), setter: WritableSignal<TDerivedValue> | ((value: TDerivedValue, monitor: Monitor) => void), options?: SignalOptions<TDerivedValue>): Signal<TDerivedValue>;
|
|
196
|
+
/**
|
|
197
|
+
* Creates a new {@link Signal}.
|
|
198
|
+
*
|
|
199
|
+
* @template TValue the type of the {@link Signal} value.
|
|
200
|
+
*
|
|
201
|
+
* @param initialValue the initial value.
|
|
202
|
+
* @param options optional {@link SignalOptions}.
|
|
203
|
+
* @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.
|
|
204
|
+
*
|
|
205
|
+
* @version 1.0.0
|
|
206
|
+
*/
|
|
207
|
+
declare function Signal<TValue>(initialValue: TValue, options?: SignalOptions<TValue>): Signal<TValue>;
|
|
208
|
+
|
|
209
|
+
declare const isDerivedSignal: {
|
|
210
|
+
/**
|
|
211
|
+
* A function to check whether or not the input is a Derived {@link Signal}.
|
|
212
|
+
*
|
|
213
|
+
* @version 1.0.0
|
|
214
|
+
*/
|
|
215
|
+
<T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>;
|
|
216
|
+
/**
|
|
217
|
+
* A function to check whether or not the input is a Derived {@link Signal}.
|
|
218
|
+
*
|
|
219
|
+
* @version 1.0.0
|
|
220
|
+
*/
|
|
221
|
+
<T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
222
|
+
/**
|
|
223
|
+
* A function to check whether or not a Derived {@link Signal} value passes the {@link check}.
|
|
224
|
+
*
|
|
225
|
+
* @version 1.0.0
|
|
226
|
+
*/
|
|
227
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | Signal<T>): input is Signal<T>;
|
|
228
|
+
/**
|
|
229
|
+
* A function to check whether or not a Derived {@link Signal} value passes the {@link check}.
|
|
230
|
+
*
|
|
231
|
+
* @version 1.0.0
|
|
232
|
+
*/
|
|
233
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
declare const isSignal: {
|
|
237
|
+
/**
|
|
238
|
+
* A function to check whether or not the input is a {@link Signal}.
|
|
239
|
+
*
|
|
240
|
+
* @version 1.0.0
|
|
241
|
+
*/
|
|
242
|
+
<T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>;
|
|
243
|
+
/**
|
|
244
|
+
* A function to check whether or not the input is a {@link Signal}.
|
|
245
|
+
*
|
|
246
|
+
* @version 1.0.0
|
|
247
|
+
*/
|
|
248
|
+
<T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
249
|
+
/**
|
|
250
|
+
* A function to check whether or not a {@link Signal} value passes the {@link check}.
|
|
251
|
+
*
|
|
252
|
+
* @version 1.0.0
|
|
253
|
+
*/
|
|
254
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | Signal<T>): input is Signal<T>;
|
|
255
|
+
/**
|
|
256
|
+
* A function to check whether or not a {@link Signal} value passes the {@link check}.
|
|
257
|
+
*
|
|
258
|
+
* @version 1.0.0
|
|
259
|
+
*/
|
|
260
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Ignores tracking any of the {@link Signal} attached to the provided {@link Monitor}.
|
|
265
|
+
* Acts like {@link batch} but returns the {@link factory} function result.
|
|
266
|
+
*
|
|
267
|
+
* @param factory a function that provides {@link Monitor} as the first argument and returns a result.
|
|
268
|
+
*
|
|
269
|
+
* @returns the {@link factory} function result.
|
|
270
|
+
*
|
|
271
|
+
* @version 1.0.0
|
|
272
|
+
*/
|
|
273
|
+
declare function untracked<TResult>(factory: (monitor: Monitor) => TResult): TResult;
|
|
274
|
+
/**
|
|
275
|
+
* Extracts the value from the provided {@link signal} without tracking it.
|
|
276
|
+
*
|
|
277
|
+
* @param signal anything that implements the {@link ReadableSignal} interface.
|
|
278
|
+
*
|
|
279
|
+
* @returns the {@link signal} value.
|
|
280
|
+
*
|
|
281
|
+
* @version 1.0.0
|
|
282
|
+
*/
|
|
283
|
+
declare function untracked<TValue>(signal: ReadableSignal<TValue>): TValue;
|
|
284
|
+
|
|
285
|
+
export { type Destructor, type Equal, Monitor, type ReadableSignal, type ReadonlySignal, Signal, type SignalOptions, type WritableSignal, batch, effect, isDerivedSignal, isSignal, untracked };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { M as Monitor, a as MonitorEmitter } from './monitor-BQJbbQ1I.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A helper to optimize multiple {@link Signal}s updates.
|
|
5
|
+
*
|
|
6
|
+
* @param execute a function that executes multiple {@link Signal.write} calls at ones.
|
|
7
|
+
* It provides {@link Monitor} to the {@link execute} function so it is useful when an async operation accesses the {@link Signal}s' values.
|
|
8
|
+
*
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
declare function batch(execute: (monitor: Monitor) => void): void;
|
|
12
|
+
|
|
13
|
+
declare const UNDEFINED_VOID_ONLY: unique symbol;
|
|
14
|
+
/**
|
|
15
|
+
* @version 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
type Destructor = void | (() => void | {
|
|
18
|
+
[UNDEFINED_VOID_ONLY]: never;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A function that provides {@link Monitor} as the first argument subscribes to changes of all {@link Signal} instances that call the {@link Signal.read} method inside the {@link listener}.
|
|
23
|
+
*
|
|
24
|
+
* @param listener Function that will be called on each {@link Signal} change, involved in the {@link listener} execution.
|
|
25
|
+
* Calls first time synchronously when {@link effect} is called.
|
|
26
|
+
* If {@link listener} returns a function then it will be called before the next {@link listener} call.
|
|
27
|
+
*
|
|
28
|
+
* @returns Dispose function that unsubscribes the {@link listener} from all involved {@link Signal} instances.
|
|
29
|
+
*
|
|
30
|
+
* @version 1.0.0
|
|
31
|
+
*/
|
|
32
|
+
declare function effect(listener: (monitor: Monitor) => Destructor): VoidFunction;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The equality check function.
|
|
36
|
+
*
|
|
37
|
+
*
|
|
38
|
+
* @template T the type of values to compare.
|
|
39
|
+
* @param left the first value to compare.
|
|
40
|
+
* @param right the second value to compare.
|
|
41
|
+
* @returns `true` if the two values are considered equal, otherwise `false`.
|
|
42
|
+
*
|
|
43
|
+
* @version 1.0.0
|
|
44
|
+
*/
|
|
45
|
+
type Equal<T> = (left: T, right: T) => boolean;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @version 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
interface ReadableSignal<T> {
|
|
51
|
+
read(monitor: Monitor): T;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The options for creating and cloning a {@link Signal}.
|
|
56
|
+
*
|
|
57
|
+
* @template T the type of the {@link Signal} value.
|
|
58
|
+
*
|
|
59
|
+
* @version 1.0.0
|
|
60
|
+
*/
|
|
61
|
+
interface SignalOptions<T> {
|
|
62
|
+
/**
|
|
63
|
+
* The equality function determines whether or not a new {@link Signal}'s value replaces the current one.
|
|
64
|
+
* In some cases specifying the function leads to better performance because it prevents unnecessary updates.
|
|
65
|
+
*/
|
|
66
|
+
readonly equals?: null | Equal<T>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @version 1.0.0
|
|
71
|
+
*/
|
|
72
|
+
interface WritableSignal<T> {
|
|
73
|
+
write(value: T): void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
declare abstract class BaseSignal<T> implements ReadableSignal<T>, WritableSignal<T> {
|
|
77
|
+
protected readonly _equals: Equal<T>;
|
|
78
|
+
protected readonly _emitters: Set<WeakRef<MonitorEmitter>>;
|
|
79
|
+
protected constructor(_equals: Equal<T>);
|
|
80
|
+
protected abstract _getter(): T;
|
|
81
|
+
protected abstract _setter(value: T): boolean;
|
|
82
|
+
protected abstract _clone(value: T, equals: Equal<T>): Signal<T>;
|
|
83
|
+
/**
|
|
84
|
+
* Return the value when serializing to JSON.
|
|
85
|
+
* It does not encode the instance for decoding it back due to runtime parts of the class,
|
|
86
|
+
* that cannot be serialized as JSON.
|
|
87
|
+
*
|
|
88
|
+
* The method is protected in order to make it impossible to make the implicit call.
|
|
89
|
+
*
|
|
90
|
+
* @version 1.0.0
|
|
91
|
+
*/
|
|
92
|
+
protected toJSON(): unknown;
|
|
93
|
+
/**
|
|
94
|
+
* Return the stringified value when the instance converts to a string.
|
|
95
|
+
*
|
|
96
|
+
* The method is protected in order to make it impossible to make the implicit call.
|
|
97
|
+
* @version 1.0.0
|
|
98
|
+
*/
|
|
99
|
+
protected toString(): string;
|
|
100
|
+
/**
|
|
101
|
+
* Reads the instance's value.
|
|
102
|
+
*
|
|
103
|
+
* @param monitor the {@link Monitor} that tracks the instance value changes.
|
|
104
|
+
*
|
|
105
|
+
* @returns the instance value.
|
|
106
|
+
*
|
|
107
|
+
* @version 1.0.0
|
|
108
|
+
*/
|
|
109
|
+
read(monitor: Monitor): T;
|
|
110
|
+
/**
|
|
111
|
+
* Updates the value.
|
|
112
|
+
*
|
|
113
|
+
* @param valueOrTransform either the new value or a function that transforms the current value.
|
|
114
|
+
*
|
|
115
|
+
* @returns `void` to emphasize that {@link Signal}s are mutable.
|
|
116
|
+
*
|
|
117
|
+
* @version 1.0.0
|
|
118
|
+
*/
|
|
119
|
+
write(valueOrTransform: T | ((currentValue: T, monitor: Monitor) => T)): void;
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new {@link Signal} instance out of the current one with the same value.
|
|
122
|
+
*
|
|
123
|
+
* @param options optional {@link SignalOptions}.
|
|
124
|
+
* @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.
|
|
125
|
+
*
|
|
126
|
+
* @returns a new {@link Signal} instance with the same value.
|
|
127
|
+
*
|
|
128
|
+
* @version 1.0.0
|
|
129
|
+
*/
|
|
130
|
+
clone(options?: SignalOptions<T>): Signal<T>;
|
|
131
|
+
/**
|
|
132
|
+
* Creates a new {@link Signal} instance out of the current one with the transformed value. Transforming might be handy when cloning mutable values (such as a {@link Signal}).
|
|
133
|
+
*
|
|
134
|
+
* @param transform an optional function that applies to the current value before cloning. It might be handy when cloning mutable values.
|
|
135
|
+
* @param options optional {@link SignalOptions}.
|
|
136
|
+
* @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.
|
|
137
|
+
*
|
|
138
|
+
* @return a new {@link Signal} instance with the transformed value.
|
|
139
|
+
*
|
|
140
|
+
* @version 1.0.0
|
|
141
|
+
*/
|
|
142
|
+
clone(transform: (value: T, monitor: Monitor) => T, options?: SignalOptions<T>): Signal<T>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @version 1.0.0
|
|
147
|
+
*/
|
|
148
|
+
type ReadonlySignal<T> = Omit<Signal<T>, "write">;
|
|
149
|
+
/**
|
|
150
|
+
* @version 1.0.0
|
|
151
|
+
*/
|
|
152
|
+
type Signal<T> = BaseSignal<T>;
|
|
153
|
+
/**
|
|
154
|
+
* Creates a new {@link Signal} without an initial value.
|
|
155
|
+
*
|
|
156
|
+
* @template TValue the type of the {@link Signal} value.
|
|
157
|
+
*
|
|
158
|
+
* @version 1.0.0
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* const signal = Signal<string>()
|
|
162
|
+
* const initiallyUndefined = signal.read(monitor) === undefined
|
|
163
|
+
*/
|
|
164
|
+
declare function Signal<TValue = undefined>(): Signal<undefined | TValue>;
|
|
165
|
+
/**
|
|
166
|
+
* Creates a new Derived {@link ReadonlySignal}.
|
|
167
|
+
* A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.
|
|
168
|
+
*
|
|
169
|
+
* @template TDerivedValue the type of the derived {@link Signal} value.
|
|
170
|
+
*
|
|
171
|
+
* @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.
|
|
172
|
+
* @param options optional {@link SignalOptions}.
|
|
173
|
+
* @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.
|
|
174
|
+
*
|
|
175
|
+
* @returns a new {@link ReadonlySignal}.
|
|
176
|
+
*
|
|
177
|
+
* @version 1.0.0
|
|
178
|
+
*/
|
|
179
|
+
declare function Signal<TDerivedValue>(getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue), options?: SignalOptions<TDerivedValue>): ReadonlySignal<TDerivedValue>;
|
|
180
|
+
/**
|
|
181
|
+
* Creates a new derived {@link Signal}.
|
|
182
|
+
* A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.
|
|
183
|
+
*
|
|
184
|
+
* @template TDerivedValue the type of the derived {@link Signal} value.
|
|
185
|
+
*
|
|
186
|
+
* @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.
|
|
187
|
+
* @param setter either anything that implements the {@link WritableSignal} interface or a function to write the derived value back to the source.
|
|
188
|
+
* @param options optional {@link SignalOptions}.
|
|
189
|
+
* @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.
|
|
190
|
+
*
|
|
191
|
+
* @returns a new {@link Signal}.
|
|
192
|
+
*
|
|
193
|
+
* @version 1.0.0
|
|
194
|
+
*/
|
|
195
|
+
declare function Signal<TDerivedValue>(getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue), setter: WritableSignal<TDerivedValue> | ((value: TDerivedValue, monitor: Monitor) => void), options?: SignalOptions<TDerivedValue>): Signal<TDerivedValue>;
|
|
196
|
+
/**
|
|
197
|
+
* Creates a new {@link Signal}.
|
|
198
|
+
*
|
|
199
|
+
* @template TValue the type of the {@link Signal} value.
|
|
200
|
+
*
|
|
201
|
+
* @param initialValue the initial value.
|
|
202
|
+
* @param options optional {@link SignalOptions}.
|
|
203
|
+
* @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.
|
|
204
|
+
*
|
|
205
|
+
* @version 1.0.0
|
|
206
|
+
*/
|
|
207
|
+
declare function Signal<TValue>(initialValue: TValue, options?: SignalOptions<TValue>): Signal<TValue>;
|
|
208
|
+
|
|
209
|
+
declare const isDerivedSignal: {
|
|
210
|
+
/**
|
|
211
|
+
* A function to check whether or not the input is a Derived {@link Signal}.
|
|
212
|
+
*
|
|
213
|
+
* @version 1.0.0
|
|
214
|
+
*/
|
|
215
|
+
<T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>;
|
|
216
|
+
/**
|
|
217
|
+
* A function to check whether or not the input is a Derived {@link Signal}.
|
|
218
|
+
*
|
|
219
|
+
* @version 1.0.0
|
|
220
|
+
*/
|
|
221
|
+
<T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
222
|
+
/**
|
|
223
|
+
* A function to check whether or not a Derived {@link Signal} value passes the {@link check}.
|
|
224
|
+
*
|
|
225
|
+
* @version 1.0.0
|
|
226
|
+
*/
|
|
227
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | Signal<T>): input is Signal<T>;
|
|
228
|
+
/**
|
|
229
|
+
* A function to check whether or not a Derived {@link Signal} value passes the {@link check}.
|
|
230
|
+
*
|
|
231
|
+
* @version 1.0.0
|
|
232
|
+
*/
|
|
233
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
declare const isSignal: {
|
|
237
|
+
/**
|
|
238
|
+
* A function to check whether or not the input is a {@link Signal}.
|
|
239
|
+
*
|
|
240
|
+
* @version 1.0.0
|
|
241
|
+
*/
|
|
242
|
+
<T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>;
|
|
243
|
+
/**
|
|
244
|
+
* A function to check whether or not the input is a {@link Signal}.
|
|
245
|
+
*
|
|
246
|
+
* @version 1.0.0
|
|
247
|
+
*/
|
|
248
|
+
<T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
249
|
+
/**
|
|
250
|
+
* A function to check whether or not a {@link Signal} value passes the {@link check}.
|
|
251
|
+
*
|
|
252
|
+
* @version 1.0.0
|
|
253
|
+
*/
|
|
254
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | Signal<T>): input is Signal<T>;
|
|
255
|
+
/**
|
|
256
|
+
* A function to check whether or not a {@link Signal} value passes the {@link check}.
|
|
257
|
+
*
|
|
258
|
+
* @version 1.0.0
|
|
259
|
+
*/
|
|
260
|
+
<T, Unknown = unknown>(monitor: Monitor, check: (value: unknown) => value is T, input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Ignores tracking any of the {@link Signal} attached to the provided {@link Monitor}.
|
|
265
|
+
* Acts like {@link batch} but returns the {@link factory} function result.
|
|
266
|
+
*
|
|
267
|
+
* @param factory a function that provides {@link Monitor} as the first argument and returns a result.
|
|
268
|
+
*
|
|
269
|
+
* @returns the {@link factory} function result.
|
|
270
|
+
*
|
|
271
|
+
* @version 1.0.0
|
|
272
|
+
*/
|
|
273
|
+
declare function untracked<TResult>(factory: (monitor: Monitor) => TResult): TResult;
|
|
274
|
+
/**
|
|
275
|
+
* Extracts the value from the provided {@link signal} without tracking it.
|
|
276
|
+
*
|
|
277
|
+
* @param signal anything that implements the {@link ReadableSignal} interface.
|
|
278
|
+
*
|
|
279
|
+
* @returns the {@link signal} value.
|
|
280
|
+
*
|
|
281
|
+
* @version 1.0.0
|
|
282
|
+
*/
|
|
283
|
+
declare function untracked<TValue>(signal: ReadableSignal<TValue>): TValue;
|
|
284
|
+
|
|
285
|
+
export { type Destructor, type Equal, Monitor, type ReadableSignal, type ReadonlySignal, Signal, type SignalOptions, type WritableSignal, batch, effect, isDerivedSignal, isSignal, untracked };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{MonitorEmitter,MonitorFactory,UNTRACKED_MONITOR,attachToMonitor,enqueue,extractMonitor,injectMonitor}from"./chunk-BE3J7QIW.js";function batch(t){enqueue(()=>{t(UNTRACKED_MONITOR)})}function effect(t){let n;const i=new MonitorFactory,e=()=>{n?.(),n=injectMonitor(t,i.create())},r=i.connect(e);return e(),()=>{batch(()=>{r(),n?.()})}}function createIsSignal(t){return(...[n,i,e])=>{if(!i)return t(n);if(t(e)){return i(e.read(n))}return!1}}function isFunction(t){return"function"==typeof t}function isStrictEqual(t,n){return Object.is(t,n)}var BaseSignal=class{constructor(t){this.t=t,this.$=new Set}toJSON(){const t=extractMonitor();return this.read(t)}toString(){const t=extractMonitor();return String(this.read(t))}read(t){return attachToMonitor(t,this.$),this.i()}write(t){enqueue(n=>{const i=isFunction(t)?t(this.i(),UNTRACKED_MONITOR):t;this.o(i)&&n(this.$)})}clone(t,n){const i=this.i(),[e,{equals:r=this.t}={}]=isFunction(t)?[t(i,UNTRACKED_MONITOR),n]:[i,t];return this.u(e,r??isStrictEqual)}},Signal=class t extends BaseSignal{constructor(t,n){super(n),this._=t}i(){return this._}o(t){return!this.t(this._,t)&&(this._=t,!0)}u(n,i){return new t(n,i)}},DerivedSignal=class extends BaseSignal{constructor(t,n,i){super(i),this.h=t,this.l=n,this.S=new MonitorEmitter(()=>{this.t(this._,this.h(UNTRACKED_MONITOR))?injectMonitor(this.h,this.S):(this.O=!0,enqueue(t=>t(this.$)))},!0).M(),this._=null,this.O=!0}i(){const t=this.h(this.S);return this.O&&(this._=t,this.O=!1),this._}o(t){return this.l(t,UNTRACKED_MONITOR),!1}u(t,n){return new Signal(t,n)}},isDerivedSignal=createIsSignal(t=>t instanceof DerivedSignal),isSignal=createIsSignal(t=>t instanceof BaseSignal);function hasProperty(t,n){return"object"==typeof t&&null!=t&&n in t}function Signal2(t,n,i){const e=isFunction(t);if(!e&&!hasProperty(t,"read")){const i=n;return new Signal(t,i?.equals??isStrictEqual)}const[r,s]=isFunction(n)||hasProperty(n,"write")?[n,i]:[void 0,n];return new DerivedSignal(e?t:n=>t.read(n),isFunction(r)?r:t=>r?.write(t),s?.equals??isStrictEqual)}function untracked(t){return enqueue(()=>isFunction(t)?t(UNTRACKED_MONITOR):t.read(UNTRACKED_MONITOR))}export{Signal2 as Signal,batch,effect,isDerivedSignal,isSignal,untracked};//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/batch.ts","../src/effect.ts","../src/_internal/create-is-signal.ts","../../tools/src/is-function.ts","../../tools/src/is-strict-equal.ts","../src/_internal/base-signal.ts","../src/_internal/signal.ts","../src/_internal/derived-signal.ts","../src/is-derived-signal.ts","../src/is-signal.ts","../../tools/src/has-property.ts","../src/signal.ts","../src/untracked.ts"],"sourcesContent":["import type { Signal } from \"./signal\"\nimport { enqueue } from \"./_internal/enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR } from \"./_internal/monitor\"\n\n/**\n * A helper to optimize multiple {@link Signal}s updates.\n *\n * @param execute a function that executes multiple {@link Signal.write} calls at ones.\n * It provides {@link Monitor} to the {@link execute} function so it is useful when an async operation accesses the {@link Signal}s' values.\n *\n * @version 1.0.0\n */\nfunction batch(execute: (monitor: Monitor) => void): void {\n enqueue(() => {\n execute(UNTRACKED_MONITOR)\n })\n}\n\nexport { batch }\n","import { batch } from \"./batch\"\nimport type { Destructor } from \"./destructor\"\nimport { MonitorFactory } from \"./monitor-factory\"\nimport type { Signal } from \"./signal\"\nimport { type Monitor, injectMonitor } from \"./_internal/monitor\"\n\n/**\n * A function that provides {@link Monitor} as the first argument subscribes to changes of all {@link Signal} instances that call the {@link Signal.read} method inside the {@link listener}.\n *\n * @param listener Function that will be called on each {@link Signal} change, involved in the {@link listener} execution.\n * Calls first time synchronously when {@link effect} is called.\n * If {@link listener} returns a function then it will be called before the next {@link listener} call.\n *\n * @returns Dispose function that unsubscribes the {@link listener} from all involved {@link Signal} instances.\n *\n * @version 1.0.0\n */\nfunction effect(listener: (monitor: Monitor) => Destructor): VoidFunction {\n let dispose: Destructor\n\n const factory = new MonitorFactory()\n\n const emit = (): void => {\n dispose?.()\n dispose = injectMonitor(listener, factory.create())\n }\n\n const disconnect = factory.connect(emit)\n\n emit()\n\n return () => {\n batch(() => {\n disconnect()\n dispose?.()\n })\n }\n}\n\nexport { effect }\n","import type { BaseSignal } from \"./base-signal\"\nimport type { Monitor } from \"./monitor\"\n\nfunction createIsSignal(isSignal: (input: unknown) => input is BaseSignal<unknown>) {\n return (\n ...[inputOrMonitor, maybeCheck, maybeInput]:\n | [input: unknown]\n | [monitor: Monitor, check: (input: unknown) => boolean, input: unknown]\n ): boolean => {\n if (!maybeCheck) {\n return isSignal(inputOrMonitor)\n }\n\n if (isSignal(maybeInput)) {\n const value = maybeInput.read(inputOrMonitor as Monitor)\n\n return maybeCheck(value)\n }\n\n return false\n }\n}\n\nexport { createIsSignal }\n","type DefinitelyFunction<T> =\n // biome-ignore lint/complexity/noBannedTypes: use Function to ensure correct typing\n Extract<T, Function> extends never ? Function : Extract<T, Function>\n\nfunction isFunction<T>(\n // biome-ignore lint/complexity/noBannedTypes: use Function to ensure correct typing\n data: Function | T,\n): data is DefinitelyFunction<T> {\n return typeof data === \"function\"\n}\n\nexport { isFunction }\n","function isStrictEqual<T>(left: T, right: T): boolean {\n return Object.is(left, right)\n}\n\nexport { isStrictEqual }\n","import { isFunction } from \"~/tools/is-function\"\nimport { isStrictEqual } from \"~/tools/is-strict-equal\"\n\nimport type { Equal } from \"../equal\"\nimport type { ReadableSignal } from \"../readable-signal\"\nimport type { Signal } from \"../signal\"\nimport type { SignalOptions } from \"../signal-options\"\nimport type { WritableSignal } from \"../writable-signal\"\n\nimport { enqueue } from \"./enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR, attachToMonitor, extractMonitor } from \"./monitor\"\nimport type { MonitorEmitter } from \"./monitor-emitter\"\n\nabstract class BaseSignal<T> implements ReadableSignal<T>, WritableSignal<T> {\n protected readonly _emitters = new Set<WeakRef<MonitorEmitter>>()\n\n protected constructor(protected readonly _equals: Equal<T>) {}\n\n protected abstract _getter(): T\n\n protected abstract _setter(value: T): boolean\n\n protected abstract _clone(value: T, equals: Equal<T>): Signal<T>\n\n /**\n * Return the value when serializing to JSON.\n * It does not encode the instance for decoding it back due to runtime parts of the class,\n * that cannot be serialized as JSON.\n *\n * The method is protected in order to make it impossible to make the implicit call.\n *\n * @version 1.0.0\n */\n protected toJSON(): unknown {\n const monitor = extractMonitor()\n\n return this.read(monitor)\n }\n\n /**\n * Return the stringified value when the instance converts to a string.\n *\n * The method is protected in order to make it impossible to make the implicit call.\n * @version 1.0.0\n */\n protected toString(): string {\n const monitor = extractMonitor()\n\n return String(this.read(monitor))\n }\n\n /**\n * Reads the instance's value.\n *\n * @param monitor the {@link Monitor} that tracks the instance value changes.\n *\n * @returns the instance value.\n *\n * @version 1.0.0\n */\n public read(monitor: Monitor): T {\n attachToMonitor(monitor, this._emitters)\n\n return this._getter()\n }\n\n /**\n * Updates the value.\n *\n * @param valueOrTransform either the new value or a function that transforms the current value.\n *\n * @returns `void` to emphasize that {@link Signal}s are mutable.\n *\n * @version 1.0.0\n */\n public write(valueOrTransform: T | ((currentValue: T, monitor: Monitor) => T)): void {\n enqueue((push) => {\n const nextValue = isFunction(valueOrTransform)\n ? valueOrTransform(this._getter(), UNTRACKED_MONITOR)\n : valueOrTransform\n\n if (this._setter(nextValue)) {\n push(this._emitters)\n }\n })\n }\n\n /**\n * Creates a new {@link Signal} instance out of the current one with the same value.\n *\n * @param options optional {@link SignalOptions}.\n * @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.\n *\n * @returns a new {@link Signal} instance with the same value.\n *\n * @version 1.0.0\n */\n public clone(options?: SignalOptions<T>): Signal<T>\n\n /**\n * Creates a new {@link Signal} instance out of the current one with the transformed value. Transforming might be handy when cloning mutable values (such as a {@link Signal}).\n *\n * @param transform an optional function that applies to the current value before cloning. It might be handy when cloning mutable values.\n * @param options optional {@link SignalOptions}.\n * @param options.equal when not defined it uses the {@link SignalOptions.equals} function from the origin instance, When `null` fallbacks to {@link Object.is}.\n *\n * @return a new {@link Signal} instance with the transformed value.\n *\n * @version 1.0.0\n */\n public clone(transform: (value: T, monitor: Monitor) => T, options?: SignalOptions<T>): Signal<T>\n\n public clone(\n transformOrOptions?: ((value: T, monitor: Monitor) => T) | SignalOptions<T>,\n maybeOptions?: SignalOptions<T>,\n ): Signal<T> {\n const value = this._getter()\n\n const [clonedValue, { equals = this._equals } = {}] = isFunction(transformOrOptions)\n ? [transformOrOptions(value, UNTRACKED_MONITOR), maybeOptions]\n : [value, transformOrOptions]\n\n return this._clone(clonedValue, equals ?? isStrictEqual)\n }\n}\n\nexport { BaseSignal }\n","import type { Equal } from \"../equal\"\n\nimport { BaseSignal } from \"./base-signal\"\n\nclass Signal<T> extends BaseSignal<T> {\n public constructor(\n private _value: T,\n equals: Equal<T>,\n ) {\n super(equals)\n }\n\n protected _getter(): T {\n return this._value\n }\n\n protected _setter(value: T): boolean {\n if (!this._equals(this._value, value)) {\n this._value = value\n\n return true\n }\n\n return false\n }\n\n protected _clone(value: T, equals: Equal<T>): Signal<T> {\n return new Signal(value, equals)\n }\n}\n\nexport { Signal }\n","import type { Equal } from \"../equal\"\n\nimport { BaseSignal } from \"./base-signal\"\nimport { enqueue } from \"./enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR, injectMonitor } from \"./monitor\"\nimport { MonitorEmitter } from \"./monitor-emitter\"\nimport { Signal } from \"./signal\"\n\nclass DerivedSignal<T> extends BaseSignal<T> {\n // the inner monitor proxies the setters to the outer monitor\n private readonly _monitor = new MonitorEmitter(() => {\n if (this._equals(this._value, this._getValue(UNTRACKED_MONITOR))) {\n // subscribe back to the dependencies\n injectMonitor(this._getValue, this._monitor)\n } else {\n this._stale = true\n enqueue((push) => push(this._emitters))\n }\n }, true)._create()\n\n // biome-ignore lint/style/noNonNullAssertion: the value is never null because it assigns the value from the _getValue on the first _getter call\n private _value: T = null!\n private _stale = true\n\n public constructor(\n private readonly _getValue: (monitor: Monitor) => T,\n private readonly _setValue: (value: T, monitor: Monitor) => void,\n equals: Equal<T>,\n ) {\n super(equals)\n }\n\n protected _getter(): T {\n const value = this._getValue(this._monitor)\n\n if (this._stale) {\n this._value = value\n this._stale = false\n }\n\n return this._value\n }\n\n protected _setter(value: T): boolean {\n this._setValue(value, UNTRACKED_MONITOR)\n\n return false\n }\n\n protected _clone(value: T, equals: Equal<T>): Signal<T> {\n return new Signal(value, equals)\n }\n}\n\nexport { DerivedSignal }\n","import type { ReadonlySignal, Signal } from \"./signal\"\nimport { createIsSignal } from \"./_internal/create-is-signal\"\nimport { DerivedSignal } from \"./_internal/derived-signal\"\nimport type { Monitor } from \"./_internal/monitor\"\n\nconst isDerivedSignal = createIsSignal((input) => input instanceof DerivedSignal) as {\n /**\n * A function to check whether or not the input is a Derived {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>\n\n /**\n * A function to check whether or not the input is a Derived {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>\n\n /**\n * A function to check whether or not a Derived {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | Signal<T>,\n ): input is Signal<T>\n\n /**\n * A function to check whether or not a Derived {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | ReadonlySignal<T>,\n ): input is ReadonlySignal<T>\n}\n\nexport { isDerivedSignal }\n","import type { ReadonlySignal, Signal } from \"./signal\"\nimport { BaseSignal } from \"./_internal/base-signal\"\nimport { createIsSignal } from \"./_internal/create-is-signal\"\nimport type { Monitor } from \"./_internal/monitor\"\n\nconst isSignal = createIsSignal((input) => input instanceof BaseSignal) as {\n /**\n * A function to check whether or not the input is a {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | Signal<T>): input is Signal<T>\n\n /**\n * A function to check whether or not the input is a {@link Signal}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(input: Unknown | ReadonlySignal<T>): input is ReadonlySignal<T>\n\n /**\n * A function to check whether or not a {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | Signal<T>,\n ): input is Signal<T>\n\n /**\n * A function to check whether or not a {@link Signal} value passes the {@link check}.\n *\n * @version 1.0.0\n */\n <T, Unknown = unknown>(\n monitor: Monitor,\n check: (value: unknown) => value is T,\n input: Unknown | ReadonlySignal<T>,\n ): input is ReadonlySignal<T>\n}\n\nexport { isSignal }\n","function hasProperty<TKey extends PropertyKey>(\n input: unknown,\n key: TKey,\n): input is Record<TKey, unknown> {\n return typeof input === \"object\" && input != null && key in input\n}\n\nexport { hasProperty }\n","import { hasProperty } from \"~/tools/has-property\"\nimport { isFunction } from \"~/tools/is-function\"\nimport { isStrictEqual } from \"~/tools/is-strict-equal\"\n\nimport type { Equal } from \"./equal\"\nimport type { ReadableSignal } from \"./readable-signal\"\nimport type { SignalOptions } from \"./signal-options\"\nimport type { WritableSignal } from \"./writable-signal\"\nimport type { BaseSignal } from \"./_internal/base-signal\"\nimport { DerivedSignal } from \"./_internal/derived-signal\"\nimport type { Monitor } from \"./_internal/monitor\"\nimport { Signal as SignalImpl } from \"./_internal/signal\"\n\n/**\n * @version 1.0.0\n */\ntype Signal<T> = BaseSignal<T>\n\n/**\n * @version 1.0.0\n */\ntype ReadonlySignal<T> = Omit<Signal<T>, \"write\">\n\n/**\n * Creates a new {@link Signal} without an initial value.\n *\n * @template TValue the type of the {@link Signal} value.\n *\n * @version 1.0.0\n *\n * @example\n * const signal = Signal<string>()\n * const initiallyUndefined = signal.read(monitor) === undefined\n */\nfunction Signal<TValue = undefined>(): Signal<undefined | TValue>\n\n/**\n * Creates a new Derived {@link ReadonlySignal}.\n * A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.\n *\n * @template TDerivedValue the type of the derived {@link Signal} value.\n *\n * @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.\n * @param options optional {@link SignalOptions}.\n * @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.\n *\n * @returns a new {@link ReadonlySignal}.\n *\n * @version 1.0.0\n */\nfunction Signal<TDerivedValue>(\n getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue),\n options?: SignalOptions<TDerivedValue>,\n): ReadonlySignal<TDerivedValue>\n\n/**\n * Creates a new derived {@link Signal}.\n * A Derived {@link Signal} is a Signal that keeps the derived value in memory and updates it whenever the source value changes.\n *\n * @template TDerivedValue the type of the derived {@link Signal} value.\n *\n * @param getter either anything that implements the {@link ReadableSignal} interface or a function to read the derived value from the source.\n * @param setter either anything that implements the {@link WritableSignal} interface or a function to write the derived value back to the source.\n * @param options optional {@link SignalOptions}.\n * @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.\n *\n * @returns a new {@link Signal}.\n *\n * @version 1.0.0\n */\nfunction Signal<TDerivedValue>(\n getter: ReadableSignal<TDerivedValue> | ((monitor: Monitor) => TDerivedValue),\n setter: WritableSignal<TDerivedValue> | ((value: TDerivedValue, monitor: Monitor) => void),\n options?: SignalOptions<TDerivedValue>,\n): Signal<TDerivedValue>\n\n/**\n * Creates a new {@link Signal}.\n *\n * @template TValue the type of the {@link Signal} value.\n *\n * @param initialValue the initial value.\n * @param options optional {@link SignalOptions}.\n * @param options.equals the {@link Equal} function that determines whether or not a new {@link Signal}'s value replaces the current one. Defaults to {@link Object.is}.\n *\n * @version 1.0.0\n */\nfunction Signal<TValue>(initialValue: TValue, options?: SignalOptions<TValue>): Signal<TValue>\n\nfunction Signal<T>(\n initialValueOrReadableSignal?: T | ReadableSignal<T> | ((monitor: Monitor) => T),\n optionsOrWritableSignal?:\n | SignalOptions<T>\n | WritableSignal<T>\n | ((value: T, monitor: Monitor) => void),\n optionsOrNothing?: SignalOptions<T>,\n): Signal<undefined | T> | Signal<T> {\n const isGetterFunction = isFunction(initialValueOrReadableSignal)\n\n if (!(isGetterFunction || hasProperty(initialValueOrReadableSignal, \"read\"))) {\n const directOptions = optionsOrWritableSignal as undefined | SignalOptions<undefined | T>\n\n return new SignalImpl(initialValueOrReadableSignal, directOptions?.equals ?? isStrictEqual)\n }\n\n const [setter, derivedOptions] =\n isFunction(optionsOrWritableSignal) || hasProperty(optionsOrWritableSignal, \"write\")\n ? [optionsOrWritableSignal, optionsOrNothing]\n : [undefined, optionsOrWritableSignal]\n\n return new DerivedSignal(\n isGetterFunction\n ? initialValueOrReadableSignal\n : (monitor) => initialValueOrReadableSignal.read(monitor),\n isFunction(setter) ? setter : (value) => setter?.write(value),\n derivedOptions?.equals ?? isStrictEqual,\n )\n}\n\nexport type { ReadonlySignal }\nexport { Signal }\n","import { isFunction } from \"~/tools/is-function\"\n\nimport type { batch } from \"./batch\"\nimport type { ReadableSignal } from \"./readable-signal\"\nimport type { Signal } from \"./signal\"\nimport { enqueue } from \"./_internal/enqueue\"\nimport { type Monitor, UNTRACKED_MONITOR } from \"./_internal/monitor\"\n\n/**\n * Ignores tracking any of the {@link Signal} attached to the provided {@link Monitor}.\n * Acts like {@link batch} but returns the {@link factory} function result.\n *\n * @param factory a function that provides {@link Monitor} as the first argument and returns a result.\n *\n * @returns the {@link factory} function result.\n *\n * @version 1.0.0\n */\nfunction untracked<TResult>(factory: (monitor: Monitor) => TResult): TResult\n\n/**\n * Extracts the value from the provided {@link signal} without tracking it.\n *\n * @param signal anything that implements the {@link ReadableSignal} interface.\n *\n * @returns the {@link signal} value.\n *\n * @version 1.0.0\n */\nfunction untracked<TValue>(signal: ReadableSignal<TValue>): TValue\n\nfunction untracked<T>(factoryOrReadableSignal: ((monitor: Monitor) => T) | ReadableSignal<T>): T {\n return enqueue(() => {\n if (isFunction(factoryOrReadableSignal)) {\n return factoryOrReadableSignal(UNTRACKED_MONITOR)\n }\n\n return factoryOrReadableSignal.read(UNTRACKED_MONITOR)\n })\n}\n\nexport { untracked }\n"],"mappings":"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","names":["isSignal","Signal"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages the lifecycle of monitor emitters, providing creation, attachment, and invalidation
|
|
3
|
+
* mechanisms for reactivity tracking within the {@link Signal} system.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Each instance maintains weak references to all emitters it is attached to, ensuring proper
|
|
7
|
+
* teardown when monitors are recreated or invalidated to avoid leaking subscriptions.
|
|
8
|
+
*/
|
|
9
|
+
declare class MonitorEmitter {
|
|
10
|
+
readonly _emit: VoidFunction;
|
|
11
|
+
readonly _derived: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Maintains the collections of monitor emitters this instance has been attached to, using nested
|
|
14
|
+
* sets of weak references so that attachments can be tracked without preventing garbage collection.
|
|
15
|
+
*/
|
|
16
|
+
private readonly _attachedTo;
|
|
17
|
+
/**
|
|
18
|
+
* Maintains a weak reference to the current monitor emitter instance, allowing listeners to access it without preventing garbage collection.
|
|
19
|
+
*/
|
|
20
|
+
private readonly _ref;
|
|
21
|
+
/**
|
|
22
|
+
* Initializes and returns a new instance of the {@link MonitorEmitter} class.
|
|
23
|
+
*
|
|
24
|
+
* @param _emit - Callback invoked via the internal queue whenever the {@link Monitor} needs to broadcast an update.
|
|
25
|
+
* @param _derived - Indicates whether the emitter originates from a {@link DerivedSignal}, deferring subscription until first access.
|
|
26
|
+
*/
|
|
27
|
+
constructor(_emit: VoidFunction, _derived: boolean);
|
|
28
|
+
/**
|
|
29
|
+
* Detaches the current {@link Monitor} reference from every emitter it is attached to
|
|
30
|
+
* and clears the internal tracking set to prevent stale subscriptions.
|
|
31
|
+
*/
|
|
32
|
+
private _detachFromAll;
|
|
33
|
+
/**
|
|
34
|
+
* Resets the current {@link Monitor} by detaching from all tracked emitters and returning a fresh {@link Monitor} instance bound to this emitter.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* A {@link Monitor} is always created on a new reading cycle, so all previous subscriptions must be cleared.
|
|
38
|
+
*
|
|
39
|
+
* @returns The newly created {@link Monitor} that references this emitter.
|
|
40
|
+
*/
|
|
41
|
+
private _renew;
|
|
42
|
+
/**
|
|
43
|
+
* Registers this monitor emitter with the provided collection of emitters,
|
|
44
|
+
* ensuring the weak reference is tracked for future coordination or cleanup.
|
|
45
|
+
*
|
|
46
|
+
* @param emitters - Set of weak references to monitor emitters that this instance should join.
|
|
47
|
+
*/
|
|
48
|
+
_attachTo(emitters: Set<WeakRef<MonitorEmitter>>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new {@link Monitor} associated with this emitter after clearing any existing attachments.
|
|
51
|
+
*
|
|
52
|
+
* @returns A fresh {@link Monitor} instance.
|
|
53
|
+
*/
|
|
54
|
+
_create: () => Monitor;
|
|
55
|
+
/**
|
|
56
|
+
* Resets the emitter state to ensure it detaches from all current dependencies and reinitializes its factory.
|
|
57
|
+
*/
|
|
58
|
+
_invalidate(): void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
declare const MONITOR_KEY: unique symbol;
|
|
62
|
+
/**
|
|
63
|
+
* @version 1.0.0
|
|
64
|
+
*/
|
|
65
|
+
interface Monitor {
|
|
66
|
+
readonly [MONITOR_KEY]: null | MonitorEmitter;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { type Monitor as M, MonitorEmitter as a };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages the lifecycle of monitor emitters, providing creation, attachment, and invalidation
|
|
3
|
+
* mechanisms for reactivity tracking within the {@link Signal} system.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Each instance maintains weak references to all emitters it is attached to, ensuring proper
|
|
7
|
+
* teardown when monitors are recreated or invalidated to avoid leaking subscriptions.
|
|
8
|
+
*/
|
|
9
|
+
declare class MonitorEmitter {
|
|
10
|
+
readonly _emit: VoidFunction;
|
|
11
|
+
readonly _derived: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Maintains the collections of monitor emitters this instance has been attached to, using nested
|
|
14
|
+
* sets of weak references so that attachments can be tracked without preventing garbage collection.
|
|
15
|
+
*/
|
|
16
|
+
private readonly _attachedTo;
|
|
17
|
+
/**
|
|
18
|
+
* Maintains a weak reference to the current monitor emitter instance, allowing listeners to access it without preventing garbage collection.
|
|
19
|
+
*/
|
|
20
|
+
private readonly _ref;
|
|
21
|
+
/**
|
|
22
|
+
* Initializes and returns a new instance of the {@link MonitorEmitter} class.
|
|
23
|
+
*
|
|
24
|
+
* @param _emit - Callback invoked via the internal queue whenever the {@link Monitor} needs to broadcast an update.
|
|
25
|
+
* @param _derived - Indicates whether the emitter originates from a {@link DerivedSignal}, deferring subscription until first access.
|
|
26
|
+
*/
|
|
27
|
+
constructor(_emit: VoidFunction, _derived: boolean);
|
|
28
|
+
/**
|
|
29
|
+
* Detaches the current {@link Monitor} reference from every emitter it is attached to
|
|
30
|
+
* and clears the internal tracking set to prevent stale subscriptions.
|
|
31
|
+
*/
|
|
32
|
+
private _detachFromAll;
|
|
33
|
+
/**
|
|
34
|
+
* Resets the current {@link Monitor} by detaching from all tracked emitters and returning a fresh {@link Monitor} instance bound to this emitter.
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* A {@link Monitor} is always created on a new reading cycle, so all previous subscriptions must be cleared.
|
|
38
|
+
*
|
|
39
|
+
* @returns The newly created {@link Monitor} that references this emitter.
|
|
40
|
+
*/
|
|
41
|
+
private _renew;
|
|
42
|
+
/**
|
|
43
|
+
* Registers this monitor emitter with the provided collection of emitters,
|
|
44
|
+
* ensuring the weak reference is tracked for future coordination or cleanup.
|
|
45
|
+
*
|
|
46
|
+
* @param emitters - Set of weak references to monitor emitters that this instance should join.
|
|
47
|
+
*/
|
|
48
|
+
_attachTo(emitters: Set<WeakRef<MonitorEmitter>>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new {@link Monitor} associated with this emitter after clearing any existing attachments.
|
|
51
|
+
*
|
|
52
|
+
* @returns A fresh {@link Monitor} instance.
|
|
53
|
+
*/
|
|
54
|
+
_create: () => Monitor;
|
|
55
|
+
/**
|
|
56
|
+
* Resets the emitter state to ensure it detaches from all current dependencies and reinitializes its factory.
|
|
57
|
+
*/
|
|
58
|
+
_invalidate(): void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
declare const MONITOR_KEY: unique symbol;
|
|
62
|
+
/**
|
|
63
|
+
* @version 1.0.0
|
|
64
|
+
*/
|
|
65
|
+
interface Monitor {
|
|
66
|
+
readonly [MONITOR_KEY]: null | MonitorEmitter;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { type Monitor as M, MonitorEmitter as a };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./chunk-NRM2F6O5.cjs");exports.MonitorFactory=e.MonitorFactory;//# sourceMappingURL=monitor-factory.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/signal/signal/packages/signal/dist/monitor-factory.cjs"],"names":[],"mappings":"AAAA;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,0DAAC","file":"/home/runner/work/signal/signal/packages/signal/dist/monitor-factory.cjs"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { M as Monitor } from './monitor-BQJbbQ1I.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Factory responsible for creating and managing {@link Monitor} instances through a shared
|
|
5
|
+
* internal {@link MonitorEmitter}. Use {@link MonitorFactory.create} to obtain a constructor for
|
|
6
|
+
* new monitors, and {@link MonitorFactory.connect} to subscribe an invalidation callback that
|
|
7
|
+
* will be invoked when the factory requests an emission.
|
|
8
|
+
*/
|
|
9
|
+
declare class MonitorFactory {
|
|
10
|
+
private _emit;
|
|
11
|
+
private readonly _emitter;
|
|
12
|
+
/**
|
|
13
|
+
* Registers an emission callback for the monitor emitter and returns a disposer.
|
|
14
|
+
*
|
|
15
|
+
* @param emit - Callback to invoke when the monitor emits changes.
|
|
16
|
+
*
|
|
17
|
+
* @returns A cleanup function that invalidates the underlying emitter when invoked.
|
|
18
|
+
*/
|
|
19
|
+
connect(emit: VoidFunction): VoidFunction;
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves the factory function used to instantiate new {@link Monitor} objects.
|
|
22
|
+
*
|
|
23
|
+
* @returns A function that creates and returns a fresh {@link Monitor}.
|
|
24
|
+
*/
|
|
25
|
+
get create(): () => Monitor;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { MonitorFactory };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { M as Monitor } from './monitor-BQJbbQ1I.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Factory responsible for creating and managing {@link Monitor} instances through a shared
|
|
5
|
+
* internal {@link MonitorEmitter}. Use {@link MonitorFactory.create} to obtain a constructor for
|
|
6
|
+
* new monitors, and {@link MonitorFactory.connect} to subscribe an invalidation callback that
|
|
7
|
+
* will be invoked when the factory requests an emission.
|
|
8
|
+
*/
|
|
9
|
+
declare class MonitorFactory {
|
|
10
|
+
private _emit;
|
|
11
|
+
private readonly _emitter;
|
|
12
|
+
/**
|
|
13
|
+
* Registers an emission callback for the monitor emitter and returns a disposer.
|
|
14
|
+
*
|
|
15
|
+
* @param emit - Callback to invoke when the monitor emits changes.
|
|
16
|
+
*
|
|
17
|
+
* @returns A cleanup function that invalidates the underlying emitter when invoked.
|
|
18
|
+
*/
|
|
19
|
+
connect(emit: VoidFunction): VoidFunction;
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves the factory function used to instantiate new {@link Monitor} objects.
|
|
22
|
+
*
|
|
23
|
+
* @returns A function that creates and returns a fresh {@link Monitor}.
|
|
24
|
+
*/
|
|
25
|
+
get create(): () => Monitor;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { MonitorFactory };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{MonitorFactory}from"./chunk-BE3J7QIW.js";export{MonitorFactory};//# sourceMappingURL=monitor-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owanturist/signal",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"description": "The clean and natural state management",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
},
|
|
36
36
|
"repository": "https://github.com/owanturist/signal/tree/master/packages/signal",
|
|
37
37
|
"homepage": "https://github.com/owanturist/signal/packages/signal#readme",
|
|
38
|
-
"scripts": {
|
|
39
|
-
"typecheck": "tsc --noEmit",
|
|
40
|
-
"build": "tsup src/index.ts src/monitor-factory.ts --config ../../tsup.config.ts"
|
|
41
|
-
},
|
|
42
38
|
"devDependencies": {
|
|
43
39
|
"vite-tsconfig-paths": "^6.0.5",
|
|
44
40
|
"vitest": "^4.0.18"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"build": "tsup src/index.ts src/monitor-factory.ts --config ../../tsup.config.ts"
|
|
45
45
|
}
|
|
46
|
-
}
|
|
46
|
+
}
|