@byearlybird/starling 0.18.0 → 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
@@ -19,20 +19,14 @@ Requires TypeScript 5 or higher.
19
19
  ## Quick Example
20
20
 
21
21
  ```typescript
22
- import { createStore, collection } from "@byearlybird/starling";
23
- import { z } from "zod";
24
-
25
- const userSchema = z.object({
26
- id: z.string(),
27
- name: z.string(),
28
- });
22
+ import { createStore } from "@byearlybird/starling";
29
23
 
30
24
  const store = createStore({
31
- users: collection(userSchema, (data) => data.id),
25
+ users: (data: { id: string; name: string }) => data.id,
32
26
  });
33
27
 
34
- store.put("users", { id: "1", name: "Alice" });
35
- 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" }
36
30
  ```
37
31
 
38
32
  ## Features
@@ -41,7 +35,6 @@ const user = store.get("users", "1"); // { id: "1", name: "Alice" }
41
35
  - **Fast and synchronous**: All operations are in-memory and synchronous
42
36
  - **Framework agnostic**: Works with React, Vue, Svelte, or vanilla JS
43
37
  - **Type-safe**: Full TypeScript support with type inference
44
- - **Schema validation**: Works with Zod, Valibot, ArkType, and more
45
38
  - **Merge snapshots**: Sync data between devices or users easily
46
39
  - **Change events**: Listen to data changes and integrate with your reactive system
47
40
 
@@ -49,28 +42,17 @@ const user = store.get("users", "1"); // { id: "1", name: "Alice" }
49
42
 
50
43
  ### Creating a Store
51
44
 
52
- 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.
53
46
 
54
47
  ```typescript
55
- import { createStore, collection } from "@byearlybird/starling";
56
- 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 };
57
52
 
58
53
  const store = createStore({
59
- users: collection(
60
- z.object({
61
- id: z.string(),
62
- name: z.string(),
63
- email: z.string().optional(),
64
- }),
65
- (data) => data.id,
66
- ),
67
- notes: collection(
68
- z.object({
69
- id: z.string(),
70
- content: z.string(),
71
- }),
72
- (data) => data.id,
73
- ),
54
+ users: (data: User) => data.id,
55
+ notes: (data: Note) => data.id,
74
56
  });
75
57
  ```
76
58
 
