@tanstack/db 0.4.9 → 0.4.11
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/dist/cjs/collection/events.cjs +9 -51
- package/dist/cjs/collection/events.cjs.map +1 -1
- package/dist/cjs/collection/events.d.cts +18 -7
- package/dist/cjs/collection/index.cjs +9 -12
- package/dist/cjs/collection/index.cjs.map +1 -1
- package/dist/cjs/collection/index.d.cts +13 -14
- package/dist/cjs/collection/subscription.cjs +62 -6
- package/dist/cjs/collection/subscription.cjs.map +1 -1
- package/dist/cjs/collection/subscription.d.cts +16 -3
- package/dist/cjs/collection/sync.cjs +58 -6
- package/dist/cjs/collection/sync.cjs.map +1 -1
- package/dist/cjs/collection/sync.d.cts +18 -4
- package/dist/cjs/errors.cjs +8 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +6 -0
- package/dist/cjs/event-emitter.cjs +94 -0
- package/dist/cjs/event-emitter.cjs.map +1 -0
- package/dist/cjs/event-emitter.d.cts +45 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/local-only.d.cts +2 -5
- package/dist/cjs/query/compiler/index.cjs +6 -2
- package/dist/cjs/query/compiler/index.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.d.cts +3 -2
- package/dist/cjs/query/compiler/joins.cjs +6 -3
- package/dist/cjs/query/compiler/joins.cjs.map +1 -1
- package/dist/cjs/query/compiler/joins.d.cts +2 -2
- package/dist/cjs/query/compiler/order-by.cjs +18 -4
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +2 -1
- package/dist/cjs/query/compiler/types.d.cts +4 -0
- package/dist/cjs/query/index.d.cts +1 -0
- package/dist/cjs/query/live/collection-config-builder.cjs +43 -6
- package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
- package/dist/cjs/query/live/collection-config-builder.d.cts +27 -1
- package/dist/cjs/query/live/collection-subscriber.cjs +29 -0
- package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
- package/dist/cjs/query/live/collection-subscriber.d.cts +1 -0
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/query/live-query-collection.d.cts +2 -2
- package/dist/cjs/types.d.cts +82 -11
- package/dist/esm/collection/events.d.ts +18 -7
- package/dist/esm/collection/events.js +9 -51
- package/dist/esm/collection/events.js.map +1 -1
- package/dist/esm/collection/index.d.ts +13 -14
- package/dist/esm/collection/index.js +9 -12
- package/dist/esm/collection/index.js.map +1 -1
- package/dist/esm/collection/subscription.d.ts +16 -3
- package/dist/esm/collection/subscription.js +62 -6
- package/dist/esm/collection/subscription.js.map +1 -1
- package/dist/esm/collection/sync.d.ts +18 -4
- package/dist/esm/collection/sync.js +59 -7
- package/dist/esm/collection/sync.js.map +1 -1
- package/dist/esm/errors.d.ts +6 -0
- package/dist/esm/errors.js +8 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/event-emitter.d.ts +45 -0
- package/dist/esm/event-emitter.js +94 -0
- package/dist/esm/event-emitter.js.map +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/local-only.d.ts +2 -5
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/query/compiler/index.d.ts +3 -2
- package/dist/esm/query/compiler/index.js +6 -2
- package/dist/esm/query/compiler/index.js.map +1 -1
- package/dist/esm/query/compiler/joins.d.ts +2 -2
- package/dist/esm/query/compiler/joins.js +6 -3
- package/dist/esm/query/compiler/joins.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +2 -1
- package/dist/esm/query/compiler/order-by.js +18 -4
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/compiler/types.d.ts +4 -0
- package/dist/esm/query/index.d.ts +1 -0
- package/dist/esm/query/live/collection-config-builder.d.ts +27 -1
- package/dist/esm/query/live/collection-config-builder.js +44 -7
- package/dist/esm/query/live/collection-config-builder.js.map +1 -1
- package/dist/esm/query/live/collection-subscriber.d.ts +1 -0
- package/dist/esm/query/live/collection-subscriber.js +29 -0
- package/dist/esm/query/live/collection-subscriber.js.map +1 -1
- package/dist/esm/query/live-query-collection.d.ts +2 -2
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/types.d.ts +82 -11
- package/package.json +2 -2
- package/src/collection/events.ts +25 -74
- package/src/collection/index.ts +15 -19
- package/src/collection/subscription.ts +88 -6
- package/src/collection/sync.ts +81 -9
- package/src/errors.ts +12 -0
- package/src/event-emitter.ts +118 -0
- package/src/local-only.ts +5 -12
- package/src/query/compiler/index.ts +9 -1
- package/src/query/compiler/joins.ts +7 -1
- package/src/query/compiler/order-by.ts +23 -2
- package/src/query/compiler/types.ts +5 -0
- package/src/query/index.ts +1 -0
- package/src/query/live/collection-config-builder.ts +76 -7
- package/src/query/live/collection-subscriber.ts +50 -0
- package/src/query/live-query-collection.ts +8 -4
- package/src/types.ts +93 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-query-collection.cjs","sources":["../../../src/query/live-query-collection.ts"],"sourcesContent":["import { createCollection } from \"../collection/index.js\"\nimport { CollectionConfigBuilder } from \"./live/collection-config-builder.js\"\nimport {\n getBuilderFromConfig,\n registerCollectionBuilder,\n} from \"./live/collection-registry.js\"\nimport type { LiveQueryCollectionUtils } from \"./live/collection-config-builder.js\"\nimport type { LiveQueryCollectionConfig } from \"./live/types.js\"\nimport type { InitialQueryBuilder, QueryBuilder } from \"./builder/index.js\"\nimport type { Collection } from \"../collection/index.js\"\nimport type {\n CollectionConfig,\n CollectionConfigSingleRowOption,\n NonSingleResult,\n SingleResult,\n UtilsRecord,\n} from \"../types.js\"\nimport type { Context, GetResult } from \"./builder/types.js\"\n\ntype CollectionConfigForContext<\n TContext extends Context,\n TResult extends object,\n> = TContext extends SingleResult\n ? CollectionConfigSingleRowOption<TResult>
|
|
1
|
+
{"version":3,"file":"live-query-collection.cjs","sources":["../../../src/query/live-query-collection.ts"],"sourcesContent":["import { createCollection } from \"../collection/index.js\"\nimport { CollectionConfigBuilder } from \"./live/collection-config-builder.js\"\nimport {\n getBuilderFromConfig,\n registerCollectionBuilder,\n} from \"./live/collection-registry.js\"\nimport type { LiveQueryCollectionUtils } from \"./live/collection-config-builder.js\"\nimport type { LiveQueryCollectionConfig } from \"./live/types.js\"\nimport type { InitialQueryBuilder, QueryBuilder } from \"./builder/index.js\"\nimport type { Collection } from \"../collection/index.js\"\nimport type {\n CollectionConfig,\n CollectionConfigSingleRowOption,\n NonSingleResult,\n SingleResult,\n UtilsRecord,\n} from \"../types.js\"\nimport type { Context, GetResult } from \"./builder/types.js\"\n\ntype CollectionConfigForContext<\n TContext extends Context,\n TResult extends object,\n TUtils extends UtilsRecord = {},\n> = TContext extends SingleResult\n ? CollectionConfigSingleRowOption<TResult, string | number, never, TUtils> &\n SingleResult\n : CollectionConfigSingleRowOption<TResult, string | number, never, TUtils> &\n NonSingleResult\n\ntype CollectionForContext<\n TContext extends Context,\n TResult extends object,\n TUtils extends UtilsRecord = {},\n> = TContext extends SingleResult\n ? Collection<TResult, string | number, TUtils> & SingleResult\n : Collection<TResult, string | number, TUtils> & NonSingleResult\n\n/**\n * Creates live query collection options for use with createCollection\n *\n * @example\n * ```typescript\n * const options = liveQueryCollectionOptions({\n * // id is optional - will auto-generate if not provided\n * query: (q) => q\n * .from({ post: postsCollection })\n * .where(({ post }) => eq(post.published, true))\n * .select(({ post }) => ({\n * id: post.id,\n * title: post.title,\n * content: post.content,\n * })),\n * // getKey is optional - will use stream key if not provided\n * })\n *\n * const collection = createCollection(options)\n * ```\n *\n * @param config - Configuration options for the live query collection\n * @returns Collection options that can be passed to createCollection\n */\nexport function liveQueryCollectionOptions<\n TContext extends Context,\n TResult extends object = GetResult<TContext>,\n>(\n config: LiveQueryCollectionConfig<TContext, TResult>\n): CollectionConfigForContext<TContext, TResult> & {\n utils: LiveQueryCollectionUtils\n} {\n const collectionConfigBuilder = new CollectionConfigBuilder<\n TContext,\n TResult\n >(config)\n return collectionConfigBuilder.getConfig() as CollectionConfigForContext<\n TContext,\n TResult\n > & { utils: LiveQueryCollectionUtils }\n}\n\n/**\n * Creates a live query collection directly\n *\n * @example\n * ```typescript\n * // Minimal usage - just pass a query function\n * const activeUsers = createLiveQueryCollection(\n * (q) => q\n * .from({ user: usersCollection })\n * .where(({ user }) => eq(user.active, true))\n * .select(({ user }) => ({ id: user.id, name: user.name }))\n * )\n *\n * // Full configuration with custom options\n * const searchResults = createLiveQueryCollection({\n * id: \"search-results\", // Custom ID (auto-generated if omitted)\n * query: (q) => q\n * .from({ post: postsCollection })\n * .where(({ post }) => like(post.title, `%${searchTerm}%`))\n * .select(({ post }) => ({\n * id: post.id,\n * title: post.title,\n * excerpt: post.excerpt,\n * })),\n * getKey: (item) => item.id, // Custom key function (uses stream key if omitted)\n * utils: {\n * updateSearchTerm: (newTerm: string) => {\n * // Custom utility functions\n * }\n * }\n * })\n * ```\n */\n\n// Overload 1: Accept just the query function\nexport function createLiveQueryCollection<\n TContext extends Context,\n TResult extends object = GetResult<TContext>,\n>(\n query: (q: InitialQueryBuilder) => QueryBuilder<TContext>\n): CollectionForContext<TContext, TResult> & {\n utils: LiveQueryCollectionUtils\n}\n\n// Overload 2: Accept full config object with optional utilities\nexport function createLiveQueryCollection<\n TContext extends Context,\n TResult extends object = GetResult<TContext>,\n TUtils extends UtilsRecord = {},\n>(\n config: LiveQueryCollectionConfig<TContext, TResult> & { utils?: TUtils }\n): CollectionForContext<TContext, TResult> & {\n utils: LiveQueryCollectionUtils & TUtils\n}\n\n// Implementation\nexport function createLiveQueryCollection<\n TContext extends Context,\n TResult extends object = GetResult<TContext>,\n TUtils extends UtilsRecord = {},\n>(\n configOrQuery:\n | (LiveQueryCollectionConfig<TContext, TResult> & { utils?: TUtils })\n | ((q: InitialQueryBuilder) => QueryBuilder<TContext>)\n): CollectionForContext<TContext, TResult> & {\n utils: LiveQueryCollectionUtils & TUtils\n} {\n // Determine if the argument is a function (query) or a config object\n if (typeof configOrQuery === `function`) {\n // Simple query function case\n const config: LiveQueryCollectionConfig<TContext, TResult> = {\n query: configOrQuery as (\n q: InitialQueryBuilder\n ) => QueryBuilder<TContext>,\n }\n const options = liveQueryCollectionOptions<TContext, TResult>(config)\n return bridgeToCreateCollection(options) as CollectionForContext<\n TContext,\n TResult\n > & { utils: LiveQueryCollectionUtils & TUtils }\n } else {\n // Config object case\n const config = configOrQuery as LiveQueryCollectionConfig<\n TContext,\n TResult\n > & { utils?: TUtils }\n const options = liveQueryCollectionOptions<TContext, TResult>(config)\n\n // Merge custom utils if provided, preserving the getBuilder() method for dependency tracking\n if (config.utils) {\n options.utils = { ...options.utils, ...config.utils }\n }\n\n return bridgeToCreateCollection(options) as CollectionForContext<\n TContext,\n TResult\n > & { utils: LiveQueryCollectionUtils & TUtils }\n }\n}\n\n/**\n * Bridge function that handles the type compatibility between query2's TResult\n * and core collection's output type without exposing ugly type assertions to users\n */\nfunction bridgeToCreateCollection<\n TResult extends object,\n TUtils extends UtilsRecord = {},\n>(\n options: CollectionConfig<TResult> & { utils: TUtils }\n): Collection<TResult, string | number, TUtils> {\n const collection = createCollection(options as any) as unknown as Collection<\n TResult,\n string | number,\n LiveQueryCollectionUtils\n >\n\n const builder = getBuilderFromConfig(options)\n if (builder) {\n registerCollectionBuilder(collection, builder)\n }\n\n return collection as unknown as Collection<TResult, string | number, TUtils>\n}\n"],"names":["collectionConfigBuilder","CollectionConfigBuilder","createCollection","getBuilderFromConfig","registerCollectionBuilder"],"mappings":";;;;;AA6DO,SAAS,2BAId,QAGA;AACA,QAAMA,4BAA0B,IAAIC,wBAAAA,wBAGlC,MAAM;AACR,SAAOD,0BAAwB,UAAA;AAIjC;AA0DO,SAAS,0BAKd,eAKA;AAEA,MAAI,OAAO,kBAAkB,YAAY;AAEvC,UAAM,SAAuD;AAAA,MAC3D,OAAO;AAAA,IAAA;AAIT,UAAM,UAAU,2BAA8C,MAAM;AACpE,WAAO,yBAAyB,OAAO;AAAA,EAIzC,OAAO;AAEL,UAAM,SAAS;AAIf,UAAM,UAAU,2BAA8C,MAAM;AAGpE,QAAI,OAAO,OAAO;AAChB,cAAQ,QAAQ,EAAE,GAAG,QAAQ,OAAO,GAAG,OAAO,MAAA;AAAA,IAChD;AAEA,WAAO,yBAAyB,OAAO;AAAA,EAIzC;AACF;AAMA,SAAS,yBAIP,SAC8C;AAC9C,QAAM,aAAaE,MAAAA,iBAAiB,OAAc;AAMlD,QAAM,UAAUC,mBAAAA,qBAAqB,OAAO;AAC5C,MAAI,SAAS;AACXC,uBAAAA,0BAA0B,YAAY,OAAO;AAAA,EAC/C;AAEA,SAAO;AACT;;;"}
|
|
@@ -4,8 +4,8 @@ import { InitialQueryBuilder, QueryBuilder } from './builder/index.js';
|
|
|
4
4
|
import { Collection } from '../collection/index.js';
|
|
5
5
|
import { CollectionConfigSingleRowOption, NonSingleResult, SingleResult, UtilsRecord } from '../types.js';
|
|
6
6
|
import { Context, GetResult } from './builder/types.js';
|
|
7
|
-
type CollectionConfigForContext<TContext extends Context, TResult extends object> = TContext extends SingleResult ? CollectionConfigSingleRowOption<TResult> & SingleResult : CollectionConfigSingleRowOption<TResult> & NonSingleResult;
|
|
8
|
-
type CollectionForContext<TContext extends Context, TResult extends object> = TContext extends SingleResult ? Collection<TResult> & SingleResult : Collection<TResult> & NonSingleResult;
|
|
7
|
+
type CollectionConfigForContext<TContext extends Context, TResult extends object, TUtils extends UtilsRecord = {}> = TContext extends SingleResult ? CollectionConfigSingleRowOption<TResult, string | number, never, TUtils> & SingleResult : CollectionConfigSingleRowOption<TResult, string | number, never, TUtils> & NonSingleResult;
|
|
8
|
+
type CollectionForContext<TContext extends Context, TResult extends object, TUtils extends UtilsRecord = {}> = TContext extends SingleResult ? Collection<TResult, string | number, TUtils> & SingleResult : Collection<TResult, string | number, TUtils> & NonSingleResult;
|
|
9
9
|
/**
|
|
10
10
|
* Creates live query collection options for use with createCollection
|
|
11
11
|
*
|
package/dist/cjs/types.d.cts
CHANGED
|
@@ -3,6 +3,7 @@ import { Collection } from './collection/index.js';
|
|
|
3
3
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
4
4
|
import { Transaction } from './transactions.cjs';
|
|
5
5
|
import { BasicExpression, OrderBy } from './query/ir.js';
|
|
6
|
+
import { EventEmitter } from './event-emitter.js';
|
|
6
7
|
/**
|
|
7
8
|
* Helper type to extract the output type from a standard schema
|
|
8
9
|
*
|
|
@@ -92,15 +93,74 @@ type Value<TExtensions = never> = string | number | boolean | bigint | null | TE
|
|
|
92
93
|
};
|
|
93
94
|
export type Row<TExtensions = never> = Record<string, Value<TExtensions>>;
|
|
94
95
|
export type OperationType = `insert` | `update` | `delete`;
|
|
95
|
-
|
|
96
|
+
/**
|
|
97
|
+
* Subscription status values
|
|
98
|
+
*/
|
|
99
|
+
export type SubscriptionStatus = `ready` | `loadingSubset`;
|
|
100
|
+
/**
|
|
101
|
+
* Event emitted when subscription status changes
|
|
102
|
+
*/
|
|
103
|
+
export interface SubscriptionStatusChangeEvent {
|
|
104
|
+
type: `status:change`;
|
|
105
|
+
subscription: Subscription;
|
|
106
|
+
previousStatus: SubscriptionStatus;
|
|
107
|
+
status: SubscriptionStatus;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Event emitted when subscription status changes to a specific status
|
|
111
|
+
*/
|
|
112
|
+
export interface SubscriptionStatusEvent<T extends SubscriptionStatus> {
|
|
113
|
+
type: `status:${T}`;
|
|
114
|
+
subscription: Subscription;
|
|
115
|
+
previousStatus: SubscriptionStatus;
|
|
116
|
+
status: T;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Event emitted when subscription is unsubscribed
|
|
120
|
+
*/
|
|
121
|
+
export interface SubscriptionUnsubscribedEvent {
|
|
122
|
+
type: `unsubscribed`;
|
|
123
|
+
subscription: Subscription;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* All subscription events
|
|
127
|
+
*/
|
|
128
|
+
export type SubscriptionEvents = {
|
|
129
|
+
"status:change": SubscriptionStatusChangeEvent;
|
|
130
|
+
"status:ready": SubscriptionStatusEvent<`ready`>;
|
|
131
|
+
"status:loadingSubset": SubscriptionStatusEvent<`loadingSubset`>;
|
|
132
|
+
unsubscribed: SubscriptionUnsubscribedEvent;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Public interface for a collection subscription
|
|
136
|
+
* Used by sync implementations to track subscription lifecycle
|
|
137
|
+
*/
|
|
138
|
+
export interface Subscription extends EventEmitter<SubscriptionEvents> {
|
|
139
|
+
/** Current status of the subscription */
|
|
140
|
+
readonly status: SubscriptionStatus;
|
|
141
|
+
}
|
|
142
|
+
export type LoadSubsetOptions = {
|
|
143
|
+
/** The where expression to filter the data */
|
|
96
144
|
where?: BasicExpression<boolean>;
|
|
145
|
+
/** The order by clause to sort the data */
|
|
97
146
|
orderBy?: OrderBy;
|
|
147
|
+
/** The limit of the data to load */
|
|
98
148
|
limit?: number;
|
|
149
|
+
/**
|
|
150
|
+
* The subscription that triggered the load.
|
|
151
|
+
* Advanced sync implementations can use this for:
|
|
152
|
+
* - LRU caching keyed by subscription
|
|
153
|
+
* - Reference counting to track active subscriptions
|
|
154
|
+
* - Subscribing to subscription events (e.g., finalization/unsubscribe)
|
|
155
|
+
* @optional Available when called from CollectionSubscription, may be undefined for direct calls
|
|
156
|
+
*/
|
|
157
|
+
subscription?: Subscription;
|
|
99
158
|
};
|
|
159
|
+
export type LoadSubsetFn = (options: LoadSubsetOptions) => true | Promise<void>;
|
|
100
160
|
export type CleanupFn = () => void;
|
|
101
161
|
export type SyncConfigRes = {
|
|
102
162
|
cleanup?: CleanupFn;
|
|
103
|
-
|
|
163
|
+
loadSubset?: LoadSubsetFn;
|
|
104
164
|
};
|
|
105
165
|
export interface SyncConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number> {
|
|
106
166
|
sync: (params: {
|
|
@@ -161,21 +221,21 @@ export interface InsertConfig {
|
|
|
161
221
|
/** Whether to apply optimistic updates immediately. Defaults to true. */
|
|
162
222
|
optimistic?: boolean;
|
|
163
223
|
}
|
|
164
|
-
export type UpdateMutationFnParams<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
224
|
+
export type UpdateMutationFnParams<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord> = {
|
|
165
225
|
transaction: TransactionWithMutations<T, `update`>;
|
|
166
226
|
collection: Collection<T, TKey, TUtils>;
|
|
167
227
|
};
|
|
168
|
-
export type InsertMutationFnParams<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
228
|
+
export type InsertMutationFnParams<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord> = {
|
|
169
229
|
transaction: TransactionWithMutations<T, `insert`>;
|
|
170
230
|
collection: Collection<T, TKey, TUtils>;
|
|
171
231
|
};
|
|
172
|
-
export type DeleteMutationFnParams<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
232
|
+
export type DeleteMutationFnParams<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord> = {
|
|
173
233
|
transaction: TransactionWithMutations<T, `delete`>;
|
|
174
234
|
collection: Collection<T, TKey, TUtils>;
|
|
175
235
|
};
|
|
176
|
-
export type InsertMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
177
|
-
export type UpdateMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
178
|
-
export type DeleteMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
236
|
+
export type InsertMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord, TReturn = any> = (params: InsertMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>;
|
|
237
|
+
export type UpdateMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord, TReturn = any> = (params: UpdateMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>;
|
|
238
|
+
export type DeleteMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord, TReturn = any> = (params: DeleteMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>;
|
|
179
239
|
/**
|
|
180
240
|
* Collection status values for lifecycle management
|
|
181
241
|
* @example
|
|
@@ -202,7 +262,8 @@ export type CollectionStatus =
|
|
|
202
262
|
| `error`
|
|
203
263
|
/** Collection has been cleaned up and resources freed */
|
|
204
264
|
| `cleaned-up`;
|
|
205
|
-
export
|
|
265
|
+
export type SyncMode = `eager` | `on-demand`;
|
|
266
|
+
export interface BaseCollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never, TUtils extends UtilsRecord = UtilsRecord, TReturn = any> {
|
|
206
267
|
id?: string;
|
|
207
268
|
schema?: TSchema;
|
|
208
269
|
/**
|
|
@@ -251,6 +312,15 @@ export interface BaseCollectionConfig<T extends object = Record<string, unknown>
|
|
|
251
312
|
* compare: (x, y) => x.createdAt.getTime() - y.createdAt.getTime()
|
|
252
313
|
*/
|
|
253
314
|
compare?: (x: T, y: T) => number;
|
|
315
|
+
/**
|
|
316
|
+
* The mode of sync to use for the collection.
|
|
317
|
+
* @default `eager`
|
|
318
|
+
* @description
|
|
319
|
+
* - `eager`: syncs all data immediately on preload
|
|
320
|
+
* - `on-demand`: syncs data in incremental snapshots when the collection is queried
|
|
321
|
+
* The exact implementation of the sync mode is up to the sync implementation.
|
|
322
|
+
*/
|
|
323
|
+
syncMode?: SyncMode;
|
|
254
324
|
/**
|
|
255
325
|
* Optional asynchronous handler function called before an insert operation
|
|
256
326
|
* @param params Object containing transaction and collection information
|
|
@@ -379,8 +449,9 @@ export interface BaseCollectionConfig<T extends object = Record<string, unknown>
|
|
|
379
449
|
* }
|
|
380
450
|
*/
|
|
381
451
|
onDelete?: DeleteMutationFn<T, TKey, TUtils, TReturn>;
|
|
452
|
+
utils?: TUtils;
|
|
382
453
|
}
|
|
383
|
-
export interface CollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never> extends BaseCollectionConfig<T, TKey, TSchema> {
|
|
454
|
+
export interface CollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never, TUtils extends UtilsRecord = UtilsRecord> extends BaseCollectionConfig<T, TKey, TSchema, TUtils> {
|
|
384
455
|
sync: SyncConfig<T, TKey>;
|
|
385
456
|
}
|
|
386
457
|
export type SingleResult = {
|
|
@@ -395,7 +466,7 @@ export type MaybeSingleResult = {
|
|
|
395
466
|
*/
|
|
396
467
|
singleResult?: true;
|
|
397
468
|
};
|
|
398
|
-
export type CollectionConfigSingleRowOption<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never> = CollectionConfig<T, TKey, TSchema> & MaybeSingleResult;
|
|
469
|
+
export type CollectionConfigSingleRowOption<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never, TUtils extends UtilsRecord = {}> = CollectionConfig<T, TKey, TSchema, TUtils> & MaybeSingleResult;
|
|
399
470
|
export type ChangesPayload<T extends object = Record<string, unknown>> = Array<ChangeMessage<T>>;
|
|
400
471
|
/**
|
|
401
472
|
* An input row from a collection
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EventEmitter } from '../event-emitter.js';
|
|
1
2
|
import { Collection } from './index.js';
|
|
2
3
|
import { CollectionStatus } from '../types.js';
|
|
3
4
|
/**
|
|
@@ -27,25 +28,35 @@ export interface CollectionSubscribersChangeEvent {
|
|
|
27
28
|
previousSubscriberCount: number;
|
|
28
29
|
subscriberCount: number;
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Event emitted when the collection's loading more state changes
|
|
33
|
+
*/
|
|
34
|
+
export interface CollectionLoadingSubsetChangeEvent {
|
|
35
|
+
type: `loadingSubset:change`;
|
|
36
|
+
collection: Collection<any, any, any, any, any>;
|
|
37
|
+
isLoadingSubset: boolean;
|
|
38
|
+
previousIsLoadingSubset: boolean;
|
|
39
|
+
loadingSubsetTransition: `start` | `end`;
|
|
40
|
+
}
|
|
30
41
|
export type AllCollectionEvents = {
|
|
31
42
|
"status:change": CollectionStatusChangeEvent;
|
|
32
43
|
"subscribers:change": CollectionSubscribersChangeEvent;
|
|
44
|
+
"loadingSubset:change": CollectionLoadingSubsetChangeEvent;
|
|
33
45
|
} & {
|
|
34
46
|
[K in CollectionStatus as `status:${K}`]: CollectionStatusEvent<K>;
|
|
35
47
|
};
|
|
36
|
-
export type CollectionEvent = AllCollectionEvents[keyof AllCollectionEvents] | CollectionStatusChangeEvent | CollectionSubscribersChangeEvent;
|
|
48
|
+
export type CollectionEvent = AllCollectionEvents[keyof AllCollectionEvents] | CollectionStatusChangeEvent | CollectionSubscribersChangeEvent | CollectionLoadingSubsetChangeEvent;
|
|
37
49
|
export type CollectionEventHandler<T extends keyof AllCollectionEvents> = (event: AllCollectionEvents[T]) => void;
|
|
38
|
-
export declare class CollectionEventsManager {
|
|
50
|
+
export declare class CollectionEventsManager extends EventEmitter<AllCollectionEvents> {
|
|
39
51
|
private collection;
|
|
40
|
-
private listeners;
|
|
41
52
|
constructor();
|
|
42
53
|
setDeps(deps: {
|
|
43
54
|
collection: Collection<any, any, any, any, any>;
|
|
44
55
|
}): void;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Emit an event to all listeners
|
|
58
|
+
* Public API for emitting collection events
|
|
59
|
+
*/
|
|
49
60
|
emit<T extends keyof AllCollectionEvents>(event: T, eventPayload: AllCollectionEvents[T]): void;
|
|
50
61
|
emitStatusChange<T extends CollectionStatus>(status: T, previousStatus: CollectionStatus): void;
|
|
51
62
|
emitSubscribersChange(subscriberCount: number, previousSubscriberCount: number): void;
|
|
@@ -1,59 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { EventEmitter } from "../event-emitter.js";
|
|
2
|
+
class CollectionEventsManager extends EventEmitter {
|
|
2
3
|
constructor() {
|
|
3
|
-
|
|
4
|
+
super();
|
|
4
5
|
}
|
|
5
6
|
setDeps(deps) {
|
|
6
7
|
this.collection = deps.collection;
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this.listeners.get(event).add(callback);
|
|
13
|
-
return () => {
|
|
14
|
-
this.listeners.get(event)?.delete(callback);
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
once(event, callback) {
|
|
18
|
-
const unsubscribe = this.on(event, (eventPayload) => {
|
|
19
|
-
callback(eventPayload);
|
|
20
|
-
unsubscribe();
|
|
21
|
-
});
|
|
22
|
-
return unsubscribe;
|
|
23
|
-
}
|
|
24
|
-
off(event, callback) {
|
|
25
|
-
this.listeners.get(event)?.delete(callback);
|
|
26
|
-
}
|
|
27
|
-
waitFor(event, timeout) {
|
|
28
|
-
return new Promise((resolve, reject) => {
|
|
29
|
-
let timeoutId;
|
|
30
|
-
const unsubscribe = this.on(event, (eventPayload) => {
|
|
31
|
-
if (timeoutId) {
|
|
32
|
-
clearTimeout(timeoutId);
|
|
33
|
-
timeoutId = void 0;
|
|
34
|
-
}
|
|
35
|
-
resolve(eventPayload);
|
|
36
|
-
unsubscribe();
|
|
37
|
-
});
|
|
38
|
-
if (timeout) {
|
|
39
|
-
timeoutId = setTimeout(() => {
|
|
40
|
-
timeoutId = void 0;
|
|
41
|
-
unsubscribe();
|
|
42
|
-
reject(new Error(`Timeout waiting for event ${event}`));
|
|
43
|
-
}, timeout);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
}
|
|
9
|
+
/**
|
|
10
|
+
* Emit an event to all listeners
|
|
11
|
+
* Public API for emitting collection events
|
|
12
|
+
*/
|
|
47
13
|
emit(event, eventPayload) {
|
|
48
|
-
this.
|
|
49
|
-
try {
|
|
50
|
-
listener(eventPayload);
|
|
51
|
-
} catch (error) {
|
|
52
|
-
queueMicrotask(() => {
|
|
53
|
-
throw error;
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
});
|
|
14
|
+
this.emitInner(event, eventPayload);
|
|
57
15
|
}
|
|
58
16
|
emitStatusChange(status, previousStatus) {
|
|
59
17
|
this.emit(`status:change`, {
|
|
@@ -79,7 +37,7 @@ class CollectionEventsManager {
|
|
|
79
37
|
});
|
|
80
38
|
}
|
|
81
39
|
cleanup() {
|
|
82
|
-
this.
|
|
40
|
+
this.clearListeners();
|
|
83
41
|
}
|
|
84
42
|
}
|
|
85
43
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sources":["../../../src/collection/events.ts"],"sourcesContent":["import type { Collection } from \"./index.js\"\nimport type { CollectionStatus } from \"../types.js\"\n\n/**\n * Event emitted when the collection status changes\n */\nexport interface CollectionStatusChangeEvent {\n type: `status:change`\n collection: Collection\n previousStatus: CollectionStatus\n status: CollectionStatus\n}\n\n/**\n * Event emitted when the collection status changes to a specific status\n */\nexport interface CollectionStatusEvent<T extends CollectionStatus> {\n type: `status:${T}`\n collection: Collection\n previousStatus: CollectionStatus\n status: T\n}\n\n/**\n * Event emitted when the number of subscribers to the collection changes\n */\nexport interface CollectionSubscribersChangeEvent {\n type: `subscribers:change`\n collection: Collection\n previousSubscriberCount: number\n subscriberCount: number\n}\n\nexport type AllCollectionEvents = {\n \"status:change\": CollectionStatusChangeEvent\n \"subscribers:change\": CollectionSubscribersChangeEvent\n} & {\n [K in CollectionStatus as `status:${K}`]: CollectionStatusEvent<K>\n}\n\nexport type CollectionEvent =\n | AllCollectionEvents[keyof AllCollectionEvents]\n | CollectionStatusChangeEvent\n | CollectionSubscribersChangeEvent\n\nexport type CollectionEventHandler<T extends keyof AllCollectionEvents> = (\n event: AllCollectionEvents[T]\n) => void\n\nexport class CollectionEventsManager {\n private collection!: Collection<any, any, any, any, any>\n
|
|
1
|
+
{"version":3,"file":"events.js","sources":["../../../src/collection/events.ts"],"sourcesContent":["import { EventEmitter } from \"../event-emitter.js\"\nimport type { Collection } from \"./index.js\"\nimport type { CollectionStatus } from \"../types.js\"\n\n/**\n * Event emitted when the collection status changes\n */\nexport interface CollectionStatusChangeEvent {\n type: `status:change`\n collection: Collection\n previousStatus: CollectionStatus\n status: CollectionStatus\n}\n\n/**\n * Event emitted when the collection status changes to a specific status\n */\nexport interface CollectionStatusEvent<T extends CollectionStatus> {\n type: `status:${T}`\n collection: Collection\n previousStatus: CollectionStatus\n status: T\n}\n\n/**\n * Event emitted when the number of subscribers to the collection changes\n */\nexport interface CollectionSubscribersChangeEvent {\n type: `subscribers:change`\n collection: Collection\n previousSubscriberCount: number\n subscriberCount: number\n}\n\n/**\n * Event emitted when the collection's loading more state changes\n */\nexport interface CollectionLoadingSubsetChangeEvent {\n type: `loadingSubset:change`\n collection: Collection<any, any, any, any, any>\n isLoadingSubset: boolean\n previousIsLoadingSubset: boolean\n loadingSubsetTransition: `start` | `end`\n}\n\nexport type AllCollectionEvents = {\n \"status:change\": CollectionStatusChangeEvent\n \"subscribers:change\": CollectionSubscribersChangeEvent\n \"loadingSubset:change\": CollectionLoadingSubsetChangeEvent\n} & {\n [K in CollectionStatus as `status:${K}`]: CollectionStatusEvent<K>\n}\n\nexport type CollectionEvent =\n | AllCollectionEvents[keyof AllCollectionEvents]\n | CollectionStatusChangeEvent\n | CollectionSubscribersChangeEvent\n | CollectionLoadingSubsetChangeEvent\n\nexport type CollectionEventHandler<T extends keyof AllCollectionEvents> = (\n event: AllCollectionEvents[T]\n) => void\n\nexport class CollectionEventsManager extends EventEmitter<AllCollectionEvents> {\n private collection!: Collection<any, any, any, any, any>\n\n constructor() {\n super()\n }\n\n setDeps(deps: { collection: Collection<any, any, any, any, any> }) {\n this.collection = deps.collection\n }\n\n /**\n * Emit an event to all listeners\n * Public API for emitting collection events\n */\n emit<T extends keyof AllCollectionEvents>(\n event: T,\n eventPayload: AllCollectionEvents[T]\n ): void {\n this.emitInner(event, eventPayload)\n }\n\n emitStatusChange<T extends CollectionStatus>(\n status: T,\n previousStatus: CollectionStatus\n ) {\n this.emit(`status:change`, {\n type: `status:change`,\n collection: this.collection,\n previousStatus,\n status,\n })\n\n // Emit specific status event using type assertion\n const eventKey: `status:${T}` = `status:${status}`\n this.emit(eventKey, {\n type: eventKey,\n collection: this.collection,\n previousStatus,\n status,\n } as AllCollectionEvents[`status:${T}`])\n }\n\n emitSubscribersChange(\n subscriberCount: number,\n previousSubscriberCount: number\n ) {\n this.emit(`subscribers:change`, {\n type: `subscribers:change`,\n collection: this.collection,\n previousSubscriberCount,\n subscriberCount,\n })\n }\n\n cleanup() {\n this.clearListeners()\n }\n}\n"],"names":[],"mappings":";AA+DO,MAAM,gCAAgC,aAAkC;AAAA,EAG7E,cAAc;AACZ,UAAA;AAAA,EACF;AAAA,EAEA,QAAQ,MAA2D;AACjE,SAAK,aAAa,KAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KACE,OACA,cACM;AACN,SAAK,UAAU,OAAO,YAAY;AAAA,EACpC;AAAA,EAEA,iBACE,QACA,gBACA;AACA,SAAK,KAAK,iBAAiB;AAAA,MACzB,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,CACD;AAGD,UAAM,WAA0B,UAAU,MAAM;AAChD,SAAK,KAAK,UAAU;AAAA,MAClB,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,CACqC;AAAA,EACzC;AAAA,EAEA,sBACE,iBACA,yBACA;AACA,SAAK,KAAK,sBAAsB;AAAA,MAC9B,MAAM;AAAA,MACN,YAAY,KAAK;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AAAA,EAEA,UAAU;AACR,SAAK,eAAA;AAAA,EACP;AACF;"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { CollectionStateManager } from './state.js';
|
|
2
2
|
import { CollectionLifecycleManager } from './lifecycle.js';
|
|
3
|
+
import { CollectionSyncManager } from './sync.js';
|
|
3
4
|
import { CollectionSubscription } from './subscription.js';
|
|
4
5
|
import { AllCollectionEvents, CollectionEventHandler } from './events.js';
|
|
5
6
|
import { BaseIndex, IndexResolver } from '../indexes/base-index.js';
|
|
6
7
|
import { IndexOptions } from '../indexes/index-options.js';
|
|
7
|
-
import { ChangeMessage, CollectionConfig, CollectionStatus, CurrentStateAsChangesOptions, Fn, InferSchemaInput, InferSchemaOutput, InsertConfig, NonSingleResult,
|
|
8
|
+
import { ChangeMessage, CollectionConfig, CollectionStatus, CurrentStateAsChangesOptions, Fn, InferSchemaInput, InferSchemaOutput, InsertConfig, NonSingleResult, OperationConfig, SingleResult, SubscribeChangesOptions, Transaction as TransactionType, UtilsRecord, WritableDeep } from '../types.js';
|
|
8
9
|
import { SingleRowRefProxy } from '../query/builder/ref-proxy.js';
|
|
9
10
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
10
11
|
import { BTreeIndex } from '../indexes/btree-index.js';
|
|
@@ -16,7 +17,7 @@ import { IndexProxy } from '../indexes/lazy-index.js';
|
|
|
16
17
|
* @template TUtils - The utilities record type
|
|
17
18
|
* @template TInsertInput - The type for insert operations (can be different from T for schemas with defaults)
|
|
18
19
|
*/
|
|
19
|
-
export interface Collection<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
20
|
+
export interface Collection<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInsertInput extends object = T> extends CollectionImpl<T, TKey, TUtils, TSchema, TInsertInput> {
|
|
20
21
|
readonly utils: TUtils;
|
|
21
22
|
readonly singleResult?: true;
|
|
22
23
|
}
|
|
@@ -90,19 +91,19 @@ export interface Collection<T extends object = Record<string, unknown>, TKey ext
|
|
|
90
91
|
* })
|
|
91
92
|
*
|
|
92
93
|
*/
|
|
93
|
-
export declare function createCollection<T extends StandardSchemaV1, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
94
|
+
export declare function createCollection<T extends StandardSchemaV1, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord>(options: CollectionConfig<InferSchemaOutput<T>, TKey, T> & {
|
|
94
95
|
schema: T;
|
|
95
96
|
utils?: TUtils;
|
|
96
97
|
} & NonSingleResult): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> & NonSingleResult;
|
|
97
|
-
export declare function createCollection<T extends StandardSchemaV1, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
98
|
+
export declare function createCollection<T extends StandardSchemaV1, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord>(options: CollectionConfig<InferSchemaOutput<T>, TKey, T> & {
|
|
98
99
|
schema: T;
|
|
99
100
|
utils?: TUtils;
|
|
100
101
|
} & SingleResult): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>> & SingleResult;
|
|
101
|
-
export declare function createCollection<T extends object, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
102
|
+
export declare function createCollection<T extends object, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord>(options: CollectionConfig<T, TKey, never> & {
|
|
102
103
|
schema?: never;
|
|
103
104
|
utils?: TUtils;
|
|
104
105
|
} & NonSingleResult): Collection<T, TKey, TUtils, never, T> & NonSingleResult;
|
|
105
|
-
export declare function createCollection<T extends object, TKey extends string | number = string | number, TUtils extends UtilsRecord =
|
|
106
|
+
export declare function createCollection<T extends object, TKey extends string | number = string | number, TUtils extends UtilsRecord = UtilsRecord>(options: CollectionConfig<T, TKey, never> & {
|
|
106
107
|
schema?: never;
|
|
107
108
|
utils?: TUtils;
|
|
108
109
|
} & SingleResult): Collection<T, TKey, TUtils, never, T> & SingleResult;
|
|
@@ -113,7 +114,7 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
113
114
|
private _events;
|
|
114
115
|
private _changes;
|
|
115
116
|
_lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>;
|
|
116
|
-
|
|
117
|
+
_sync: CollectionSyncManager<TOutput, TKey, TSchema, TInput>;
|
|
117
118
|
private _indexes;
|
|
118
119
|
private _mutations;
|
|
119
120
|
_state: CollectionStateManager<TOutput, TKey, TSchema, TInput>;
|
|
@@ -156,18 +157,16 @@ export declare class CollectionImpl<TOutput extends object = Record<string, unkn
|
|
|
156
157
|
* }
|
|
157
158
|
*/
|
|
158
159
|
isReady(): boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Check if the collection is currently loading more data
|
|
162
|
+
* @returns true if the collection has pending load more operations, false otherwise
|
|
163
|
+
*/
|
|
164
|
+
get isLoadingSubset(): boolean;
|
|
159
165
|
/**
|
|
160
166
|
* Start sync immediately - internal method for compiled queries
|
|
161
167
|
* This bypasses lazy loading for special cases like live query results
|
|
162
168
|
*/
|
|
163
169
|
startSyncImmediate(): void;
|
|
164
|
-
/**
|
|
165
|
-
* Requests the sync layer to load more data.
|
|
166
|
-
* @param options Options to control what data is being loaded
|
|
167
|
-
* @returns If data loading is asynchronous, this method returns a promise that resolves when the data is loaded.
|
|
168
|
-
* If data loading is synchronous, the data is loaded when the method returns.
|
|
169
|
-
*/
|
|
170
|
-
syncMore(options: OnLoadMoreOptions): void | Promise<void>;
|
|
171
170
|
/**
|
|
172
171
|
* Preload the collection data by starting sync if not already started
|
|
173
172
|
* Multiple concurrent calls will share the same promise
|
|
@@ -94,7 +94,8 @@ class CollectionImpl {
|
|
|
94
94
|
collection: this,
|
|
95
95
|
// Required for passing to config.sync callback
|
|
96
96
|
state: this._state,
|
|
97
|
-
lifecycle: this._lifecycle
|
|
97
|
+
lifecycle: this._lifecycle,
|
|
98
|
+
events: this._events
|
|
98
99
|
});
|
|
99
100
|
if (config.startSync === true) {
|
|
100
101
|
this._sync.startSync();
|
|
@@ -140,6 +141,13 @@ class CollectionImpl {
|
|
|
140
141
|
isReady() {
|
|
141
142
|
return this._lifecycle.status === `ready`;
|
|
142
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Check if the collection is currently loading more data
|
|
146
|
+
* @returns true if the collection has pending load more operations, false otherwise
|
|
147
|
+
*/
|
|
148
|
+
get isLoadingSubset() {
|
|
149
|
+
return this._sync.isLoadingSubset;
|
|
150
|
+
}
|
|
143
151
|
/**
|
|
144
152
|
* Start sync immediately - internal method for compiled queries
|
|
145
153
|
* This bypasses lazy loading for special cases like live query results
|
|
@@ -147,17 +155,6 @@ class CollectionImpl {
|
|
|
147
155
|
startSyncImmediate() {
|
|
148
156
|
this._sync.startSync();
|
|
149
157
|
}
|
|
150
|
-
/**
|
|
151
|
-
* Requests the sync layer to load more data.
|
|
152
|
-
* @param options Options to control what data is being loaded
|
|
153
|
-
* @returns If data loading is asynchronous, this method returns a promise that resolves when the data is loaded.
|
|
154
|
-
* If data loading is synchronous, the data is loaded when the method returns.
|
|
155
|
-
*/
|
|
156
|
-
syncMore(options) {
|
|
157
|
-
if (this._sync.syncOnLoadMoreFn) {
|
|
158
|
-
return this._sync.syncOnLoadMoreFn(options);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
158
|
/**
|
|
162
159
|
* Preload the collection data by starting sync if not already started
|
|
163
160
|
* Multiple concurrent calls will share the same promise
|