@byearlybird/starling 0.17.3 → 0.19.0

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/README.md CHANGED
@@ -10,6 +10,8 @@ Starling is a CRDT (conflict-free replicated data type) library that provides au
10
10
  npm install @byearlybird/starling
11
11
  # or
12
12
  pnpm add @byearlybird/starling
13
+ # or
14
+ bun add @byearlybird/starling
13
15
  ```
14
16
 
15
17
  Requires TypeScript 5 or higher.
@@ -17,20 +19,14 @@ Requires TypeScript 5 or higher.
17
19
  ## Quick Example
18
20
 
19
21
  ```typescript
20
- import { createStore, collection } from "@byearlybird/starling";
21
- import { z } from "zod";
22
-
23
- const userSchema = z.object({
24
- id: z.string(),
25
- name: z.string(),
26
- });
22
+ import { createStore } from "@byearlybird/starling";
27
23
 
28
24
  const store = createStore({
29
- users: collection(userSchema, (data) => data.id),
25
+ users: (data: { id: string; name: string }) => data.id,
30
26
  });
31
27
 
32
- store.put("users", { id: "1", name: "Alice" });
33
- const user = store.get("users", "1"); // { id: "1", name: "Alice" }
28
+ store.users.put({ id: "1", name: "Alice" });
29
+ const user = store.users.get("1"); // { id: "1", name: "Alice" }
34
30
  ```
35
31
 
36
32
  ## Features
@@ -39,7 +35,6 @@ const user = store.get("users", "1"); // { id: "1", name: "Alice" }
39
35
  - **Fast and synchronous**: All operations are in-memory and synchronous
40
36
  - **Framework agnostic**: Works with React, Vue, Svelte, or vanilla JS
41
37
  - **Type-safe**: Full TypeScript support with type inference
42
- - **Schema validation**: Works with Zod, Valibot, ArkType, and more
43
38
  - **Merge snapshots**: Sync data between devices or users easily
44
39
  - **Change events**: Listen to data changes and integrate with your reactive system
45
40
 
@@ -47,28 +42,17 @@ const user = store.get("users", "1"); // { id: "1", name: "Alice" }
47
42
 
48
43
  ### Creating a Store
49
44
 
50
- A store holds one or more collections. Each collection has a schema that defines what data it can store.
45
+ A store holds one or more collections. Each collection is defined by a function that extracts the document ID.
51
46
 
52
47
  ```typescript
53
- import { createStore, collection } from "@byearlybird/starling";
54
- import { z } from "zod";
48
+ import { createStore } from "@byearlybird/starling";
49
+
50
+ type User = { id: string; name: string; email?: string };
51
+ type Note = { id: string; content: string };
55
52
 
56
53
  const store = createStore({
57
- users: collection(
58
- z.object({
59
- id: z.string(),
60
- name: z.string(),
61
- email: z.string().optional(),
62
- }),
63
- (data) => data.id,
64
- ),
65
- notes: collection(
66
- z.object({
67
- id: z.string(),
68
- content: z.string(),
69
- }),
70
- (data) => data.id,
71
- ),
54
+ users: (data: User) => data.id,
55
+ notes: (data: Note) => data.id,
72
56
  });
73
57
  ```
74
58
 
@@ -77,7 +61,7 @@ const store = createStore({
77
61
  Add new items to a collection using `put()`:
78
62
 
79
63
  ```typescript
