@fumari/stf 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as FieldKey } from "./types-PXiOOMNs.js";
1
+ import { t as FieldKey } from "./types-Do_aTV5I.js";
2
2
  import { ReactNode } from "react";
3
3
  import * as react_jsx_runtime0 from "react/jsx-runtime";
4
4
 
@@ -117,13 +117,11 @@ declare function useFieldValue<V = unknown>(key: FieldKey, options?: {
117
117
  *
118
118
  * to re-compute on in-place updates (may happen on objects, arrays), you should clone the object here.
119
119
  */
120
- compute?: (currentValue: unknown) => V;
121
- /** determine whether the value/computed value is changed */
120
+ compute?: (currentValue: unknown) => V; /** determine whether the value/computed value is changed */
122
121
  isChanged?: (prev: V, next: V) => boolean;
123
122
  }): readonly [V, (newValue: unknown) => boolean];
124
123
  declare function useListener(listener: DataEngineListener & {
125
124
  stf?: Stf;
126
125
  }): void;
127
126
  //#endregion
128
- export { ArrayItemInfo, DataEngine, DataEngineListener, DefaultValue, FieldKey, PropertyItemInfo, Stf, StfProvider, useArray, useDataEngine, useFieldValue, useListener, useObject, useStf };
129
- //# sourceMappingURL=index.d.ts.map
127
+ export { ArrayItemInfo, DataEngine, DataEngineListener, DefaultValue, FieldKey, PropertyItemInfo, Stf, StfProvider, useArray, useDataEngine, useFieldValue, useListener, useObject, useStf };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { a as stringifyFieldKey, i as objectSet, n as deepEqual, r as objectGet } from "./utils-W82BoH4I.js";
3
+ import { deepEqual, objectGet, objectSet, stringifyFieldKey } from "./lib/utils.js";
4
4
  import { createContext, use, useEffect, useMemo, useRef, useState } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
 
