@cgtk/std 0.0.191 → 0.0.193

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/async.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { Fn, Constantly, Optional, Dispose, MaybePromise } from "./types";
1
+ import type { Fn, Constantly, Maybe, Dispose, MaybePromise } from "./types";
2
2
  export declare const timeout: (ms: number, signal?: AbortSignal) => Promise<unknown>;
3
- export declare const delay: (ms: number) => <T>(x: T) => Promise<T>;
4
- export declare const probing: <T>(p: Promise<T>) => Constantly<Optional<T>>;
3
+ export declare const delay: (ms: number, signal?: AbortSignal) => <T>(x: T) => Promise<T>;
4
+ export declare const probing: <T>(p: Promise<T>) => Constantly<Maybe<T>>;
5
5
  export declare const resolved: <T>(p: Promise<T>) => (f: Fn<T>) => () => void;
6
6
  export declare const promise: <T>(x: MaybePromise<T>) => Promise<any>;
7
7
  export declare const then: <T>(p: Promise<T>) => <R>(f: Fn<T, R>) => Promise<R>;
package/async.js CHANGED
@@ -4,15 +4,16 @@ export const timeout = (ms, signal) => new Promise((resolve, reject) => {
4
4
  if (signal?.aborted)
5
5
  reject(signal.reason);
6
6
  else {
7
- setTimeout(() => {
7
+ const t = setTimeout(() => {
8
8
  if (signal?.aborted)
9
9
  reject(signal.reason);
10
10
  else
11
11
  resolve(undefined);
12
12
  }, ms);
13
+ signal?.addEventListener("abort", () => (clearTimeout(t), reject(signal.reason)), { once: true });
13
14
  }
14
15
  });
15
- export const delay = (ms) => async (x) => (await timeout(ms), x);
16
+ export const delay = (ms, signal) => async (x) => (await timeout(ms, signal), x);
16
17
  export const probing = (p) => {
17
18
  let value = undefined;
18
19
  p.then(x => value = x);
package/checks.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import type { TypedArray, NumberArray, BigIntArray, Pred, TPred, Optional } from "./types";
1
+ import type { TypedArray, NumberArray, BigIntArray, Pred, TPred, Maybe } from "./types";
2
2
  export declare const isTypedArray: (x: any) => x is TypedArray;
3
3
  export declare const isNumberArray: (x: any) => x is NumberArray;
4
4
  export declare const isBigIntArray: (x: any) => x is BigIntArray;
5
5
  export declare const isUndefined: (x: any) => x is undefined;
6
6
  export declare const isNull: (x: any) => x is null;
7
- export declare const isDefined: <T>(x: Optional<T>) => x is T;
7
+ export declare const isDefined: <T>(x: Maybe<T>) => x is T;
8
8
  export declare function assert(condition: boolean, msg: string): asserts condition;
9
9
  export declare function assertType<T>(x: any, pred: TPred<T>, msg: string): asserts x is T;
10
10
  export declare const isObject: TPred<Object>;
package/dom.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Fn, Dispose, RecordOf, Optional } from "./types";
1
+ import type { Fn, Dispose, RecordOf, Maybe } from "./types";
2
2
  export declare const customEvent: <T>(type: string, detail: T, { composed, bubbles, cancelable }?: EventInit) => CustomEvent<T>;
3
3
  type ListenOpts = boolean | AddEventListenerOptions;
4
4
  export declare const on: {
@@ -46,5 +46,5 @@ export declare const onResize: (el: Element, f: Fn<ResizeObserverEntry[]>, optio
46
46
  export declare const preventDefault: <T extends Event>(e: T) => void;
47
47
  export declare const loadImage: (img: HTMLImageElement, src: string) => Promise<HTMLImageElement>;
48
48
  export declare const pushState: (path: string, query?: RecordOf<string>, data?: any) => void;
49
- export declare const qs: (search?: string) => Optional<RecordOf<string>>;
49
+ export declare const qs: (search?: string) => Maybe<RecordOf<string>>;
50
50
  export {};
package/fn.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Fn, FnV, FnF, Pred, TPred, FirstParam, Last, Constantly, Optional, Dispose, Reactive } from "./types";
1
+ import type { Fn, FnV, FnF, Pred, TPred, FirstParam, Last, Constantly, Maybe, Dispose, Reactive } from "./types";
2
2
  export declare const tee: <T>(f: Fn<T, void>) => Fn<T, T>;
3
3
  export declare const comp: <Fs extends Fn[]>(...fs: Fs) => (x: FirstParam<Fs[0]>) => Last<Fs> extends Fn<any, infer R> ? R : never;
4
4
  export declare const pipe: <T, Fs extends [Fn<T>, ...Fn[]]>(x: T, ...fs: Fs) => Last<Fs> extends Fn<any, infer R> ? R : never;
@@ -23,9 +23,9 @@ export declare const filter: <T>(p: Pred<T>, f: Fn<T>) => (x: T) => void;
23
23
  export declare const filterT: <T>(p: TPred<T>, f: Fn<T>) => <S>(x: S) => void;
24
24
  export declare const scan: <T, S>(f: FnV<[S, T], S>, a: S) => Fn<T, S>;
25
25
  export declare const memoize: <T extends any[], K, V>(f: FnV<T, V>, key?: FnV<T, K>, cache?: Map<K, V>) => (...xs: T) => NonNullable<V>;
26
- export declare const abortable: <T = any>(f: Fn<AbortSignal>, reason?: T) => () => void;
26
+ export declare const abortable: <T = any>(f: Fn<AbortSignal>) => (reason?: T) => void;
27
27
  export declare const disposable: (f: Fn<Fn<Dispose, Dispose>>, disposes?: Set<Dispose>) => Dispose;
28
- export declare const disposing: () => <F extends FnV<any[], Optional<Dispose>>>(f: F) => FnV<Parameters<F>, Dispose>;
28
+ export declare const disposing: () => <F extends FnV<any[], Maybe<Dispose>>>(f: F) => FnV<Parameters<F>, Dispose>;
29
29
  export declare const disposeWith: <T>(f: Fn<T, Dispose>) => (g: Fn<Fn<T>>) => Dispose;
30
30
  export declare const idemp: <F extends FnV<any[], Dispose | void>>(d: Fn<Dispose, Dispose>, f: F) => FnV<Parameters<F>, Dispose>;
31
31
  export declare const toggler: (f: Fn<void, Dispose>) => (x: boolean) => Dispose;
package/fn.js CHANGED
@@ -34,10 +34,10 @@ export const memoize = (f, key = (...xs) => xs[0], cache = new Map()) => (...xs)
34
34
  cache.set(k, f(...xs));
35
35
  return cache.get(k);
36
36
  };
37
- export const abortable = (f, reason) => {
37
+ export const abortable = (f) => {
38
38
  const ctrl = new AbortController();
39
39
  f(ctrl.signal);
40
- return () => ctrl.abort(reason);
40
+ return (reason) => ctrl.abort(reason);
41
41
  };
42
42
  export const disposable = (f, disposes = new Set()) => {
43
43
  f(bind(add, disposes));
package/http.d.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  export declare const assertStatus: (status: number) => (resp: Response) => void;
2
2
  export declare const contentLength: (response: Response) => number;
3
- export declare const toByteArray: (stream: ReadableStream<Uint8Array>) => Promise<Uint8Array<ArrayBufferLike>>;
4
- export declare const fetchBuffer: (url: string | URL | Request, init?: RequestInit) => Promise<Uint8Array<ArrayBufferLike>>;
5
- export declare const fetchText: (url: string, init?: RequestInit) => Promise<string>;
6
- export declare const fetchDOM: (url: string, init?: RequestInit) => Promise<HTMLElement>;
3
+ export declare const fetchBuffer: (url: string | URL | Request, init?: RequestInit) => Promise<ArrayBuffer>;
4
+ export declare const fetchText: (url: string | URL | Request, init?: RequestInit) => Promise<string>;
5
+ export declare const fetchDOM: (url: string | URL | Request, init?: RequestInit) => Promise<HTMLElement>;
7
6
  export declare const fetchImage: (src: string) => Promise<HTMLImageElement>;
8
- export declare const fetchImageBitmap: (url: string, init?: RequestInit) => Promise<ImageBitmap>;
9
- export declare const fetchJSON: (url: string, init?: RequestInit) => Promise<any>;
10
- export declare const fetchDataUrl: (url: string) => Promise<string>;
7
+ export declare const fetchImageBitmap: (url: string | URL | Request, init?: RequestInit) => Promise<ImageBitmap>;
8
+ export declare const fetchJSON: (url: string | URL | Request, init?: RequestInit) => Promise<any>;
9
+ export declare const fetchDataUrl: (url: string | URL | Request, init?: RequestInit) => Promise<string>;
package/http.js CHANGED
@@ -1,18 +1,14 @@
1
1
  import { tee } from "./fn";
2
2
  import { assert } from "./checks";
3
- import { reduceArray } from './stream';
4
- import { concat } from "./typedarray";
5
- import { fromBytes } from "./json";
6
3
  export const assertStatus = (status) => (resp) => assert(resp.status == status, `Invalid HTTP Status ${resp.status}: ${resp.url}`);
7
4
  export const contentLength = (response) => {
8
5
  const cl = response.headers.get("content-length");
9
6
  return cl ? parseInt(cl) : -1;
10
7
  };
11
- export const toByteArray = async (stream) => concat(await reduceArray(stream));
12
8
  export const fetchBuffer = (url, init) => fetch(url, init)
13
9
  .then(tee(assertStatus(200)))
14
- .then(resp => resp.body)
15
- .then(toByteArray);
10
+ .then(resp => resp.blob())
11
+ .then(blob => blob.arrayBuffer());
16
12
  export const fetchText = (url, init) => fetchBuffer(url, init).then(buf => new TextDecoder("utf-8").decode(buf));
17
13
  export const fetchDOM = (url, init) => fetchText(url, init).then(txt => new DOMParser().parseFromString(txt, "image/svg+xml").documentElement);
18
14
  export const fetchImage = (src) => new Promise((resolve, reject) => {
@@ -22,13 +18,13 @@ export const fetchImage = (src) => new Promise((resolve, reject) => {
22
18
  image.onload = () => resolve(image);
23
19
  image.onerror = reject;
24
20
  });
25
- export const fetchImageBitmap = async (url, init) => {
26
- const res = await fetch(url, init);
27
- const blob = await res.blob();
28
- return await createImageBitmap(blob, { colorSpaceConversion: "none" });
29
- };
30
- export const fetchJSON = (url, init) => fetchBuffer(url, init).then(fromBytes);
31
- export const fetchDataUrl = (url) => fetch(url)
21
+ export const fetchImageBitmap = async (url, init) => fetch(url, init)
22
+ .then(tee(assertStatus(200)))
23
+ .then(resp => resp.blob())
24
+ .then(blob => createImageBitmap(blob, { colorSpaceConversion: "none" }));
25
+ export const fetchJSON = (url, init) => fetchText(url, init).then(JSON.parse);
26
+ export const fetchDataUrl = (url, init) => fetch(url, init)
27
+ .then(tee(assertStatus(200)))
32
28
  .then(resp => resp.blob())
33
29
  .then(blob => new Promise(resolve => {
34
30
  const f = new FileReader();
package/json.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const fromBytes: (data: Uint8Array) => any;
1
+ export declare const fromBytes: (data: AllowSharedBufferSource, options?: TextDecodeOptions) => any;
package/json.js CHANGED
@@ -1 +1 @@
1
- export const fromBytes = (data) => JSON.parse(new TextDecoder("utf-8").decode(data));
1
+ export const fromBytes = (data, options) => JSON.parse(new TextDecoder("utf-8").decode(data, options));
package/map.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { FnV, Optional } from "./types";
1
+ import type { FnV, Maybe } from "./types";
2
2
  export declare const transform: <K, S, V>({ create, update, remove }: {
3
3
  create: FnV<[S, K, Map<K, V>], V>;
4
4
  update: FnV<[V, S, K, Map<K, V>], V>;
@@ -7,6 +7,6 @@ export declare const transform: <K, S, V>({ create, update, remove }: {
7
7
  export declare const set: <K, V>(m: Map<K, V>, [i, x]: [K, V]) => Map<K, V>;
8
8
  export declare const get: <K, V>(m: Map<K, V>, k: K, d: V) => V;
9
9
  export declare const update: <K, V>(m: Map<K, V>, k: K, f: FnV<[V | undefined, K, Map<K, V>], V>) => Map<K, V>;
10
- export declare const first: <K, V>(m: Map<K, V>) => Optional<V>;
11
- export declare const shift: <K, V>(m: Map<K, V>) => Optional<[K, V]>;
10
+ export declare const first: <K, V>(m: Map<K, V>) => Maybe<V>;
11
+ export declare const shift: <K, V>(m: Map<K, V>) => Maybe<[K, V]>;
12
12
  export declare const reduce: <K, V, T>(m: Map<K, V>, f: FnV<[T, V, K, Map<K, V>], T>, a: T) => T;
package/object.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RecordOf, Elements, Optional, FnV, ValueOf, EntriesTuple, UnionToTuple, Entry } from "./types.js";
1
+ import type { RecordOf, Elements, Maybe, FnV, ValueOf, EntriesTuple, UnionToTuple, Entry } from "./types.js";
2
2
  export declare const entries: <T extends RecordOf<any>>(o: T) => EntriesTuple<T>;
3
3
  export declare const keys: <T extends RecordOf<any>>(o: T) => UnionToTuple<keyof T>;
4
4
  export declare const entry: <K extends PropertyKey, V>(k: K, v: V) => Entry<K, V>;
@@ -11,5 +11,5 @@ export declare const assoc: <T extends RecordOf<any>>(a: T, [k, v]: [keyof T, Va
11
11
  type Merge<T extends RecordOf<unknown>, S extends RecordOf<unknown>, V> = {
12
12
  [K in keyof (T & S)]: V;
13
13
  };
14
- export declare const merge: <T, S = T, V = T>(f: FnV<[Optional<T>, Optional<S>], V>) => <X extends RecordOf<T>, Y extends RecordOf<T>>(x: X, y: Y) => Merge<X, Y, V>;
14
+ export declare const merge: <T, S = T, V = T>(f: FnV<[Maybe<T>, Maybe<S>], V>) => <X extends RecordOf<T>, Y extends RecordOf<T>>(x: X, y: Y) => Merge<X, Y, V>;
15
15
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cgtk/std",
3
- "version": "0.0.191",
3
+ "version": "0.0.193",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "exports": {
@@ -41,7 +41,7 @@
41
41
  "./utils": "./utils.js"
42
42
  },
43
43
  "devDependencies": {
44
- "typescript": "^5.9.2"
44
+ "typescript": "^5.9.3"
45
45
  },
46
46
  "publishConfig": {
47
47
  "access": "public"
package/port.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Dispose, Fn, Fns, FnV, RecordOf, MaybePromise } from "./types";
1
+ import type { Dispose, Fn, Fns, FnV, RecordOf, MaybePromise, Reactive } from "./types";
2
2
  export interface Message<K, V> {
3
3
  type: K;
4
4
  payload: V;
@@ -8,6 +8,7 @@ export type Port = {
8
8
  };
9
9
  export declare const onMessages: <S extends RecordOf<any>, T = Worker>(target: MessageEventTarget<T>, fs: Fns<S>) => Dispose;
10
10
  export declare const onMessage: <K extends string, S, T = Worker>(target: MessageEventTarget<T>, name: K, f: Fn<S>) => Dispose;
11
+ export declare const messageSources: <T extends RecordOf<any>, S = Worker>(worker: MessageEventTarget<S>) => { [K in keyof T]: Reactive<T[K]>; };
11
12
  export declare const postMessages: <T extends RecordOf<any>>(port: Port) => { [k in keyof T]: FnV<[T[k], (StructuredSerializeOptions | undefined)?]>; };
12
13
  export interface Request {
13
14
  id: number;
package/port.js CHANGED
@@ -1,10 +1,13 @@
1
- import { forEach, noop } from "./fn";
1
+ import { forEach, noop, bind } from "./fn";
2
2
  import { isDefined } from "./checks";
3
3
  import { on } from "./dom";
4
4
  import { promise } from "./async";
5
5
  ;
6
6
  export const onMessages = (target, fs) => on(target, "message", ({ data: { type, payload } }) => (type in fs) && fs[type](payload));
7
7
  export const onMessage = (target, name, f) => on(target, "message", ({ data: { type, payload } }) => type == name && f(payload));
8
+ export const messageSources = (worker) => new Proxy({}, {
9
+ get: (_, k) => bind((onMessage), worker, k)
10
+ });
8
11
  export const postMessages = (port) => new Proxy({}, {
9
12
  get: (_, type) => (payload, options) => port.postMessage({ type, payload }, options)
10
13
  });
package/resource.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import type { Fn, Dispose, Resource, RecordOf } from "./types";
2
- export declare const resource: <T>(x: T, d?: Dispose) => Resource<T>;
3
- export declare const map: <T, S>(r: Resource<T>, g: Fn<T, S>) => Resource<S>;
4
- export declare const flatMap: <T, S>(r: Resource<T>, g: Fn<T, Resource<S>>) => Resource<S>;
5
- type Structure<T> = T | Structure<T>[] | RecordOf<Structure<T>>;
6
- type Resolved<T extends Structure<Resource<any>>> = {
7
- [K in keyof T]: T[K] extends Resource<infer R> ? R : T[K] extends Structure<Resource<any>> ? Resolved<T[K]> : never;
1
+ import type { Fn, Dispose, Structure, Reactive } from "./types";
2
+ export type Resource<T> = Reactive<T, Dispose | void> & {
3
+ value: T;
4
+ dispose: Dispose;
5
+ map<S>(f: Fn<T, S>): Resource<S>;
8
6
  };
9
- export declare const combine: <R extends Structure<Resource<any>>>(rs: R) => Resource<Resolved<R>>;
7
+ export declare const resource: <T>(value: T, dispose?: Dispose) => Resource<T>;
8
+ type Unwrapped<T> = T extends Resource<infer U> ? U : {
9
+ [K in keyof T]: Unwrapped<T[K]>;
10
+ };
11
+ export declare const compose: <R extends Structure<Resource<any>>>(rs: R) => Resource<Unwrapped<R>>;
10
12
  export {};
package/resource.js CHANGED
@@ -1,21 +1,28 @@
1
- import { forEach, noop, comp } from "./fn";
2
- import { push, empty } from "./array";
3
- import { assoc } from "./object";
4
- import { reduceRec } from './iterable';
1
+ import { forEach, noop } from "./fn";
5
2
  import { isFunction } from "./checks";
6
- export const resource = (x, d = noop) => (f) => forEach(f(x) ?? noop, d);
7
- export const map = (r, g) => f => r(comp(g, f));
8
- export const flatMap = (r, g) => f => r(x => g(x)(f));
9
- const isResource = (r) => isFunction(r);
10
- export const combine = (rs) => f => {
11
- const rec = (rs, f) => {
3
+ export const resource = (value, dispose = noop) => {
4
+ const res = ((f) => forEach(f(value) ?? noop, dispose));
5
+ res.value = value;
6
+ res.dispose = dispose;
7
+ res.map = (f) => resource(f(value), dispose);
8
+ return res;
9
+ };
10
+ const isResource = (r) => isFunction(r)
11
+ && Object.hasOwn(r, "value")
12
+ && Object.hasOwn(r, "dispose")
13
+ && isFunction(r["dispose"]);
14
+ export const compose = (rs) => {
15
+ const disposes = [];
16
+ const rec = (rs) => {
12
17
  if (isResource(rs)) {
13
- return rs(x => f(x) ?? noop);
18
+ disposes.push(rs.dispose);
19
+ return rs.value;
14
20
  }
15
21
  else if (Array.isArray(rs)) {
16
- return reduceRec(Iterator.from(rs), (o, r, next) => rec(r, (x) => next(push(o, x))), empty(), o => f(o) ?? noop);
22
+ return rs.map(rec);
17
23
  }
18
- return reduceRec(Iterator.from(Object.entries(rs)), (o, [k, r], next) => rec(r, (x) => next(assoc(o, [k, x]))), {}, r => f(r) ?? noop);
24
+ return Object.fromEntries(Object.entries(rs).map(([k, v]) => [k, rec(v)]));
19
25
  };
20
- return rec(rs, f);
26
+ const value = rec(rs);
27
+ return resource(value, forEach(...disposes));
21
28
  };
package/set.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export declare const add: <T>(xs: Set<T>, x: T) => () => boolean;
2
+ export declare const isEqual: <T>(a: Set<T>, b: Set<T>) => boolean;
package/set.js CHANGED
@@ -1 +1,2 @@
1
1
  export const add = (xs, x) => (xs.add(x), () => xs.delete(x));
2
+ export const isEqual = (a, b) => a.size == b.size && a.isSubsetOf(b) && b.isSubsetOf(a);
package/signal.d.ts CHANGED
@@ -1,24 +1,37 @@
1
- import type { Fn, FnV, Fns, Reactive, RecordOf } from "./types";
1
+ import type { Fn, FnV, Fns, Pred, Reactive, RecordOf, Structure } from "./types";
2
2
  export type Signal<T> = Fn<T> & {
3
3
  on: Reactive<T>;
4
4
  };
5
5
  export declare const create: <T>(f: Fn<T>, on: Reactive<T>) => Signal<T>;
6
6
  export declare const signal: <T>(fns?: Set<Fn<T>>) => Signal<T>;
7
- export interface Value<T> {
7
+ export declare const map: <T, S>(source: Reactive<T>, f: Fn<T, S>) => Reactive<S>;
8
+ export declare const filter: <T>(source: Reactive<T>, p: Pred<T>) => Reactive<T>;
9
+ export declare const cache: <T>(source: Reactive<T>) => Reactive<T>;
10
+ export interface ValueLike<T> {
8
11
  value: T;
9
12
  on: Reactive<T>;
13
+ }
14
+ export interface Box<T, F extends RecordOf<FnV>> extends ValueLike<T> {
15
+ ops: F;
16
+ }
17
+ export interface Value<T> extends ValueLike<T> {
10
18
  op: <F extends FnV>(f: Fn<T, F>) => F;
11
19
  ops: <F extends RecordOf<FnV>>(f: Fn<T, F>) => F;
12
20
  set: Fn<T>;
13
21
  update(): void;
22
+ map<S>(f: Fn<T, S>): Reactive<S>;
23
+ box: <F extends RecordOf<FnV>>(f: Fn<T, F>) => Box<T, F>;
14
24
  }
15
- export declare const value: <T>(x: T) => Value<T>;
25
+ export declare const value: <T>(x: T, fs?: Set<Fn<T>>) => Value<T>;
16
26
  export type Values<T extends RecordOf<any>> = {
17
27
  [k in keyof T]: Value<T[k]>;
18
28
  };
19
29
  export declare const values: <T extends RecordOf<any>>(vals: T) => Values<T>;
20
- export declare const map: <T, S>(source: Reactive<T>, f: Fn<T, S>) => Reactive<S>;
21
- export declare const merge: <T extends RecordOf<any>>(vals: Values<T>) => Reactive<T>;
30
+ type Unwrapped<T> = T extends ValueLike<infer U> ? U : {
31
+ [K in keyof T]: Unwrapped<T[K]>;
32
+ };
33
+ export declare const compose: <T extends Structure<ValueLike<any>>, S = Unwrapped<T>>(xs: T, transform?: Fn<Unwrapped<T>, S>) => Reactive<S>;
22
34
  export declare const mux: <I extends RecordOf<any>, O extends RecordOf<any>>(init: Fn<Fns<O>, Fns<I>>) => Fns<I> & {
23
35
  on: { [k in keyof O]: Reactive<O[k]>; };
24
36
  };
37
+ export {};
package/signal.js CHANGED
@@ -1,6 +1,6 @@
1
- import { after, constantly, noop, bind, comp, forEach } from "./fn";
1
+ import { after, constantly, noop, bind, comp, forEach, filter as filter_, identity } from "./fn";
2
2
  import { mapValues } from "./object";
3
- import { isDefined } from "./checks";
3
+ import { isDefined, isFunction } from "./checks";
4
4
  import { add } from "./set";
5
5
  export const create = (f, on) => {
6
6
  const g = f;
@@ -8,26 +8,67 @@ export const create = (f, on) => {
8
8
  return g;
9
9
  };
10
10
  export const signal = (fns = new Set()) => create((x) => fns.forEach(f => f(x)), bind(add, fns));
11
+ export const map = (source, f) => g => source(comp(f, g));
12
+ export const filter = (source, p) => f => source(filter_(p, f));
13
+ export const cache = (source) => {
14
+ let x;
15
+ source(y => x = y);
16
+ return f => {
17
+ if (isDefined(x))
18
+ f(x);
19
+ return source(f);
20
+ };
21
+ };
11
22
  ;
12
- export const value = (x) => {
13
- const sig = signal();
23
+ ;
24
+ const isValueLike = (v) => Object.hasOwn(v, "value") && Object.hasOwn(v, "on") && isFunction(v.on);
25
+ export const value = (x, fs = new Set()) => {
26
+ const sig = signal(fs);
14
27
  const notify = after(() => sig(x));
15
28
  const op = (f) => notify(f(x));
29
+ const on = (f) => (f(x), sig.on(f));
30
+ const ops = (f) => mapValues(f(x), notify);
16
31
  return {
17
32
  get value() { return x; },
18
33
  set value(y) { sig(x = y); },
19
- op,
20
- on: (f) => (f(x), sig.on(f)),
21
- ops: (f) => mapValues(f(x), notify),
34
+ op, on, ops,
22
35
  set: op(constantly((y) => x = y)),
23
- update: op(constantly(noop))
36
+ update: op(constantly(noop)),
37
+ map: bind(map, on),
38
+ box: (f) => ({
39
+ on,
40
+ get value() { return x; },
41
+ ops: ops(f),
42
+ })
24
43
  };
25
44
  };
26
- export const values = (vals) => mapValues(vals, value);
27
- export const map = (source, f) => g => source(comp(f, g));
28
- export const merge = (vals) => f => {
29
- const sub = () => f(mapValues(vals, (v) => v.value));
30
- return forEach(...Object.values(vals).map((v) => v.on(sub)));
45
+ export const values = (vals) => mapValues(vals, v => value(v));
46
+ export const compose = (xs, transform = identity) => f => {
47
+ const collect = (vs) => {
48
+ if (isValueLike(vs)) {
49
+ return vs.value;
50
+ }
51
+ else if (Array.isArray(vs)) {
52
+ return vs.map(collect);
53
+ }
54
+ return Object.fromEntries(Object.entries(vs).map(([k, v]) => [k, collect(v)]));
55
+ };
56
+ const notify = () => f(transform(collect(xs)));
57
+ let ready = false;
58
+ const sub = (vs) => {
59
+ if (isValueLike(vs)) {
60
+ return vs.on(() => { if (ready)
61
+ notify(); });
62
+ }
63
+ else if (Array.isArray(vs)) {
64
+ return forEach(...vs.map(sub));
65
+ }
66
+ return forEach(...Object.values(vs).map(sub));
67
+ };
68
+ const off = sub(xs);
69
+ ready = true;
70
+ notify();
71
+ return off;
31
72
  };
32
73
  export const mux = (init) => {
33
74
  const sigs = {};
package/string.d.ts CHANGED
@@ -5,3 +5,4 @@ export declare const splitext: (path: string) => Tuple<string, 2>;
5
5
  export declare const objectURL: (data: Uint8Array<ArrayBuffer>, type: string) => string;
6
6
  export declare const decode: (label?: string, opts?: TextDecoderOptions) => (x: Uint8Array, stream?: boolean) => string;
7
7
  export declare const readLine: (delims?: Set<number>) => (data: Uint8Array, offset?: number) => string;
8
+ export declare const DATA_URL: RegExp;
package/string.js CHANGED
@@ -26,3 +26,4 @@ export const readLine = (delims = new Set([0x0A])) => {
26
26
  return n > 0 ? dec(data.subarray(offset, n + 1)) : EMPTY.STR;
27
27
  };
28
28
  };
29
+ export const DATA_URL = /^data:(?<mime>[\w/\-\+]+)?(;(?<params>[\w\-]+\=[^;,\s]+)*)?(;(?<encoding>base64))?,(?<data>.*)$/;
package/struct.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { TypedArray, Fn } from "./types";
1
+ import type { TypedArray, Fn, NumberArray } from "./types";
2
2
  import type { Constructor } from "./typedarray";
3
3
  export interface Type {
4
4
  size: number;
@@ -36,7 +36,7 @@ export type Struct<T extends ReadonlyArray<Field<any>>> = Type & {
36
36
  export declare const isStruct: (t: any) => t is Struct<any>;
37
37
  export declare const struct: <T extends ReadonlyArray<Field<any>>>(fs: T, align?: number, offset?: number) => Struct<T>;
38
38
  export type View<T extends Type> = T extends Vec<infer C, any> ? C : T extends Array<infer S> ? View<S>[] : T extends Struct<infer F> ? {
39
- [K in F[number] as K[0]]: K[1] extends Vec<infer C, infer N> ? (N extends 1 ? (C extends TypedArray ? number : bigint) : C) : View<K[1]>;
39
+ [K in F[number] as K[0]]: K[1] extends Vec<infer C, infer N> ? (N extends 1 ? (C extends NumberArray ? number : bigint) : C) : View<K[1]>;
40
40
  } : never;
41
41
  export declare const view: <T extends Vec<any, any> | Array<any> | Struct<any>>(t: T, buf?: ArrayBufferLike, offset?: number) => View<T>;
42
42
  export {};
package/struct.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { align as _align } from "./math";
2
- import { isTypedArray, isBigIntArray } from "./checks";
2
+ import { isBigIntArray, isNumberArray } from "./checks";
3
3
  const vec = (type) => (length = 1, align = type.BYTES_PER_ELEMENT) => ({
4
4
  type, align, length, size: type.BYTES_PER_ELEMENT * length,
5
5
  });
@@ -42,7 +42,7 @@ export const struct = (fs, align = 0, offset = 0) => {
42
42
  };
43
43
  const property = (value) => ({
44
44
  enumerable: true,
45
- ...((isTypedArray(value) || isBigIntArray(value)) && value.length == 1 ? {
45
+ ...((isNumberArray(value) || isBigIntArray(value)) && value.length == 1 ? {
46
46
  get: () => value[0],
47
47
  set: (x) => value[0] = x,
48
48
  } : { value })
package/tree.d.ts CHANGED
@@ -3,8 +3,8 @@ export type Node<S, T = S> = T | Tree<S, T>;
3
3
  export type Tree<S, T = S> = [S, Node<S, T>[]];
4
4
  export declare const tree: <S, T = S>(value: S, children?: Node<S, T>[]) => Tree<S, T>;
5
5
  export declare const isTree: <S, T = S>(x: Node<S, T>) => x is Tree<S, T>;
6
- export declare const children: <S, T = S>(p?: TPred<Tree<S, T>, Node<S, T>>) => (x: Node<S, T>) => Node<S, T>[];
7
- export declare const value: <S, T = S>(p?: TPred<Tree<S, T>, Node<S, T>>) => (x: Node<S, T>) => S | T;
6
+ export declare const children: <S, T = S>(x: Node<S, T>, p?: TPred<Tree<S, T>, Node<S, T>>) => Node<S, T>[];
7
+ export declare const value: <S, T = S>(x: Node<S, T>, p?: TPred<Tree<S, T>, Node<S, T>>) => S | T;
8
8
  export declare const transform: <S, T = S, A = Tree<S, T>, B = Node<S, T>, C = void>(node: FnV<[Tree<S, T>, Fn<C, Fn<Node<S, T>>>, C], A>, leaf: FnV<[T, C], B>, p?: TPred<Tree<S, T>>) => Fn<C, Fn<Node<S, T>, A | B>>;
9
9
  export declare const map: <S, T = S, U = S, V = T, C = void>(parent: FnV<[S, C], U>, child: FnV<[T, C], V>, update?: FnV<[C, S], C>, p?: TPred<Tree<S, T>>) => Fn<C, Fn<Node<S, T>, Node<U, V>>>;
10
10
  export declare const filter: <S, T = S, C = void>(ps: PredV<[Node<S, T>, C]>, update?: FnV<[C, S], C>, p?: TPred<Tree<S, T>>) => Fn<C, Fn<Node<S, T>, T | Tree<S, T>>>;
package/tree.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { identity } from './fn';
2
2
  import { EMPTY } from './constants';
3
3
  import { zip as zipI } from './iterable';
4
- export const tree = (value, children = EMPTY.LIST) => [value, children];
4
+ export const tree = (value, children = []) => [value, children];
5
5
  export const isTree = (x) => Array.isArray(x) && x.length == 2 && Array.isArray(x[1]);
6
- export const children = (p = isTree) => (x) => p(x) ? x[1] : EMPTY.LIST;
7
- export const value = (p = isTree) => (x) => p(x) ? x[0] : x;
6
+ export const children = (x, p = isTree) => p(x) ? x[1] : EMPTY.LIST;
7
+ export const value = (x, p = isTree) => p(x) ? x[0] : x;
8
8
  export const transform = (node, leaf, p = isTree) => {
9
9
  const f = (c) => (x) => p(x) ? node(x, f, c) : leaf(x, c);
10
10
  return f;
@@ -13,13 +13,11 @@ export const map = (parent, child, update = identity, p = isTree) => transform((
13
13
  export const filter = (ps, update = identity, p = isTree) => transform((x, f, c) => tree(x[0], x[1].filter(x => ps(x, c)).map(f(update(c, x[0])))), identity, p);
14
14
  export const zip = (na, nb) => {
15
15
  const res = [];
16
- const va = value(), vb = value();
17
- const ca = children(), cb = children();
18
16
  for (const [a, b] of zipI(Iterator.from(na), Iterator.from(nb))) {
19
17
  if (!isTree(a) && !isTree(a))
20
- res.push([va(a), vb(b)]);
18
+ res.push([value(a), value(b)]);
21
19
  else if ((isTree(a) && isTree(a)))
22
- res.push([[va(a), vb(b)], zip(ca(a), cb(b))]);
20
+ res.push([[value(a), value(b)], zip(children(a), children(b))]);
23
21
  else
24
22
  throw new Error("[tree] a and b should be both tree or node");
25
23
  }
package/treemap.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- export declare class Treemap<T = number> {
2
- #private;
3
- static from<T>(iter: Iterable<[T, T?]>): Treemap<T>;
4
- nodes: Set<T>;
5
- parents: Map<T, T>;
6
- changed: boolean;
7
- add(node: T, parent?: T): T;
8
- remove(key: T): void;
9
- parent(key: T): T | undefined;
10
- get size(): number;
11
- children(key: T): T[] | undefined;
12
- [Symbol.iterator](): Generator<NonNullable<T>, void, unknown>;
1
+ import type { Maybe } from "./types";
2
+ export interface Treemap<T = number> {
3
+ set(node: T, parent?: T): Treemap<T>;
4
+ delete(key: T): void;
5
+ parent(key: T): Maybe<T>;
6
+ size: number;
7
+ children(key: T): T[];
8
+ roots(): IteratorObject<T>;
9
+ ancestors(node: T): IteratorObject<T>;
10
+ dfs(root: T): IteratorObject<T>;
11
+ bfs(): IteratorObject<T>;
13
12
  }
13
+ export declare const treemap: <T = number>() => Treemap<T>;
package/treemap.js CHANGED
@@ -1,68 +1,71 @@
1
- import { isUndefined } from "./checks";
2
- export class Treemap {
3
- static from(iter) {
4
- const tree = new Treemap();
5
- for (const [n, p] of iter)
6
- tree.add(n, p);
7
- return tree;
8
- }
9
- nodes = new Set();
10
- parents = new Map();
11
- #children = new Map();
12
- changed = false;
13
- add(node, parent) {
14
- const { nodes, parents } = this;
15
- nodes.add(node);
16
- if (!isUndefined(parent))
17
- parents.set(node, parent);
18
- this.changed = true;
19
- return node;
20
- }
21
- remove(key) {
22
- const { nodes, parents } = this;
23
- nodes.delete(key);
24
- parents.delete(key);
25
- this.changed = true;
26
- }
27
- #update() {
28
- const changed = this.changed;
29
- if (changed) {
30
- const { nodes, parents } = this;
31
- const children = this.#children;
1
+ import { before } from "./fn";
2
+ import { isDefined } from "./checks";
3
+ import { EMPTY } from "./constants";
4
+ export const treemap = () => {
5
+ const nodes = new Set();
6
+ const parents = new Map();
7
+ const children = new Map();
8
+ let changed = false;
9
+ const update = () => {
10
+ const hasChanged = changed;
11
+ if (hasChanged) {
32
12
  children.clear();
33
13
  for (const k of nodes) {
34
14
  const p = parents.get(k);
35
- if (!isUndefined(p)) {
15
+ if (isDefined(p)) {
36
16
  if (!children.has(p))
37
17
  children.set(p, []);
38
18
  children.get(p).push(k);
39
19
  }
40
20
  }
41
- this.changed = false;
21
+ changed = false;
42
22
  }
43
- return changed;
44
- }
45
- parent(key) {
46
- this.#update();
47
- return this.parents.get(key);
48
- }
49
- get size() {
50
- this.#update();
51
- return this.nodes.size;
52
- }
53
- children(key) {
54
- this.#update();
55
- return this.#children.get(key);
56
- }
57
- *[Symbol.iterator]() {
58
- this.#update();
59
- const { nodes, parents } = this;
60
- const queue = [], children = this.#children;
61
- nodes.forEach(k => !parents.has(k) && queue.push(k));
62
- for (let node; queue.length > 0;) {
63
- yield node = queue.shift();
64
- if (children.has(node))
65
- queue.push(...children.get(node));
66
- }
67
- }
68
- }
23
+ return hasChanged;
24
+ };
25
+ const updated = before(update);
26
+ const getChildren = updated((key) => children.get(key) ?? EMPTY.LIST);
27
+ const parent = updated((key) => parents.get(key));
28
+ const roots = () => nodes.values().filter(k => !parents.has(k));
29
+ return {
30
+ set(node, parent) {
31
+ nodes.add(node);
32
+ if (isDefined(parent)) {
33
+ nodes.add(parent);
34
+ parents.set(node, parent);
35
+ }
36
+ changed = true;
37
+ return this;
38
+ },
39
+ delete(key) {
40
+ nodes.delete(key);
41
+ parents.delete(key);
42
+ changed = true;
43
+ },
44
+ get size() {
45
+ update();
46
+ return nodes.size;
47
+ },
48
+ parent,
49
+ children: getChildren,
50
+ roots,
51
+ ancestors: updated(function* (node) {
52
+ for (let cur = node; isDefined(cur); cur = parent(cur))
53
+ yield cur;
54
+ }),
55
+ dfs: updated(function* (root) {
56
+ const stack = [root];
57
+ for (let node; stack.length > 0;) {
58
+ yield node = stack.pop();
59
+ const items = getChildren(node);
60
+ for (let i = items.length - 1; i >= 0; i--)
61
+ stack.push(items[i]);
62
+ }
63
+ }),
64
+ bfs: updated(function* (queue = [...roots()]) {
65
+ for (let node; queue.length > 0;) {
66
+ yield node = queue.shift();
67
+ queue.push(...getChildren(node));
68
+ }
69
+ })
70
+ };
71
+ };
package/types.d.ts CHANGED
@@ -2,6 +2,8 @@ export interface RecordOf<T> {
2
2
  [id: PropertyKey]: T;
3
3
  }
4
4
  export type ValueOf<T> = T[keyof T];
5
+ export type Structure<T> = T | readonly Structure<T>[] | RecordOf<Structure<T>>;
6
+ export type Optional<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> & Partial<Pick<T, K>>;
5
7
  export type Tuple<T, N extends number, R extends T[] = []> = R['length'] extends N ? R : Tuple<T, N, [T, ...R]>;
6
8
  export type Elements<A extends readonly unknown[]> = A extends readonly (infer T)[] ? T : never;
7
9
  export type MaybeFirst<T extends unknown[], S = void> = T extends {
@@ -16,7 +18,6 @@ export type Fns<T> = {
16
18
  export type FnF = <F extends FnV>(f: F) => (...xs: Parameters<F>) => ReturnType<F>;
17
19
  export type Dispose = Fn<void>;
18
20
  export type Reactive<T = unknown, R = any> = Fn<Fn<T, R>, Dispose>;
19
- export type Resource<T> = Reactive<T, Dispose | void>;
20
21
  export type Constantly<T> = () => T;
21
22
  export type FirstParam<F extends FnV> = MaybeFirst<Parameters<F>>;
22
23
  export type MaybePromise<T = unknown> = T | PromiseLike<T>;
@@ -50,7 +51,7 @@ export type Eq<A, B = A> = FnV<[A, B], boolean>;
50
51
  export type Pred<T> = Fn<T, boolean>;
51
52
  export type PredV<T extends any[]> = FnV<T, boolean>;
52
53
  export type TPred<T extends S, S = any> = (x: S) => x is T;
53
- export type Optional<T> = T | undefined;
54
+ export type Maybe<T> = T | undefined;
54
55
  export type Indexed<T> = [number, T];
55
56
  export type Required<T, K extends keyof T> = T & {
56
57
  [P in K]-?: T[P];
@@ -59,9 +60,4 @@ export type Partials<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
59
60
  export type KeyMap<T extends string> = {
60
61
  [K in T]: Extract<K, T>;
61
62
  };
62
- export interface BufferView<T extends ArrayBufferLike = ArrayBufferLike> {
63
- readonly buffer: T;
64
- readonly byteLength: number;
65
- readonly byteOffset: number;
66
- }
67
63
  export {};
package/weak.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import type { Fn, Optional } from "./types";
2
- export declare const deref: <T extends WeakKey, F extends Fn<T>>(r: WeakRef<T>, f: F) => Optional<ReturnType<F>>;
1
+ import type { Fn, Maybe } from "./types";
2
+ export declare const deref: <T extends WeakKey, F extends Fn<T>>(r: WeakRef<T>, f: F) => Maybe<ReturnType<F>>;