fetchium 0.0.0 → 0.1.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.
- package/CHANGELOG.md +250 -0
- package/README.md +287 -0
- package/dist/cjs/development/QueryClient-CLi3ONNM.js +2 -0
- package/dist/cjs/development/QueryClient-CLi3ONNM.js.map +1 -0
- package/dist/cjs/development/QueryController-BQA49OYU.js +2 -0
- package/dist/cjs/development/QueryController-BQA49OYU.js.map +1 -0
- package/dist/cjs/development/index.js +2 -0
- package/dist/cjs/development/index.js.map +1 -0
- package/dist/cjs/development/mutation-CikIl_6k.js +2 -0
- package/dist/cjs/development/mutation-CikIl_6k.js.map +1 -0
- package/dist/cjs/development/package.json +3 -0
- package/dist/cjs/development/react/index.js +2 -0
- package/dist/cjs/development/react/index.js.map +1 -0
- package/dist/cjs/development/rest/index.js +2 -0
- package/dist/cjs/development/rest/index.js.map +1 -0
- package/dist/cjs/development/shared-Ct5zKrt4.js +2 -0
- package/dist/cjs/development/shared-Ct5zKrt4.js.map +1 -0
- package/dist/cjs/development/stores/async.js +2 -0
- package/dist/cjs/development/stores/async.js.map +1 -0
- package/dist/cjs/development/stores/sync.js +2 -0
- package/dist/cjs/development/stores/sync.js.map +1 -0
- package/dist/cjs/development/subscriptions/polling.js +2 -0
- package/dist/cjs/development/subscriptions/polling.js.map +1 -0
- package/dist/cjs/development/topic/index.js +2 -0
- package/dist/cjs/development/topic/index.js.map +1 -0
- package/dist/cjs/production/QueryClient-N0MJmuHW.js +2 -0
- package/dist/cjs/production/QueryClient-N0MJmuHW.js.map +1 -0
- package/dist/cjs/production/QueryController-BQA49OYU.js +2 -0
- package/dist/cjs/production/QueryController-BQA49OYU.js.map +1 -0
- package/dist/cjs/production/index.js +2 -0
- package/dist/cjs/production/index.js.map +1 -0
- package/dist/cjs/production/mutation-P_Yb4LI9.js +2 -0
- package/dist/cjs/production/mutation-P_Yb4LI9.js.map +1 -0
- package/dist/cjs/production/package.json +3 -0
- package/dist/cjs/production/react/index.js +2 -0
- package/dist/cjs/production/react/index.js.map +1 -0
- package/dist/cjs/production/rest/index.js +2 -0
- package/dist/cjs/production/rest/index.js.map +1 -0
- package/dist/cjs/production/shared-Ct5zKrt4.js +2 -0
- package/dist/cjs/production/shared-Ct5zKrt4.js.map +1 -0
- package/dist/cjs/production/stores/async.js +2 -0
- package/dist/cjs/production/stores/async.js.map +1 -0
- package/dist/cjs/production/stores/sync.js +2 -0
- package/dist/cjs/production/stores/sync.js.map +1 -0
- package/dist/cjs/production/subscriptions/polling.js +2 -0
- package/dist/cjs/production/subscriptions/polling.js.map +1 -0
- package/dist/cjs/production/topic/index.js +2 -0
- package/dist/cjs/production/topic/index.js.map +1 -0
- package/dist/esm/ConstraintMatcher.d.ts +42 -0
- package/dist/esm/ConstraintMatcher.d.ts.map +1 -0
- package/dist/esm/EntityInstance.d.ts +38 -0
- package/dist/esm/EntityInstance.d.ts.map +1 -0
- package/dist/esm/EntityStore.d.ts +14 -0
- package/dist/esm/EntityStore.d.ts.map +1 -0
- package/dist/esm/GcManager.d.ts +38 -0
- package/dist/esm/GcManager.d.ts.map +1 -0
- package/dist/esm/LiveCollection.d.ts +86 -0
- package/dist/esm/LiveCollection.d.ts.map +1 -0
- package/dist/esm/MutationResult.d.ts +22 -0
- package/dist/esm/MutationResult.d.ts.map +1 -0
- package/dist/esm/NetworkManager.d.ts +62 -0
- package/dist/esm/NetworkManager.d.ts.map +1 -0
- package/dist/esm/QueryClient.d.ts +98 -0
- package/dist/esm/QueryClient.d.ts.map +1 -0
- package/dist/esm/QueryController.d.ts +49 -0
- package/dist/esm/QueryController.d.ts.map +1 -0
- package/dist/esm/QueryResult.d.ts +67 -0
- package/dist/esm/QueryResult.d.ts.map +1 -0
- package/dist/esm/applyEntities.d.ts +12 -0
- package/dist/esm/applyEntities.d.ts.map +1 -0
- package/dist/esm/development/QueryClient-Dtde3pss.js +2572 -0
- package/dist/esm/development/QueryClient-Dtde3pss.js.map +1 -0
- package/dist/esm/development/QueryController-Ch_ncxiI.js +14 -0
- package/dist/esm/development/QueryController-Ch_ncxiI.js.map +1 -0
- package/dist/esm/development/index.js +32 -0
- package/dist/esm/development/index.js.map +1 -0
- package/dist/esm/development/mutation-UZshUQAf.js +58 -0
- package/dist/esm/development/mutation-UZshUQAf.js.map +1 -0
- package/dist/esm/development/react/index.js +40 -0
- package/dist/esm/development/react/index.js.map +1 -0
- package/dist/esm/development/rest/index.js +142 -0
- package/dist/esm/development/rest/index.js.map +1 -0
- package/dist/esm/development/shared-DcuVH8Pf.js +15 -0
- package/dist/esm/development/shared-DcuVH8Pf.js.map +1 -0
- package/dist/esm/development/stores/async.js +214 -0
- package/dist/esm/development/stores/async.js.map +1 -0
- package/dist/esm/development/stores/sync.js +149 -0
- package/dist/esm/development/stores/sync.js.map +1 -0
- package/dist/esm/development/subscriptions/polling.js +25 -0
- package/dist/esm/development/subscriptions/polling.js.map +1 -0
- package/dist/esm/development/topic/index.js +86 -0
- package/dist/esm/development/topic/index.js.map +1 -0
- package/dist/esm/errors.d.ts +4 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/fieldRef.d.ts +15 -0
- package/dist/esm/fieldRef.d.ts.map +1 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/mutation.d.ts +34 -0
- package/dist/esm/mutation.d.ts.map +1 -0
- package/dist/esm/parseEntities.d.ts +44 -0
- package/dist/esm/parseEntities.d.ts.map +1 -0
- package/dist/esm/production/QueryClient-YqnBxFy1.js +2457 -0
- package/dist/esm/production/QueryClient-YqnBxFy1.js.map +1 -0
- package/dist/esm/production/QueryController-Ch_ncxiI.js +14 -0
- package/dist/esm/production/QueryController-Ch_ncxiI.js.map +1 -0
- package/dist/esm/production/index.js +32 -0
- package/dist/esm/production/index.js.map +1 -0
- package/dist/esm/production/mutation-pgFl1uIY.js +58 -0
- package/dist/esm/production/mutation-pgFl1uIY.js.map +1 -0
- package/dist/esm/production/react/index.js +40 -0
- package/dist/esm/production/react/index.js.map +1 -0
- package/dist/esm/production/rest/index.js +142 -0
- package/dist/esm/production/rest/index.js.map +1 -0
- package/dist/esm/production/shared-DcuVH8Pf.js +15 -0
- package/dist/esm/production/shared-DcuVH8Pf.js.map +1 -0
- package/dist/esm/production/stores/async.js +214 -0
- package/dist/esm/production/stores/async.js.map +1 -0
- package/dist/esm/production/stores/sync.js +149 -0
- package/dist/esm/production/stores/sync.js.map +1 -0
- package/dist/esm/production/subscriptions/polling.js +25 -0
- package/dist/esm/production/subscriptions/polling.js.map +1 -0
- package/dist/esm/production/topic/index.js +86 -0
- package/dist/esm/production/topic/index.js.map +1 -0
- package/dist/esm/proxy.d.ts +20 -0
- package/dist/esm/proxy.d.ts.map +1 -0
- package/dist/esm/proxyId.d.ts +8 -0
- package/dist/esm/proxyId.d.ts.map +1 -0
- package/dist/esm/query-types.d.ts +60 -0
- package/dist/esm/query-types.d.ts.map +1 -0
- package/dist/esm/query.d.ts +64 -0
- package/dist/esm/query.d.ts.map +1 -0
- package/dist/esm/react/index.d.ts +2 -0
- package/dist/esm/react/index.d.ts.map +1 -0
- package/dist/esm/react/use-query.d.ts +5 -0
- package/dist/esm/react/use-query.d.ts.map +1 -0
- package/dist/esm/rest/RESTMutation.d.ts +18 -0
- package/dist/esm/rest/RESTMutation.d.ts.map +1 -0
- package/dist/esm/rest/RESTQuery.d.ts +24 -0
- package/dist/esm/rest/RESTQuery.d.ts.map +1 -0
- package/dist/esm/rest/RESTQueryController.d.ts +34 -0
- package/dist/esm/rest/RESTQueryController.d.ts.map +1 -0
- package/dist/esm/rest/index.d.ts +5 -0
- package/dist/esm/rest/index.d.ts.map +1 -0
- package/dist/esm/retry.d.ts +4 -0
- package/dist/esm/retry.d.ts.map +1 -0
- package/dist/esm/stores/async.d.ts +80 -0
- package/dist/esm/stores/async.d.ts.map +1 -0
- package/dist/esm/stores/shared.d.ts +12 -0
- package/dist/esm/stores/shared.d.ts.map +1 -0
- package/dist/esm/stores/sync.d.ts +41 -0
- package/dist/esm/stores/sync.d.ts.map +1 -0
- package/dist/esm/subscriptions/polling.d.ts +6 -0
- package/dist/esm/subscriptions/polling.d.ts.map +1 -0
- package/dist/esm/testing/MockClient.d.ts +64 -0
- package/dist/esm/testing/MockClient.d.ts.map +1 -0
- package/dist/esm/testing/auto-generate.d.ts +20 -0
- package/dist/esm/testing/auto-generate.d.ts.map +1 -0
- package/dist/esm/testing/entity-factory.d.ts +13 -0
- package/dist/esm/testing/entity-factory.d.ts.map +1 -0
- package/dist/esm/testing/index.d.ts +6 -0
- package/dist/esm/testing/index.d.ts.map +1 -0
- package/dist/esm/testing/types.d.ts +37 -0
- package/dist/esm/testing/types.d.ts.map +1 -0
- package/dist/esm/topic/TopicQuery.d.ts +10 -0
- package/dist/esm/topic/TopicQuery.d.ts.map +1 -0
- package/dist/esm/topic/TopicQueryController.d.ts +43 -0
- package/dist/esm/topic/TopicQueryController.d.ts.map +1 -0
- package/dist/esm/topic/index.d.ts +3 -0
- package/dist/esm/topic/index.d.ts.map +1 -0
- package/dist/esm/type-utils.d.ts +16 -0
- package/dist/esm/type-utils.d.ts.map +1 -0
- package/dist/esm/typeDefs.d.ts +86 -0
- package/dist/esm/typeDefs.d.ts.map +1 -0
- package/dist/esm/types.d.ts +277 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/utils.d.ts +38 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/index.d.ts +1 -0
- package/package.json +181 -5
- package/plugin/.claude-plugin/plugin.json +10 -0
- package/plugin/agents/fetchium.md +168 -0
- package/plugin/docs/api/fetchium-react.md +135 -0
- package/plugin/docs/api/fetchium.md +674 -0
- package/plugin/docs/api/stores-async.md +219 -0
- package/plugin/docs/api/stores-sync.md +133 -0
- package/plugin/docs/core/entities.md +351 -0
- package/plugin/docs/core/queries.md +600 -0
- package/plugin/docs/core/streaming.md +550 -0
- package/plugin/docs/core/types.md +374 -0
- package/plugin/docs/data/caching.md +298 -0
- package/plugin/docs/data/live-data.md +435 -0
- package/plugin/docs/data/mutations.md +465 -0
- package/plugin/docs/guides/auth.md +318 -0
- package/plugin/docs/guides/error-handling.md +351 -0
- package/plugin/docs/guides/offline.md +270 -0
- package/plugin/docs/guides/testing.md +301 -0
- package/plugin/docs/quickstart.md +170 -0
- package/plugin/docs/reference/pagination.md +519 -0
- package/plugin/docs/reference/rest-queries.md +107 -0
- package/plugin/docs/reference/why-signalium.md +364 -0
- package/plugin/docs/setup/project-setup.md +319 -0
- package/plugin/install.mjs +88 -0
- package/plugin/skills/design/SKILL.md +140 -0
- package/plugin/skills/teach/SKILL.md +105 -0
- package/stores/async.d.ts +1 -0
- package/stores/async.js +15 -0
- package/stores/sync.d.ts +1 -0
- package/stores/sync.js +15 -0
- package/index.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryController-BQA49OYU.js","sources":["../../../src/QueryController.ts"],"sourcesContent":["import { type QueryContext } from './query-types.js';\nimport type { Query } from './query.js';\nimport type { Mutation } from './mutation.js';\n\n// ================================\n// IQueryClient — minimal interface QueryController needs from the client\n// (avoids circular import: QueryClient → QueryController → QueryClient)\n// ================================\n\nexport interface IQueryClientForController {\n getContext(): QueryContext;\n applyMutationEvent(event: import('./types.js').MutationEvent): void;\n}\n\n// ================================\n// QueryController base class\n// ================================\n\nexport abstract class QueryController {\n protected queryClient: IQueryClientForController | undefined;\n\n /**\n * Called once by QueryClient when this controller is registered.\n * Subclasses can override to do setup (e.g. open a WebSocket connection).\n */\n register(queryClient: IQueryClientForController): void {\n this.queryClient = queryClient;\n }\n\n /**\n * Called when the network comes online or goes offline.\n * Subclasses can override to reconnect persistent connections (e.g. WebSocket).\n */\n onNetworkStatusChange?(isOnline: boolean): void;\n\n /**\n * Called when the QueryClient is destroyed.\n * Subclasses can override to clean up connections or timers.\n */\n destroy?(): void;\n\n /**\n * Send the query and return the raw response data.\n * @param ctx The query execution context (a reified Query instance with params applied).\n * @param signal AbortSignal to cancel the in-flight request.\n */\n abstract send(ctx: Query, signal: AbortSignal): Promise<unknown>;\n\n /**\n * Fetch the next page of results. Only implement if the controller supports pagination.\n * @param ctx The query execution context. `ctx.resultData` contains the current page's data.\n * @param signal AbortSignal to cancel the in-flight request.\n */\n sendNext?(ctx: Query, signal: AbortSignal): Promise<unknown>;\n\n /**\n * Return true if more pages are available for the current result.\n * Called reactively — do not perform async work here.\n */\n hasNext?(ctx: Query): boolean;\n\n /**\n * Send a mutation and return the raw response data.\n * @param ctx The mutation execution context (a reified Mutation instance with params applied).\n * @param signal AbortSignal to cancel the in-flight request.\n */\n sendMutation?(ctx: Mutation, signal: AbortSignal): Promise<unknown>;\n}\n"],"names":["QueryController","queryClient"],"mappings":"aAkBO,MAAeA,CAAgB,CAC1B,YAMV,SAASC,EAA8C,CACrD,KAAK,YAAcA,CACrB,CAwCF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./QueryClient-N0MJmuHW.js"),r=require("./QueryController-BQA49OYU.js"),t=require("./mutation-P_Yb4LI9.js");exports.ARRAY_KEY=e.ARRAY_KEY;exports.Entity=e.Entity;exports.GcManager=e.GcManager;exports.LiveFieldConfig=e.LiveFieldConfig;exports.LiveFieldType=e.LiveFieldType;exports.Mask=e.Mask;exports.NetworkManager=e.NetworkManager;exports.NetworkManagerContext=e.NetworkManagerContext;exports.NetworkMode=e.NetworkMode;exports.NoOpGcManager=e.NoOpGcManager;exports.NoOpNetworkManager=e.NoOpNetworkManager;exports.QUERY_ID=e.QUERY_ID;exports.Query=e.Query;exports.QueryClient=e.QueryClient;exports.QueryClientContext=e.QueryClientContext;exports.RECORD_KEY=e.RECORD_KEY;exports.defaultNetworkManager=e.defaultNetworkManager;exports.draft=e.draft;exports.fetchQuery=e.fetchQuery;exports.queryKeyForClass=e.queryKeyForClass;exports.registerFormat=e.registerFormat;exports.t=e.t;exports.QueryController=r.QueryController;exports.Mutation=t.Mutation;exports.getMutation=t.getMutation;exports.mutationKeyForClass=t.mutationKeyForClass;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const g=require("signalium"),n=require("./QueryClient-N0MJmuHW.js");class y{static controller;params;result;optimisticUpdates;config;effects;constructor(){return n.createDefinitionProxy(this)}}const a=new WeakMap,h=t=>{const e=a.get(t);if(e===void 0)throw new Error("Mutation definition not found");return e().id};function D(t){let e=a.get(t);if(e!==void 0)return e;let o;const f=()=>{if(o!==void 0)return o;const l=new t,r=n.extractDefinition(l),{fields:i}=r,d=`mutation:${String(r.methods.getIdentityKey.call(i))}`,c=i.params??{},m=c instanceof n.ValidatorDef?c:n.t.object(c),s=i.result,p=s!==void 0?s instanceof n.ValidatorDef?s:n.t.object(s):void 0,u=t.controller;if(!u)throw new Error(`Mutation class "${t.name}" must define a static \`controller\` property. Extend RESTMutation (from fetchium/rest) or set \`static controller = MyController\` on your mutation class.`);return o={id:d,requestShape:m,responseShape:p,captured:r,optimisticUpdates:i.optimisticUpdates??!1,config:i.config,effects:i.effects,hasGetEffects:typeof r.methods.getEffects=="function",controllerClass:u},o};return a.set(t,f),f}function M(t){const e=D(t),o=g.getContext(n.QueryClientContext);if(o===void 0)throw new Error("QueryClient not found");return o.getMutation(e())}exports.Mutation=y;exports.getMutation=M;exports.mutationKeyForClass=h;
|
|
2
|
+
//# sourceMappingURL=mutation-P_Yb4LI9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-P_Yb4LI9.js","sources":["../../../src/mutation.ts"],"sourcesContent":["import { getContext, ReactiveTask } from 'signalium';\nimport { ExtractType, InternalTypeDef, MutationEffects, TypeDef, RetryConfig, TypeDefShape } from './types.js';\nimport { QueryClientContext, type QueryContext } from './QueryClient.js';\nimport { ValidatorDef, t } from './typeDefs.js';\nimport { createDefinitionProxy, extractDefinition, type CapturedDefinition } from './fieldRef.js';\nimport type { QueryController } from './QueryController.js';\n\n// ================================\n// Mutation Definition Types\n// ================================\n\nexport interface MutationConfigOptions {\n retry?: RetryConfig | number | false;\n}\n\nexport interface MutationDefinition<Request, Response> {\n id: string;\n requestShape: InternalTypeDef;\n responseShape: InternalTypeDef | undefined;\n captured: CapturedDefinition<Mutation>;\n optimisticUpdates: boolean;\n config?: MutationConfigOptions;\n effects?: MutationEffects;\n hasGetEffects: boolean;\n controllerClass: typeof QueryController;\n}\n\n// ================================\n// Mutation base class\n// ================================\n\nexport abstract class Mutation {\n static controller?: typeof QueryController;\n\n readonly params?: TypeDefShape;\n readonly result?: TypeDefShape;\n readonly optimisticUpdates?: boolean;\n readonly config?: MutationConfigOptions;\n readonly effects?: Readonly<MutationEffects>;\n\n declare context: QueryContext;\n\n abstract getIdentityKey(): unknown;\n\n getEffects?(): MutationEffects;\n\n constructor() {\n return createDefinitionProxy(this);\n }\n}\n\n// ================================\n// Mutation definition cache and lookup\n// ================================\n\nconst mutationDefCache = new WeakMap<new () => Mutation, () => MutationDefinition<any, any>>();\n\nexport const mutationKeyForClass = (cls: new () => Mutation): string => {\n const getMutationDef = mutationDefCache.get(cls);\n\n if (getMutationDef === undefined) {\n throw new Error('Mutation definition not found');\n }\n\n return getMutationDef().id;\n};\n\n// ================================\n// Internal: build mutation definition from class\n// ================================\n\nfunction buildMutationDefinition(MutationClass: new () => Mutation): () => MutationDefinition<any, any> {\n let cached = mutationDefCache.get(MutationClass);\n\n if (cached !== undefined) {\n return cached;\n }\n\n let mutationDefinition: MutationDefinition<any, any> | undefined;\n\n const getter = (): MutationDefinition<any, any> => {\n if (mutationDefinition !== undefined) {\n return mutationDefinition;\n }\n\n const instance = new MutationClass();\n const captured = extractDefinition(instance);\n const { fields } = captured;\n\n const id = `mutation:${String(captured.methods.getIdentityKey.call(fields))}`;\n\n const requestDef = fields.params ?? {};\n const requestShape = (requestDef instanceof ValidatorDef\n ? requestDef\n : t.object(requestDef)) as unknown as InternalTypeDef;\n const responseDef = fields.result;\n const responseShape =\n responseDef !== undefined\n ? ((responseDef instanceof ValidatorDef ? responseDef : t.object(responseDef)) as unknown as InternalTypeDef)\n : undefined;\n\n const controllerClass = (MutationClass as typeof Mutation).controller;\n if (!controllerClass) {\n throw new Error(\n `Mutation class \"${MutationClass.name}\" must define a static \\`controller\\` property. ` +\n `Extend RESTMutation (from fetchium/rest) or set \\`static controller = MyController\\` on your mutation class.`,\n );\n }\n\n mutationDefinition = {\n id,\n requestShape,\n responseShape,\n captured,\n optimisticUpdates: fields.optimisticUpdates ?? false,\n config: fields.config,\n effects: fields.effects,\n hasGetEffects: typeof captured.methods.getEffects === 'function',\n controllerClass,\n };\n\n return mutationDefinition;\n };\n\n mutationDefCache.set(MutationClass, getter);\n return getter;\n}\n\n// ================================\n// Public API\n// ================================\n\nexport function getMutation<T extends Mutation>(\n MutationClass: new () => T,\n): ReactiveTask<Readonly<ExtractType<T['result']>>, [ExtractType<T['params']>]> {\n const getMutationDef = buildMutationDefinition(MutationClass);\n\n const queryClient = getContext(QueryClientContext);\n\n if (queryClient === undefined) {\n throw new Error('QueryClient not found');\n }\n\n return queryClient.getMutation<any, any>(getMutationDef());\n}\n"],"names":["Mutation","createDefinitionProxy","mutationDefCache","mutationKeyForClass","cls","getMutationDef","buildMutationDefinition","MutationClass","cached","mutationDefinition","getter","instance","captured","extractDefinition","fields","id","requestDef","requestShape","ValidatorDef","t","responseDef","responseShape","controllerClass","getMutation","queryClient","getContext","QueryClientContext"],"mappings":"iFA+BO,MAAeA,CAAS,CAC7B,OAAO,WAEE,OACA,OACA,kBACA,OACA,QAQT,aAAc,CACZ,OAAOC,EAAAA,sBAAsB,IAAI,CACnC,CACF,CAMA,MAAMC,MAAuB,QAEhBC,EAAuBC,GAAoC,CACtE,MAAMC,EAAiBH,EAAiB,IAAIE,CAAG,EAE/C,GAAIC,IAAmB,OACrB,MAAM,IAAI,MAAM,+BAA+B,EAGjD,OAAOA,IAAiB,EAC1B,EAMA,SAASC,EAAwBC,EAAuE,CACtG,IAAIC,EAASN,EAAiB,IAAIK,CAAa,EAE/C,GAAIC,IAAW,OACb,OAAOA,EAGT,IAAIC,EAEJ,MAAMC,EAAS,IAAoC,CACjD,GAAID,IAAuB,OACzB,OAAOA,EAGT,MAAME,EAAW,IAAIJ,EACfK,EAAWC,EAAAA,kBAAkBF,CAAQ,EACrC,CAAE,OAAAG,GAAWF,EAEbG,EAAK,YAAY,OAAOH,EAAS,QAAQ,eAAe,KAAKE,CAAM,CAAC,CAAC,GAErEE,EAAaF,EAAO,QAAU,CAAA,EAC9BG,EAAgBD,aAAsBE,EAAAA,aACxCF,EACAG,EAAAA,EAAE,OAAOH,CAAU,EACjBI,EAAcN,EAAO,OACrBO,EACJD,IAAgB,OACVA,aAAuBF,EAAAA,aAAeE,EAAcD,IAAE,OAAOC,CAAW,EAC1E,OAEAE,EAAmBf,EAAkC,WAC3D,GAAI,CAACe,EACH,MAAM,IAAI,MACR,mBAAmBf,EAAc,IAAI,8JAAA,EAKzC,OAAAE,EAAqB,CACnB,GAAAM,EACA,aAAAE,EACA,cAAAI,EACA,SAAAT,EACA,kBAAmBE,EAAO,mBAAqB,GAC/C,OAAQA,EAAO,OACf,QAASA,EAAO,QAChB,cAAe,OAAOF,EAAS,QAAQ,YAAe,WACtD,gBAAAU,CAAA,EAGKb,CACT,EAEA,OAAAP,EAAiB,IAAIK,EAAeG,CAAM,EACnCA,CACT,CAMO,SAASa,EACdhB,EAC8E,CAC9E,MAAMF,EAAiBC,EAAwBC,CAAa,EAEtDiB,EAAcC,EAAAA,WAAWC,oBAAkB,EAEjD,GAAIF,IAAgB,OAClB,MAAM,IAAI,MAAM,uBAAuB,EAGzC,OAAOA,EAAY,YAAsBnB,GAAgB,CAC3D"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("signalium/react"),i=require("signalium"),f=require("../QueryClient-N0MJmuHW.js");function n(e){if(Array.isArray(e))return e.map(n);if(e&&typeof e=="object"){if(e instanceof Date)return new Date(e);if(e instanceof RegExp)return new RegExp(e);if(e instanceof Map)return new Map(Array.from(e.entries()).map(([t,c])=>[n(t),n(c)]));if(e instanceof Set)return new Set(Array.from(e).map(n));const r=Object.create(Object.getPrototypeOf(e));for(const t of Object.keys(e))r[t]=n(e[t]);return r}return e}const y=i.reactive(e=>n(e.value)),a=i.reactive((e,...r)=>{const t=f.fetchQuery(e,...r);return new Proxy(t,{get(c,o,u){return o==="value"?y(c):Reflect.get(c,o,u)}})}),p=i.reactive(e=>e.value);function g(e,...r){const t=s.useReactive(a,e,...r);return s.useReactive(p,t),t}exports.useQuery=g;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/react/use-query.ts"],"sourcesContent":["import { useReactive } from 'signalium/react';\nimport { reactive } from 'signalium';\nimport { ExtractType, QueryPromise } from '../types.js';\nimport { ExtractQueryParams, fetchQuery, Query } from '../query.js';\nimport { HasRequiredKeys, Optionalize, Signalize } from '../type-utils.js';\n\nfunction cloneDeep<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map(cloneDeep) as unknown as T;\n }\n if (value && typeof value === 'object') {\n if (value instanceof Date) {\n return new Date(value) as unknown as T;\n }\n if (value instanceof RegExp) {\n return new RegExp(value) as unknown as T;\n }\n if (value instanceof Map) {\n return new Map(Array.from(value.entries()).map(([k, v]) => [cloneDeep(k), cloneDeep(v)])) as unknown as T;\n }\n if (value instanceof Set) {\n return new Set(Array.from(value).map(cloneDeep)) as unknown as T;\n }\n const result: any = Object.create(Object.getPrototypeOf(value));\n for (const key of Object.keys(value)) {\n result[key] = cloneDeep((value as any)[key]);\n }\n return result as T;\n }\n return value;\n}\n\nconst clonedResult = reactive((result: QueryPromise<Query>) => cloneDeep(result.value));\n\nconst reifiedQuery = reactive(\n <T extends Query>(\n QueryClass: new () => T,\n ...args: HasRequiredKeys<ExtractType<T['params']>> extends true\n ? [params: Optionalize<Signalize<ExtractType<T['params']>>>]\n : [params?: Optionalize<Signalize<ExtractType<T['params']>>> | undefined]\n ): QueryPromise<T> => {\n const queryResult = fetchQuery(QueryClass, ...args);\n\n return new Proxy(queryResult, {\n get(target, prop, receiver) {\n if (prop === 'value') {\n return clonedResult(target);\n }\n\n return Reflect.get(target, prop, receiver);\n },\n });\n },\n);\n\nconst resultValue = reactive((result: QueryPromise<Query>) => result.value);\n\nexport function useQuery<T extends Query>(\n QueryClass: new () => T,\n ...args: HasRequiredKeys<ExtractType<T['params']>> extends true\n ? [params: Optionalize<Signalize<ExtractType<T['params']>>>]\n : [params?: Optionalize<Signalize<ExtractType<T['params']>>> | undefined]\n): QueryPromise<T> {\n const result = useReactive(reifiedQuery, QueryClass, ...args);\n\n useReactive(resultValue, result);\n\n return result;\n}\n"],"names":["cloneDeep","value","k","v","result","key","clonedResult","reactive","reifiedQuery","QueryClass","args","queryResult","fetchQuery","target","prop","receiver","resultValue","useQuery","useReactive"],"mappings":"kLAMA,SAASA,EAAaC,EAAa,CACjC,GAAI,MAAM,QAAQA,CAAK,EACrB,OAAOA,EAAM,IAAID,CAAS,EAE5B,GAAIC,GAAS,OAAOA,GAAU,SAAU,CACtC,GAAIA,aAAiB,KACnB,OAAO,IAAI,KAAKA,CAAK,EAEvB,GAAIA,aAAiB,OACnB,OAAO,IAAI,OAAOA,CAAK,EAEzB,GAAIA,aAAiB,IACnB,OAAO,IAAI,IAAI,MAAM,KAAKA,EAAM,QAAA,CAAS,EAAE,IAAI,CAAC,CAACC,EAAGC,CAAC,IAAM,CAACH,EAAUE,CAAC,EAAGF,EAAUG,CAAC,CAAC,CAAC,CAAC,EAE1F,GAAIF,aAAiB,IACnB,OAAO,IAAI,IAAI,MAAM,KAAKA,CAAK,EAAE,IAAID,CAAS,CAAC,EAEjD,MAAMI,EAAc,OAAO,OAAO,OAAO,eAAeH,CAAK,CAAC,EAC9D,UAAWI,KAAO,OAAO,KAAKJ,CAAK,EACjCG,EAAOC,CAAG,EAAIL,EAAWC,EAAcI,CAAG,CAAC,EAE7C,OAAOD,CACT,CACA,OAAOH,CACT,CAEA,MAAMK,EAAeC,EAAAA,SAAUH,GAAgCJ,EAAUI,EAAO,KAAK,CAAC,EAEhFI,EAAeD,EAAAA,SACnB,CACEE,KACGC,IAGiB,CACpB,MAAMC,EAAcC,EAAAA,WAAWH,EAAY,GAAGC,CAAI,EAElD,OAAO,IAAI,MAAMC,EAAa,CAC5B,IAAIE,EAAQC,EAAMC,EAAU,CAC1B,OAAID,IAAS,QACJR,EAAaO,CAAM,EAGrB,QAAQ,IAAIA,EAAQC,EAAMC,CAAQ,CAC3C,CAAA,CACD,CACH,CACF,EAEMC,EAAcT,EAAAA,SAAUH,GAAgCA,EAAO,KAAK,EAEnE,SAASa,EACdR,KACGC,EAGc,CACjB,MAAMN,EAASc,EAAAA,YAAYV,EAAcC,EAAY,GAAGC,CAAI,EAE5DQ,OAAAA,EAAAA,YAAYF,EAAaZ,CAAM,EAExBA,CACT"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../QueryClient-N0MJmuHW.js"),q=require("../QueryController-BQA49OYU.js"),T=require("../mutation-P_Yb4LI9.js");class f extends q.QueryController{_fetch;_baseUrl;constructor(e){super(),this._fetch=e?.fetch??globalThis.fetch,this._baseUrl=e?.baseUrl}async send(e,s){return this.executeRequest(e,s)}async sendNext(e,s){const t=this.resolveFetchNext(e);if(t===void 0)throw new Error("fetchNext is not configured for this query");return this.executeRequest(e,s,t)}hasNext(e){const s=this.resolveFetchNext(e);if(s===void 0)return!1;if(s.url!==void 0&&s.url!==null)return!0;if(s.searchParams!==void 0){const t=Object.keys(s.searchParams);if(t.length===0)return!1;for(const r of t)if(s.searchParams[r]===void 0||s.searchParams[r]===null)return!1;return!0}return!1}resolveFetchNext(e){const t=(e.getFetchNext?e.getFetchNext():void 0)??e.rawFetchNext;if(t===void 0)return;const r={params:e.params??{},result:e.resultData};return{url:t.url!==void 0?i.reifyValue(t.url,r):void 0,searchParams:t.searchParams!==void 0?i.reifyValue(t.searchParams,r):void 0}}buildUrl(e,s){if(e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"))return e;if(e.startsWith("/")){const t=i.resolveBaseUrl(s)??i.resolveBaseUrl(this._baseUrl)??globalThis.location?.origin;if(!t)throw new Error(`RESTQueryController: cannot resolve URL for path "${e}". Set \`baseUrl\` on the query/mutation, pass it to \`new RESTQueryController({ baseUrl })\`, or use an absolute URL.`);return`${t}${e}`}return e}async executeRequest(e,s,t){const r=t?.url??(e.getPath?e.getPath():e.path),h=e.getMethod?e.getMethod():e.method,o=e.getSearchParams?e.getSearchParams():e.searchParams,a=t?.searchParams?{...o,...t.searchParams}:o,n=e.getBody?e.getBody():e.body,l=e.getRequestOptions?e.getRequestOptions():e.requestOptions;if(!r)throw new Error("RESTQuery requires a path. Define `path` as a field or override `getPath()`.");let u=r;if(a){const m=new URLSearchParams;for(const U in a){const d=a[U];d!=null&&m.append(U,String(d))}const v=m.toString();v&&(u+="?"+v)}const g=l?.baseUrl??e.baseUrl,c=this.buildUrl(u,g),{baseUrl:p,signal:P,...R}=l??{},S=n||e.headers?{...n?{"Content-Type":"application/json"}:void 0,...e.headers}:void 0,b=await this._fetch(c,{method:h,headers:S,body:n?JSON.stringify(n):void 0,signal:s,...R});return e.response=b,b.json()}async sendMutation(e,s){const t=e,r=t.getPath?t.getPath():t.path,h=t.getMethod?t.getMethod():t.method,o=t.getBody?t.getBody():t.body,a=t.getRequestOptions?t.getRequestOptions():t.requestOptions;if(!r)throw new Error("RESTMutation requires a path. Define `path` as a field or override `getPath()`.");const n=a?.baseUrl??t.baseUrl,l=this.buildUrl(r,n),{baseUrl:u,signal:g,...c}=a??{},p={...o!==void 0?{"Content-Type":"application/json"}:{},...t.headers};return(await this._fetch(l,{method:h,headers:p,...o!==void 0?{body:JSON.stringify(o)}:{},signal:s,...c})).json()}}class O extends i.Query{static controller=f;method="GET";path;baseUrl;searchParams;body;headers;requestOptions;fetchNext;getIdentityKey(){return`${this.method??"GET"}:${this.path??""}`}}class E extends T.Mutation{static controller=f;path;baseUrl;method="POST";body;headers;requestOptions;getIdentityKey(){return`${this.method??"POST"}:${this.path??""}`}}exports.RESTMutation=E;exports.RESTQuery=O;exports.RESTQueryController=f;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/rest/RESTQueryController.ts","../../../../src/rest/RESTQuery.ts","../../../../src/rest/RESTMutation.ts"],"sourcesContent":["import { QueryController } from '../QueryController.js';\nimport { resolveBaseUrl } from '../query-types.js';\nimport { reifyValue } from '../fieldRef.js';\nimport type { Query } from '../query.js';\nimport type { Mutation } from '../mutation.js';\nimport type { FetchNextConfig } from '../query-types.js';\nimport type { RESTQuery } from './RESTQuery.js';\nimport type { RESTMutation } from './RESTMutation.js';\nimport type { QueryRequestInit, BaseUrlValue, QueryRequestOptions } from '../types.js';\n\n// ================================\n// ResolvedFetchNext\n// ================================\n\nexport interface ResolvedFetchNext {\n url?: string;\n searchParams?: Record<string, unknown>;\n}\n\n// ================================\n// RESTQueryController options\n// ================================\n\nexport interface RESTQueryControllerOptions {\n fetch?: (url: string, init?: QueryRequestInit) => Promise<Response>;\n baseUrl?: BaseUrlValue;\n}\n\n// ================================\n// RESTQueryController\n// ================================\n\nexport class RESTQueryController extends QueryController {\n private readonly _fetch: (url: string, init?: QueryRequestInit) => Promise<Response>;\n private readonly _baseUrl: BaseUrlValue | undefined;\n\n constructor(options?: RESTQueryControllerOptions) {\n super();\n this._fetch =\n options?.fetch ?? (globalThis.fetch as unknown as (url: string, init?: QueryRequestInit) => Promise<Response>);\n this._baseUrl = options?.baseUrl;\n }\n\n override async send(ctx: Query, signal: AbortSignal): Promise<unknown> {\n return this.executeRequest(ctx as RESTQuery, signal);\n }\n\n override async sendNext(ctx: Query, signal: AbortSignal): Promise<unknown> {\n const resolved = this.resolveFetchNext(ctx as RESTQuery);\n if (resolved === undefined) {\n throw new Error('fetchNext is not configured for this query');\n }\n return this.executeRequest(ctx as RESTQuery, signal, resolved);\n }\n\n override hasNext(ctx: Query): boolean {\n const resolved = this.resolveFetchNext(ctx as RESTQuery);\n if (resolved === undefined) return false;\n\n if (resolved.url !== undefined && resolved.url !== null) {\n return true;\n }\n\n if (resolved.searchParams !== undefined) {\n const keys = Object.keys(resolved.searchParams);\n if (keys.length === 0) return false;\n for (const key of keys) {\n if (resolved.searchParams[key] === undefined || resolved.searchParams[key] === null) {\n return false;\n }\n }\n return true;\n }\n\n return false;\n }\n\n private resolveFetchNext(ctx: RESTQuery): ResolvedFetchNext | undefined {\n const dynamicConfig = ctx.getFetchNext ? ctx.getFetchNext() : undefined;\n const fetchNextConfig: FetchNextConfig | undefined = dynamicConfig ?? ctx.rawFetchNext;\n if (fetchNextConfig === undefined) return undefined;\n\n const resolveRoot: Record<string, unknown> = {\n params: ctx.params ?? {},\n result: ctx.resultData,\n };\n\n return {\n url: fetchNextConfig.url !== undefined ? (reifyValue(fetchNextConfig.url, resolveRoot) as string) : undefined,\n searchParams:\n fetchNextConfig.searchParams !== undefined\n ? (reifyValue(fetchNextConfig.searchParams, resolveRoot) as Record<string, unknown>)\n : undefined,\n };\n }\n\n /**\n * Resolves a path to a full URL.\n *\n * - Absolute URLs (`https://...`, `//...`) are returned as-is.\n * - Root-relative paths (`/foo`) are prepended with the resolved baseUrl.\n * The baseUrl priority is: per-query/mutation > controller-level > `location.origin`.\n * If none is available and the path is root-relative, an error is thrown.\n * - Other paths (e.g. `example.com/foo`) are returned as-is.\n */\n private buildUrl(path: string, ctxBaseUrl: BaseUrlValue | undefined): string {\n // Absolute URL — use as-is regardless of any configured baseUrl\n if (path.startsWith('http://') || path.startsWith('https://') || path.startsWith('//')) {\n return path;\n }\n\n // Root-relative path — needs a base\n if (path.startsWith('/')) {\n const base = resolveBaseUrl(ctxBaseUrl) ?? resolveBaseUrl(this._baseUrl) ?? globalThis.location?.origin;\n\n if (!base) {\n throw new Error(\n `RESTQueryController: cannot resolve URL for path \"${path}\". ` +\n `Set \\`baseUrl\\` on the query/mutation, pass it to \\`new RESTQueryController({ baseUrl })\\`, ` +\n `or use an absolute URL.`,\n );\n }\n\n return `${base}${path}`;\n }\n\n // Relative path — use as-is\n return path;\n }\n\n private async executeRequest(\n ctx: RESTQuery,\n signal: AbortSignal,\n next?: { url?: string; searchParams?: Record<string, unknown> },\n ): Promise<unknown> {\n const path = next?.url ?? (ctx.getPath ? ctx.getPath() : ctx.path);\n const method = ctx.getMethod ? ctx.getMethod() : ctx.method;\n const baseSearchParams = ctx.getSearchParams ? ctx.getSearchParams() : ctx.searchParams;\n const searchParams = next?.searchParams ? { ...baseSearchParams, ...next.searchParams } : baseSearchParams;\n const body = ctx.getBody ? ctx.getBody() : ctx.body;\n const requestOptions = ctx.getRequestOptions ? ctx.getRequestOptions() : ctx.requestOptions;\n\n if (!path) {\n throw new Error('RESTQuery requires a path. Define `path` as a field or override `getPath()`.');\n }\n\n let url = path;\n\n if (searchParams) {\n const sp = new URLSearchParams();\n for (const key in searchParams) {\n const val = searchParams[key];\n if (val !== undefined && val !== null) {\n sp.append(key, String(val));\n }\n }\n const qs = sp.toString();\n if (qs) {\n url += '?' + qs;\n }\n }\n\n const ctxBaseUrl = requestOptions?.baseUrl ?? ctx.baseUrl;\n const fullUrl = this.buildUrl(url, ctxBaseUrl);\n\n const { baseUrl: _baseUrl, signal: _signal, ...fetchOptions } = requestOptions ?? ({} as Record<string, unknown>);\n\n const hasHeaders = body || ctx.headers;\n const headers: HeadersInit | undefined = hasHeaders\n ? {\n ...(body ? { 'Content-Type': 'application/json' } : undefined),\n ...(ctx.headers as Record<string, string>),\n }\n : undefined;\n\n const fetchResponse = await this._fetch(fullUrl, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal,\n ...fetchOptions,\n });\n\n ctx.response = fetchResponse as unknown as Response;\n\n return fetchResponse.json();\n }\n\n override async sendMutation(ctx: Mutation, signal: AbortSignal): Promise<unknown> {\n const restCtx = ctx as RESTMutation;\n const path = restCtx.getPath ? restCtx.getPath() : restCtx.path;\n const method = restCtx.getMethod ? restCtx.getMethod() : restCtx.method;\n const body = restCtx.getBody ? restCtx.getBody() : restCtx.body;\n const requestOptions = restCtx.getRequestOptions ? restCtx.getRequestOptions() : restCtx.requestOptions;\n\n if (!path) {\n throw new Error('RESTMutation requires a path. Define `path` as a field or override `getPath()`.');\n }\n\n const ctxBaseUrl = (requestOptions as QueryRequestOptions | undefined)?.baseUrl ?? restCtx.baseUrl;\n const fullUrl = this.buildUrl(path, ctxBaseUrl);\n\n const { baseUrl: _baseUrl, signal: _signal, ...fetchOptions } = (requestOptions ?? {}) as Record<string, unknown>;\n\n const headers: HeadersInit = {\n ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...(restCtx.headers as Record<string, string>),\n };\n\n const fetchResponse = await this._fetch(fullUrl, {\n method,\n headers,\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n signal,\n ...fetchOptions,\n });\n\n return fetchResponse.json();\n }\n}\n","import { Query } from '../query.js';\nimport { RESTQueryController } from './RESTQueryController.js';\nimport type { FetchNextConfig } from '../query-types.js';\nimport type { BaseUrlValue, QueryRequestOptions } from '../types.js';\n\n// ================================\n// RESTQuery — declarative HTTP query definition\n// ================================\n\nexport abstract class RESTQuery extends Query {\n static override controller = RESTQueryController;\n\n method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' = 'GET';\n path?: string;\n baseUrl?: BaseUrlValue;\n searchParams?: Record<string, unknown>;\n body?: Record<string, unknown>;\n headers?: HeadersInit;\n requestOptions?: QueryRequestOptions;\n fetchNext?: FetchNextConfig;\n\n declare response: Response | undefined;\n\n getIdentityKey(): string {\n return `${this.method ?? 'GET'}:${this.path ?? ''}`;\n }\n\n // User-overridable getters — the controller reads these from the execution context\n getPath?(): string | undefined;\n getMethod?(): string;\n getSearchParams?(): Record<string, unknown> | undefined;\n getBody?(): Record<string, unknown> | undefined;\n getRequestOptions?(): QueryRequestOptions | undefined;\n getFetchNext?(): FetchNextConfig | undefined;\n}\n","import { Mutation } from '../mutation.js';\nimport type { BaseUrlValue, QueryRequestOptions } from '../types.js';\nimport { RESTQueryController } from './RESTQueryController.js';\n\nexport abstract class RESTMutation extends Mutation {\n static override controller = RESTQueryController;\n\n path?: string;\n baseUrl?: BaseUrlValue;\n method: 'POST' | 'PUT' | 'DELETE' | 'PATCH' = 'POST';\n body?: Record<string, unknown>;\n headers?: HeadersInit;\n requestOptions?: QueryRequestOptions;\n\n getIdentityKey(): string {\n return `${this.method ?? 'POST'}:${this.path ?? ''}`;\n }\n\n getPath?(): string | undefined;\n getMethod?(): string;\n getBody?(): Record<string, unknown> | undefined;\n getRequestOptions?(): QueryRequestOptions | undefined;\n}\n"],"names":["RESTQueryController","QueryController","options","ctx","signal","resolved","keys","key","fetchNextConfig","resolveRoot","reifyValue","path","ctxBaseUrl","base","resolveBaseUrl","next","method","baseSearchParams","searchParams","body","requestOptions","url","sp","val","qs","fullUrl","_baseUrl","_signal","fetchOptions","headers","fetchResponse","restCtx","RESTQuery","Query","RESTMutation","Mutation"],"mappings":"+MAgCO,MAAMA,UAA4BC,EAAAA,eAAgB,CACtC,OACA,SAEjB,YAAYC,EAAsC,CAChD,MAAA,EACA,KAAK,OACHA,GAAS,OAAU,WAAW,MAChC,KAAK,SAAWA,GAAS,OAC3B,CAEA,MAAe,KAAKC,EAAYC,EAAuC,CACrE,OAAO,KAAK,eAAeD,EAAkBC,CAAM,CACrD,CAEA,MAAe,SAASD,EAAYC,EAAuC,CACzE,MAAMC,EAAW,KAAK,iBAAiBF,CAAgB,EACvD,GAAIE,IAAa,OACf,MAAM,IAAI,MAAM,4CAA4C,EAE9D,OAAO,KAAK,eAAeF,EAAkBC,EAAQC,CAAQ,CAC/D,CAES,QAAQF,EAAqB,CACpC,MAAME,EAAW,KAAK,iBAAiBF,CAAgB,EACvD,GAAIE,IAAa,OAAW,MAAO,GAEnC,GAAIA,EAAS,MAAQ,QAAaA,EAAS,MAAQ,KACjD,MAAO,GAGT,GAAIA,EAAS,eAAiB,OAAW,CACvC,MAAMC,EAAO,OAAO,KAAKD,EAAS,YAAY,EAC9C,GAAIC,EAAK,SAAW,EAAG,MAAO,GAC9B,UAAWC,KAAOD,EAChB,GAAID,EAAS,aAAaE,CAAG,IAAM,QAAaF,EAAS,aAAaE,CAAG,IAAM,KAC7E,MAAO,GAGX,MAAO,EACT,CAEA,MAAO,EACT,CAEQ,iBAAiBJ,EAA+C,CAEtE,MAAMK,GADgBL,EAAI,aAAeA,EAAI,eAAiB,SACQA,EAAI,aAC1E,GAAIK,IAAoB,OAAW,OAEnC,MAAMC,EAAuC,CAC3C,OAAQN,EAAI,QAAU,CAAA,EACtB,OAAQA,EAAI,UAAA,EAGd,MAAO,CACL,IAAKK,EAAgB,MAAQ,OAAaE,EAAAA,WAAWF,EAAgB,IAAKC,CAAW,EAAe,OACpG,aACED,EAAgB,eAAiB,OAC5BE,EAAAA,WAAWF,EAAgB,aAAcC,CAAW,EACrD,MAAA,CAEV,CAWQ,SAASE,EAAcC,EAA8C,CAE3E,GAAID,EAAK,WAAW,SAAS,GAAKA,EAAK,WAAW,UAAU,GAAKA,EAAK,WAAW,IAAI,EACnF,OAAOA,EAIT,GAAIA,EAAK,WAAW,GAAG,EAAG,CACxB,MAAME,EAAOC,iBAAeF,CAAU,GAAKE,EAAAA,eAAe,KAAK,QAAQ,GAAK,WAAW,UAAU,OAEjG,GAAI,CAACD,EACH,MAAM,IAAI,MACR,qDAAqDF,CAAI,wHAAA,EAM7D,MAAO,GAAGE,CAAI,GAAGF,CAAI,EACvB,CAGA,OAAOA,CACT,CAEA,MAAc,eACZR,EACAC,EACAW,EACkB,CAClB,MAAMJ,EAAOI,GAAM,MAAQZ,EAAI,QAAUA,EAAI,QAAA,EAAYA,EAAI,MACvDa,EAASb,EAAI,UAAYA,EAAI,UAAA,EAAcA,EAAI,OAC/Cc,EAAmBd,EAAI,gBAAkBA,EAAI,gBAAA,EAAoBA,EAAI,aACrEe,EAAeH,GAAM,aAAe,CAAE,GAAGE,EAAkB,GAAGF,EAAK,YAAA,EAAiBE,EACpFE,EAAOhB,EAAI,QAAUA,EAAI,QAAA,EAAYA,EAAI,KACzCiB,EAAiBjB,EAAI,kBAAoBA,EAAI,kBAAA,EAAsBA,EAAI,eAE7E,GAAI,CAACQ,EACH,MAAM,IAAI,MAAM,8EAA8E,EAGhG,IAAIU,EAAMV,EAEV,GAAIO,EAAc,CAChB,MAAMI,EAAK,IAAI,gBACf,UAAWf,KAAOW,EAAc,CAC9B,MAAMK,EAAML,EAAaX,CAAG,EACHgB,GAAQ,MAC/BD,EAAG,OAAOf,EAAK,OAAOgB,CAAG,CAAC,CAE9B,CACA,MAAMC,EAAKF,EAAG,SAAA,EACVE,IACFH,GAAO,IAAMG,EAEjB,CAEA,MAAMZ,EAAaQ,GAAgB,SAAWjB,EAAI,QAC5CsB,EAAU,KAAK,SAASJ,EAAKT,CAAU,EAEvC,CAAE,QAASc,EAAU,OAAQC,EAAS,GAAGC,CAAA,EAAiBR,GAAmB,CAAA,EAG7ES,EADaV,GAAQhB,EAAI,QAE3B,CACE,GAAIgB,EAAO,CAAE,eAAgB,oBAAuB,OACpD,GAAIhB,EAAI,OAAA,EAEV,OAEE2B,EAAgB,MAAM,KAAK,OAAOL,EAAS,CAC/C,OAAAT,EACA,QAAAa,EACA,KAAMV,EAAO,KAAK,UAAUA,CAAI,EAAI,OACpC,OAAAf,EACA,GAAGwB,CAAA,CACJ,EAED,OAAAzB,EAAI,SAAW2B,EAERA,EAAc,KAAA,CACvB,CAEA,MAAe,aAAa3B,EAAeC,EAAuC,CAChF,MAAM2B,EAAU5B,EACVQ,EAAOoB,EAAQ,QAAUA,EAAQ,QAAA,EAAYA,EAAQ,KACrDf,EAASe,EAAQ,UAAYA,EAAQ,UAAA,EAAcA,EAAQ,OAC3DZ,EAAOY,EAAQ,QAAUA,EAAQ,QAAA,EAAYA,EAAQ,KACrDX,EAAiBW,EAAQ,kBAAoBA,EAAQ,kBAAA,EAAsBA,EAAQ,eAEzF,GAAI,CAACpB,EACH,MAAM,IAAI,MAAM,iFAAiF,EAGnG,MAAMC,EAAcQ,GAAoD,SAAWW,EAAQ,QACrFN,EAAU,KAAK,SAASd,EAAMC,CAAU,EAExC,CAAE,QAASc,EAAU,OAAQC,EAAS,GAAGC,CAAA,EAAkBR,GAAkB,CAAA,EAE7ES,EAAuB,CAC3B,GAAIV,IAAS,OAAY,CAAE,eAAgB,kBAAA,EAAuB,CAAA,EAClE,GAAIY,EAAQ,OAAA,EAWd,OARsB,MAAM,KAAK,OAAON,EAAS,CAC/C,OAAAT,EACA,QAAAa,EACA,GAAIV,IAAS,OAAY,CAAE,KAAM,KAAK,UAAUA,CAAI,CAAA,EAAM,CAAA,EAC1D,OAAAf,EACA,GAAGwB,CAAA,CACJ,GAEoB,KAAA,CACvB,CACF,CClNO,MAAeI,UAAkBC,EAAAA,KAAM,CAC5C,OAAgB,WAAajC,EAE7B,OAAsD,MACtD,KACA,QACA,aACA,KACA,QACA,eACA,UAIA,gBAAyB,CACvB,MAAO,GAAG,KAAK,QAAU,KAAK,IAAI,KAAK,MAAQ,EAAE,EACnD,CASF,CC9BO,MAAekC,UAAqBC,EAAAA,QAAS,CAClD,OAAgB,WAAanC,EAE7B,KACA,QACA,OAA8C,OAC9C,KACA,QACA,eAEA,gBAAyB,CACvB,MAAO,GAAG,KAAK,QAAU,MAAM,IAAI,KAAK,MAAQ,EAAE,EACpD,CAMF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const o=e=>`sq:doc:value:${e}`,s=e=>`sq:doc:refCount:${e}`,c=e=>`sq:doc:refIds:${e}`,t=e=>`sq:doc:updatedAt:${e}`,F=e=>`sq:doc:queue:${e}`,T=e=>`sq:doc:lastUsed:${e}`,E=e=>`sq:doc:cacheTime:${e}`,_="sq:doc:lastUsed:";exports.DEFAULT_CACHE_TIME=1440;exports.DEFAULT_GC_TIME=5;exports.DEFAULT_MAX_COUNT=50;exports.LAST_USED_PREFIX=_;exports.cacheTimeKeyFor=E;exports.lastUsedKeyFor=T;exports.queueKeyFor=F;exports.refCountKeyFor=s;exports.refIdsKeyFor=c;exports.updatedAtKeyFor=t;exports.valueKeyFor=o;
|
|
2
|
+
//# sourceMappingURL=shared-Ct5zKrt4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-Ct5zKrt4.js","sources":["../../../src/stores/shared.ts"],"sourcesContent":["// Query Instance keys\nexport const valueKeyFor = (id: number) => `sq:doc:value:${id}`;\nexport const refCountKeyFor = (id: number) => `sq:doc:refCount:${id}`;\nexport const refIdsKeyFor = (id: number) => `sq:doc:refIds:${id}`;\nexport const updatedAtKeyFor = (id: number) => `sq:doc:updatedAt:${id}`;\n// Query Type keys\nexport const queueKeyFor = (queryDefId: string) => `sq:doc:queue:${queryDefId}`;\n// Query Type metadata keys (used for stale cache cleanup)\nexport const lastUsedKeyFor = (queryDefId: string) => `sq:doc:lastUsed:${queryDefId}`;\nexport const cacheTimeKeyFor = (queryDefId: string) => `sq:doc:cacheTime:${queryDefId}`;\n\nexport const LAST_USED_PREFIX = 'sq:doc:lastUsed:';\n\n// Default values\nexport const DEFAULT_MAX_COUNT = 50;\nexport const DEFAULT_CACHE_TIME = 60 * 24; // 24 hours in minutes\nexport const DEFAULT_GC_TIME = 5; // 5 minutes - in-memory eviction default\n"],"names":["valueKeyFor","id","refCountKeyFor","refIdsKeyFor","updatedAtKeyFor","queueKeyFor","queryDefId","lastUsedKeyFor","cacheTimeKeyFor","LAST_USED_PREFIX"],"mappings":"aACO,MAAMA,EAAeC,GAAe,gBAAgBA,CAAE,GAChDC,EAAkBD,GAAe,mBAAmBA,CAAE,GACtDE,EAAgBF,GAAe,iBAAiBA,CAAE,GAClDG,EAAmBH,GAAe,oBAAoBA,CAAE,GAExDI,EAAeC,GAAuB,gBAAgBA,CAAU,GAEhEC,EAAkBD,GAAuB,mBAAmBA,CAAU,GACtEE,EAAmBF,GAAuB,oBAAoBA,CAAU,GAExEG,EAAmB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../shared-Ct5zKrt4.js");class d{isWriter;delegate;sendMessage;messageQueue=[];queues=new Map;queueProcessorPromise;resolveQueueWait;constructor(e){this.isWriter=e.isWriter,this.delegate=e.delegate;const{sendMessage:t}=e.connect(this.handleMessage.bind(this));if(this.sendMessage=t,this.isWriter){if(!this.delegate)throw new Error("Writer must have a delegate");this.startQueueProcessor()}}handleMessage(e){this.isWriter&&this.enqueueMessage(e)}enqueueMessage(e){this.messageQueue.push(e),this.resolveQueueWait&&(this.resolveQueueWait(),this.resolveQueueWait=void 0)}dispatch(e){this.isWriter?this.enqueueMessage(e):this.sendMessage(e)}startQueueProcessor(){this.queueProcessorPromise=this.processQueue()}async processQueue(){for(;;){for(;this.messageQueue.length===0;)await new Promise(t=>{this.resolveQueueWait=t});const e=this.messageQueue.shift();try{await this.processMessage(e)}catch(t){console.error("Error processing message:",t)}}}async processMessage(e){switch(e.type){case 0:await this.writerSaveQuery(e.queryDefId,e.queryKey,e.value,e.updatedAt,e.cacheTime,e.refIds);break;case 1:await this.writerSaveEntity(e.entityKey,e.value,e.refIds);break;case 2:await this.writerActivateQuery(e.queryDefId,e.queryKey,e.cacheTime);break;case 3:await this.writerDeleteValue(e.queryKey);break}}async loadQuery(e,t){if(!this.delegate)return;const s=await this.delegate.getNumber(r.updatedAtKeyFor(t)),a=(e.statics.cache?.cacheTime??r.DEFAULT_CACHE_TIME)*60*1e3;if(s===void 0||s<Date.now()-a)return;const i=await this.delegate.getString(r.valueKeyFor(t));if(i===void 0)return;const o=await this.delegate.getBuffer(r.refIdsKeyFor(t));let n;return o!==void 0&&(n=new Map,await this.preloadEntities(o,n)),this.activateQuery(e,t),{value:JSON.parse(i),refIds:o===void 0?void 0:new Set(o??[]),updatedAt:s,preloadedEntities:n}}async preloadEntities(e,t){if(this.delegate)for(const s of e){const a=await this.delegate.getString(r.valueKeyFor(s));if(a===void 0)continue;t.set(s,JSON.parse(a));const i=await this.delegate.getBuffer(r.refIdsKeyFor(s));i!==void 0&&await this.preloadEntities(i,t)}}saveQuery(e,t,s,a,i){const o={type:0,queryDefId:e.statics.id,queryKey:t,value:s,updatedAt:a,cacheTime:e.statics.cache?.cacheTime??r.DEFAULT_CACHE_TIME,refIds:i?Array.from(i):void 0};this.dispatch(o)}saveEntity(e,t,s){const a={type:1,entityKey:e,value:t,refIds:s?Array.from(s):void 0};this.dispatch(a)}activateQuery(e,t){const s={type:2,queryDefId:e.statics.id,queryKey:t,cacheTime:e.statics.cache?.cacheTime??r.DEFAULT_CACHE_TIME};this.dispatch(s)}deleteQuery(e){const t={type:3,queryKey:e};this.dispatch(t)}async writerSaveQuery(e,t,s,a,i,o){await this.setValue(t,s,o?new Set(o):void 0),await this.delegate.setNumber(r.updatedAtKeyFor(t),a),await this.writerActivateQuery(e,t,i)}async writerSaveEntity(e,t,s){await this.setValue(e,t,s?new Set(s):void 0)}async writerActivateQuery(e,t,s){if(!await this.delegate.has(r.valueKeyFor(t)))return;const a=r.queueKeyFor(e);let i=this.queues.get(e);if(i===void 0){const u=r.DEFAULT_MAX_COUNT;i=await this.delegate.getBuffer(a),i===void 0?(i=new Uint32Array(u),await this.delegate.setBuffer(a,i)):i.length!==u&&(i=new Uint32Array(i.buffer,0,u),await this.delegate.setBuffer(a,i)),this.queues.set(e,i)}await this.delegate.setNumber(r.lastUsedKeyFor(e),Date.now()),await this.delegate.setNumber(r.cacheTimeKeyFor(e),s);const o=i.indexOf(t);if(o>=0){if(o===0)return;i.copyWithin(1,0,o),i[0]=t;return}const n=i[i.length-1];i.copyWithin(1,0,i.length-1),i[0]=t,n!==0&&(await this.writerDeleteValue(n),await this.delegate.delete(r.updatedAtKeyFor(n)))}async purgeStaleQueries(){if(!this.delegate)return;const e=await this.delegate.getAllKeys(),t=Date.now();for(const s of e){if(!s.startsWith(r.LAST_USED_PREFIX))continue;const a=s.slice(r.LAST_USED_PREFIX.length),i=await this.delegate.getNumber(s),n=(await this.delegate.getNumber(r.cacheTimeKeyFor(a))??r.DEFAULT_CACHE_TIME)*60*1e3;if(i===void 0||t-i>n){const u=await this.delegate.getBuffer(r.queueKeyFor(a));if(u!==void 0)for(const c of u)c!==0&&(await this.writerDeleteValue(c),await this.delegate.delete(r.updatedAtKeyFor(c)));await this.delegate.delete(r.queueKeyFor(a)),await this.delegate.delete(s),await this.delegate.delete(r.cacheTimeKeyFor(a)),this.queues.delete(a)}}}async setValue(e,t,s){const a=this.delegate;await a.setString(r.valueKeyFor(e),JSON.stringify(t));const i=r.refIdsKeyFor(e),o=await a.getBuffer(i);if(s===void 0||s.size===0){if(await a.delete(i),o!==void 0)for(let n=0;n<o.length;n++){const u=o[n];await this.decrementRefCount(u)}}else{const n=new Uint32Array([...s]);if(o!==void 0)for(let u=0;u<o.length;u++){const c=o[u];s.has(c)?s.delete(c):await this.decrementRefCount(c)}for(const u of s)await this.incrementRefCount(u);await a.setBuffer(i,n)}}async writerDeleteValue(e){const t=this.delegate,s=r.refIdsKeyFor(e);await t.delete(r.valueKeyFor(e)),await t.delete(r.refCountKeyFor(e));const a=await t.getBuffer(s);if(await t.delete(s),a!==void 0)for(const i of a)i!==0&&await this.decrementRefCount(i)}async incrementRefCount(e){const t=this.delegate,s=r.refCountKeyFor(e),i=(await t.getNumber(s)??0)+1;await t.setNumber(s,i)}async decrementRefCount(e){const t=this.delegate,s=r.refCountKeyFor(e),a=await t.getNumber(s);if(a===void 0)return;const i=a-1;i===0?await this.writerDeleteValue(e):await t.setNumber(s,i)}}exports.AsyncQueryStore=d;
|
|
2
|
+
//# sourceMappingURL=async.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async.js","sources":["../../../../src/stores/async.ts"],"sourcesContent":["import { QueryDefinition } from '../query.js';\nimport { CachedQuery, QueryStore, type PreloadedEntityMap } from '../QueryClient.js';\nimport {\n cacheTimeKeyFor,\n DEFAULT_CACHE_TIME,\n DEFAULT_MAX_COUNT,\n LAST_USED_PREFIX,\n lastUsedKeyFor,\n queueKeyFor,\n refCountKeyFor,\n refIdsKeyFor,\n updatedAtKeyFor,\n valueKeyFor,\n} from './shared.js';\n\n// -----------------------------------------------------------------------------\n// Async QueryStore Interfaces\n// -----------------------------------------------------------------------------\n\nexport interface AsyncPersistentStore {\n has(key: string): Promise<boolean>;\n\n getString(key: string): Promise<string | undefined>;\n setString(key: string, value: string): Promise<void>;\n\n getNumber(key: string): Promise<number | undefined>;\n setNumber(key: string, value: number): Promise<void>;\n\n getBuffer(key: string): Promise<Uint32Array | undefined>;\n setBuffer(key: string, value: Uint32Array): Promise<void>;\n\n delete(key: string): Promise<void>;\n\n getAllKeys(): Promise<string[]>;\n}\n\nconst enum StoreMessageType {\n SaveQuery = 0,\n SaveEntity = 1,\n ActivateQuery = 2,\n DeleteQuery = 3,\n}\n\nexport type StoreMessage =\n | {\n type: StoreMessageType.SaveQuery;\n queryDefId: string;\n queryKey: number;\n value: unknown;\n updatedAt: number;\n cacheTime: number;\n refIds?: number[];\n }\n | { type: StoreMessageType.SaveEntity; entityKey: number; value: unknown; refIds?: number[] }\n | { type: StoreMessageType.ActivateQuery; queryDefId: string; queryKey: number; cacheTime: number }\n | { type: StoreMessageType.DeleteQuery; queryKey: number };\n\nexport interface AsyncQueryStoreConfig {\n isWriter: boolean;\n connect: (handleMessage: (msg: StoreMessage) => void) => {\n sendMessage: (msg: StoreMessage) => void;\n };\n delegate?: AsyncPersistentStore; // Only provided for writer\n}\n// -----------------------------------------------------------------------------\n// Async QueryStore Implementation\n// -----------------------------------------------------------------------------\n\nexport class AsyncQueryStore implements QueryStore {\n private readonly isWriter: boolean;\n private readonly delegate?: AsyncPersistentStore;\n private readonly sendMessage: (msg: StoreMessage) => void;\n private readonly messageQueue: StoreMessage[] = [];\n private readonly queues: Map<string, Uint32Array> = new Map();\n private queueProcessorPromise?: Promise<void>;\n private resolveQueueWait?: () => void;\n\n constructor(config: AsyncQueryStoreConfig) {\n this.isWriter = config.isWriter;\n this.delegate = config.delegate;\n\n // Connect and get sendMessage function\n const { sendMessage } = config.connect(this.handleMessage.bind(this));\n this.sendMessage = sendMessage;\n\n // Start queue processor if this is a writer\n if (this.isWriter) {\n if (!this.delegate) {\n throw new Error('Writer must have a delegate');\n }\n this.startQueueProcessor();\n }\n }\n\n private handleMessage(msg: StoreMessage): void {\n if (this.isWriter) {\n // Enqueue the message for serial processing\n this.enqueueMessage(msg);\n }\n // Readers don't handle incoming messages\n }\n\n private enqueueMessage(msg: StoreMessage): void {\n this.messageQueue.push(msg);\n // Wake up the queue processor if it's waiting\n if (this.resolveQueueWait) {\n this.resolveQueueWait();\n this.resolveQueueWait = undefined;\n }\n }\n\n private dispatch(msg: StoreMessage): void {\n if (this.isWriter) {\n this.enqueueMessage(msg);\n } else {\n this.sendMessage(msg);\n }\n }\n\n private startQueueProcessor(): void {\n this.queueProcessorPromise = this.processQueue();\n }\n\n private async processQueue(): Promise<void> {\n while (true) {\n // Wait for messages if queue is empty\n while (this.messageQueue.length === 0) {\n await new Promise<void>(resolve => {\n this.resolveQueueWait = resolve;\n });\n }\n\n // Process one message at a time\n const msg = this.messageQueue.shift()!;\n\n try {\n await this.processMessage(msg);\n } catch (error) {\n console.error('Error processing message:', error);\n }\n }\n }\n\n private async processMessage(msg: StoreMessage): Promise<void> {\n switch (msg.type) {\n case StoreMessageType.SaveQuery:\n await this.writerSaveQuery(msg.queryDefId, msg.queryKey, msg.value, msg.updatedAt, msg.cacheTime, msg.refIds);\n break;\n case StoreMessageType.SaveEntity:\n await this.writerSaveEntity(msg.entityKey, msg.value, msg.refIds);\n break;\n case StoreMessageType.ActivateQuery:\n await this.writerActivateQuery(msg.queryDefId, msg.queryKey, msg.cacheTime);\n break;\n case StoreMessageType.DeleteQuery:\n await this.writerDeleteValue(msg.queryKey);\n break;\n }\n }\n\n async loadQuery(queryDef: QueryDefinition<any, any, any>, queryKey: number): Promise<CachedQuery | undefined> {\n if (!this.delegate) {\n return undefined;\n }\n\n const updatedAt = await this.delegate.getNumber(updatedAtKeyFor(queryKey));\n\n const cacheTimeMs = (queryDef.statics.cache?.cacheTime ?? DEFAULT_CACHE_TIME) * 60 * 1000;\n if (updatedAt === undefined || updatedAt < Date.now() - cacheTimeMs) {\n return undefined;\n }\n\n const valueStr = await this.delegate.getString(valueKeyFor(queryKey));\n\n if (valueStr === undefined) {\n return undefined;\n }\n\n const entityIds = await this.delegate.getBuffer(refIdsKeyFor(queryKey));\n\n let preloadedEntities: PreloadedEntityMap | undefined;\n if (entityIds !== undefined) {\n preloadedEntities = new Map();\n await this.preloadEntities(entityIds, preloadedEntities);\n }\n\n this.activateQuery(queryDef, queryKey);\n\n return {\n value: JSON.parse(valueStr) as Record<string, unknown>,\n refIds: entityIds === undefined ? undefined : new Set(entityIds ?? []),\n updatedAt,\n preloadedEntities,\n };\n }\n\n private async preloadEntities(entityIds: Uint32Array, preloaded: PreloadedEntityMap): Promise<void> {\n if (!this.delegate) {\n return;\n }\n\n for (const entityId of entityIds) {\n const entityValue = await this.delegate.getString(valueKeyFor(entityId));\n\n if (entityValue === undefined) {\n continue;\n }\n\n preloaded.set(entityId, JSON.parse(entityValue) as Record<string, unknown>);\n\n const childIds = await this.delegate.getBuffer(refIdsKeyFor(entityId));\n\n if (childIds === undefined) {\n continue;\n }\n\n await this.preloadEntities(childIds, preloaded);\n }\n }\n\n saveQuery(\n queryDef: QueryDefinition<any, any, any>,\n queryKey: number,\n value: unknown,\n updatedAt: number,\n refIds?: Set<number>,\n ): void {\n const message: StoreMessage = {\n type: StoreMessageType.SaveQuery,\n queryDefId: queryDef.statics.id,\n queryKey,\n value,\n updatedAt,\n cacheTime: queryDef.statics.cache?.cacheTime ?? DEFAULT_CACHE_TIME,\n refIds: refIds ? Array.from(refIds) : undefined,\n };\n\n this.dispatch(message);\n }\n\n saveEntity(entityKey: number, value: unknown, refIds?: Set<number>): void {\n const message: StoreMessage = {\n type: StoreMessageType.SaveEntity,\n entityKey,\n value,\n refIds: refIds ? Array.from(refIds) : undefined,\n };\n\n this.dispatch(message);\n }\n\n activateQuery(queryDef: QueryDefinition<any, any, any>, queryKey: number): void {\n const message: StoreMessage = {\n type: StoreMessageType.ActivateQuery,\n queryDefId: queryDef.statics.id,\n queryKey,\n cacheTime: queryDef.statics.cache?.cacheTime ?? DEFAULT_CACHE_TIME,\n };\n\n this.dispatch(message);\n }\n\n deleteQuery(queryKey: number): void {\n const message: StoreMessage = {\n type: StoreMessageType.DeleteQuery,\n queryKey,\n };\n\n this.dispatch(message);\n }\n\n // Writer-specific methods below\n\n private async writerSaveQuery(\n queryDefId: string,\n queryKey: number,\n value: unknown,\n updatedAt: number,\n cacheTime: number,\n refIds?: number[],\n ): Promise<void> {\n await this.setValue(queryKey, value, refIds ? new Set(refIds) : undefined);\n await this.delegate!.setNumber(updatedAtKeyFor(queryKey), updatedAt);\n await this.writerActivateQuery(queryDefId, queryKey, cacheTime);\n }\n\n private async writerSaveEntity(entityKey: number, value: unknown, refIds?: number[]): Promise<void> {\n await this.setValue(entityKey, value, refIds ? new Set(refIds) : undefined);\n }\n\n private async writerActivateQuery(queryDefId: string, queryKey: number, cacheTime: number): Promise<void> {\n if (!(await this.delegate!.has(valueKeyFor(queryKey)))) {\n return;\n }\n\n const queueKey = queueKeyFor(queryDefId);\n let queue = this.queues.get(queryDefId);\n\n if (queue === undefined) {\n const maxCount = DEFAULT_MAX_COUNT;\n queue = await this.delegate!.getBuffer(queueKey);\n\n if (queue === undefined) {\n queue = new Uint32Array(maxCount);\n await this.delegate!.setBuffer(queueKey, queue);\n } else if (queue.length !== maxCount) {\n queue = new Uint32Array(queue.buffer, 0, maxCount);\n await this.delegate!.setBuffer(queueKey, queue);\n }\n\n this.queues.set(queryDefId, queue);\n }\n\n await this.delegate!.setNumber(lastUsedKeyFor(queryDefId), Date.now());\n await this.delegate!.setNumber(cacheTimeKeyFor(queryDefId), cacheTime);\n\n const indexOfKey = queue.indexOf(queryKey);\n\n if (indexOfKey >= 0) {\n if (indexOfKey === 0) {\n return;\n }\n queue.copyWithin(1, 0, indexOfKey);\n queue[0] = queryKey;\n return;\n }\n\n const evicted = queue[queue.length - 1];\n queue.copyWithin(1, 0, queue.length - 1);\n queue[0] = queryKey;\n\n if (evicted !== 0) {\n await this.writerDeleteValue(evicted);\n await this.delegate!.delete(updatedAtKeyFor(evicted));\n }\n }\n\n async purgeStaleQueries(): Promise<void> {\n if (!this.delegate) return;\n\n const allKeys = await this.delegate.getAllKeys();\n const now = Date.now();\n\n for (const key of allKeys) {\n if (!key.startsWith(LAST_USED_PREFIX)) continue;\n\n const queryDefId = key.slice(LAST_USED_PREFIX.length);\n const lastUsedAt = await this.delegate.getNumber(key);\n const cacheTime = (await this.delegate.getNumber(cacheTimeKeyFor(queryDefId))) ?? DEFAULT_CACHE_TIME;\n const cacheTimeMs = cacheTime * 60 * 1000;\n\n if (lastUsedAt === undefined || now - lastUsedAt > cacheTimeMs) {\n const queue = await this.delegate.getBuffer(queueKeyFor(queryDefId));\n\n if (queue !== undefined) {\n for (const queryKey of queue) {\n if (queryKey !== 0) {\n await this.writerDeleteValue(queryKey);\n await this.delegate.delete(updatedAtKeyFor(queryKey));\n }\n }\n }\n\n await this.delegate.delete(queueKeyFor(queryDefId));\n await this.delegate.delete(key);\n await this.delegate.delete(cacheTimeKeyFor(queryDefId));\n this.queues.delete(queryDefId);\n }\n }\n }\n\n private async setValue(id: number, value: unknown, refIds?: Set<number>): Promise<void> {\n const delegate = this.delegate!;\n\n await delegate.setString(valueKeyFor(id), JSON.stringify(value));\n\n const refIdsKey = refIdsKeyFor(id);\n\n const prevRefIds = await delegate.getBuffer(refIdsKey);\n\n if (refIds === undefined || refIds.size === 0) {\n await delegate.delete(refIdsKey);\n\n // Decrement all previous refs\n if (prevRefIds !== undefined) {\n for (let i = 0; i < prevRefIds.length; i++) {\n const refId = prevRefIds[i];\n await this.decrementRefCount(refId);\n }\n }\n } else {\n // Convert the set to a Uint32Array and capture all the refIds before we\n // delete previous ones from the set\n // NOTE: Using spread operator because Hermes (React Native) doesn't correctly\n // handle new Uint32Array(Set) - it produces an empty array instead of converting\n const newRefIds = new Uint32Array([...refIds]);\n\n if (prevRefIds !== undefined) {\n // Process new refs: increment if not in old\n for (let i = 0; i < prevRefIds.length; i++) {\n const refId = prevRefIds[i];\n\n if (refIds.has(refId)) {\n refIds.delete(refId);\n } else {\n await this.decrementRefCount(refId);\n }\n }\n }\n\n // No previous refs, increment all unique new refs\n for (const refId of refIds) {\n await this.incrementRefCount(refId);\n }\n\n await delegate.setBuffer(refIdsKey, newRefIds);\n }\n }\n\n private async writerDeleteValue(id: number): Promise<void> {\n const delegate = this.delegate!;\n const refIdsKey = refIdsKeyFor(id);\n\n await delegate.delete(valueKeyFor(id));\n await delegate.delete(refCountKeyFor(id));\n\n const refIds = await delegate.getBuffer(refIdsKey);\n await delegate.delete(refIdsKey); // Clean up the refIds key\n\n if (refIds === undefined) {\n return;\n }\n\n // Decrement ref counts for all referenced entities\n for (const refId of refIds) {\n if (refId !== 0) {\n await this.decrementRefCount(refId);\n }\n }\n }\n\n private async incrementRefCount(refId: number): Promise<void> {\n const delegate = this.delegate!;\n const refCountKey = refCountKeyFor(refId);\n const currentCount = (await delegate.getNumber(refCountKey)) ?? 0;\n const newCount = currentCount + 1;\n await delegate.setNumber(refCountKey, newCount);\n }\n\n private async decrementRefCount(refId: number): Promise<void> {\n const delegate = this.delegate!;\n const refCountKey = refCountKeyFor(refId);\n const currentCount = await delegate.getNumber(refCountKey);\n\n if (currentCount === undefined) {\n // Already deleted or never existed\n return;\n }\n\n const newCount = currentCount - 1;\n\n if (newCount === 0) {\n // Entity exists, cascade delete it\n await this.writerDeleteValue(refId);\n } else {\n await delegate.setNumber(refCountKey, newCount);\n }\n }\n}\n"],"names":["AsyncQueryStore","config","sendMessage","msg","resolve","error","queryDef","queryKey","updatedAt","updatedAtKeyFor","cacheTimeMs","DEFAULT_CACHE_TIME","valueStr","valueKeyFor","entityIds","refIdsKeyFor","preloadedEntities","preloaded","entityId","entityValue","childIds","value","refIds","message","entityKey","queryDefId","cacheTime","queueKey","queueKeyFor","queue","maxCount","DEFAULT_MAX_COUNT","lastUsedKeyFor","cacheTimeKeyFor","indexOfKey","evicted","allKeys","now","key","LAST_USED_PREFIX","lastUsedAt","id","delegate","refIdsKey","prevRefIds","i","refId","newRefIds","refCountKeyFor","refCountKey","newCount","currentCount"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("../shared-Ct5zKrt4.js");class v{kv=Object.create(null);has(e){return e in this.kv}getString(e){return this.kv[e]}setString(e,s){this.kv[e]=s}getNumber(e){return this.kv[e]}setNumber(e,s){this.kv[e]=s}getBuffer(e){return this.kv[e]}setBuffer(e,s){this.kv[e]=s}delete(e){delete this.kv[e]}getAllKeys(){return Object.keys(this.kv)}}class a{constructor(e){this.kv=e}queues=new Map;loadQuery(e,s){const i=this.kv.getNumber(r.updatedAtKeyFor(s)),t=(e.statics.cache?.cacheTime??r.DEFAULT_CACHE_TIME)*60*1e3;if(i===void 0||i<Date.now()-t)return;const n=this.kv.getString(r.valueKeyFor(s));if(n===void 0)return;const o=this.kv.getBuffer(r.refIdsKeyFor(s));let u;return o!==void 0&&(u=new Map,this.preloadEntities(o,u)),this.activateQuery(e,s),{value:JSON.parse(n),refIds:o===void 0?void 0:new Set(o??[]),updatedAt:i,preloadedEntities:u}}preloadEntities(e,s){for(const i of e){const t=this.kv.getString(r.valueKeyFor(i));if(t===void 0)continue;s.set(i,JSON.parse(t));const n=this.kv.getBuffer(r.refIdsKeyFor(i));n!==void 0&&this.preloadEntities(n,s)}}saveQuery(e,s,i,t,n){this.setValue(s,i,n),this.kv.setNumber(r.updatedAtKeyFor(s),t),this.activateQuery(e,s)}saveEntity(e,s,i){this.setValue(e,s,i)}activateQuery(e,s){if(!this.kv.has(r.valueKeyFor(s)))return;const i=e.statics.id;let t=this.queues.get(i);if(t===void 0){const u=e.statics.cache?.maxCount??r.DEFAULT_MAX_COUNT;t=this.kv.getBuffer(r.queueKeyFor(i)),t===void 0?(t=new Uint32Array(u),this.kv.setBuffer(r.queueKeyFor(i),t)):t.length!==u&&(t=new Uint32Array(t.buffer,0,u),this.kv.setBuffer(r.queueKeyFor(i),t)),this.queues.set(i,t)}this.kv.setNumber(r.lastUsedKeyFor(i),Date.now()),this.kv.setNumber(r.cacheTimeKeyFor(i),e.statics.cache?.cacheTime??r.DEFAULT_CACHE_TIME);const n=t.indexOf(s);if(n>=0){if(n===0)return;t.copyWithin(1,0,n),t[0]=s;return}const o=t[t.length-1];t.copyWithin(1,0,t.length-1),t[0]=s,o!==0&&(this.deleteQuery(o),this.kv.delete(r.updatedAtKeyFor(o)))}purgeStaleQueries(){const e=this.kv.getAllKeys(),s=Date.now();for(const i of e){if(!i.startsWith(r.LAST_USED_PREFIX))continue;const t=i.slice(r.LAST_USED_PREFIX.length),n=this.kv.getNumber(i),u=(this.kv.getNumber(r.cacheTimeKeyFor(t))??r.DEFAULT_CACHE_TIME)*60*1e3;if(n===void 0||s-n>u){const c=this.kv.getBuffer(r.queueKeyFor(t));if(c!==void 0)for(const f of c)f!==0&&(this.deleteQuery(f),this.kv.delete(r.updatedAtKeyFor(f)));this.kv.delete(r.queueKeyFor(t)),this.kv.delete(i),this.kv.delete(r.cacheTimeKeyFor(t)),this.queues.delete(t)}}}setValue(e,s,i){const t=this.kv;t.setString(r.valueKeyFor(e),JSON.stringify(s));const n=r.refIdsKeyFor(e),o=t.getBuffer(n);if(i===void 0||i.size===0){if(t.delete(n),o!==void 0)for(let u=0;u<o.length;u++){const c=o[u];this.decrementRefCount(c)}}else{const u=new Uint32Array([...i]);if(o!==void 0)for(let c=0;c<o.length;c++){const f=o[c];i.has(f)?i.delete(f):this.decrementRefCount(f)}for(const c of i)this.incrementRefCount(c);t.setBuffer(n,u)}}deleteQuery(e){const s=this.kv;s.delete(r.valueKeyFor(e)),s.delete(r.refCountKeyFor(e));const i=s.getBuffer(r.refIdsKeyFor(e));if(s.delete(r.refIdsKeyFor(e)),i!==void 0)for(const t of i)t!==0&&this.decrementRefCount(t)}incrementRefCount(e){const s=r.refCountKeyFor(e),t=(this.kv.getNumber(s)??0)+1;this.kv.setNumber(s,t)}decrementRefCount(e){const s=r.refCountKeyFor(e),i=this.kv.getNumber(s);if(i===void 0)return;const t=i-1;t===0?this.deleteQuery(e):this.kv.setNumber(s,t)}}exports.MemoryPersistentStore=v;exports.SyncQueryStore=a;
|
|
2
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sources":["../../../../src/stores/sync.ts"],"sourcesContent":["import { CachedQuery, QueryStore, type PreloadedEntityMap } from '../QueryClient.js';\nimport { QueryDefinition } from '../query.js';\nimport {\n cacheTimeKeyFor,\n DEFAULT_CACHE_TIME,\n DEFAULT_MAX_COUNT,\n LAST_USED_PREFIX,\n lastUsedKeyFor,\n queueKeyFor,\n refCountKeyFor,\n refIdsKeyFor,\n updatedAtKeyFor,\n valueKeyFor,\n} from './shared.js';\n\nexport interface SyncPersistentStore {\n has(key: string): boolean;\n\n getString(key: string): string | undefined;\n setString(key: string, value: string): void;\n\n getNumber(key: string): number | undefined;\n setNumber(key: string, value: number): void;\n\n getBuffer(key: string): Uint32Array | undefined;\n setBuffer(key: string, value: Uint32Array): void;\n\n delete(key: string): void;\n\n getAllKeys(): string[];\n}\n\nexport class MemoryPersistentStore implements SyncPersistentStore {\n private readonly kv: Record<string, unknown> = Object.create(null);\n\n has(key: string): boolean {\n return key in this.kv;\n }\n\n getString(key: string): string | undefined {\n return this.kv[key] as string | undefined;\n }\n\n setString(key: string, value: string): void {\n this.kv[key] = value;\n }\n\n getNumber(key: string): number | undefined {\n return this.kv[key] as number | undefined;\n }\n\n setNumber(key: string, value: number): void {\n this.kv[key] = value;\n }\n\n getBuffer(key: string): Uint32Array | undefined {\n return this.kv[key] as Uint32Array | undefined;\n }\n\n setBuffer(key: string, value: Uint32Array): void {\n this.kv[key] = value;\n }\n\n delete(key: string): void {\n delete this.kv[key];\n }\n\n getAllKeys(): string[] {\n return Object.keys(this.kv);\n }\n}\n\nexport class SyncQueryStore implements QueryStore {\n queues: Map<string, Uint32Array> = new Map();\n\n constructor(private readonly kv: SyncPersistentStore) {}\n\n loadQuery(queryDef: QueryDefinition<any, any, any>, queryKey: number): CachedQuery | undefined {\n const updatedAt = this.kv.getNumber(updatedAtKeyFor(queryKey));\n\n const cacheTimeMs = (queryDef.statics.cache?.cacheTime ?? DEFAULT_CACHE_TIME) * 60 * 1000;\n if (updatedAt === undefined || updatedAt < Date.now() - cacheTimeMs) {\n return;\n }\n\n const valueStr = this.kv.getString(valueKeyFor(queryKey));\n\n if (valueStr === undefined) {\n return;\n }\n\n const entityIds = this.kv.getBuffer(refIdsKeyFor(queryKey));\n\n let preloadedEntities: PreloadedEntityMap | undefined;\n if (entityIds !== undefined) {\n preloadedEntities = new Map();\n this.preloadEntities(entityIds, preloadedEntities);\n }\n\n this.activateQuery(queryDef, queryKey);\n\n return {\n value: JSON.parse(valueStr) as Record<string, unknown>,\n refIds: entityIds === undefined ? undefined : new Set(entityIds ?? []),\n updatedAt,\n preloadedEntities,\n };\n }\n\n private preloadEntities(entityIds: Uint32Array, preloaded: PreloadedEntityMap): void {\n for (const entityId of entityIds) {\n const entityValue = this.kv.getString(valueKeyFor(entityId));\n\n if (entityValue === undefined) {\n continue;\n }\n\n preloaded.set(entityId, JSON.parse(entityValue) as Record<string, unknown>);\n\n const childIds = this.kv.getBuffer(refIdsKeyFor(entityId));\n\n if (childIds === undefined) {\n continue;\n }\n\n this.preloadEntities(childIds, preloaded);\n }\n }\n\n saveQuery(\n queryDef: QueryDefinition<any, any, any>,\n queryKey: number,\n value: unknown,\n updatedAt: number,\n refIds?: Set<number>,\n ): void {\n this.setValue(queryKey, value, refIds);\n this.kv.setNumber(updatedAtKeyFor(queryKey), updatedAt);\n this.activateQuery(queryDef, queryKey);\n }\n\n saveEntity(entityKey: number, value: unknown, refIds?: Set<number>): void {\n this.setValue(entityKey, value, refIds);\n }\n\n activateQuery(queryDef: QueryDefinition<any, any, any>, queryKey: number): void {\n if (!this.kv.has(valueKeyFor(queryKey))) {\n return;\n }\n\n const queryDefId = queryDef.statics.id;\n let queue = this.queues.get(queryDefId);\n\n if (queue === undefined) {\n const maxCount = queryDef.statics.cache?.maxCount ?? DEFAULT_MAX_COUNT;\n queue = this.kv.getBuffer(queueKeyFor(queryDefId));\n\n if (queue === undefined) {\n queue = new Uint32Array(maxCount);\n this.kv.setBuffer(queueKeyFor(queryDefId), queue);\n } else if (queue.length !== maxCount) {\n queue = new Uint32Array(queue.buffer, 0, maxCount);\n this.kv.setBuffer(queueKeyFor(queryDefId), queue);\n }\n\n this.queues.set(queryDefId, queue);\n }\n\n this.kv.setNumber(lastUsedKeyFor(queryDefId), Date.now());\n this.kv.setNumber(cacheTimeKeyFor(queryDefId), queryDef.statics.cache?.cacheTime ?? DEFAULT_CACHE_TIME);\n\n const indexOfKey = queue.indexOf(queryKey);\n\n if (indexOfKey >= 0) {\n if (indexOfKey === 0) {\n return;\n }\n queue.copyWithin(1, 0, indexOfKey);\n queue[0] = queryKey;\n return;\n }\n\n const evicted = queue[queue.length - 1];\n queue.copyWithin(1, 0, queue.length - 1);\n queue[0] = queryKey;\n\n if (evicted !== 0) {\n this.deleteQuery(evicted);\n this.kv.delete(updatedAtKeyFor(evicted));\n }\n }\n\n purgeStaleQueries(): void {\n const allKeys = this.kv.getAllKeys();\n const now = Date.now();\n\n for (const key of allKeys) {\n if (!key.startsWith(LAST_USED_PREFIX)) continue;\n\n const queryDefId = key.slice(LAST_USED_PREFIX.length);\n const lastUsedAt = this.kv.getNumber(key);\n const cacheTime = this.kv.getNumber(cacheTimeKeyFor(queryDefId)) ?? DEFAULT_CACHE_TIME;\n const cacheTimeMs = cacheTime * 60 * 1000;\n\n if (lastUsedAt === undefined || now - lastUsedAt > cacheTimeMs) {\n const queue = this.kv.getBuffer(queueKeyFor(queryDefId));\n\n if (queue !== undefined) {\n for (const queryKey of queue) {\n if (queryKey !== 0) {\n this.deleteQuery(queryKey);\n this.kv.delete(updatedAtKeyFor(queryKey));\n }\n }\n }\n\n this.kv.delete(queueKeyFor(queryDefId));\n this.kv.delete(key);\n this.kv.delete(cacheTimeKeyFor(queryDefId));\n this.queues.delete(queryDefId);\n }\n }\n }\n\n private setValue(id: number, value: unknown, refIds?: Set<number>): void {\n const kv = this.kv;\n\n kv.setString(valueKeyFor(id), JSON.stringify(value));\n\n const refIdsKey = refIdsKeyFor(id);\n\n const prevRefIds = kv.getBuffer(refIdsKey);\n\n if (refIds === undefined || refIds.size === 0) {\n kv.delete(refIdsKey);\n\n // Decrement all previous refs\n if (prevRefIds !== undefined) {\n for (let i = 0; i < prevRefIds.length; i++) {\n const refId = prevRefIds[i];\n this.decrementRefCount(refId);\n }\n }\n } else {\n // Convert the set to a Uint32Array and capture all the refIds before we\n // delete previous ones from the set\n // NOTE: Using spread operator because Hermes (React Native) doesn't correctly\n // handle new Uint32Array(Set) - it produces an empty array instead of converting\n const newRefIds = new Uint32Array([...refIds]);\n\n if (prevRefIds !== undefined) {\n // Process new refs: increment if not in old\n for (let i = 0; i < prevRefIds.length; i++) {\n const refId = prevRefIds[i];\n\n if (refIds.has(refId)) {\n refIds.delete(refId);\n } else {\n this.decrementRefCount(refId);\n }\n }\n }\n\n // No previous refs, increment all unique new refs\n for (const refId of refIds) {\n this.incrementRefCount(refId);\n }\n\n kv.setBuffer(refIdsKey, newRefIds);\n }\n }\n\n deleteQuery(id: number): void {\n const kv = this.kv;\n\n kv.delete(valueKeyFor(id));\n kv.delete(refCountKeyFor(id));\n\n const refIds = kv.getBuffer(refIdsKeyFor(id));\n kv.delete(refIdsKeyFor(id)); // Clean up the refIds key\n\n if (refIds === undefined) {\n return;\n }\n\n // Decrement ref counts for all referenced entities\n for (const refId of refIds) {\n if (refId !== 0) {\n this.decrementRefCount(refId);\n }\n }\n }\n\n private incrementRefCount(refId: number): void {\n const refCountKey = refCountKeyFor(refId);\n const currentCount = this.kv.getNumber(refCountKey) ?? 0;\n const newCount = currentCount + 1;\n this.kv.setNumber(refCountKey, newCount);\n }\n\n private decrementRefCount(refId: number): void {\n const refCountKey = refCountKeyFor(refId);\n const currentCount = this.kv.getNumber(refCountKey);\n\n if (currentCount === undefined) {\n // Already deleted or never existed\n return;\n }\n\n const newCount = currentCount - 1;\n\n if (newCount === 0) {\n // Entity exists, cascade delete it\n this.deleteQuery(refId);\n } else {\n this.kv.setNumber(refCountKey, newCount);\n }\n }\n}\n"],"names":["MemoryPersistentStore","key","value","SyncQueryStore","kv","queryDef","queryKey","updatedAt","updatedAtKeyFor","cacheTimeMs","DEFAULT_CACHE_TIME","valueStr","valueKeyFor","entityIds","refIdsKeyFor","preloadedEntities","preloaded","entityId","entityValue","childIds","refIds","entityKey","queryDefId","queue","maxCount","DEFAULT_MAX_COUNT","queueKeyFor","lastUsedKeyFor","cacheTimeKeyFor","indexOfKey","evicted","allKeys","now","LAST_USED_PREFIX","lastUsedAt","id","refIdsKey","prevRefIds","i","refId","newRefIds","refCountKeyFor","refCountKey","newCount","currentCount"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=100;function u(t){return!Number.isFinite(t)||t<c?c:t}function s(t){const r=u(t.interval);return function(a){let i=!0,e;const o=this.refetch,n=async()=>{if(i){try{await o()}catch{}i&&(e=setTimeout(n,r))}};return e=setTimeout(n,r),()=>{i=!1,e!==void 0&&(clearTimeout(e),e=void 0)}}}exports.poll=s;
|
|
2
|
+
//# sourceMappingURL=polling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling.js","sources":["../../../../src/subscriptions/polling.ts"],"sourcesContent":["import type { MutationEvent } from '../types.js';\n\nconst MIN_INTERVAL = 100;\n\nexport interface PollConfig {\n interval: number;\n}\n\nfunction clampInterval(interval: number): number {\n if (!Number.isFinite(interval) || interval < MIN_INTERVAL) {\n if (IS_DEV && (Number.isNaN(interval) || interval < 0)) {\n console.warn(`poll: invalid interval ${interval}, clamping to ${MIN_INTERVAL}ms`);\n }\n return MIN_INTERVAL;\n }\n return interval;\n}\n\nexport function poll(config: PollConfig): (this: any, onEvent: (event: MutationEvent) => void) => () => void {\n const interval = clampInterval(config.interval);\n\n return function subscribe(this: any, _onEvent: (event: MutationEvent) => void): () => void {\n let active = true;\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n const refetch = this.refetch as () => Promise<unknown>;\n\n const tick = async () => {\n if (!active) return;\n try {\n await refetch();\n } catch {\n // Keep polling after errors\n }\n if (active) {\n timer = setTimeout(tick, interval);\n }\n };\n\n timer = setTimeout(tick, interval);\n\n return () => {\n active = false;\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n };\n };\n}\n"],"names":["MIN_INTERVAL","clampInterval","interval","poll","config","_onEvent","active","timer","refetch","tick"],"mappings":"gFAEA,MAAMA,EAAe,IAMrB,SAASC,EAAcC,EAA0B,CAC/C,MAAI,CAAC,OAAO,SAASA,CAAQ,GAAKA,EAAWF,EAIpCA,EAEFE,CACT,CAEO,SAASC,EAAKC,EAAwF,CAC3G,MAAMF,EAAWD,EAAcG,EAAO,QAAQ,EAE9C,OAAO,SAA8BC,EAAsD,CACzF,IAAIC,EAAS,GACTC,EAEJ,MAAMC,EAAU,KAAK,QAEfC,EAAO,SAAY,CACvB,GAAKH,EACL,IAAI,CACF,MAAME,EAAA,CACR,MAAQ,CAER,CACIF,IACFC,EAAQ,WAAWE,EAAMP,CAAQ,GAErC,EAEA,OAAAK,EAAQ,WAAWE,EAAMP,CAAQ,EAE1B,IAAM,CACXI,EAAS,GACLC,IAAU,SACZ,aAAaA,CAAK,EAClBA,EAAQ,OAEZ,CACF,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../QueryClient-N0MJmuHW.js"),d=require("../QueryController-BQA49OYU.js");class h extends a.Query{static controller;getIdentityKey(){return`topic:${this.topic}`}getConfig(){return{staleTime:0,subscribe:()=>()=>{this._topicController?.unsubscribe(this.topic)}}}}class f extends d.QueryController{_topics=new Map;fulfillTopic(e,s){const t=this._topics.get(e);if(t===void 0){this._topics.set(e,{status:"fulfilled",data:s});return}t.status==="pending"&&(t.status="fulfilled",t.data=s,t.resolve(s))}rejectTopic(e,s){const t=this._topics.get(e);if(t===void 0){this._topics.set(e,{status:"rejected",error:s});return}t.status==="pending"&&(t.status="rejected",t.error=s,t.reject(s))}clearTopic(e){this._topics.delete(e)}clearAll(){this._topics.clear()}async send(e,s){const t=e;t._topicController=this;const r=t.topic,i=this._topics.get(r);if(i)switch(i.status){case"fulfilled":return i.data;case"rejected":throw i.error;case"pending":return i.promise}let o,c;const n=new Promise((u,p)=>{o=u,c=p});return this._topics.set(r,{status:"pending",promise:n,resolve:o,reject:c}),this.subscribe(r),n}sendMutationEvent(e){this.queryClient.applyMutationEvent(e)}}exports.TopicQuery=h;exports.TopicQueryController=f;
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/topic/TopicQuery.ts","../../../../src/topic/TopicQueryController.ts"],"sourcesContent":["import { Query } from '../query.js';\nimport type { TopicQueryController } from './TopicQueryController.js';\nimport type { QueryConfigOptions } from '../query-types.js';\n\n// ================================\n// TopicQuery — declarative topic-based query definition\n// ================================\n\nexport abstract class TopicQuery extends Query {\n static override controller: typeof TopicQueryController;\n\n abstract topic: string;\n\n getIdentityKey(): string {\n return `topic:${this.topic}`;\n }\n\n getConfig(): QueryConfigOptions {\n return {\n staleTime: 0,\n subscribe: () => {\n return () => {\n const controller = (this as Record<string, any>)._topicController as TopicQueryController | undefined;\n controller?.unsubscribe(this.topic);\n };\n },\n };\n }\n}\n","import { QueryController } from '../QueryController.js';\nimport type { Query } from '../query.js';\nimport type { MutationEvent } from '../types.js';\n\n// ================================\n// TopicQueryController — abstract controller for topic-based subscriptions\n// ================================\n\ninterface TopicCtx extends Query {\n topic: string;\n _topicController?: TopicQueryController;\n}\n\ninterface TopicState {\n status: 'pending' | 'fulfilled' | 'rejected';\n promise?: Promise<unknown>;\n resolve?: (data: unknown) => void;\n reject?: (error: unknown) => void;\n data?: unknown;\n error?: unknown;\n}\n\nexport abstract class TopicQueryController extends QueryController {\n private _topics = new Map<string, TopicState>();\n\n /**\n * Called when a query activates for a given topic.\n * Implementations should start delivering data for this topic,\n * calling `fulfillTopic()` when initial data is available and\n * `sendMutationEvent()` for ongoing updates.\n */\n abstract subscribe(topic: string): void;\n\n /**\n * Called when the query deactivates. Implementations should\n * tear down any resources for this topic.\n */\n abstract unsubscribe(topic: string): void;\n\n /**\n * Resolve the pending promise for a topic with initial data.\n * Can be called before `send()` — the data will be picked up\n * when the query activates.\n */\n protected fulfillTopic(topic: string, data: unknown): void {\n const state = this._topics.get(topic);\n\n if (state === undefined) {\n this._topics.set(topic, { status: 'fulfilled', data });\n return;\n }\n\n if (state.status === 'pending') {\n state.status = 'fulfilled';\n state.data = data;\n state.resolve!(data);\n }\n }\n\n /**\n * Reject the pending promise for a topic.\n * Can be called before `send()` — the error will be propagated\n * when the query activates.\n */\n protected rejectTopic(topic: string, error: unknown): void {\n const state = this._topics.get(topic);\n\n if (state === undefined) {\n this._topics.set(topic, { status: 'rejected', error });\n return;\n }\n\n if (state.status === 'pending') {\n state.status = 'rejected';\n state.error = error;\n state.reject!(error);\n }\n }\n\n /**\n * Clears internal state for a topic. Called automatically by\n * `unsubscribe` — subclasses generally don't need to call this.\n */\n protected clearTopic(topic: string): void {\n this._topics.delete(topic);\n }\n\n protected clearAll(): void {\n this._topics.clear();\n }\n\n override async send(ctx: Query, _signal: AbortSignal): Promise<unknown> {\n const topicCtx = ctx as TopicCtx;\n topicCtx._topicController = this;\n const topic = topicCtx.topic;\n\n const existing = this._topics.get(topic);\n\n if (existing) {\n switch (existing.status) {\n case 'fulfilled':\n return existing.data;\n case 'rejected':\n throw existing.error;\n case 'pending':\n return existing.promise;\n }\n }\n\n // No state yet — create a deferred and subscribe\n let resolve!: (data: unknown) => void;\n let reject!: (error: unknown) => void;\n const promise = new Promise<unknown>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n this._topics.set(topic, { status: 'pending', promise, resolve, reject });\n this.subscribe(topic);\n\n return promise;\n }\n\n /**\n * Convenience wrapper — pushes a mutation event through the QueryClient\n * so that entities and live collections are updated reactively.\n */\n protected sendMutationEvent(event: MutationEvent): void {\n this.queryClient!.applyMutationEvent(event);\n }\n}\n"],"names":["TopicQuery","Query","TopicQueryController","QueryController","topic","data","state","error","ctx","_signal","topicCtx","existing","resolve","reject","promise","res","rej","event"],"mappings":"0KAQO,MAAeA,UAAmBC,EAAAA,KAAM,CAC7C,OAAgB,WAIhB,gBAAyB,CACvB,MAAO,SAAS,KAAK,KAAK,EAC5B,CAEA,WAAgC,CAC9B,MAAO,CACL,UAAW,EACX,UAAW,IACF,IAAM,CACS,KAA6B,kBACrC,YAAY,KAAK,KAAK,CACpC,CACF,CAEJ,CACF,CCNO,MAAeC,UAA6BC,EAAAA,eAAgB,CACzD,YAAc,IAqBZ,aAAaC,EAAeC,EAAqB,CACzD,MAAMC,EAAQ,KAAK,QAAQ,IAAIF,CAAK,EAEpC,GAAIE,IAAU,OAAW,CACvB,KAAK,QAAQ,IAAIF,EAAO,CAAE,OAAQ,YAAa,KAAAC,EAAM,EACrD,MACF,CAEIC,EAAM,SAAW,YACnBA,EAAM,OAAS,YACfA,EAAM,KAAOD,EACbC,EAAM,QAASD,CAAI,EAEvB,CAOU,YAAYD,EAAeG,EAAsB,CACzD,MAAMD,EAAQ,KAAK,QAAQ,IAAIF,CAAK,EAEpC,GAAIE,IAAU,OAAW,CACvB,KAAK,QAAQ,IAAIF,EAAO,CAAE,OAAQ,WAAY,MAAAG,EAAO,EACrD,MACF,CAEID,EAAM,SAAW,YACnBA,EAAM,OAAS,WACfA,EAAM,MAAQC,EACdD,EAAM,OAAQC,CAAK,EAEvB,CAMU,WAAWH,EAAqB,CACxC,KAAK,QAAQ,OAAOA,CAAK,CAC3B,CAEU,UAAiB,CACzB,KAAK,QAAQ,MAAA,CACf,CAEA,MAAe,KAAKI,EAAYC,EAAwC,CACtE,MAAMC,EAAWF,EACjBE,EAAS,iBAAmB,KAC5B,MAAMN,EAAQM,EAAS,MAEjBC,EAAW,KAAK,QAAQ,IAAIP,CAAK,EAEvC,GAAIO,EACF,OAAQA,EAAS,OAAA,CACf,IAAK,YACH,OAAOA,EAAS,KAClB,IAAK,WACH,MAAMA,EAAS,MACjB,IAAK,UACH,OAAOA,EAAS,OAAA,CAKtB,IAAIC,EACAC,EACJ,MAAMC,EAAU,IAAI,QAAiB,CAACC,EAAKC,IAAQ,CACjDJ,EAAUG,EACVF,EAASG,CACX,CAAC,EAED,YAAK,QAAQ,IAAIZ,EAAO,CAAE,OAAQ,UAAW,QAAAU,EAAS,QAAAF,EAAS,OAAAC,EAAQ,EACvE,KAAK,UAAUT,CAAK,EAEbU,CACT,CAMU,kBAAkBG,EAA4B,CACtD,KAAK,YAAa,mBAAmBA,CAAK,CAC5C,CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { LiveCollectionBinding } from './LiveCollection.js';
|
|
2
|
+
export declare const EVENT_SOURCE_FIELD = "__eventSource";
|
|
3
|
+
/**
|
|
4
|
+
* Pre-computed field path: original field name + split segments (for dotted paths).
|
|
5
|
+
*/
|
|
6
|
+
export interface FieldPath {
|
|
7
|
+
field: string;
|
|
8
|
+
segments: string[] | undefined;
|
|
9
|
+
}
|
|
10
|
+
export declare function buildFieldPath(field: string): FieldPath;
|
|
11
|
+
export declare function buildFieldPaths(fields: string[]): FieldPath[];
|
|
12
|
+
/**
|
|
13
|
+
* Compute a constraint hash from an entity's data given pre-computed field paths.
|
|
14
|
+
* Returns undefined if any constraint field is missing from the entity data.
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeConstraintHash(entityData: Record<string, unknown>, fieldPaths: FieldPath[]): number | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve constraint FieldRefs against a data object to produce concrete constraint
|
|
19
|
+
* hashes. Used when creating a LiveArrayInstance/LiveValueInstance to compute the
|
|
20
|
+
* hash under which it should be registered.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveConstraintHashes(constraintFieldRefs: Map<string, Array<[string, unknown]>> | undefined, parentData: Record<string, unknown>): Map<string, number> | undefined;
|
|
23
|
+
export declare class ConstraintGroup {
|
|
24
|
+
fields: string[];
|
|
25
|
+
fieldPaths: FieldPath[];
|
|
26
|
+
private _bindings;
|
|
27
|
+
constructor(fields: string[]);
|
|
28
|
+
register(constraintHash: number, binding: LiveCollectionBinding): void;
|
|
29
|
+
unregister(constraintHash: number, binding: LiveCollectionBinding): void;
|
|
30
|
+
getMatching(constraintHash: number): Set<LiveCollectionBinding> | undefined;
|
|
31
|
+
get isEmpty(): boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare class ConstraintMatcher {
|
|
34
|
+
private _groups;
|
|
35
|
+
private getOrCreateGroup;
|
|
36
|
+
register(constraintHash: number, fields: string[], binding: LiveCollectionBinding): void;
|
|
37
|
+
unregister(constraintHash: number, fields: string[], binding: LiveCollectionBinding): void;
|
|
38
|
+
registerBinding(binding: LiveCollectionBinding, typename: string): void;
|
|
39
|
+
unregisterBinding(binding: LiveCollectionBinding, typename: string): void;
|
|
40
|
+
routeEvent(typename: string, entityData: Record<string, unknown>, entityKey: number, eventType: 'create' | 'update' | 'delete', onMatch?: () => void, deleteData?: Record<string, unknown>): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=ConstraintMatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConstraintMatcher.d.ts","sourceRoot":"","sources":["../../src/ConstraintMatcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAMjE,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAMlD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAChC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAEvD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAE7D;AAYD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,UAAU,EAAE,SAAS,EAAE,GACtB,MAAM,GAAG,SAAS,CASpB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EACtE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CA+BjC;AAYD,qBAAa,eAAe;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,CAAC,SAAS,CAAsD;gBAE3D,MAAM,EAAE,MAAM,EAAE;IAK5B,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAStE,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAUxE,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,GAAG,CAAC,qBAAqB,CAAC,GAAG,SAAS;IAI3E,IAAI,OAAO,IAAI,OAAO,CAErB;CACF;AAUD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,gBAAgB;IAUxB,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAIxF,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAW1F,eAAe,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUvE,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAUzE,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACzC,OAAO,CAAC,EAAE,MAAM,IAAI,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,IAAI;CAaR"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type EntityDef } from './types.js';
|
|
2
|
+
import type { QueryClient } from './QueryClient.js';
|
|
3
|
+
import { ValidatorDef } from './typeDefs.js';
|
|
4
|
+
import type { LiveCollectionBinding } from './LiveCollection.js';
|
|
5
|
+
export declare class EntityInstance {
|
|
6
|
+
private _notifier;
|
|
7
|
+
_queryClient: QueryClient;
|
|
8
|
+
private _proxies;
|
|
9
|
+
key: number;
|
|
10
|
+
typename: string;
|
|
11
|
+
id: string | number;
|
|
12
|
+
idField: string | symbol;
|
|
13
|
+
data: Record<string, unknown>;
|
|
14
|
+
refCount: number;
|
|
15
|
+
entityRefs: Map<EntityInstance, number> | undefined;
|
|
16
|
+
liveCollections: LiveCollectionBinding[];
|
|
17
|
+
satisfiedDefs: WeakSet<ValidatorDef<unknown>>;
|
|
18
|
+
parseId: number;
|
|
19
|
+
_entityCache: {
|
|
20
|
+
gcTime?: number;
|
|
21
|
+
} | undefined;
|
|
22
|
+
_extraMethods: Record<string, (...args: unknown[]) => unknown> | undefined;
|
|
23
|
+
_extraGetters: Record<string, () => unknown> | undefined;
|
|
24
|
+
constructor(key: number, typename: string, id: string | number, idField: string | symbol, data: Record<string, unknown>, queryClient: QueryClient);
|
|
25
|
+
retain(): void;
|
|
26
|
+
release(): void;
|
|
27
|
+
evict(): void;
|
|
28
|
+
setChildRefs(newRefs: Map<EntityInstance, number> | undefined, persist?: boolean): void;
|
|
29
|
+
addChildRef(child: EntityInstance): void;
|
|
30
|
+
removeChildRef(child: EntityInstance): void;
|
|
31
|
+
getProxy(shape: EntityDef): Record<string, unknown>;
|
|
32
|
+
get proxy(): Record<string, unknown> | undefined;
|
|
33
|
+
satisfiesDef(def: ValidatorDef<unknown>): boolean;
|
|
34
|
+
save(): void;
|
|
35
|
+
notify(): void;
|
|
36
|
+
consume(): void;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=EntityInstance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityInstance.d.ts","sourceRoot":"","sources":["../../src/EntityInstance.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,SAAS,EAAQ,MAAM,YAAY,CAAC;AAIlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAiB,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAqFjE,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAW;IAC5B,YAAY,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,QAAQ,CAA6D;IAE7E,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAK;IACrB,UAAU,EAAE,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACpD,eAAe,EAAE,qBAAqB,EAAE,CAAM;IAC9C,aAAa,EAAE,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAiB;IAC9D,OAAO,EAAE,MAAM,CAAM;IACrB,YAAY,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;IAC3E,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,GAAG,SAAS,CAAC;gBAGvD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,GAAG,MAAM,EACnB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,EAAE,WAAW;IAY1B,MAAM,IAAI,IAAI;IAQd,OAAO,IAAI,IAAI;IAcf,KAAK,IAAI,IAAI;IAYb,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAgBvF,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAQxC,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAa3C,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUnD,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAE/C;IAED,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,OAAO;IASjD,IAAI,IAAI,IAAI;IAIZ,MAAM,IAAI,IAAI;IAId,OAAO,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EntityDef } from './types.js';
|
|
2
|
+
import type { QueryClient } from './QueryClient.js';
|
|
3
|
+
import { EntityInstance } from './EntityInstance.js';
|
|
4
|
+
export declare class EntityStore {
|
|
5
|
+
private instances;
|
|
6
|
+
private persistEntity;
|
|
7
|
+
constructor(persistEntity: (key: number, data: Record<string, unknown>, refKeys?: Set<number>) => void);
|
|
8
|
+
hasEntity(key: number): boolean;
|
|
9
|
+
getEntity(key: number): EntityInstance | undefined;
|
|
10
|
+
getOrCreateEntity(key: number, data: Record<string, unknown>, shape: EntityDef, queryClient: QueryClient): EntityInstance;
|
|
11
|
+
remove(key: number): void;
|
|
12
|
+
save(instance: EntityInstance): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=EntityStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityStore.d.ts","sourceRoot":"","sources":["../../src/EntityStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,aAAa,CAA8E;gBAEvF,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI;IAItG,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIlD,iBAAiB,CACf,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,WAAW,GACvB,cAAc;IA0BjB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,IAAI,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;CAQrC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GcManager — bucket-based in-memory garbage collection.
|
|
3
|
+
*
|
|
4
|
+
* Each unique `gcTime` value (in minutes) gets its own interval with two
|
|
5
|
+
* rotating sets (`currentFlush` / `nextFlush`). When `schedule(key, gcTime)`
|
|
6
|
+
* is called the key is added to `nextFlush`. On the next tick of that
|
|
7
|
+
* bucket's interval the set rotates, so the key lands in `currentFlush` and
|
|
8
|
+
* is evicted on the *following* tick. This means:
|
|
9
|
+
*
|
|
10
|
+
* minimum eviction delay ≈ gcTime
|
|
11
|
+
* maximum eviction delay ≈ 2 × gcTime
|
|
12
|
+
*
|
|
13
|
+
* Special values:
|
|
14
|
+
* gcTime === 0 → evict on the next microtask (setTimeout(0))
|
|
15
|
+
* gcTime === Infinity → never evict
|
|
16
|
+
*/
|
|
17
|
+
export declare const enum GcKeyType {
|
|
18
|
+
Query = 0,
|
|
19
|
+
Entity = 1
|
|
20
|
+
}
|
|
21
|
+
export declare class GcManager {
|
|
22
|
+
private _buckets;
|
|
23
|
+
private _nextTickEntries;
|
|
24
|
+
private _nextTickScheduled;
|
|
25
|
+
private _onEvict;
|
|
26
|
+
private _multiplier;
|
|
27
|
+
constructor(onEvict: (key: number, type: GcKeyType) => void, multiplier?: number);
|
|
28
|
+
schedule(key: number, gcTime: number, type: GcKeyType): void;
|
|
29
|
+
cancel(key: number, gcTime: number): void;
|
|
30
|
+
private _flushNextTick;
|
|
31
|
+
destroy(): void;
|
|
32
|
+
}
|
|
33
|
+
export declare class NoOpGcManager {
|
|
34
|
+
schedule(_key: number, _gcTime: number, _type: GcKeyType): void;
|
|
35
|
+
cancel(_key: number, _gcTime: number): void;
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=GcManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GcManager.d.ts","sourceRoot":"","sources":["../../src/GcManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,0BAAkB,SAAS;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;CACX;AAsCD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,EAAE,UAAU,GAAE,MAAU;IAKnF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAsB5D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAWzC,OAAO,CAAC,cAAc,CAOpB;IAEF,OAAO,IAAI,IAAI;CAQhB;AAED,qBAAa,aAAa;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAC/D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAC3C,OAAO,IAAI,IAAI;CAChB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type Notifier, type ReadonlySignal } from 'signalium';
|
|
2
|
+
import { type LiveFieldConfig } from './types.js';
|
|
3
|
+
import type { QueryClient } from './QueryClient.js';
|
|
4
|
+
import type { EntityInstance } from './EntityInstance.js';
|
|
5
|
+
import { type FieldPath } from './ConstraintMatcher.js';
|
|
6
|
+
import { ValidatorDef } from './typeDefs.js';
|
|
7
|
+
export interface LiveCollectionParent {
|
|
8
|
+
key: number;
|
|
9
|
+
entityRefs: Map<EntityInstance, number> | undefined;
|
|
10
|
+
liveCollections: LiveCollectionBinding[];
|
|
11
|
+
addChildRef(child: EntityInstance): void;
|
|
12
|
+
removeChildRef(child: EntityInstance): void;
|
|
13
|
+
save(): void;
|
|
14
|
+
}
|
|
15
|
+
export interface LiveInstance {
|
|
16
|
+
getValue(): unknown;
|
|
17
|
+
getRawValue(): unknown;
|
|
18
|
+
reset(raw: unknown): void;
|
|
19
|
+
append(raw: unknown): void;
|
|
20
|
+
onEvent(entityKey: number, entity: unknown, entityData: Record<string, unknown>, eventType: 'create' | 'update' | 'delete'): void;
|
|
21
|
+
}
|
|
22
|
+
export declare class LiveCollectionBinding {
|
|
23
|
+
_queryClient: QueryClient;
|
|
24
|
+
_parent: LiveCollectionParent;
|
|
25
|
+
_constraintHashes: Map<string, number>;
|
|
26
|
+
_entityDefsByTypename: Map<string, ValidatorDef<any>>;
|
|
27
|
+
_constraintFieldRefs: Map<string, Array<[string, unknown]>>;
|
|
28
|
+
readonly instance: LiveInstance;
|
|
29
|
+
constructor(entityDefs: ValidatorDef<any>[], constraintFieldRefs: Map<string, Array<[string, unknown]>>, queryClient: QueryClient, parent: LiveCollectionParent, constraintHashes: Map<string, number>, instance: LiveInstance);
|
|
30
|
+
getValue(): unknown;
|
|
31
|
+
toJSON(): unknown;
|
|
32
|
+
reset(parsed: unknown): void;
|
|
33
|
+
append(parsed: unknown): void;
|
|
34
|
+
/**
|
|
35
|
+
* Handle an entity event. The entity has already been created/updated at the
|
|
36
|
+
* root level by applyMutationEvent. The binding just checks if the entity's
|
|
37
|
+
* current data satisfies this binding's shape and forwards to the instance.
|
|
38
|
+
*/
|
|
39
|
+
onEvent(typename: string, entityKey: number, eventType: 'create' | 'update' | 'delete', onMatch?: () => void, deleteData?: Record<string, unknown>): void;
|
|
40
|
+
destroy(): void;
|
|
41
|
+
}
|
|
42
|
+
export declare class LiveArrayInstance {
|
|
43
|
+
_notifier: Notifier;
|
|
44
|
+
_items: unknown[];
|
|
45
|
+
_keys: Set<number>;
|
|
46
|
+
_outputSignal: ReadonlySignal<unknown[]> | undefined;
|
|
47
|
+
_queryClient: QueryClient;
|
|
48
|
+
_parent: LiveCollectionParent;
|
|
49
|
+
constructor(queryClient: QueryClient, parent: LiveCollectionParent, items: unknown[], constraintFieldPaths?: FieldPath[], constraintHash?: number, sort?: (a: unknown, b: unknown) => number);
|
|
50
|
+
onEvent(entityKey: number, entity: unknown, _entityData: Record<string, unknown>, eventType: 'create' | 'update' | 'delete'): void;
|
|
51
|
+
getValue(): unknown[];
|
|
52
|
+
getRawValue(): unknown[];
|
|
53
|
+
add(key: number, proxy: unknown): boolean;
|
|
54
|
+
remove(key: number): boolean;
|
|
55
|
+
has(key: number): boolean;
|
|
56
|
+
reset(rawValue: unknown): void;
|
|
57
|
+
append(rawValue: unknown): void;
|
|
58
|
+
private _findIndex;
|
|
59
|
+
}
|
|
60
|
+
export declare class LiveValueInstance {
|
|
61
|
+
_notifier: Notifier;
|
|
62
|
+
_value: unknown;
|
|
63
|
+
_createdKeys: Set<number>;
|
|
64
|
+
_deletedKeys: Set<number>;
|
|
65
|
+
_queryClient: QueryClient;
|
|
66
|
+
_parent: LiveCollectionParent;
|
|
67
|
+
private _onCreate;
|
|
68
|
+
private _onUpdate;
|
|
69
|
+
private _onDelete;
|
|
70
|
+
constructor(queryClient: QueryClient, parent: LiveCollectionParent, initialValue: unknown, onCreate: (value: unknown, entity: unknown) => unknown, onUpdate: (value: unknown, entity: unknown) => unknown, onDelete: (value: unknown, entity: unknown) => unknown);
|
|
71
|
+
onEvent(entityKey: number, entity: unknown, entityData: Record<string, unknown>, eventType: 'create' | 'update' | 'delete'): void;
|
|
72
|
+
getValue(): unknown;
|
|
73
|
+
getRawValue(): unknown;
|
|
74
|
+
reset(value: unknown): void;
|
|
75
|
+
append(_value: unknown): void;
|
|
76
|
+
}
|
|
77
|
+
export declare function createLiveCollection(config: LiveFieldConfig, parsedValue: unknown, parent: LiveCollectionParent, parentData: Record<string, unknown>, queryClient: QueryClient): LiveCollectionBinding;
|
|
78
|
+
/**
|
|
79
|
+
* Walk an object shape and create or update LiveCollectionBinding instances for
|
|
80
|
+
* live fields. Values in `data` should already be parsed.
|
|
81
|
+
* Bindings are stored directly in `data[fieldName]`.
|
|
82
|
+
* On first call, creates new bindings. On subsequent calls (e.g. refetch),
|
|
83
|
+
* resets existing instances with fresh data.
|
|
84
|
+
*/
|
|
85
|
+
export declare function initializeLiveFields(shape: Record<string, unknown>, data: Record<string, unknown>, previousData: Record<string, unknown> | undefined, parent: LiveCollectionParent, queryClient: QueryClient, appendMode?: boolean): void;
|
|
86
|
+
//# sourceMappingURL=LiveCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveCollection.d.ts","sourceRoot":"","sources":["../../src/LiveCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAA4B,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AACzF,OAAO,EAAuB,KAAK,eAAe,EAAkB,MAAM,YAAY,CAAC;AACvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,YAAY,EAAiB,MAAM,eAAe,CAAC;AAiB5D,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACpD,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5C,IAAI,IAAI,IAAI,CAAC;CACd;AAMD,MAAM,WAAW,YAAY;IAC3B,QAAQ,IAAI,OAAO,CAAC;IACpB,WAAW,IAAI,OAAO,CAAC;IACvB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,OAAO,CACL,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GACxC,IAAI,CAAC;CACT;AAMD,qBAAa,qBAAqB;IAChC,YAAY,EAAE,WAAW,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;gBAG9B,UAAU,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,EAC/B,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAC1D,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,oBAAoB,EAC5B,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,QAAQ,EAAE,YAAY;IAkBxB,QAAQ,IAAI,OAAO;IAInB,MAAM,IAAI,OAAO;IAIjB,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAI5B,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAI7B;;;;OAIG;IACH,OAAO,CACL,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EACzC,OAAO,CAAC,EAAE,MAAM,IAAI,EACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,IAAI;IAsBP,OAAO,IAAI,IAAI;CAMhB;AAMD,qBAAa,iBAAiB;IAC5B,SAAS,EAAE,QAAQ,CAAC;IACpB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,aAAa,EAAE,cAAc,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC;IACrD,YAAY,EAAE,WAAW,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;gBAG5B,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,oBAAoB,EAC5B,KAAK,EAAE,OAAO,EAAE,EAChB,oBAAoB,CAAC,EAAE,SAAS,EAAE,EAClC,cAAc,CAAC,EAAE,MAAM,EACvB,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM;IAmD3C,OAAO,CACL,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GACxC,IAAI;IAgBP,QAAQ,IAAI,OAAO,EAAE;IAQrB,WAAW,IAAI,OAAO,EAAE;IAIxB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO;IAezC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAe5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,KAAK,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAiC9B,MAAM,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAW/B,OAAO,CAAC,UAAU;CASnB;AAMD,qBAAa,iBAAiB;IAC5B,SAAS,EAAE,QAAQ,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,EAAE,WAAW,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,SAAS,CAA+C;IAChE,OAAO,CAAC,SAAS,CAA+C;gBAG9D,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,oBAAoB,EAC5B,YAAY,EAAE,OAAO,EACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,EACtD,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,EACtD,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO;IAaxD,OAAO,CACL,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GACxC,IAAI;IAmBP,QAAQ,IAAI,OAAO;IAKnB,WAAW,IAAI,OAAO;IAItB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAO3B,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;CAI9B;AAMD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,eAAe,EACvB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,oBAAoB,EAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,WAAW,GACvB,qBAAqB,CAkEvB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACjD,MAAM,EAAE,oBAAoB,EAC5B,WAAW,EAAE,WAAW,EACxB,UAAU,GAAE,OAAe,GAC1B,IAAI,CAsCN"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReactiveTask } from 'signalium';
|
|
2
|
+
import { type QueryClient } from './QueryClient.js';
|
|
3
|
+
import { MutationDefinition } from './mutation.js';
|
|
4
|
+
/**
|
|
5
|
+
* Internal mutation manager. Consumers interact with the public `task` property,
|
|
6
|
+
* which is a standard ReactiveTask whose resolved value is the validated response.
|
|
7
|
+
*
|
|
8
|
+
* Mutations use Phase 1 only (parseData) for response validation. Entity store
|
|
9
|
+
* updates are handled exclusively through effects (creates/updates/deletes).
|
|
10
|
+
*/
|
|
11
|
+
export declare class MutationResultImpl<Request, Result> {
|
|
12
|
+
def: MutationDefinition<Request, Result>;
|
|
13
|
+
private queryClient;
|
|
14
|
+
private _inFlight;
|
|
15
|
+
readonly task: ReactiveTask<Result, [Request]>;
|
|
16
|
+
constructor(def: MutationDefinition<Request, Result>, queryClient: QueryClient);
|
|
17
|
+
private createTask;
|
|
18
|
+
private validateResponse;
|
|
19
|
+
private processEffects;
|
|
20
|
+
private executeWithRetry;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=MutationResult.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MutationResult.d.ts","sourceRoot":"","sources":["../../src/MutationResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAGpD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAOnD;;;;;;GAMG;AACH,qBAAa,kBAAkB,CAAC,OAAO,EAAE,MAAM;IAC7C,GAAG,EAAE,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAAkB;IAEnC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;gBAEnC,GAAG,EAAE,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,WAAW;IAM9E,OAAO,CAAC,UAAU;IAuBlB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,cAAc;IAgCtB,OAAO,CAAC,gBAAgB;CAsBzB"}
|