@tanstack/db 0.2.4 → 0.2.5
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.cjs +23 -4
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +35 -41
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/local-only.d.cts +17 -43
- package/dist/cjs/local-storage.cjs +3 -12
- package/dist/cjs/local-storage.cjs.map +1 -1
- package/dist/cjs/local-storage.d.cts +16 -39
- package/dist/cjs/query/builder/types.d.cts +3 -10
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/types.d.cts +10 -31
- package/dist/esm/collection.d.ts +35 -41
- package/dist/esm/collection.js +23 -4
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/local-only.d.ts +17 -43
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/local-storage.d.ts +16 -39
- package/dist/esm/local-storage.js +3 -12
- package/dist/esm/local-storage.js.map +1 -1
- package/dist/esm/query/builder/types.d.ts +3 -10
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/types.d.ts +10 -31
- package/package.json +2 -2
- package/src/collection.ts +148 -196
- package/src/local-only.ts +57 -77
- package/src/local-storage.ts +53 -85
- package/src/query/builder/types.ts +3 -12
- package/src/query/live-query-collection.ts +1 -1
- package/src/types.ts +25 -55
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CollectionImpl } from '../../collection.js';
|
|
2
2
|
import { Aggregate, BasicExpression, Func, OrderByDirection, PropRef, Value } from '../ir.js';
|
|
3
3
|
import { QueryBuilder } from './index.js';
|
|
4
|
-
import { ResolveType } from '../../types.js';
|
|
5
4
|
/**
|
|
6
5
|
* Context - The central state container for query builder operations
|
|
7
6
|
*
|
|
@@ -57,16 +56,10 @@ export type Source = {
|
|
|
57
56
|
/**
|
|
58
57
|
* InferCollectionType - Extracts the TypeScript type from a CollectionImpl
|
|
59
58
|
*
|
|
60
|
-
* This helper ensures we get the same type that
|
|
61
|
-
*
|
|
62
|
-
* consistency between collection creation and query type inference.
|
|
63
|
-
*
|
|
64
|
-
* The complex generic parameters extract:
|
|
65
|
-
* - U: The base document type
|
|
66
|
-
* - TSchema: The schema definition
|
|
67
|
-
* - The resolved type combines these with any transforms
|
|
59
|
+
* This helper ensures we get the same type that was used when creating the collection itself.
|
|
60
|
+
* This can be an explicit type passed by the user or the schema output type.
|
|
68
61
|
*/
|
|
69
|
-
export type InferCollectionType<T> = T extends CollectionImpl<infer
|
|
62
|
+
export type InferCollectionType<T> = T extends CollectionImpl<infer TOutput, any, any, any, any> ? TOutput : never;
|
|
70
63
|
/**
|
|
71
64
|
* SchemaFromSource - Converts a Source definition into a ContextSchema
|
|
72
65
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-query-collection.cjs","sources":["../../../src/query/live-query-collection.ts"],"sourcesContent":["import { createCollection } from \"../collection.js\"\nimport { CollectionConfigBuilder } 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.js\"\nimport type { CollectionConfig, UtilsRecord } from \"../types.js\"\nimport type { Context, GetResult } from \"./builder/types.js\"\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): CollectionConfig<TResult> {\n const collectionConfigBuilder = new CollectionConfigBuilder<\n TContext,\n TResult\n >(config)\n return collectionConfigBuilder.getConfig()\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): Collection<TResult, string | number, {}>\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): Collection<TResult, string | number, TUtils>\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): Collection<TResult, string | number, TUtils> {\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)\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 return bridgeToCreateCollection({\n ...options,\n utils: config.utils,\n })\n }\n}\n\n/**\n * Bridge function that handles the type compatibility between query2's TResult\n * and core collection's
|
|
1
|
+
{"version":3,"file":"live-query-collection.cjs","sources":["../../../src/query/live-query-collection.ts"],"sourcesContent":["import { createCollection } from \"../collection.js\"\nimport { CollectionConfigBuilder } 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.js\"\nimport type { CollectionConfig, UtilsRecord } from \"../types.js\"\nimport type { Context, GetResult } from \"./builder/types.js\"\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): CollectionConfig<TResult> {\n const collectionConfigBuilder = new CollectionConfigBuilder<\n TContext,\n TResult\n >(config)\n return collectionConfigBuilder.getConfig()\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): Collection<TResult, string | number, {}>\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): Collection<TResult, string | number, TUtils>\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): Collection<TResult, string | number, TUtils> {\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)\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 return bridgeToCreateCollection({\n ...options,\n utils: config.utils,\n })\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 // This is the only place we need a type assertion, hidden from user API\n return createCollection(options as any) as unknown as Collection<\n TResult,\n string | number,\n TUtils\n >\n}\n"],"names":["collectionConfigBuilder","CollectionConfigBuilder","createCollection"],"mappings":";;;;AAgCO,SAAS,2BAId,QAC2B;AAC3B,QAAMA,4BAA0B,IAAIC,wBAAAA,wBAGlC,MAAM;AACR,SAAOD,0BAAwB,UAAA;AACjC;AAsDO,SAAS,0BAKd,eAG8C;AAE9C,MAAI,OAAO,kBAAkB,YAAY;AAEvC,UAAM,SAAuD;AAAA,MAC3D,OAAO;AAAA,IAAA;AAIT,UAAM,UAAU,2BAA8C,MAAM;AACpE,WAAO,yBAAyB,OAAO;AAAA,EACzC,OAAO;AAEL,UAAM,SAAS;AAIf,UAAM,UAAU,2BAA8C,MAAM;AACpE,WAAO,yBAAyB;AAAA,MAC9B,GAAG;AAAA,MACH,OAAO,OAAO;AAAA,IAAA,CACf;AAAA,EACH;AACF;AAMA,SAAS,yBAIP,SAC8C;AAE9C,SAAOE,WAAAA,iBAAiB,OAAc;AAKxC;;;"}
|
package/dist/cjs/types.d.cts
CHANGED
|
@@ -16,29 +16,6 @@ export type InferSchemaOutput<T> = T extends StandardSchemaV1 ? StandardSchemaV1
|
|
|
16
16
|
* @internal This is used for collection insert type inference
|
|
17
17
|
*/
|
|
18
18
|
export type InferSchemaInput<T> = T extends StandardSchemaV1 ? StandardSchemaV1.InferInput<T> extends object ? StandardSchemaV1.InferInput<T> : Record<string, unknown> : Record<string, unknown>;
|
|
19
|
-
/**
|
|
20
|
-
* Helper type to determine the insert input type
|
|
21
|
-
* This takes the raw generics (TExplicit, TSchema, TFallback) instead of the resolved T.
|
|
22
|
-
*
|
|
23
|
-
* Priority:
|
|
24
|
-
* 1. Explicit generic TExplicit (if not 'unknown')
|
|
25
|
-
* 2. Schema input type (if schema provided)
|
|
26
|
-
* 3. Fallback type TFallback
|
|
27
|
-
*
|
|
28
|
-
* @internal This is used for collection insert type inference
|
|
29
|
-
*/
|
|
30
|
-
export type ResolveInsertInput<TExplicit = unknown, TSchema extends StandardSchemaV1 = never, TFallback extends object = Record<string, unknown>> = unknown extends TExplicit ? [TSchema] extends [never] ? TFallback : InferSchemaInput<TSchema> : TExplicit extends object ? TExplicit : Record<string, unknown>;
|
|
31
|
-
/**
|
|
32
|
-
* Helper type to determine the final type based on priority:
|
|
33
|
-
* 1. Explicit generic TExplicit (if not 'unknown')
|
|
34
|
-
* 2. Schema output type (if schema provided)
|
|
35
|
-
* 3. Fallback type TFallback
|
|
36
|
-
*
|
|
37
|
-
* @remarks
|
|
38
|
-
* This type is used internally to resolve the collection item type based on the provided generics and schema.
|
|
39
|
-
* Users should not need to use this type directly, but understanding the priority order helps when defining collections.
|
|
40
|
-
*/
|
|
41
|
-
export type ResolveType<TExplicit, TSchema extends StandardSchemaV1 = never, TFallback extends object = Record<string, unknown>> = unknown extends TExplicit ? [TSchema] extends [never] ? TFallback : InferSchemaOutput<TSchema> : TExplicit extends object ? TExplicit : Record<string, unknown>;
|
|
42
19
|
export type TransactionState = `pending` | `persisting` | `completed` | `failed`;
|
|
43
20
|
/**
|
|
44
21
|
* Represents a utility function that can be attached to a collection
|
|
@@ -187,9 +164,9 @@ export type DeleteMutationFnParams<T extends object = Record<string, unknown>, T
|
|
|
187
164
|
transaction: TransactionWithMutations<T, `delete`>;
|
|
188
165
|
collection: Collection<T, TKey, TUtils>;
|
|
189
166
|
};
|
|
190
|
-
export type InsertMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = Record<string, Fn
|
|
191
|
-
export type UpdateMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = Record<string, Fn
|
|
192
|
-
export type DeleteMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = Record<string, Fn
|
|
167
|
+
export type InsertMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = Record<string, Fn>, TReturn = any> = (params: InsertMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>;
|
|
168
|
+
export type UpdateMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = Record<string, Fn>, TReturn = any> = (params: UpdateMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>;
|
|
169
|
+
export type DeleteMutationFn<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = Record<string, Fn>, TReturn = any> = (params: DeleteMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>;
|
|
193
170
|
/**
|
|
194
171
|
* Collection status values for lifecycle management
|
|
195
172
|
* @example
|
|
@@ -218,9 +195,8 @@ export type CollectionStatus =
|
|
|
218
195
|
| `error`
|
|
219
196
|
/** Collection has been cleaned up and resources freed */
|
|
220
197
|
| `cleaned-up`;
|
|
221
|
-
export interface
|
|
198
|
+
export interface BaseCollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never, TUtils extends UtilsRecord = Record<string, Fn>, TReturn = any> {
|
|
222
199
|
id?: string;
|
|
223
|
-
sync: SyncConfig<T, TKey>;
|
|
224
200
|
schema?: TSchema;
|
|
225
201
|
/**
|
|
226
202
|
* Function to extract the ID from an object
|
|
@@ -303,7 +279,7 @@ export interface CollectionConfig<T extends object = Record<string, unknown>, TK
|
|
|
303
279
|
* })
|
|
304
280
|
* }
|
|
305
281
|
*/
|
|
306
|
-
onInsert?: InsertMutationFn<
|
|
282
|
+
onInsert?: InsertMutationFn<T, TKey, TUtils, TReturn>;
|
|
307
283
|
/**
|
|
308
284
|
* Optional asynchronous handler function called before an update operation
|
|
309
285
|
* @param params Object containing transaction and collection information
|
|
@@ -346,7 +322,7 @@ export interface CollectionConfig<T extends object = Record<string, unknown>, TK
|
|
|
346
322
|
* }
|
|
347
323
|
* }
|
|
348
324
|
*/
|
|
349
|
-
onUpdate?: UpdateMutationFn<T, TKey>;
|
|
325
|
+
onUpdate?: UpdateMutationFn<T, TKey, TUtils, TReturn>;
|
|
350
326
|
/**
|
|
351
327
|
* Optional asynchronous handler function called before a delete operation
|
|
352
328
|
* @param params Object containing transaction and collection information
|
|
@@ -389,7 +365,10 @@ export interface CollectionConfig<T extends object = Record<string, unknown>, TK
|
|
|
389
365
|
* }
|
|
390
366
|
* }
|
|
391
367
|
*/
|
|
392
|
-
onDelete?: DeleteMutationFn<T, TKey>;
|
|
368
|
+
onDelete?: DeleteMutationFn<T, TKey, TUtils, TReturn>;
|
|
369
|
+
}
|
|
370
|
+
export interface CollectionConfig<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TSchema extends StandardSchemaV1 = never> extends BaseCollectionConfig<T, TKey, TSchema> {
|
|
371
|
+
sync: SyncConfig<T, TKey>;
|
|
393
372
|
}
|
|
394
373
|
export type ChangesPayload<T extends object = Record<string, unknown>> = Array<ChangeMessage<T>>;
|
|
395
374
|
/**
|
package/dist/esm/collection.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { IndexProxy } from './indexes/lazy-index.js';
|
|
|
4
4
|
import { Transaction } from './transactions.js';
|
|
5
5
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
6
6
|
import { SingleRowRefProxy } from './query/builder/ref-proxy.js';
|
|
7
|
-
import { ChangeListener, ChangeMessage, CollectionConfig, CollectionStatus, CurrentStateAsChangesOptions, Fn,
|
|
7
|
+
import { ChangeListener, ChangeMessage, CollectionConfig, CollectionStatus, CurrentStateAsChangesOptions, Fn, InferSchemaInput, InferSchemaOutput, InsertConfig, OperationConfig, OptimisticChangeMessage, SubscribeChangesOptions, Transaction as TransactionType, UtilsRecord, WritableDeep } from './types.js';
|
|
8
8
|
import { IndexOptions } from './indexes/index-options.js';
|
|
9
9
|
import { BaseIndex, IndexResolver } from './indexes/base-index.js';
|
|
10
10
|
interface PendingSyncedTransaction<T extends object = Record<string, unknown>> {
|
|
@@ -26,11 +26,9 @@ export interface Collection<T extends object = Record<string, unknown>, TKey ext
|
|
|
26
26
|
/**
|
|
27
27
|
* Creates a new Collection instance with the given configuration
|
|
28
28
|
*
|
|
29
|
-
* @template
|
|
29
|
+
* @template T - The schema type if a schema is provided, otherwise the type of items in the collection
|
|
30
30
|
* @template TKey - The type of the key for the collection
|
|
31
31
|
* @template TUtils - The utilities record type
|
|
32
|
-
* @template TSchema - The schema type for validation and type inference (second priority)
|
|
33
|
-
* @template TFallback - The fallback type if no explicit or schema type is provided
|
|
34
32
|
* @param options - Collection options with optional utilities
|
|
35
33
|
* @returns A new Collection with utilities exposed both at top level and under .utils
|
|
36
34
|
*
|
|
@@ -94,26 +92,22 @@ export interface Collection<T extends object = Record<string, unknown>, TKey ext
|
|
|
94
92
|
* sync: { sync: () => {} }
|
|
95
93
|
* })
|
|
96
94
|
*
|
|
97
|
-
* // Note: You can provide an explicit type, a schema, or both. When both are provided, the explicit type takes precedence.
|
|
98
95
|
*/
|
|
99
|
-
export declare function createCollection<
|
|
100
|
-
schema:
|
|
96
|
+
export declare function createCollection<T extends StandardSchemaV1, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}>(options: CollectionConfig<InferSchemaOutput<T>, TKey, T> & {
|
|
97
|
+
schema: T;
|
|
101
98
|
utils?: TUtils;
|
|
102
|
-
}): Collection<
|
|
103
|
-
export declare function createCollection<
|
|
104
|
-
schema
|
|
99
|
+
}): Collection<InferSchemaOutput<T>, TKey, TUtils, T, InferSchemaInput<T>>;
|
|
100
|
+
export declare function createCollection<T extends object, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}>(options: CollectionConfig<T, TKey, never> & {
|
|
101
|
+
schema?: never;
|
|
105
102
|
utils?: TUtils;
|
|
106
|
-
}): Collection<
|
|
107
|
-
export declare
|
|
108
|
-
|
|
109
|
-
}): Collection<ResolveType<TExplicit, TSchema, TFallback>, TKey, TUtils, TSchema, ResolveInsertInput<TExplicit, TSchema, TFallback>>;
|
|
110
|
-
export declare class CollectionImpl<T extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInsertInput extends object = T> {
|
|
111
|
-
config: CollectionConfig<T, TKey, TSchema, TInsertInput>;
|
|
103
|
+
}): Collection<T, TKey, TUtils, never, T>;
|
|
104
|
+
export declare class CollectionImpl<TOutput extends object = Record<string, unknown>, TKey extends string | number = string | number, TUtils extends UtilsRecord = {}, TSchema extends StandardSchemaV1 = StandardSchemaV1, TInput extends object = TOutput> {
|
|
105
|
+
config: CollectionConfig<TOutput, TKey, TSchema>;
|
|
112
106
|
transactions: SortedMap<string, Transaction<any>>;
|
|
113
|
-
pendingSyncedTransactions: Array<PendingSyncedTransaction<
|
|
114
|
-
syncedData: Map<TKey,
|
|
107
|
+
pendingSyncedTransactions: Array<PendingSyncedTransaction<TOutput>>;
|
|
108
|
+
syncedData: Map<TKey, TOutput> | SortedMap<TKey, TOutput>;
|
|
115
109
|
syncedMetadata: Map<TKey, unknown>;
|
|
116
|
-
optimisticUpserts: Map<TKey,
|
|
110
|
+
optimisticUpserts: Map<TKey, TOutput>;
|
|
117
111
|
optimisticDeletes: Set<TKey>;
|
|
118
112
|
private _size;
|
|
119
113
|
private lazyIndexes;
|
|
@@ -194,7 +188,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
194
188
|
* @param config - Configuration object for the collection
|
|
195
189
|
* @throws Error if sync config is missing
|
|
196
190
|
*/
|
|
197
|
-
constructor(config: CollectionConfig<
|
|
191
|
+
constructor(config: CollectionConfig<TOutput, TKey, TSchema>);
|
|
198
192
|
/**
|
|
199
193
|
* Start sync immediately - internal method for compiled queries
|
|
200
194
|
* This bypasses lazy loading for special cases like live query results
|
|
@@ -261,7 +255,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
261
255
|
/**
|
|
262
256
|
* Get the current value for a key (virtual derived state)
|
|
263
257
|
*/
|
|
264
|
-
get(key: TKey):
|
|
258
|
+
get(key: TKey): TOutput | undefined;
|
|
265
259
|
/**
|
|
266
260
|
* Check if a key exists in the collection (virtual derived state)
|
|
267
261
|
*/
|
|
@@ -277,23 +271,23 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
277
271
|
/**
|
|
278
272
|
* Get all values (virtual derived state)
|
|
279
273
|
*/
|
|
280
|
-
values(): IterableIterator<
|
|
274
|
+
values(): IterableIterator<TOutput>;
|
|
281
275
|
/**
|
|
282
276
|
* Get all entries (virtual derived state)
|
|
283
277
|
*/
|
|
284
|
-
entries(): IterableIterator<[TKey,
|
|
278
|
+
entries(): IterableIterator<[TKey, TOutput]>;
|
|
285
279
|
/**
|
|
286
280
|
* Get all entries (virtual derived state)
|
|
287
281
|
*/
|
|
288
|
-
[Symbol.iterator](): IterableIterator<[TKey,
|
|
282
|
+
[Symbol.iterator](): IterableIterator<[TKey, TOutput]>;
|
|
289
283
|
/**
|
|
290
284
|
* Execute a callback for each entry in the collection
|
|
291
285
|
*/
|
|
292
|
-
forEach(callbackfn: (value:
|
|
286
|
+
forEach(callbackfn: (value: TOutput, key: TKey, index: number) => void): void;
|
|
293
287
|
/**
|
|
294
288
|
* Create a new array with the results of calling a function for each entry in the collection
|
|
295
289
|
*/
|
|
296
|
-
map<U>(callbackfn: (value:
|
|
290
|
+
map<U>(callbackfn: (value: TOutput, key: TKey, index: number) => U): Array<U>;
|
|
297
291
|
/**
|
|
298
292
|
* Attempts to commit pending synced transactions if there are no active transactions
|
|
299
293
|
* This method processes operations from pending transactions and applies them to the synced data
|
|
@@ -305,7 +299,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
305
299
|
*/
|
|
306
300
|
private scheduleTransactionCleanup;
|
|
307
301
|
private ensureStandardSchema;
|
|
308
|
-
getKeyFromItem(item:
|
|
302
|
+
getKeyFromItem(item: TOutput): TKey;
|
|
309
303
|
generateGlobalKey(key: any, item: any): string;
|
|
310
304
|
/**
|
|
311
305
|
* Creates an index on a collection for faster queries.
|
|
@@ -337,7 +331,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
337
331
|
* options: { language: 'en' }
|
|
338
332
|
* })
|
|
339
333
|
*/
|
|
340
|
-
createIndex<TResolver extends IndexResolver<TKey> = typeof BTreeIndex>(indexCallback: (row: SingleRowRefProxy<
|
|
334
|
+
createIndex<TResolver extends IndexResolver<TKey> = typeof BTreeIndex>(indexCallback: (row: SingleRowRefProxy<TOutput>) => any, config?: IndexOptions<TResolver>): IndexProxy<TKey>;
|
|
341
335
|
/**
|
|
342
336
|
* Resolve all lazy indexes (called when collection first syncs)
|
|
343
337
|
* @private
|
|
@@ -357,7 +351,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
357
351
|
* @private
|
|
358
352
|
*/
|
|
359
353
|
private updateIndexes;
|
|
360
|
-
validateData(data: unknown, type: `insert` | `update`, key?: TKey):
|
|
354
|
+
validateData(data: unknown, type: `insert` | `update`, key?: TKey): TOutput | never;
|
|
361
355
|
/**
|
|
362
356
|
* Inserts one or more items into the collection
|
|
363
357
|
* @param items - Single item or array of items to insert
|
|
@@ -394,7 +388,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
394
388
|
* console.log('Insert failed:', error)
|
|
395
389
|
* }
|
|
396
390
|
*/
|
|
397
|
-
insert: (data:
|
|
391
|
+
insert: (data: TInput | Array<TInput>, config?: InsertConfig) => Transaction<Record<string, unknown>> | Transaction<TOutput>;
|
|
398
392
|
/**
|
|
399
393
|
* Updates one or more items in the collection using a callback function
|
|
400
394
|
* @param keys - Single key or array of keys to update
|
|
@@ -434,10 +428,10 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
434
428
|
* console.log('Update failed:', error)
|
|
435
429
|
* }
|
|
436
430
|
*/
|
|
437
|
-
update
|
|
438
|
-
update
|
|
439
|
-
update
|
|
440
|
-
update
|
|
431
|
+
update(key: Array<TKey | unknown>, callback: (drafts: Array<WritableDeep<TInput>>) => void): TransactionType;
|
|
432
|
+
update(keys: Array<TKey | unknown>, config: OperationConfig, callback: (drafts: Array<WritableDeep<TInput>>) => void): TransactionType;
|
|
433
|
+
update(id: TKey | unknown, callback: (draft: WritableDeep<TInput>) => void): TransactionType;
|
|
434
|
+
update(id: TKey | unknown, config: OperationConfig, callback: (draft: WritableDeep<TInput>) => void): TransactionType;
|
|
441
435
|
/**
|
|
442
436
|
* Deletes one or more items from the collection
|
|
443
437
|
* @param keys - Single key or array of keys to delete
|
|
@@ -485,27 +479,27 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
485
479
|
* console.log("Todo 1 exists:", itemsMap.get("todo-1"))
|
|
486
480
|
* }
|
|
487
481
|
*/
|
|
488
|
-
get state(): Map<TKey,
|
|
482
|
+
get state(): Map<TKey, TOutput>;
|
|
489
483
|
/**
|
|
490
484
|
* Gets the current state of the collection as a Map, but only resolves when data is available
|
|
491
485
|
* Waits for the first sync commit to complete before resolving
|
|
492
486
|
*
|
|
493
487
|
* @returns Promise that resolves to a Map containing all items in the collection
|
|
494
488
|
*/
|
|
495
|
-
stateWhenReady(): Promise<Map<TKey,
|
|
489
|
+
stateWhenReady(): Promise<Map<TKey, TOutput>>;
|
|
496
490
|
/**
|
|
497
491
|
* Gets the current state of the collection as an Array
|
|
498
492
|
*
|
|
499
493
|
* @returns An Array containing all items in the collection
|
|
500
494
|
*/
|
|
501
|
-
get toArray():
|
|
495
|
+
get toArray(): TOutput[];
|
|
502
496
|
/**
|
|
503
497
|
* Gets the current state of the collection as an Array, but only resolves when data is available
|
|
504
498
|
* Waits for the first sync commit to complete before resolving
|
|
505
499
|
*
|
|
506
500
|
* @returns Promise that resolves to an Array containing all items in the collection
|
|
507
501
|
*/
|
|
508
|
-
toArrayWhenReady(): Promise<Array<
|
|
502
|
+
toArrayWhenReady(): Promise<Array<TOutput>>;
|
|
509
503
|
/**
|
|
510
504
|
* Returns the current state of the collection as an array of changes
|
|
511
505
|
* @param options - Options including optional where filter
|
|
@@ -524,7 +518,7 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
524
518
|
* whereExpression: eq(row.status, 'active')
|
|
525
519
|
* })
|
|
526
520
|
*/
|
|
527
|
-
currentStateAsChanges(options?: CurrentStateAsChangesOptions<
|
|
521
|
+
currentStateAsChanges(options?: CurrentStateAsChangesOptions<TOutput>): Array<ChangeMessage<TOutput>>;
|
|
528
522
|
/**
|
|
529
523
|
* Subscribe to changes in the collection
|
|
530
524
|
* @param callback - Function called when items change
|
|
@@ -564,11 +558,11 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
|
|
|
564
558
|
* whereExpression: eq(row.status, 'active')
|
|
565
559
|
* })
|
|
566
560
|
*/
|
|
567
|
-
subscribeChanges(callback: (changes: Array<ChangeMessage<
|
|
561
|
+
subscribeChanges(callback: (changes: Array<ChangeMessage<TOutput>>) => void, options?: SubscribeChangesOptions<TOutput>): () => void;
|
|
568
562
|
/**
|
|
569
563
|
* Subscribe to changes for a specific key
|
|
570
564
|
*/
|
|
571
|
-
subscribeChangesKey(key: TKey, listener: ChangeListener<
|
|
565
|
+
subscribeChangesKey(key: TKey, listener: ChangeListener<TOutput, TKey>, { includeInitialState }?: {
|
|
572
566
|
includeInitialState?: boolean;
|
|
573
567
|
}): () => void;
|
|
574
568
|
/**
|
package/dist/esm/collection.js
CHANGED
|
@@ -9,7 +9,9 @@ import { getActiveTransaction, createTransaction } from "./transactions.js";
|
|
|
9
9
|
import { MissingInsertHandlerError, DuplicateKeyError, MissingDeleteHandlerError, NoKeysPassedToDeleteError, DeleteKeyNotFoundError, CollectionRequiresConfigError, CollectionRequiresSyncConfigError, CollectionInErrorStateError, InvalidCollectionStatusTransitionError, NoPendingSyncTransactionWriteError, SyncTransactionAlreadyCommittedWriteError, NoPendingSyncTransactionCommitError, SyncTransactionAlreadyCommittedError, DuplicateKeySyncError, CollectionIsInErrorStateError, SyncCleanupError, NegativeActiveSubscribersError, InvalidSchemaError, UndefinedKeyError, SchemaMustBeSynchronousError, SchemaValidationError, MissingUpdateArgumentError, MissingUpdateHandlerError, NoKeysPassedToUpdateError, UpdateKeyNotFoundError, KeyUpdateNotAllowedError } from "./errors.js";
|
|
10
10
|
import { currentStateAsChanges, createFilteredCallback } from "./change-events.js";
|
|
11
11
|
function createCollection(options) {
|
|
12
|
-
const collection = new CollectionImpl(
|
|
12
|
+
const collection = new CollectionImpl(
|
|
13
|
+
options
|
|
14
|
+
);
|
|
13
15
|
if (options.utils) {
|
|
14
16
|
collection.utils = { ...options.utils };
|
|
15
17
|
} else {
|
|
@@ -802,7 +804,10 @@ class CollectionImpl {
|
|
|
802
804
|
switch (mutation.type) {
|
|
803
805
|
case `insert`:
|
|
804
806
|
case `update`:
|
|
805
|
-
this.optimisticUpserts.set(
|
|
807
|
+
this.optimisticUpserts.set(
|
|
808
|
+
mutation.key,
|
|
809
|
+
mutation.modified
|
|
810
|
+
);
|
|
806
811
|
this.optimisticDeletes.delete(mutation.key);
|
|
807
812
|
break;
|
|
808
813
|
case `delete`:
|
|
@@ -1234,7 +1239,12 @@ class CollectionImpl {
|
|
|
1234
1239
|
});
|
|
1235
1240
|
throw new SchemaValidationError(type, typedIssues);
|
|
1236
1241
|
}
|
|
1237
|
-
|
|
1242
|
+
const validatedMergedData = result2.value;
|
|
1243
|
+
const modifiedKeys = Object.keys(data);
|
|
1244
|
+
const extractedChanges = Object.fromEntries(
|
|
1245
|
+
modifiedKeys.map((k) => [k, validatedMergedData[k]])
|
|
1246
|
+
);
|
|
1247
|
+
return extractedChanges;
|
|
1238
1248
|
}
|
|
1239
1249
|
}
|
|
1240
1250
|
const result = standardSchema[`~standard`].validate(data);
|
|
@@ -1315,7 +1325,16 @@ class CollectionImpl {
|
|
|
1315
1325
|
mutationId: crypto.randomUUID(),
|
|
1316
1326
|
original: originalItem,
|
|
1317
1327
|
modified: modifiedItem,
|
|
1318
|
-
|
|
1328
|
+
// Pick the values from modifiedItem based on what's passed in - this is for cases
|
|
1329
|
+
// where a schema has default values or transforms. The modified data has the extra
|
|
1330
|
+
// default or transformed values but for changes, we just want to show the data that
|
|
1331
|
+
// was actually passed in.
|
|
1332
|
+
changes: Object.fromEntries(
|
|
1333
|
+
Object.keys(itemChanges).map((k) => [
|
|
1334
|
+
k,
|
|
1335
|
+
modifiedItem[k]
|
|
1336
|
+
])
|
|
1337
|
+
),
|
|
1319
1338
|
globalKey,
|
|
1320
1339
|
key,
|
|
1321
1340
|
metadata: config.metadata,
|