80
- store.put("users", {
64
+ store.users.put({
81
65
  id: "1",
82
66
  name: "Alice",
83
67
  email: "alice@example.com",
@@ -88,8 +72,8 @@ Or use `transact()` for atomic multi-collection operations:
88
72
 
89
73
  ```typescript
90
74
  store.transact((tx) => {
91
- tx.put("users", { id: "1", name: "Alice", email: "alice@example.com" });
92
- tx.put("notes", { id: "n1", content: "Hello" });
75
+ tx.users.put({ id: "1", name: "Alice", email: "alice@example.com" });
76
+ tx.notes.put({ id: "n1", content: "Hello" });
93
77
  });
94
78
  ```
95
79
 
@@ -98,7 +82,7 @@ store.transact((tx) => {
98
82
  Update existing items using `patch()`:
99
83
 
100
84
  ```typescript
101
- store.patch("users", "1", {
85
+ store.users.patch("1", {
102
86
  email: "newemail@example.com",
103
87
  });
104
88
  ```
@@ -108,7 +92,7 @@ store.patch("users", "1", {
108
92
  Remove items using `remove()`:
109
93
 
110
94
  ```typescript
111
- store.remove("users", "1");
95
+ store.users.remove("1");
112
96
  ```
113
97
 
114
98
  ### Reading Data
@@ -117,10 +101,13 @@ Read data directly from the store:
117
101
 
118
102
  ```typescript
119
103
  // Get a single item
120
- const user = store.get("users", "1");
104
+ const user = store.users.get("1");
121
105
 
122
106
  // Get all items as an array
123
- const allUsers = store.list("users");
107
+ const allUsers = store.users.list();
108
+
109
+ // Filter with a where clause
110
+ const admins = store.users.list({ where: (u) => u.role === "admin" });
124
111
 
125
112
  // You can easily derive other operations:
126
113
  const userIds = allUsers.map((u) => u.id);
@@ -132,15 +119,9 @@ const hasUser = allUsers.some((u) => u.id === "1");
132
119
  Subscribe to changes with `subscribe()`:
133
120
 
134
121
  ```typescript
135
- // Subscribe to specific collections
136
- const unsubscribe = store.subscribe(["users"], (event) => {
137
- console.log("Users collection changed:", event);
138
- const allUsers = store.list("users");
139
- // Update UI, invalidate queries, etc.
140
- });
141
-
142
- // Or subscribe to all changes
143
- store.subscribe((event) => {
122
+ // Subscribe to all changes
123
+ const unsubscribe = store.subscribe((event) => {
124
+ // event is e.g. { users: true } or { users: true, notes: true }
144
125
  console.log("Store changed:", event);
145
126
  });
146
127
 
@@ -181,14 +162,16 @@ function useUsers() {
181
162
  const queryClient = useQueryClient();
182
163
 
183
164
  useEffect(() => {
184
- return store.subscribe(["users"], () => {
185
- queryClient.invalidateQueries({ queryKey: ["users"] });
165
+ return store.subscribe((event) => {
166
+ if ("users" in event) {
167
+ queryClient.invalidateQueries({ queryKey: ["users"] });
168
+ }
186
169
  });
187
170
  }, []);
188
171
 
189
172
  return useQuery({
190
173
  queryKey: ["users"],
191
- queryFn: () => store.list("users"),
174
+ queryFn: () => store.users.list(),
192
175
  });
193
176
  }
194
177
  ```
@@ -200,8 +183,11 @@ import { useSyncExternalStore } from "react";
200
183
 
201
184
  function useUsers() {
202
185
  return useSyncExternalStore(
203
- (callback) => store.subscribe(["users"], () => callback()),
204
- () => store.list("users"),
186
+ (callback) =>
187
+ store.subscribe((event) => {
188
+ if ("users" in event) callback();
189
+ }),
190
+ () => store.users.list(),
205
191
  );
206
192
  }
207
193
  ```
@@ -211,9 +197,11 @@ function useUsers() {
211
197
  ```typescript
212
198
  import { writable } from "svelte/store";
213
199
 
214
- const users = writable(store.list("users"));
215
- store.subscribe(["users"], () => {
216
- users.set(store.list("users"));
200
+ const users = writable(store.users.list());
201
+ store.subscribe((event) => {
202
+ if ("users" in event) {
203
+ users.set(store.users.list());
204
+ }
217
205
  });
218
206
  ```
219
207
 
@@ -222,55 +210,36 @@ store.subscribe(["users"], () => {
222
210
  ```typescript
223
211
  import { ref } from "vue";
224
212
 
225
- const users = ref(store.list("users"));
226
- store.subscribe(["users"], () => {
227
- users.value = store.list("users");
213
+ const users = ref(store.users.list());
214
+ store.subscribe((event) => {
215
+ if ("users" in event) {
216
+ users.value = store.users.list();
217
+ }
228
218
  });
229
219
  ```
230
220
 
231
- ## Schema Support
232
-
233
- Starling works with any library that follows the [Standard Schema](https://github.com/standard-schema/spec) specification. This includes:
234
-
235
- - **Zod** - Most popular schema library
236
- - **Valibot** - Lightweight alternative
237
- - **ArkType** - TypeScript-first schemas
238
-
239
- You can use any of these to define your data shapes. Starling will validate your data and give you full TypeScript types.
240
-
241
- ```typescript
242
- import { z } from "zod";
243
- // or
244
- import * as v from "valibot";
245
- // or
246
- import { type } from "arktype";
247
-
248
- // All of these work the same way
249
- const schema = z.object({ id: z.string(), name: z.string() });
250
- // or
251
- const schema = v.object({ id: v.string(), name: v.string() });
252
- // or
253
- const schema = type({ id: "string", name: "string" });
254
- ```
255
-
256
221
  ## API Overview
257
222
 
258
223
  ### Main Export
259
224
 
260
225
  - `createStore(config)` - Creates a new store with collections
261
226
 
227
+ ### Collection Methods
228
+
229
+ Each collection is accessed as a property on the store (e.g., `store.users`):
230
+
231
+ - `store.<collection>.get(id)` - Get a document by ID
232
+ - `store.<collection>.list(options?)` - Get all documents as an array, with optional `where` filter
233
+ - `store.<collection>.put(data)` - Insert or replace a document (upsert, revives tombstoned IDs)
234
+ - `store.<collection>.patch(id, data)` - Partially update an existing document (throws if ID missing)
235
+ - `store.<collection>.remove(id)` - Remove a document
236
+
262
237
  ### Store Methods
263
238
 
264
- - `get(collection, id)` - Get a document by ID from a collection
265
- - `list(collection)` - Get all documents as an array from a collection
266
- - `put(collection, data)` - Insert or replace a document (upsert, revives tombstoned IDs)
267
- - `patch(collection, id, data)` - Partially update an existing document (throws if ID missing)
268
- - `remove(collection, id)` - Remove a document
269
- - `transact(callback)` - Execute operations atomically. Collections are cloned lazily on first access.
270
- - `subscribe(callback)` - Subscribe to all collection changes
271
- - `subscribe(collections, callback)` - Subscribe to changes in specific collections
272
- - `getState()` - Get current store state as a snapshot
273
- - `merge(snapshot)` - Merge a snapshot into the store
239
+ - `store.transact(callback)` - Execute operations atomically across collections. The `tx` object has the same collection properties (e.g., `tx.users.put(...)`)
240
+ - `store.subscribe(callback)` - Subscribe to all collection changes
241
+ - `store.getState()` - Get current store state as a snapshot
242
+ - `store.merge(snapshot)` - Merge a snapshot into the store
274
243
 
275
244
  For full type definitions, see the TypeScript types exported from the package.
276
245
 
@@ -278,20 +247,19 @@ For full type definitions, see the TypeScript types exported from the package.
278
247
 
279
248
  - **`lib/core/`** – CRDT primitives: hybrid logical clock, per-field atoms (LWW), tombstones, and document/collection merging.
280
249
  - **`lib/store/`** – Store API with collections, batching, queries, and change subscriptions.
281
- - **`lib/middleware/`** – Optional middleware (e.g. persistence).
282
250
 
283
251
  ## Development
284
252
 
285
253
  ```bash
286
254
  # Install dependencies
287
- pnpm install
255
+ bun install
288
256
 
289
257
  # Build the library
290
- pnpm run build
258
+ bun run build
291
259
 
292
260
  # Run tests
293
- pnpm test
261
+ bun test
294
262
 
295
263
  # Watch mode for development
296
- pnpm run dev
264
+ bun run dev
297
265
  ```
package/dist/index.d.ts CHANGED
@@ -1,209 +1,94 @@
1
1
  import { StandardSchemaV1 } from "@standard-schema/spec";
2
2
 
3
- //#region lib/core/clock.d.ts
3
+ //#region lib/clock.d.ts
4
4
  type Clock = {
5
5
  ms: number;
6
6
  seq: number;
7
7
  };
8
8
  /**
9
- * Branded type for HLC timestamps.
10
- * Stamps are lexicographically sortable hex strings encoding (ms, seq, nonce).
9
+ * HLC timestamp.
10
+ * Lexicographically sortable string: `${ms}@${seq}@${deviceId}`.
11
+ * ms and seq are zero-padded hex; deviceId is appended as-is.
11
12
  */
12
- type Stamp = string & {
13
- readonly __brand: "Stamp";
14
- };
13
+ type Stamp = string;
15
14
  declare function advanceClock(current: Clock, next: Clock): Clock;
16
- declare function makeStamp(ms: number, seq: number): Stamp;
17
- /**
18
- * Parse and validate a string as a Stamp. Use when deserializing stored state.
19
- * Throws if the value is not a valid 24-character hex string.
20
- */
21
- declare function asStamp(value: string): Stamp;
15
+ declare function makeStamp(ms: number, seq: number, deviceId: string): Stamp;
22
16
  //#endregion
23
- //#region lib/core/tombstone.d.ts
24
- type Tombstones = Record<string, Stamp>;
25
- declare function isDeleted(id: string, tombstones: Tombstones): boolean;
26
- declare function mergeTombstones(target: Tombstones, source: Tombstones): Tombstones;
27
- //#endregion
28
- //#region lib/core/types.d.ts
29
- declare const KEYS: {
30
- readonly VAL: "~val";
31
- readonly TS: "~ts";
32
- };
33
- /**
34
- * Base constraint for plain document shapes - any object with string keys.
35
- */
17
+ //#region lib/crdt.d.ts
36
18
  type Document = Record<string, unknown>;
37
19
  type Atom<T> = {
38
- [KEYS.VAL]: T;
39
- [KEYS.TS]: Stamp;
20
+ "~v": T;
21
+ "~ts": string;
40
22
  };
41
- /**
42
- * Atomized document with plain shape T. Each key K is stored as Atom<T[K]> (per-field).
43
- */
44
- type AtomizedDocument<T extends Document> = { [K in keyof T]: Atom<T[K]> };
45
- /**
46
- * Collection of atomized documents with shape T. Map from document ID to AtomizedDocument<T>.
47
- */
48
- type Collection<T extends Document> = Record<string, AtomizedDocument<T>>;
49
- /**
50
- * Collection state containing documents and tombstones.
51
- */
52
- type CollectionState<T extends Document> = {
53
- documents: Collection<T>;
23
+ type AtomizedDocument = Record<string, Atom<unknown>>;
24
+ type Tombstones = Record<string, string>;
25
+ type CollectionState = {
26
+ documents: Record<string, AtomizedDocument>;
54
27
  tombstones: Tombstones;
55
28
  };
56
29
  type StoreState = {
57
30
  clock: Clock;
58
- collections: Record<string, CollectionState<Document>>;
31
+ collections: Record<string, CollectionState>;
32
+ };
33
+ type CollectionChangeEvent = {
34
+ put: string[];
35
+ patch: string[];
36
+ remove: string[];
59
37
  };
60
- /**
61
- * Type guard to check if a value is an AtomizedDocument.
62
- * An AtomizedDocument is an object where all values are Atoms.
63
- */
64
- declare function isAtomizedDocument<T extends Document>(value: unknown): value is AtomizedDocument<T>;
65
- /**
66
- * Type guard to check if a value is a Collection.
67
- * A Collection is a Record where all values are AtomizedDocuments.
68
- */
69
- declare function isCollection<T extends Document>(value: unknown): value is Collection<T>;
70
- /**
71
- * Type guard to check if a value is a CollectionState.
72
- * A CollectionState has documents (Collection) and tombstones (Record<string, string>).
73
- */
74
- declare function isCollectionState<T extends Document>(value: unknown): value is CollectionState<T>;
75
- //#endregion
76
- //#region lib/core/atomizer.d.ts
77
- declare function pack<T>(value: T, timestamp: Stamp): Atom<T>;
78
- declare function unpack<T>(node: unknown): T | undefined;
79
- declare function isAtom(node: unknown): node is Atom<unknown>;
80
- declare function atomize<T extends Document>(data: T, timestamp: Stamp): AtomizedDocument<T>;
81
- //#endregion
82
- //#region lib/core/lens.d.ts
83
- declare function createReadLens<T extends Document>(doc: AtomizedDocument<T>): T;
84
- //#endregion
85
- //#region lib/core/merge.d.ts
86
- /** Merges incoming doc fields into local. Adds new keys from incoming; LWW on conflicts. */
87
- declare function mergeDocs<T extends Document>(local: AtomizedDocument<T>, incoming: Partial<AtomizedDocument<T>>): AtomizedDocument<T>;
88
- /**
89
- * Merges two collection states, respecting tombstones.
90
- * Documents that are tombstoned are excluded from the result.
91
- * For documents that exist in both collections, fields are merged using LWW semantics.
92
- */
93
- declare function mergeCollections<T extends Document>(local: CollectionState<T>, incoming: CollectionState<T>): CollectionState<T>;
94
38
  //#endregion
95
- //#region lib/store/schema.d.ts
96
- /**
97
- * Validates input data against a schema.
98
- * Accepts `unknown` input to allow safe validation of untyped data.
99
- * The schema's runtime validation will ensure type safety.
100
- */
101
- declare function validate<T extends StandardSchemaV1>(schema: T, input: unknown): StandardSchemaV1.InferOutput<T>;
102
- /**
103
- * Base type constraint for any standard schema object
104
- */
105
- type AnyObject = StandardSchemaV1<Record<string, any>>;
106
- type Output<T extends AnyObject> = StandardSchemaV1.InferOutput<T>;
107
- type Input<T extends AnyObject> = StandardSchemaV1.InferInput<T>;
108
- type CollectionDef<T extends Document = Document, Id extends string = string, S$1 extends AnyObject = AnyObject> = {
109
- readonly "~docType": T;
110
- readonly "~idType": Id;
111
- readonly "~schemaType": S$1;
112
- schema: AnyObject;
113
- getId: (data: T) => Id;
39
+ //#region lib/collection.d.ts
40
+ type CollectionDef<Input = unknown, Output extends Document = Document, KeyPath extends keyof Output & string = string> = {
41
+ keyPath: KeyPath;
42
+ schema?: StandardSchemaV1<Input, Output>;
114
43
  };
115
- /**
116
- * Helper function to create a collection definition with proper type inference.
117
- * This captures the schema output type directly as the document type.
118
- *
119
- * @example
120
- * ```ts
121
- * const store = createStore({
122
- * users: define(userSchema, (data) => data.id),
123
- * });
124
- * ```
125
- */
126
- declare function define<S$1 extends AnyObject, Id extends string = string>(schema: S$1, getId: (data: Output<S$1>) => Id): CollectionDef<Output<S$1>, Id, S$1>;
127
- /**
128
- * Extract the document type from a CollectionDef
129
- */
130
- type DocType<C extends CollectionDef> = C["~docType"];
131
- /**
132
- * Extract the ID type from a CollectionDef
133
- */
134
- type IdType<C extends CollectionDef> = C["~idType"];
135
- /**
136
- * Extract the input type from a CollectionDef's schema
137
- * This allows put() to accept partial data when schemas have defaults
138
- */
139
- type InputType<C extends CollectionDef> = C extends CollectionDef<any, any, infer S> ? Input<S> : never;
140
- /**
141
- * Configuration for all collections in a store.
142
- * All collection definitions must be created using the `collection()` helper.
143
- *
144
- * Uses `any` for type parameters to allow any CollectionDef to be stored,
145
- * while still preserving specific types through inference in createStore.
146
- */
44
+ //#endregion
45
+ //#region lib/store.d.ts
46
+ type DocType<C> = C extends CollectionDef<any, infer T, any> ? T : never;
47
+ type InputType<C> = C extends CollectionDef<infer I, any, any> ? I : never;
147
48
  type StoreConfig = Record<string, CollectionDef<any, any, any>>;
148
- /**
149
- * Valid collection name from a store config
150
- */
151
49
  type CollectionName<T extends StoreConfig> = keyof T & string;
152
- //#endregion
153
- //#region lib/store/types.d.ts
154
- type StoreChangeEvent<T extends StoreConfig> = { [K in keyof T]?: true };
155
- //#endregion
156
- //#region lib/store/store.d.ts
157
- type TransactionAPI<T extends StoreConfig> = {
158
- get<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): DocType<T[N]> | undefined;
159
- list<N extends CollectionName<T>>(collection: N): DocType<T[N]>[];
160
- put<N extends CollectionName<T>>(collection: N, data: InputType<T[N]>): DocType<T[N]>;
161
- patch<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>, data: Partial<DocType<T[N]>>): DocType<T[N]>;
162
- remove<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): void;
50
+ type CollectionAPI<C extends CollectionDef> = {
51
+ get(id: string): DocType<C> | undefined;
52
+ list(options?: {
53
+ where?: (doc: DocType<C>) => boolean;
54
+ }): DocType<C>[];
55
+ put(data: InputType<C>): DocType<C>;
56
+ patch(id: string, data: Partial<DocType<C>>): DocType<C>;
57
+ remove(id: string): void;
163
58
  };
164
- declare class Store<T extends StoreConfig> {
165
- #private;
166
- constructor(config: T);
167
- get<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): DocType<T[N]> | undefined;
168
- list<N extends CollectionName<T>>(collection: N): DocType<T[N]>[];
169
- put<N extends CollectionName<T>>(collection: N, data: InputType<T[N]>): DocType<T[N]>;
170
- patch<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>, data: Partial<DocType<T[N]>>): DocType<T[N]>;
171
- remove<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): void;
59
+ type StoreChangeEvent<T extends StoreConfig> = { [K in keyof T]?: CollectionChangeEvent };
60
+ type TransactionAPI<T extends StoreConfig> = { [K in CollectionName<T>]: CollectionAPI<T[K]> };
61
+ type Store<T extends StoreConfig> = { [K in CollectionName<T>]: CollectionAPI<T[K]> } & {
172
62
  subscribe(callback: (event: StoreChangeEvent<T>) => void): () => void;
173
63
  getState(): StoreState;
174
64
  merge(snapshot: StoreState): StoreChangeEvent<T>;
175
65
  transact<R>(callback: (tx: TransactionAPI<T>) => R): R;
176
- }
177
- declare function createStore<T extends StoreConfig>(config: T): Store<T>;
178
- //#endregion
179
- //#region lib/store/operations.d.ts
180
- declare function doGet<T extends Document>(docs: Collection<T>, tombstones: Tombstones, id: string): T | undefined;
181
- declare function doList<T extends Document>(docs: Collection<T>, tombstones: Tombstones): T[];
182
- declare function doPut<T extends Document>(docs: Collection<T>, tombstones: Tombstones, data: T, stamp: Stamp, validateFn: (data: unknown) => T, getId: (data: T) => string): T;
183
- declare function doPatch<T extends Document>(docs: Collection<T>, id: string, data: Partial<T>, stamp: Stamp, validateFn: (data: unknown) => T): T;
184
- declare function doRemove(docs: Collection<Document>, tombstones: Tombstones, id: string, stamp: Stamp): void;
185
- declare function mergeState<T extends StoreConfig>(currentState: StoreState, snapshot: StoreState, config: T): StoreChangeEvent<T>;
66
+ };
67
+ type StringKeyOf<T> = { [K in keyof T & string]: T[K] extends string ? K : never }[keyof T & string];
68
+ declare function createStore<T extends StoreConfig>(config: {
69
+ deviceId: string;
70
+ collections: T & { [K in keyof T & string]: T[K] extends {
71
+ schema: StandardSchemaV1<any, infer O>;
72
+ } ? {
73
+ keyPath: StringKeyOf<O>;
74
+ } : T[K] };
75
+ }): Store<T>;
76
+ declare function createStore<T extends Record<string, Document & {
77
+ keyPath?: never;
78
+ }>>(config: {
79
+ deviceId: string;
80
+ collections: { [K in keyof T & string]: {
81
+ keyPath: StringKeyOf<T[K]>;
82
+ } };
83
+ }): Store<{ [K in keyof T & string]: CollectionDef<T[K], T[K], string> }>;
186
84
  //#endregion
187
- //#region lib/persisters/idb-persister.d.ts
188
- interface IPersister {
189
- init(): Promise<void>;
190
- dispose(): Promise<void>;
191
- }
192
- type PersistenceOptions = {
193
- key: string;
194
- storeName?: string;
195
- debounceMs?: number;
196
- channelName?: string;
197
- serialize?: (state: StoreState) => string;
198
- deserialize?: (serialized: string) => StoreState;
85
+ //#region lib/query.d.ts
86
+ type Query<R> = {
87
+ readonly result: R;
88
+ subscribe(cb: (result: R) => void): () => void;
89
+ dispose(): void;
199
90
  };
200
- declare class IdbPersister<T extends StoreConfig> implements IPersister {
201
- #private;
202
- constructor(store: Store<T>, options: PersistenceOptions);
203
- init(): Promise<void>;
204
- dispose(): Promise<void>;
205
- subscribe(listener: (serialized: string) => void): () => void;
206
- }
91
+ declare function createQuery<T extends StoreConfig, R>(store: Store<T>, predicate: (store: Store<T>) => R, dependencies: CollectionName<T>[]): Query<R>;
207
92
  //#endregion
208
- export { AnyObject, Atom, AtomizedDocument, Clock, Collection, CollectionDef, CollectionName, CollectionState, DocType, Document, IPersister, IdType, IdbPersister, Input, InputType, KEYS, Output, PersistenceOptions, Stamp, Store, StoreConfig, StoreState, Tombstones, TransactionAPI, advanceClock, asStamp, atomize, createReadLens, createStore, define, doGet, doList, doPatch, doPut, doRemove, isAtom, isAtomizedDocument, isCollection, isCollectionState, isDeleted, makeStamp, mergeCollections, mergeDocs, mergeState, mergeTombstones, pack, unpack, validate };
93
+ export { type Clock, type CollectionAPI, type CollectionChangeEvent, type CollectionDef, type CollectionName, type CollectionState, type DocType, type Document, type InputType, type Query, type Store, type StoreChangeEvent, type StoreConfig, type StoreState, type Tombstones, type TransactionAPI, advanceClock, createQuery, createStore, makeStamp };
209
94
  //# sourceMappingURL=index.d.ts.map