@zeix/cause-effect 1.0.0 → 1.0.2
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/.github/copilot-instructions.md +5 -1
- package/.zed/settings.json +24 -1
- package/ARCHITECTURE.md +27 -1
- package/CHANGELOG.md +21 -0
- package/CLAUDE.md +1 -1
- package/GUIDE.md +2 -5
- package/README.md +45 -3
- package/REQUIREMENTS.md +3 -3
- package/eslint.config.js +2 -1
- package/index.dev.js +14 -0
- package/index.js +1 -1
- package/index.ts +1 -1
- package/package.json +5 -4
- package/skills/cause-effect/SKILL.md +69 -0
- package/skills/cause-effect/agents/openai.yaml +4 -0
- package/skills/cause-effect/references/api-facts.md +179 -0
- package/skills/cause-effect/references/error-classes.md +153 -0
- package/skills/cause-effect/references/non-obvious-behaviors.md +195 -0
- package/skills/cause-effect/references/signal-types.md +292 -0
- package/skills/cause-effect/workflows/answer-question.md +54 -0
- package/skills/cause-effect/workflows/debug.md +71 -0
- package/skills/cause-effect/workflows/use-api.md +63 -0
- package/skills/cause-effect-dev/SKILL.md +61 -100
- package/skills/cause-effect-dev/references/api-facts.md +96 -0
- package/skills/cause-effect-dev/references/error-classes.md +97 -0
- package/skills/cause-effect-dev/references/internal-types.md +54 -0
- package/skills/cause-effect-dev/references/non-obvious-behaviors.md +162 -0
- package/skills/cause-effect-dev/references/source-map.md +45 -0
- package/skills/cause-effect-dev/workflows/answer-question.md +55 -0
- package/skills/cause-effect-dev/workflows/fix-bug.md +63 -0
- package/skills/cause-effect-dev/workflows/implement-feature.md +46 -0
- package/skills/cause-effect-dev/workflows/write-tests.md +64 -0
- package/skills/changelog-keeper/SKILL.md +47 -37
- package/skills/tech-writer/SKILL.md +94 -0
- package/skills/tech-writer/references/document-map.md +199 -0
- package/skills/tech-writer/references/tone-guide.md +189 -0
- package/skills/tech-writer/workflows/consistency-review.md +98 -0
- package/skills/tech-writer/workflows/update-after-change.md +65 -0
- package/skills/tech-writer/workflows/update-agent-docs.md +77 -0
- package/skills/tech-writer/workflows/update-architecture.md +61 -0
- package/skills/tech-writer/workflows/update-jsdoc.md +72 -0
- package/skills/tech-writer/workflows/update-public-api.md +59 -0
- package/skills/tech-writer/workflows/update-requirements.md +80 -0
- package/src/graph.ts +2 -0
- package/src/nodes/collection.ts +38 -0
- package/src/nodes/effect.ts +13 -1
- package/src/nodes/list.ts +41 -2
- package/src/nodes/memo.ts +0 -1
- package/src/nodes/sensor.ts +10 -4
- package/src/nodes/store.ts +11 -0
- package/src/signal.ts +6 -0
- package/test/list.test.ts +121 -0
- package/tsconfig.json +9 -0
- package/types/index.d.ts +1 -1
- package/types/src/graph.d.ts +2 -0
- package/types/src/nodes/collection.d.ts +38 -0
- package/types/src/nodes/effect.d.ts +13 -1
- package/types/src/nodes/list.d.ts +30 -2
- package/types/src/nodes/memo.d.ts +0 -1
- package/types/src/nodes/sensor.d.ts +10 -4
- package/types/src/nodes/store.d.ts +11 -0
- package/types/src/signal.d.ts +6 -0
|
@@ -10,7 +10,7 @@ Cause & Effect is a reactive state management library for JavaScript/TypeScript
|
|
|
10
10
|
- **Nodes**: StateNode (source + equality), MemoNode (source + sink), TaskNode (source + sink + async), EffectNode (sink + owner)
|
|
11
11
|
- **Edges**: Doubly-linked list connecting sources to sinks
|
|
12
12
|
- **Operations**: `link()` creates edges, `propagate()` flags sinks dirty, `flush()` runs queued effects, `batch()` defers flushing
|
|
13
|
-
- **Flags**: FLAG_CLEAN, FLAG_CHECK, FLAG_DIRTY, FLAG_RUNNING for efficient dirty checking
|
|
13
|
+
- **Flags**: FLAG_CLEAN, FLAG_CHECK, FLAG_DIRTY, FLAG_RUNNING, FLAG_RELINK for efficient dirty checking
|
|
14
14
|
|
|
15
15
|
### Signal Types (all in `src/nodes/`)
|
|
16
16
|
- **State** (`createState`): Mutable signals for values (`get`, `set`, `update`)
|
|
@@ -36,6 +36,7 @@ Cause & Effect is a reactive state management library for JavaScript/TypeScript
|
|
|
36
36
|
- `src/nodes/list.ts` - createList, isList, List type
|
|
37
37
|
- `src/nodes/collection.ts` - createCollection, isCollection, Collection type, deriveCollection (internal)
|
|
38
38
|
- `src/nodes/slot.ts` - createSlot, isSlot, Slot type
|
|
39
|
+
- `src/signal.ts` - Polymorphic factories (createSignal, createMutableSignal, createComputed) and type predicates (isSignal, isMutableSignal, isComputed)
|
|
39
40
|
- `src/util.ts` - Utility functions and type checks
|
|
40
41
|
- `index.ts` - Entry point / main export file
|
|
41
42
|
|
|
@@ -119,6 +120,9 @@ const users = createList(
|
|
|
119
120
|
[{ id: 'alice', name: 'Alice' }],
|
|
120
121
|
{ keyConfig: u => u.id }
|
|
121
122
|
)
|
|
123
|
+
const key = users.add({ id: 'bob', name: 'Bob' })
|
|
124
|
+
users.replace(key, { id: 'bob', name: 'Bobby' }) // update item, propagates to all subscribers
|
|
125
|
+
users.remove(key)
|
|
122
126
|
|
|
123
127
|
// Memo for synchronous derived values
|
|
124
128
|
const doubled = createMemo(() => count.get() * 2)
|
package/.zed/settings.json
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"project_name": "Cause & Effect",
|
|
3
|
+
"languages": {
|
|
4
|
+
"TypeScript": {
|
|
5
|
+
"language_servers": ["!eslint", "..."],
|
|
6
|
+
"code_actions_on_format": {
|
|
7
|
+
"source.fixAll.biome": true,
|
|
8
|
+
"source.organizeImports.biome": true,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
"JavaScript": {
|
|
12
|
+
"language_servers": ["!eslint", "..."],
|
|
13
|
+
"code_actions_on_format": {
|
|
14
|
+
"source.fixAll.biome": true,
|
|
15
|
+
"source.organizeImports.biome": true,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
"TSX": {
|
|
19
|
+
"language_servers": ["!eslint", "..."],
|
|
20
|
+
"code_actions_on_format": {
|
|
21
|
+
"source.fixAll.biome": true,
|
|
22
|
+
"source.organizeImports.biome": true,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
3
26
|
}
|
package/ARCHITECTURE.md
CHANGED
|
@@ -178,7 +178,7 @@ Creates an ownership scope without an effect. The scope becomes `activeOwner` du
|
|
|
178
178
|
|
|
179
179
|
### State (`src/nodes/state.ts`)
|
|
180
180
|
|
|
181
|
-
**Graph node**: `
|
|
181
|
+
**Graph node**: `StateNode<T>` (source only)
|
|
182
182
|
|
|
183
183
|
A mutable value container. The simplest signal type — `get()` links and returns the value, `set()` validates, calls `setState()`, which propagates changes to dependents.
|
|
184
184
|
|
|
@@ -253,6 +253,8 @@ A reactive object where each property is its own signal. Properties are automati
|
|
|
253
253
|
|
|
254
254
|
**Two-path access with `FLAG_RELINK`**: On first `get()`, `refresh()` executes `buildValue()` with `activeSink = storeNode`, establishing edges from each child signal to the store. Subsequent reads use a fast path: `untrack(buildValue)` rebuilds the value without re-establishing edges. Structural mutations (`add`/`remove`/`set` with additions or removals) set `FLAG_DIRTY | FLAG_RELINK` on the node. The next `get()` detects `FLAG_RELINK` and forces a tracked `refresh()` after rebuilding the value, so `recomputeMemo()` links new child signals and trims removed ones without orphaning edges.
|
|
255
255
|
|
|
256
|
+
**Same two-path propagation asymmetry as List**: `store.name.set(v)` (via proxy, equivalent to `byKey('name').set(v)`) propagates only if `childSignal → storeNode` edges exist — which requires `store.get()` to have been called at least once. Effects that subscribe only via `store.keys()` or the iterator, without ever calling `store.get()`, will not be notified of child signal mutations. In practice this is uncommon for Store because typical consumers either call `store.get()` (whole object) or `store.name.get()` (single property) — both of which establish the necessary edges. Effects that use `store.set({...})` rather than `store.name.set(v)` are always safe: `set()` explicitly propagates through `node.sinks` after `applyChanges()`.
|
|
257
|
+
|
|
256
258
|
**Diff-based updates**: `store.set(newObj)` diffs the new object against the current state, applying only the granular changes to child signals. This preserves identity of unchanged child signals and their downstream edges.
|
|
257
259
|
|
|
258
260
|
**Watched lifecycle**: An optional `watched` callback in options provides lazy resource allocation, following the same pattern as Sensor — activated on first sink, cleaned up when the last sink detaches.
|
|
@@ -269,6 +271,30 @@ A reactive array with stable keys and per-item reactivity. Each item becomes a `
|
|
|
269
271
|
|
|
270
272
|
**Diff-based updates**: `list.set(newArray)` uses `diffArrays()` to compute granular additions, changes, and removals. Changed items update their existing `State` signals; structural changes (add/remove) set `FLAG_DIRTY | FLAG_RELINK`.
|
|
271
273
|
|
|
274
|
+
**Two propagation paths — and the asymmetry between them**
|
|
275
|
+
|
|
276
|
+
The List node has two distinct propagation paths. Understanding when each applies is essential for correct usage and for implementing `replace()`:
|
|
277
|
+
|
|
278
|
+
| Path | Trigger | How it works | When it fires |
|
|
279
|
+
|------|---------|-------------|---------------|
|
|
280
|
+
| Structural | `add()`, `remove()`, `sort()`, `splice()`, `set()` | Calls `propagate(e.sink)` directly on `node.sinks` | Always, as soon as any consumer has subscribed via `keys()`, `length`, `get()`, or iterator |
|
|
281
|
+
| Value | `byKey(k).set(v)` on a raw item signal | `setState(itemNode)` → propagates to `itemNode.sinks` → listNode (if linked) → downstream | Only if `recomputeMemo(listNode)` has previously run with that item, establishing the `itemSignal → listNode` edge |
|
|
282
|
+
|
|
283
|
+
The value path has a prerequisite: `list.get()` must have been called at least once after the item was present, so that `buildValue()` executed with `activeSink = listNode` and called `link(itemSignal, listNode)` for each item. This happens automatically for any consumer that reads `list.get()` directly. It does **not** happen for consumers that subscribe only via structural methods (`list.keys()`, `list.length`, the `[Symbol.iterator]`): those call `subscribe()` which links `listNode → effectNode`, but `buildValue()` is never run with `activeSink = listNode`, so no `itemSignal → listNode` edges are established.
|
|
284
|
+
|
|
285
|
+
Consequence: code that calls `byKey(k).set(v)` to update an item will silently fail to notify effects that subscribe via structural accessors. The item signal propagates to nothing because `listNode` is absent from its sinks.
|
|
286
|
+
|
|
287
|
+
**`list.replace(key, value)` — the correct API for item mutation with guaranteed propagation**
|
|
288
|
+
|
|
289
|
+
To close this gap, `List` should expose a `replace(key, value)` method that combines both paths:
|
|
290
|
+
|
|
291
|
+
1. Updates the item signal: `signals.get(key)?.set(value)` — this propagates through item signal edges to any consumers that subscribed directly (e.g. effects reading `byKey(k).get()`).
|
|
292
|
+
2. Explicitly marks the list dirty and propagates through `node.sinks`: `node.flags |= FLAG_DIRTY; for (let e = node.sinks; e; e = e.nextSink) propagate(e.sink)` — this notifies structural consumers regardless of edge state.
|
|
293
|
+
|
|
294
|
+
This mirrors what `list.set(newArray)` already does internally: `applyChanges()` calls `signal.set(val)` on changed items, then `list.set()` calls `propagate(e.sink)` on `node.sinks` unconditionally. `replace(key, value)` is a single-item version of the same invariant.
|
|
295
|
+
|
|
296
|
+
`byKey(key).set(value)` remains valid for effects that subscribe directly to the item signal. It is **not** a safe pattern for effects that subscribe to the list via structural accessors. This asymmetry should be documented in the public API.
|
|
297
|
+
|
|
272
298
|
### Collection (`src/nodes/collection.ts`)
|
|
273
299
|
|
|
274
300
|
Collection implements two creation patterns that share the same `Collection<T>` interface:
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.2
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`List.replace(key, value)` — guaranteed item mutation**: Updates the value of an existing item in place, propagating to all subscribers regardless of how they subscribed. `byKey(key).set(value)` only propagates through `itemSignal → listNode` edges, which are established lazily when `list.get()` is called; effects that subscribed via `list.keys()`, `list.length`, or the iterator never trigger that path and receive no notification. `replace()` closes this gap by also walking `node.sinks` directly — the same structural propagation path used by `add()`, `remove()`, and `sort()`. Signal identity is preserved: the `State<T>` returned by `byKey(key)` is the same object before and after. No-op if the key does not exist or the value is reference-equal to the current value.
|
|
8
|
+
|
|
9
|
+
## 1.0.1
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`cause-effect` skill for consumer projects**: New Claude Code skill with self-contained API knowledge in `references/` — no library source access required. Covers three workflows: `use-api`, `debug`, and `answer-question`.
|
|
14
|
+
- **`README.md` Utilities section**: Documents the previously undocumented `createSignal`, `createMutableSignal`, `createComputed` factories and `isSignal`, `isMutableSignal`, `isComputed` predicates exported from `index.ts`.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **`cause-effect-dev` skill restructured**: Refactored to progressive disclosure pattern with separate `workflows/` and `references/` modules. Scoped explicitly to library development; external references to `REQUIREMENTS.md`, `ARCHITECTURE.md`, and `src/` are now clearly library-repo-only.
|
|
19
|
+
- **Documentation alignment**: Corrected wrong graph node type for `State` in `ARCHITECTURE.md`; added missing `FLAG_RELINK` and `src/signal.ts` to `copilot-instructions.md`; updated `REQUIREMENTS.md` stability section to reflect 1.0 release; completed and corrected JSDoc across `Sensor`, `Memo`, `Store`, `List`, `Collection`, and utility types. No runtime behaviour changed.
|
|
20
|
+
- **TypeScript 6 compatibility**: Added `erasableSyntaxOnly` to `tsconfig.json` (requires TS ≥5.8); replaced `@types/bun` with `bun-types` directly and added `"types": ["bun-types"]` to `tsconfig.json` to fix module resolution under TypeScript 6.
|
|
21
|
+
- **Package management cleanup**: Added `typescript` to `devDependencies` (was only in `peerDependencies`, causing stale version installs); updated `peerDependencies` range to `>=5.8.0`; removed `package-lock.json` and gitignored npm/yarn/pnpm lockfiles — Bun is required for development.
|
|
22
|
+
- **Zed editor configuration**: Disabled ESLint language server for JS/TS/TSX in `.zed/settings.json` — project uses Biome for linting.
|
|
23
|
+
|
|
3
24
|
## 1.0.0
|
|
4
25
|
|
|
5
26
|
### Changed
|
package/CLAUDE.md
CHANGED
|
@@ -30,7 +30,7 @@ Scope — owner only (createScope)
|
|
|
30
30
|
|
|
31
31
|
**`T extends {}` excludes `null` and `undefined` at the type level.** Every signal generic uses this constraint. Signals cannot hold nullish values — use a wrapper type or a union with a sentinel if you need to represent absence.
|
|
32
32
|
|
|
33
|
-
**`byKey()`, `at()`, `keyAt()`, and `indexOfKey()` do NOT create graph edges.** They are direct lookups. An effect that only calls `collection.byKey('x')?.get()` will react to value changes of key `'x'` but will *not* re-run if that key is added or removed. To track structural changes, read `get()`, `keys()`, or `length`.
|
|
33
|
+
**`byKey()`, `at()`, `keyAt()`, and `indexOfKey()` do NOT create graph edges.** They are direct lookups. An effect that only calls `collection.byKey('x')?.get()` will react to value changes of key `'x'` but will *not* re-run if that key is added or removed. To track structural changes, read `get()`, `keys()`, or `length`. When updating an existing item's value, use `list.replace(key, value)` rather than `byKey(key).set(value)`. `replace()` guarantees propagation to all subscribers regardless of graph edge state. `byKey(key).set(value)` is only safe for effects that directly call `byKey(key).get()` inside their body.
|
|
34
34
|
|
|
35
35
|
**Conditional reads delay `watched` activation.** Dependencies are tracked only for `.get()` calls that actually execute during a given effect run. If a signal read is inside a branch that doesn't execute (e.g. the `ok` arm of `match()` while a Task is still pending), no edge is created and `watched` does not fire. Read signals eagerly before conditional logic when lifecycle activation matters:
|
|
36
36
|
|
package/GUIDE.md
CHANGED
|
@@ -224,14 +224,11 @@ const todos = createList([
|
|
|
224
224
|
{ id: 't2', text: 'Build app', done: false }
|
|
225
225
|
], { keyConfig: todo => todo.id })
|
|
226
226
|
|
|
227
|
-
// Get a stable reference to a specific item
|
|
228
|
-
const first = todos.byKey('t1')
|
|
229
|
-
|
|
230
227
|
todos.sort((a, b) => a.text.localeCompare(b.text))
|
|
231
|
-
//
|
|
228
|
+
// 'Learn signals' is still at key 't1', regardless of position
|
|
232
229
|
|
|
233
230
|
// Update a single item without replacing the array
|
|
234
|
-
|
|
231
|
+
todos.replace('t1', { id: 't1', text: 'Learn signals', done: true })
|
|
235
232
|
```
|
|
236
233
|
|
|
237
234
|
Each item is its own signal. Sorting reorders keys without destroying signals or their downstream dependencies. Adding and removing items is granular — unaffected items and their effects don't re-run.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cause & Effect
|
|
2
2
|
|
|
3
|
-
Version 1.0.
|
|
3
|
+
Version 1.0.2
|
|
4
4
|
|
|
5
5
|
**Cause & Effect** is a reactive state management primitives library for TypeScript. It provides the foundational building blocks for managing complex, dynamic, composite, and asynchronous state — correctly and performantly — in a unified signal graph.
|
|
6
6
|
|
|
@@ -242,7 +242,7 @@ items.splice(1, 1, 'orange')
|
|
|
242
242
|
items.sort()
|
|
243
243
|
```
|
|
244
244
|
|
|
245
|
-
Access items by key using `.byKey()` or by index using `.at()`. `.indexOfKey()` returns the current index of an item in the list, while `.keyAt()` returns the key of an item at a given position.
|
|
245
|
+
Access items by key using `.byKey()` or by index using `.at()`. `.indexOfKey()` returns the current index of an item in the list, while `.keyAt()` returns the key of an item at a given position. To update an existing item, use `.replace(key, value)` — this propagates to all subscribers regardless of how they subscribed to the list.
|
|
246
246
|
|
|
247
247
|
Keys are stable across reordering. Use `keyConfig` in options to control key generation:
|
|
248
248
|
|
|
@@ -260,10 +260,11 @@ const users = createList(
|
|
|
260
260
|
const key = items.add('orange')
|
|
261
261
|
items.sort()
|
|
262
262
|
console.log(items.byKey(key)?.get()) // 'orange'
|
|
263
|
+
items.replace(key, 'ORANGE') // update in place
|
|
263
264
|
console.log(items.indexOfKey(key)) // current index
|
|
264
265
|
```
|
|
265
266
|
|
|
266
|
-
Lists have `.keys()`, `.add()`, and `.remove()` methods like stores. Additionally, they have `.sort()`, `.splice()`, and a reactive `.length` property. But unlike stores, deeply nested properties in items are not converted to individual signals.
|
|
267
|
+
Lists have `.keys()`, `.add()`, and `.remove()` methods like stores. Additionally, they have `.replace()`, `.sort()`, `.splice()`, and a reactive `.length` property. But unlike stores, deeply nested properties in items are not converted to individual signals.
|
|
267
268
|
|
|
268
269
|
### Collection
|
|
269
270
|
|
|
@@ -399,6 +400,47 @@ createEffect(() => {
|
|
|
399
400
|
})
|
|
400
401
|
```
|
|
401
402
|
|
|
403
|
+
### Utilities
|
|
404
|
+
|
|
405
|
+
Polymorphic factories and type predicates for generic and library-author code.
|
|
406
|
+
|
|
407
|
+
**`createSignal(value)`** converts any value to its corresponding signal type:
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
import { createSignal } from '@zeix/cause-effect'
|
|
411
|
+
|
|
412
|
+
createSignal(0) // → State<number>
|
|
413
|
+
createSignal([1, 2, 3]) // → List<number>
|
|
414
|
+
createSignal({ x: 0 }) // → Store<{ x: number }>
|
|
415
|
+
createSignal(() => x.get() * 2) // → Memo<number>
|
|
416
|
+
createSignal(async (_, s) =>
|
|
417
|
+
fetch('/api', { signal: s }).then(r => r.json())) // → Task<Response>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
If the value is already a signal, it is returned unchanged.
|
|
421
|
+
|
|
422
|
+
**`createMutableSignal(value)`** is the same, but restricted to mutable signals — returns `State`, `Store`, or `List`. Throws `InvalidSignalValueError` if passed a function or a read-only signal.
|
|
423
|
+
|
|
424
|
+
**`createComputed(callback, options?)`** creates a `Memo` or `Task` by detecting whether the callback is async:
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
import { createComputed } from '@zeix/cause-effect'
|
|
428
|
+
|
|
429
|
+
const doubled = createComputed(() => count.get() * 2)
|
|
430
|
+
const data = createComputed(async (_, signal) =>
|
|
431
|
+
fetch(url.get(), { signal }).then(r => r.json()))
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Type predicates**
|
|
435
|
+
|
|
436
|
+
| Predicate | True for |
|
|
437
|
+
|---|---|
|
|
438
|
+
| `isSignal(value)` | Any signal (all 9 types) |
|
|
439
|
+
| `isMutableSignal(value)` | `State`, `Store`, `List` — signals with `.set()` and `.update()` |
|
|
440
|
+
| `isComputed(value)` | `Memo`, `Task` — derived signals |
|
|
441
|
+
|
|
442
|
+
The `MutableSignal<T>` type is the corresponding TypeScript type for `isMutableSignal` — use it as a parameter type in generic code that accepts any writable signal.
|
|
443
|
+
|
|
402
444
|
## Choosing the Right Signal
|
|
403
445
|
|
|
404
446
|
```
|
package/REQUIREMENTS.md
CHANGED
|
@@ -84,11 +84,11 @@ The following are explicitly out of scope and will not be added to the library:
|
|
|
84
84
|
|
|
85
85
|
## Stability
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
The library is stable at 1.0.0. The API surface — how signals are created and consumed — will not change except under the following conditions:
|
|
88
88
|
|
|
89
|
-
- **Breaking changes**
|
|
89
|
+
- **Breaking changes** only if major new features of the Web Platform shift the optimal way to achieve the goals this library already covers.
|
|
90
90
|
- **New features** are not expected. The signal type set is complete.
|
|
91
|
-
- **Backward compatibility**
|
|
91
|
+
- **Backward compatibility** is maintained from 1.0 onward.
|
|
92
92
|
|
|
93
93
|
## Success Criteria
|
|
94
94
|
|
package/eslint.config.js
CHANGED
|
@@ -4,8 +4,9 @@ import tseslint from 'typescript-eslint'
|
|
|
4
4
|
|
|
5
5
|
/** @type {import('eslint').Linter.Config[]} */
|
|
6
6
|
export default [
|
|
7
|
+
// Global ignores to prevent warnings about these files
|
|
7
8
|
{
|
|
8
|
-
ignores: ['index.js', '**/*.min.js'],
|
|
9
|
+
ignores: ['index.js', 'index.dev.js', 'types/**/*.d.ts', '**/*.min.js'],
|
|
9
10
|
},
|
|
10
11
|
{
|
|
11
12
|
files: ['**/*.{js,mjs,cjs,ts}'],
|
package/index.dev.js
CHANGED
|
@@ -727,6 +727,20 @@ function createList(value, options) {
|
|
|
727
727
|
flush();
|
|
728
728
|
}
|
|
729
729
|
},
|
|
730
|
+
replace(key, value2) {
|
|
731
|
+
const signal = signals.get(key);
|
|
732
|
+
if (!signal)
|
|
733
|
+
return;
|
|
734
|
+
validateSignalValue(`${TYPE_LIST} item for key "${key}"`, value2);
|
|
735
|
+
if (signal.get() === value2)
|
|
736
|
+
return;
|
|
737
|
+
signal.set(value2);
|
|
738
|
+
node.flags |= FLAG_DIRTY;
|
|
739
|
+
for (let e = node.sinks;e; e = e.nextSink)
|
|
740
|
+
propagate(e.sink);
|
|
741
|
+
if (batchDepth === 0)
|
|
742
|
+
flush();
|
|
743
|
+
},
|
|
730
744
|
sort(compareFn) {
|
|
731
745
|
const entries = keys.map((key) => [key, signals.get(key)?.get()]).sort(isFunction(compareFn) ? (a, b) => compareFn(a[1], b[1]) : (a, b) => String(a[1]).localeCompare(String(b[1])));
|
|
732
746
|
const newOrder = entries.map(([key]) => key);
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function g($){return typeof $==="function"}function o($){return g($)&&$.constructor.name==="AsyncFunction"}function X$($){return g($)&&$.constructor.name!=="AsyncFunction"}function Y($,J){return Object.prototype.toString.call($)===`[object ${J}]`}function T($){return Y($,"Object")}function Y$($,J=(z)=>z!=null){return Array.isArray($)&&$.every(J)}function D$($){return typeof $==="string"?`"${$}"`:!!$&&typeof $==="object"?JSON.stringify($):String($)}class Z$ extends Error{constructor($){super(`[${$}] Circular dependency detected`);this.name="CircularDependencyError"}}class A$ extends TypeError{constructor($){super(`[${$}] Signal value cannot be null or undefined`);this.name="NullishSignalValueError"}}class i extends Error{constructor($){super(`[${$}] Signal value is unset`);this.name="UnsetSignalValueError"}}class j$ extends TypeError{constructor($,J){super(`[${$}] Signal value ${D$(J)} is invalid`);this.name="InvalidSignalValueError"}}class b$ extends TypeError{constructor($,J){super(`[${$}] Callback ${D$(J)} is invalid`);this.name="InvalidCallbackError"}}class P$ extends Error{constructor($){super(`[${$}] Signal is read-only`);this.name="ReadonlySignalError"}}class G$ extends Error{constructor($){super(`[${$}] Active owner is required`);this.name="RequiredOwnerError"}}class e extends Error{constructor($,J,z){super(`[${$}] Could not add key "${J}"${z?` with value ${JSON.stringify(z)}`:""} because it already exists`);this.name="DuplicateKeyError"}}function O($,J,z){if(J==null)throw new A$($);if(z&&!z(J))throw new j$($,J)}function W$($,J){if(J==null)throw new i($)}function E($,J,z=g){if(!z(J))throw new b$($,J)}var c="State",u="Memo",d="Task",t="Sensor",S="List",s="Collection",l="Store",r="Slot",p=0,$$=1,G=2,U$=4,b=8,N=null,_=null,C$=[],x=0,_$=!1,k=($,J)=>$===J,L$=($,J)=>!1;function g$($,J){let z=J.sourcesTail;if(z){let X=J.sources;while(X){if(X===$)return!0;if(X===z)break;X=X.nextSource}}return!1}function R($,J){let z=J.sourcesTail;if(z?.source===$)return;let X=null,W=J.flags&U$;if(W){if(X=z?z.nextSource:J.sources,X?.source===$){J.sourcesTail=X;return}}let B=$.sinksTail;if(B?.sink===J&&(!W||g$(B,J)))return;let D={source:$,sink:J,nextSource:X,prevSink:B,nextSink:null};if(J.sourcesTail=$.sinksTail=D,z)z.nextSource=D;else J.sources=D;if(B)B.nextSink=D;else $.sinks=D}function k$($){let{source:J,nextSource:z,nextSink:X,prevSink:W}=$;if(X)X.prevSink=W;else J.sinksTail=W;if(W)W.nextSink=X;else J.sinks=X;if(!J.sinks){if(J.stop)J.stop(),J.stop=void 0;if("sources"in J&&J.sources){let B=J;B.sourcesTail=null,H$(B)}}return z}function H$($){let J=$.sourcesTail,z=J?J.nextSource:$.sources;while(z)z=k$(z);if(J)J.nextSource=null;else $.sources=null}function F($,J=G){let z=$.flags;if("sinks"in $){if((z&(G|$$))>=J)return;if($.flags=z|J,"controller"in $&&$.controller)$.controller.abort(),$.controller=void 0;for(let X=$.sinks;X;X=X.nextSink)F(X.sink,$$)}else{if((z&(G|$$))>=J)return;let X=z&(G|$$);if($.flags=J,!X)C$.push($)}}function N$($,J){if($.equals($.value,J))return;$.value=J;for(let z=$.sinks;z;z=z.nextSink)F(z.sink);if(x===0)I()}function J$($,J){if(!$.cleanup)$.cleanup=J;else if(Array.isArray($.cleanup))$.cleanup.push(J);else $.cleanup=[$.cleanup,J]}function O$($){if(!$.cleanup)return;if(Array.isArray($.cleanup))for(let J=0;J<$.cleanup.length;J++)$.cleanup[J]();else $.cleanup();$.cleanup=null}function v$($){let J=N;N=$,$.sourcesTail=null,$.flags=U$;let z=!1;try{let X=$.fn($.value);if($.error||!$.equals(X,$.value))$.value=X,$.error=void 0,z=!0}catch(X){z=!0,$.error=X instanceof Error?X:Error(String(X))}finally{N=J,H$($)}if(z){for(let X=$.sinks;X;X=X.nextSink)if(X.sink.flags&$$)X.sink.flags|=G}$.flags=p}function c$($){$.controller?.abort();let J=new AbortController;$.controller=J,$.error=void 0;let z=N;N=$,$.sourcesTail=null,$.flags=U$;let X;try{X=$.fn($.value,J.signal)}catch(W){$.controller=void 0,$.error=W instanceof Error?W:Error(String(W));return}finally{N=z,H$($)}X.then((W)=>{if(J.signal.aborted)return;if($.controller=void 0,$.error||!$.equals(W,$.value)){$.value=W,$.error=void 0;for(let B=$.sinks;B;B=B.nextSink)F(B.sink);if(x===0)I()}},(W)=>{if(J.signal.aborted)return;$.controller=void 0;let B=W instanceof Error?W:Error(String(W));if(!$.error||B.name!==$.error.name||B.message!==$.error.message){$.error=B;for(let D=$.sinks;D;D=D.nextSink)F(D.sink);if(x===0)I()}}),$.flags=p}function T$($){O$($);let J=N,z=_;N=_=$,$.sourcesTail=null,$.flags=U$;try{let X=$.fn();if(typeof X==="function")J$($,X)}finally{N=J,_=z,H$($)}$.flags=p}function f($){if($.flags&$$)for(let J=$.sources;J;J=J.nextSource){if("fn"in J.source)f(J.source);if($.flags&G)break}if($.flags&U$)throw new Z$("controller"in $?d:("value"in $)?u:"Effect");if($.flags&G)if("controller"in $)c$($);else if("value"in $)v$($);else T$($);else $.flags=p}function I(){if(_$)return;_$=!0;try{for(let $=0;$<C$.length;$++){let J=C$[$];if(J.flags&(G|$$))f(J)}C$.length=0}finally{_$=!1}}function z$($){x++;try{$()}finally{if(x--,x===0)I()}}function v($){let J=N;N=null;try{return $()}finally{N=J}}function u$($){let J=_,z={cleanup:null};_=z;try{let X=$();if(typeof X==="function")J$(z,X);let W=()=>O$(z);if(J)J$(J,W);return W}finally{_=J}}function d$($){let J=_;_=null;try{return $()}finally{_=J}}function y($,J){O(c,$,J?.guard);let z={value:$,sinks:null,sinksTail:null,equals:J?.equals??k,guard:J?.guard};return{[Symbol.toStringTag]:c,get(){if(N)R(z,N);return z.value},set(X){O(c,X,z.guard),N$(z,X)},update(X){E(c,X);let W=X(z.value);O(c,W,z.guard),N$(z,W)}}}function m$($){return Y($,c)}function n($,J,z){if(Object.is($,J))return!0;if(typeof $!==typeof J)return!1;if($==null||typeof $!=="object"||J==null||typeof J!=="object")return!1;if(!z)z=new WeakSet;if(z.has($)||z.has(J))throw new Z$("isEqual");z.add($),z.add(J);try{let X=Array.isArray($);if(X!==Array.isArray(J))return!1;if(X){let W=$,B=J;if(W.length!==B.length)return!1;for(let D=0;D<W.length;D++)if(!n(W[D],B[D],z))return!1;return!0}if(T($)&&T(J)){let W=Object.keys($),B=Object.keys(J);if(W.length!==B.length)return!1;for(let D of W){if(!(D in J))return!1;if(!n($[D],J[D],z))return!1}return!0}return!1}finally{z.delete($),z.delete(J)}}function K$($,J){if($.length!==J.length)return!1;for(let z=0;z<$.length;z++)if($[z]!==J[z])return!1;return!0}function E$($){let J=0,z=typeof $==="function";return[typeof $==="string"?()=>`${$}${J++}`:z?(X)=>$(X)||String(J++):()=>String(J++),z]}function t$($,J,z,X,W){let B=new WeakSet,D={},M={},C={},U=[],Q=!1,j=new Map;for(let q=0;q<$.length;q++){let Z=z[q],H=$[q];if(Z&&H!==void 0)j.set(Z,H)}let P=new Set;for(let q=0;q<J.length;q++){let Z=J[q];if(Z===void 0)continue;let H=W?X(Z):z[q]??X(Z);if(P.has(H))throw new e(S,H,Z);if(U.push(H),P.add(H),!j.has(H))D[H]=Z,Q=!0;else if(!n(j.get(H),Z,B))M[H]=Z,Q=!0}for(let[q]of j)if(!P.has(q))C[q]=null,Q=!0;if(!Q&&!K$(z,U))Q=!0;return{add:D,change:M,remove:C,newKeys:U,changed:Q}}function Q$($,J){O(S,$,Array.isArray);let z=new Map,X=[],[W,B]=E$(J?.keyConfig),D=()=>X.map((Z)=>z.get(Z)?.get()).filter((Z)=>Z!==void 0),M={fn:D,value:$,flags:G,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:n,error:void 0},C=(Z)=>{let H={};for(let m=0;m<Z.length;m++){let V=Z[m];if(V===void 0)continue;let K=X[m];if(!K)K=W(V),X[m]=K;H[K]=V}return H},U=(Z)=>{let H=!1;for(let m in Z.add){let V=Z.add[m];O(`${S} item for key "${m}"`,V),z.set(m,y(V)),H=!0}if(Object.keys(Z.change).length)z$(()=>{for(let m in Z.change){let V=Z.change[m];O(`${S} item for key "${m}"`,V);let K=z.get(m);if(K)K.set(V)}});for(let m in Z.remove){z.delete(m);let V=X.indexOf(m);if(V!==-1)X.splice(V,1);H=!0}if(H)M.flags|=b;return Z.changed},Q=J?.watched,j=Q?()=>{if(N){if(!M.sinks)M.stop=Q();R(M,N)}}:()=>{if(N)R(M,N)},P=C($);for(let Z in P){let H=P[Z];O(`${S} item for key "${Z}"`,H),z.set(Z,y(H))}M.value=$,M.flags=0;let q={[Symbol.toStringTag]:S,[Symbol.isConcatSpreadable]:!0,*[Symbol.iterator](){for(let Z of X){let H=z.get(Z);if(H)yield H}},get length(){return j(),X.length},get(){if(j(),M.sources){if(M.flags){let Z=M.flags&b;if(M.value=v(D),Z){if(M.flags=G,f(M),M.error)throw M.error}else M.flags=p}}else if(f(M),M.error)throw M.error;return M.value},set(Z){let H=M.flags&G?D():M.value,m=t$(H,Z,X,W,B);if(m.changed){X=m.newKeys,U(m),M.flags|=G;for(let V=M.sinks;V;V=V.nextSink)F(V.sink);if(x===0)I()}},update(Z){q.set(Z(q.get()))},at(Z){let H=X[Z];return H!==void 0?z.get(H):void 0},keys(){return j(),X.values()},byKey(Z){return z.get(Z)},keyAt(Z){return X[Z]},indexOfKey(Z){return X.indexOf(Z)},add(Z){let H=W(Z);if(z.has(H))throw new e(S,H,Z);if(!X.includes(H))X.push(H);O(`${S} item for key "${H}"`,Z),z.set(H,y(Z)),M.flags|=G|b;for(let m=M.sinks;m;m=m.nextSink)F(m.sink);if(x===0)I();return H},remove(Z){let H=typeof Z==="number"?X[Z]:Z;if(H===void 0)return;if(z.delete(H)){let V=typeof Z==="number"?Z:X.indexOf(H);if(V>=0)X.splice(V,1);M.flags|=G|b;for(let K=M.sinks;K;K=K.nextSink)F(K.sink);if(x===0)I()}},sort(Z){let m=X.map((V)=>[V,z.get(V)?.get()]).sort(g(Z)?(V,K)=>Z(V[1],K[1]):(V,K)=>String(V[1]).localeCompare(String(K[1]))).map(([V])=>V);if(!K$(X,m)){X=m,M.flags|=G;for(let V=M.sinks;V;V=V.nextSink)F(V.sink);if(x===0)I()}},splice(Z,H,...m){let V=X.length,K=Z<0?Math.max(0,V+Z):Math.min(Z,V),w=Math.max(0,Math.min(H??Math.max(0,V-Math.max(0,K)),V-K)),A={},L={};for(let h=0;h<w;h++){let a=K+h,w$=X[a];if(w$){let y$=z.get(w$);if(y$)L[w$]=y$.get()}}let f$=X.slice(0,K);for(let h of m){let a=W(h);if(z.has(a)&&!(a in L))throw new e(S,a,h);f$.push(a),A[a]=h}f$.push(...X.slice(K+w));let h$=!!(Object.keys(A).length||Object.keys(L).length);if(h$){U({add:A,change:{},remove:L,changed:h$}),X=f$,M.flags|=G;for(let h=M.sinks;h;h=h.nextSink)F(h.sink);if(x===0)I()}return Object.values(L)},deriveCollection(Z){return x$(q,Z)}};return q}function R$($){return Y($,S)}function B$($,J){if(E(u,$,X$),J?.value!==void 0)O(u,J.value,J?.guard);let z={fn:$,value:J?.value,flags:G,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:J?.equals??k,error:void 0,stop:void 0},X=J?.watched,W=X?()=>{if(N){if(!z.sinks)z.stop=X(()=>{if(F(z),x===0)I()});R(z,N)}}:()=>{if(N)R(z,N)};return{[Symbol.toStringTag]:u,get(){if(W(),f(z),z.error)throw z.error;return W$(u,z.value),z.value}}}function S$($){return Y($,u)}function q$($,J){if(E(d,$,o),J?.value!==void 0)O(d,J.value,J?.guard);let z={fn:$,value:J?.value,sources:null,sourcesTail:null,sinks:null,sinksTail:null,flags:G,equals:J?.equals??k,controller:void 0,error:void 0,stop:void 0},X=J?.watched,W=X?()=>{if(N){if(!z.sinks)z.stop=X(()=>{if(F(z),x===0)I()});R(z,N)}}:()=>{if(N)R(z,N)};return{[Symbol.toStringTag]:d,get(){if(W(),f(z),z.error)throw z.error;return W$(d,z.value),z.value},isPending(){return!!z.controller},abort(){z.controller?.abort(),z.controller=void 0}}}function p$($){return Y($,d)}function x$($,J){E(s,J);let z=o(J),X=new Map,W=[],B=(q)=>{let Z=z?q$(async(H,m)=>{let V=$.byKey(q)?.get();if(V==null)return H;return J(V,m)}):B$(()=>{let H=$.byKey(q)?.get();if(H==null)return;return J(H)});X.set(q,Z)};function D(q){if(!K$(W,q)){let Z=new Set(W),H=new Set(q);for(let m of W)if(!H.has(m))X.delete(m);for(let m of q)if(!Z.has(m))B(m);W=q,U.flags|=b}}function M(){D(Array.from($.keys()));let q=[];for(let Z of W)try{let H=X.get(Z)?.get();if(H!=null)q.push(H)}catch(H){if(!(H instanceof i))throw H}return q}let U={fn:M,value:[],flags:G,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:(q,Z)=>{if(q.length!==Z.length)return!1;for(let H=0;H<q.length;H++)if(q[H]!==Z[H])return!1;return!0},error:void 0};function Q(){if(U.sources){if(U.flags)if(U.value=v(M),U.flags&b){if(U.flags=G,f(U),U.error)throw U.error}else U.flags=p}else if(U.sinks){if(f(U),U.error)throw U.error}else U.value=v(M)}let j=Array.from(v(()=>$.keys()));for(let q of j)B(q);W=j;let P={[Symbol.toStringTag]:s,[Symbol.isConcatSpreadable]:!0,*[Symbol.iterator](){for(let q of W){let Z=X.get(q);if(Z)yield Z}},get length(){if(N)R(U,N);return Q(),W.length},keys(){if(N)R(U,N);return Q(),W.values()},get(){if(N)R(U,N);return Q(),U.value},at(q){let Z=W[q];return Z!==void 0?X.get(Z):void 0},byKey(q){return X.get(q)},keyAt(q){return W[q]},indexOfKey(q){return W.indexOf(q)},deriveCollection(q){return x$(P,q)}};return P}function s$($,J){let z=J?.value??[];if(z.length)O(s,z,Array.isArray);E(s,$,X$);let X=new Map,W=[],B=new Map,[D,M]=E$(J?.keyConfig),C=(Z)=>B.get(Z)??(M?D(Z):void 0),U=J?.createItem??y;function Q(){let Z=[];for(let H of W)try{let m=X.get(H)?.get();if(m!=null)Z.push(m)}catch(m){if(!(m instanceof i))throw m}return Z}let j={fn:Q,value:z,flags:G,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:L$,error:void 0};for(let Z of z){let H=D(Z);X.set(H,U(Z)),B.set(Z,H),W.push(H)}j.value=z,j.flags=G;function P(){if(N){if(!j.sinks)j.stop=$((Z)=>{let{add:H,change:m,remove:V}=Z;if(!H?.length&&!m?.length&&!V?.length)return;let K=!1;z$(()=>{if(H)for(let w of H){let A=D(w);if(X.set(A,U(w)),B.set(w,A),!W.includes(A))W.push(A);K=!0}if(m)for(let w of m){let A=C(w);if(!A)continue;let L=X.get(A);if(L&&m$(L))B.delete(L.get()),L.set(w),B.set(w,A)}if(V)for(let w of V){let A=C(w);if(!A)continue;B.delete(w),X.delete(A);let L=W.indexOf(A);if(L!==-1)W.splice(L,1);K=!0}j.flags=G|(K?b:0);for(let w=j.sinks;w;w=w.nextSink)F(w.sink)})});R(j,N)}}let q={[Symbol.toStringTag]:s,[Symbol.isConcatSpreadable]:!0,*[Symbol.iterator](){for(let Z of W){let H=X.get(Z);if(H)yield H}},get length(){return P(),W.length},keys(){return P(),W.values()},get(){if(P(),j.sources){if(j.flags){let Z=j.flags&b;if(j.value=v(Q),Z){if(j.flags=G,f(j),j.error)throw j.error}else j.flags=p}}else if(f(j),j.error)throw j.error;return j.value},at(Z){let H=W[Z];return H!==void 0?X.get(H):void 0},byKey(Z){return X.get(Z)},keyAt(Z){return W[Z]},indexOfKey(Z){return W.indexOf(Z)},deriveCollection(Z){return x$(q,Z)}};return q}function l$($){return Y($,s)}function r$($){E("Effect",$);let J={fn:$,flags:G,sources:null,sourcesTail:null,cleanup:null},z=()=>{O$(J),J.fn=void 0,J.flags=p,J.sourcesTail=null,H$(J)};if(_)J$(_,z);return T$(J),z}function o$($,J){if(!_)throw new G$("match");let{ok:z,err:X=console.error,nil:W}=J,B,D=!1,M=Array($.length);for(let U=0;U<$.length;U++)try{M[U]=$[U].get()}catch(Q){if(Q instanceof i){D=!0;continue}if(!B)B=[];B.push(Q instanceof Error?Q:Error(String(Q)))}let C;try{if(D)C=W?.();else if(B)C=X(B);else C=z(M)}catch(U){X([U instanceof Error?U:Error(String(U))])}if(typeof C==="function")return C;if(C instanceof Promise){let U=_,Q=new AbortController;J$(U,()=>Q.abort()),C.then((j)=>{if(!Q.signal.aborted&&typeof j==="function")J$(U,j)}).catch((j)=>{X([j instanceof Error?j:Error(String(j))])})}}function i$($,J){if(E(t,$,X$),J?.value!==void 0)O(t,J.value,J?.guard);let z={value:J?.value,sinks:null,sinksTail:null,equals:J?.equals??k,guard:J?.guard,stop:void 0};return{[Symbol.toStringTag]:t,get(){if(N){if(!z.sinks)z.stop=$((X)=>{O(t,X,z.guard),N$(z,X)});R(z,N)}return W$(t,z.value),z.value}}}function n$($){return Y($,t)}function a$($,J){let z=T($)||Array.isArray($),X=T(J)||Array.isArray(J);if(!z||!X){let j=!Object.is($,J);return{changed:j,add:j&&X?J:{},change:{},remove:j&&z?$:{}}}let W=new WeakSet,B={},D={},M={},C=!1,U=Object.keys($),Q=Object.keys(J);for(let j of Q)if(j in $){if(!n($[j],J[j],W))D[j]=J[j],C=!0}else B[j]=J[j],C=!0;for(let j of U)if(!(j in J))M[j]=void 0,C=!0;return{add:B,change:D,remove:M,changed:C}}function V$($,J){O(l,$,T);let z=new Map,X=(Q,j)=>{if(O(`${l} for key "${Q}"`,j),Array.isArray(j))z.set(Q,Q$(j));else if(T(j))z.set(Q,V$(j));else z.set(Q,y(j))},W=()=>{let Q={};return z.forEach((j,P)=>{Q[P]=j.get()}),Q},B={fn:W,value:$,flags:G,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:n,error:void 0},D=(Q)=>{let j=!1;for(let P in Q.add)X(P,Q.add[P]),j=!0;if(Object.keys(Q.change).length)z$(()=>{for(let P in Q.change){let q=Q.change[P];O(`${l} for key "${P}"`,q);let Z=z.get(P);if(Z)if(T(q)!==F$(Z))X(P,q),j=!0;else Z.set(q)}});for(let P in Q.remove)z.delete(P),j=!0;if(j)B.flags|=b;return Q.changed},M=J?.watched,C=M?()=>{if(N){if(!B.sinks)B.stop=M();R(B,N)}}:()=>{if(N)R(B,N)};for(let Q of Object.keys($))X(Q,$[Q]);let U={[Symbol.toStringTag]:l,[Symbol.isConcatSpreadable]:!1,*[Symbol.iterator](){for(let Q of Array.from(z.keys())){let j=z.get(Q);if(j)yield[Q,j]}},keys(){return C(),z.keys()},byKey(Q){return z.get(Q)},get(){if(C(),B.sources){if(B.flags){let Q=B.flags&b;if(B.value=v(W),Q){if(B.flags=G,f(B),B.error)throw B.error}else B.flags=p}}else if(f(B),B.error)throw B.error;return B.value},set(Q){let j=B.flags&G?W():B.value,P=a$(j,Q);if(D(P)){B.flags|=G;for(let q=B.sinks;q;q=q.nextSink)F(q.sink);if(x===0)I()}},update(Q){U.set(Q(U.get()))},add(Q,j){if(z.has(Q))throw new e(l,Q,j);X(Q,j),B.flags|=G|b;for(let P=B.sinks;P;P=P.nextSink)F(P.sink);if(x===0)I();return Q},remove(Q){if(z.delete(Q)){B.flags|=G|b;for(let P=B.sinks;P;P=P.nextSink)F(P.sink);if(x===0)I()}}};return new Proxy(U,{get(Q,j){if(j in Q)return Reflect.get(Q,j);if(typeof j!=="symbol")return Q.byKey(j)},has(Q,j){if(j in Q)return!0;return Q.byKey(String(j))!==void 0},ownKeys(Q){return Array.from(Q.keys())},getOwnPropertyDescriptor(Q,j){if(j in Q)return Reflect.getOwnPropertyDescriptor(Q,j);if(typeof j==="symbol")return;let P=Q.byKey(String(j));return P?{enumerable:!0,configurable:!0,writable:!0,value:P}:void 0}})}function F$($){return Y($,l)}function e$($,J){return o($)?q$($,J):B$($,J)}function $J($){if(M$($))return $;if($==null)throw new j$("createSignal",$);if(o($))return q$($);if(g($))return B$($);if(Y$($))return Q$($);if(T($))return V$($);return y($)}function JJ($){if(I$($))return $;if($==null||g($)||M$($))throw new j$("createMutableSignal",$);if(Y$($))return Q$($);if(T($))return V$($);return y($)}function zJ($){return S$($)||p$($)}function M$($){let J=[c,u,d,t,r,S,s,l],z=Object.prototype.toString.call($).slice(8,-1);return J.includes(z)}function I$($){return m$($)||F$($)||R$($)}function XJ($,J){O(r,$,M$);let z=$,X=J?.guard,W={fn:()=>z.get(),value:void 0,flags:G,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:J?.equals??k,error:void 0},B=()=>{if(N)R(W,N);if(f(W),W.error)throw W.error;return W.value},D=(C)=>{if(!I$(z))throw new P$(r);O(r,C,X),z.set(C)},M=(C)=>{O(r,C,M$),z=C,W.flags|=G;for(let U=W.sinks;U;U=U.nextSink)F(U.sink);if(x===0)I()};return{[Symbol.toStringTag]:r,configurable:!0,enumerable:!0,get:B,set:D,replace:M,current:()=>z}}function ZJ($){return Y($,r)}export{D$ as valueString,v as untrack,d$ as unown,o$ as match,p$ as isTask,F$ as isStore,m$ as isState,ZJ as isSlot,M$ as isSignal,n$ as isSensor,T as isRecord,Y as isObjectOfType,I$ as isMutableSignal,S$ as isMemo,R$ as isList,g as isFunction,n as isEqual,zJ as isComputed,l$ as isCollection,o as isAsyncFunction,q$ as createTask,V$ as createStore,y as createState,XJ as createSlot,$J as createSignal,i$ as createSensor,u$ as createScope,JJ as createMutableSignal,B$ as createMemo,Q$ as createList,r$ as createEffect,e$ as createComputed,s$ as createCollection,z$ as batch,i as UnsetSignalValueError,L$ as SKIP_EQUALITY,G$ as RequiredOwnerError,P$ as ReadonlySignalError,A$ as NullishSignalValueError,j$ as InvalidSignalValueError,b$ as InvalidCallbackError,Z$ as CircularDependencyError};
|
|
1
|
+
function g($){return typeof $==="function"}function o($){return g($)&&$.constructor.name==="AsyncFunction"}function X$($){return g($)&&$.constructor.name!=="AsyncFunction"}function f($,J){return Object.prototype.toString.call($)===`[object ${J}]`}function E($){return f($,"Object")}function f$($,J=(z)=>z!=null){return Array.isArray($)&&$.every(J)}function D$($){return typeof $==="string"?`"${$}"`:!!$&&typeof $==="object"?JSON.stringify($):String($)}class Z$ extends Error{constructor($){super(`[${$}] Circular dependency detected`);this.name="CircularDependencyError"}}class A$ extends TypeError{constructor($){super(`[${$}] Signal value cannot be null or undefined`);this.name="NullishSignalValueError"}}class i extends Error{constructor($){super(`[${$}] Signal value is unset`);this.name="UnsetSignalValueError"}}class W$ extends TypeError{constructor($,J){super(`[${$}] Signal value ${D$(J)} is invalid`);this.name="InvalidSignalValueError"}}class b$ extends TypeError{constructor($,J){super(`[${$}] Callback ${D$(J)} is invalid`);this.name="InvalidCallbackError"}}class P$ extends Error{constructor($){super(`[${$}] Signal is read-only`);this.name="ReadonlySignalError"}}class G$ extends Error{constructor($){super(`[${$}] Active owner is required`);this.name="RequiredOwnerError"}}class e extends Error{constructor($,J,z){super(`[${$}] Could not add key "${J}"${z?` with value ${JSON.stringify(z)}`:""} because it already exists`);this.name="DuplicateKeyError"}}function K($,J,z){if(J==null)throw new A$($);if(z&&!z(J))throw new W$($,J)}function j$($,J){if(J==null)throw new i($)}function S($,J,z=g){if(!z(J))throw new b$($,J)}var c="State",u="Memo",d="Task",s="Sensor",L="List",t="Collection",l="Store",r="Slot",p=0,$$=1,P=2,U$=4,b=8,m=null,_=null,C$=[],R=0,_$=!1,k=($,J)=>$===J,L$=($,J)=>!1;function g$($,J){let z=J.sourcesTail;if(z){let X=J.sources;while(X){if(X===$)return!0;if(X===z)break;X=X.nextSource}}return!1}function F($,J){let z=J.sourcesTail;if(z?.source===$)return;let X=null,j=J.flags&U$;if(j){if(X=z?z.nextSource:J.sources,X?.source===$){J.sourcesTail=X;return}}let B=$.sinksTail;if(B?.sink===J&&(!j||g$(B,J)))return;let D={source:$,sink:J,nextSource:X,prevSink:B,nextSink:null};if(J.sourcesTail=$.sinksTail=D,z)z.nextSource=D;else J.sources=D;if(B)B.nextSink=D;else $.sinks=D}function k$($){let{source:J,nextSource:z,nextSink:X,prevSink:j}=$;if(X)X.prevSink=j;else J.sinksTail=j;if(j)j.nextSink=X;else J.sinks=X;if(!J.sinks){if(J.stop)J.stop(),J.stop=void 0;if("sources"in J&&J.sources){let B=J;B.sourcesTail=null,H$(B)}}return z}function H$($){let J=$.sourcesTail,z=J?J.nextSource:$.sources;while(z)z=k$(z);if(J)J.nextSource=null;else $.sources=null}function x($,J=P){let z=$.flags;if("sinks"in $){if((z&(P|$$))>=J)return;if($.flags=z|J,"controller"in $&&$.controller)$.controller.abort(),$.controller=void 0;for(let X=$.sinks;X;X=X.nextSink)x(X.sink,$$)}else{if((z&(P|$$))>=J)return;let X=z&(P|$$);if($.flags=J,!X)C$.push($)}}function N$($,J){if($.equals($.value,J))return;$.value=J;for(let z=$.sinks;z;z=z.nextSink)x(z.sink);if(R===0)I()}function J$($,J){if(!$.cleanup)$.cleanup=J;else if(Array.isArray($.cleanup))$.cleanup.push(J);else $.cleanup=[$.cleanup,J]}function K$($){if(!$.cleanup)return;if(Array.isArray($.cleanup))for(let J=0;J<$.cleanup.length;J++)$.cleanup[J]();else $.cleanup();$.cleanup=null}function v$($){let J=m;m=$,$.sourcesTail=null,$.flags=U$;let z=!1;try{let X=$.fn($.value);if($.error||!$.equals(X,$.value))$.value=X,$.error=void 0,z=!0}catch(X){z=!0,$.error=X instanceof Error?X:Error(String(X))}finally{m=J,H$($)}if(z){for(let X=$.sinks;X;X=X.nextSink)if(X.sink.flags&$$)X.sink.flags|=P}$.flags=p}function c$($){$.controller?.abort();let J=new AbortController;$.controller=J,$.error=void 0;let z=m;m=$,$.sourcesTail=null,$.flags=U$;let X;try{X=$.fn($.value,J.signal)}catch(j){$.controller=void 0,$.error=j instanceof Error?j:Error(String(j));return}finally{m=z,H$($)}X.then((j)=>{if(J.signal.aborted)return;if($.controller=void 0,$.error||!$.equals(j,$.value)){$.value=j,$.error=void 0;for(let B=$.sinks;B;B=B.nextSink)x(B.sink);if(R===0)I()}},(j)=>{if(J.signal.aborted)return;$.controller=void 0;let B=j instanceof Error?j:Error(String(j));if(!$.error||B.name!==$.error.name||B.message!==$.error.message){$.error=B;for(let D=$.sinks;D;D=D.nextSink)x(D.sink);if(R===0)I()}}),$.flags=p}function T$($){K$($);let J=m,z=_;m=_=$,$.sourcesTail=null,$.flags=U$;try{let X=$.fn();if(typeof X==="function")J$($,X)}finally{m=J,_=z,H$($)}$.flags=p}function w($){if($.flags&$$)for(let J=$.sources;J;J=J.nextSource){if("fn"in J.source)w(J.source);if($.flags&P)break}if($.flags&U$)throw new Z$("controller"in $?d:("value"in $)?u:"Effect");if($.flags&P)if("controller"in $)c$($);else if("value"in $)v$($);else T$($);else $.flags=p}function I(){if(_$)return;_$=!0;try{for(let $=0;$<C$.length;$++){let J=C$[$];if(J.flags&(P|$$))w(J)}C$.length=0}finally{_$=!1}}function z$($){R++;try{$()}finally{if(R--,R===0)I()}}function v($){let J=m;m=null;try{return $()}finally{m=J}}function u$($){let J=_,z={cleanup:null};_=z;try{let X=$();if(typeof X==="function")J$(z,X);let j=()=>K$(z);if(J)J$(J,j);return j}finally{_=J}}function d$($){let J=_;_=null;try{return $()}finally{_=J}}function y($,J){K(c,$,J?.guard);let z={value:$,sinks:null,sinksTail:null,equals:J?.equals??k,guard:J?.guard};return{[Symbol.toStringTag]:c,get(){if(m)F(z,m);return z.value},set(X){K(c,X,z.guard),N$(z,X)},update(X){S(c,X);let j=X(z.value);K(c,j,z.guard),N$(z,j)}}}function V$($){return f($,c)}function n($,J,z){if(Object.is($,J))return!0;if(typeof $!==typeof J)return!1;if($==null||typeof $!=="object"||J==null||typeof J!=="object")return!1;if(!z)z=new WeakSet;if(z.has($)||z.has(J))throw new Z$("isEqual");z.add($),z.add(J);try{let X=Array.isArray($);if(X!==Array.isArray(J))return!1;if(X){let j=$,B=J;if(j.length!==B.length)return!1;for(let D=0;D<j.length;D++)if(!n(j[D],B[D],z))return!1;return!0}if(E($)&&E(J)){let j=Object.keys($),B=Object.keys(J);if(j.length!==B.length)return!1;for(let D of j){if(!(D in J))return!1;if(!n($[D],J[D],z))return!1}return!0}return!1}finally{z.delete($),z.delete(J)}}function O$($,J){if($.length!==J.length)return!1;for(let z=0;z<$.length;z++)if($[z]!==J[z])return!1;return!0}function E$($){let J=0,z=typeof $==="function";return[typeof $==="string"?()=>`${$}${J++}`:z?(X)=>$(X)||String(J++):()=>String(J++),z]}function s$($,J,z,X,j){let B=new WeakSet,D={},M={},C={},N=[],Q=!1,W=new Map;for(let q=0;q<$.length;q++){let Z=z[q],H=$[q];if(Z&&H!==void 0)W.set(Z,H)}let G=new Set;for(let q=0;q<J.length;q++){let Z=J[q];if(Z===void 0)continue;let H=j?X(Z):z[q]??X(Z);if(G.has(H))throw new e(L,H,Z);if(N.push(H),G.add(H),!W.has(H))D[H]=Z,Q=!0;else if(!n(W.get(H),Z,B))M[H]=Z,Q=!0}for(let[q]of W)if(!G.has(q))C[q]=null,Q=!0;if(!Q&&!O$(z,N))Q=!0;return{add:D,change:M,remove:C,newKeys:N,changed:Q}}function Q$($,J){K(L,$,Array.isArray);let z=new Map,X=[],[j,B]=E$(J?.keyConfig),D=()=>X.map((Z)=>z.get(Z)?.get()).filter((Z)=>Z!==void 0),M={fn:D,value:$,flags:P,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:n,error:void 0},C=(Z)=>{let H={};for(let U=0;U<Z.length;U++){let V=Z[U];if(V===void 0)continue;let O=X[U];if(!O)O=j(V),X[U]=O;H[O]=V}return H},N=(Z)=>{let H=!1;for(let U in Z.add){let V=Z.add[U];K(`${L} item for key "${U}"`,V),z.set(U,y(V)),H=!0}if(Object.keys(Z.change).length)z$(()=>{for(let U in Z.change){let V=Z.change[U];K(`${L} item for key "${U}"`,V);let O=z.get(U);if(O)O.set(V)}});for(let U in Z.remove){z.delete(U);let V=X.indexOf(U);if(V!==-1)X.splice(V,1);H=!0}if(H)M.flags|=b;return Z.changed},Q=J?.watched,W=Q?()=>{if(m){if(!M.sinks)M.stop=Q();F(M,m)}}:()=>{if(m)F(M,m)},G=C($);for(let Z in G){let H=G[Z];K(`${L} item for key "${Z}"`,H),z.set(Z,y(H))}M.value=$,M.flags=0;let q={[Symbol.toStringTag]:L,[Symbol.isConcatSpreadable]:!0,*[Symbol.iterator](){for(let Z of X){let H=z.get(Z);if(H)yield H}},get length(){return W(),X.length},get(){if(W(),M.sources){if(M.flags){let Z=M.flags&b;if(M.value=v(D),Z){if(M.flags=P,w(M),M.error)throw M.error}else M.flags=p}}else if(w(M),M.error)throw M.error;return M.value},set(Z){let H=M.flags&P?D():M.value,U=s$(H,Z,X,j,B);if(U.changed){X=U.newKeys,N(U),M.flags|=P;for(let V=M.sinks;V;V=V.nextSink)x(V.sink);if(R===0)I()}},update(Z){q.set(Z(q.get()))},at(Z){let H=X[Z];return H!==void 0?z.get(H):void 0},keys(){return W(),X.values()},byKey(Z){return z.get(Z)},keyAt(Z){return X[Z]},indexOfKey(Z){return X.indexOf(Z)},add(Z){let H=j(Z);if(z.has(H))throw new e(L,H,Z);if(!X.includes(H))X.push(H);K(`${L} item for key "${H}"`,Z),z.set(H,y(Z)),M.flags|=P|b;for(let U=M.sinks;U;U=U.nextSink)x(U.sink);if(R===0)I();return H},remove(Z){let H=typeof Z==="number"?X[Z]:Z;if(H===void 0)return;if(z.delete(H)){let V=typeof Z==="number"?Z:X.indexOf(H);if(V>=0)X.splice(V,1);M.flags|=P|b;for(let O=M.sinks;O;O=O.nextSink)x(O.sink);if(R===0)I()}},replace(Z,H){let U=z.get(Z);if(!U)return;if(K(`${L} item for key "${Z}"`,H),U.get()===H)return;U.set(H),M.flags|=P;for(let V=M.sinks;V;V=V.nextSink)x(V.sink);if(R===0)I()},sort(Z){let U=X.map((V)=>[V,z.get(V)?.get()]).sort(g(Z)?(V,O)=>Z(V[1],O[1]):(V,O)=>String(V[1]).localeCompare(String(O[1]))).map(([V])=>V);if(!O$(X,U)){X=U,M.flags|=P;for(let V=M.sinks;V;V=V.nextSink)x(V.sink);if(R===0)I()}},splice(Z,H,...U){let V=X.length,O=Z<0?Math.max(0,V+Z):Math.min(Z,V),Y=Math.max(0,Math.min(H??Math.max(0,V-Math.max(0,O)),V-O)),A={},T={};for(let h=0;h<Y;h++){let a=O+h,Y$=X[a];if(Y$){let y$=z.get(Y$);if(y$)T[Y$]=y$.get()}}let w$=X.slice(0,O);for(let h of U){let a=j(h);if(z.has(a)&&!(a in T))throw new e(L,a,h);w$.push(a),A[a]=h}w$.push(...X.slice(O+Y));let h$=!!(Object.keys(A).length||Object.keys(T).length);if(h$){N({add:A,change:{},remove:T,changed:h$}),X=w$,M.flags|=P;for(let h=M.sinks;h;h=h.nextSink)x(h.sink);if(R===0)I()}return Object.values(T)},deriveCollection(Z){return x$(q,Z)}};return q}function R$($){return f($,L)}function B$($,J){if(S(u,$,X$),J?.value!==void 0)K(u,J.value,J?.guard);let z={fn:$,value:J?.value,flags:P,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:J?.equals??k,error:void 0,stop:void 0},X=J?.watched,j=X?()=>{if(m){if(!z.sinks)z.stop=X(()=>{if(x(z),R===0)I()});F(z,m)}}:()=>{if(m)F(z,m)};return{[Symbol.toStringTag]:u,get(){if(j(),w(z),z.error)throw z.error;return j$(u,z.value),z.value}}}function S$($){return f($,u)}function q$($,J){if(S(d,$,o),J?.value!==void 0)K(d,J.value,J?.guard);let z={fn:$,value:J?.value,sources:null,sourcesTail:null,sinks:null,sinksTail:null,flags:P,equals:J?.equals??k,controller:void 0,error:void 0,stop:void 0},X=J?.watched,j=X?()=>{if(m){if(!z.sinks)z.stop=X(()=>{if(x(z),R===0)I()});F(z,m)}}:()=>{if(m)F(z,m)};return{[Symbol.toStringTag]:d,get(){if(j(),w(z),z.error)throw z.error;return j$(d,z.value),z.value},isPending(){return!!z.controller},abort(){z.controller?.abort(),z.controller=void 0}}}function p$($){return f($,d)}function x$($,J){S(t,J);let z=o(J),X=new Map,j=[],B=(q)=>{let Z=z?q$(async(H,U)=>{let V=$.byKey(q)?.get();if(V==null)return H;return J(V,U)}):B$(()=>{let H=$.byKey(q)?.get();if(H==null)return;return J(H)});X.set(q,Z)};function D(q){if(!O$(j,q)){let Z=new Set(j),H=new Set(q);for(let U of j)if(!H.has(U))X.delete(U);for(let U of q)if(!Z.has(U))B(U);j=q,N.flags|=b}}function M(){D(Array.from($.keys()));let q=[];for(let Z of j)try{let H=X.get(Z)?.get();if(H!=null)q.push(H)}catch(H){if(!(H instanceof i))throw H}return q}let N={fn:M,value:[],flags:P,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:(q,Z)=>{if(q.length!==Z.length)return!1;for(let H=0;H<q.length;H++)if(q[H]!==Z[H])return!1;return!0},error:void 0};function Q(){if(N.sources){if(N.flags)if(N.value=v(M),N.flags&b){if(N.flags=P,w(N),N.error)throw N.error}else N.flags=p}else if(N.sinks){if(w(N),N.error)throw N.error}else N.value=v(M)}let W=Array.from(v(()=>$.keys()));for(let q of W)B(q);j=W;let G={[Symbol.toStringTag]:t,[Symbol.isConcatSpreadable]:!0,*[Symbol.iterator](){for(let q of j){let Z=X.get(q);if(Z)yield Z}},get length(){if(m)F(N,m);return Q(),j.length},keys(){if(m)F(N,m);return Q(),j.values()},get(){if(m)F(N,m);return Q(),N.value},at(q){let Z=j[q];return Z!==void 0?X.get(Z):void 0},byKey(q){return X.get(q)},keyAt(q){return j[q]},indexOfKey(q){return j.indexOf(q)},deriveCollection(q){return x$(G,q)}};return G}function t$($,J){let z=J?.value??[];if(z.length)K(t,z,Array.isArray);S(t,$,X$);let X=new Map,j=[],B=new Map,[D,M]=E$(J?.keyConfig),C=(Z)=>B.get(Z)??(M?D(Z):void 0),N=J?.createItem??y;function Q(){let Z=[];for(let H of j)try{let U=X.get(H)?.get();if(U!=null)Z.push(U)}catch(U){if(!(U instanceof i))throw U}return Z}let W={fn:Q,value:z,flags:P,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:L$,error:void 0};for(let Z of z){let H=D(Z);X.set(H,N(Z)),B.set(Z,H),j.push(H)}W.value=z,W.flags=P;function G(){if(m){if(!W.sinks)W.stop=$((Z)=>{let{add:H,change:U,remove:V}=Z;if(!H?.length&&!U?.length&&!V?.length)return;let O=!1;z$(()=>{if(H)for(let Y of H){let A=D(Y);if(X.set(A,N(Y)),B.set(Y,A),!j.includes(A))j.push(A);O=!0}if(U)for(let Y of U){let A=C(Y);if(!A)continue;let T=X.get(A);if(T&&V$(T))B.delete(T.get()),T.set(Y),B.set(Y,A)}if(V)for(let Y of V){let A=C(Y);if(!A)continue;B.delete(Y),X.delete(A);let T=j.indexOf(A);if(T!==-1)j.splice(T,1);O=!0}W.flags=P|(O?b:0);for(let Y=W.sinks;Y;Y=Y.nextSink)x(Y.sink)})});F(W,m)}}let q={[Symbol.toStringTag]:t,[Symbol.isConcatSpreadable]:!0,*[Symbol.iterator](){for(let Z of j){let H=X.get(Z);if(H)yield H}},get length(){return G(),j.length},keys(){return G(),j.values()},get(){if(G(),W.sources){if(W.flags){let Z=W.flags&b;if(W.value=v(Q),Z){if(W.flags=P,w(W),W.error)throw W.error}else W.flags=p}}else if(w(W),W.error)throw W.error;return W.value},at(Z){let H=j[Z];return H!==void 0?X.get(H):void 0},byKey(Z){return X.get(Z)},keyAt(Z){return j[Z]},indexOfKey(Z){return j.indexOf(Z)},deriveCollection(Z){return x$(q,Z)}};return q}function l$($){return f($,t)}function r$($){S("Effect",$);let J={fn:$,flags:P,sources:null,sourcesTail:null,cleanup:null},z=()=>{K$(J),J.fn=void 0,J.flags=p,J.sourcesTail=null,H$(J)};if(_)J$(_,z);return T$(J),z}function o$($,J){if(!_)throw new G$("match");let{ok:z,err:X=console.error,nil:j}=J,B,D=!1,M=Array($.length);for(let N=0;N<$.length;N++)try{M[N]=$[N].get()}catch(Q){if(Q instanceof i){D=!0;continue}if(!B)B=[];B.push(Q instanceof Error?Q:Error(String(Q)))}let C;try{if(D)C=j?.();else if(B)C=X(B);else C=z(M)}catch(N){X([N instanceof Error?N:Error(String(N))])}if(typeof C==="function")return C;if(C instanceof Promise){let N=_,Q=new AbortController;J$(N,()=>Q.abort()),C.then((W)=>{if(!Q.signal.aborted&&typeof W==="function")J$(N,W)}).catch((W)=>{X([W instanceof Error?W:Error(String(W))])})}}function i$($,J){if(S(s,$,X$),J?.value!==void 0)K(s,J.value,J?.guard);let z={value:J?.value,sinks:null,sinksTail:null,equals:J?.equals??k,guard:J?.guard,stop:void 0};return{[Symbol.toStringTag]:s,get(){if(m){if(!z.sinks)z.stop=$((X)=>{K(s,X,z.guard),N$(z,X)});F(z,m)}return j$(s,z.value),z.value}}}function n$($){return f($,s)}function a$($,J){let z=E($)||Array.isArray($),X=E(J)||Array.isArray(J);if(!z||!X){let W=!Object.is($,J);return{changed:W,add:W&&X?J:{},change:{},remove:W&&z?$:{}}}let j=new WeakSet,B={},D={},M={},C=!1,N=Object.keys($),Q=Object.keys(J);for(let W of Q)if(W in $){if(!n($[W],J[W],j))D[W]=J[W],C=!0}else B[W]=J[W],C=!0;for(let W of N)if(!(W in J))M[W]=void 0,C=!0;return{add:B,change:D,remove:M,changed:C}}function m$($,J){K(l,$,E);let z=new Map,X=(Q,W)=>{if(K(`${l} for key "${Q}"`,W),Array.isArray(W))z.set(Q,Q$(W));else if(E(W))z.set(Q,m$(W));else z.set(Q,y(W))},j=()=>{let Q={};return z.forEach((W,G)=>{Q[G]=W.get()}),Q},B={fn:j,value:$,flags:P,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:n,error:void 0},D=(Q)=>{let W=!1;for(let G in Q.add)X(G,Q.add[G]),W=!0;if(Object.keys(Q.change).length)z$(()=>{for(let G in Q.change){let q=Q.change[G];K(`${l} for key "${G}"`,q);let Z=z.get(G);if(Z)if(E(q)!==F$(Z))X(G,q),W=!0;else Z.set(q)}});for(let G in Q.remove)z.delete(G),W=!0;if(W)B.flags|=b;return Q.changed},M=J?.watched,C=M?()=>{if(m){if(!B.sinks)B.stop=M();F(B,m)}}:()=>{if(m)F(B,m)};for(let Q of Object.keys($))X(Q,$[Q]);let N={[Symbol.toStringTag]:l,[Symbol.isConcatSpreadable]:!1,*[Symbol.iterator](){for(let Q of Array.from(z.keys())){let W=z.get(Q);if(W)yield[Q,W]}},keys(){return C(),z.keys()},byKey(Q){return z.get(Q)},get(){if(C(),B.sources){if(B.flags){let Q=B.flags&b;if(B.value=v(j),Q){if(B.flags=P,w(B),B.error)throw B.error}else B.flags=p}}else if(w(B),B.error)throw B.error;return B.value},set(Q){let W=B.flags&P?j():B.value,G=a$(W,Q);if(D(G)){B.flags|=P;for(let q=B.sinks;q;q=q.nextSink)x(q.sink);if(R===0)I()}},update(Q){N.set(Q(N.get()))},add(Q,W){if(z.has(Q))throw new e(l,Q,W);X(Q,W),B.flags|=P|b;for(let G=B.sinks;G;G=G.nextSink)x(G.sink);if(R===0)I();return Q},remove(Q){if(z.delete(Q)){B.flags|=P|b;for(let G=B.sinks;G;G=G.nextSink)x(G.sink);if(R===0)I()}}};return new Proxy(N,{get(Q,W){if(W in Q)return Reflect.get(Q,W);if(typeof W!=="symbol")return Q.byKey(W)},has(Q,W){if(W in Q)return!0;return Q.byKey(String(W))!==void 0},ownKeys(Q){return Array.from(Q.keys())},getOwnPropertyDescriptor(Q,W){if(W in Q)return Reflect.getOwnPropertyDescriptor(Q,W);if(typeof W==="symbol")return;let G=Q.byKey(String(W));return G?{enumerable:!0,configurable:!0,writable:!0,value:G}:void 0}})}function F$($){return f($,l)}function e$($,J){return o($)?q$($,J):B$($,J)}function $J($){if(M$($))return $;if($==null)throw new W$("createSignal",$);if(o($))return q$($);if(g($))return B$($);if(f$($))return Q$($);if(E($))return m$($);return y($)}function JJ($){if(I$($))return $;if($==null||g($)||M$($))throw new W$("createMutableSignal",$);if(f$($))return Q$($);if(E($))return m$($);return y($)}function zJ($){return S$($)||p$($)}function M$($){let J=[c,u,d,s,r,L,t,l],z=Object.prototype.toString.call($).slice(8,-1);return J.includes(z)}function I$($){return V$($)||F$($)||R$($)}function XJ($,J){K(r,$,M$);let z=$,X=J?.guard,j={fn:()=>z.get(),value:void 0,flags:P,sources:null,sourcesTail:null,sinks:null,sinksTail:null,equals:J?.equals??k,error:void 0},B=()=>{if(m)F(j,m);if(w(j),j.error)throw j.error;return j.value},D=(C)=>{if(!I$(z))throw new P$(r);K(r,C,X),z.set(C)},M=(C)=>{K(r,C,M$),z=C,j.flags|=P;for(let N=j.sinks;N;N=N.nextSink)x(N.sink);if(R===0)I()};return{[Symbol.toStringTag]:r,configurable:!0,enumerable:!0,get:B,set:D,replace:M,current:()=>z}}function ZJ($){return f($,r)}export{D$ as valueString,v as untrack,d$ as unown,o$ as match,p$ as isTask,F$ as isStore,V$ as isState,ZJ as isSlot,M$ as isSignal,n$ as isSensor,E as isRecord,f as isObjectOfType,I$ as isMutableSignal,S$ as isMemo,R$ as isList,g as isFunction,n as isEqual,zJ as isComputed,l$ as isCollection,o as isAsyncFunction,q$ as createTask,m$ as createStore,y as createState,XJ as createSlot,$J as createSignal,i$ as createSensor,u$ as createScope,JJ as createMutableSignal,B$ as createMemo,Q$ as createList,r$ as createEffect,e$ as createComputed,t$ as createCollection,z$ as batch,i as UnsetSignalValueError,L$ as SKIP_EQUALITY,G$ as RequiredOwnerError,P$ as ReadonlySignalError,A$ as NullishSignalValueError,W$ as InvalidSignalValueError,b$ as InvalidCallbackError,Z$ as CircularDependencyError};
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeix/cause-effect",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"author": "Esther Brunner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
"types": "types/index.d.ts",
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@biomejs/biome": "2.4.6",
|
|
11
|
-
"
|
|
11
|
+
"bun-types": "latest",
|
|
12
12
|
"mitata": "^1.0.34",
|
|
13
|
-
"random": "^5.4.1"
|
|
13
|
+
"random": "^5.4.1",
|
|
14
|
+
"typescript": "latest"
|
|
14
15
|
},
|
|
15
16
|
"peerDependencies": {
|
|
16
|
-
"typescript": "
|
|
17
|
+
"typescript": ">=5.8.0"
|
|
17
18
|
},
|
|
18
19
|
"description": "Cause & Effect - reactive state management primitives library for TypeScript.",
|
|
19
20
|
"license": "MIT",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cause-effect
|
|
3
|
+
description: >
|
|
4
|
+
Expert guidance for using the @zeix/cause-effect reactive signals library in any project.
|
|
5
|
+
Use when implementing reactive patterns, debugging unexpected behavior, or answering
|
|
6
|
+
questions about the public API, signal types, or design decisions. Works in any project
|
|
7
|
+
that depends on @zeix/cause-effect — all knowledge is embedded, no library source required.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<scope>
|
|
11
|
+
This skill is for **consumer projects** that use `@zeix/cause-effect` as a dependency.
|
|
12
|
+
All domain knowledge is embedded in `references/` — no library source files are required.
|
|
13
|
+
|
|
14
|
+
For development work on the library itself, use the `cause-effect-dev` skill instead.
|
|
15
|
+
</scope>
|
|
16
|
+
|
|
17
|
+
<essential_principles>
|
|
18
|
+
**`T extends {}`** — all signal generics exclude `null` and `undefined`. Use wrapper types or sentinel values to represent absence.
|
|
19
|
+
|
|
20
|
+
**`createEffect` must be inside an owner.** Always wrap effect creation in `createScope` or nest it inside another effect.
|
|
21
|
+
|
|
22
|
+
**Never guess API shapes or behaviors.** The answers are in `references/`. If the embedded knowledge is insufficient, check the library's README or GUIDE — do not invent behavior.
|
|
23
|
+
</essential_principles>
|
|
24
|
+
|
|
25
|
+
<intake>
|
|
26
|
+
What kind of task is this?
|
|
27
|
+
|
|
28
|
+
1. **Use** — implement reactive patterns using the library's public API
|
|
29
|
+
2. **Debug** — investigate unexpected or broken reactive behavior
|
|
30
|
+
3. **Question** — understand the API, which signal to use, or a design decision
|
|
31
|
+
|
|
32
|
+
**Wait for response before proceeding.**
|
|
33
|
+
</intake>
|
|
34
|
+
|
|
35
|
+
<routing>
|
|
36
|
+
| Response | Workflow |
|
|
37
|
+
|---|---|
|
|
38
|
+
| 1, "use", "implement", "add", "build", "write" | workflows/use-api.md |
|
|
39
|
+
| 2, "debug", "fix", "broken", "not working", "wrong", "unexpected" | workflows/debug.md |
|
|
40
|
+
| 3, "question", "explain", "how", "why", "what", "which", "when" | workflows/answer-question.md |
|
|
41
|
+
|
|
42
|
+
**Intent-based routing** (if user provides clear context without selecting):
|
|
43
|
+
- Describes code to write or a feature to add → workflows/use-api.md
|
|
44
|
+
- Describes something not working as expected → workflows/debug.md
|
|
45
|
+
- Asks how something works or which signal to use → workflows/answer-question.md
|
|
46
|
+
|
|
47
|
+
**After identifying the workflow, read it and follow it exactly.**
|
|
48
|
+
</routing>
|
|
49
|
+
|
|
50
|
+
<reference_index>
|
|
51
|
+
All in `references/` — all knowledge is self-contained, no external files required:
|
|
52
|
+
|
|
53
|
+
| File | Contents |
|
|
54
|
+
|---|---|
|
|
55
|
+
| signal-types.md | What each signal is for, when to use each, decision guide |
|
|
56
|
+
| api-facts.md | Key API constraints, core functions, options, callback patterns |
|
|
57
|
+
| non-obvious-behaviors.md | Counterintuitive behaviors with correct vs incorrect examples |
|
|
58
|
+
| error-classes.md | Error classes, trigger conditions, and how to handle them |
|
|
59
|
+
</reference_index>
|
|
60
|
+
|
|
61
|
+
<workflows_index>
|
|
62
|
+
All in `workflows/`:
|
|
63
|
+
|
|
64
|
+
| Workflow | Purpose |
|
|
65
|
+
|---|---|
|
|
66
|
+
| use-api.md | Implement reactive patterns using the public API |
|
|
67
|
+
| debug.md | Diagnose and fix unexpected reactive behavior |
|
|
68
|
+
| answer-question.md | Answer questions about the API, signals, or design |
|
|
69
|
+
</workflows_index>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Cause & Effect"
|
|
3
|
+
short_description: "Expert guidance for using the @zeix/cause-effect reactive signals library in your project"
|
|
4
|
+
default_prompt: "Use $cause-effect to implement reactive patterns, debug unexpected behavior, or answer questions about the @zeix/cause-effect public API."
|