@kontsedal/olas-core 0.0.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 +39 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +22 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +39 -10
- package/dist/index.mjs.map +1 -1
- package/dist/{root-BCZDC5Fv.mjs → root-De-6KWIZ.mjs} +309 -11
- package/dist/root-De-6KWIZ.mjs.map +1 -0
- package/dist/{root-DXV1gVbQ.cjs → root-XKEsSmcd.cjs} +309 -11
- 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-CffZ1QXt.d.cts → types-C-zV1JZA.d.mts} +134 -4
- package/dist/types-C-zV1JZA.d.mts.map +1 -0
- package/dist/{types-DSlDowpE.d.mts → types-DKfpkm17.d.cts} +134 -4
- 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 +317 -3
- package/src/controller/types.ts +131 -0
- package/src/emitter.ts +34 -3
- package/src/forms/form.ts +47 -5
- package/src/index.ts +7 -1
- 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 +8 -4
- package/dist/root-BCZDC5Fv.mjs.map +0 -1
- package/dist/root-DXV1gVbQ.cjs.map +0 -1
- package/dist/types-CffZ1QXt.d.cts.map +0 -1
- package/dist/types-DSlDowpE.d.mts.map +0 -1
|
@@ -212,14 +212,16 @@ function untracked(fn) {
|
|
|
212
212
|
//#endregion
|
|
213
213
|
//#region src/utils.ts
|
|
214
214
|
/**
|
|
215
|
-
* True iff `err`
|
|
216
|
-
*
|
|
215
|
+
* True iff `err` looks like an AbortError. Matches the standard `DOMException`
|
|
216
|
+
* shape thrown by `AbortController` AND any object whose `name === 'AbortError'`
|
|
217
|
+
* — that covers axios / msw / user-thrown plain Errors that signal abort.
|
|
217
218
|
*
|
|
218
|
-
* Spec: §20.12
|
|
219
|
-
*
|
|
219
|
+
* Spec: §20.12. Node 17+ exposes a global DOMException, so the instanceof
|
|
220
|
+
* branch works server-side; the name-based branch is the portable fallback.
|
|
220
221
|
*/
|
|
221
222
|
function isAbortError(err) {
|
|
222
223
|
if (typeof DOMException !== "undefined" && err instanceof DOMException) return err.name === "AbortError";
|
|
224
|
+
if (err != null && typeof err === "object" && "name" in err) return err.name === "AbortError";
|
|
223
225
|
return false;
|
|
224
226
|
}
|
|
225
227
|
/**
|
|
@@ -1630,12 +1632,25 @@ function waitUntilFalse(sig) {
|
|
|
1630
1632
|
//#endregion
|
|
1631
1633
|
//#region src/emitter.ts
|
|
1632
1634
|
var EmitterImpl = class {
|
|
1635
|
+
onError;
|
|
1633
1636
|
handlers = /* @__PURE__ */ new Set();
|
|
1634
1637
|
disposed = false;
|
|
1638
|
+
constructor(onError) {
|
|
1639
|
+
this.onError = onError;
|
|
1640
|
+
}
|
|
1635
1641
|
emit(value) {
|
|
1636
1642
|
if (this.disposed) return;
|
|
1637
1643
|
const snapshot = Array.from(this.handlers);
|
|
1638
|
-
for (const handler of snapshot)
|
|
1644
|
+
for (const handler of snapshot) try {
|
|
1645
|
+
handler(value);
|
|
1646
|
+
} catch (err) {
|
|
1647
|
+
if (this.onError) try {
|
|
1648
|
+
this.onError(err);
|
|
1649
|
+
} catch {
|
|
1650
|
+
console.error("[olas] emitter handler threw and reporter threw:", err);
|
|
1651
|
+
}
|
|
1652
|
+
else console.error("[olas] emitter handler threw:", err);
|
|
1653
|
+
}
|
|
1639
1654
|
}
|
|
1640
1655
|
on(handler) {
|
|
1641
1656
|
if (this.disposed) return () => {};
|
|
@@ -1667,9 +1682,14 @@ var EmitterImpl = class {
|
|
|
1667
1682
|
* (or the emitter is disposed). Use this for emitters that live outside any
|
|
1668
1683
|
* single controller — typically in deps. Use `ctx.emitter()` for emitters that
|
|
1669
1684
|
* should auto-clean with a controller.
|
|
1685
|
+
*
|
|
1686
|
+
* Pass `onError` to receive emit-time handler throws (spec §20.6 — one
|
|
1687
|
+
* throwing handler must not block the rest of the fan-out). `ctx.emitter()`
|
|
1688
|
+
* wires this to the root's `onError` so deps-level emitters get isolation
|
|
1689
|
+
* by default when constructed via `ctx`.
|
|
1670
1690
|
*/
|
|
1671
|
-
function createEmitter() {
|
|
1672
|
-
const impl = new EmitterImpl();
|
|
1691
|
+
function createEmitter(options) {
|
|
1692
|
+
const impl = new EmitterImpl(options?.onError);
|
|
1673
1693
|
return {
|
|
1674
1694
|
emit: ((value) => impl.emit(value)),
|
|
1675
1695
|
on: (handler) => impl.on(handler),
|
|
@@ -2034,8 +2054,23 @@ var FormImpl = class {
|
|
|
2034
2054
|
else child.set(val);
|
|
2035
2055
|
else if (isFieldArray(child)) {
|
|
2036
2056
|
const arr = child;
|
|
2037
|
-
|
|
2038
|
-
|
|
2057
|
+
const newValues = val;
|
|
2058
|
+
if (asInitial) {
|
|
2059
|
+
arr.clear();
|
|
2060
|
+
for (const itemVal of newValues) arr.add(itemVal);
|
|
2061
|
+
arr.replaceInitialItems(newValues);
|
|
2062
|
+
} else {
|
|
2063
|
+
const current = arr.items.peek();
|
|
2064
|
+
const overlap = Math.min(current.length, newValues.length);
|
|
2065
|
+
for (let i = 0; i < overlap; i++) {
|
|
2066
|
+
const item = current[i];
|
|
2067
|
+
const v = newValues[i];
|
|
2068
|
+
if (isForm(item)) item.set(v);
|
|
2069
|
+
else item.set(v);
|
|
2070
|
+
}
|
|
2071
|
+
for (let i = current.length; i < newValues.length; i++) arr.add(newValues[i]);
|
|
2072
|
+
for (let i = current.length - 1; i >= newValues.length; i--) arr.remove(i);
|
|
2073
|
+
}
|
|
2039
2074
|
} else {
|
|
2040
2075
|
const f = child;
|
|
2041
2076
|
if (asInitial) f.setAsInitial(val);
|
|
@@ -2283,6 +2318,15 @@ var FieldArrayImpl = class {
|
|
|
2283
2318
|
for (const item of this.items$.peek()) item.dispose?.();
|
|
2284
2319
|
this.items$.set([]);
|
|
2285
2320
|
}
|
|
2321
|
+
/**
|
|
2322
|
+
* Internal — used by `Form.resetWithInitial` to re-anchor the array's
|
|
2323
|
+
* initial items after a parent-driven `applyPartial(..., asInitial: true)`.
|
|
2324
|
+
* Without this, a subsequent `reset()` would revert to the construction-
|
|
2325
|
+
* time initials rather than the most-recently-applied ones.
|
|
2326
|
+
*/
|
|
2327
|
+
replaceInitialItems(items) {
|
|
2328
|
+
this.initialItems = [...items];
|
|
2329
|
+
}
|
|
2286
2330
|
reset() {
|
|
2287
2331
|
if (this.disposed) return;
|
|
2288
2332
|
batch(() => {
|
|
@@ -3228,7 +3272,12 @@ var ControllerInstance = class ControllerInstance {
|
|
|
3228
3272
|
return m;
|
|
3229
3273
|
},
|
|
3230
3274
|
emitter() {
|
|
3231
|
-
const e = createEmitter()
|
|
3275
|
+
const e = createEmitter({ onError: (err) => {
|
|
3276
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3277
|
+
kind: "emitter",
|
|
3278
|
+
controllerPath: self.path
|
|
3279
|
+
});
|
|
3280
|
+
} });
|
|
3232
3281
|
self.entries.push({
|
|
3233
3282
|
kind: "cleanup",
|
|
3234
3283
|
dispose: () => e.dispose()
|
|
@@ -3395,6 +3444,255 @@ var ControllerInstance = class ControllerInstance {
|
|
|
3395
3444
|
}
|
|
3396
3445
|
};
|
|
3397
3446
|
},
|
|
3447
|
+
session(def, props, options) {
|
|
3448
|
+
const segment = self.makeChildSegment(getFactory(def), getName(def));
|
|
3449
|
+
const override = options?.deps;
|
|
3450
|
+
const childDeps = override !== void 0 ? {
|
|
3451
|
+
...self.deps,
|
|
3452
|
+
...override
|
|
3453
|
+
} : self.deps;
|
|
3454
|
+
const childInstance = new ControllerInstance(self, self.rootShared, segment, childDeps);
|
|
3455
|
+
const api = childInstance.construct(getFactory(def), props);
|
|
3456
|
+
const entry = {
|
|
3457
|
+
kind: "child",
|
|
3458
|
+
instance: childInstance
|
|
3459
|
+
};
|
|
3460
|
+
self.entries.push(entry);
|
|
3461
|
+
let disposed = false;
|
|
3462
|
+
const dispose = () => {
|
|
3463
|
+
if (disposed) return;
|
|
3464
|
+
disposed = true;
|
|
3465
|
+
const idx = self.entries.indexOf(entry);
|
|
3466
|
+
if (idx >= 0) self.entries.splice(idx, 1);
|
|
3467
|
+
try {
|
|
3468
|
+
childInstance.dispose();
|
|
3469
|
+
} catch (err) {
|
|
3470
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3471
|
+
kind: "effect",
|
|
3472
|
+
controllerPath: self.path
|
|
3473
|
+
});
|
|
3474
|
+
}
|
|
3475
|
+
};
|
|
3476
|
+
return [api, dispose];
|
|
3477
|
+
},
|
|
3478
|
+
collection(options) {
|
|
3479
|
+
const childMap = /* @__PURE__ */ new Map();
|
|
3480
|
+
const items$ = signal([]);
|
|
3481
|
+
const size$ = computed(() => items$.value.length);
|
|
3482
|
+
const isFactoryForm = options.factory !== void 0;
|
|
3483
|
+
const buildChild = (item) => {
|
|
3484
|
+
let def;
|
|
3485
|
+
let childProps;
|
|
3486
|
+
if (isFactoryForm) {
|
|
3487
|
+
const result = options.factory(item);
|
|
3488
|
+
def = result.controller;
|
|
3489
|
+
childProps = result.props;
|
|
3490
|
+
} else {
|
|
3491
|
+
const homoOpts = options;
|
|
3492
|
+
def = homoOpts.controller;
|
|
3493
|
+
childProps = homoOpts.propsOf(item);
|
|
3494
|
+
}
|
|
3495
|
+
const segment = self.makeChildSegment(getFactory(def), getName(def));
|
|
3496
|
+
const childDeps = options.deps !== void 0 ? {
|
|
3497
|
+
...self.deps,
|
|
3498
|
+
...options.deps
|
|
3499
|
+
} : self.deps;
|
|
3500
|
+
const instance = new ControllerInstance(self, self.rootShared, segment, childDeps);
|
|
3501
|
+
try {
|
|
3502
|
+
return {
|
|
3503
|
+
instance,
|
|
3504
|
+
api: instance.construct(getFactory(def), childProps),
|
|
3505
|
+
def
|
|
3506
|
+
};
|
|
3507
|
+
} catch (err) {
|
|
3508
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3509
|
+
kind: "construction",
|
|
3510
|
+
controllerPath: self.path
|
|
3511
|
+
});
|
|
3512
|
+
return null;
|
|
3513
|
+
}
|
|
3514
|
+
};
|
|
3515
|
+
const removeKey = (key) => {
|
|
3516
|
+
const info = childMap.get(key);
|
|
3517
|
+
if (info === void 0) return;
|
|
3518
|
+
childMap.delete(key);
|
|
3519
|
+
const idx = self.entries.indexOf(info.entry);
|
|
3520
|
+
if (idx >= 0) self.entries.splice(idx, 1);
|
|
3521
|
+
try {
|
|
3522
|
+
info.instance.dispose();
|
|
3523
|
+
} catch (err) {
|
|
3524
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3525
|
+
kind: "effect",
|
|
3526
|
+
controllerPath: self.path
|
|
3527
|
+
});
|
|
3528
|
+
}
|
|
3529
|
+
};
|
|
3530
|
+
const reconcile = () => {
|
|
3531
|
+
const source = options.source.value;
|
|
3532
|
+
const itemByKey = /* @__PURE__ */ new Map();
|
|
3533
|
+
for (const item of source) {
|
|
3534
|
+
const key = options.keyOf(item);
|
|
3535
|
+
if (!itemByKey.has(key)) itemByKey.set(key, item);
|
|
3536
|
+
}
|
|
3537
|
+
for (const key of [...childMap.keys()]) if (!itemByKey.has(key)) removeKey(key);
|
|
3538
|
+
for (const [key, item] of itemByKey) {
|
|
3539
|
+
const existing = childMap.get(key);
|
|
3540
|
+
if (existing !== void 0) {
|
|
3541
|
+
if (isFactoryForm) {
|
|
3542
|
+
if (options.factory(item).controller !== existing.def) {
|
|
3543
|
+
removeKey(key);
|
|
3544
|
+
const built = buildChild(item);
|
|
3545
|
+
if (built !== null) {
|
|
3546
|
+
const entry = {
|
|
3547
|
+
kind: "child",
|
|
3548
|
+
instance: built.instance
|
|
3549
|
+
};
|
|
3550
|
+
self.entries.push(entry);
|
|
3551
|
+
childMap.set(key, {
|
|
3552
|
+
...built,
|
|
3553
|
+
entry
|
|
3554
|
+
});
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
continue;
|
|
3559
|
+
}
|
|
3560
|
+
const built = buildChild(item);
|
|
3561
|
+
if (built !== null) {
|
|
3562
|
+
const entry = {
|
|
3563
|
+
kind: "child",
|
|
3564
|
+
instance: built.instance
|
|
3565
|
+
};
|
|
3566
|
+
self.entries.push(entry);
|
|
3567
|
+
childMap.set(key, {
|
|
3568
|
+
...built,
|
|
3569
|
+
entry
|
|
3570
|
+
});
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
const next = [];
|
|
3574
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3575
|
+
for (const item of source) {
|
|
3576
|
+
const key = options.keyOf(item);
|
|
3577
|
+
if (seen.has(key)) continue;
|
|
3578
|
+
seen.add(key);
|
|
3579
|
+
const info = childMap.get(key);
|
|
3580
|
+
if (info !== void 0) next.push({
|
|
3581
|
+
key,
|
|
3582
|
+
api: info.api
|
|
3583
|
+
});
|
|
3584
|
+
}
|
|
3585
|
+
items$.set(next);
|
|
3586
|
+
};
|
|
3587
|
+
const wrapped = () => {
|
|
3588
|
+
try {
|
|
3589
|
+
reconcile();
|
|
3590
|
+
} catch (err) {
|
|
3591
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3592
|
+
kind: "effect",
|
|
3593
|
+
controllerPath: self.path
|
|
3594
|
+
});
|
|
3595
|
+
}
|
|
3596
|
+
};
|
|
3597
|
+
const effectEntry = {
|
|
3598
|
+
kind: "effect",
|
|
3599
|
+
factory: wrapped,
|
|
3600
|
+
dispose: null
|
|
3601
|
+
};
|
|
3602
|
+
if (self.state !== "suspended") effectEntry.dispose = effect(wrapped);
|
|
3603
|
+
self.entries.push(effectEntry);
|
|
3604
|
+
return {
|
|
3605
|
+
items: items$,
|
|
3606
|
+
size: size$,
|
|
3607
|
+
get: (key) => childMap.get(key)?.api,
|
|
3608
|
+
has: (key) => childMap.has(key)
|
|
3609
|
+
};
|
|
3610
|
+
},
|
|
3611
|
+
lazyChild(loader, props, options) {
|
|
3612
|
+
const status$ = signal("idle");
|
|
3613
|
+
const api$ = signal(void 0);
|
|
3614
|
+
const error$ = signal(void 0);
|
|
3615
|
+
let childInstance = null;
|
|
3616
|
+
let childEntry = null;
|
|
3617
|
+
let pendingLoad = null;
|
|
3618
|
+
let disposed = false;
|
|
3619
|
+
const flagEntry = {
|
|
3620
|
+
kind: "onDispose",
|
|
3621
|
+
fn: () => {
|
|
3622
|
+
disposed = true;
|
|
3623
|
+
}
|
|
3624
|
+
};
|
|
3625
|
+
self.entries.push(flagEntry);
|
|
3626
|
+
const handleFailure = (err) => {
|
|
3627
|
+
status$.set("error");
|
|
3628
|
+
error$.set(err);
|
|
3629
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3630
|
+
kind: "construction",
|
|
3631
|
+
controllerPath: self.path
|
|
3632
|
+
});
|
|
3633
|
+
};
|
|
3634
|
+
const load = () => {
|
|
3635
|
+
if (disposed) return Promise.reject(/* @__PURE__ */ new Error("[olas] ctx.lazyChild: cannot load after dispose"));
|
|
3636
|
+
if (pendingLoad !== null) return pendingLoad;
|
|
3637
|
+
status$.set("loading");
|
|
3638
|
+
pendingLoad = loader().then((def) => {
|
|
3639
|
+
if (disposed) throw new Error("[olas] ctx.lazyChild: disposed during load");
|
|
3640
|
+
const segment = self.makeChildSegment(getFactory(def), getName(def));
|
|
3641
|
+
const childDeps = options?.deps !== void 0 ? {
|
|
3642
|
+
...self.deps,
|
|
3643
|
+
...options.deps
|
|
3644
|
+
} : self.deps;
|
|
3645
|
+
const instance = new ControllerInstance(self, self.rootShared, segment, childDeps);
|
|
3646
|
+
try {
|
|
3647
|
+
const api = instance.construct(getFactory(def), props);
|
|
3648
|
+
childInstance = instance;
|
|
3649
|
+
childEntry = {
|
|
3650
|
+
kind: "child",
|
|
3651
|
+
instance
|
|
3652
|
+
};
|
|
3653
|
+
self.entries.push(childEntry);
|
|
3654
|
+
api$.set(api);
|
|
3655
|
+
status$.set("ready");
|
|
3656
|
+
return api;
|
|
3657
|
+
} catch (err) {
|
|
3658
|
+
handleFailure(err);
|
|
3659
|
+
throw err;
|
|
3660
|
+
}
|
|
3661
|
+
}, (err) => {
|
|
3662
|
+
if (disposed) throw err;
|
|
3663
|
+
handleFailure(err);
|
|
3664
|
+
throw err;
|
|
3665
|
+
});
|
|
3666
|
+
return pendingLoad;
|
|
3667
|
+
};
|
|
3668
|
+
const dispose = () => {
|
|
3669
|
+
if (disposed) return;
|
|
3670
|
+
disposed = true;
|
|
3671
|
+
if (childEntry !== null && childInstance !== null) {
|
|
3672
|
+
const idx = self.entries.indexOf(childEntry);
|
|
3673
|
+
if (idx >= 0) self.entries.splice(idx, 1);
|
|
3674
|
+
try {
|
|
3675
|
+
childInstance.dispose();
|
|
3676
|
+
} catch (err) {
|
|
3677
|
+
dispatchError(self.rootShared.onError, err, {
|
|
3678
|
+
kind: "effect",
|
|
3679
|
+
controllerPath: self.path
|
|
3680
|
+
});
|
|
3681
|
+
}
|
|
3682
|
+
childInstance = null;
|
|
3683
|
+
childEntry = null;
|
|
3684
|
+
}
|
|
3685
|
+
const flagIdx = self.entries.indexOf(flagEntry);
|
|
3686
|
+
if (flagIdx >= 0) self.entries.splice(flagIdx, 1);
|
|
3687
|
+
};
|
|
3688
|
+
return {
|
|
3689
|
+
status: status$,
|
|
3690
|
+
api: api$,
|
|
3691
|
+
error: error$,
|
|
3692
|
+
load,
|
|
3693
|
+
dispose
|
|
3694
|
+
};
|
|
3695
|
+
},
|
|
3398
3696
|
onDispose(fn) {
|
|
3399
3697
|
self.entries.push({
|
|
3400
3698
|
kind: "onDispose",
|
|
@@ -3653,4 +3951,4 @@ Object.defineProperty(exports, "untracked", {
|
|
|
3653
3951
|
}
|
|
3654
3952
|
});
|
|
3655
3953
|
|
|
3656
|
-
//# sourceMappingURL=root-
|
|
3954
|
+
//# sourceMappingURL=root-XKEsSmcd.cjs.map
|