storion 0.11.1 → 0.11.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.
@@ -2,6 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { e as emitter } from "./emitter-j4rC71vY.js";
5
+ import { i as isPromiseLike$1 } from "./isPromiseLike-bFkfHAbm.js";
5
6
  const STORION_TYPE = Symbol("STORION");
6
7
  function is$1(value, kind) {
7
8
  return value !== null && (typeof value === "object" || typeof value === "function") && STORION_TYPE in value && value[STORION_TYPE] === kind;
@@ -2286,6 +2287,25 @@ function pool(createItem, optionsOrInitial) {
2286
2287
  const keyOf = options == null ? void 0 : options.keyOf;
2287
2288
  const keyEquality = (options == null ? void 0 : options.equality) && !keyOf ? resolveEquality(options.equality) : null;
2288
2289
  const shouldAutoDispose = !!(options == null ? void 0 : options.autoDispose);
2290
+ const onAdded = emitter();
2291
+ const onRemoved = emitter();
2292
+ const dispatchEvent = (event) => {
2293
+ if (event.type === "add") {
2294
+ onAdded.emit(event);
2295
+ } else {
2296
+ onRemoved.emit(event);
2297
+ }
2298
+ };
2299
+ if (options == null ? void 0 : options.onAdded) {
2300
+ onAdded.on(options.onAdded);
2301
+ }
2302
+ if (options == null ? void 0 : options.onRemoved) {
2303
+ onRemoved.on(options.onRemoved);
2304
+ }
2305
+ if (options == null ? void 0 : options.onChanged) {
2306
+ onAdded.on(options.onChanged);
2307
+ onRemoved.on(options.onChanged);
2308
+ }
2289
2309
  if (keyOf) {
2290
2310
  const map2 = /* @__PURE__ */ new Map();
2291
2311
  for (const [k, v] of initial ?? []) {
@@ -2297,6 +2317,11 @@ function pool(createItem, optionsOrInitial) {
2297
2317
  if (entry) return entry.value;
2298
2318
  const value = createItem(key);
2299
2319
  map2.set(hash, { key, value });
2320
+ dispatchEvent({
2321
+ key,
2322
+ value,
2323
+ type: "add"
2324
+ });
2300
2325
  return value;
2301
2326
  };
2302
2327
  return Object.assign(get22, {
@@ -2309,22 +2334,38 @@ function pool(createItem, optionsOrInitial) {
2309
2334
  get: get22,
2310
2335
  set(key, value) {
2311
2336
  const hash = keyOf(key);
2312
- if (shouldAutoDispose) {
2313
- const existing = map2.get(hash);
2314
- if (existing && existing.value !== value) {
2315
- tryDispose(existing.value);
2316
- }
2337
+ const existing = map2.get(hash);
2338
+ const isNew = !existing;
2339
+ if (shouldAutoDispose && existing && existing.value !== value) {
2340
+ tryDispose(existing.value);
2341
+ }
2342
+ if (existing && existing.value !== value) {
2343
+ dispatchEvent({
2344
+ key: existing.key,
2345
+ value: existing.value,
2346
+ type: "remove"
2347
+ });
2317
2348
  }
2318
2349
  map2.set(hash, { key, value });
2350
+ if (isNew || (existing == null ? void 0 : existing.value) !== value) {
2351
+ dispatchEvent({ key, value, type: "add" });
2352
+ }
2319
2353
  return this;
2320
2354
  },
2321
2355
  size() {
2322
2356
  return map2.size;
2323
2357
  },
2324
2358
  clear() {
2325
- if (shouldAutoDispose) {
2359
+ if (shouldAutoDispose || onAdded.size > 0 || onRemoved.size > 0) {
2326
2360
  for (const entry of map2.values()) {
2327
- tryDispose(entry.value);
2361
+ if (shouldAutoDispose) {
2362
+ tryDispose(entry.value);
2363
+ }
2364
+ dispatchEvent({
2365
+ key: entry.key,
2366
+ value: entry.value,
2367
+ type: "remove"
2368
+ });
2328
2369
  }
2329
2370
  }
2330
2371
  map2.clear();
@@ -2332,9 +2373,16 @@ function pool(createItem, optionsOrInitial) {
2332
2373
  },
2333
2374
  delete(key) {
2334
2375
  const hash = keyOf(key);
2335
- if (shouldAutoDispose) {
2336
- const entry = map2.get(hash);
2337
- if (entry) tryDispose(entry.value);
2376
+ const entry = map2.get(hash);
2377
+ if (entry) {
2378
+ if (shouldAutoDispose) {
2379
+ tryDispose(entry.value);
2380
+ }
2381
+ dispatchEvent({
2382
+ key: entry.key,
2383
+ value: entry.value,
2384
+ type: "remove"
2385
+ });
2338
2386
  }
2339
2387
  map2.delete(hash);
2340
2388
  return this;
@@ -2366,6 +2414,11 @@ function pool(createItem, optionsOrInitial) {
2366
2414
  }
2367
2415
  const value = createItem(key);
2368
2416
  map.set(key, value);
2417
+ dispatchEvent({
2418
+ key,
2419
+ value,
2420
+ type: "add"
2421
+ });
2369
2422
  return value;
2370
2423
  };
2371
2424
  return Object.assign(get2, {
@@ -2385,15 +2438,32 @@ function pool(createItem, optionsOrInitial) {
2385
2438
  set(key, value) {
2386
2439
  const existingKey = findKey(key);
2387
2440
  if (existingKey !== void 0) {
2388
- if (shouldAutoDispose) {
2389
- const existing = map.get(existingKey);
2390
- if (existing !== value) {
2391
- tryDispose(existing);
2392
- }
2441
+ const existing = map.get(existingKey);
2442
+ if (shouldAutoDispose && existing !== void 0 && existing !== value) {
2443
+ tryDispose(existing);
2444
+ }
2445
+ if (existing !== void 0 && existing !== value) {
2446
+ dispatchEvent({
2447
+ key: existingKey,
2448
+ value: existing,
2449
+ type: "remove"
2450
+ });
2393
2451
  }
2394
2452
  map.set(existingKey, value);
2453
+ if (existing === void 0 || existing !== value) {
2454
+ dispatchEvent({
2455
+ key: existingKey,
2456
+ value,
2457
+ type: "add"
2458
+ });
2459
+ }
2395
2460
  } else {
2396
2461
  map.set(key, value);
2462
+ dispatchEvent({
2463
+ key,
2464
+ value,
2465
+ type: "add"
2466
+ });
2397
2467
  }
2398
2468
  return this;
2399
2469
  },
@@ -2403,9 +2473,16 @@ function pool(createItem, optionsOrInitial) {
2403
2473
  },
2404
2474
  /** Remove all items */
2405
2475
  clear() {
2406
- if (shouldAutoDispose) {
2407
- for (const value of map.values()) {
2408
- tryDispose(value);
2476
+ if (shouldAutoDispose || onAdded.size > 0 || onRemoved.size > 0) {
2477
+ for (const [key, value] of map.entries()) {
2478
+ if (shouldAutoDispose) {
2479
+ tryDispose(value);
2480
+ }
2481
+ dispatchEvent({
2482
+ key,
2483
+ value,
2484
+ type: "remove"
2485
+ });
2409
2486
  }
2410
2487
  }
2411
2488
  map.clear();
@@ -2415,8 +2492,16 @@ function pool(createItem, optionsOrInitial) {
2415
2492
  delete(key) {
2416
2493
  const existingKey = findKey(key);
2417
2494
  if (existingKey !== void 0) {
2418
- if (shouldAutoDispose) {
2419
- tryDispose(map.get(existingKey));
2495
+ const value = map.get(existingKey);
2496
+ if (value !== void 0) {
2497
+ if (shouldAutoDispose) {
2498
+ tryDispose(value);
2499
+ }
2500
+ dispatchEvent({
2501
+ key: existingKey,
2502
+ value,
2503
+ type: "remove"
2504
+ });
2420
2505
  }
2421
2506
  map.delete(existingKey);
2422
2507
  }
@@ -3137,10 +3222,72 @@ function abortable(fn) {
3137
3222
  });
3138
3223
  return wrapper;
3139
3224
  }
3140
- function isPromiseLike(value) {
3141
- return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
3225
+ const retryStrategy = {
3226
+ /** Exponential backoff: 1s, 2s, 4s, 8s... (max 30s) */
3227
+ backoff: (attempt) => Math.min(1e3 * 2 ** attempt, 3e4),
3228
+ /** Linear: 1s, 2s, 3s, 4s... (max 30s) */
3229
+ linear: (attempt) => Math.min(1e3 * (attempt + 1), 3e4),
3230
+ /** Fixed 1 second delay */
3231
+ fixed: () => 1e3,
3232
+ /** Fibonacci: 1s, 1s, 2s, 3s, 5s, 8s... (max 30s) */
3233
+ fibonacci: (attempt) => {
3234
+ const fib = [1, 1, 2, 3, 5, 8, 13, 21, 30];
3235
+ return Math.min(fib[attempt] ?? 30, 30) * 1e3;
3236
+ },
3237
+ /** Immediate retry (no delay) */
3238
+ immediate: () => 0,
3239
+ /** Add jitter (±30%) to any strategy */
3240
+ withJitter: (strategy) => (attempt) => {
3241
+ const base = strategy(attempt);
3242
+ const jitter = base * 0.3 * (Math.random() * 2 - 1);
3243
+ return Math.max(0, Math.round(base + jitter));
3244
+ }
3245
+ };
3246
+ class AsyncNotReadyError extends Error {
3247
+ constructor(message, status) {
3248
+ super(message);
3249
+ this.status = status;
3250
+ this.name = "AsyncNotReadyError";
3251
+ }
3252
+ }
3253
+ class AsyncAggregateError extends Error {
3254
+ constructor(message, errors2) {
3255
+ super(message);
3256
+ this.errors = errors2;
3257
+ this.name = "AsyncAggregateError";
3258
+ }
3259
+ }
3260
+ function createAsyncContext(abortController, isCancelledOrAborted, cancel, resolver) {
3261
+ const safe = createSafe(
3262
+ () => abortController.signal,
3263
+ isCancelledOrAborted
3264
+ );
3265
+ return {
3266
+ signal: abortController.signal,
3267
+ get(specOrFactory) {
3268
+ const instance = resolver.get(specOrFactory);
3269
+ if (isSpec(specOrFactory)) {
3270
+ const store2 = instance;
3271
+ return storeTuple(store2);
3272
+ }
3273
+ return instance;
3274
+ },
3275
+ safe,
3276
+ cancel
3277
+ };
3278
+ }
3279
+ const pendingPromises = /* @__PURE__ */ new WeakMap();
3280
+ const promiseStates = /* @__PURE__ */ new WeakMap();
3281
+ function getPendingPromise(state) {
3282
+ if (state.status === "pending" && "__key" in state && state.__key) {
3283
+ return pendingPromises.get(state.__key);
3284
+ }
3285
+ return void 0;
3142
3286
  }
3143
3287
  function toPromise(value) {
3288
+ if (isPromiseLike$1(value)) {
3289
+ return Promise.resolve(value);
3290
+ }
3144
3291
  if (typeof value === "function") {
3145
3292
  try {
3146
3293
  const result = value();
@@ -3149,11 +3296,607 @@ function toPromise(value) {
3149
3296
  return Promise.reject(e);
3150
3297
  }
3151
3298
  }
3152
- if (isPromiseLike(value)) {
3153
- return Promise.resolve(value);
3154
- }
3155
3299
  return Promise.resolve(value);
3156
3300
  }
3301
+ function promiseTry(fn) {
3302
+ return new Promise((resolve) => {
3303
+ resolve(fn());
3304
+ });
3305
+ }
3306
+ function createCancellablePromise(promise, cancel) {
3307
+ const cancellable = promise;
3308
+ cancellable.cancel = cancel;
3309
+ return cancellable;
3310
+ }
3311
+ function stateToJSON() {
3312
+ if (this.mode === "stale") {
3313
+ return { status: "success", mode: "stale", data: this.data };
3314
+ }
3315
+ if (this.status === "success") {
3316
+ return { status: "success", mode: "fresh", data: this.data };
3317
+ }
3318
+ return null;
3319
+ }
3320
+ function wrapAbortable(fn) {
3321
+ return (ctx, ...args) => {
3322
+ return fn.withSignal(ctx.signal, ...args);
3323
+ };
3324
+ }
3325
+ function asyncWithFocus(focus, handler, options) {
3326
+ if (!focus._storeContext.isSetupPhase()) {
3327
+ throw new SetupPhaseError(
3328
+ "async.action",
3329
+ "async.action() must be called during store setup phase."
3330
+ );
3331
+ }
3332
+ const [getState, setState] = focus;
3333
+ const asyncKey = {};
3334
+ let lastCancel = null;
3335
+ let lastArgs = null;
3336
+ let invocationCount = 0;
3337
+ function dispatch(...args) {
3338
+ return untrack(() => {
3339
+ if (lastCancel && (options == null ? void 0 : options.autoCancel) !== false) {
3340
+ lastCancel();
3341
+ }
3342
+ const abortController = new AbortController();
3343
+ let isCancelled = false;
3344
+ const requestId = {};
3345
+ let rejectOnCancel = null;
3346
+ const cancelPromise = new Promise((_, reject) => {
3347
+ rejectOnCancel = reject;
3348
+ });
3349
+ const cancel2 = () => {
3350
+ if (!isCancelled) {
3351
+ isCancelled = true;
3352
+ abortController.abort();
3353
+ pendingPromises.delete(asyncKey);
3354
+ rejectOnCancel == null ? void 0 : rejectOnCancel(new DOMException("Aborted", "AbortError"));
3355
+ }
3356
+ };
3357
+ lastCancel = cancel2;
3358
+ lastArgs = args;
3359
+ invocationCount++;
3360
+ const prevState = getState();
3361
+ const mode = prevState.mode;
3362
+ const staleData = mode === "stale" ? prevState.data : prevState.status === "success" ? prevState.data : void 0;
3363
+ const autoCancel = (options == null ? void 0 : options.autoCancel) !== false;
3364
+ const isStateExternallyModified = () => {
3365
+ if (!autoCancel) {
3366
+ const currentState2 = getState();
3367
+ return currentState2.__requestId === void 0;
3368
+ }
3369
+ const currentState = getState();
3370
+ return currentState.__requestId !== requestId;
3371
+ };
3372
+ const execute = async () => {
3373
+ try {
3374
+ const isCancelledOrAborted = () => isCancelled || abortController.signal.aborted;
3375
+ const asyncContext = createAsyncContext(
3376
+ abortController,
3377
+ isCancelledOrAborted,
3378
+ cancel2,
3379
+ focus._resolver
3380
+ );
3381
+ const result = await promiseTry(() => handler(asyncContext, ...args));
3382
+ if (isCancelled) {
3383
+ throw new DOMException("Aborted", "AbortError");
3384
+ }
3385
+ if (isStateExternallyModified()) {
3386
+ return result;
3387
+ }
3388
+ setState({
3389
+ status: "success",
3390
+ mode,
3391
+ data: result,
3392
+ error: void 0,
3393
+ timestamp: Date.now(),
3394
+ __requestId: requestId,
3395
+ toJSON: stateToJSON
3396
+ });
3397
+ if (lastCancel === cancel2) {
3398
+ lastCancel = null;
3399
+ }
3400
+ return result;
3401
+ } catch (error) {
3402
+ if (isCancelled || abortController.signal.aborted) {
3403
+ throw error instanceof Error ? error : new DOMException("Aborted", "AbortError");
3404
+ }
3405
+ const errorObj = error instanceof Error ? error : new Error(String(error));
3406
+ if (!abortController.signal.aborted) {
3407
+ abortController.abort();
3408
+ }
3409
+ if (isStateExternallyModified()) {
3410
+ throw errorObj;
3411
+ }
3412
+ setState({
3413
+ status: "error",
3414
+ mode,
3415
+ data: mode === "stale" ? staleData : void 0,
3416
+ error: errorObj,
3417
+ timestamp: void 0,
3418
+ __requestId: requestId,
3419
+ toJSON: stateToJSON
3420
+ });
3421
+ if (lastCancel === cancel2) {
3422
+ lastCancel = null;
3423
+ }
3424
+ throw errorObj;
3425
+ }
3426
+ };
3427
+ const executionPromise = execute();
3428
+ const promise = Promise.race([executionPromise, cancelPromise]);
3429
+ pendingPromises.set(asyncKey, executionPromise);
3430
+ setState({
3431
+ status: "pending",
3432
+ mode,
3433
+ data: mode === "stale" ? staleData : void 0,
3434
+ error: void 0,
3435
+ timestamp: void 0,
3436
+ __key: asyncKey,
3437
+ __requestId: requestId,
3438
+ toJSON: stateToJSON
3439
+ });
3440
+ promise.then(
3441
+ () => pendingPromises.delete(asyncKey),
3442
+ () => pendingPromises.delete(asyncKey)
3443
+ );
3444
+ return createCancellablePromise(promise, cancel2);
3445
+ });
3446
+ }
3447
+ function refresh() {
3448
+ if (lastArgs === null) {
3449
+ return void 0;
3450
+ }
3451
+ return dispatch(...lastArgs);
3452
+ }
3453
+ function cancel() {
3454
+ if (lastCancel) {
3455
+ lastCancel();
3456
+ lastCancel = null;
3457
+ }
3458
+ }
3459
+ function reset() {
3460
+ cancel();
3461
+ lastArgs = null;
3462
+ const currentState = getState();
3463
+ const mode = currentState.mode;
3464
+ const resetRequestId = {};
3465
+ if (mode === "stale") {
3466
+ setState({
3467
+ status: "idle",
3468
+ mode: "stale",
3469
+ data: currentState.data,
3470
+ error: void 0,
3471
+ timestamp: void 0,
3472
+ __requestId: resetRequestId,
3473
+ toJSON: stateToJSON
3474
+ });
3475
+ } else {
3476
+ setState({
3477
+ status: "idle",
3478
+ mode: "fresh",
3479
+ data: void 0,
3480
+ error: void 0,
3481
+ timestamp: void 0,
3482
+ __requestId: resetRequestId,
3483
+ toJSON: stateToJSON
3484
+ });
3485
+ }
3486
+ }
3487
+ function last() {
3488
+ const hasDispatched = !!lastArgs;
3489
+ if (!hasDispatched) {
3490
+ return void 0;
3491
+ }
3492
+ return {
3493
+ args: lastArgs,
3494
+ nth: invocationCount,
3495
+ // Read state to trigger reactivity (via focus getter) - this is the only tracked read
3496
+ state: getState()
3497
+ };
3498
+ }
3499
+ if (options == null ? void 0 : options.autoCancel) {
3500
+ focus._storeContext.onDispose(() => {
3501
+ cancel();
3502
+ });
3503
+ }
3504
+ return {
3505
+ dispatch,
3506
+ refresh,
3507
+ cancel,
3508
+ reset,
3509
+ last
3510
+ };
3511
+ }
3512
+ function asyncState(mode, status, dataOrError, errorOrExtra, extra) {
3513
+ let state;
3514
+ if (mode === "fresh") {
3515
+ switch (status) {
3516
+ case "idle":
3517
+ state = {
3518
+ status: "idle",
3519
+ mode: "fresh",
3520
+ data: void 0,
3521
+ error: void 0,
3522
+ timestamp: void 0,
3523
+ toJSON: stateToJSON
3524
+ };
3525
+ break;
3526
+ case "pending":
3527
+ state = {
3528
+ status: "pending",
3529
+ mode: "fresh",
3530
+ data: void 0,
3531
+ error: void 0,
3532
+ timestamp: void 0,
3533
+ ...dataOrError,
3534
+ toJSON: stateToJSON
3535
+ };
3536
+ break;
3537
+ case "success":
3538
+ state = {
3539
+ status: "success",
3540
+ mode: "fresh",
3541
+ data: dataOrError,
3542
+ error: void 0,
3543
+ timestamp: Date.now(),
3544
+ toJSON: stateToJSON
3545
+ };
3546
+ break;
3547
+ case "error":
3548
+ state = {
3549
+ status: "error",
3550
+ mode: "fresh",
3551
+ data: void 0,
3552
+ error: dataOrError,
3553
+ timestamp: void 0,
3554
+ ...errorOrExtra,
3555
+ toJSON: stateToJSON
3556
+ };
3557
+ break;
3558
+ }
3559
+ } else {
3560
+ switch (status) {
3561
+ case "idle":
3562
+ state = {
3563
+ status: "idle",
3564
+ mode: "stale",
3565
+ data: dataOrError,
3566
+ error: void 0,
3567
+ timestamp: void 0,
3568
+ toJSON: stateToJSON
3569
+ };
3570
+ break;
3571
+ case "pending":
3572
+ state = {
3573
+ status: "pending",
3574
+ mode: "stale",
3575
+ data: dataOrError,
3576
+ error: void 0,
3577
+ timestamp: void 0,
3578
+ ...errorOrExtra,
3579
+ toJSON: stateToJSON
3580
+ };
3581
+ break;
3582
+ case "success":
3583
+ state = {
3584
+ status: "success",
3585
+ mode: "stale",
3586
+ data: dataOrError,
3587
+ error: void 0,
3588
+ timestamp: Date.now(),
3589
+ toJSON: stateToJSON
3590
+ };
3591
+ break;
3592
+ case "error":
3593
+ state = {
3594
+ status: "error",
3595
+ mode: "stale",
3596
+ data: dataOrError,
3597
+ error: errorOrExtra,
3598
+ timestamp: void 0,
3599
+ ...extra,
3600
+ toJSON: stateToJSON
3601
+ };
3602
+ break;
3603
+ }
3604
+ }
3605
+ return Object.freeze(state);
3606
+ }
3607
+ function asyncStateFrom(prev, status, dataOrError) {
3608
+ const mode = prev.mode;
3609
+ const staleData = mode === "stale" ? prev.data : void 0;
3610
+ if (mode === "stale") {
3611
+ switch (status) {
3612
+ case "idle":
3613
+ return asyncState("stale", "idle", staleData);
3614
+ case "pending":
3615
+ return asyncState("stale", "pending", staleData);
3616
+ case "success":
3617
+ return asyncState("stale", "success", dataOrError);
3618
+ case "error":
3619
+ return asyncState(
3620
+ "stale",
3621
+ "error",
3622
+ staleData,
3623
+ dataOrError
3624
+ );
3625
+ }
3626
+ } else {
3627
+ switch (status) {
3628
+ case "idle":
3629
+ return asyncState("fresh", "idle");
3630
+ case "pending":
3631
+ return asyncState("fresh", "pending");
3632
+ case "success":
3633
+ return asyncState("fresh", "success", dataOrError);
3634
+ case "error":
3635
+ return asyncState("fresh", "error", dataOrError);
3636
+ }
3637
+ }
3638
+ }
3639
+ asyncState.from = asyncStateFrom;
3640
+ var async;
3641
+ ((async2) => {
3642
+ function fresh() {
3643
+ return asyncState("fresh", "idle");
3644
+ }
3645
+ async2.fresh = fresh;
3646
+ function stale(initialData) {
3647
+ return asyncState("stale", "idle", initialData);
3648
+ }
3649
+ async2.stale = stale;
3650
+ function action(focus, handlerOrAbortable, options) {
3651
+ const handler = isAbortable(handlerOrAbortable) ? wrapAbortable(handlerOrAbortable) : handlerOrAbortable;
3652
+ return asyncWithFocus(focus, handler, options);
3653
+ }
3654
+ async2.action = action;
3655
+ function mixin(handlerOrAbortable, options) {
3656
+ const handler = isAbortable(handlerOrAbortable) ? wrapAbortable(handlerOrAbortable) : handlerOrAbortable;
3657
+ const initialState = (options == null ? void 0 : options.initial) ?? asyncState("fresh", "idle");
3658
+ const asyncSpec = store({
3659
+ name: (options == null ? void 0 : options.name) ?? `async:${handler.name || "anonymous"}`,
3660
+ state: { result: initialState },
3661
+ meta: options == null ? void 0 : options.meta,
3662
+ setup(storeContext) {
3663
+ const { focus } = storeContext;
3664
+ const actions = asyncWithFocus(
3665
+ focus("result"),
3666
+ (asyncContext, ...args) => {
3667
+ return handler(asyncContext, ...args);
3668
+ },
3669
+ options
3670
+ );
3671
+ return actions;
3672
+ }
3673
+ });
3674
+ return (context) => {
3675
+ const [state2, actions] = context.scoped(asyncSpec);
3676
+ return [state2.result, actions];
3677
+ };
3678
+ }
3679
+ async2.mixin = mixin;
3680
+ function delay(ms, resolved) {
3681
+ let timeout;
3682
+ return createCancellablePromise(
3683
+ new Promise((resolve) => {
3684
+ timeout = setTimeout(resolve, ms, resolved);
3685
+ }),
3686
+ () => {
3687
+ clearTimeout(timeout);
3688
+ }
3689
+ );
3690
+ }
3691
+ async2.delay = delay;
3692
+ async2.invoke = promiseTry;
3693
+ function wait(state2) {
3694
+ if (state2.status === "success") {
3695
+ return state2.data;
3696
+ }
3697
+ if (state2.mode === "stale" && state2.data !== void 0) {
3698
+ return state2.data;
3699
+ }
3700
+ if (state2.status === "error") {
3701
+ throw state2.error;
3702
+ }
3703
+ if (state2.status === "pending") {
3704
+ const promise = getPendingPromise(state2);
3705
+ if (promise) {
3706
+ throw promise;
3707
+ }
3708
+ }
3709
+ const message = state2.status === "idle" ? `Cannot wait: state is idle. Call dispatch() or use trigger() to start the async operation before calling async.wait().` : `Cannot wait: state is ${state2.status}`;
3710
+ throw new AsyncNotReadyError(message, state2.status);
3711
+ }
3712
+ async2.wait = wait;
3713
+ function race(states) {
3714
+ for (const key in states) {
3715
+ if (Object.prototype.hasOwnProperty.call(states, key)) {
3716
+ const state2 = states[key];
3717
+ if (state2.status === "success") {
3718
+ return [key, state2.data];
3719
+ }
3720
+ }
3721
+ }
3722
+ for (const key in states) {
3723
+ if (Object.prototype.hasOwnProperty.call(states, key)) {
3724
+ const state2 = states[key];
3725
+ if (state2.mode === "stale" && state2.data !== void 0) {
3726
+ return [key, state2.data];
3727
+ }
3728
+ }
3729
+ }
3730
+ for (const key in states) {
3731
+ if (Object.prototype.hasOwnProperty.call(states, key)) {
3732
+ const state2 = states[key];
3733
+ if (state2.status === "error") {
3734
+ throw state2.error;
3735
+ }
3736
+ }
3737
+ }
3738
+ throw new AsyncNotReadyError(
3739
+ "No async state has resolved successfully",
3740
+ "pending"
3741
+ );
3742
+ }
3743
+ async2.race = race;
3744
+ function withState(promise) {
3745
+ const s = state(promise);
3746
+ return Object.assign(promise, { state: s });
3747
+ }
3748
+ async2.withState = withState;
3749
+ function state(promise) {
3750
+ const state2 = promiseStates.get(promise);
3751
+ if (state2) {
3752
+ return state2;
3753
+ }
3754
+ const newState = {
3755
+ status: "pending",
3756
+ resolved: void 0,
3757
+ rejected: void 0
3758
+ };
3759
+ promise.then(
3760
+ (value) => {
3761
+ newState.status = "fulfilled";
3762
+ newState.resolved = value;
3763
+ },
3764
+ (error) => {
3765
+ newState.status = "rejected";
3766
+ newState.rejected = error;
3767
+ }
3768
+ );
3769
+ promiseStates.set(promise, newState);
3770
+ return newState;
3771
+ }
3772
+ async2.state = state;
3773
+ function all(...states) {
3774
+ const results = [];
3775
+ for (let i = 0; i < states.length; i++) {
3776
+ const state2 = states[i];
3777
+ if (state2.status === "success") {
3778
+ results.push(state2.data);
3779
+ continue;
3780
+ }
3781
+ if (state2.mode === "stale" && state2.data !== void 0) {
3782
+ results.push(state2.data);
3783
+ continue;
3784
+ }
3785
+ if (state2.status === "error") {
3786
+ throw state2.error;
3787
+ }
3788
+ throw new AsyncNotReadyError(
3789
+ `State at index ${i} is ${state2.status}`,
3790
+ state2.status
3791
+ );
3792
+ }
3793
+ return results;
3794
+ }
3795
+ async2.all = all;
3796
+ function any(...states) {
3797
+ const errors2 = [];
3798
+ for (const state2 of states) {
3799
+ if (state2.status === "success") {
3800
+ return state2.data;
3801
+ }
3802
+ }
3803
+ for (const state2 of states) {
3804
+ if (state2.mode === "stale" && state2.data !== void 0) {
3805
+ return state2.data;
3806
+ }
3807
+ if (state2.status === "error") {
3808
+ errors2.push(state2.error);
3809
+ }
3810
+ }
3811
+ if (errors2.length === states.length) {
3812
+ throw new AsyncAggregateError("All async states have errors", errors2);
3813
+ }
3814
+ throw new AsyncNotReadyError(
3815
+ "No async state has resolved successfully",
3816
+ "pending"
3817
+ );
3818
+ }
3819
+ async2.any = any;
3820
+ function settled(...states) {
3821
+ const results = [];
3822
+ for (const state2 of states) {
3823
+ switch (state2.status) {
3824
+ case "success":
3825
+ results.push({ status: "success", data: state2.data });
3826
+ break;
3827
+ case "error":
3828
+ results.push({
3829
+ status: "error",
3830
+ error: state2.error,
3831
+ data: state2.mode === "stale" ? state2.data : void 0
3832
+ });
3833
+ break;
3834
+ case "pending":
3835
+ results.push({
3836
+ status: "pending",
3837
+ data: state2.mode === "stale" ? state2.data : void 0
3838
+ });
3839
+ break;
3840
+ case "idle":
3841
+ results.push({
3842
+ status: "idle",
3843
+ data: state2.mode === "stale" ? state2.data : void 0
3844
+ });
3845
+ break;
3846
+ }
3847
+ }
3848
+ return results;
3849
+ }
3850
+ async2.settled = settled;
3851
+ function hasData(state2) {
3852
+ if (state2.status === "success") return true;
3853
+ if (state2.mode === "stale" && state2.data !== void 0) return true;
3854
+ return false;
3855
+ }
3856
+ async2.hasData = hasData;
3857
+ function isLoading(state2) {
3858
+ return state2.status === "pending";
3859
+ }
3860
+ async2.isLoading = isLoading;
3861
+ function isError(state2) {
3862
+ return state2.status === "error";
3863
+ }
3864
+ async2.isError = isError;
3865
+ function derive(focus, computeFn) {
3866
+ const [getState, setState] = focus;
3867
+ let hasSetPending = false;
3868
+ return effect((ctx) => {
3869
+ const currentState = untrack(getState);
3870
+ try {
3871
+ const result = computeFn();
3872
+ if (result !== null && result !== void 0 && typeof result.then === "function") {
3873
+ throw new AsyncFunctionError(
3874
+ "async.derive computeFn",
3875
+ "Use async.wait() for async values, not async/await or returning promises."
3876
+ );
3877
+ }
3878
+ hasSetPending = false;
3879
+ setState(asyncState.from(currentState, "success", result));
3880
+ } catch (ex) {
3881
+ if (ex !== null && ex !== void 0 && typeof ex.then === "function") {
3882
+ if (!hasSetPending) {
3883
+ hasSetPending = true;
3884
+ setState(asyncState.from(currentState, "pending"));
3885
+ }
3886
+ ctx.safe(ex).then(ctx.refresh, ctx.refresh);
3887
+ } else {
3888
+ hasSetPending = false;
3889
+ const error = ex instanceof Error ? ex : new Error(String(ex));
3890
+ setState(asyncState.from(currentState, "error", error));
3891
+ }
3892
+ }
3893
+ });
3894
+ }
3895
+ async2.derive = derive;
3896
+ })(async || (async = {}));
3897
+ function isPromiseLike(value) {
3898
+ return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
3899
+ }
3157
3900
  class AggregateErrorImpl extends Error {
3158
3901
  constructor(errors2, message) {
3159
3902
  super(message);
@@ -3317,41 +4060,6 @@ function createSafe(getSignal, isCancelled) {
3317
4060
  delay
3318
4061
  });
3319
4062
  }
3320
- const retryStrategy = {
3321
- /** Exponential backoff: 1s, 2s, 4s, 8s... (max 30s) */
3322
- backoff: (attempt) => Math.min(1e3 * 2 ** attempt, 3e4),
3323
- /** Linear: 1s, 2s, 3s, 4s... (max 30s) */
3324
- linear: (attempt) => Math.min(1e3 * (attempt + 1), 3e4),
3325
- /** Fixed 1 second delay */
3326
- fixed: () => 1e3,
3327
- /** Fibonacci: 1s, 1s, 2s, 3s, 5s, 8s... (max 30s) */
3328
- fibonacci: (attempt) => {
3329
- const fib = [1, 1, 2, 3, 5, 8, 13, 21, 30];
3330
- return Math.min(fib[attempt] ?? 30, 30) * 1e3;
3331
- },
3332
- /** Immediate retry (no delay) */
3333
- immediate: () => 0,
3334
- /** Add jitter (±30%) to any strategy */
3335
- withJitter: (strategy) => (attempt) => {
3336
- const base = strategy(attempt);
3337
- const jitter = base * 0.3 * (Math.random() * 2 - 1);
3338
- return Math.max(0, Math.round(base + jitter));
3339
- }
3340
- };
3341
- class AsyncNotReadyError extends Error {
3342
- constructor(message, status) {
3343
- super(message);
3344
- this.status = status;
3345
- this.name = "AsyncNotReadyError";
3346
- }
3347
- }
3348
- class AsyncAggregateError extends Error {
3349
- constructor(message, errors2) {
3350
- super(message);
3351
- this.errors = errors2;
3352
- this.name = "AsyncAggregateError";
3353
- }
3354
- }
3355
4063
  function createEffectContext(nth, onRefresh) {
3356
4064
  let cleanupEmitter = null;
3357
4065
  let abortController = null;
@@ -3613,40 +4321,41 @@ function effect(fn, options) {
3613
4321
  }
3614
4322
  export {
3615
4323
  AsyncNotReadyError as A,
3616
- LocalStoreDependencyError as B,
3617
- pool as C,
3618
- tryDispose as D,
4324
+ StoreDisposedError as B,
4325
+ LocalStoreDependencyError as C,
4326
+ pool as D,
3619
4327
  EffectRefreshError as E,
3620
- unwrapFn as F,
4328
+ tryDispose as F,
4329
+ unwrapFn as G,
3621
4330
  HooksContextError as H,
3622
4331
  InvalidActionError as I,
3623
4332
  LifetimeMismatchError as L,
3624
4333
  ProviderMissingError as P,
3625
- SetupPhaseError as S,
3626
- store as a,
3627
- AsyncAggregateError as b,
4334
+ ScopedOutsideSelectorError as S,
4335
+ async as a,
4336
+ abortable as b,
3628
4337
  createSafe as c,
3629
- AsyncFunctionError as d,
3630
- effect as e,
3631
- isAbortable as f,
3632
- abortable as g,
3633
- strictEqual as h,
3634
- isSpec as i,
3635
- ScopedOutsideSelectorError as j,
3636
- STORION_TYPE as k,
3637
- dev as l,
3638
- resolveEquality as m,
3639
- is$1 as n,
3640
- batch as o,
4338
+ AsyncAggregateError as d,
4339
+ AsyncFunctionError as e,
4340
+ storeTuple as f,
4341
+ isSpec as g,
4342
+ STORION_TYPE as h,
4343
+ isAbortable as i,
4344
+ dev as j,
4345
+ resolveEquality as k,
4346
+ store as l,
4347
+ is$1 as m,
4348
+ batch as n,
4349
+ effect as o,
3641
4350
  pick as p,
3642
4351
  equality as q,
3643
4352
  retryStrategy as r,
3644
- storeTuple as s,
4353
+ strictEqual as s,
3645
4354
  tryStabilize as t,
3646
4355
  untrack as u,
3647
4356
  shallowEqual as v,
3648
4357
  withHooks as w,
3649
4358
  deepEqual as x,
3650
4359
  StorionError as y,
3651
- StoreDisposedError as z
4360
+ SetupPhaseError as z
3652
4361
  };