@logixjs/query 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.
Files changed (43) hide show
  1. package/dist/Engine.cjs +77 -0
  2. package/dist/Engine.cjs.map +1 -0
  3. package/dist/Engine.d.cts +57 -0
  4. package/dist/Engine.d.ts +57 -0
  5. package/dist/Engine.js +8 -0
  6. package/dist/Engine.js.map +1 -0
  7. package/dist/Query.cjs +457 -0
  8. package/dist/Query.cjs.map +1 -0
  9. package/dist/Query.d.cts +61 -0
  10. package/dist/Query.d.ts +61 -0
  11. package/dist/Query.js +10 -0
  12. package/dist/Query.js.map +1 -0
  13. package/dist/TanStack-C3mxN6Aj.d.cts +40 -0
  14. package/dist/TanStack-jQhqYG8i.d.ts +40 -0
  15. package/dist/TanStack.cjs +139 -0
  16. package/dist/TanStack.cjs.map +1 -0
  17. package/dist/TanStack.d.cts +5 -0
  18. package/dist/TanStack.d.ts +5 -0
  19. package/dist/TanStack.js +10 -0
  20. package/dist/TanStack.js.map +1 -0
  21. package/dist/Traits.cjs +65 -0
  22. package/dist/Traits.cjs.map +1 -0
  23. package/dist/Traits.d.cts +76 -0
  24. package/dist/Traits.d.ts +76 -0
  25. package/dist/Traits.js +10 -0
  26. package/dist/Traits.js.map +1 -0
  27. package/dist/chunk-L745BR5P.js +124 -0
  28. package/dist/chunk-L745BR5P.js.map +1 -0
  29. package/dist/chunk-NXFX6RIH.js +355 -0
  30. package/dist/chunk-NXFX6RIH.js.map +1 -0
  31. package/dist/chunk-PZ5AY32C.js +10 -0
  32. package/dist/chunk-PZ5AY32C.js.map +1 -0
  33. package/dist/chunk-THVAADR2.js +53 -0
  34. package/dist/chunk-THVAADR2.js.map +1 -0
  35. package/dist/chunk-V3F5KWNH.js +30 -0
  36. package/dist/chunk-V3F5KWNH.js.map +1 -0
  37. package/dist/index.cjs +582 -0
  38. package/dist/index.cjs.map +1 -0
  39. package/dist/index.d.cts +8 -0
  40. package/dist/index.d.ts +8 -0
  41. package/dist/index.js +22 -0
  42. package/dist/index.js.map +1 -0
  43. package/package.json +55 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,582 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Engine: () => Engine,