@@ -79,7 +61,7 @@ const store = createStore({
79
61
  Add new items to a collection using `put()`:
80
62
 
81
63
  ```typescript
82
- store.put("users", {
64
+ store.users.put({
83
65
  id: "1",
84
66
  name: "Alice",
85
67
  email: "alice@example.com",
@@ -90,8 +72,8 @@ Or use `transact()` for atomic multi-collection operations:
90
72
 
91
73
  ```typescript
92
74
  store.transact((tx) => {
93
- tx.put("users", { id: "1", name: "Alice", email: "alice@example.com" });
94
- 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" });
95
77
  });
96
78
  ```
97
79
 
@@ -100,7 +82,7 @@ store.transact((tx) => {
100
82
  Update existing items using `patch()`:
101
83
 
102
84
  ```typescript
103
- store.patch("users", "1", {
85
+ store.users.patch("1", {
104
86
  email: "newemail@example.com",
105
87
  });
106
88
  ```
@@ -110,7 +92,7 @@ store.patch("users", "1", {
110
92
  Remove items using `remove()`:
111
93
 
112
94
  ```typescript
113
- store.remove("users", "1");
95
+ store.users.remove("1");
114
96
  ```
115
97
 
116
98
  ### Reading Data
@@ -119,10 +101,13 @@ Read data directly from the store:
119
101
 
120
102
  ```typescript
121
103
  // Get a single item
122
- const user = store.get("users", "1");
104
+ const user = store.users.get("1");
123
105
 
124
106
  // Get all items as an array
125
- 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" });
126
111
 
127
112
  // You can easily derive other operations:
128
113
  const userIds = allUsers.map((u) => u.id);
@@ -134,15 +119,9 @@ const hasUser = allUsers.some((u) => u.id === "1");
134
119
  Subscribe to changes with `subscribe()`:
135
120
 
136
121
  ```typescript
137
- // Subscribe to specific collections
138
- const unsubscribe = store.subscribe(["users"], (event) => {
139
- console.log("Users collection changed:", event);
140
- const allUsers = store.list("users");
141
- // Update UI, invalidate queries, etc.
142
- });
143
-
144
- // Or subscribe to all changes
145
- 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 }
146
125
  console.log("Store changed:", event);
147
126
  });
148
127
 
@@ -183,14 +162,16 @@ function useUsers() {
183
162
  const queryClient = useQueryClient();
184
163
 
185
164
  useEffect(() => {
186
- return store.subscribe(["users"], () => {
187
- queryClient.invalidateQueries({ queryKey: ["users"] });
165
+ return store.subscribe((event) => {
166
+ if ("users" in event) {
167
+ queryClient.invalidateQueries({ queryKey: ["users"] });
168
+ }
188
169
  });
189
170
  }, []);
190
171
 
191
172
  return useQuery({
192
173
  queryKey: ["users"],
193
- queryFn: () => store.list("users"),
174
+ queryFn: () => store.users.list(),
194
175
  });
195
176
  }
196
177
  ```
@@ -202,8 +183,11 @@ import { useSyncExternalStore } from "react";
202
183
 
203
184
  function useUsers() {
204
185
  return useSyncExternalStore(
205
- (callback) => store.subscribe(["users"], () => callback()),
206
- () => store.list("users"),
186
+ (callback) =>
187
+ store.subscribe((event) => {
188
+ if ("users" in event) callback();
189
+ }),
190
+ () => store.users.list(),
207
191
  );
208
192
  }
209
193
  ```
@@ -213,9 +197,11 @@ function useUsers() {
213
197
  ```typescript
214
198
  import { writable } from "svelte/store";
215
199
 
216
- const users = writable(store.list("users"));
217
- store.subscribe(["users"], () => {
218
- 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
+ }
219
205
  });
220
206
  ```
221
207
 
@@ -224,55 +210,36 @@ store.subscribe(["users"], () => {
224
210
  ```typescript
225
211
  import { ref } from "vue";
226
212
 
227
- const users = ref(store.list("users"));
228
- store.subscribe(["users"], () => {
229
- 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
+ }
230
218
  });
231
219
  ```
232
220
 
233
- ## Schema Support
234
-
235
- Starling works with any library that follows the [Standard Schema](https://github.com/standard-schema/spec) specification. This includes:
236
-
237
- - **Zod** - Most popular schema library
238
- - **Valibot** - Lightweight alternative
239
- - **ArkType** - TypeScript-first schemas
240
-
241
- You can use any of these to define your data shapes. Starling will validate your data and give you full TypeScript types.
242
-
243
- ```typescript
244
- import { z } from "zod";
245
- // or
246
- import * as v from "valibot";
247
- // or
248
- import { type } from "arktype";
249
-
250
- // All of these work the same way
251
- const schema = z.object({ id: z.string(), name: z.string() });
252
- // or
253
- const schema = v.object({ id: v.string(), name: v.string() });
254
- // or
255
- const schema = type({ id: "string", name: "string" });
256
- ```
257
-
258
221
  ## API Overview
259
222
 
260
223
  ### Main Export
261
224
 
262
225
  - `createStore(config)` - Creates a new store with collections
263
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
+
264
237
  ### Store Methods
265
238
 
266
- - `get(collection, id)` - Get a document by ID from a collection
267
- - `list(collection)` - Get all documents as an array from a collection
268
- - `put(collection, data)` - Insert or replace a document (upsert, revives tombstoned IDs)
269
- - `patch(collection, id, data)` - Partially update an existing document (throws if ID missing)
270
- - `remove(collection, id)` - Remove a document
271
- - `transact(callback)` - Execute operations atomically. Collections are cloned lazily on first access.
272
- - `subscribe(callback)` - Subscribe to all collection changes
273
- - `subscribe(collections, callback)` - Subscribe to changes in specific collections
274
- - `getState()` - Get current store state as a snapshot
275
- - `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
276
243
 
277
244
  For full type definitions, see the TypeScript types exported from the package.
278
245
 
@@ -280,7 +247,6 @@ For full type definitions, see the TypeScript types exported from the package.
280
247
 
281
248
  - **`lib/core/`** – CRDT primitives: hybrid logical clock, per-field atoms (LWW), tombstones, and document/collection merging.
282
249
  - **`lib/store/`** – Store API with collections, batching, queries, and change subscriptions.
283
- - **`lib/middleware/`** – Optional middleware (e.g. persistence).
284
250
 
285
251
  ## Development
286
252
 
package/dist/index.d.ts CHANGED
@@ -1,212 +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 ListOptions<T> = {
158
- where?: (doc: T) => boolean;
159
- };
160
- type TransactionAPI<T extends StoreConfig> = {
161
- get<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): DocType<T[N]> | undefined;
162
- list<N extends CollectionName<T>>(collection: N, options?: ListOptions<DocType<T[N]>>): DocType<T[N]>[];
163
- put<N extends CollectionName<T>>(collection: N, data: InputType<T[N]>): DocType<T[N]>;
164
- patch<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>, data: Partial<DocType<T[N]>>): DocType<T[N]>;
165
- 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;
166
58
  };
