• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

live-input-vector-output-node / livon-ts / 23539813859

25 Mar 2026 11:55AM UTC coverage: 83.161% (+1.3%) from 81.847%
23539813859

push

github

cr15p1
fix(sync): address copilot review and graph-based qg flow

857 of 1015 branches covered (84.43%)

Branch coverage included in aggregate %.

5 of 5 new or added lines in 2 files covered. (100.0%)

214 existing lines in 8 files now uncovered.

3800 of 4585 relevant lines covered (82.88%)

35.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.11
/packages/sync/src/source/source.ts
1
import { type DraftMode, type EntityId } from '../entity.js';
2
import {
3
  applyEntityRunResult,
4
  clearEntityMembership,
5
  createEntityRunContextMethods,
6
  createRunContextEntryCache,
7
  createCacheWriteQueue,
8
  createSerializedKeyCache,
9
  cloneValue,
10
  createUnitSnapshot,
11
  notifyEffectListeners,
12
  resolveInput,
13
  resolveValue,
14
  setManyEntityMembership,
15
  setOneEntityMembership,
16
  serializeKey,
17
  type EffectListener,
18
  type InputUpdater,
19
  type ValueUpdater,
20
} from '../utils/index.js';
21

22
import {
23
  areDraftValuesEqual,
24
  getModeValue,
25
  invokeSourceCleanup,
26
  isCacheRecordExpired,
27
  isEntityArray,
28
  isEntityValue,
29
  isRecordValue,
30
  isSourceCleanup,
31
  readSourceCacheRecord,
32
  resolveCacheLruMaxEntries,
33
  resolveCacheKey,
34
  resolveCacheStorage,
35
  resolveCacheTtl,
36
  serializeSourceCacheRecord,
37
  shouldUseCache,
38
} from './helpers.js';
39
import type {
40
  ReadEntityValueById,
41
  Source,
42
  SourceConfig,
43
  SourceContext,
44
  SourceRunContext,
45
  SourceRunContextEntry,
46
  SourceRunGate,
47
  SourceUnit,
48
  SourceUnitByKeyMap,
49
  SourceUnitInternal,
50
} from './types.js';
51

52
const DEFAULT_DESTROY_DELAY = 250;
37✔
53
const DEFAULT_DRAFT_MODE: DraftMode = 'global';
37✔
54
const RUN_CONTEXT_CACHE_LIMIT = 32;
37✔
55
const SOURCE_CACHE_LRU_STORAGE_KEY_SUFFIX = '__lru__';
37✔
56

57
export const source = <
37✔
58
  TInput extends object | undefined,
59
  TPayload = unknown,
60
  TEntity extends object = object,
61
  RResult = unknown,
62
  UUpdate extends RResult = RResult,
63
  TEntityId extends EntityId = string,