@@ -26,12 +26,12 @@ function useArray(field, options = {}) {
26
26
  const [items] = useFieldValue(field, {
27
27
  defaultValue: options.defaultValue,
28
28
  compute(value) {
29
- const items$1 = [];
30
- if (Array.isArray(value)) for (let i = 0; i < value.length; i++) items$1.push({
29
+ const items = [];
30
+ if (Array.isArray(value)) for (let i = 0; i < value.length; i++) items.push({
31
31
  field: [...field, i],
32
32
  index: i
33
33
  });
34
- return items$1;
34
+ return items;
35
35
  },
36
36
  isChanged(prev, next) {
37
37
  return prev.length !== next.length;
@@ -118,12 +118,12 @@ function getDefaultValue(defaultValue) {
118
118
  }
119
119
  var ListenerManager = class {
120
120
  constructor() {
121
- this.listeners = /* @__PURE__ */ new Set();
121
+ this.unindexed = /* @__PURE__ */ new Set();
122
122
  this.indexed = /* @__PURE__ */ new Map();
123
123
  }
124
124
  add(listener) {
125
125
  if (!listener.field) {
126
- this.listeners.add(listener);
126
+ this.unindexed.add(listener);
127
127
  return;
128
128
  }
129
129
  const key = stringifyFieldKey(listener.field);
@@ -132,27 +132,27 @@ var ListenerManager = class {
132
132
  this.indexed.set(key, set);
133
133
  }
134
134
  remove(listener) {
135
- if (!listener.field) this.listeners.delete(listener);
135
+ if (!listener.field) this.unindexed.delete(listener);
136
136
  else this.indexed.get(stringifyFieldKey(listener.field))?.delete(listener);
137
137
  }
138
138
  onUpdate(field, ctx) {
139
- for (const v of this.listeners) v.onUpdate?.(field, ctx);
139
+ for (const v of this.unindexed) v.onUpdate?.(field, ctx);
140
140
  const updatedKey = stringifyFieldKey(field);
141
141
  if (ctx.swallow) {
142
142
  const set = this.indexed.get(updatedKey);
143
143
  if (set) for (const v of set) v.onUpdate?.(field, ctx);
144
144
  } else for (const [k, listeners] of this.indexed.entries()) {
145
- if (k !== updatedKey && !k.startsWith(updatedKey + ".")) continue;
145
+ if (updatedKey.length !== 0 && k !== updatedKey && !k.startsWith(updatedKey + ".")) continue;
146
146
  for (const v of listeners) v.onUpdate?.(field, ctx);
147
147
  }
148
148
  }
149
149
  onInit(field) {
150
- for (const v of this.listeners) v.onInit?.(field);
150
+ for (const v of this.unindexed) v.onInit?.(field);
151
151
  const set = this.indexed.get(stringifyFieldKey(field));
152
152
  if (set) for (const v of set) v.onInit?.(field);
153
153
  }
154
154
  onDelete(field) {
155
- for (const v of this.listeners) v.onDelete?.(field);
155
+ for (const v of this.unindexed) v.onDelete?.(field);
156
156
  const set = this.indexed.get(stringifyFieldKey(field));
157
157
  if (set) for (const v of set) v.onDelete?.(field);
158
158
  }
@@ -249,8 +249,8 @@ var DataEngine = class {
249
249
  };
250
250
  }
251
251
  reset(data) {
252
- this.update([], data);
253
252
  this.attachedDataMap.clear();
253
+ this.update([], data);
254
254
  }
255
255
  };
256
256
  function useFieldValue(key, options = {}) {
@@ -295,5 +295,4 @@ function useListener(listener) {
295
295
  }
296
296
 
297
297
  //#endregion
298
- export { DataEngine, StfProvider, useArray, useDataEngine, useFieldValue, useListener, useObject, useStf };
299
- //# sourceMappingURL=index.js.map
298
+ export { DataEngine, StfProvider, useArray, useDataEngine, useFieldValue, useListener, useObject, useStf };
@@ -1,7 +1,6 @@
1
- import { t as FieldKey } from "../types-PXiOOMNs.js";
1
+ import { t as FieldKey } from "../types-Do_aTV5I.js";
2
2
 
3
3
  //#region src/lib/utils.d.ts
4
-
5
4
  /**
6
5
  * test if array a starts with array b, only compare values via `===`.
7
6
  */
@@ -19,5 +18,4 @@ declare function objectSet(obj: unknown, key: FieldKey, value: unknown): unknown
19
18
  declare function deepEqual(a: unknown, b: unknown): boolean;
20
19
  declare function stringifyFieldKey(fieldKey: FieldKey): string;
21
20
  //#endregion
22
- export { arrayStartsWith, deepEqual, objectGet, objectSet, stringifyFieldKey };
23
- //# sourceMappingURL=utils.d.ts.map
21
+ export { arrayStartsWith, deepEqual, objectGet, objectSet, stringifyFieldKey };
package/dist/lib/utils.js CHANGED
@@ -1,3 +1,52 @@
1
- import { a as stringifyFieldKey, i as objectSet, n as deepEqual, r as objectGet, t as arrayStartsWith } from "../utils-W82BoH4I.js";
1
+ //#region src/lib/utils.ts
2
+ /**
3
+ * test if array a starts with array b, only compare values via `===`.
4
+ */
5
+ function arrayStartsWith(a, b) {
6
+ if (b.length > a.length) return false;
7
+ for (let i = 0; i < b.length; i++) if (a[i] !== b[i]) return false;
8
+ return true;
9
+ }
10
+ function objectGet(obj, key) {
11
+ let cur = obj;
12
+ for (const prop of key) {
13
+ if (typeof cur !== "object" || cur === null || !(prop in cur)) return;
14
+ cur = cur[prop];
15
+ }
16
+ return cur;
17
+ }
18
+ /**
19
+ * set the value of field if it exists (in place)
20
+ *
21
+ * @returns updated value, throw error if parent object doesn't exist
22
+ */
23
+ function objectSet(obj, key, value) {
24
+ if (key.length === 0) return value;
25
+ const parent = objectGet(obj, key.slice(0, -1));
26
+ if (typeof parent !== "object" || parent === null) throw new Error("missing parent object");
27
+ parent[key[key.length - 1]] = value;
28
+ return obj;
29
+ }
30
+ /**
31
+ * doesn't handle recursive objects
32
+ */
33
+ function deepEqual(a, b) {
34
+ if (a === b) return true;
35
+ if (a == null || b == null) return false;
36
+ if (typeof a !== "object" || typeof b !== "object") return false;
37
+ if (Array.isArray(a) && Array.isArray(b)) {
38
+ if (a.length !== b.length) return false;
39
+ return a.every((item, index) => deepEqual(item, b[index]));
40
+ }
41
+ if (Array.isArray(a) || Array.isArray(b)) return false;
42
+ const keysA = Object.keys(a);
43
+ const keysB = Object.keys(b);
44
+ if (keysA.length !== keysB.length) return false;
45
+ return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && deepEqual(a[key], b[key]));
46
+ }
47
+ function stringifyFieldKey(fieldKey) {
48
+ return fieldKey.map((v) => `${typeof v}:${v}`).join(".");
49
+ }
2
50
 
51
+ //#endregion
3
52
  export { arrayStartsWith, deepEqual, objectGet, objectSet, stringifyFieldKey };
@@ -1,5 +1,4 @@
1
1
  //#region src/lib/types.d.ts
2
2
  type FieldKey = (string | number)[];
3
3
  //#endregion
4
- export { FieldKey as t };
5
- //# sourceMappingURL=types-PXiOOMNs.d.ts.map
4
+ export { FieldKey as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fumari/stf",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Schema to Form.",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -19,9 +19,9 @@
19
19
  "access": "public"
20
20
  },
21
21
  "devDependencies": {
22
- "@types/node": "25.0.5",
23
- "@types/react": "^19.2.8",
24
- "tsdown": "^0.19.0",
22
+ "@types/node": "25.2.1",
23
+ "@types/react": "^19.2.13",
24
+ "tsdown": "^0.20.3",
25
25
  "eslint-config-custom": "0.0.0",
26
26
  "tsconfig": "0.0.0"
27
27
  },
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/lib/stf.tsx","../src/lib/data-engine.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["items"],"sources":["../src/lib/stf.tsx","../src/lib/data-engine.ts"],"sourcesContent":["import { createContext, ReactNode, use, useMemo } from 'react';\nimport { DataEngine, DefaultValue, useFieldValue } from './data-engine';\nimport { FieldKey } from './types';\nimport { deepEqual } from './utils';\n\nconst Context = createContext<Stf | null>(null);\n\nexport interface Stf {\n dataEngine: DataEngine;\n}\n\nexport function StfProvider({ value, children }: { value: Stf; children: ReactNode }) {\n return <Context value={value}>{children}</Context>;\n}\n\nexport function useStf(options: {\n /**\n * Note: the passed object will be modified in place, use `structuredClone()` to keep the original object unchanged.\n */\n defaultValues?: DefaultValue<Record<string, unknown>>;\n}): Stf {\n const { defaultValues } = options;\n\n const dataEngine = useMemo(\n () => new DataEngine(defaultValues),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- assume unchanged\n [],\n );\n return useMemo(\n () => ({\n dataEngine,\n }),\n [dataEngine],\n );\n}\n\nexport function useDataEngine(stf?: Stf) {\n if (stf) return stf.dataEngine;\n return use(Context)!.dataEngine;\n}\n\nexport interface ArrayItemInfo {\n field: FieldKey;\n index: number;\n}\n\nexport function useArray(\n field: FieldKey,\n options: { defaultValue?: DefaultValue<unknown[]> } = {},\n) {\n const engine = useDataEngine();\n const [items] = useFieldValue(field, {\n defaultValue: options.defaultValue,\n compute(value) {\n const items: ArrayItemInfo[] = [];\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n items.push({\n field: [...field, i],\n index: i,\n });\n }\n }\n return items;\n },\n isChanged(prev, next) {\n return prev.length !== next.length;\n },\n });\n\n return {\n items,\n insertItem(itemValue?: unknown) {\n const value = engine.get(field);\n\n engine.update(field, Array.isArray(value) ? [...value, itemValue] : [itemValue]);\n },\n removeItem(index: number) {\n engine.delete([...field, index]);\n },\n };\n}\nexport type PropertyItemInfo<T> =\n | {\n kind: 'fixed' | 'fallback';\n field: FieldKey;\n key: string;\n info: T;\n }\n | {\n kind: 'pattern';\n field: FieldKey;\n key: string;\n pattern: string;\n info: T;\n };\n\nexport function useObject<T>(\n field: FieldKey,\n options: {\n defaultValue?: DefaultValue<object>;\n properties: Record<string, T>;\n patternProperties?: Record<string, T>;\n fallback?: T;\n },\n) {\n const engine = useDataEngine();\n const [objectKeys] = useFieldValue(field, {\n defaultValue: options.defaultValue,\n compute(currentValue) {\n return currentValue ? Object.keys(currentValue) : [];\n },\n isChanged(prev, next) {\n return !deepEqual(prev, next);\n },\n });\n\n const properties = useMemo(() => {\n const properties: PropertyItemInfo<T>[] = [];\n const unknownKeys = new Set(objectKeys);\n for (const [key, prop] of Object.entries(options.properties)) {\n unknownKeys.delete(key);\n properties.push({\n kind: 'fixed',\n field: [...field, key],\n key,\n info: prop,\n });\n }\n\n for (const [pattern, prop] of Object.entries(options.patternProperties ?? {})) {\n const regex = RegExp(pattern);\n\n for (const key of unknownKeys) {\n if (!key.match(regex)) continue;\n unknownKeys.delete(key);\n properties.push({\n kind: 'pattern',\n info: prop,\n key,\n pattern,\n field: [...field, key],\n });\n }\n }\n\n if (options.fallback) {\n for (const key of unknownKeys) {\n properties.push({\n kind: 'fallback',\n field: [...field, key],\n key,\n info: options.fallback,\n });\n }\n }\n\n return properties;\n }, [field, objectKeys, options.fallback, options.patternProperties, options.properties]);\n\n return {\n properties,\n onAppend(name: string, value?: unknown) {\n name = name.trim();\n if (name.length === 0) return;\n\n engine.init([...field, name], value);\n },\n onDelete(name: string) {\n return engine.delete([...field, name]);\n },\n };\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { objectGet, objectSet, stringifyFieldKey } from './utils';\nimport type { FieldKey } from './types';\nimport { Stf, useDataEngine } from './stf';\n\nexport type DefaultValue<T = unknown> = T | (() => T);\n\nfunction getDefaultValue<T>(defaultValue: DefaultValue<T>): T {\n return typeof defaultValue === 'function' ? (defaultValue as () => T)() : defaultValue;\n}\n\nexport interface DataEngineListener {\n /**\n * when specified, only call the listener for events affecting the specified field.\n */\n field?: FieldKey;\n /**\n * when field value is changed\n */\n onUpdate?: (key: FieldKey, ctx: OnUpdateContext) => void;\n /**\n * when `init(field)` is called\n */\n onInit?: (key: FieldKey) => void;\n /**\n * when `delete(field)` is called\n */\n onDelete?: (key: FieldKey) => void;\n}\n\ninterface OnUpdateContext {\n /**\n * An update is swallow if the change doesn't affect the values of children fields.\n */\n swallow: boolean;\n}\n\nclass ListenerManager {\n private readonly listeners = new Set<DataEngineListener>();\n private readonly indexed = new Map<string, Set<DataEngineListener>>();\n\n add(listener: DataEngineListener) {\n if (!listener.field) {\n this.listeners.add(listener);\n return;\n }\n const key = stringifyFieldKey(listener.field);\n const set = this.indexed.get(key) ?? new Set();\n set.add(listener);\n this.indexed.set(key, set);\n }\n\n remove(listener: DataEngineListener) {\n if (!listener.field) {\n this.listeners.delete(listener);\n } else {\n this.indexed.get(stringifyFieldKey(listener.field))?.delete(listener);\n }\n }\n\n onUpdate(field: FieldKey, ctx: OnUpdateContext) {\n for (const v of this.listeners) v.onUpdate?.(field, ctx);\n const updatedKey = stringifyFieldKey(field);\n\n if (ctx.swallow) {\n const set = this.indexed.get(updatedKey);\n if (set) for (const v of set) v.onUpdate?.(field, ctx);\n } else {\n for (const [k, listeners] of this.indexed.entries()) {\n if (k !== updatedKey && !k.startsWith(updatedKey + '.')) continue;\n for (const v of listeners) v.onUpdate?.(field, ctx);\n }\n }\n }\n\n onInit(field: FieldKey) {\n for (const v of this.listeners) v.onInit?.(field);\n const set = this.indexed.get(stringifyFieldKey(field));\n if (set) for (const v of set) v.onInit?.(field);\n }\n\n onDelete(field: FieldKey) {\n for (const v of this.listeners) v.onDelete?.(field);\n const set = this.indexed.get(stringifyFieldKey(field));\n if (set) for (const v of set) v.onDelete?.(field);\n }\n}\n\nexport class DataEngine {\n private data: NonNullable<object>;\n private attachedDataMap = new Map<string, unknown>();\n private readonly listeners = new ListenerManager();\n\n constructor(defaultValues: DefaultValue<NonNullable<object>> = {}) {\n this.data = getDefaultValue(defaultValues);\n }\n\n listen(listener: DataEngineListener) {\n this.listeners.add(listener);\n }\n\n unlisten(listener: DataEngineListener) {\n this.listeners.remove(listener);\n }\n\n getData() {\n return this.data;\n }\n\n /**\n * init a field\n * @param key the key of field\n * @param defaultValue the initial value, the field is also created for `undefined`\n * @returns the value of initialized field, or the current value of field if already initialized\n */\n init(key: FieldKey, defaultValue?: DefaultValue): unknown {\n if (key.length === 0) return this.data;\n let cur = this.data as Record<string, unknown>;\n const currentKey: FieldKey = [];\n\n for (let i = 0; i < key.length; i++) {\n const propKey = key[i];\n const propValue = cur[propKey];\n\n if (i === key.length - 1) {\n if (propValue !== undefined) return propValue;\n cur[propKey] = getDefaultValue(defaultValue);\n\n this.listeners.onUpdate(currentKey, { swallow: true });\n this.listeners.onInit(key);\n return cur[propKey];\n } else if (typeof propValue === 'object' && propValue !== null) {\n cur = propValue as Record<string, unknown>;\n } else {\n if (propValue !== undefined)\n console.warn(\n `the original value of field ${currentKey.join('.')} is overidden, this might be unexpected.`,\n );\n\n cur = cur[propKey] = {};\n this.listeners.onUpdate(currentKey, { swallow: true });\n }\n currentKey.push(propKey);\n }\n }\n\n delete(key: FieldKey): unknown | undefined {\n if (key.length === 0) return;\n const parentKey = key.slice(0, -1);\n const prop = key[key.length - 1];\n const parent = this.get(parentKey);\n\n if (Array.isArray(parent) && typeof prop === 'number') {\n const [deleted] = parent.splice(prop, 1);\n this.listeners.onUpdate(parentKey, { swallow: false });\n this.listeners.onDelete(key);\n return deleted;\n } else if (typeof parent === 'object' && parent !== null) {\n const temp = (parent as Record<string, unknown>)[prop];\n delete parent[prop as never];\n this.listeners.onUpdate(parentKey, { swallow: true });\n this.listeners.onDelete(key);\n return temp;\n }\n }\n\n get(key: FieldKey) {\n return objectGet(this.data, key);\n }\n\n /**\n * update the value of field if it exists\n * @returns if the field is updated\n */\n update(key: FieldKey, value: unknown): boolean {\n try {\n this.data = objectSet(this.data, key, value) as NonNullable<object>;\n this.listeners.onUpdate(key, { swallow: false });\n return true;\n } catch {\n return false;\n }\n }\n\n attachedData<T>(namespace: string) {\n return {\n get: (field: FieldKey): T | undefined => {\n return this.attachedDataMap.get(`${namespace}:${stringifyFieldKey(field)}`) as\n | T\n | undefined;\n },\n set: (field: FieldKey, value: T) => {\n this.attachedDataMap.set(`${namespace}:${stringifyFieldKey(field)}`, value);\n },\n delete: (field?: FieldKey) => {\n if (field) {\n this.attachedDataMap.delete(`${namespace}:${stringifyFieldKey(field)}`);\n } else {\n for (const key of this.attachedDataMap.keys()) {\n if (key.startsWith(`${namespace}:`)) this.attachedDataMap.delete(key);\n }\n }\n },\n };\n }\n\n reset(data: Record<string, unknown>) {\n this.update([], data);\n this.attachedDataMap.clear();\n }\n}\n\nexport function useFieldValue<V = unknown>(\n key: FieldKey,\n options: {\n stf?: Stf;\n defaultValue?: DefaultValue;\n\n /**\n * compute value from the actual field value.\n *\n * to re-compute on in-place updates (may happen on objects, arrays), you should clone the object here.\n */\n compute?: (currentValue: unknown) => V;\n /** determine whether the value/computed value is changed */\n isChanged?: (prev: V, next: V) => boolean;\n } = {},\n) {\n const engine = useDataEngine(options.stf);\n const { compute = (v) => v as V, defaultValue, isChanged = (a, b) => a !== b } = options;\n const [value, setValue] = useState<V>(() => compute(engine.init(key, defaultValue)));\n\n useListener({\n field: key,\n onUpdate() {\n const computed = compute(engine.get(key));\n if (isChanged(value, computed)) setValue(computed);\n },\n onDelete() {\n const computed = compute(undefined);\n if (isChanged(value, computed)) setValue(computed);\n },\n });\n\n return [value, (newValue: unknown) => engine.update(key, newValue)] as const;\n}\n\nexport function useListener(listener: DataEngineListener & { stf?: Stf }) {\n const engine = useDataEngine(listener.stf);\n const listenerRef = useRef(listener);\n listenerRef.current = listener;\n\n useEffect(() => {\n const internal: DataEngineListener = {\n field: listener.field,\n onDelete(...args) {\n return listenerRef.current.onDelete?.(...args);\n },\n onInit(...args) {\n return listenerRef.current.onInit?.(...args);\n },\n onUpdate(...args) {\n return listenerRef.current.onUpdate?.(...args);\n },\n };\n\n engine.listen(internal);\n return () => {\n engine.unlisten(internal);\n };\n }, [engine, listener.field]);\n}\n"],"mappings":";;;;;;;AAKA,MAAM,UAAU,cAA0B,KAAK;AAM/C,SAAgB,YAAY,EAAE,OAAO,YAAiD;AACpF,QAAO,oBAAC;EAAe;EAAQ;GAAmB;;AAGpD,SAAgB,OAAO,SAKf;CACN,MAAM,EAAE,kBAAkB;CAE1B,MAAM,aAAa,cACX,IAAI,WAAW,cAAc,EAEnC,EAAE,CACH;AACD,QAAO,eACE,EACL,YACD,GACD,CAAC,WAAW,CACb;;AAGH,SAAgB,cAAc,KAAW;AACvC,KAAI,IAAK,QAAO,IAAI;AACpB,QAAO,IAAI,QAAQ,CAAE;;AAQvB,SAAgB,SACd,OACA,UAAsD,EAAE,EACxD;CACA,MAAM,SAAS,eAAe;CAC9B,MAAM,CAAC,SAAS,cAAc,OAAO;EACnC,cAAc,QAAQ;EACtB,QAAQ,OAAO;GACb,MAAMA,UAAyB,EAAE;AACjC,OAAI,MAAM,QAAQ,MAAM,CACtB,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IAChC,SAAM,KAAK;IACT,OAAO,CAAC,GAAG,OAAO,EAAE;IACpB,OAAO;IACR,CAAC;AAGN,UAAOA;;EAET,UAAU,MAAM,MAAM;AACpB,UAAO,KAAK,WAAW,KAAK;;EAE/B,CAAC;AAEF,QAAO;EACL;EACA,WAAW,WAAqB;GAC9B,MAAM,QAAQ,OAAO,IAAI,MAAM;AAE/B,UAAO,OAAO,OAAO,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG,OAAO,UAAU,GAAG,CAAC,UAAU,CAAC;;EAElF,WAAW,OAAe;AACxB,UAAO,OAAO,CAAC,GAAG,OAAO,MAAM,CAAC;;EAEnC;;AAiBH,SAAgB,UACd,OACA,SAMA;CACA,MAAM,SAAS,eAAe;CAC9B,MAAM,CAAC,cAAc,cAAc,OAAO;EACxC,cAAc,QAAQ;EACtB,QAAQ,cAAc;AACpB,UAAO,eAAe,OAAO,KAAK,aAAa,GAAG,EAAE;;EAEtD,UAAU,MAAM,MAAM;AACpB,UAAO,CAAC,UAAU,MAAM,KAAK;;EAEhC,CAAC;AA6CF,QAAO;EACL,YA5CiB,cAAc;GAC/B,MAAM,aAAoC,EAAE;GAC5C,MAAM,cAAc,IAAI,IAAI,WAAW;AACvC,QAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,QAAQ,WAAW,EAAE;AAC5D,gBAAY,OAAO,IAAI;AACvB,eAAW,KAAK;KACd,MAAM;KACN,OAAO,CAAC,GAAG,OAAO,IAAI;KACtB;KACA,MAAM;KACP,CAAC;;AAGJ,QAAK,MAAM,CAAC,SAAS,SAAS,OAAO,QAAQ,QAAQ,qBAAqB,EAAE,CAAC,EAAE;IAC7E,MAAM,QAAQ,OAAO,QAAQ;AAE7B,SAAK,MAAM,OAAO,aAAa;AAC7B,SAAI,CAAC,IAAI,MAAM,MAAM,CAAE;AACvB,iBAAY,OAAO,IAAI;AACvB,gBAAW,KAAK;MACd,MAAM;MACN,MAAM;MACN;MACA;MACA,OAAO,CAAC,GAAG,OAAO,IAAI;MACvB,CAAC;;;AAIN,OAAI,QAAQ,SACV,MAAK,MAAM,OAAO,YAChB,YAAW,KAAK;IACd,MAAM;IACN,OAAO,CAAC,GAAG,OAAO,IAAI;IACtB;IACA,MAAM,QAAQ;IACf,CAAC;AAIN,UAAO;KACN;GAAC;GAAO;GAAY,QAAQ;GAAU,QAAQ;GAAmB,QAAQ;GAAW,CAAC;EAItF,SAAS,MAAc,OAAiB;AACtC,UAAO,KAAK,MAAM;AAClB,OAAI,KAAK,WAAW,EAAG;AAEvB,UAAO,KAAK,CAAC,GAAG,OAAO,KAAK,EAAE,MAAM;;EAEtC,SAAS,MAAc;AACrB,UAAO,OAAO,OAAO,CAAC,GAAG,OAAO,KAAK,CAAC;;EAEzC;;;;;ACpKH,SAAS,gBAAmB,cAAkC;AAC5D,QAAO,OAAO,iBAAiB,aAAc,cAA0B,GAAG;;AA6B5E,IAAM,kBAAN,MAAsB;;mCACS,IAAI,KAAyB;iCAC/B,IAAI,KAAsC;;CAErE,IAAI,UAA8B;AAChC,MAAI,CAAC,SAAS,OAAO;AACnB,QAAK,UAAU,IAAI,SAAS;AAC5B;;EAEF,MAAM,MAAM,kBAAkB,SAAS,MAAM;EAC7C,MAAM,MAAM,KAAK,QAAQ,IAAI,IAAI,oBAAI,IAAI,KAAK;AAC9C,MAAI,IAAI,SAAS;AACjB,OAAK,QAAQ,IAAI,KAAK,IAAI;;CAG5B,OAAO,UAA8B;AACnC,MAAI,CAAC,SAAS,MACZ,MAAK,UAAU,OAAO,SAAS;MAE/B,MAAK,QAAQ,IAAI,kBAAkB,SAAS,MAAM,CAAC,EAAE,OAAO,SAAS;;CAIzE,SAAS,OAAiB,KAAsB;AAC9C,OAAK,MAAM,KAAK,KAAK,UAAW,GAAE,WAAW,OAAO,IAAI;EACxD,MAAM,aAAa,kBAAkB,MAAM;AAE3C,MAAI,IAAI,SAAS;GACf,MAAM,MAAM,KAAK,QAAQ,IAAI,WAAW;AACxC,OAAI,IAAK,MAAK,MAAM,KAAK,IAAK,GAAE,WAAW,OAAO,IAAI;QAEtD,MAAK,MAAM,CAAC,GAAG,cAAc,KAAK,QAAQ,SAAS,EAAE;AACnD,OAAI,MAAM,cAAc,CAAC,EAAE,WAAW,aAAa,IAAI,CAAE;AACzD,QAAK,MAAM,KAAK,UAAW,GAAE,WAAW,OAAO,IAAI;;;CAKzD,OAAO,OAAiB;AACtB,OAAK,MAAM,KAAK,KAAK,UAAW,GAAE,SAAS,MAAM;EACjD,MAAM,MAAM,KAAK,QAAQ,IAAI,kBAAkB,MAAM,CAAC;AACtD,MAAI,IAAK,MAAK,MAAM,KAAK,IAAK,GAAE,SAAS,MAAM;;CAGjD,SAAS,OAAiB;AACxB,OAAK,MAAM,KAAK,KAAK,UAAW,GAAE,WAAW,MAAM;EACnD,MAAM,MAAM,KAAK,QAAQ,IAAI,kBAAkB,MAAM,CAAC;AACtD,MAAI,IAAK,MAAK,MAAM,KAAK,IAAK,GAAE,WAAW,MAAM;;;AAIrD,IAAa,aAAb,MAAwB;CAKtB,YAAY,gBAAmD,EAAE,EAAE;yCAHzC,IAAI,KAAsB;mBACvB,IAAI,iBAAiB;AAGhD,OAAK,OAAO,gBAAgB,cAAc;;CAG5C,OAAO,UAA8B;AACnC,OAAK,UAAU,IAAI,SAAS;;CAG9B,SAAS,UAA8B;AACrC,OAAK,UAAU,OAAO,SAAS;;CAGjC,UAAU;AACR,SAAO,KAAK;;;;;;;;CASd,KAAK,KAAe,cAAsC;AACxD,MAAI,IAAI,WAAW,EAAG,QAAO,KAAK;EAClC,IAAI,MAAM,KAAK;EACf,MAAM,aAAuB,EAAE;AAE/B,OAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;GACnC,MAAM,UAAU,IAAI;GACpB,MAAM,YAAY,IAAI;AAEtB,OAAI,MAAM,IAAI,SAAS,GAAG;AACxB,QAAI,cAAc,OAAW,QAAO;AACpC,QAAI,WAAW,gBAAgB,aAAa;AAE5C,SAAK,UAAU,SAAS,YAAY,EAAE,SAAS,MAAM,CAAC;AACtD,SAAK,UAAU,OAAO,IAAI;AAC1B,WAAO,IAAI;cACF,OAAO,cAAc,YAAY,cAAc,KACxD,OAAM;QACD;AACL,QAAI,cAAc,OAChB,SAAQ,KACN,+BAA+B,WAAW,KAAK,IAAI,CAAC,0CACrD;AAEH,UAAM,IAAI,WAAW,EAAE;AACvB,SAAK,UAAU,SAAS,YAAY,EAAE,SAAS,MAAM,CAAC;;AAExD,cAAW,KAAK,QAAQ;;;CAI5B,OAAO,KAAoC;AACzC,MAAI,IAAI,WAAW,EAAG;EACtB,MAAM,YAAY,IAAI,MAAM,GAAG,GAAG;EAClC,MAAM,OAAO,IAAI,IAAI,SAAS;EAC9B,MAAM,SAAS,KAAK,IAAI,UAAU;AAElC,MAAI,MAAM,QAAQ,OAAO,IAAI,OAAO,SAAS,UAAU;GACrD,MAAM,CAAC,WAAW,OAAO,OAAO,MAAM,EAAE;AACxC,QAAK,UAAU,SAAS,WAAW,EAAE,SAAS,OAAO,CAAC;AACtD,QAAK,UAAU,SAAS,IAAI;AAC5B,UAAO;aACE,OAAO,WAAW,YAAY,WAAW,MAAM;GACxD,MAAM,OAAQ,OAAmC;AACjD,UAAO,OAAO;AACd,QAAK,UAAU,SAAS,WAAW,EAAE,SAAS,MAAM,CAAC;AACrD,QAAK,UAAU,SAAS,IAAI;AAC5B,UAAO;;;CAIX,IAAI,KAAe;AACjB,SAAO,UAAU,KAAK,MAAM,IAAI;;;;;;CAOlC,OAAO,KAAe,OAAyB;AAC7C,MAAI;AACF,QAAK,OAAO,UAAU,KAAK,MAAM,KAAK,MAAM;AAC5C,QAAK,UAAU,SAAS,KAAK,EAAE,SAAS,OAAO,CAAC;AAChD,UAAO;UACD;AACN,UAAO;;;CAIX,aAAgB,WAAmB;AACjC,SAAO;GACL,MAAM,UAAmC;AACvC,WAAO,KAAK,gBAAgB,IAAI,GAAG,UAAU,GAAG,kBAAkB,MAAM,GAAG;;GAI7E,MAAM,OAAiB,UAAa;AAClC,SAAK,gBAAgB,IAAI,GAAG,UAAU,GAAG,kBAAkB,MAAM,IAAI,MAAM;;GAE7E,SAAS,UAAqB;AAC5B,QAAI,MACF,MAAK,gBAAgB,OAAO,GAAG,UAAU,GAAG,kBAAkB,MAAM,GAAG;QAEvE,MAAK,MAAM,OAAO,KAAK,gBAAgB,MAAM,CAC3C,KAAI,IAAI,WAAW,GAAG,UAAU,GAAG,CAAE,MAAK,gBAAgB,OAAO,IAAI;;GAI5E;;CAGH,MAAM,MAA+B;AACnC,OAAK,OAAO,EAAE,EAAE,KAAK;AACrB,OAAK,gBAAgB,OAAO;;;AAIhC,SAAgB,cACd,KACA,UAYI,EAAE,EACN;CACA,MAAM,SAAS,cAAc,QAAQ,IAAI;CACzC,MAAM,EAAE,WAAW,MAAM,GAAQ,cAAc,aAAa,GAAG,MAAM,MAAM,MAAM;CACjF,MAAM,CAAC,OAAO,YAAY,eAAkB,QAAQ,OAAO,KAAK,KAAK,aAAa,CAAC,CAAC;AAEpF,aAAY;EACV,OAAO;EACP,WAAW;GACT,MAAM,WAAW,QAAQ,OAAO,IAAI,IAAI,CAAC;AACzC,OAAI,UAAU,OAAO,SAAS,CAAE,UAAS,SAAS;;EAEpD,WAAW;GACT,MAAM,WAAW,QAAQ,OAAU;AACnC,OAAI,UAAU,OAAO,SAAS,CAAE,UAAS,SAAS;;EAErD,CAAC;AAEF,QAAO,CAAC,QAAQ,aAAsB,OAAO,OAAO,KAAK,SAAS,CAAC;;AAGrE,SAAgB,YAAY,UAA8C;CACxE,MAAM,SAAS,cAAc,SAAS,IAAI;CAC1C,MAAM,cAAc,OAAO,SAAS;AACpC,aAAY,UAAU;AAEtB,iBAAgB;EACd,MAAM,WAA+B;GACnC,OAAO,SAAS;GAChB,SAAS,GAAG,MAAM;AAChB,WAAO,YAAY,QAAQ,WAAW,GAAG,KAAK;;GAEhD,OAAO,GAAG,MAAM;AACd,WAAO,YAAY,QAAQ,SAAS,GAAG,KAAK;;GAE9C,SAAS,GAAG,MAAM;AAChB,WAAO,YAAY,QAAQ,WAAW,GAAG,KAAK;;GAEjD;AAED,SAAO,OAAO,SAAS;AACvB,eAAa;AACX,UAAO,SAAS,SAAS;;IAE1B,CAAC,QAAQ,SAAS,MAAM,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/lib/utils.ts"],"sourcesContent":[],"mappings":";;;;;;AAKA;AAUgB,iBAVA,eAAA,CAUS,CAAA,EAAA,OAAA,EAAA,EAAA,CAAA,EAAA,OAAA,EAAA,CAAA,EAAA,OAAA;AAiBT,iBAjBA,SAAA,CAiB6B,GAAQ,EAAA,OAAA,EAAA,GAAA,EAAA,CAAA,MAAA,GAAA,MAAA,CAAA,EAAA,CAAA,EAAA,OAAA,GAAA,SAAA;AAcrD;AAsCA;;;;iBApDgB,SAAA,oBAA6B;;;;iBAc7B,SAAA;iBAsCA,iBAAA,WAA4B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-PXiOOMNs.d.ts","names":[],"sources":["../src/lib/types.ts"],"sourcesContent":[],"mappings":";KAAY,QAAA"}
@@ -1,53 +0,0 @@
1
- //#region src/lib/utils.ts
2
- /**
3
- * test if array a starts with array b, only compare values via `===`.
4
- */
5
- function arrayStartsWith(a, b) {
6
- if (b.length > a.length) return false;
7
- for (let i = 0; i < b.length; i++) if (a[i] !== b[i]) return false;
8
- return true;
9
- }
10
- function objectGet(obj, key) {
11
- let cur = obj;
12
- for (const prop of key) {
13
- if (typeof cur !== "object" || cur === null || !(prop in cur)) return;
14
- cur = cur[prop];
15
- }
16
- return cur;
17
- }
18
- /**
19
- * set the value of field if it exists (in place)
20
- *
21
- * @returns updated value, throw error if parent object doesn't exist
22
- */
23
- function objectSet(obj, key, value) {
24
- if (key.length === 0) return value;
25
- const parent = objectGet(obj, key.slice(0, -1));
26
- if (typeof parent !== "object" || parent === null) throw new Error("missing parent object");
27
- parent[key[key.length - 1]] = value;
28
- return obj;
29
- }
30
- /**
31
- * doesn't handle recursive objects
32
- */
33
- function deepEqual(a, b) {
34
- if (a === b) return true;
35
- if (a == null || b == null) return false;
36
- if (typeof a !== "object" || typeof b !== "object") return false;
37
- if (Array.isArray(a) && Array.isArray(b)) {
38
- if (a.length !== b.length) return false;
39
- return a.every((item, index) => deepEqual(item, b[index]));
40
- }
41
- if (Array.isArray(a) || Array.isArray(b)) return false;
42
- const keysA = Object.keys(a);
43
- const keysB = Object.keys(b);
44
- if (keysA.length !== keysB.length) return false;
45
- return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && deepEqual(a[key], b[key]));
46
- }
47
- function stringifyFieldKey(fieldKey) {
48
- return fieldKey.map((v) => `${typeof v}:${v}`).join(".");
49
- }
50
-
51
- //#endregion
52
- export { stringifyFieldKey as a, objectSet as i, deepEqual as n, objectGet as r, arrayStartsWith as t };
53
- //# sourceMappingURL=utils-W82BoH4I.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils-W82BoH4I.js","names":[],"sources":["../src/lib/utils.ts"],"sourcesContent":["import { FieldKey } from './types';\n\n/**\n * test if array a starts with array b, only compare values via `===`.\n */\nexport function arrayStartsWith(a: unknown[], b: unknown[]): boolean {\n if (b.length > a.length) return false;\n\n for (let i = 0; i < b.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n\n return true;\n}\n\nexport function objectGet(obj: unknown, key: (string | number)[]): unknown | undefined {\n let cur = obj;\n\n for (const prop of key) {\n if (typeof cur !== 'object' || cur === null || !(prop in cur)) return;\n\n cur = cur[prop as keyof typeof cur];\n }\n\n return cur;\n}\n\n/**\n * set the value of field if it exists (in place)\n *\n * @returns updated value, throw error if parent object doesn't exist\n */\nexport function objectSet(obj: unknown, key: FieldKey, value: unknown): unknown {\n if (key.length === 0) {\n return value;\n }\n\n const parent = objectGet(obj, key.slice(0, -1));\n if (typeof parent !== 'object' || parent === null) throw new Error('missing parent object');\n (parent as Record<string, unknown>)[key[key.length - 1]] = value;\n return obj;\n}\n\n/**\n * doesn't handle recursive objects\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) {\n return true;\n }\n\n if (a == null || b == null) {\n return false;\n }\n\n if (typeof a !== 'object' || typeof b !== 'object') {\n return false;\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n return a.every((item, index) => deepEqual(item, b[index]));\n }\n\n if (Array.isArray(a) || Array.isArray(b)) {\n return false;\n }\n\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n return keysA.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(b, key) &&\n deepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n );\n}\n\nexport function stringifyFieldKey(fieldKey: FieldKey) {\n return fieldKey.map((v) => `${typeof v}:${v}`).join('.');\n}\n"],"mappings":";;;;AAKA,SAAgB,gBAAgB,GAAc,GAAuB;AACnE,KAAI,EAAE,SAAS,EAAE,OAAQ,QAAO;AAEhC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,KAAI,EAAE,OAAO,EAAE,GAAI,QAAO;AAG5B,QAAO;;AAGT,SAAgB,UAAU,KAAc,KAA+C;CACrF,IAAI,MAAM;AAEV,MAAK,MAAM,QAAQ,KAAK;AACtB,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,EAAE,QAAQ,KAAM;AAE/D,QAAM,IAAI;;AAGZ,QAAO;;;;;;;AAQT,SAAgB,UAAU,KAAc,KAAe,OAAyB;AAC9E,KAAI,IAAI,WAAW,EACjB,QAAO;CAGT,MAAM,SAAS,UAAU,KAAK,IAAI,MAAM,GAAG,GAAG,CAAC;AAC/C,KAAI,OAAO,WAAW,YAAY,WAAW,KAAM,OAAM,IAAI,MAAM,wBAAwB;AAC3F,CAAC,OAAmC,IAAI,IAAI,SAAS,MAAM;AAC3D,QAAO;;;;;AAMT,SAAgB,UAAU,GAAY,GAAqB;AACzD,KAAI,MAAM,EACR,QAAO;AAGT,KAAI,KAAK,QAAQ,KAAK,KACpB,QAAO;AAGT,KAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SACxC,QAAO;AAGT,KAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,EAAE;AACxC,MAAI,EAAE,WAAW,EAAE,OACjB,QAAO;AAET,SAAO,EAAE,OAAO,MAAM,UAAU,UAAU,MAAM,EAAE,OAAO,CAAC;;AAG5D,KAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,CACtC,QAAO;CAGT,MAAM,QAAQ,OAAO,KAAK,EAAY;CACtC,MAAM,QAAQ,OAAO,KAAK,EAAY;AAEtC,KAAI,MAAM,WAAW,MAAM,OACzB,QAAO;AAGT,QAAO,MAAM,OACV,QACC,OAAO,UAAU,eAAe,KAAK,GAAG,IAAI,IAC5C,UAAW,EAA8B,MAAO,EAA8B,KAAK,CACtF;;AAGH,SAAgB,kBAAkB,UAAoB;AACpD,QAAO,SAAS,KAAK,MAAM,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI"}