167
- declare class Store<T extends StoreConfig> {
168
- #private;
169
- constructor(config: T);
170
- get<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): DocType<T[N]> | undefined;
171
- list<N extends CollectionName<T>>(collection: N, options?: ListOptions<DocType<T[N]>>): DocType<T[N]>[];
172
- put<N extends CollectionName<T>>(collection: N, data: InputType<T[N]>): DocType<T[N]>;
173
- patch<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>, data: Partial<DocType<T[N]>>): DocType<T[N]>;
174
- 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]> } & {
175
62
  subscribe(callback: (event: StoreChangeEvent<T>) => void): () => void;
176
63
  getState(): StoreState;
177
64
  merge(snapshot: StoreState): StoreChangeEvent<T>;
178
65
  transact<R>(callback: (tx: TransactionAPI<T>) => R): R;
179
- }
180
- declare function createStore<T extends StoreConfig>(config: T): Store<T>;
181
- //#endregion
182
- //#region lib/store/operations.d.ts
183
- declare function doGet<T extends Document>(docs: Collection<T>, tombstones: Tombstones, id: string): T | undefined;
184
- declare function doList<T extends Document>(docs: Collection<T>, tombstones: Tombstones, where?: (doc: T) => boolean): T[];
185
- declare function doPut<T extends Document>(docs: Collection<T>, tombstones: Tombstones, data: T, stamp: Stamp, validateFn: (data: unknown) => T, getId: (data: T) => string): T;
186
- declare function doPatch<T extends Document>(docs: Collection<T>, id: string, data: Partial<T>, stamp: Stamp, validateFn: (data: unknown) => T): T;
187
- declare function doRemove(docs: Collection<Document>, tombstones: Tombstones, id: string, stamp: Stamp): void;
188
- 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> }>;
189
84
  //#endregion
190
- //#region lib/persisters/idb-persister.d.ts
191
- interface IPersister {
192
- init(): Promise<void>;
193
- dispose(): Promise<void>;
194
- }
195
- type PersistenceOptions = {
196
- key: string;
197
- storeName?: string;
198
- debounceMs?: number;
199
- channelName?: string;
200
- serialize?: (state: StoreState) => string;
201
- 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;
202
90
  };
203
- declare class IdbPersister<T extends StoreConfig> implements IPersister {
204
- #private;
205
- constructor(store: Store<T>, options: PersistenceOptions);
206
- init(): Promise<void>;
207
- dispose(): Promise<void>;
208
- subscribe(listener: (serialized: string) => void): () => void;
209
- }
91
+ declare function createQuery<T extends StoreConfig, R>(store: Store<T>, predicate: (store: Store<T>) => R, dependencies: CollectionName<T>[]): Query<R>;
210
92
  //#endregion
211
- export { AnyObject, Atom, AtomizedDocument, Clock, Collection, CollectionDef, CollectionName, CollectionState, DocType, Document, IPersister, IdType, IdbPersister, Input, InputType, KEYS, ListOptions, 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 };
212
94
  //# sourceMappingURL=index.d.ts.map