64
>({
65
  entity,
66
  ttl = entity.ttl ?? 0,
67
  draft = entity.draft ?? DEFAULT_DRAFT_MODE,
68
  cache,
69
  destroyDelay = entity.destroyDelay ?? DEFAULT_DESTROY_DELAY,
70
  onDestroy,
71
  run,
72
  defaultValue,
73
}: SourceConfig<TInput, TPayload, TEntity, RResult, TEntityId>,
74
): Source<TInput, TPayload, RResult, UUpdate> => {
75
  const cacheTtl = resolveCacheTtl({
195✔
76
    sourceCache: cache,
77
    entityCache: entity.cache,
78
  });
79
  const cacheLruMaxEntries = resolveCacheLruMaxEntries({
195✔
80
    sourceCache: cache,
81
    entityCache: entity.cache,
82
  });
83
  const cacheStorage = resolveCacheStorage({
195✔
84
    sourceCache: cache,
85
    entityCache: entity.cache,
86
  });
87
  const cacheWriteQueue = cacheStorage
195✔
88
    ? createCacheWriteQueue({ storage: cacheStorage })
89
    : undefined;
90
  const cacheKeyPrefix = resolveCacheKey({
195✔
91
    sourceCache: cache,
92
    entityCache: entity.cache,
93
    sourceKey: serializeKey({
94
      mode: Array.isArray(defaultValue ?? null) ? 'many' : 'one',
95
    }),
96
  });
97

98
  const unitsByKey: SourceUnitByKeyMap<TInput, TPayload, TEntityId, RResult, UUpdate> =
99
    new Map<string, SourceUnitInternal<TInput, TPayload, TEntityId, RResult, UUpdate>>();
195✔
100
  const scopedDraftsById = new Map<TEntityId, TEntity>();
195✔
101
  const unitKeyCache = createSerializedKeyCache({
195✔
102
    mode: 'scoped-unit',
103
  });
104

105
  const notifyScopedUnitsById = (id: TEntityId): void => {
195✔
106
    Array.from(unitsByKey.values()).forEach((unitInternal) => {
2✔
107
      const hasMembership = unitInternal.membershipIds.some((membershipId) => membershipId === id);
2✔
108
      if (!hasMembership) {
2✔
UNCOV
109
        return;
×
110
      }
111

112
      notifyUnit(unitInternal);
2✔
113
    });
114
  };
115

116
  const readEntityValueById: ReadEntityValueById<TEntityId, TEntity> = (id) => {
195✔
117
    if (draft === 'off') {
354✔
118
      return entity.getById(id);
4✔
119
    }
120

121
    if (draft === 'global') {
350✔
122
      const globalDraft = entity.getDraftById(id);
338✔
123
      if (globalDraft) {
338✔
124
        return globalDraft;
14✔
125
      }
126

127
      return entity.getById(id);
324✔
128
    }
129

130
    const scopedDraft = scopedDraftsById.get(id);
12✔
131
    if (scopedDraft) {
12✔
132
      return scopedDraft;
2✔
133
    }
134

135
    return entity.getById(id);
10✔
136
  };
137

138
  const setDraftById = (id: TEntityId, value: TEntity): void => {
195✔
139
    if (draft === 'off') {
12✔
UNCOV
140
      return;
×
141
    }
142

143
    if (draft === 'global') {
12✔
144
      entity.setDraftById(id, value);
10✔
145
      return;
10✔
146
    }
147

148
    scopedDraftsById.set(id, value);
2✔
149
    notifyScopedUnitsById(id);
2✔
150
  };
151

152
  const clearDraftById = (id: TEntityId): void => {
195✔
153
    if (draft === 'off') {
3✔
154
      return;
×
155
    }
156

157
    if (draft === 'global') {
3✔
158
      entity.clearDraftById(id);
3✔
159
      return;
3✔
160
    }
161

UNCOV
162
    const existed = scopedDraftsById.delete(id);
×
UNCOV
163
    if (!existed) {
×
UNCOV
164
      return;
×
165
    }
166

UNCOV
167
    notifyScopedUnitsById(id);
×
168
  };
169

170
  const notifyUnit = (
195✔
171
    internal: SourceUnitInternal<TInput, TPayload, TEntityId, RResult, UUpdate>,
172
  ): void => {
173
    internal.state.value = getModeValue(internal, readEntityValueById);
328✔
174

175
    notifyEffectListeners(
328✔
176
      internal.listeners,
177
      createUnitSnapshot({
178
        value: internal.state.value,
179
        status: internal.state.status,
180
        meta: internal.state.meta,
181
        context: internal.state.context,
182
      }),
183
    );
184
  };
185

186
  const sourceFactory: Source<TInput, TPayload, RResult, UUpdate> = (scope) => {
195✔
187
    const key = unitKeyCache.getOrCreateKey(scope);
207✔
188
    const existingUnit = unitsByKey.get(key);
207✔
189

190
    if (existingUnit) {
207✔
191
      return existingUnit.unit;
42✔
192
    }
193

194
    const initialValue = (defaultValue ?? null) as RResult;
165✔
195
    const initialMode: 'one' | 'many' = Array.isArray(initialValue) ? 'many' : 'one';
207✔
196

197
    const internal: SourceUnitInternal<TInput, TPayload, TEntityId, RResult, UUpdate> = {
207✔
198
      key,
199
      ttl,
200
      destroyDelay,
201
      scope,
202
      payload: undefined as TPayload,
203
      state: {
204
        value: initialValue,
205
        status: 'idle',
206
        meta: null,
207
        context: {
208
          cacheState: cacheStorage ? 'miss' : 'disabled',
209
          error: null,
210
        },
211
      },
212
      mode: initialMode,
213
      modeLocked: false,
214
      hasEntityValue: false,
215
      membershipIds: [],
216
      readWrite: {
217
        subview: entity.readWrite.subview,
218
      },
219
      listeners: new Set<EffectListener<RResult>>(),
220
      inFlightByPayload: new Map<string, Promise<RResult>>(),
221
      runSequence: 0,
222
      latestRunSequence: 0,
223
      lastRunAt: null,
224
      cleanup: null,
225
      stopped: false,
226
      destroyed: false,
227
      destroyHandled: false,
228
      unit: {} as SourceUnit<TInput, TPayload, RResult, UUpdate>,
229
    };
230
    const payloadKeyCache = createSerializedKeyCache({
207✔
231
      mode: 'payload-hot-path',
232
      limit: RUN_CONTEXT_CACHE_LIMIT,
233
    });
234
    const createRunContextEntry = (
207✔
235
      payload: TPayload,
236
    ): SourceRunContextEntry<TInput, TPayload, TEntity, RResult, TEntityId> => {
237
      const gate: SourceRunGate = {
131✔
UNCOV
238
        isLatestRun: () => false,
×
239
      };
240
      const runContextMethods = createEntityRunContextMethods<
131✔
241
        TEntity,
242
        RResult,
243
        TEntityId
244
      >({
245
        entity,
246
        state: internal,
247
        isActive: () => gate.isLatestRun(),
×
248
        refreshValue: () => {
249
          internal.state.value = getModeValue(internal, readEntityValueById);
×
250
        },
251
        readValue: () => internal.state.value,
1✔
252
      });
253
      const runContextBase: SourceRunContext<
254
        TInput,
255
        TPayload,
256
        TEntity,
257
        RResult,
258
        TEntityId
259
      > = {
131✔
260
        scope: internal.scope,
261
        payload,
262
        setMeta: (metaInput: unknown) => {
263
          if (!gate.isLatestRun()) {
13✔
UNCOV
264
            return;
×
265
          }
266

267
          const nextMeta = resolveValue(
13✔
268
            internal.state.meta,
269
            metaInput,
270
          );
271
          if (Object.is(nextMeta, internal.state.meta)) {
13✔
272
            return;
2✔
273
          }
274

275
          internal.state.meta = nextMeta;
11✔
276
          notifyUnit(internal);
11✔
277
        },
278
        ...runContextMethods,
279
      };
280

281
      return {
131✔
282
        gate,
283
        context: runContextBase,
284
      };
285
    };
286
    const runContextEntryCache = createRunContextEntryCache<
207✔
287
      TPayload,
288
      SourceRunContextEntry<TInput, TPayload, TEntity, RResult, TEntityId>
289
    >({
290
      createEntry: createRunContextEntry,
291
      limit: RUN_CONTEXT_CACHE_LIMIT,
292
    });
293

294
    const setContext = (input: Partial<SourceContext>): void => {
207✔
295
      const hasCacheState = Object.prototype.hasOwnProperty.call(input, 'cacheState');
506✔
296
      const hasError = Object.prototype.hasOwnProperty.call(input, 'error');
506✔
297

298
      if (
506✔
299
        (!hasCacheState || input.cacheState === internal.state.context.cacheState)
300
        && (!hasError || Object.is(input.error, internal.state.context.error))
301
      ) {
302
        return;
463✔
303
      }
304

305
      internal.state.context = {
43✔
306
        ...internal.state.context,
307
        ...input,
308
      };
309
    };
310

311
    const cacheEnabled = Boolean(
207✔
312
      cacheStorage
313
      && (cacheTtl === 'infinity' || cacheTtl > 0),
314
    );
315
    const cacheLruEnabled = Boolean(
207✔
316
      cacheEnabled
317
      && cacheLruMaxEntries > 0
318
      && cacheStorage
319
      && cacheWriteQueue,
320
    );
321
    const cacheLruStorageKey = `${cacheKeyPrefix}:${SOURCE_CACHE_LRU_STORAGE_KEY_SUFFIX}`;
207✔
322
    let cacheLruLoaded = false;
207✔
323
    let cacheLruKeys: string[] = [];
207✔
324
    let activePayloadCacheKey: string | null = null;
207✔
325

326
    const loadCacheLruState = (): void => {
207✔
327
      if (!cacheLruEnabled || cacheLruLoaded || !cacheStorage) {
3✔
328
        return;
2✔
329
      }
330

331
      cacheLruLoaded = true;
1✔
332
      const rawLruState = cacheStorage.getItem(cacheLruStorageKey);
1✔
333
      if (!rawLruState) {
1✔
334
        return;
1✔
335
      }
336

UNCOV
337
      try {
×
UNCOV
338
        const parsedLruState: unknown = JSON.parse(rawLruState);
×
339
        if (!isRecordValue(parsedLruState)) {
×
340
          return;
×
341
        }
342

UNCOV
343
        const keysCandidate = parsedLruState.keys;
×
UNCOV
344
        if (!Array.isArray(keysCandidate)) {
×
UNCOV
345
          return;
×
346
        }
347

UNCOV
348
        if (!keysCandidate.every((entry) => typeof entry === 'string')) {
×
UNCOV
349
          return;
×
350
        }
351

UNCOV
352
        cacheLruKeys = keysCandidate;
×
353
      } catch {
UNCOV
354
        return;
×
355
      }
356
    };
357

358
    const persistCacheLruState = (): void => {
207✔
359
      if (!cacheLruEnabled || !cacheWriteQueue) {
3✔
UNCOV
360
        return;
×
361
      }
362

363
      if (cacheLruKeys.length === 0) {
3✔
UNCOV
364
        cacheWriteQueue.enqueueRemove(cacheLruStorageKey);
×
UNCOV
365
        return;
×
366
      }
367

368
      cacheWriteQueue.enqueueSet(
3✔
369
        cacheLruStorageKey,
370
        () => {
371
          return JSON.stringify({
3✔
372
            keys: cacheLruKeys,
373
          });
374
        },
375
      );
376
    };
377

378
    const touchCacheLruKey = (unitCacheKey: string): void => {
207✔
379
      if (!cacheLruEnabled || !cacheWriteQueue) {
14✔
380
        return;
11✔
381
      }
382

383
      loadCacheLruState();
3✔
384
      if (cacheLruKeys[0] === unitCacheKey) {
3✔
UNCOV
385
        return;
×
386
      }
387

388
      const existingIndex = cacheLruKeys.findIndex((entry) => entry === unitCacheKey);
3✔
389
      if (existingIndex > 0) {
3✔
UNCOV
390
        const existingEntry = cacheLruKeys[existingIndex];
×
UNCOV
391
        if (existingEntry === undefined) {
×
UNCOV
392
          return;
×
393
        }
394

UNCOV
395
        cacheLruKeys.splice(existingIndex, 1);
×
UNCOV
396
        cacheLruKeys.unshift(existingEntry);
×
UNCOV
397
        persistCacheLruState();
×
UNCOV
398
        return;
×
399
      }
400

401
      cacheLruKeys.unshift(unitCacheKey);
3✔
402
      const evictedEntry = cacheLruKeys.length > cacheLruMaxEntries
3✔
403
        ? cacheLruKeys.pop()
404
        : undefined;
405
      if (evictedEntry && evictedEntry !== unitCacheKey) {
14✔
406
        cacheWriteQueue.enqueueRemove(evictedEntry);
1✔
407
      }
408

409
      persistCacheLruState();
3✔
410
    };
411

412
    const removeCacheLruKey = (unitCacheKey: string): void => {
207✔
413
      if (!cacheLruEnabled) {
4✔
414
        return;
4✔
415
      }
416

UNCOV
417
      loadCacheLruState();
×
UNCOV
418
      const existingIndex = cacheLruKeys.findIndex((entry) => entry === unitCacheKey);
×
UNCOV
419
      if (existingIndex < 0) {
×
UNCOV
420
        return;
×
421
      }
422

UNCOV
423
      cacheLruKeys.splice(existingIndex, 1);
×
UNCOV
424
      persistCacheLruState();
×
425
    };
426

427
    const resolvePayloadCacheKey = (payload: TPayload): string => {
207✔
428
      return payloadKeyCache.getOrCreateKey(payload);
321✔
429
    };
430

431
    const resolveUnitCacheKey = (payloadCacheKey: string): string => {
207✔
432
      return `${cacheKeyPrefix}:${key}:${payloadCacheKey}`;
32✔
433
    };
434

435
    const syncCacheRecord = (): void => {
207✔
436
      if (!cacheEnabled || !cacheWriteQueue) {
168✔
437
        return;
158✔
438
      }
439

440
      const payloadCacheKey = resolvePayloadCacheKey(internal.payload);
10✔
441
      const unitCacheKey = resolveUnitCacheKey(payloadCacheKey);
10✔
442
      if (!internal.hasEntityValue) {
10✔
443
        removeCacheLruKey(unitCacheKey);
1✔
444
        cacheWriteQueue.enqueueRemove(unitCacheKey);
1✔
445
        return;
1✔
446
      }
447

448
      touchCacheLruKey(unitCacheKey);
9✔
449
      cacheWriteQueue.enqueueSet(unitCacheKey, () => {
9✔
450
        const entities = internal.membershipIds
8✔
451
          .map((id) => entity.getById(id))
8✔
452
          .filter((entry): entry is TEntity => entry !== undefined);
8✔
453

454
        return serializeSourceCacheRecord({
8✔
455
          mode: internal.mode,
456
          entities,
457
          writtenAt: Date.now(),
458
        });
459
      });
460
    };
461

462
    const hydrateFromCache = (payloadCacheKey: string): boolean => {
207✔
463
      if (!cacheStorage) {
226✔
464
        setContext({
171✔
465
          cacheState: 'disabled',
466
        });
467
        return false;
171✔
468
      }
469

470
      if (!cacheEnabled) {
55✔
471
        setContext({
33✔
472
          cacheState: 'disabled',
473
        });
474
        return false;
33✔
475
      }
476

477
      const unitCacheKey = resolveUnitCacheKey(payloadCacheKey);
22✔
478
      const rawRecord = cacheStorage.getItem(unitCacheKey);
22✔
479
      const parsedRecord = readSourceCacheRecord<TEntity>(rawRecord);
22✔
480
      if (!parsedRecord) {
22✔
481
        setContext({
14✔
482
          cacheState: 'miss',
483
        });
484
        return false;
14✔
485
      }
486

487
      if (isCacheRecordExpired({ ttl: cacheTtl, writtenAt: parsedRecord.writtenAt })) {
8✔
488
        removeCacheLruKey(unitCacheKey);
3✔
489
        if (cacheWriteQueue) {
3✔
490
          cacheWriteQueue.enqueueRemove(unitCacheKey);
3✔
491
        } else {
UNCOV
492
          try {
×
UNCOV
493
            cacheStorage.removeItem(unitCacheKey);
×
494
          } catch {
495
            // Ignore storage write errors and continue with stale cache behavior.
496
          }
497
        }
498
        setContext({
3✔
499
          cacheState: 'stale',
500
        });
501
        return false;
3✔
502
      }
503

504
      touchCacheLruKey(unitCacheKey);
5✔
505
      if (parsedRecord.mode === 'one') {
5✔
506
        const firstEntity = parsedRecord.entities[0];
5✔
507
        internal.hasEntityValue = true;
5✔
508

509
        if (firstEntity) {
5✔
510
          const upsertedEntity = entity.upsertOne(firstEntity);
5✔
511
          setOneEntityMembership(internal, {
5✔
512
            entity,
513
            value: upsertedEntity,
514
            operation: 'cache rehydrate one',
515
          });
516
          internal.state.value = getModeValue(internal, readEntityValueById);
5✔
517
        } else {
UNCOV
518
          clearEntityMembership(internal, { clearUnitMembership: entity.clearUnitMembership });
×
UNCOV
519
          internal.state.value = getModeValue(internal, readEntityValueById);
×
520
        }
521
      }
522

523
      if (parsedRecord.mode === 'many') {
5✔
UNCOV
524
        const upsertedEntities = entity.upsertMany(parsedRecord.entities);
×
UNCOV
525
        setManyEntityMembership(internal, {
×
526
          entity,
527
          values: upsertedEntities,
528
          operation: 'cache rehydrate many',
529
        });
UNCOV
530
        internal.state.value = getModeValue(internal, readEntityValueById);
×
531
      }
532

533
      internal.state.status = 'rehydrated';
5✔
534
      setContext({
5✔
535
        cacheState: 'hit',
536
        error: null,
537
      });
538
      return true;
5✔
539
    };
540

541
    const hydrateFromPayloadCache = (payload: TPayload): boolean => {
207✔
542
      const payloadCacheKey = resolvePayloadCacheKey(payload);
311✔
543
      if (activePayloadCacheKey === payloadCacheKey) {
311✔
544
        return false;
85✔
545
      }
546

547
      activePayloadCacheKey = payloadCacheKey;
226✔
548
      return hydrateFromCache(payloadCacheKey);
226✔
549
    };
550

551
    const unregisterFromEntity = entity.registerUnit({
207✔
552
      key: internal.key,
553
      onChange: () => {
554
        if (internal.destroyed) {
34✔
UNCOV
555
          return;
×
556
        }
557

558
        notifyUnit(internal);
34✔
559
        syncCacheRecord();
34✔
560
      },
561
    });
562

563
    hydrateFromPayloadCache(internal.payload);
207✔
564

565
    const destroyInternal = (): void => {
207✔
566
      if (internal.destroyed) {
9✔
567
        return;
1✔
568
      }
569

570
      internal.runSequence += 1;
8✔
571
      internal.latestRunSequence = internal.runSequence;
8✔
572
      internal.stopped = true;
8✔
573
      invokeSourceCleanup(internal.cleanup);
8✔
574
      internal.cleanup = null;
8✔
575
      internal.destroyed = true;
8✔
576
      runContextEntryCache.clear();
8✔
577
      payloadKeyCache.clear();
8✔
578
      activePayloadCacheKey = null;
8✔
579
      singleInFlightPromise = null;
8✔
580
      hasSingleInFlightPayload = false;
8✔
581
      singleInFlightPayload = undefined;
8✔
582
      singleInFlightPayloadKey = null;
8✔
583

584
      unregisterFromEntity();
8✔
585
      internal.listeners.clear();
8✔
586

587
      if (!internal.destroyHandled) {
8✔
588
        internal.destroyHandled = true;
8✔
589
        onDestroy?.({
8✔
590
          scope: internal.scope,
591
          payload: internal.payload,
592
        });
593
      }
594

595
      unitsByKey.delete(internal.key);
8✔
596
    };
597
      let singleInFlightPromise: Promise<RResult> | null = null;
207✔
598
      let hasSingleInFlightPayload = false;
207✔
599
      let singleInFlightPayload: TPayload | undefined;
600
      let singleInFlightPayloadKey: string | null = null;
207✔
601

602
      const executeRun = (
207✔
603
        isForce: boolean,
604
        payloadInput?: TPayload | InputUpdater<TPayload>,
605
      ): Promise<RResult> => {
606
        if (internal.destroyed) {
149✔
607
          return Promise.resolve(internal.state.value);
2✔
608
        }
609

610
        const hasPayloadInput = payloadInput !== undefined;
147✔
611
        const nextPayload = resolveInput(internal.payload, payloadInput);
147✔
612
        if (hasPayloadInput) {
147✔
613
          internal.payload = nextPayload;
64✔
614
        }
615
        let payloadKey: string | null = null;
147✔
616
        if (singleInFlightPromise) {
147✔
617
          if (hasSingleInFlightPayload && Object.is(singleInFlightPayload, internal.payload)) {
5✔
UNCOV
618
            return singleInFlightPromise;
×
619
          }
620

621
          payloadKey = payloadKeyCache.getOrCreateKey(internal.payload);
5✔
622
          if (singleInFlightPayloadKey === null && hasSingleInFlightPayload) {
5✔
623
            singleInFlightPayloadKey = payloadKeyCache.getOrCreateKey(singleInFlightPayload);
4✔
624
          }
625

626
          if (singleInFlightPayloadKey === payloadKey) {
5✔
627
            return singleInFlightPromise;
1✔
628
          }
629
        }
630

631
        if (internal.inFlightByPayload.size > 0) {
146✔
632
          payloadKey ??= payloadKeyCache.getOrCreateKey(internal.payload);
1✔
633
          const inFlightForPayload = internal.inFlightByPayload.get(payloadKey);
1✔
634
          if (inFlightForPayload) {
1✔
UNCOV
635
            return inFlightForPayload;
×
636
          }
637
        }
638

639
        internal.stopped = false;
146✔
640
        internal.runSequence += 1;
146✔
641
        internal.latestRunSequence = internal.runSequence;
146✔
642
        const runSequence = internal.runSequence;
146✔
643
        const isLatestRun = () => {
146✔
644
          return internal.latestRunSequence === runSequence && !internal.destroyed;
574✔
645
        };
646

647
        const didHydrateFromPayloadCache = hydrateFromPayloadCache(internal.payload);
146✔
648
        if (didHydrateFromPayloadCache && isLatestRun()) {
146✔
649
          notifyUnit(internal);
1✔
650
        }
651

652
        if (!isForce && !hasPayloadInput && shouldUseCache(internal)) {
146✔
653
          return Promise.resolve(internal.state.value);
2✔
654
        }
655

656
        const shouldUseRefreshingStatus = internal.state.status === 'rehydrated'
144✔
657
          || internal.state.status === 'success';
658
        if (isLatestRun()) {
149✔
659
          internal.state.status = shouldUseRefreshingStatus ? 'refreshing' : 'loading';
144✔
660
          setContext({
144✔
661
            error: null,
662
          });
663
          notifyUnit(internal);
144✔
664
        }
665

666
        const applyRunValue = (nextValue: RResult | void): void => {
144✔
667
          if (!isLatestRun()) {
135✔
UNCOV
668
            return;
×
669
          }
670

671
          applyEntityRunResult({
135✔
672
            entity,
673
            state: internal,
674
            nextValue,
675
            refreshValueFromMembership: () => {
676
              internal.state.value = getModeValue(internal, readEntityValueById);
133✔
677
            },
678
            setRawValue: (value) => {
679
              internal.state.value = value;
1✔
680
            },
681
          });
682
        };
683

684
        const runContextEntry = runContextEntryCache.getOrCreate(internal.payload);
144✔
685
        runContextEntry.gate.isLatestRun = isLatestRun;
144✔
686
        runContextEntry.context.payload = internal.payload;
144✔
687

688
        const usesSingleInFlight = singleInFlightPromise === null && internal.inFlightByPayload.size === 0;
144✔
689
        const trackedPayloadKey = usesSingleInFlight
149✔
690
          ? null
691
          : (payloadKey ?? payloadKeyCache.getOrCreateKey(internal.payload));
692

693
        const runPromise: Promise<RResult> = Promise.resolve(run(runContextEntry.context))
149✔
694
          .then((result) => {
695
            if (!isLatestRun() && isSourceCleanup(result)) {
141✔
696
              invokeSourceCleanup(result);
3✔
697
              return internal.state.value;
3✔
698
            }
699

700
            if (!isLatestRun()) {
138✔
701
              return internal.state.value;
3✔
702
            }
703

704
            if (isSourceCleanup(result)) {
135✔
UNCOV
705
              if (internal.destroyed || internal.stopped) {
×
UNCOV
706
                invokeSourceCleanup(result);
×
707
              } else {
UNCOV
708
                invokeSourceCleanup(internal.cleanup);
×
UNCOV
709
                internal.cleanup = result;
×
710
              }
711

UNCOV
712
              internal.state.value = getModeValue(internal, readEntityValueById);
×
713
            } else {
714
              applyRunValue(result);
135✔
715
            }
716

717
            internal.lastRunAt = Date.now();
134✔
718
            internal.state.status = 'success';
134✔
719
            setContext({
134✔
720
              error: null,
721
            });
722
            notifyUnit(internal);
134✔
723
            syncCacheRecord();
134✔
724

725
            return internal.state.value;
134✔
726
          })
727
          .catch((error: unknown) => {
728
            if (isLatestRun()) {
2✔
729
              internal.state.status = 'error';
2✔
730
              setContext({
2✔
731
                error,
732
              });
733
              notifyUnit(internal);
2✔
734
            }
735

736
            throw error;
2✔
737
          })
738
          .finally(() => {
739
            if (usesSingleInFlight) {
142✔
740
              if (singleInFlightPromise === runPromise) {
139✔
741
                singleInFlightPromise = null;
137✔
742
                hasSingleInFlightPayload = false;
137✔
743
                singleInFlightPayload = undefined;
137✔
744
                singleInFlightPayloadKey = null;
137✔
745
              }
746
              return;
139✔
747
            }
748

749
            if (trackedPayloadKey !== null) {
3✔
750
              internal.inFlightByPayload.delete(trackedPayloadKey);
3✔
751
            }
752
          });
753

754
        if (usesSingleInFlight) {
149✔
755
          singleInFlightPromise = runPromise;
140✔
756
          hasSingleInFlightPayload = true;
140✔
757
          singleInFlightPayload = internal.payload;
140✔
758
          singleInFlightPayloadKey = null;
140✔
759
        } else {
760
          if (trackedPayloadKey !== null) {
4✔
761
            internal.inFlightByPayload.set(trackedPayloadKey, runPromise);
4✔
762
          }
763
        }
764

765
        return runPromise;
144✔
766
      };
767

768
      const unit = ((payloadInput?: TPayload | InputUpdater<TPayload>) => {
207✔
769
        internal.payload = resolveInput(internal.payload, payloadInput);
×
770
        return unit;
×
771
      }) as SourceUnit<TInput, TPayload, RResult, UUpdate>;
772

773
      unit.ttl = ttl;
207✔
774
      unit.cacheTtl = cacheTtl;
207✔
775
      unit.destroyDelay = destroyDelay;
207✔
776
      unit.run = (payloadInput) => executeRun(false, payloadInput);
207✔
777
      unit.get = () => {
207✔
778
        return internal.state.value;
75✔
779
      };
780
      unit.draft = {
207✔
781
        set: (input: UUpdate | ValueUpdater<RResult, UUpdate>) => {
782
          if (internal.destroyed || draft === 'off') {
20✔
783
            return;
2✔
784
          }
785

786
          const previousValue: RResult = getModeValue(internal, readEntityValueById);
18✔
787
          const draftSeed: RResult = cloneValue(previousValue);
18✔
788
          const nextUpdate = resolveValue(draftSeed, input);
18✔
789

790
          if (Object.is(nextUpdate, previousValue)) {
18✔
791
            return;
3✔
792
          }
793

794
          if (areDraftValuesEqual(previousValue, nextUpdate)) {
15✔
795
            return;
3✔
796
          }
797

798
          if (internal.mode === 'one') {
12✔
799
            const firstId = internal.membershipIds[0];
12✔
800
            if (!firstId || !isEntityValue<TEntity>(nextUpdate)) {
12✔
UNCOV
801
              return;
×
802
            }
803

804
            setDraftById(firstId, cloneValue(nextUpdate));
12✔
805
            return;
12✔
806
          }
807

UNCOV
808
          if (internal.mode === 'many') {
×
UNCOV
809
            if (!isEntityArray<TEntity>(nextUpdate)) {
×
UNCOV
810
              return;
×
811
            }
812

UNCOV
813
            nextUpdate.forEach((entry) => {
×
UNCOV
814
              const entryId = entity.idOf(entry);
×
UNCOV
815
              setDraftById(entryId, cloneValue(entry));
×
816
            });
817
          }
818
        },
819
        clean: () => {
820
          if (internal.destroyed || draft === 'off') {
5✔
UNCOV
821
            return;
×
822
          }
823

824
          internal.membershipIds.forEach((id) => {
5✔
825
            clearDraftById(id);
3✔
826
          });
827
        },
828
      };
829
      unit.effect = (listener) => {
207✔
830
        if (internal.destroyed) {
66✔
831
          return undefined;
1✔
832
        }
833

834
        internal.listeners.add(listener);
65✔
835

836
        return () => {
65✔
837
          internal.listeners.delete(listener);
20✔
838
        };
839
      };
840
      unit.refetch = (payloadInput) => {
207✔
841
        const nextPayload = resolveInput(internal.payload, payloadInput);
5✔
842
        return sourceFactory(internal.scope).force(nextPayload);
5✔
843
      };
844
      unit.force = (payloadInput) => executeRun(true, payloadInput);
207✔
845
      unit.stop = () => {
207✔
846
        if (internal.destroyed) {
10✔
UNCOV
847
          return;
×
848
        }
849

850
        internal.runSequence += 1;
10✔
851
        internal.latestRunSequence = internal.runSequence;
10✔
852
        internal.stopped = true;
10✔
853
        invokeSourceCleanup(internal.cleanup);
10✔
854
        internal.cleanup = null;
10✔
855
      };
856
      unit.destroy = () => {
207✔
857
        destroyInternal();
9✔
858
      };
859

860
      Object.defineProperty(unit, 'getSnapshot', {
207✔
861
        configurable: false,
862
        enumerable: false,
863
        writable: false,
864
        value: () => {
865
          return createUnitSnapshot({
23✔
866
            value: internal.state.value,
867
            status: internal.state.status,
868
            meta: internal.state.meta,
869
            context: internal.state.context,
870
          });
871
        },
872
      });
873

874
      internal.unit = unit;
207✔
875
      unitsByKey.set(key, internal);
207✔
876

877
      return unit;
207✔
878
  };
879

880
  return sourceFactory;
195✔
881
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc