@kontsedal/olas-core 0.0.1-rc.1 → 0.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/dist/index.cjs +40 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -11
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +32 -11
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +40 -11
- package/dist/index.mjs.map +1 -1
- package/dist/{root-BImHnGj1.mjs → root-De-6KWIZ.mjs} +750 -149
- package/dist/root-De-6KWIZ.mjs.map +1 -0
- package/dist/{root-Bazp5_Ik.cjs → root-XKEsSmcd.cjs} +755 -148
- package/dist/root-XKEsSmcd.cjs.map +1 -0
- package/dist/testing.cjs +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.mjs +1 -1
- package/dist/{types-CAMgqCMz.d.mts → types-C-zV1JZA.d.mts} +215 -13
- package/dist/types-C-zV1JZA.d.mts.map +1 -0
- package/dist/{types-emq_lZd7.d.cts → types-DKfpkm17.d.cts} +215 -13
- package/dist/types-DKfpkm17.d.cts.map +1 -0
- package/package.json +1 -1
- package/src/controller/index.ts +6 -0
- package/src/controller/instance.ts +432 -18
- package/src/controller/root.ts +9 -1
- package/src/controller/types.ts +148 -7
- package/src/emitter.ts +34 -3
- package/src/forms/field.ts +73 -8
- package/src/forms/form-types.ts +16 -0
- package/src/forms/form.ts +218 -26
- package/src/index.ts +12 -1
- package/src/query/client.ts +161 -6
- package/src/query/define.ts +14 -0
- package/src/query/entry.ts +64 -42
- package/src/query/infinite.ts +77 -55
- package/src/query/mutation.ts +11 -21
- package/src/query/plugin.ts +50 -0
- package/src/query/use.ts +80 -3
- package/src/signals/readonly.ts +3 -3
- package/src/timing/debounced.ts +24 -4
- package/src/timing/throttled.ts +22 -3
- package/src/utils.ts +32 -4
- package/dist/root-BImHnGj1.mjs.map +0 -1
- package/dist/root-Bazp5_Ik.cjs.map +0 -1
- package/dist/types-CAMgqCMz.d.mts.map +0 -1
- package/dist/types-emq_lZd7.d.cts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_root = require("./root-
|
|
2
|
+
const require_root = require("./root-XKEsSmcd.cjs");
|
|
3
3
|
//#region src/signals/readonly.ts
|
|
4
4
|
/**
|
|
5
5
|
* Project a Signal (or any object with a reactive `value` + `peek` + `subscribe`)
|
|
@@ -9,7 +9,7 @@ const require_root = require("./root-Bazp5_Ik.cjs");
|
|
|
9
9
|
* Internal helper — not exported from the package's public surface.
|
|
10
10
|
*/
|
|
11
11
|
function readOnly(source) {
|
|
12
|
-
return {
|
|
12
|
+
return Object.freeze({
|
|
13
13
|
get value() {
|
|
14
14
|
return source.value;
|
|
15
15
|
},
|
|
@@ -19,7 +19,7 @@ function readOnly(source) {
|
|
|
19
19
|
subscribe(handler) {
|
|
20
20
|
return source.subscribe(handler);
|
|
21
21
|
}
|
|
22
|
-
};
|
|
22
|
+
});
|
|
23
23
|
}
|
|
24
24
|
//#endregion
|
|
25
25
|
//#region src/forms/validators.ts
|
|
@@ -272,14 +272,17 @@ function selection(options) {
|
|
|
272
272
|
* Lag a signal by `ms`. The returned signal updates only after the source has
|
|
273
273
|
* been unchanged for `ms`. Each new write resets the timer.
|
|
274
274
|
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
275
|
+
* Pass `options.signal` (an `AbortSignal`) to tie the internal effect to a
|
|
276
|
+
* lifecycle — when the signal aborts the effect disposes, the pending timer
|
|
277
|
+
* clears, and the subscriber chain on `source` drops. Without `signal`, the
|
|
278
|
+
* effect lives as long as `source` does; pass a signal whenever the source
|
|
279
|
+
* outlives the consumer.
|
|
277
280
|
*/
|
|
278
|
-
function debounced(source, ms) {
|
|
281
|
+
function debounced(source, ms, options) {
|
|
279
282
|
const out = require_root.signal(source.peek());
|
|
280
283
|
let timer = null;
|
|
281
284
|
let initial = true;
|
|
282
|
-
require_root.effect(() => {
|
|
285
|
+
const dispose = require_root.effect(() => {
|
|
283
286
|
const value = source.value;
|
|
284
287
|
if (initial) {
|
|
285
288
|
initial = false;
|
|
@@ -291,6 +294,18 @@ function debounced(source, ms) {
|
|
|
291
294
|
timer = null;
|
|
292
295
|
}, ms);
|
|
293
296
|
});
|
|
297
|
+
const sig = options?.signal;
|
|
298
|
+
if (sig) {
|
|
299
|
+
const stop = () => {
|
|
300
|
+
if (timer != null) {
|
|
301
|
+
clearTimeout(timer);
|
|
302
|
+
timer = null;
|
|
303
|
+
}
|
|
304
|
+
dispose();
|
|
305
|
+
};
|
|
306
|
+
if (sig.aborted) stop();
|
|
307
|
+
else sig.addEventListener("abort", stop, { once: true });
|
|
308
|
+
}
|
|
294
309
|
return out;
|
|
295
310
|
}
|
|
296
311
|
//#endregion
|
|
@@ -300,15 +315,17 @@ function debounced(source, ms) {
|
|
|
300
315
|
* The first change passes through immediately. Subsequent changes within the
|
|
301
316
|
* window are coalesced; the latest value is emitted when the window expires.
|
|
302
317
|
*
|
|
303
|
-
*
|
|
318
|
+
* Pass `options.signal` to tie the internal effect to a lifecycle — when the
|
|
319
|
+
* signal aborts the effect disposes and any pending trailing timer clears.
|
|
320
|
+
* Without `signal`, the effect lives as long as `source` does.
|
|
304
321
|
*/
|
|
305
|
-
function throttled(source, ms) {
|
|
322
|
+
function throttled(source, ms, options) {
|
|
306
323
|
const out = require_root.signal(source.peek());
|
|
307
324
|
let lastEmit = Number.NEGATIVE_INFINITY;
|
|
308
325
|
let trailingTimer = null;
|
|
309
326
|
let trailingValue = source.peek();
|
|
310
327
|
let initial = true;
|
|
311
|
-
require_root.effect(() => {
|
|
328
|
+
const dispose = require_root.effect(() => {
|
|
312
329
|
const value = source.value;
|
|
313
330
|
if (initial) {
|
|
314
331
|
initial = false;
|
|
@@ -332,6 +349,18 @@ function throttled(source, ms) {
|
|
|
332
349
|
}, ms - elapsed);
|
|
333
350
|
}
|
|
334
351
|
});
|
|
352
|
+
const sig = options?.signal;
|
|
353
|
+
if (sig) {
|
|
354
|
+
const stop = () => {
|
|
355
|
+
if (trailingTimer != null) {
|
|
356
|
+
clearTimeout(trailingTimer);
|
|
357
|
+
trailingTimer = null;
|
|
358
|
+
}
|
|
359
|
+
dispose();
|
|
360
|
+
};
|
|
361
|
+
if (sig.aborted) stop();
|
|
362
|
+
else sig.addEventListener("abort", stop, { once: true });
|
|
363
|
+
}
|
|
335
364
|
return out;
|
|
336
365
|
}
|
|
337
366
|
//#endregion
|
|
@@ -357,6 +386,7 @@ exports.pattern = pattern;
|
|
|
357
386
|
exports.required = required;
|
|
358
387
|
exports.selection = selection;
|
|
359
388
|
exports.signal = require_root.signal;
|
|
389
|
+
exports.stableHash = require_root.stableHash;
|
|
360
390
|
exports.throttled = throttled;
|
|
361
391
|
exports.untracked = require_root.untracked;
|
|
362
392
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["signal","computed","signal","signal"],"sources":["../src/signals/readonly.ts","../src/forms/validators.ts","../src/query/define.ts","../src/scope.ts","../src/selection.ts","../src/timing/debounced.ts","../src/timing/throttled.ts"],"sourcesContent":["import type { ReadSignal } from './types'\n\n/**\n * Project a Signal (or any object with a reactive `value` + `peek` + `subscribe`)\n * as a `ReadSignal`. The returned object does not expose `set` / `update` /\n * settable `value`, so it can be returned from APIs without callers mutating it.\n *\n * Internal helper — not exported from the package's public surface.\n */\nexport function readOnly<T>(source: ReadSignal<T>): ReadSignal<T> {\n return {\n get value() {\n return source.value\n },\n peek() {\n return source.peek()\n },\n subscribe(handler) {\n return source.subscribe(handler)\n },\n }\n}\n","import type { Validator } from './types'\n\nconst isEmpty = (value: unknown): boolean => {\n if (value === undefined || value === null) return true\n if (typeof value === 'string') return value.length === 0\n if (Array.isArray(value)) return value.length === 0\n return false\n}\n\n/** Reject empty values (undefined, null, empty string, empty array). */\nexport const required =\n <T>(message = 'Required'): Validator<T> =>\n (value) =>\n isEmpty(value) ? message : null\n\n/** Reject strings / arrays shorter than `n`. Allows null/undefined (use with `required` to forbid). */\nexport const minLength =\n (n: number, message?: string): Validator<string | readonly unknown[]> =>\n (value) => {\n if (value == null) return null\n if (value.length >= n) return null\n return message ?? `Must be at least ${n} characters`\n }\n\n/** Reject strings / arrays longer than `n`. */\nexport const maxLength =\n (n: number, message?: string): Validator<string | readonly unknown[]> =>\n (value) => {\n if (value == null) return null\n if (value.length <= n) return null\n return message ?? `Must be no more than ${n} characters`\n }\n\n/** Reject numbers less than `n`. */\nexport const min =\n (n: number, message?: string): Validator<number> =>\n (value) => {\n if (value == null) return null\n if (value >= n) return null\n return message ?? `Must be at least ${n}`\n }\n\n/** Reject numbers greater than `n`. */\nexport const max =\n (n: number, message?: string): Validator<number> =>\n (value) => {\n if (value == null) return null\n if (value <= n) return null\n return message ?? `Must be no more than ${n}`\n }\n\n// RFC-5322-light. Pragmatic, not exhaustive — production forms should\n// rely on server-side validation for definitive answers.\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n/** Reject strings that don't look like an email. Empty / null pass (use with `required` to forbid). */\nexport const email =\n (message = 'Invalid email address'): Validator<string> =>\n (value) => {\n if (value == null || value === '') return null\n return EMAIL_RE.test(value) ? null : message\n }\n\n/** Reject strings that don't match the supplied `RegExp`. */\nexport const pattern =\n (re: RegExp, message = 'Invalid format'): Validator<string> =>\n (value) => {\n if (value == null || value === '') return null\n return re.test(value) ? null : message\n }\n","import type { QueryClient } from './client'\nimport type { InfiniteQuery, InfiniteQuerySpec } from './infinite'\nimport { type RegisteredQuery, registerQueryById } from './plugin'\nimport type { Query, QuerySpec, Snapshot } from './types'\n\ntype QueryInternal<Args extends unknown[], T> = Query<Args, T> & {\n readonly __spec: QuerySpec<Args, T>\n __clients: Set<QueryClient>\n}\n\nconst warnedMissingId = new WeakSet<object>()\n\nfunction registerQueryId(spec: { queryId?: string; crossTab?: boolean }, query: object): void {\n if (spec.queryId != null) {\n registerQueryById(spec.queryId, query as RegisteredQuery)\n } else if (spec.crossTab === true) {\n // Plugins can't route a message without a `queryId`. Warn once per\n // offending spec — repeated warnings on every render would be noisy.\n if (__DEV__ && !warnedMissingId.has(spec as object)) {\n warnedMissingId.add(spec as object)\n console.warn(\n '[olas] defineQuery({ crossTab: true }) requires a stable `queryId`. ' +\n 'Add `queryId: \"<unique-string>\"` to the spec. Cross-tab sync is disabled for this query.',\n )\n }\n }\n}\n\n/**\n * Define a keyed, shared query. The returned Query value lives at module\n * scope; per-root QueryClients bind their own entry registries to it.\n */\nexport function defineQuery<Args extends unknown[], T>(spec: QuerySpec<Args, T>): Query<Args, T> {\n const clients = new Set<QueryClient>()\n const query = {\n __olas: 'query' as const,\n __spec: spec,\n __clients: clients,\n\n invalidate(...args: Args): void {\n for (const client of clients) {\n client.invalidate(query as Query<Args, T>, args)\n }\n },\n\n invalidateAll(): void {\n for (const client of clients) {\n client.invalidateAll(query as Query<Args, T>)\n }\n },\n\n setData(...rest: [...Args, updater: (prev: T | undefined) => T]): Snapshot {\n const updater = rest[rest.length - 1] as (prev: T | undefined) => T\n const keyArgs = rest.slice(0, -1) as unknown as Args\n const childSnapshots: Snapshot[] = []\n for (const client of clients) {\n childSnapshots.push(client.setData(query as Query<Args, T>, keyArgs, updater))\n }\n return {\n rollback: () => {\n for (const s of childSnapshots) s.rollback()\n },\n finalize: () => {\n for (const s of childSnapshots) s.finalize()\n },\n }\n },\n\n prefetch(...args: Args): Promise<T> {\n // Single-client common case; if none, throw.\n const [first] = clients\n if (!first) {\n return Promise.reject(new Error('[olas] prefetch called before any root has subscribed'))\n }\n return first.prefetch(query as Query<Args, T>, args)\n },\n } satisfies QueryInternal<Args, T>\n\n registerQueryId(spec, query)\n return query as Query<Args, T>\n}\n\ntype InfiniteQueryInternal<Args extends unknown[], TPage, TItem> = InfiniteQuery<\n Args,\n TPage,\n TItem\n> & {\n readonly __spec: InfiniteQuerySpec<Args, any, TPage, TItem>\n __clients: Set<QueryClient>\n}\n\n/**\n * Define a paginated query (chat-style \"load more\", infinite scrolling). Pages\n * are kept in order and concatenated via `getNextPageParam` /\n * `getPreviousPageParam`. The returned handle is module-scoped — bind\n * subscribers via `ctx.use(infiniteQuery, () => [...args])`. Spec §5.7,\n * §20.4.\n */\nexport function defineInfiniteQuery<Args extends unknown[], PageParam, TPage, TItem = TPage>(\n spec: InfiniteQuerySpec<Args, PageParam, TPage, TItem>,\n): InfiniteQuery<Args, TPage, TItem> {\n const clients = new Set<QueryClient>()\n const query = {\n __olas: 'infiniteQuery' as const,\n __spec: spec,\n __clients: clients,\n\n invalidate(...args: Args): void {\n for (const client of clients) {\n client.invalidateInfinite(query as InfiniteQuery<Args, TPage, TItem>, args)\n }\n },\n\n invalidateAll(): void {\n for (const client of clients) {\n client.invalidateAllInfinite(query as InfiniteQuery<Args, TPage, TItem>)\n }\n },\n\n setData(...rest: [...Args, updater: (prev: TPage[] | undefined) => TPage[]]): Snapshot {\n const updater = rest[rest.length - 1] as (prev: TPage[] | undefined) => TPage[]\n const keyArgs = rest.slice(0, -1) as unknown as Args\n const childSnapshots: Snapshot[] = []\n for (const client of clients) {\n childSnapshots.push(\n client.setInfiniteData<Args, TPage>(\n query as InfiniteQuery<Args, TPage, TItem>,\n keyArgs,\n updater,\n ),\n )\n }\n return {\n rollback: () => {\n for (const s of childSnapshots) s.rollback()\n },\n finalize: () => {\n for (const s of childSnapshots) s.finalize()\n },\n }\n },\n\n prefetch(...args: Args): Promise<TPage> {\n const [first] = clients\n if (!first) {\n return Promise.reject(new Error('[olas] prefetch called before any root has subscribed'))\n }\n return first.prefetchInfinite(query as InfiniteQuery<Args, TPage, TItem>, args)\n },\n } satisfies InfiniteQueryInternal<Args, TPage, TItem>\n\n registerQueryId(spec, query)\n return query as InfiniteQuery<Args, TPage, TItem>\n}\n","/**\n * Typed cross-tree data slot. Provided by an ancestor via `ctx.provide(scope, value)`\n * and consumed anywhere in its subtree via `ctx.inject(scope)`. Defined at module\n * scope so the identity is stable across calls. See spec §10.3.\n */\nexport type Scope<T> = {\n readonly __olas: 'scope'\n /** Per-scope identity; matches across `provide` / `inject`. */\n readonly __id: symbol\n /** Optional human-readable name (used in error messages). */\n readonly name?: string\n /** Default value used when no provider exists; `undefined` if none was set. */\n readonly default?: T\n /** True iff `defineScope` was called with a `default` (even `default: undefined`). */\n readonly hasDefault: boolean\n // Phantom for inference — typed `T` is preserved through the scope's lifetime.\n readonly __t?: T\n}\n\nexport type ScopeOptions<T> = {\n default?: T\n name?: string\n}\n\n/**\n * Create a scope. The returned value is the typed handle passed to\n * `ctx.provide(scope, value)` and `ctx.inject(scope)`. Identity is keyed by\n * an internal symbol so two `defineScope()` calls — even with identical\n * options — yield distinct scopes.\n */\nexport function defineScope<T>(options?: ScopeOptions<T>): Scope<T> {\n const hasDefault = options !== undefined && 'default' in options\n const name = options?.name\n const scope: Scope<T> = {\n __olas: 'scope',\n __id: Symbol(name ?? 'scope'),\n hasDefault,\n ...(name !== undefined ? { name } : {}),\n ...(hasDefault ? { default: options?.default as T } : {}),\n }\n return scope\n}\n","import { computed, signal } from './signals'\nimport { readOnly } from './signals/readonly'\nimport type { ReadSignal } from './signals/types'\n\n/**\n * Multi-select state for tables / lists with bulk actions (spec §17.5).\n *\n * Plain function — not bound to `ctx`. Place it in a controller's closure so\n * it dies with the closure. The phantom `T` parameter brands the selection by\n * item type; IDs are always strings.\n */\n// biome-ignore lint/correctness/noUnusedVariables: phantom branding param (spec §17.5)\nexport type Selection<T = unknown> = {\n selectedIds: ReadSignal<ReadonlySet<string>>\n size: ReadSignal<number>\n isSelected(id: string): ReadSignal<boolean>\n\n select(id: string): void\n deselect(id: string): void\n toggle(id: string): void\n clear(): void\n selectAll(ids: readonly string[]): void\n\n handleClick(\n id: string,\n mods: { shift?: boolean; meta?: boolean },\n ordered: readonly string[],\n ): void\n}\n\n/**\n * Create a `Selection<T>`. Optional `initial` seeds the selected set.\n *\n * `handleClick` encapsulates the standard click semantics:\n * - plain click → select only `id` (anchor moves to `id`)\n * - meta-click → toggle `id` (anchor moves to `id` on add)\n * - shift-click → range from anchor to `id` along `ordered` (anchor sticks,\n * so subsequent shift-clicks extend from the same origin)\n *\n * Spec §16.5 / §17.5.\n */\nexport function selection<T = unknown>(options?: { initial?: readonly string[] }): Selection<T> {\n const ids = signal<ReadonlySet<string>>(new Set(options?.initial))\n let anchor: string | null = options?.initial?.length\n ? (options.initial[options.initial.length - 1] ?? null)\n : null\n // Snapshot of the selection just before the first shift-click of a run.\n // Subsequent shift-clicks re-compute the range against this snapshot so the\n // user can shrink or grow the range. Reset on any non-shift click.\n let preShiftSelection: ReadonlySet<string> | null = null\n\n const size = computed(() => ids.value.size)\n\n const isSelected = (id: string): ReadSignal<boolean> => computed(() => ids.value.has(id))\n\n const select = (id: string): void => {\n const prev = ids.peek()\n if (!prev.has(id)) {\n const next = new Set(prev)\n next.add(id)\n ids.set(next)\n }\n anchor = id\n }\n\n const deselect = (id: string): void => {\n const prev = ids.peek()\n if (!prev.has(id)) return\n const next = new Set(prev)\n next.delete(id)\n ids.set(next)\n }\n\n const toggle = (id: string): void => {\n const prev = ids.peek()\n const next = new Set(prev)\n if (prev.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n anchor = id\n }\n ids.set(next)\n }\n\n const clear = (): void => {\n if (ids.peek().size === 0) {\n anchor = null\n return\n }\n ids.set(new Set())\n anchor = null\n }\n\n const selectAll = (incoming: readonly string[]): void => {\n ids.set(new Set(incoming))\n anchor = incoming.length > 0 ? (incoming[incoming.length - 1] ?? null) : null\n }\n\n const handleClick = (\n id: string,\n mods: { shift?: boolean; meta?: boolean },\n ordered: readonly string[],\n ): void => {\n if (mods.shift && anchor !== null) {\n const anchorIdx = ordered.indexOf(anchor)\n const targetIdx = ordered.indexOf(id)\n if (anchorIdx === -1 || targetIdx === -1) {\n // anchor or target not visible — fall back to plain select\n ids.set(new Set([id]))\n anchor = id\n preShiftSelection = null\n return\n }\n if (preShiftSelection === null) {\n preShiftSelection = ids.peek()\n }\n const [lo, hi] = anchorIdx < targetIdx ? [anchorIdx, targetIdx] : [targetIdx, anchorIdx]\n const next = new Set(preShiftSelection)\n for (const k of ordered.slice(lo, hi + 1)) next.add(k)\n ids.set(next)\n // Anchor stays — subsequent shift-clicks extend from the same origin.\n return\n }\n // Any non-shift click ends the shift run.\n preShiftSelection = null\n if (mods.meta) {\n toggle(id)\n return\n }\n ids.set(new Set([id]))\n anchor = id\n }\n\n return {\n selectedIds: readOnly(ids),\n size,\n isSelected,\n select,\n deselect,\n toggle,\n clear,\n selectAll,\n handleClick,\n }\n}\n","import { effect, signal } from '../signals'\nimport type { ReadSignal } from '../signals/types'\n\n/**\n * Lag a signal by `ms`. The returned signal updates only after the source has\n * been unchanged for `ms`. Each new write resets the timer.\n *\n * No lifecycle — the internal effect runs for the lifetime of the program.\n * Use inside a controller closure so it dies with the closure.\n */\nexport function debounced<T>(source: ReadSignal<T>, ms: number): ReadSignal<T> {\n const out = signal<T>(source.peek())\n let timer: ReturnType<typeof setTimeout> | null = null\n let initial = true\n\n effect(() => {\n const value = source.value\n if (initial) {\n // The first effect run reads the source for tracking; we already\n // initialized `out` to the same value, so skip scheduling.\n initial = false\n return\n }\n if (timer != null) clearTimeout(timer)\n timer = setTimeout(() => {\n out.set(value)\n timer = null\n }, ms)\n })\n\n return out\n}\n","import { effect, signal } from '../signals'\nimport type { ReadSignal } from '../signals/types'\n\n/**\n * Rate-limit a signal so it emits at most once per `ms` (leading + trailing).\n * The first change passes through immediately. Subsequent changes within the\n * window are coalesced; the latest value is emitted when the window expires.\n *\n * No lifecycle — see debounced() note.\n */\nexport function throttled<T>(source: ReadSignal<T>, ms: number): ReadSignal<T> {\n const out = signal<T>(source.peek())\n let lastEmit = Number.NEGATIVE_INFINITY\n let trailingTimer: ReturnType<typeof setTimeout> | null = null\n let trailingValue: T = source.peek()\n let initial = true\n\n effect(() => {\n const value = source.value\n if (initial) {\n initial = false\n return\n }\n const now = Date.now()\n const elapsed = now - lastEmit\n if (elapsed >= ms) {\n out.set(value)\n lastEmit = now\n if (trailingTimer != null) {\n clearTimeout(trailingTimer)\n trailingTimer = null\n }\n } else {\n trailingValue = value\n if (trailingTimer == null) {\n trailingTimer = setTimeout(() => {\n out.set(trailingValue)\n lastEmit = Date.now()\n trailingTimer = null\n }, ms - elapsed)\n }\n }\n })\n\n return out\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["signal","computed","signal","effect","signal","effect"],"sources":["../src/signals/readonly.ts","../src/forms/validators.ts","../src/query/define.ts","../src/scope.ts","../src/selection.ts","../src/timing/debounced.ts","../src/timing/throttled.ts"],"sourcesContent":["import type { ReadSignal } from './types'\n\n/**\n * Project a Signal (or any object with a reactive `value` + `peek` + `subscribe`)\n * as a `ReadSignal`. The returned object does not expose `set` / `update` /\n * settable `value`, so it can be returned from APIs without callers mutating it.\n *\n * Internal helper — not exported from the package's public surface.\n */\nexport function readOnly<T>(source: ReadSignal<T>): ReadSignal<T> {\n return Object.freeze({\n get value() {\n return source.value\n },\n peek() {\n return source.peek()\n },\n subscribe(handler: (value: T) => void) {\n return source.subscribe(handler)\n },\n })\n}\n","import type { Validator } from './types'\n\nconst isEmpty = (value: unknown): boolean => {\n if (value === undefined || value === null) return true\n if (typeof value === 'string') return value.length === 0\n if (Array.isArray(value)) return value.length === 0\n return false\n}\n\n/** Reject empty values (undefined, null, empty string, empty array). */\nexport const required =\n <T>(message = 'Required'): Validator<T> =>\n (value) =>\n isEmpty(value) ? message : null\n\n/** Reject strings / arrays shorter than `n`. Allows null/undefined (use with `required` to forbid). */\nexport const minLength =\n (n: number, message?: string): Validator<string | readonly unknown[]> =>\n (value) => {\n if (value == null) return null\n if (value.length >= n) return null\n return message ?? `Must be at least ${n} characters`\n }\n\n/** Reject strings / arrays longer than `n`. */\nexport const maxLength =\n (n: number, message?: string): Validator<string | readonly unknown[]> =>\n (value) => {\n if (value == null) return null\n if (value.length <= n) return null\n return message ?? `Must be no more than ${n} characters`\n }\n\n/** Reject numbers less than `n`. */\nexport const min =\n (n: number, message?: string): Validator<number> =>\n (value) => {\n if (value == null) return null\n if (value >= n) return null\n return message ?? `Must be at least ${n}`\n }\n\n/** Reject numbers greater than `n`. */\nexport const max =\n (n: number, message?: string): Validator<number> =>\n (value) => {\n if (value == null) return null\n if (value <= n) return null\n return message ?? `Must be no more than ${n}`\n }\n\n// RFC-5322-light. Pragmatic, not exhaustive — production forms should\n// rely on server-side validation for definitive answers.\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\n/** Reject strings that don't look like an email. Empty / null pass (use with `required` to forbid). */\nexport const email =\n (message = 'Invalid email address'): Validator<string> =>\n (value) => {\n if (value == null || value === '') return null\n return EMAIL_RE.test(value) ? null : message\n }\n\n/** Reject strings that don't match the supplied `RegExp`. */\nexport const pattern =\n (re: RegExp, message = 'Invalid format'): Validator<string> =>\n (value) => {\n if (value == null || value === '') return null\n return re.test(value) ? null : message\n }\n","import type { QueryClient } from './client'\nimport type { InfiniteQuery, InfiniteQuerySpec } from './infinite'\nimport { type RegisteredQuery, registerQueryById } from './plugin'\nimport type { Query, QuerySpec, Snapshot } from './types'\n\ntype QueryInternal<Args extends unknown[], T> = Query<Args, T> & {\n readonly __spec: QuerySpec<Args, T>\n __clients: Set<QueryClient>\n}\n\nconst warnedMissingId = new WeakSet<object>()\n\nfunction registerQueryId(spec: { queryId?: string; crossTab?: boolean }, query: object): void {\n if (spec.queryId != null) {\n registerQueryById(spec.queryId, query as RegisteredQuery)\n } else if (spec.crossTab === true) {\n // Plugins can't route a message without a `queryId`. Warn once per\n // offending spec — repeated warnings on every render would be noisy.\n if (__DEV__ && !warnedMissingId.has(spec as object)) {\n warnedMissingId.add(spec as object)\n console.warn(\n '[olas] defineQuery({ crossTab: true }) requires a stable `queryId`. ' +\n 'Add `queryId: \"<unique-string>\"` to the spec. Cross-tab sync is disabled for this query.',\n )\n }\n }\n}\n\n/**\n * Define a keyed, shared query. The returned Query value lives at module\n * scope; per-root QueryClients bind their own entry registries to it.\n */\nexport function defineQuery<Args extends unknown[], T>(spec: QuerySpec<Args, T>): Query<Args, T> {\n const clients = new Set<QueryClient>()\n const query = {\n __olas: 'query' as const,\n __spec: spec,\n __clients: clients,\n\n invalidate(...args: Args): void {\n for (const client of clients) {\n client.invalidate(query as Query<Args, T>, args)\n }\n },\n\n invalidateAll(): void {\n for (const client of clients) {\n client.invalidateAll(query as Query<Args, T>)\n }\n },\n\n setData(...rest: [...Args, updater: (prev: T | undefined) => T]): Snapshot {\n const updater = rest[rest.length - 1] as (prev: T | undefined) => T\n const keyArgs = rest.slice(0, -1) as unknown as Args\n const childSnapshots: Snapshot[] = []\n for (const client of clients) {\n childSnapshots.push(client.setData(query as Query<Args, T>, keyArgs, updater))\n }\n return {\n rollback: () => {\n for (const s of childSnapshots) s.rollback()\n },\n finalize: () => {\n for (const s of childSnapshots) s.finalize()\n },\n }\n },\n\n prefetch(...args: Args): Promise<T> {\n // Single-client common case; if none, throw.\n const [first] = clients\n if (!first) {\n return Promise.reject(new Error('[olas] prefetch called before any root has subscribed'))\n }\n if (__DEV__ && clients.size > 1) {\n // eslint-disable-next-line no-console\n console.warn(\n '[olas] query.prefetch() is ambiguous when multiple roots are registered; ' +\n 'using an arbitrary root. Call `root.prefetch(query, args)` (or per-root) to be explicit.',\n )\n }\n return first.prefetch(query as Query<Args, T>, args)\n },\n } satisfies QueryInternal<Args, T>\n\n registerQueryId(spec, query)\n return query as Query<Args, T>\n}\n\ntype InfiniteQueryInternal<Args extends unknown[], TPage, TItem> = InfiniteQuery<\n Args,\n TPage,\n TItem\n> & {\n readonly __spec: InfiniteQuerySpec<Args, any, TPage, TItem>\n __clients: Set<QueryClient>\n}\n\n/**\n * Define a paginated query (chat-style \"load more\", infinite scrolling). Pages\n * are kept in order and concatenated via `getNextPageParam` /\n * `getPreviousPageParam`. The returned handle is module-scoped — bind\n * subscribers via `ctx.use(infiniteQuery, () => [...args])`. Spec §5.7,\n * §20.4.\n */\nexport function defineInfiniteQuery<Args extends unknown[], PageParam, TPage, TItem = TPage>(\n spec: InfiniteQuerySpec<Args, PageParam, TPage, TItem>,\n): InfiniteQuery<Args, TPage, TItem> {\n const clients = new Set<QueryClient>()\n const query = {\n __olas: 'infiniteQuery' as const,\n __spec: spec,\n __clients: clients,\n\n invalidate(...args: Args): void {\n for (const client of clients) {\n client.invalidateInfinite(query as InfiniteQuery<Args, TPage, TItem>, args)\n }\n },\n\n invalidateAll(): void {\n for (const client of clients) {\n client.invalidateAllInfinite(query as InfiniteQuery<Args, TPage, TItem>)\n }\n },\n\n setData(...rest: [...Args, updater: (prev: TPage[] | undefined) => TPage[]]): Snapshot {\n const updater = rest[rest.length - 1] as (prev: TPage[] | undefined) => TPage[]\n const keyArgs = rest.slice(0, -1) as unknown as Args\n const childSnapshots: Snapshot[] = []\n for (const client of clients) {\n childSnapshots.push(\n client.setInfiniteData<Args, TPage>(\n query as InfiniteQuery<Args, TPage, TItem>,\n keyArgs,\n updater,\n ),\n )\n }\n return {\n rollback: () => {\n for (const s of childSnapshots) s.rollback()\n },\n finalize: () => {\n for (const s of childSnapshots) s.finalize()\n },\n }\n },\n\n prefetch(...args: Args): Promise<TPage> {\n const [first] = clients\n if (!first) {\n return Promise.reject(new Error('[olas] prefetch called before any root has subscribed'))\n }\n if (__DEV__ && clients.size > 1) {\n // eslint-disable-next-line no-console\n console.warn(\n '[olas] infiniteQuery.prefetch() is ambiguous when multiple roots are registered; ' +\n 'using an arbitrary root. Call `root.prefetch(query, args)` (or per-root) to be explicit.',\n )\n }\n return first.prefetchInfinite(query as InfiniteQuery<Args, TPage, TItem>, args)\n },\n } satisfies InfiniteQueryInternal<Args, TPage, TItem>\n\n registerQueryId(spec, query)\n return query as InfiniteQuery<Args, TPage, TItem>\n}\n","/**\n * Typed cross-tree data slot. Provided by an ancestor via `ctx.provide(scope, value)`\n * and consumed anywhere in its subtree via `ctx.inject(scope)`. Defined at module\n * scope so the identity is stable across calls. See spec §10.3.\n */\nexport type Scope<T> = {\n readonly __olas: 'scope'\n /** Per-scope identity; matches across `provide` / `inject`. */\n readonly __id: symbol\n /** Optional human-readable name (used in error messages). */\n readonly name?: string\n /** Default value used when no provider exists; `undefined` if none was set. */\n readonly default?: T\n /** True iff `defineScope` was called with a `default` (even `default: undefined`). */\n readonly hasDefault: boolean\n // Phantom for inference — typed `T` is preserved through the scope's lifetime.\n readonly __t?: T\n}\n\nexport type ScopeOptions<T> = {\n default?: T\n name?: string\n}\n\n/**\n * Create a scope. The returned value is the typed handle passed to\n * `ctx.provide(scope, value)` and `ctx.inject(scope)`. Identity is keyed by\n * an internal symbol so two `defineScope()` calls — even with identical\n * options — yield distinct scopes.\n */\nexport function defineScope<T>(options?: ScopeOptions<T>): Scope<T> {\n const hasDefault = options !== undefined && 'default' in options\n const name = options?.name\n const scope: Scope<T> = {\n __olas: 'scope',\n __id: Symbol(name ?? 'scope'),\n hasDefault,\n ...(name !== undefined ? { name } : {}),\n ...(hasDefault ? { default: options?.default as T } : {}),\n }\n return scope\n}\n","import { computed, signal } from './signals'\nimport { readOnly } from './signals/readonly'\nimport type { ReadSignal } from './signals/types'\n\n/**\n * Multi-select state for tables / lists with bulk actions (spec §17.5).\n *\n * Plain function — not bound to `ctx`. Place it in a controller's closure so\n * it dies with the closure. The phantom `T` parameter brands the selection by\n * item type; IDs are always strings.\n */\n// biome-ignore lint/correctness/noUnusedVariables: phantom branding param (spec §17.5)\nexport type Selection<T = unknown> = {\n selectedIds: ReadSignal<ReadonlySet<string>>\n size: ReadSignal<number>\n isSelected(id: string): ReadSignal<boolean>\n\n select(id: string): void\n deselect(id: string): void\n toggle(id: string): void\n clear(): void\n selectAll(ids: readonly string[]): void\n\n handleClick(\n id: string,\n mods: { shift?: boolean; meta?: boolean },\n ordered: readonly string[],\n ): void\n}\n\n/**\n * Create a `Selection<T>`. Optional `initial` seeds the selected set.\n *\n * `handleClick` encapsulates the standard click semantics:\n * - plain click → select only `id` (anchor moves to `id`)\n * - meta-click → toggle `id` (anchor moves to `id` on add)\n * - shift-click → range from anchor to `id` along `ordered` (anchor sticks,\n * so subsequent shift-clicks extend from the same origin)\n *\n * Spec §16.5 / §17.5.\n */\nexport function selection<T = unknown>(options?: { initial?: readonly string[] }): Selection<T> {\n const ids = signal<ReadonlySet<string>>(new Set(options?.initial))\n let anchor: string | null = options?.initial?.length\n ? (options.initial[options.initial.length - 1] ?? null)\n : null\n // Snapshot of the selection just before the first shift-click of a run.\n // Subsequent shift-clicks re-compute the range against this snapshot so the\n // user can shrink or grow the range. Reset on any non-shift click.\n let preShiftSelection: ReadonlySet<string> | null = null\n\n const size = computed(() => ids.value.size)\n\n const isSelected = (id: string): ReadSignal<boolean> => computed(() => ids.value.has(id))\n\n const select = (id: string): void => {\n const prev = ids.peek()\n if (!prev.has(id)) {\n const next = new Set(prev)\n next.add(id)\n ids.set(next)\n }\n anchor = id\n }\n\n const deselect = (id: string): void => {\n const prev = ids.peek()\n if (!prev.has(id)) return\n const next = new Set(prev)\n next.delete(id)\n ids.set(next)\n }\n\n const toggle = (id: string): void => {\n const prev = ids.peek()\n const next = new Set(prev)\n if (prev.has(id)) {\n next.delete(id)\n } else {\n next.add(id)\n anchor = id\n }\n ids.set(next)\n }\n\n const clear = (): void => {\n if (ids.peek().size === 0) {\n anchor = null\n return\n }\n ids.set(new Set())\n anchor = null\n }\n\n const selectAll = (incoming: readonly string[]): void => {\n ids.set(new Set(incoming))\n anchor = incoming.length > 0 ? (incoming[incoming.length - 1] ?? null) : null\n }\n\n const handleClick = (\n id: string,\n mods: { shift?: boolean; meta?: boolean },\n ordered: readonly string[],\n ): void => {\n if (mods.shift && anchor !== null) {\n const anchorIdx = ordered.indexOf(anchor)\n const targetIdx = ordered.indexOf(id)\n if (anchorIdx === -1 || targetIdx === -1) {\n // anchor or target not visible — fall back to plain select\n ids.set(new Set([id]))\n anchor = id\n preShiftSelection = null\n return\n }\n if (preShiftSelection === null) {\n preShiftSelection = ids.peek()\n }\n const [lo, hi] = anchorIdx < targetIdx ? [anchorIdx, targetIdx] : [targetIdx, anchorIdx]\n const next = new Set(preShiftSelection)\n for (const k of ordered.slice(lo, hi + 1)) next.add(k)\n ids.set(next)\n // Anchor stays — subsequent shift-clicks extend from the same origin.\n return\n }\n // Any non-shift click ends the shift run.\n preShiftSelection = null\n if (mods.meta) {\n toggle(id)\n return\n }\n ids.set(new Set([id]))\n anchor = id\n }\n\n return {\n selectedIds: readOnly(ids),\n size,\n isSelected,\n select,\n deselect,\n toggle,\n clear,\n selectAll,\n handleClick,\n }\n}\n","import { effect, signal } from '../signals'\nimport type { ReadSignal } from '../signals/types'\n\n/**\n * Lag a signal by `ms`. The returned signal updates only after the source has\n * been unchanged for `ms`. Each new write resets the timer.\n *\n * Pass `options.signal` (an `AbortSignal`) to tie the internal effect to a\n * lifecycle — when the signal aborts the effect disposes, the pending timer\n * clears, and the subscriber chain on `source` drops. Without `signal`, the\n * effect lives as long as `source` does; pass a signal whenever the source\n * outlives the consumer.\n */\nexport function debounced<T>(\n source: ReadSignal<T>,\n ms: number,\n options?: { signal?: AbortSignal },\n): ReadSignal<T> {\n const out = signal<T>(source.peek())\n let timer: ReturnType<typeof setTimeout> | null = null\n let initial = true\n\n const dispose = effect(() => {\n const value = source.value\n if (initial) {\n // The first effect run reads the source for tracking; we already\n // initialized `out` to the same value, so skip scheduling.\n initial = false\n return\n }\n if (timer != null) clearTimeout(timer)\n timer = setTimeout(() => {\n out.set(value)\n timer = null\n }, ms)\n })\n\n const sig = options?.signal\n if (sig) {\n const stop = () => {\n if (timer != null) {\n clearTimeout(timer)\n timer = null\n }\n dispose()\n }\n if (sig.aborted) stop()\n else sig.addEventListener('abort', stop, { once: true })\n }\n\n return out\n}\n","import { effect, signal } from '../signals'\nimport type { ReadSignal } from '../signals/types'\n\n/**\n * Rate-limit a signal so it emits at most once per `ms` (leading + trailing).\n * The first change passes through immediately. Subsequent changes within the\n * window are coalesced; the latest value is emitted when the window expires.\n *\n * Pass `options.signal` to tie the internal effect to a lifecycle — when the\n * signal aborts the effect disposes and any pending trailing timer clears.\n * Without `signal`, the effect lives as long as `source` does.\n */\nexport function throttled<T>(\n source: ReadSignal<T>,\n ms: number,\n options?: { signal?: AbortSignal },\n): ReadSignal<T> {\n const out = signal<T>(source.peek())\n let lastEmit = Number.NEGATIVE_INFINITY\n let trailingTimer: ReturnType<typeof setTimeout> | null = null\n let trailingValue: T = source.peek()\n let initial = true\n\n const dispose = effect(() => {\n const value = source.value\n if (initial) {\n initial = false\n return\n }\n const now = Date.now()\n const elapsed = now - lastEmit\n if (elapsed >= ms) {\n out.set(value)\n lastEmit = now\n if (trailingTimer != null) {\n clearTimeout(trailingTimer)\n trailingTimer = null\n }\n } else {\n trailingValue = value\n if (trailingTimer == null) {\n trailingTimer = setTimeout(() => {\n out.set(trailingValue)\n lastEmit = Date.now()\n trailingTimer = null\n }, ms - elapsed)\n }\n }\n })\n\n const sig = options?.signal\n if (sig) {\n const stop = () => {\n if (trailingTimer != null) {\n clearTimeout(trailingTimer)\n trailingTimer = null\n }\n dispose()\n }\n if (sig.aborted) stop()\n else sig.addEventListener('abort', stop, { once: true })\n }\n\n return out\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,SAAY,QAAsC;CAChE,OAAO,OAAO,OAAO;EACnB,IAAI,QAAQ;GACV,OAAO,OAAO;EAChB;EACA,OAAO;GACL,OAAO,OAAO,KAAK;EACrB;EACA,UAAU,SAA6B;GACrC,OAAO,OAAO,UAAU,OAAO;EACjC;CACF,CAAC;AACH;;;ACnBA,MAAM,WAAW,UAA4B;CAC3C,IAAI,UAAU,KAAA,KAAa,UAAU,MAAM,OAAO;CAClD,IAAI,OAAO,UAAU,UAAU,OAAO,MAAM,WAAW;CACvD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,WAAW;CAClD,OAAO;AACT;;AAGA,MAAa,YACP,UAAU,gBACb,UACC,QAAQ,KAAK,IAAI,UAAU;;AAG/B,MAAa,aACV,GAAW,aACX,UAAU;CACT,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI,MAAM,UAAU,GAAG,OAAO;CAC9B,OAAO,WAAW,oBAAoB,EAAE;AAC1C;;AAGF,MAAa,aACV,GAAW,aACX,UAAU;CACT,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI,MAAM,UAAU,GAAG,OAAO;CAC9B,OAAO,WAAW,wBAAwB,EAAE;AAC9C;;AAGF,MAAa,OACV,GAAW,aACX,UAAU;CACT,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI,SAAS,GAAG,OAAO;CACvB,OAAO,WAAW,oBAAoB;AACxC;;AAGF,MAAa,OACV,GAAW,aACX,UAAU;CACT,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI,SAAS,GAAG,OAAO;CACvB,OAAO,WAAW,wBAAwB;AAC5C;AAIF,MAAM,WAAW;;AAGjB,MAAa,SACV,UAAU,6BACV,UAAU;CACT,IAAI,SAAS,QAAQ,UAAU,IAAI,OAAO;CAC1C,OAAO,SAAS,KAAK,KAAK,IAAI,OAAO;AACvC;;AAGF,MAAa,WACV,IAAY,UAAU,sBACtB,UAAU;CACT,IAAI,SAAS,QAAQ,UAAU,IAAI,OAAO;CAC1C,OAAO,GAAG,KAAK,KAAK,IAAI,OAAO;AACjC;;;ACzDF,SAAS,gBAAgB,MAAgD,OAAqB;CAC5F,IAAI,KAAK,WAAW,MAClB,aAAA,kBAAkB,KAAK,SAAS,KAAwB;MACnD,IAAI,KAAK,aAAa,MAAM,CAUnC;AACF;;;;;AAMA,SAAgB,YAAuC,MAA0C;CAC/F,MAAM,0BAAU,IAAI,IAAiB;CACrC,MAAM,QAAQ;EACZ,QAAQ;EACR,QAAQ;EACR,WAAW;EAEX,WAAW,GAAG,MAAkB;GAC9B,KAAK,MAAM,UAAU,SACnB,OAAO,WAAW,OAAyB,IAAI;EAEnD;EAEA,gBAAsB;GACpB,KAAK,MAAM,UAAU,SACnB,OAAO,cAAc,KAAuB;EAEhD;EAEA,QAAQ,GAAG,MAAgE;GACzE,MAAM,UAAU,KAAK,KAAK,SAAS;GACnC,MAAM,UAAU,KAAK,MAAM,GAAG,EAAE;GAChC,MAAM,iBAA6B,CAAC;GACpC,KAAK,MAAM,UAAU,SACnB,eAAe,KAAK,OAAO,QAAQ,OAAyB,SAAS,OAAO,CAAC;GAE/E,OAAO;IACL,gBAAgB;KACd,KAAK,MAAM,KAAK,gBAAgB,EAAE,SAAS;IAC7C;IACA,gBAAgB;KACd,KAAK,MAAM,KAAK,gBAAgB,EAAE,SAAS;IAC7C;GACF;EACF;EAEA,SAAS,GAAG,MAAwB;GAElC,MAAM,CAAC,SAAS;GAChB,IAAI,CAAC,OACH,OAAO,QAAQ,uBAAO,IAAI,MAAM,uDAAuD,CAAC;GAS1F,OAAO,MAAM,SAAS,OAAyB,IAAI;EACrD;CACF;CAEA,gBAAgB,MAAM,KAAK;CAC3B,OAAO;AACT;;;;;;;;AAkBA,SAAgB,oBACd,MACmC;CACnC,MAAM,0BAAU,IAAI,IAAiB;CACrC,MAAM,QAAQ;EACZ,QAAQ;EACR,QAAQ;EACR,WAAW;EAEX,WAAW,GAAG,MAAkB;GAC9B,KAAK,MAAM,UAAU,SACnB,OAAO,mBAAmB,OAA4C,IAAI;EAE9E;EAEA,gBAAsB;GACpB,KAAK,MAAM,UAAU,SACnB,OAAO,sBAAsB,KAA0C;EAE3E;EAEA,QAAQ,GAAG,MAA4E;GACrF,MAAM,UAAU,KAAK,KAAK,SAAS;GACnC,MAAM,UAAU,KAAK,MAAM,GAAG,EAAE;GAChC,MAAM,iBAA6B,CAAC;GACpC,KAAK,MAAM,UAAU,SACnB,eAAe,KACb,OAAO,gBACL,OACA,SACA,OACF,CACF;GAEF,OAAO;IACL,gBAAgB;KACd,KAAK,MAAM,KAAK,gBAAgB,EAAE,SAAS;IAC7C;IACA,gBAAgB;KACd,KAAK,MAAM,KAAK,gBAAgB,EAAE,SAAS;IAC7C;GACF;EACF;EAEA,SAAS,GAAG,MAA4B;GACtC,MAAM,CAAC,SAAS;GAChB,IAAI,CAAC,OACH,OAAO,QAAQ,uBAAO,IAAI,MAAM,uDAAuD,CAAC;GAS1F,OAAO,MAAM,iBAAiB,OAA4C,IAAI;EAChF;CACF;CAEA,gBAAgB,MAAM,KAAK;CAC3B,OAAO;AACT;;;;;;;;;ACzIA,SAAgB,YAAe,SAAqC;CAClE,MAAM,aAAa,YAAY,KAAA,KAAa,aAAa;CACzD,MAAM,OAAO,SAAS;CAQtB,OAAO;EANL,QAAQ;EACR,MAAM,OAAO,QAAQ,OAAO;EAC5B;EACA,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,aAAa,EAAE,SAAS,SAAS,QAAa,IAAI,CAAC;CAE9C;AACb;;;;;;;;;;;;;;ACAA,SAAgB,UAAuB,SAAyD;CAC9F,MAAM,MAAMA,aAAAA,OAA4B,IAAI,IAAI,SAAS,OAAO,CAAC;CACjE,IAAI,SAAwB,SAAS,SAAS,SACzC,QAAQ,QAAQ,QAAQ,QAAQ,SAAS,MAAM,OAChD;CAIJ,IAAI,oBAAgD;CAEpD,MAAM,OAAOC,aAAAA,eAAe,IAAI,MAAM,IAAI;CAE1C,MAAM,cAAc,OAAoCA,aAAAA,eAAe,IAAI,MAAM,IAAI,EAAE,CAAC;CAExF,MAAM,UAAU,OAAqB;EACnC,MAAM,OAAO,IAAI,KAAK;EACtB,IAAI,CAAC,KAAK,IAAI,EAAE,GAAG;GACjB,MAAM,OAAO,IAAI,IAAI,IAAI;GACzB,KAAK,IAAI,EAAE;GACX,IAAI,IAAI,IAAI;EACd;EACA,SAAS;CACX;CAEA,MAAM,YAAY,OAAqB;EACrC,MAAM,OAAO,IAAI,KAAK;EACtB,IAAI,CAAC,KAAK,IAAI,EAAE,GAAG;EACnB,MAAM,OAAO,IAAI,IAAI,IAAI;EACzB,KAAK,OAAO,EAAE;EACd,IAAI,IAAI,IAAI;CACd;CAEA,MAAM,UAAU,OAAqB;EACnC,MAAM,OAAO,IAAI,KAAK;EACtB,MAAM,OAAO,IAAI,IAAI,IAAI;EACzB,IAAI,KAAK,IAAI,EAAE,GACb,KAAK,OAAO,EAAE;OACT;GACL,KAAK,IAAI,EAAE;GACX,SAAS;EACX;EACA,IAAI,IAAI,IAAI;CACd;CAEA,MAAM,cAAoB;EACxB,IAAI,IAAI,KAAK,EAAE,SAAS,GAAG;GACzB,SAAS;GACT;EACF;EACA,IAAI,oBAAI,IAAI,IAAI,CAAC;EACjB,SAAS;CACX;CAEA,MAAM,aAAa,aAAsC;EACvD,IAAI,IAAI,IAAI,IAAI,QAAQ,CAAC;EACzB,SAAS,SAAS,SAAS,IAAK,SAAS,SAAS,SAAS,MAAM,OAAQ;CAC3E;CAEA,MAAM,eACJ,IACA,MACA,YACS;EACT,IAAI,KAAK,SAAS,WAAW,MAAM;GACjC,MAAM,YAAY,QAAQ,QAAQ,MAAM;GACxC,MAAM,YAAY,QAAQ,QAAQ,EAAE;GACpC,IAAI,cAAc,MAAM,cAAc,IAAI;IAExC,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACrB,SAAS;IACT,oBAAoB;IACpB;GACF;GACA,IAAI,sBAAsB,MACxB,oBAAoB,IAAI,KAAK;GAE/B,MAAM,CAAC,IAAI,MAAM,YAAY,YAAY,CAAC,WAAW,SAAS,IAAI,CAAC,WAAW,SAAS;GACvF,MAAM,OAAO,IAAI,IAAI,iBAAiB;GACtC,KAAK,MAAM,KAAK,QAAQ,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC;GACrD,IAAI,IAAI,IAAI;GAEZ;EACF;EAEA,oBAAoB;EACpB,IAAI,KAAK,MAAM;GACb,OAAO,EAAE;GACT;EACF;EACA,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;EACrB,SAAS;CACX;CAEA,OAAO;EACL,aAAa,SAAS,GAAG;EACzB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;;;;;;;;;;ACpIA,SAAgB,UACd,QACA,IACA,SACe;CACf,MAAM,MAAMC,aAAAA,OAAU,OAAO,KAAK,CAAC;CACnC,IAAI,QAA8C;CAClD,IAAI,UAAU;CAEd,MAAM,UAAUC,aAAAA,aAAa;EAC3B,MAAM,QAAQ,OAAO;EACrB,IAAI,SAAS;GAGX,UAAU;GACV;EACF;EACA,IAAI,SAAS,MAAM,aAAa,KAAK;EACrC,QAAQ,iBAAiB;GACvB,IAAI,IAAI,KAAK;GACb,QAAQ;EACV,GAAG,EAAE;CACP,CAAC;CAED,MAAM,MAAM,SAAS;CACrB,IAAI,KAAK;EACP,MAAM,aAAa;GACjB,IAAI,SAAS,MAAM;IACjB,aAAa,KAAK;IAClB,QAAQ;GACV;GACA,QAAQ;EACV;EACA,IAAI,IAAI,SAAS,KAAK;OACjB,IAAI,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;CACzD;CAEA,OAAO;AACT;;;;;;;;;;;;ACvCA,SAAgB,UACd,QACA,IACA,SACe;CACf,MAAM,MAAMC,aAAAA,OAAU,OAAO,KAAK,CAAC;CACnC,IAAI,WAAW,OAAO;CACtB,IAAI,gBAAsD;CAC1D,IAAI,gBAAmB,OAAO,KAAK;CACnC,IAAI,UAAU;CAEd,MAAM,UAAUC,aAAAA,aAAa;EAC3B,MAAM,QAAQ,OAAO;EACrB,IAAI,SAAS;GACX,UAAU;GACV;EACF;EACA,MAAM,MAAM,KAAK,IAAI;EACrB,MAAM,UAAU,MAAM;EACtB,IAAI,WAAW,IAAI;GACjB,IAAI,IAAI,KAAK;GACb,WAAW;GACX,IAAI,iBAAiB,MAAM;IACzB,aAAa,aAAa;IAC1B,gBAAgB;GAClB;EACF,OAAO;GACL,gBAAgB;GAChB,IAAI,iBAAiB,MACnB,gBAAgB,iBAAiB;IAC/B,IAAI,IAAI,aAAa;IACrB,WAAW,KAAK,IAAI;IACpB,gBAAgB;GAClB,GAAG,KAAK,OAAO;EAEnB;CACF,CAAC;CAED,MAAM,MAAM,SAAS;CACrB,IAAI,KAAK;EACP,MAAM,aAAa;GACjB,IAAI,iBAAiB,MAAM;IACzB,aAAa,aAAa;IAC1B,gBAAgB;GAClB;GACA,QAAQ;EACV;EACA,IAAI,IAAI,SAAS,KAAK;OACjB,IAAI,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;CACzD;CAEA,OAAO;AACT"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as FormErrors, A as DebugEvent, B as QuerySpec, C as SetDataEvent, D as MutationSpec, E as MutationConcurrency, F as AsyncStatus, G as UseOptions, H as RetryDelay, I as DehydratedEntry, J as FieldArrayItemErrors, K as DeepPartial, L as DehydratedState, M as InfiniteQuerySpec, N as InfiniteQuerySubscription, O as DebugBus, P as AsyncState, Q as Form, R as LocalCache, S as RegisteredQuery, T as Mutation, U as RetryPolicy, V as QuerySubscription, W as Snapshot, X as FieldArrayValidator, Y as FieldArrayOptions, Z as FieldArrayValue, _ as defineScope, a as CollectionFactoryResult, at as Validator, b as QueryClientPlugin, c as CtrlApi, ct as Signal, d as Field, dt as EmitterErrorReporter, et as FormOptions, f as LazyChild, ft as createEmitter, g as ScopeOptions, h as Scope, i as CollectionFactoryOptions, it as ItemInitial, j as InfiniteQuery, k as DebugCacheEntry, l as CtrlProps, lt as ErrorContext, m as RootOptions, n as Collection, nt as FormValidator, o as CollectionHomogeneousOptions, ot as Computed, p as Root, q as FieldArray, r as CollectionFactoryApi, rt as FormValue, s as ControllerDef, st as ReadSignal, t as AmbientDeps, tt as FormSchema, u as Ctx, ut as Emitter, v as GcEvent, w as lookupRegisteredQuery, x as QueryClientPluginApi, y as InvalidateEvent, z as Query } from "./types-DKfpkm17.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/signals/runtime.d.ts
|
|
4
4
|
/**
|
|
@@ -107,6 +107,17 @@ declare function defineQuery<Args extends unknown[], T>(spec: QuerySpec<Args, T>
|
|
|
107
107
|
*/
|
|
108
108
|
declare function defineInfiniteQuery<Args extends unknown[], PageParam, TPage, TItem = TPage>(spec: InfiniteQuerySpec<Args, PageParam, TPage, TItem>): InfiniteQuery<Args, TPage, TItem>;
|
|
109
109
|
//#endregion
|
|
110
|
+
//#region src/query/keys.d.ts
|
|
111
|
+
/**
|
|
112
|
+
* Stable string hash of a key tuple. Two equal-by-content args produce the
|
|
113
|
+
* same string regardless of property iteration order. Handles primitives,
|
|
114
|
+
* arrays, plain objects, Date.
|
|
115
|
+
*
|
|
116
|
+
* Functions and symbols throw — keys must be serializable so distinct
|
|
117
|
+
* subscribers can share entries.
|
|
118
|
+
*/
|
|
119
|
+
declare function stableHash(args: readonly unknown[]): string;
|
|
120
|
+
//#endregion
|
|
110
121
|
//#region src/selection.d.ts
|
|
111
122
|
/**
|
|
112
123
|
* Multi-select state for tables / lists with bulk actions (spec §17.5).
|
|
@@ -149,10 +160,15 @@ declare function selection<T = unknown>(options?: {
|
|
|
149
160
|
* Lag a signal by `ms`. The returned signal updates only after the source has
|
|
150
161
|
* been unchanged for `ms`. Each new write resets the timer.
|
|
151
162
|
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
163
|
+
* Pass `options.signal` (an `AbortSignal`) to tie the internal effect to a
|
|
164
|
+
* lifecycle — when the signal aborts the effect disposes, the pending timer
|
|
165
|
+
* clears, and the subscriber chain on `source` drops. Without `signal`, the
|
|
166
|
+
* effect lives as long as `source` does; pass a signal whenever the source
|
|
167
|
+
* outlives the consumer.
|
|
154
168
|
*/
|
|
155
|
-
declare function debounced<T>(source: ReadSignal<T>, ms: number
|
|
169
|
+
declare function debounced<T>(source: ReadSignal<T>, ms: number, options?: {
|
|
170
|
+
signal?: AbortSignal;
|
|
171
|
+
}): ReadSignal<T>;
|
|
156
172
|
//#endregion
|
|
157
173
|
//#region src/timing/throttled.d.ts
|
|
158
174
|
/**
|
|
@@ -160,19 +176,24 @@ declare function debounced<T>(source: ReadSignal<T>, ms: number): ReadSignal<T>;
|
|
|
160
176
|
* The first change passes through immediately. Subsequent changes within the
|
|
161
177
|
* window are coalesced; the latest value is emitted when the window expires.
|
|
162
178
|
*
|
|
163
|
-
*
|
|
179
|
+
* Pass `options.signal` to tie the internal effect to a lifecycle — when the
|
|
180
|
+
* signal aborts the effect disposes and any pending trailing timer clears.
|
|
181
|
+
* Without `signal`, the effect lives as long as `source` does.
|
|
164
182
|
*/
|
|
165
|
-
declare function throttled<T>(source: ReadSignal<T>, ms: number
|
|
183
|
+
declare function throttled<T>(source: ReadSignal<T>, ms: number, options?: {
|
|
184
|
+
signal?: AbortSignal;
|
|
185
|
+
}): ReadSignal<T>;
|
|
166
186
|
//#endregion
|
|
167
187
|
//#region src/utils.d.ts
|
|
168
188
|
/**
|
|
169
|
-
* True iff `err`
|
|
170
|
-
*
|
|
189
|
+
* True iff `err` looks like an AbortError. Matches the standard `DOMException`
|
|
190
|
+
* shape thrown by `AbortController` AND any object whose `name === 'AbortError'`
|
|
191
|
+
* — that covers axios / msw / user-thrown plain Errors that signal abort.
|
|
171
192
|
*
|
|
172
|
-
* Spec: §20.12
|
|
173
|
-
*
|
|
193
|
+
* Spec: §20.12. Node 17+ exposes a global DOMException, so the instanceof
|
|
194
|
+
* branch works server-side; the name-based branch is the portable fallback.
|
|
174
195
|
*/
|
|
175
196
|
declare function isAbortError(err: unknown): boolean;
|
|
176
197
|
//#endregion
|
|
177
|
-
export { type AmbientDeps, type AsyncState, type AsyncStatus, type Computed, type ControllerDef, type CtrlApi, type CtrlProps, type Ctx, type DebugBus, type DebugCacheEntry, type DebugEvent, type DeepPartial, type DehydratedEntry, type DehydratedState, type Emitter, type ErrorContext, type Field, type FieldArray, type FieldArrayItemErrors, type FieldArrayOptions, type FieldArrayValidator, type FieldArrayValue, type Form, type FormErrors, type FormOptions, type FormSchema, type FormValidator, type FormValue, type GcEvent, type InfiniteQuery, type InfiniteQuerySpec, type InfiniteQuerySubscription, type InvalidateEvent, type ItemInitial, type LocalCache, type Mutation, type MutationConcurrency, type MutationSpec, type Query, type QueryClientPlugin, type QueryClientPluginApi, type QuerySpec, type QuerySubscription, type ReadSignal, type RegisteredQuery, type RetryDelay, type RetryPolicy, type Root, type RootOptions, type Scope, type ScopeOptions, type Selection, type SetDataEvent, type Signal, type Snapshot, type UseOptions, type Validator, batch, computed, createEmitter, createRoot, debounced, debouncedValidator, defineController, defineInfiniteQuery, defineQuery, defineScope, effect, email, isAbortError, lookupRegisteredQuery, max, maxLength, min, minLength, pattern, required, selection, signal, throttled, untracked };
|
|
198
|
+
export { type AmbientDeps, type AsyncState, type AsyncStatus, type Collection, type CollectionFactoryApi, type CollectionFactoryOptions, type CollectionFactoryResult, type CollectionHomogeneousOptions, type Computed, type ControllerDef, type CtrlApi, type CtrlProps, type Ctx, type DebugBus, type DebugCacheEntry, type DebugEvent, type DeepPartial, type DehydratedEntry, type DehydratedState, type Emitter, type EmitterErrorReporter, type ErrorContext, type Field, type FieldArray, type FieldArrayItemErrors, type FieldArrayOptions, type FieldArrayValidator, type FieldArrayValue, type Form, type FormErrors, type FormOptions, type FormSchema, type FormValidator, type FormValue, type GcEvent, type InfiniteQuery, type InfiniteQuerySpec, type InfiniteQuerySubscription, type InvalidateEvent, type ItemInitial, type LazyChild, type LocalCache, type Mutation, type MutationConcurrency, type MutationSpec, type Query, type QueryClientPlugin, type QueryClientPluginApi, type QuerySpec, type QuerySubscription, type ReadSignal, type RegisteredQuery, type RetryDelay, type RetryPolicy, type Root, type RootOptions, type Scope, type ScopeOptions, type Selection, type SetDataEvent, type Signal, type Snapshot, type UseOptions, type Validator, batch, computed, createEmitter, createRoot, debounced, debouncedValidator, defineController, defineInfiniteQuery, defineQuery, defineScope, effect, email, isAbortError, lookupRegisteredQuery, max, maxLength, min, minLength, pattern, required, selection, signal, stableHash, throttled, untracked };
|
|
178
199
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/signals/runtime.ts","../src/controller/define.ts","../src/controller/root.ts","../src/forms/validators.ts","../src/forms/field.ts","../src/query/define.ts","../src/selection.ts","../src/timing/debounced.ts","../src/timing/throttled.ts","../src/utils.ts"],"mappings":";;;;;AAsEA;;;;iBAAgB,MAAA,GAAA,CAAU,OAAA,EAAS,CAAA,GAAI,MAAA,CAAO,CAAA;;;;;;;;;iBAY9B,QAAA,GAAA,CAAY,EAAA,QAAU,CAAA,GAAI,QAAA,CAAS,CAAA;AAZJ;AAY/C;;;;;;;AAZ+C,iBAwB/B,MAAA,CAAO,EAA6B;;;;;iBAQpC,KAAA,GAAA,CAAS,EAAA,QAAU,CAAA,GAAI,CAAC;;AApBY;AAYpD;;;;iBAkBgB,SAAA,GAAA,CAAa,EAAA,QAAU,CAAA,GAAI,CAAC;;;;KCxGhC,uBAAA;ED8DI;;;;;;;;ECrDd,IAAI;AAAA;;;;;ADqDyC;AAY/C;;iBCvDgB,gBAAA,6BAAA,CACd,OAAA,GAAU,GAAA,EAAK,GAAA,EAAK,KAAA,EAAO,KAAA,KAAU,GAAA,EACrC,OAAA,GAAU,uBAAA,GACT,aAAA,CAAc,KAAA,EAAO,GAAA;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/signals/runtime.ts","../src/controller/define.ts","../src/controller/root.ts","../src/forms/validators.ts","../src/forms/field.ts","../src/query/define.ts","../src/query/keys.ts","../src/selection.ts","../src/timing/debounced.ts","../src/timing/throttled.ts","../src/utils.ts"],"mappings":";;;;;AAsEA;;;;iBAAgB,MAAA,GAAA,CAAU,OAAA,EAAS,CAAA,GAAI,MAAA,CAAO,CAAA;;;;;;;;;iBAY9B,QAAA,GAAA,CAAY,EAAA,QAAU,CAAA,GAAI,QAAA,CAAS,CAAA;AAZJ;AAY/C;;;;;;;AAZ+C,iBAwB/B,MAAA,CAAO,EAA6B;;;;;iBAQpC,KAAA,GAAA,CAAS,EAAA,QAAU,CAAA,GAAI,CAAC;;AApBY;AAYpD;;;;iBAkBgB,SAAA,GAAA,CAAa,EAAA,QAAU,CAAA,GAAI,CAAC;;;;KCxGhC,uBAAA;ED8DI;;;;;;;;ECrDd,IAAI;AAAA;;;;;ADqDyC;AAY/C;;iBCvDgB,gBAAA,6BAAA,CACd,OAAA,GAAU,GAAA,EAAK,GAAA,EAAK,KAAA,EAAO,KAAA,KAAU,GAAA,EACrC,OAAA,GAAU,uBAAA,GACT,aAAA,CAAc,KAAA,EAAO,GAAA;;;;;;;iBCoIR,UAAA,oBAA8B,MAAA,oBAA0B,WAAA,CAAA,CACtE,GAAA,EAAK,aAAA,OAAoB,GAAA,GACzB,OAAA,EAAS,WAAA,CAAY,KAAA,IACpB,IAAA,CAAK,GAAA;;;;cC3JK,QAAA,MACP,OAAA,cAAuB,SAAS,CAAC,CAAA;AH2DvC;AAAA,cGtDa,SAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAQ7B,SAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAQ7B,GAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAQ7B,GAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAY7B,KAAA,GACV,OAAA,cAAoC,SAAS;;cAOnC,OAAA,GACV,EAAA,EAAI,MAAA,EAAQ,OAAA,cAA6B,SAAS;;;;;;;;iBCyRrC,kBAAA,GAAA,CACd,EAAA,GAAK,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,WAAA,KAAgB,OAAA,iBACvC,EAAA,WACC,SAAA,CAAU,CAAA;;;;AJvRb;;;iBKtCgB,WAAA,2BAAA,CAAuC,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,CAAA,IAAK,KAAA,CAAM,IAAA,EAAM,CAAA;;;;;;;;iBAyE9E,mBAAA,mDAAsE,KAAA,CAAA,CACpF,IAAA,EAAM,iBAAA,CAAkB,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,KAAA,IAC/C,aAAA,CAAc,IAAA,EAAM,KAAA,EAAO,KAAA;;;;;;ALrC9B;;;;;iBM9DgB,UAAA,CAAW,IAAwB;;;;;AN8DnD;;;;;KO1DY,SAAA;EACV,WAAA,EAAa,UAAA,CAAW,WAAA;EACxB,IAAA,EAAM,UAAA;EACN,UAAA,CAAW,EAAA,WAAa,UAAA;EAExB,MAAA,CAAO,EAAA;EACP,QAAA,CAAS,EAAA;EACT,MAAA,CAAO,EAAA;EACP,KAAA;EACA,SAAA,CAAU,GAAA;EAEV,WAAA,CACE,EAAA,UACA,IAAA;IAAQ,KAAA;IAAiB,IAAA;EAAA,GACzB,OAAA;AAAA;;;;;;;;;;;APwDgD;iBOzCpC,SAAA,aAAA,CAAuB,OAAA;EAAY,OAAA;AAAA,IAAgC,SAAS,CAAC,CAAA;;;;;AP6B7F;;;;;;;;iBQzDgB,SAAA,GAAA,CACd,MAAA,EAAQ,UAAA,CAAW,CAAA,GACnB,EAAA,UACA,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,UAAA,CAAW,CAAA;;;;;ARqDd;;;;;;;iBS1DgB,SAAA,GAAA,CACd,MAAA,EAAQ,UAAA,CAAW,CAAA,GACnB,EAAA,UACA,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,UAAA,CAAW,CAAA;;;;;;ATsDd;;;;;iBU9DgB,YAAA,CAAa,GAAY"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as FormErrors, A as DebugEvent, B as QuerySpec, C as SetDataEvent, D as MutationSpec, E as MutationConcurrency, F as AsyncStatus, G as UseOptions, H as RetryDelay, I as DehydratedEntry, J as FieldArrayItemErrors, K as DeepPartial, L as DehydratedState, M as InfiniteQuerySpec, N as InfiniteQuerySubscription, O as DebugBus, P as AsyncState, Q as Form, R as LocalCache, S as RegisteredQuery, T as Mutation, U as RetryPolicy, V as QuerySubscription, W as Snapshot, X as FieldArrayValidator, Y as FieldArrayOptions, Z as FieldArrayValue, _ as defineScope, a as CollectionFactoryResult, at as Validator, b as QueryClientPlugin, c as CtrlApi, ct as Signal, d as Field, dt as EmitterErrorReporter, et as FormOptions, f as LazyChild, ft as createEmitter, g as ScopeOptions, h as Scope, i as CollectionFactoryOptions, it as ItemInitial, j as InfiniteQuery, k as DebugCacheEntry, l as CtrlProps, lt as ErrorContext, m as RootOptions, n as Collection, nt as FormValidator, o as CollectionHomogeneousOptions, ot as Computed, p as Root, q as FieldArray, r as CollectionFactoryApi, rt as FormValue, s as ControllerDef, st as ReadSignal, t as AmbientDeps, tt as FormSchema, u as Ctx, ut as Emitter, v as GcEvent, w as lookupRegisteredQuery, x as QueryClientPluginApi, y as InvalidateEvent, z as Query } from "./types-C-zV1JZA.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/signals/runtime.d.ts
|
|
4
4
|
/**
|
|
@@ -107,6 +107,17 @@ declare function defineQuery<Args extends unknown[], T>(spec: QuerySpec<Args, T>
|
|
|
107
107
|
*/
|
|
108
108
|
declare function defineInfiniteQuery<Args extends unknown[], PageParam, TPage, TItem = TPage>(spec: InfiniteQuerySpec<Args, PageParam, TPage, TItem>): InfiniteQuery<Args, TPage, TItem>;
|
|
109
109
|
//#endregion
|
|
110
|
+
//#region src/query/keys.d.ts
|
|
111
|
+
/**
|
|
112
|
+
* Stable string hash of a key tuple. Two equal-by-content args produce the
|
|
113
|
+
* same string regardless of property iteration order. Handles primitives,
|
|
114
|
+
* arrays, plain objects, Date.
|
|
115
|
+
*
|
|
116
|
+
* Functions and symbols throw — keys must be serializable so distinct
|
|
117
|
+
* subscribers can share entries.
|
|
118
|
+
*/
|
|
119
|
+
declare function stableHash(args: readonly unknown[]): string;
|
|
120
|
+
//#endregion
|
|
110
121
|
//#region src/selection.d.ts
|
|
111
122
|
/**
|
|
112
123
|
* Multi-select state for tables / lists with bulk actions (spec §17.5).
|
|
@@ -149,10 +160,15 @@ declare function selection<T = unknown>(options?: {
|
|
|
149
160
|
* Lag a signal by `ms`. The returned signal updates only after the source has
|
|
150
161
|
* been unchanged for `ms`. Each new write resets the timer.
|
|
151
162
|
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
163
|
+
* Pass `options.signal` (an `AbortSignal`) to tie the internal effect to a
|
|
164
|
+
* lifecycle — when the signal aborts the effect disposes, the pending timer
|
|
165
|
+
* clears, and the subscriber chain on `source` drops. Without `signal`, the
|
|
166
|
+
* effect lives as long as `source` does; pass a signal whenever the source
|
|
167
|
+
* outlives the consumer.
|
|
154
168
|
*/
|
|
155
|
-
declare function debounced<T>(source: ReadSignal<T>, ms: number
|
|
169
|
+
declare function debounced<T>(source: ReadSignal<T>, ms: number, options?: {
|
|
170
|
+
signal?: AbortSignal;
|
|
171
|
+
}): ReadSignal<T>;
|
|
156
172
|
//#endregion
|
|
157
173
|
//#region src/timing/throttled.d.ts
|
|
158
174
|
/**
|
|
@@ -160,19 +176,24 @@ declare function debounced<T>(source: ReadSignal<T>, ms: number): ReadSignal<T>;
|
|
|
160
176
|
* The first change passes through immediately. Subsequent changes within the
|
|
161
177
|
* window are coalesced; the latest value is emitted when the window expires.
|
|
162
178
|
*
|
|
163
|
-
*
|
|
179
|
+
* Pass `options.signal` to tie the internal effect to a lifecycle — when the
|
|
180
|
+
* signal aborts the effect disposes and any pending trailing timer clears.
|
|
181
|
+
* Without `signal`, the effect lives as long as `source` does.
|
|
164
182
|
*/
|
|
165
|
-
declare function throttled<T>(source: ReadSignal<T>, ms: number
|
|
183
|
+
declare function throttled<T>(source: ReadSignal<T>, ms: number, options?: {
|
|
184
|
+
signal?: AbortSignal;
|
|
185
|
+
}): ReadSignal<T>;
|
|
166
186
|
//#endregion
|
|
167
187
|
//#region src/utils.d.ts
|
|
168
188
|
/**
|
|
169
|
-
* True iff `err`
|
|
170
|
-
*
|
|
189
|
+
* True iff `err` looks like an AbortError. Matches the standard `DOMException`
|
|
190
|
+
* shape thrown by `AbortController` AND any object whose `name === 'AbortError'`
|
|
191
|
+
* — that covers axios / msw / user-thrown plain Errors that signal abort.
|
|
171
192
|
*
|
|
172
|
-
* Spec: §20.12
|
|
173
|
-
*
|
|
193
|
+
* Spec: §20.12. Node 17+ exposes a global DOMException, so the instanceof
|
|
194
|
+
* branch works server-side; the name-based branch is the portable fallback.
|
|
174
195
|
*/
|
|
175
196
|
declare function isAbortError(err: unknown): boolean;
|
|
176
197
|
//#endregion
|
|
177
|
-
export { type AmbientDeps, type AsyncState, type AsyncStatus, type Computed, type ControllerDef, type CtrlApi, type CtrlProps, type Ctx, type DebugBus, type DebugCacheEntry, type DebugEvent, type DeepPartial, type DehydratedEntry, type DehydratedState, type Emitter, type ErrorContext, type Field, type FieldArray, type FieldArrayItemErrors, type FieldArrayOptions, type FieldArrayValidator, type FieldArrayValue, type Form, type FormErrors, type FormOptions, type FormSchema, type FormValidator, type FormValue, type GcEvent, type InfiniteQuery, type InfiniteQuerySpec, type InfiniteQuerySubscription, type InvalidateEvent, type ItemInitial, type LocalCache, type Mutation, type MutationConcurrency, type MutationSpec, type Query, type QueryClientPlugin, type QueryClientPluginApi, type QuerySpec, type QuerySubscription, type ReadSignal, type RegisteredQuery, type RetryDelay, type RetryPolicy, type Root, type RootOptions, type Scope, type ScopeOptions, type Selection, type SetDataEvent, type Signal, type Snapshot, type UseOptions, type Validator, batch, computed, createEmitter, createRoot, debounced, debouncedValidator, defineController, defineInfiniteQuery, defineQuery, defineScope, effect, email, isAbortError, lookupRegisteredQuery, max, maxLength, min, minLength, pattern, required, selection, signal, throttled, untracked };
|
|
198
|
+
export { type AmbientDeps, type AsyncState, type AsyncStatus, type Collection, type CollectionFactoryApi, type CollectionFactoryOptions, type CollectionFactoryResult, type CollectionHomogeneousOptions, type Computed, type ControllerDef, type CtrlApi, type CtrlProps, type Ctx, type DebugBus, type DebugCacheEntry, type DebugEvent, type DeepPartial, type DehydratedEntry, type DehydratedState, type Emitter, type EmitterErrorReporter, type ErrorContext, type Field, type FieldArray, type FieldArrayItemErrors, type FieldArrayOptions, type FieldArrayValidator, type FieldArrayValue, type Form, type FormErrors, type FormOptions, type FormSchema, type FormValidator, type FormValue, type GcEvent, type InfiniteQuery, type InfiniteQuerySpec, type InfiniteQuerySubscription, type InvalidateEvent, type ItemInitial, type LazyChild, type LocalCache, type Mutation, type MutationConcurrency, type MutationSpec, type Query, type QueryClientPlugin, type QueryClientPluginApi, type QuerySpec, type QuerySubscription, type ReadSignal, type RegisteredQuery, type RetryDelay, type RetryPolicy, type Root, type RootOptions, type Scope, type ScopeOptions, type Selection, type SetDataEvent, type Signal, type Snapshot, type UseOptions, type Validator, batch, computed, createEmitter, createRoot, debounced, debouncedValidator, defineController, defineInfiniteQuery, defineQuery, defineScope, effect, email, isAbortError, lookupRegisteredQuery, max, maxLength, min, minLength, pattern, required, selection, signal, stableHash, throttled, untracked };
|
|
178
199
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/signals/runtime.ts","../src/controller/define.ts","../src/controller/root.ts","../src/forms/validators.ts","../src/forms/field.ts","../src/query/define.ts","../src/selection.ts","../src/timing/debounced.ts","../src/timing/throttled.ts","../src/utils.ts"],"mappings":";;;;;AAsEA;;;;iBAAgB,MAAA,GAAA,CAAU,OAAA,EAAS,CAAA,GAAI,MAAA,CAAO,CAAA;;;;;;;;;iBAY9B,QAAA,GAAA,CAAY,EAAA,QAAU,CAAA,GAAI,QAAA,CAAS,CAAA;AAZJ;AAY/C;;;;;;;AAZ+C,iBAwB/B,MAAA,CAAO,EAA6B;;;;;iBAQpC,KAAA,GAAA,CAAS,EAAA,QAAU,CAAA,GAAI,CAAC;;AApBY;AAYpD;;;;iBAkBgB,SAAA,GAAA,CAAa,EAAA,QAAU,CAAA,GAAI,CAAC;;;;KCxGhC,uBAAA;ED8DI;;;;;;;;ECrDd,IAAI;AAAA;;;;;ADqDyC;AAY/C;;iBCvDgB,gBAAA,6BAAA,CACd,OAAA,GAAU,GAAA,EAAK,GAAA,EAAK,KAAA,EAAO,KAAA,KAAU,GAAA,EACrC,OAAA,GAAU,uBAAA,GACT,aAAA,CAAc,KAAA,EAAO,GAAA;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/signals/runtime.ts","../src/controller/define.ts","../src/controller/root.ts","../src/forms/validators.ts","../src/forms/field.ts","../src/query/define.ts","../src/query/keys.ts","../src/selection.ts","../src/timing/debounced.ts","../src/timing/throttled.ts","../src/utils.ts"],"mappings":";;;;;AAsEA;;;;iBAAgB,MAAA,GAAA,CAAU,OAAA,EAAS,CAAA,GAAI,MAAA,CAAO,CAAA;;;;;;;;;iBAY9B,QAAA,GAAA,CAAY,EAAA,QAAU,CAAA,GAAI,QAAA,CAAS,CAAA;AAZJ;AAY/C;;;;;;;AAZ+C,iBAwB/B,MAAA,CAAO,EAA6B;;;;;iBAQpC,KAAA,GAAA,CAAS,EAAA,QAAU,CAAA,GAAI,CAAC;;AApBY;AAYpD;;;;iBAkBgB,SAAA,GAAA,CAAa,EAAA,QAAU,CAAA,GAAI,CAAC;;;;KCxGhC,uBAAA;ED8DI;;;;;;;;ECrDd,IAAI;AAAA;;;;;ADqDyC;AAY/C;;iBCvDgB,gBAAA,6BAAA,CACd,OAAA,GAAU,GAAA,EAAK,GAAA,EAAK,KAAA,EAAO,KAAA,KAAU,GAAA,EACrC,OAAA,GAAU,uBAAA,GACT,aAAA,CAAc,KAAA,EAAO,GAAA;;;;;;;iBCoIR,UAAA,oBAA8B,MAAA,oBAA0B,WAAA,CAAA,CACtE,GAAA,EAAK,aAAA,OAAoB,GAAA,GACzB,OAAA,EAAS,WAAA,CAAY,KAAA,IACpB,IAAA,CAAK,GAAA;;;;cC3JK,QAAA,MACP,OAAA,cAAuB,SAAS,CAAC,CAAA;AH2DvC;AAAA,cGtDa,SAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAQ7B,SAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAQ7B,GAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAQ7B,GAAA,GACV,CAAA,UAAW,OAAA,cAAmB,SAAS;;cAY7B,KAAA,GACV,OAAA,cAAoC,SAAS;;cAOnC,OAAA,GACV,EAAA,EAAI,MAAA,EAAQ,OAAA,cAA6B,SAAS;;;;;;;;iBCyRrC,kBAAA,GAAA,CACd,EAAA,GAAK,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,WAAA,KAAgB,OAAA,iBACvC,EAAA,WACC,SAAA,CAAU,CAAA;;;;AJvRb;;;iBKtCgB,WAAA,2BAAA,CAAuC,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,CAAA,IAAK,KAAA,CAAM,IAAA,EAAM,CAAA;;;;;;;;iBAyE9E,mBAAA,mDAAsE,KAAA,CAAA,CACpF,IAAA,EAAM,iBAAA,CAAkB,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,KAAA,IAC/C,aAAA,CAAc,IAAA,EAAM,KAAA,EAAO,KAAA;;;;;;ALrC9B;;;;;iBM9DgB,UAAA,CAAW,IAAwB;;;;;AN8DnD;;;;;KO1DY,SAAA;EACV,WAAA,EAAa,UAAA,CAAW,WAAA;EACxB,IAAA,EAAM,UAAA;EACN,UAAA,CAAW,EAAA,WAAa,UAAA;EAExB,MAAA,CAAO,EAAA;EACP,QAAA,CAAS,EAAA;EACT,MAAA,CAAO,EAAA;EACP,KAAA;EACA,SAAA,CAAU,GAAA;EAEV,WAAA,CACE,EAAA,UACA,IAAA;IAAQ,KAAA;IAAiB,IAAA;EAAA,GACzB,OAAA;AAAA;;;;;;;;;;;APwDgD;iBOzCpC,SAAA,aAAA,CAAuB,OAAA;EAAY,OAAA;AAAA,IAAgC,SAAS,CAAC,CAAA;;;;;AP6B7F;;;;;;;;iBQzDgB,SAAA,GAAA,CACd,MAAA,EAAQ,UAAA,CAAW,CAAA,GACnB,EAAA,UACA,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,UAAA,CAAW,CAAA;;;;;ARqDd;;;;;;;iBS1DgB,SAAA,GAAA,CACd,MAAA,EAAQ,UAAA,CAAW,CAAA,GACnB,EAAA,UACA,OAAA;EAAY,MAAA,GAAS,WAAA;AAAA,IACpB,UAAA,CAAW,CAAA;;;;;;ATsDd;;;;;iBU9DgB,YAAA,CAAa,GAAY"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as lookupRegisteredQuery, c as
|
|
1
|
+
import { a as lookupRegisteredQuery, c as isAbortError, d as effect, f as signal, i as createEmitter, l as batch, m as defineController, o as registerQueryById, p as untracked, r as debouncedValidator, s as stableHash, t as createRoot, u as computed } from "./root-De-6KWIZ.mjs";
|
|
2
2
|
//#region src/signals/readonly.ts
|
|
3
3
|
/**
|
|
4
4
|
* Project a Signal (or any object with a reactive `value` + `peek` + `subscribe`)
|
|
@@ -8,7 +8,7 @@ import { a as lookupRegisteredQuery, c as batch, d as signal, f as untracked, i
|
|
|
8
8
|
* Internal helper — not exported from the package's public surface.
|
|
9
9
|
*/
|
|
10
10
|
function readOnly(source) {
|
|
11
|
-
return {
|
|
11
|
+
return Object.freeze({
|
|
12
12
|
get value() {
|
|
13
13
|
return source.value;
|
|
14
14
|
},
|
|
@@ -18,7 +18,7 @@ function readOnly(source) {
|
|
|
18
18
|
subscribe(handler) {
|
|
19
19
|
return source.subscribe(handler);
|
|
20
20
|
}
|
|
21
|
-
};
|
|
21
|
+
});
|
|
22
22
|
}
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/forms/validators.ts
|
|
@@ -271,14 +271,17 @@ function selection(options) {
|
|
|
271
271
|
* Lag a signal by `ms`. The returned signal updates only after the source has
|
|
272
272
|
* been unchanged for `ms`. Each new write resets the timer.
|
|
273
273
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
274
|
+
* Pass `options.signal` (an `AbortSignal`) to tie the internal effect to a
|
|
275
|
+
* lifecycle — when the signal aborts the effect disposes, the pending timer
|
|
276
|
+
* clears, and the subscriber chain on `source` drops. Without `signal`, the
|
|
277
|
+
* effect lives as long as `source` does; pass a signal whenever the source
|
|
278
|
+
* outlives the consumer.
|
|
276
279
|
*/
|
|
277
|
-
function debounced(source, ms) {
|
|
280
|
+
function debounced(source, ms, options) {
|
|
278
281
|
const out = signal(source.peek());
|
|
279
282
|
let timer = null;
|
|
280
283
|
let initial = true;
|
|
281
|
-
effect(() => {
|
|
284
|
+
const dispose = effect(() => {
|
|
282
285
|
const value = source.value;
|
|
283
286
|
if (initial) {
|
|
284
287
|
initial = false;
|
|
@@ -290,6 +293,18 @@ function debounced(source, ms) {
|
|
|
290
293
|
timer = null;
|
|
291
294
|
}, ms);
|
|
292
295
|
});
|
|
296
|
+
const sig = options?.signal;
|
|
297
|
+
if (sig) {
|
|
298
|
+
const stop = () => {
|
|
299
|
+
if (timer != null) {
|
|
300
|
+
clearTimeout(timer);
|
|
301
|
+
timer = null;
|
|
302
|
+
}
|
|
303
|
+
dispose();
|
|
304
|
+
};
|
|
305
|
+
if (sig.aborted) stop();
|
|
306
|
+
else sig.addEventListener("abort", stop, { once: true });
|
|
307
|
+
}
|
|
293
308
|
return out;
|
|
294
309
|
}
|
|
295
310
|
//#endregion
|
|
@@ -299,15 +314,17 @@ function debounced(source, ms) {
|
|
|
299
314
|
* The first change passes through immediately. Subsequent changes within the
|
|
300
315
|
* window are coalesced; the latest value is emitted when the window expires.
|
|
301
316
|
*
|
|
302
|
-
*
|
|
317
|
+
* Pass `options.signal` to tie the internal effect to a lifecycle — when the
|
|
318
|
+
* signal aborts the effect disposes and any pending trailing timer clears.
|
|
319
|
+
* Without `signal`, the effect lives as long as `source` does.
|
|
303
320
|
*/
|
|
304
|
-
function throttled(source, ms) {
|
|
321
|
+
function throttled(source, ms, options) {
|
|
305
322
|
const out = signal(source.peek());
|
|
306
323
|
let lastEmit = Number.NEGATIVE_INFINITY;
|
|
307
324
|
let trailingTimer = null;
|
|
308
325
|
let trailingValue = source.peek();
|
|
309
326
|
let initial = true;
|
|
310
|
-
effect(() => {
|
|
327
|
+
const dispose = effect(() => {
|
|
311
328
|
const value = source.value;
|
|
312
329
|
if (initial) {
|
|
313
330
|
initial = false;
|
|
@@ -331,9 +348,21 @@ function throttled(source, ms) {
|
|
|
331
348
|
}, ms - elapsed);
|
|
332
349
|
}
|
|
333
350
|
});
|
|
351
|
+
const sig = options?.signal;
|
|
352
|
+
if (sig) {
|
|
353
|
+
const stop = () => {
|
|
354
|
+
if (trailingTimer != null) {
|
|
355
|
+
clearTimeout(trailingTimer);
|
|
356
|
+
trailingTimer = null;
|
|
357
|
+
}
|
|
358
|
+
dispose();
|
|
359
|
+
};
|
|
360
|
+
if (sig.aborted) stop();
|
|
361
|
+
else sig.addEventListener("abort", stop, { once: true });
|
|
362
|
+
}
|
|
334
363
|
return out;
|
|
335
364
|
}
|
|
336
365
|
//#endregion
|
|
337
|
-
export { batch, computed, createEmitter, createRoot, debounced, debouncedValidator, defineController, defineInfiniteQuery, defineQuery, defineScope, effect, email, isAbortError, lookupRegisteredQuery, max, maxLength, min, minLength, pattern, required, selection, signal, throttled, untracked };
|
|
366
|
+
export { batch, computed, createEmitter, createRoot, debounced, debouncedValidator, defineController, defineInfiniteQuery, defineQuery, defineScope, effect, email, isAbortError, lookupRegisteredQuery, max, maxLength, min, minLength, pattern, required, selection, signal, stableHash, throttled, untracked };
|
|
338
367
|
|
|
339
368
|
//# sourceMappingURL=index.mjs.map
|