34
+ TanStack: () => TanStack_exports,
35
+ make: () => make,
36
+ source: () => source,
37
+ traits: () => toStateTraitSpec
38
+ });
39
+ module.exports = __toCommonJS(index_exports);
40
+
41
+ // src/Query.ts
42
+ var Logix4 = __toESM(require("@logixjs/core"), 1);
43
+ var import_effect5 = require("effect");
44
+
45
+ // src/internal/logics/auto-trigger.ts
46
+ var Logix = __toESM(require("@logixjs/core"), 1);
47
+ var import_effect3 = require("effect");
48
+
49
+ // src/Engine.ts
50
+ var import_effect2 = require("effect");
51
+
52
+ // src/internal/middleware/middleware.ts
53
+ var import_effect = require("effect");
54
+ var middleware = (config) => /* @__PURE__ */ (() => {
55
+ let cachedEngine;
56
+ return (op) => {
57
+ if (op.kind !== "service" && op.kind !== "trait-source" || !op.meta?.resourceId || !op.meta.keyHash) {
58
+ return op.effect;
59
+ }
60
+ const resourceId = op.meta.resourceId;
61
+ if (config?.useFor && !config.useFor(resourceId)) {
62
+ return op.effect;
63
+ }
64
+ const keyHash = op.meta.keyHash;
65
+ if (cachedEngine) {
66
+ if (cachedEngine.fetchFast) {
67
+ return cachedEngine.fetchFast(resourceId, keyHash, op.effect);
68
+ }
69
+ return cachedEngine.fetch({ resourceId, keyHash, effect: op.effect });
70
+ }
71
+ return import_effect.Effect.serviceOption(Engine).pipe(
72
+ import_effect.Effect.flatMap((engineOpt) => {
73
+ if (import_effect.Option.isNone(engineOpt)) {
74
+ return import_effect.Effect.fail(
75
+ new Error(
76
+ `[Query.Engine.middleware] Missing Query.Engine in the Runtime scope; please provide Query.Engine.layer(Query.TanStack.engine(new QueryClient())) (recommended) or Query.Engine.layer(customEngine).`
77
+ )
78
+ );
79
+ }
80
+ cachedEngine = engineOpt.value;
81
+ if (cachedEngine.fetchFast) {
82
+ return cachedEngine.fetchFast(resourceId, keyHash, op.effect);
83
+ }
84
+ return cachedEngine.fetch({ resourceId, keyHash, effect: op.effect });
85
+ })
86
+ );
87
+ };
88
+ })();
89
+
90
+ // src/Engine.ts
91
+ var EngineTagImpl = class extends import_effect2.Context.Tag("@logixjs/query/Engine")() {
92
+ };
93
+ var Engine = Object.assign(EngineTagImpl, {
94
+ layer: (engine2) => import_effect2.Layer.succeed(EngineTagImpl, engine2),
95
+ middleware: (config) => middleware(config)
96
+ });
97
+
98
+ // src/internal/logics/auto-trigger.ts
99
+ var defaultTriggers = ["onMount", "onKeyChange"];
100
+ var getTriggers = (triggers) => triggers ?? defaultTriggers;
101
+ var isManualOnly = (triggers) => triggers.length === 1 && triggers[0] === "manual";
102
+ var getSnapshotKeyHash = (snapshot) => {
103
+ if (!snapshot || typeof snapshot !== "object") return void 0;
104
+ const keyHash = snapshot.keyHash;
105
+ return typeof keyHash === "string" ? keyHash : void 0;
106
+ };
107
+ var getSnapshotStatus = (snapshot) => {
108
+ if (!snapshot || typeof snapshot !== "object") return void 0;
109
+ const status = snapshot.status;
110
+ return typeof status === "string" ? status : void 0;
111
+ };
112
+ var autoTrigger = (module2, config) => module2.logic(($) => {
113
+ const pending = /* @__PURE__ */ new Map();
114
+ const lastKeyHash = /* @__PURE__ */ new Map();
115
+ const hydrateFromFreshCache = (name, q, keyHash) => import_effect3.Effect.gen(function* () {
116
+ const engineOpt = yield* import_effect3.Effect.serviceOption(Engine);
117
+ if (engineOpt._tag === "None") return false;
118
+ const engine2 = engineOpt.value;
119
+ if (!engine2.peekFresh) return false;
120
+ const dataOpt = yield* engine2.peekFresh({
121
+ resourceId: q.resource.id,
122
+ keyHash
123
+ });
124
+ if (dataOpt._tag === "None") return false;
125
+ const snapshot = Logix.Resource.Snapshot.success({
126
+ keyHash,
127
+ data: dataOpt.value
128
+ });
129
+ yield* $.state.mutate((draft) => {
130
+ ;
131
+ draft.queries[name] = snapshot;
132
+ });
133
+ return true;
134
+ });
135
+ const cancelPending = (name) => import_effect3.Effect.gen(function* () {
136
+ const prev = pending.get(name);
137
+ if (!prev) return;
138
+ pending.delete(name);
139
+ yield* import_effect3.Fiber.interruptFork(prev);
140
+ });
141
+ const sourcePathOf = (name) => `queries.${name}`;
142
+ const refresh = (name, options) => $.traits.source.refresh(sourcePathOf(name), options);
143
+ const scheduleDebounced = (name, ms) => import_effect3.Effect.gen(function* () {
144
+ yield* cancelPending(name);
145
+ const fiber = yield* import_effect3.Effect.forkScoped(
146
+ import_effect3.Effect.sleep(import_effect3.Duration.millis(ms)).pipe(
147
+ import_effect3.Effect.zipRight(refresh(name)),
148
+ import_effect3.Effect.ensuring(import_effect3.Effect.sync(() => pending.delete(name))),
149
+ import_effect3.Effect.catchAllCause(() => import_effect3.Effect.void)
150
+ )
151
+ );
152
+ pending.set(name, fiber);
153
+ });
154
+ const computeKeyHash = (state, q) => {
155
+ const getAtPath = (root, path) => {
156
+ const parts = path.split(".");
157
+ let cur = root;
158
+ for (const p of parts) {
159
+ if (cur == null) return void 0;
160
+ cur = cur[p];
161
+ }
162
+ return cur;
163
+ };
164
+ try {
165
+ const keyState = { params: state.params, ui: state.ui };
166
+ const args = q.deps.map((dep) => getAtPath(keyState, dep));
167
+ const key = q.key(...args);
168
+ if (key === void 0) return void 0;
169
+ return Logix.Resource.keyHash(key);
170
+ } catch {
171
+ return void 0;
172
+ }
173
+ };
174
+ const maybeAutoRefresh = (phase, stateOverride) => import_effect3.Effect.gen(function* () {
175
+ const state = stateOverride ?? (yield* $.state.read);
176
+ for (const [name, q] of Object.entries(config.queries)) {
177
+ const queryName = name;
178
+ const triggers = getTriggers(q.triggers);
179
+ if (isManualOnly(triggers)) {
180
+ continue;
181
+ }
182
+ if (phase === "mount" && !triggers.includes("onMount")) {
183
+ continue;
184
+ }
185
+ if (phase === "keyChange" && !triggers.includes("onKeyChange")) {
186
+ continue;
187
+ }
188
+ const keyHash = computeKeyHash(state, q);
189
+ const snapshot = state?.queries?.[queryName];
190
+ const snapshotKeyHash = getSnapshotKeyHash(snapshot);
191
+ const snapshotStatus = getSnapshotStatus(snapshot);
192
+ if (keyHash === void 0) {
193
+ lastKeyHash.set(queryName, void 0);
194
+ continue;
195
+ }
196
+ const last = lastKeyHash.get(queryName);
197
+ if (snapshotStatus && snapshotStatus !== "idle" && snapshotKeyHash === keyHash && last === keyHash) {
198
+ continue;
199
+ }
200
+ if (snapshotStatus && snapshotStatus !== "idle" && snapshotKeyHash === keyHash) {
201
+ lastKeyHash.set(queryName, keyHash);
202
+ continue;
203
+ }
204
+ lastKeyHash.set(queryName, keyHash);
205
+ const hydrated = yield* hydrateFromFreshCache(queryName, q, keyHash);
206
+ if (hydrated) {
207
+ yield* cancelPending(queryName);
208
+ continue;
209
+ }
210
+ const debounceMs = q.debounceMs ?? 0;
211
+ if (phase === "keyChange" && debounceMs > 0) {
212
+ yield* scheduleDebounced(queryName, debounceMs);
213
+ } else {
214
+ yield* cancelPending(queryName);
215
+ yield* refresh(queryName);
216
+ }
217
+ }
218
+ });
219
+ const refreshAll = (options) => import_effect3.Effect.forEach(
220
+ Object.keys(config.queries),
221
+ (name) => cancelPending(name).pipe(import_effect3.Effect.zipRight(refresh(name, options)))
222
+ ).pipe(import_effect3.Effect.asVoid);
223
+ const setup = $.lifecycle.onStart(maybeAutoRefresh("mount"));
224
+ const run = import_effect3.Effect.suspend(
225
+ () => import_effect3.Effect.all(
226
+ [
227
+ // params/ui changes: handled by Query's default logic, avoiding scattered UI-side useEffect triggers.
228
+ $.onAction("setParams").runFork(
229
+ (action) => import_effect3.Effect.gen(function* () {
230
+ const state = yield* $.state.read;
231
+ const next = { ...state, params: action.payload };
232
+ yield* maybeAutoRefresh("keyChange", next);
233
+ })
234
+ ),
235
+ $.onAction("setUi").runFork(
236
+ (action) => import_effect3.Effect.gen(function* () {
237
+ const state = yield* $.state.read;
238
+ const next = { ...state, ui: action.payload };
239
+ yield* maybeAutoRefresh("keyChange", next);
240
+ })
241
+ ),
242
+ // Manual refresh: not restricted by triggers (manual-only still allows explicit refresh).
243
+ $.onAction("refresh").runFork(
244
+ (action) => import_effect3.Effect.gen(function* () {
245
+ const target = action.payload;
246
+ if (typeof target === "string" && target.length > 0) {
247
+ yield* cancelPending(target);
248
+ yield* refresh(target, { force: true });
249
+ } else {
250
+ yield* refreshAll({ force: true });
251
+ }
252
+ })
253
+ )
254
+ ],
255
+ { concurrency: "unbounded" }
256
+ ).pipe(import_effect3.Effect.asVoid)
257
+ );
258
+ return { setup, run };
259
+ });
260
+
261
+ // src/internal/logics/invalidate.ts
262
+ var Logix2 = __toESM(require("@logixjs/core"), 1);
263
+ var import_effect4 = require("effect");
264
+ var toInvalidateTargets = (request, queries) => {
265
+ if (request.kind === "byResource") {
266
+ return Object.entries(queries).filter(([, q]) => q.resource.id === request.resourceId).map(([name, q]) => ({ name, resourceId: q.resource.id }));
267
+ }
268
+ if (request.kind === "byParams") {
269
+ return Object.entries(queries).filter(([, q]) => q.resource.id === request.resourceId).map(([name, q]) => ({ name, resourceId: q.resource.id }));
270
+ }
271
+ const entries = Object.entries(queries);
272
+ const tagged = entries.filter(([, q]) => Array.isArray(q.tags) && q.tags.includes(request.tag));
273
+ const selected = tagged.length > 0 ? tagged : entries;
274
+ return selected.map(([name, q]) => ({ name, resourceId: q.resource.id }));
275
+ };
276
+ var invalidate = (module2, config) => module2.logic(
277
+ ($) => import_effect4.Effect.gen(function* () {
278
+ yield* $.onAction("invalidate").runFork(
279
+ (action) => import_effect4.Effect.gen(function* () {
280
+ const request = action.payload;
281
+ yield* Logix2.TraitLifecycle.scopedExecute($, {
282
+ kind: "query:invalidate",
283
+ request
284
+ });
285
+ const engineOpt = yield* import_effect4.Effect.serviceOption(Engine);
286
+ if (engineOpt._tag !== "None") {
287
+ yield* engineOpt.value.invalidate(request);
288
+ }
289
+ const targets = toInvalidateTargets(request, config.queries);
290
+ const sourcePathOf = (name) => `queries.${name}`;
291
+ yield* import_effect4.Effect.forEach(
292
+ targets,
293
+ (t) => $.traits.source.refresh(sourcePathOf(t.name), { force: true })
294
+ ).pipe(import_effect4.Effect.asVoid);
295
+ })
296
+ );
297
+ })
298
+ );
299
+
300
+ // src/Traits.ts
301
+ var Logix3 = __toESM(require("@logixjs/core"), 1);
302
+ var source = (config) => config;
303
+ var toStateTraitSpec = (input) => {
304
+ const out = {};
305
+ for (const [name, q] of Object.entries(input.queries)) {
306
+ const triggers = q.triggers ?? ["onMount", "onKeyChange"];
307
+ if (triggers.includes("manual") && triggers.length > 1) {
308
+ throw new Error(
309
+ `[Query.traits] "manual" must be exclusive, but got triggers=[${triggers.join(", ")}] for query "${name}".`
310
+ );
311
+ }
312
+ out[`queries.${name}`] = Logix3.StateTrait.source({
313
+ // deps: used for graph building/diagnostics/future reverse-closure; Query also reuses deps to converge triggers.
314
+ deps: q.deps,
315
+ resource: q.resource.id,
316
+ triggers,
317
+ debounceMs: q.debounceMs,
318
+ concurrency: q.concurrency === "exhaust" ? "exhaust-trailing" : q.concurrency,
319
+ key: (...depsValues) => q.key(...depsValues)
320
+ });
321
+ }
322
+ return out;
323
+ };
324
+
325
+ // src/Query.ts
326
+ var InvalidateRequestSchema = import_effect5.Schema.Union(
327
+ import_effect5.Schema.Struct({
328
+ kind: import_effect5.Schema.Literal("byResource"),
329
+ resourceId: import_effect5.Schema.String
330
+ }),
331
+ import_effect5.Schema.Struct({
332
+ kind: import_effect5.Schema.Literal("byParams"),
333
+ resourceId: import_effect5.Schema.String,
334
+ keyHash: import_effect5.Schema.String
335
+ }),
336
+ import_effect5.Schema.Struct({
337
+ kind: import_effect5.Schema.Literal("byTag"),
338
+ tag: import_effect5.Schema.String
339
+ })
340
+ );
341
+ var assertQueryName = (name) => {
342
+ if (!name) {
343
+ throw new Error(`[Query.make] query name must be non-empty`);
344
+ }
345
+ if (name.includes(".")) {
346
+ throw new Error(`[Query.make] query name must not include "."; got "${name}"`);
347
+ }
348
+ if (name === "params" || name === "ui" || name === "queries") {
349
+ throw new Error(`[Query.make] query name "${name}" is reserved`);
350
+ }
351
+ };
352
+ var make = (id, config) => {
353
+ const queryBuilder = {
354
+ source: (q) => q
355
+ };
356
+ const queries = (() => {
357
+ const raw = config.queries;
358
+ if (!raw) return {};
359
+ return raw(queryBuilder);
360
+ })();
361
+ const queriesForTraits = queries;
362
+ for (const name of Object.keys(queries)) {
363
+ assertQueryName(name);
364
+ }
365
+ const RefreshTargetSchema = (() => {
366
+ const names = Object.keys(queries);
367
+ if (names.length === 0) return import_effect5.Schema.Never;
368
+ if (names.length === 1) {
369
+ return import_effect5.Schema.Literal(names[0]);
370
+ }
371
+ const asUnionMembers = (items) => {
372
+ if (items.length < 2) {
373
+ throw new Error(`[Query.make] internal error: expected at least 2 query names for union`);
374
+ }
375
+ return items;
376
+ };
377
+ const members = names.map((n) => import_effect5.Schema.Literal(n));
378
+ return import_effect5.Schema.Union(...asUnionMembers(members));
379
+ })();
380
+ const UiSchema = import_effect5.Schema.Unknown;
381
+ const QueriesSchema = import_effect5.Schema.Struct(
382
+ Object.fromEntries(Object.keys(queries).map((k) => [k, import_effect5.Schema.Unknown]))
383
+ );
384
+ const StateSchema = import_effect5.Schema.Struct({
385
+ params: config.params,
386
+ ui: UiSchema,
387
+ queries: QueriesSchema
388
+ });
389
+ const Actions = {
390
+ setParams: config.params,
391
+ setUi: UiSchema,
392
+ refresh: import_effect5.Schema.UndefinedOr(RefreshTargetSchema),
393
+ invalidate: InvalidateRequestSchema
394
+ };
395
+ const reducers = {
396
+ setParams: (state, action, sink) => {
397
+ sink?.("params");
398
+ return { ...state, params: action.payload ?? state.params };
399
+ },
400
+ setUi: (state, action, sink) => {
401
+ sink?.("ui");
402
+ return { ...state, ui: action.payload ?? state.ui };
403
+ },
404
+ refresh: (state) => state,
405
+ invalidate: (state) => state
406
+ };
407
+ const queryTraits = Object.keys(queriesForTraits).length > 0 ? toStateTraitSpec({ queries: queriesForTraits }) : void 0;
408
+ const traits = queryTraits || config.traits ? {
409
+ ...queryTraits,
410
+ ...config.traits
411
+ } : void 0;
412
+ const module2 = Logix4.Module.make(id, {
413
+ state: StateSchema,
414
+ actions: Actions,
415
+ reducers,
416
+ traits
417
+ });
418
+ const logics = [
419
+ autoTrigger(module2.tag, { queries: queriesForTraits }),
420
+ invalidate(module2.tag, { queries: queriesForTraits })
421
+ ];
422
+ const initial = (params) => ({
423
+ params: params ?? config.initialParams,
424
+ ui: config.ui ?? {},
425
+ queries: Object.fromEntries(
426
+ Object.keys(queries).map((k) => [k, Logix4.Resource.Snapshot.idle()])
427
+ )
428
+ });
429
+ const controller = {
430
+ make: (runtime) => {
431
+ const dispatch = runtime.dispatch;
432
+ const actions = module2.actions;
433
+ return {
434
+ runtime,
435
+ getState: runtime.getState,
436
+ dispatch,
437
+ controller: {
438
+ setParams: (params) => dispatch(actions.setParams(params)),
439
+ setUi: (ui) => dispatch(actions.setUi(ui)),
440
+ refresh: (target) => dispatch(actions.refresh(target)),
441
+ invalidate: (request) => dispatch(actions.invalidate(request))
442
+ }
443
+ };
444
+ }
445
+ };
446
+ module2.controller = controller;
447
+ const EXTEND_HANDLE = /* @__PURE__ */ Symbol.for("logix.module.handle.extend");
448
+ module2.tag[EXTEND_HANDLE] = (runtime, base) => {
449
+ const c = controller.make(runtime);
450
+ return {
451
+ ...base,
452
+ controller: c.controller
453
+ };
454
+ };
455
+ return module2.implement({
456
+ initial: initial(),
457
+ logics: [...logics]
458
+ });
459
+ };
460
+
461
+ // src/TanStack.ts
462
+ var TanStack_exports = {};
463
+ __export(TanStack_exports, {
464
+ engine: () => engine,
465
+ observe: () => observe
466
+ });
467
+
468
+ // src/internal/engine/tanstack.ts
469
+ var import_effect6 = require("effect");
470
+ var makeQueryKey = (resourceId, keyHash) => [resourceId, keyHash];
471
+ var engine = (queryClient, config) => {
472
+ const byResourceId = /* @__PURE__ */ new Map();
473
+ const maxEntriesPerResource = config?.maxEntriesPerResource ?? 2e3;
474
+ try {
475
+ const queryCache = queryClient.getQueryCache?.();
476
+ if (queryCache && typeof queryCache.clear === "function") {
477
+ const original = queryCache.clear.bind(queryCache);
478
+ queryCache.clear = () => {
479
+ byResourceId.clear();
480
+ return original();
481
+ };
482
+ }
483
+ } catch {
484
+ }
485
+ const ensureBucket = (resourceId) => {
486
+ let bucket = byResourceId.get(resourceId);
487
+ if (!bucket) {
488
+ bucket = /* @__PURE__ */ new Map();
489
+ byResourceId.set(resourceId, bucket);
490
+ }
491
+ return bucket;
492
+ };
493
+ const evictIfNeeded = (bucket) => {
494
+ if (maxEntriesPerResource === Infinity) return;
495
+ if (!Number.isFinite(maxEntriesPerResource) || maxEntriesPerResource <= 0) return;
496
+ while (bucket.size > maxEntriesPerResource) {
497
+ const firstKey = bucket.keys().next().value;
498
+ if (firstKey === void 0) return;
499
+ bucket.delete(firstKey);
500
+ }
501
+ };
502
+ const fetchFast = (resourceId, keyHash, effect) => import_effect6.Effect.suspend(() => {
503
+ const hit = byResourceId.get(resourceId)?.get(keyHash);
504
+ if (hit !== void 0) {
505
+ return import_effect6.Effect.succeed(hit);
506
+ }
507
+ return import_effect6.Effect.map(effect, (out) => {
508
+ if (out !== void 0) {
509
+ const bucket = ensureBucket(resourceId);
510
+ bucket.set(keyHash, out);
511
+ evictIfNeeded(bucket);
512
+ }
513
+ return out;
514
+ });
515
+ });
516
+ return {
517
+ fetch: ({ resourceId, keyHash, effect }) => fetchFast(resourceId, keyHash, effect),
518
+ fetchFast,
519
+ invalidate: (request) => import_effect6.Effect.gen(function* () {
520
+ yield* import_effect6.Effect.sync(() => {
521
+ if (request.kind === "byParams") {
522
+ const bucket = byResourceId.get(request.resourceId);
523
+ if (!bucket) return;
524
+ bucket.delete(request.keyHash);
525
+ if (bucket.size === 0) {
526
+ byResourceId.delete(request.resourceId);
527
+ }
528
+ return;
529
+ }
530
+ if (request.kind === "byResource") {
531
+ byResourceId.delete(request.resourceId);
532
+ return;
533
+ }
534
+ byResourceId.clear();
535
+ });
536
+ yield* import_effect6.Effect.tryPromise({
537
+ try: () => {
538
+ if (request.kind === "byResource") {
539
+ return queryClient.invalidateQueries({
540
+ queryKey: [request.resourceId]
541
+ });
542
+ }
543
+ if (request.kind === "byParams") {
544
+ return queryClient.invalidateQueries({
545
+ queryKey: makeQueryKey(request.resourceId, request.keyHash)
546
+ });
547
+ }
548
+ return queryClient.invalidateQueries({
549
+ predicate: (q) => {
550
+ const tags = q.meta?.tags;
551
+ return Array.isArray(tags) && tags.includes(request.tag);
552
+ }
553
+ });
554
+ },
555
+ catch: (e) => e
556
+ }).pipe(import_effect6.Effect.asVoid);
557
+ }),
558
+ peekFresh: ({ resourceId, keyHash }) => import_effect6.Effect.sync(() => {
559
+ const hit = byResourceId.get(resourceId)?.get(keyHash);
560
+ return hit === void 0 ? import_effect6.Option.none() : import_effect6.Option.some(hit);
561
+ })
562
+ };
563
+ };
564
+
565
+ // src/internal/tanstack/observer.ts
566
+ var import_effect7 = require("effect");
567
+ var import_query_core = require("@tanstack/query-core");
568
+ var observe = (params) => import_effect7.Effect.gen(function* () {
569
+ const observer = new import_query_core.QueryObserver(params.queryClient, params.options);
570
+ const unsubscribe = observer.subscribe(params.onResult);
571
+ yield* import_effect7.Effect.addFinalizer(() => import_effect7.Effect.sync(() => unsubscribe()));
572
+ return observer;
573
+ });
574
+ // Annotate the CommonJS export names for ESM import in node:
575
+ 0 && (module.exports = {
576
+ Engine,
577
+ TanStack,
578
+ make,
579
+ source,
580
+ traits
581
+ });
582
+ //# sourceMappingURL=index.cjs.map