@bgub/fig 0.0.1

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.
@@ -0,0 +1,611 @@
1
+ import { i as setCurrentDataStore, n as markDataResourceError, r as resolveCurrentDataStore, t as dataResourceKeysForError } from "./data-h46EcMnE.js";
2
+ //#region src/data-store.ts
3
+ const DataResourceSymbol = Symbol.for("fig.data-resource");
4
+ const DataStoreFactorySymbol = Symbol.for("fig.data-store-factory");
5
+ const DEFAULT_INACTIVE_RETENTION_MS = 300 * 1e3;
6
+ const DEFAULT_PRELOAD_RETENTION_MS = 30 * 1e3;
7
+ const dataStoreFactory = createDataStore;
8
+ function dataResource(options) {
9
+ const resource = {
10
+ $$typeof: DataResourceSymbol,
11
+ debugArgs: options.debugArgs,
12
+ key: options.key,
13
+ load: options.load
14
+ };
15
+ resource[DataStoreFactorySymbol] = dataStoreFactory;
16
+ return resource;
17
+ }
18
+ function invalidateData(resource, ...args) {
19
+ resolveDataMutationStore("invalidateData").invalidateData(resource, ...args);
20
+ }
21
+ function invalidateDataError(error) {
22
+ return resolveDataMutationStore("invalidateDataError").invalidateDataError(error);
23
+ }
24
+ function invalidateDataKey(key) {
25
+ resolveDataMutationStore("invalidateDataKey").invalidateDataKey(key);
26
+ }
27
+ function invalidateDataPrefix(prefix) {
28
+ resolveDataMutationStore("invalidateDataPrefix").invalidateDataPrefix(prefix);
29
+ }
30
+ function refreshData(resource, ...args) {
31
+ return resolveDataMutationStore("refreshData").refreshData(resource, ...args);
32
+ }
33
+ function readDataStore() {
34
+ return resolveCurrentDataStore("readDataStore() must be called synchronously while Fig is executing — during render, an event handler, an action, or an effect. Capture the handle there and use it after awaits.");
35
+ }
36
+ function resolveDataMutationStore(name) {
37
+ return resolveCurrentDataStore(`${name}() must be called synchronously while Fig is executing — during render, an event handler, an action, or an effect. Capture readDataStore() (or root.data) synchronously and call the handle instead.`);
38
+ }
39
+ function createDataStore(host) {
40
+ return new DefaultDataStore(host);
41
+ }
42
+ function normalizeDataResourceKey(key) {
43
+ return normalizeKey(key).canonical;
44
+ }
45
+ var DefaultDataStore = class {
46
+ host;
47
+ entries = /* @__PURE__ */ new Map();
48
+ inactiveRetentionMs;
49
+ ownerKeys = /* @__PURE__ */ new WeakMap();
50
+ pendingOwnerKeys = /* @__PURE__ */ new WeakMap();
51
+ partitionKey;
52
+ preloadRetentionMs;
53
+ disposed = false;
54
+ constructor(host) {
55
+ this.host = host;
56
+ this.inactiveRetentionMs = host.inactiveRetentionMs ?? DEFAULT_INACTIVE_RETENTION_MS;
57
+ this.partitionKey = host.partition === void 0 ? "" : encodeValue(host.partition, createEncodePath("partition"));
58
+ this.preloadRetentionMs = host.preloadRetentionMs ?? DEFAULT_PRELOAD_RETENTION_MS;
59
+ }
60
+ commitDataDependencies(owner, previousOwner) {
61
+ const nextKeys = this.pendingOwnerKeys.get(owner) ?? null;
62
+ const ownerKeys = this.ownerKeys.get(owner) ?? null;
63
+ const previousOwnerKeys = previousOwner === null ? null : this.ownerKeys.get(previousOwner) ?? null;
64
+ this.pendingOwnerKeys.delete(owner);
65
+ if ((nextKeys === null || nextKeys.size === 0) && ownerKeys === null && previousOwnerKeys === null) return;
66
+ let orphanCandidates = null;
67
+ orphanCandidates = this.collectSubscribedEntries(ownerKeys, orphanCandidates);
68
+ orphanCandidates = this.collectSubscribedEntries(previousOwnerKeys, orphanCandidates);
69
+ this.deleteDataOwner(owner, nextKeys);
70
+ if (previousOwner !== null) this.deleteDataOwner(previousOwner, nextKeys);
71
+ if (nextKeys !== null && nextKeys.size > 0) {
72
+ this.ownerKeys.set(owner, nextKeys);
73
+ for (const key of nextKeys) {
74
+ const entry = this.entries.get(key);
75
+ if (entry !== void 0) {
76
+ this.clearInactiveTimer(entry);
77
+ entry.subscribers.add(owner);
78
+ this.notifyEntryChange(entry);
79
+ }
80
+ }
81
+ }
82
+ if (orphanCandidates !== null) for (const entry of orphanCandidates) this.abortOrphanedLoad(entry);
83
+ }
84
+ releaseDataOwner(owner) {
85
+ const orphanCandidates = this.collectSubscribedEntries(this.ownerKeys.get(owner) ?? null, null);
86
+ this.deleteDataOwner(owner);
87
+ if (orphanCandidates !== null) for (const entry of orphanCandidates) this.abortOrphanedLoad(entry);
88
+ }
89
+ resetDataDependencies(owner) {
90
+ this.pendingOwnerKeys.delete(owner);
91
+ }
92
+ deleteDataOwner(owner, retainedKeys = null) {
93
+ this.pendingOwnerKeys.delete(owner);
94
+ const keys = this.ownerKeys.get(owner);
95
+ if (keys === void 0) return;
96
+ this.ownerKeys.delete(owner);
97
+ for (const key of keys) {
98
+ const entry = this.entries.get(key);
99
+ if (entry === void 0) continue;
100
+ entry.subscribers.delete(owner);
101
+ this.notifyEntryChange(entry);
102
+ if (retainedKeys?.has(key) !== true) this.scheduleInactiveCleanup(entry);
103
+ }
104
+ }
105
+ collectSubscribedEntries(keys, into) {
106
+ if (keys === null) return into;
107
+ for (const key of keys) {
108
+ const entry = this.entries.get(key);
109
+ if (entry !== void 0) {
110
+ into ??= /* @__PURE__ */ new Set();
111
+ into.add(entry);
112
+ }
113
+ }
114
+ return into;
115
+ }
116
+ abortOrphanedLoad(entry) {
117
+ if (this.entries.get(entry.storeKey) !== entry) return;
118
+ if (entry.subscribers.size > 0 || entry.preloadTimer !== null || entry.pending === null || entryHasValue(entry)) return;
119
+ this.evictEntry(entry, "evicted");
120
+ }
121
+ dispose() {
122
+ this.disposed = true;
123
+ for (const entry of this.entries.values()) {
124
+ this.clearInactiveTimer(entry);
125
+ this.clearPreloadTimer(entry);
126
+ this.abortActiveLoad(entry, "store-disposed");
127
+ this.notifyEntryChange(entry);
128
+ }
129
+ }
130
+ hydrate(entries) {
131
+ if (this.disposed) return;
132
+ for (const hydrated of entries) {
133
+ const normalized = normalizeKey(hydrated.key);
134
+ const storeKey = this.storeKey(normalized.canonical);
135
+ const current = this.entries.get(storeKey);
136
+ if (current !== void 0) {
137
+ this.hydrateEntry(current, normalized.key, hydrated.value);
138
+ this.publish(current);
139
+ continue;
140
+ }
141
+ const entry = this.createEntry(normalized, storeKey, null, null, "fulfilled", hydrated.value);
142
+ this.entries.set(storeKey, entry);
143
+ this.notifyEntryChange(entry);
144
+ }
145
+ }
146
+ snapshot() {
147
+ const entries = [];
148
+ for (const entry of this.entries.values()) if (entryHasValue(entry)) entries.push({
149
+ key: entry.key,
150
+ value: entry.value
151
+ });
152
+ return entries;
153
+ }
154
+ inspectDataEntries() {
155
+ return Array.from(this.entries.values(), (entry) => this.snapshotEntry(entry));
156
+ }
157
+ invalidateData(resource, ...args) {
158
+ if (this.disposed) return;
159
+ const { entry } = this.entryFor(resource, args, false);
160
+ if (entry === null) return;
161
+ this.invalidateEntry(entry, this.host.getLane());
162
+ }
163
+ invalidateDataError(error) {
164
+ if (this.disposed) return false;
165
+ const keys = dataResourceKeysForError(error);
166
+ if (keys === void 0 || keys.length === 0) return false;
167
+ const entries = [];
168
+ for (const key of keys) {
169
+ const entry = this.entryForKey(key);
170
+ if (entry !== null) entries.push(entry);
171
+ }
172
+ this.invalidateEntries(entries);
173
+ return true;
174
+ }
175
+ invalidateDataKey(key) {
176
+ if (this.disposed) return;
177
+ const entry = this.entryForKey(key);
178
+ if (entry === null) return;
179
+ this.invalidateEntry(entry, this.host.getLane());
180
+ }
181
+ invalidateDataPrefix(prefix) {
182
+ if (this.disposed) return;
183
+ const prefixCanonical = normalizeKey(prefix).canonical;
184
+ const entries = [];
185
+ for (const entry of this.entries.values()) if (canonicalKeyStartsWith(entry.canonicalKey, prefixCanonical)) entries.push(entry);
186
+ this.invalidateEntries(entries);
187
+ }
188
+ preloadData(resource, ...args) {
189
+ if (this.disposed || resource.load === void 0) return;
190
+ const { entry } = this.entryFor(resource, args, true);
191
+ this.clearInactiveTimer(entry);
192
+ this.retainPreload(entry);
193
+ if (entry.pending !== null) return;
194
+ if (entry.status === "fulfilled" && !entry.stale) return;
195
+ this.startLoad(entry, resource, args, {
196
+ lane: this.host.getLane(),
197
+ refresh: entry.status === "fulfilled"
198
+ });
199
+ }
200
+ readData(resource, args, owner) {
201
+ const { entry, key } = this.entryFor(resource, args, true);
202
+ this.clearInactiveTimer(entry);
203
+ this.clearPreloadTimer(entry);
204
+ this.addOwnerKey(owner, key);
205
+ if (entry.status === "fulfilled" && entry.stale && entry.pending === null && entry.refreshError === void 0 && resource.load !== void 0) this.startLoad(entry, resource, args, {
206
+ lane: this.host.getLane(),
207
+ refresh: true
208
+ });
209
+ if (entry.status === "pending" && entry.pending === null) this.startLoad(entry, resource, args, {
210
+ lane: this.host.getLane(),
211
+ refresh: false
212
+ });
213
+ return this.readCurrentValue(entry);
214
+ }
215
+ refreshData(resource, ...args) {
216
+ if (this.disposed) return Promise.resolve({
217
+ reason: "store-disposed",
218
+ staleValue: void 0,
219
+ status: "aborted"
220
+ });
221
+ if (resource.load === void 0) {
222
+ const { entry } = this.entryFor(resource, args, false);
223
+ if (entry === null) return Promise.resolve(unsupportedRefreshResult());
224
+ this.clearInactiveTimer(entry);
225
+ return Promise.resolve(unsupportedRefreshResult(entry));
226
+ }
227
+ const { entry } = this.entryFor(resource, args, true);
228
+ this.clearInactiveTimer(entry);
229
+ if (entry.pending !== null && entry.status !== "refreshing") return entry.pending.promise;
230
+ return this.startLoad(entry, resource, args, {
231
+ lane: this.host.getLane(),
232
+ refresh: entry.status === "fulfilled" || entry.status === "refreshing"
233
+ });
234
+ }
235
+ run(callback) {
236
+ const previousStore = setCurrentDataStore(this);
237
+ try {
238
+ return callback();
239
+ } finally {
240
+ setCurrentDataStore(previousStore);
241
+ }
242
+ }
243
+ addOwnerKey(owner, key) {
244
+ let keys = this.pendingOwnerKeys.get(owner);
245
+ if (keys === void 0) {
246
+ keys = /* @__PURE__ */ new Set();
247
+ this.pendingOwnerKeys.set(owner, keys);
248
+ }
249
+ keys.add(key);
250
+ }
251
+ entryFor(resource, args, create) {
252
+ const normalized = normalizeKey(resource.key(...args));
253
+ const fingerprint = null;
254
+ const key = this.storeKey(normalized.canonical);
255
+ const current = this.entries.get(key);
256
+ if (current !== void 0) return {
257
+ entry: current,
258
+ key
259
+ };
260
+ if (!create) return {
261
+ entry: null,
262
+ key
263
+ };
264
+ const entry = this.createEntry(normalized, key, resource, fingerprint, "pending", void 0);
265
+ if (this.disposed) return {
266
+ entry,
267
+ key
268
+ };
269
+ this.entries.set(key, entry);
270
+ this.notifyEntryChange(entry);
271
+ return {
272
+ entry,
273
+ key
274
+ };
275
+ }
276
+ entryForKey(key) {
277
+ const normalized = normalizeKey(key);
278
+ return this.entries.get(this.storeKey(normalized.canonical)) ?? null;
279
+ }
280
+ createEntry(normalized, storeKey, resource, fingerprint, status, value) {
281
+ return {
282
+ canonicalKey: normalized.canonical,
283
+ controller: null,
284
+ error: void 0,
285
+ fingerprint,
286
+ generation: 0,
287
+ invalidationVersion: 0,
288
+ inactiveTimer: null,
289
+ key: normalized.key,
290
+ lane: null,
291
+ pending: null,
292
+ preloadTimer: null,
293
+ refreshError: void 0,
294
+ resource,
295
+ stale: false,
296
+ status,
297
+ storeKey,
298
+ subscribers: /* @__PURE__ */ new Set(),
299
+ value
300
+ };
301
+ }
302
+ hydrateEntry(entry, key, value) {
303
+ this.clearInactiveTimer(entry);
304
+ this.abortActiveLoad(entry, "superseded");
305
+ entry.error = void 0;
306
+ entry.generation += 1;
307
+ entry.invalidationVersion = 0;
308
+ entry.key = key;
309
+ entry.lane = null;
310
+ entry.refreshError = void 0;
311
+ entry.stale = false;
312
+ entry.status = "fulfilled";
313
+ entry.value = value;
314
+ }
315
+ storeKey(canonicalKey) {
316
+ return this.partitionKey === "" ? canonicalKey : `${this.partitionKey}:${canonicalKey}`;
317
+ }
318
+ startLoad(entry, resource, args, options) {
319
+ const hadValue = entryHasValue(entry);
320
+ const load = resource.load;
321
+ if (this.disposed) return Promise.resolve(abortedRefreshResult(entry, "store-disposed"));
322
+ if (load === void 0) {
323
+ const error = /* @__PURE__ */ new Error(`Data resource "${entry.canonicalKey}" has no loader and no hydrated value.`);
324
+ entry.error = error;
325
+ entry.status = "rejected";
326
+ markDataResourceError(error, entry.key);
327
+ this.notifyEntryChange(entry);
328
+ return Promise.resolve(unsupportedRefreshResult(entry));
329
+ }
330
+ this.abortActiveLoad(entry, "superseded");
331
+ const controller = new AbortController();
332
+ const generation = entry.generation + 1;
333
+ const invalidationVersion = entry.invalidationVersion;
334
+ const pending = createPendingResult();
335
+ entry.controller = controller;
336
+ entry.generation = generation;
337
+ entry.lane = options.lane;
338
+ entry.pending = pending;
339
+ entry.status = options.refresh && hadValue ? "refreshing" : "pending";
340
+ this.notifyEntryChange(entry);
341
+ let loaded;
342
+ try {
343
+ loaded = load(...args, { signal: controller.signal });
344
+ } catch (error) {
345
+ loaded = Promise.reject(error);
346
+ }
347
+ const settleAborted = () => {
348
+ const result = abortedRefreshResult(entry, "superseded");
349
+ pending.resolve(result);
350
+ return result;
351
+ };
352
+ const fulfill = (value) => {
353
+ if (entry.generation !== generation || controller.signal.aborted) return settleAborted();
354
+ entry.controller = null;
355
+ entry.error = void 0;
356
+ entry.pending = null;
357
+ entry.refreshError = void 0;
358
+ entry.stale = entry.invalidationVersion !== invalidationVersion;
359
+ entry.status = "fulfilled";
360
+ entry.value = value;
361
+ this.publish(entry);
362
+ const result = {
363
+ status: "fulfilled",
364
+ value
365
+ };
366
+ pending.resolve(result);
367
+ return result;
368
+ };
369
+ const reject = (error) => {
370
+ if (entry.generation !== generation || controller.signal.aborted) return settleAborted();
371
+ entry.controller = null;
372
+ entry.pending = null;
373
+ if (hadValue) {
374
+ entry.refreshError = error;
375
+ entry.stale = true;
376
+ entry.status = "fulfilled";
377
+ this.publish(entry);
378
+ const result = {
379
+ error,
380
+ staleValue: entry.value,
381
+ status: "rejected"
382
+ };
383
+ pending.resolve(result);
384
+ return result;
385
+ }
386
+ entry.error = error;
387
+ entry.status = "rejected";
388
+ markDataResourceError(error, entry.key);
389
+ this.publish(entry);
390
+ const result = {
391
+ error,
392
+ status: "rejected"
393
+ };
394
+ pending.resolve(result);
395
+ return result;
396
+ };
397
+ if (!isThenable(loaded)) {
398
+ fulfill(loaded);
399
+ return pending.promise;
400
+ }
401
+ Promise.resolve(loaded).then(fulfill, reject);
402
+ return pending.promise;
403
+ }
404
+ publish(entry) {
405
+ this.notifyEntryChange(entry);
406
+ this.scheduleInactiveCleanup(entry);
407
+ this.scheduleSubscribers(entry, entry.lane ?? this.host.getLane());
408
+ }
409
+ scheduleSubscribers(entry, lane) {
410
+ for (const subscriber of entry.subscribers) this.host.schedule(subscriber, lane);
411
+ }
412
+ abortActiveLoad(entry, reason) {
413
+ const pending = entry.pending;
414
+ if (pending === null) return;
415
+ entry.controller?.abort();
416
+ entry.controller = null;
417
+ entry.pending = null;
418
+ pending.resolve(abortedRefreshResult(entry, reason));
419
+ }
420
+ retainPreload(entry) {
421
+ this.clearPreloadTimer(entry);
422
+ if (this.disposed || !Number.isFinite(this.preloadRetentionMs)) return;
423
+ entry.preloadTimer = scheduleStoreTimer(() => {
424
+ entry.preloadTimer = null;
425
+ if (entry.subscribers.size === 0 && entry.pending !== null && !entryHasValue(entry)) {
426
+ this.evictEntry(entry, "evicted");
427
+ return;
428
+ }
429
+ this.scheduleInactiveCleanup(entry);
430
+ }, Math.max(0, this.preloadRetentionMs));
431
+ }
432
+ scheduleInactiveCleanup(entry) {
433
+ if (this.disposed || entry.subscribers.size > 0 || entry.pending !== null || entry.preloadTimer !== null || !Number.isFinite(this.inactiveRetentionMs)) return;
434
+ this.clearInactiveTimer(entry);
435
+ entry.inactiveTimer = scheduleStoreTimer(() => {
436
+ entry.inactiveTimer = null;
437
+ if (entry.subscribers.size > 0 || entry.pending !== null || entry.preloadTimer !== null) return;
438
+ this.evictEntry(entry, "evicted");
439
+ }, Math.max(0, this.inactiveRetentionMs));
440
+ }
441
+ evictEntry(entry, reason) {
442
+ if (this.entries.get(entry.storeKey) !== entry) return;
443
+ this.clearInactiveTimer(entry);
444
+ this.clearPreloadTimer(entry);
445
+ this.abortActiveLoad(entry, reason);
446
+ this.entries.delete(entry.storeKey);
447
+ this.host.onEntryEvict?.(this.snapshotEntry(entry));
448
+ }
449
+ clearInactiveTimer(entry) {
450
+ if (entry.inactiveTimer === null) return;
451
+ clearTimeout(entry.inactiveTimer);
452
+ entry.inactiveTimer = null;
453
+ }
454
+ clearPreloadTimer(entry) {
455
+ if (entry.preloadTimer === null) return;
456
+ clearTimeout(entry.preloadTimer);
457
+ entry.preloadTimer = null;
458
+ }
459
+ notifyEntryChange(entry) {
460
+ this.host.onEntryChange?.(this.snapshotEntry(entry));
461
+ }
462
+ snapshotEntry(entry) {
463
+ const hasValue = entryHasValue(entry);
464
+ return {
465
+ canonicalKey: entry.canonicalKey,
466
+ error: entry.status === "rejected" ? entry.error : void 0,
467
+ hasValue,
468
+ key: entry.key,
469
+ pending: entry.pending !== null,
470
+ refreshError: entry.refreshError,
471
+ stale: entry.stale,
472
+ status: entry.status,
473
+ subscriberCount: entry.subscribers.size,
474
+ value: hasValue ? entry.value : void 0
475
+ };
476
+ }
477
+ readCurrentValue(entry) {
478
+ if (entryHasValue(entry)) return entry.value;
479
+ if (entry.status === "rejected") throwDataResourceError(entry);
480
+ if (entry.pending === null) throw new Error(`Data resource "${entry.canonicalKey}" has no pending load.`);
481
+ throw entry.pending.promise;
482
+ }
483
+ invalidateEntry(entry, lane) {
484
+ entry.invalidationVersion += 1;
485
+ entry.stale = true;
486
+ entry.refreshError = void 0;
487
+ if (entry.status === "rejected") {
488
+ entry.error = void 0;
489
+ entry.status = "pending";
490
+ }
491
+ this.notifyEntryChange(entry);
492
+ if (entry.subscribers.size === 0) return;
493
+ this.scheduleSubscribers(entry, lane);
494
+ }
495
+ invalidateEntries(entries) {
496
+ if (entries.length === 0) return;
497
+ const lane = this.host.getLane();
498
+ for (const entry of entries) this.invalidateEntry(entry, lane);
499
+ }
500
+ };
501
+ function normalizeKey(key) {
502
+ if (!Array.isArray(key) || typeof key[0] !== "string") throw new Error("Data resource keys must be arrays starting with a string.");
503
+ return {
504
+ canonical: encodeArray(key, createEncodePath("key")),
505
+ key
506
+ };
507
+ }
508
+ function canonicalKeyStartsWith(key, prefix) {
509
+ if (key === prefix) return true;
510
+ const arrayPrefix = prefix.slice(0, -1);
511
+ return key.startsWith(arrayPrefix) && key[arrayPrefix.length] === ",";
512
+ }
513
+ function entryHasValue(entry) {
514
+ return entry.status === "fulfilled" || entry.status === "refreshing";
515
+ }
516
+ function throwDataResourceError(entry) {
517
+ markDataResourceError(entry.error, entry.key);
518
+ throw entry.error;
519
+ }
520
+ function abortedRefreshResult(entry, reason) {
521
+ return {
522
+ reason,
523
+ staleValue: entryHasValue(entry) ? entry.value : void 0,
524
+ status: "aborted"
525
+ };
526
+ }
527
+ function unsupportedRefreshResult(entry) {
528
+ const result = {
529
+ reason: "no-client-loader",
530
+ status: "unsupported"
531
+ };
532
+ if (entry !== void 0) result.staleValue = entryHasValue(entry) ? entry.value : void 0;
533
+ return result;
534
+ }
535
+ function createEncodePath(root) {
536
+ return {
537
+ root,
538
+ segments: []
539
+ };
540
+ }
541
+ function formatEncodePath(path) {
542
+ let text = path.root;
543
+ for (const segment of path.segments) text += typeof segment === "number" ? `[${segment}]` : `.${segment}`;
544
+ return text;
545
+ }
546
+ function encodeArray(values, path) {
547
+ const parts = [];
548
+ for (let index = 0; index < values.length; index += 1) {
549
+ path.segments.push(index);
550
+ parts.push(encodeValue(values[index], path));
551
+ path.segments.pop();
552
+ }
553
+ return `[${parts.join(",")}]`;
554
+ }
555
+ function encodeObject(value, path) {
556
+ const prototype = Object.getPrototypeOf(value);
557
+ if (prototype !== Object.prototype && prototype !== null) throw new Error(`Invalid data resource key value at ${formatEncodePath(path)}.`);
558
+ const record = value;
559
+ const keys = Object.keys(record).sort();
560
+ const parts = [];
561
+ for (const key of keys) {
562
+ const child = record[key];
563
+ if (child === void 0) throw new Error(`Invalid undefined data resource key value at ${formatEncodePath(path)}.`);
564
+ path.segments.push(key);
565
+ parts.push(`${JSON.stringify(key)}:${encodeValue(child, path)}`);
566
+ path.segments.pop();
567
+ }
568
+ return `{${parts.join(",")}}`;
569
+ }
570
+ function encodeValue(value, path) {
571
+ if (value === null) return "null";
572
+ switch (typeof value) {
573
+ case "string": return JSON.stringify(value);
574
+ case "boolean": return value ? "true" : "false";
575
+ case "number":
576
+ if (!Number.isFinite(value)) throw new Error(`Invalid number in data resource key at ${formatEncodePath(path)}.`);
577
+ return Object.is(value, -0) ? "0" : JSON.stringify(value);
578
+ case "object":
579
+ if (Array.isArray(value)) return encodeArray(value, path);
580
+ return encodeObject(value, path);
581
+ default: throw new Error(`Invalid data resource key value at ${formatEncodePath(path)}.`);
582
+ }
583
+ }
584
+ function isThenable(value) {
585
+ return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
586
+ }
587
+ function createPendingResult() {
588
+ let resolve = () => void 0;
589
+ return {
590
+ promise: new Promise((settle) => {
591
+ resolve = settle;
592
+ }),
593
+ resolve
594
+ };
595
+ }
596
+ function scheduleStoreTimer(callback, delay) {
597
+ const timer = setTimeout(callback, delay);
598
+ const unref = timer.unref;
599
+ if (unref !== void 0) unref.call(timer);
600
+ return timer;
601
+ }
602
+ function runWithDataStore(store, callback) {
603
+ return store.run(callback);
604
+ }
605
+ function currentDataStore() {
606
+ return resolveCurrentDataStore();
607
+ }
608
+ //#endregion
609
+ export { invalidateDataError as a, normalizeDataResourceKey as c, runWithDataStore as d, invalidateData as i, readDataStore as l, currentDataStore as n, invalidateDataKey as o, dataResource as r, invalidateDataPrefix as s, createDataStore as t, refreshData as u };
610
+
611
+ //# sourceMappingURL=data-store-CRnNAT9-.js.map