@byearlybird/starling 0.14.0 → 0.17.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
@@ -17,7 +17,7 @@ Requires TypeScript 5 or higher.
17
17
  ## Quick Example
18
18
 
19
19
  ```typescript
20
- import { createStore } from "@byearlybird/starling";
20
+ import { createStore, collection } from "@byearlybird/starling";
21
21
  import { z } from "zod";
22
22
 
23
23
  const userSchema = z.object({
@@ -26,12 +26,10 @@ const userSchema = z.object({
26
26
  });
27
27
 
28
28
  const store = createStore({
29
- collections: {
30
- users: { schema: userSchema },
31
- },
29
+ users: collection(userSchema, (data) => data.id),
32
30
  });
33
31
 
34
- store.add("users", { id: "1", name: "Alice" });
32
+ store.put("users", { id: "1", name: "Alice" });
35
33
  const user = store.get("users", "1"); // { id: "1", name: "Alice" }
36
34
  ```
37
35
 
@@ -52,53 +50,62 @@ const user = store.get("users", "1"); // { id: "1", name: "Alice" }
52
50
  A store holds one or more collections. Each collection has a schema that defines what data it can store.
53
51
 
54
52
  ```typescript
55
- import { createStore } from "@byearlybird/starling";
53
+ import { createStore, collection } from "@byearlybird/starling";
56
54
  import { z } from "zod";
57
55
 
58
56
  const store = createStore({
59
- collections: {
60
- users: {
61
- schema: z.object({
62
- id: z.string(),
63
- name: z.string(),
64
- email: z.string().optional(),
65
- }),
66
- },
67
- notes: {
68
- schema: z.object({
69
- id: z.string(),
70
- content: z.string(),
71
- }),
72
- },
73
- },
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
+ ),
74
72
  });
75
73
  ```
76
74
 
77
75
  ### Adding Documents
78
76
 
79
- Add new items to a collection with `add()`:
77
+ Add new items to a collection using `put()`:
80
78
 
81
79
  ```typescript
82
- store.add("users", {
80
+ store.put("users", {
83
81
  id: "1",
84
82
  name: "Alice",
85
83
  email: "alice@example.com",
86
84
  });
87
85
  ```
88
86
 
87
+ Or use `transact()` for atomic multi-collection operations:
88
+
89
+ ```typescript
90
+ store.transact((tx) => {
91
+ tx.put("users", { id: "1", name: "Alice", email: "alice@example.com" });
92
+ tx.put("notes", { id: "n1", content: "Hello" });
93
+ });
94
+ ```
95
+
89
96
  ### Updating Documents
90
97
 
91
- Update existing items with `update()`:
98
+ Update existing items using `patch()`:
92
99
 
93
100
  ```typescript
94
- store.update("users", "1", {
101
+ store.patch("users", "1", {
95
102
  email: "newemail@example.com",
96
103
  });
97
104
  ```
98
105
 
99
106
  ### Removing Documents
100
107
 
101
- Remove items with `remove()`:
108
+ Remove items using `remove()`:
102
109
 
103
110
  ```typescript
104
111
  store.remove("users", "1");
@@ -106,14 +113,14 @@ store.remove("users", "1");
106
113
 
107
114
  ### Reading Data
108
115
 
109
- The store provides simple getter methods:
116
+ Read data directly from the store:
110
117
 
111
118
  ```typescript
112
119
  // Get a single item
113
120
  const user = store.get("users", "1");
114
121
 
115
122
  // Get all items as an array
116
- const allUsers = store.getAll("users");
123
+ const allUsers = store.list("users");
117
124
 
118
125
  // You can easily derive other operations:
119
126
  const userIds = allUsers.map((u) => u.id);
@@ -122,75 +129,48 @@ const hasUser = allUsers.some((u) => u.id === "1");
122
129
 
123
130
  ### Listening to Changes
124
131
 
125
- Subscribe to changes with `onChange()`:
132
+ Subscribe to changes with `subscribe()`:
126
133
 
127
134
  ```typescript
128
- // Listen to all store changes
129
- store.onChange((event) => {
130
- console.log(`${event.collection} changed:`, event.event.type);
131
- // Invalidate queries, update UI, etc.
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.
132
140
  });
133
141
 
134
- // Filter for specific collection changes
135
- store.onChange((event) => {
136
- if (event.collection === "users") {
137
- console.log("User change:", event.event.type, event.event.id);
138
- if (event.event.type === "add") {
139
- console.log("New user:", event.event.data);
140
- }
141
- }
142
+ // Or subscribe to all changes
143
+ store.subscribe((event) => {
144
+ console.log("Store changed:", event);
142
145
  });
146
+
147
+ // Later, unsubscribe
148
+ unsubscribe();
143
149
  ```
144
150
 
145
151
  ## Merging Data
146
152
 
147
153
  Starling's core feature is conflict-free merging. When data changes in multiple places, Starling automatically resolves conflicts using timestamps.
148
154
 
149
- ### Getting a Snapshot
150
-
151
- Get the current state of your store:
155
+ Merge snapshots directly:
152
156
 
153
157
  ```typescript
154
- const snapshot = store.getSnapshot();
155
- // { clock: { ms: ..., seq: ... }, collections: { ... } }
156
- ```
157
-
158
- ### Merging a Snapshot
158
+ // Get current state as a snapshot
159
+ const snapshot = store.getState();
159
160
 
160
- Merge a snapshot from another device or user:
161
-
162
- ```typescript
163
- // Get snapshot from another device
164
- const otherSnapshot = await fetchFromServer();
161
+ // Send to server or save locally
162
+ await sendToServer(snapshot);
165
163
 
166
- // Merge it into your store
167
- store.merge(otherSnapshot);
164
+ // Later, merge a snapshot from another source
165
+ const remoteSnapshot = await fetchFromServer();
166
+ store.merge(remoteSnapshot);
168
167
  ```
169
168
 
170
169
  Starling automatically resolves conflicts. If the same field was changed in both places, it keeps the change with the newer timestamp (Last-Write-Wins).
171
170
 
172
- ### Syncing Between Two Stores
173
-
174
- Here's a simple example of syncing between two stores:
175
-
176
- ```typescript
177
- const store1 = createStore({ collections: { users: { schema: userSchema } } });
178
- const store2 = createStore({ collections: { users: { schema: userSchema } } });
179
-
180
- // Add data to store1
181
- store1.add("users", { id: "1", name: "Alice" });
182
-
183
- // Sync to store2
184
- const snapshot = store1.getSnapshot();
185
- store2.merge(snapshot);
186
-
187
- // Now store2 has the same data
188
- console.log(store2.get("users", "1")); // { id: "1", name: "Alice" }
189
- ```
190
-
191
171
  ## Reactivity Integration
192
172
 
193
- Starling is framework-agnostic. Use `onChange()` to integrate with your reactive system:
173
+ Starling is framework-agnostic. Use `subscribe()` to integrate with your reactive system:
194
174
 
195
175
  ### React with TanStack Query
196
176
 
@@ -201,16 +181,14 @@ function useUsers() {
201
181
  const queryClient = useQueryClient();
202
182
 
203
183
  useEffect(() => {
204
- return store.onChange((event) => {
205
- if (event.collection === "users") {
206
- queryClient.invalidateQueries({ queryKey: ["users"] });
207
- }
184
+ return store.subscribe(["users"], () => {
185
+ queryClient.invalidateQueries({ queryKey: ["users"] });
208
186
  });
209
187
  }, []);
210
188
 
211
189
  return useQuery({
212
190
  queryKey: ["users"],
213
- queryFn: () => store.getAll("users"),
191
+ queryFn: () => store.list("users"),
214
192
  });
215
193
  }
216
194
  ```
@@ -222,11 +200,8 @@ import { useSyncExternalStore } from "react";
222
200
 
223
201
  function useUsers() {
224
202
  return useSyncExternalStore(
225
- (callback) =>
226
- store.onChange((event) => {
227
- if (event.collection === "users") callback();
228
- }),
229
- () => store.getAll("users"),
203
+ (callback) => store.subscribe(["users"], () => callback()),
204
+ () => store.list("users"),
230
205
  );
231
206
  }
232
207
  ```
@@ -236,11 +211,9 @@ function useUsers() {
236
211
  ```typescript
237
212
  import { writable } from "svelte/store";
238
213
 
239
- const users = writable(store.getAll("users"));
240
- store.onChange((event) => {
241
- if (event.collection === "users") {
242
- users.set(store.getAll("users"));
243
- }
214
+ const users = writable(store.list("users"));
215
+ store.subscribe(["users"], () => {
216
+ users.set(store.list("users"));
244
217
  });
245
218
  ```
246
219
 
@@ -249,11 +222,9 @@ store.onChange((event) => {
249
222
  ```typescript
250
223
  import { ref } from "vue";
251
224
 
252
- const users = ref(store.getAll("users"));
253
- store.onChange((event) => {
254
- if (event.collection === "users") {
255
- users.value = store.getAll("users");
256
- }
225
+ const users = ref(store.list("users"));
226
+ store.subscribe(["users"], () => {
227
+ users.value = store.list("users");
257
228
  });
258
229
  ```
259
230
 
@@ -290,17 +261,25 @@ const schema = type({ id: "string", name: "string" });
290
261
 
291
262
  ### Store Methods
292
263
 
293
- - `add(collection, data)` - Add a new document to a collection
294
264
  - `get(collection, id)` - Get a document by ID from a collection
295
- - `getAll(collection)` - Get all documents from a collection as an array
296
- - `update(collection, id, data)` - Update an existing document in a collection
297
- - `remove(collection, id)` - Remove a document from a collection
298
- - `getSnapshot()` - Get the full store snapshot for syncing
299
- - `merge(snapshot)` - Merge a store snapshot
300
- - `onChange(listener)` - Subscribe to all collection changes
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
301
274
 
302
275
  For full type definitions, see the TypeScript types exported from the package.
303
276
 
277
+ ## Package structure
278
+
279
+ - **`lib/core/`** – CRDT primitives: hybrid logical clock, per-field atoms (LWW), tombstones, and document/collection merging.
280
+ - **`lib/store/`** – Store API with collections, batching, queries, and change subscriptions.
281
+ - **`lib/middleware/`** – Optional middleware (e.g. persistence).
282
+
304
283
  ## Development
305
284
 
306
285
  ```bash
package/dist/index.d.ts CHANGED
@@ -5,22 +5,92 @@ type Clock = {
5
5
  ms: number;
6
6
  seq: number;
7
7
  };
8
- //#endregion
9
- //#region lib/core/document.d.ts
10
- type Field<T = unknown> = {
11
- "~value": T;
12
- "~stamp": string;
8
+ /**
9
+ * Branded type for HLC timestamps.
10
+ * Stamps are lexicographically sortable hex strings encoding (ms, seq, nonce).
11
+ */
12
+ type Stamp = string & {
13
+ readonly __brand: "Stamp";
13
14
  };
14
- type Document = Record<string, Field>;
15
+ 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
22
  //#endregion
16
23
  //#region lib/core/tombstone.d.ts
17
- type Tombstones = Record<string, string>;
24
+ type Tombstones = Record<string, Stamp>;
25
+ declare function isDeleted(id: string, tombstones: Tombstones): boolean;
26
+ declare function mergeTombstones(target: Tombstones, source: Tombstones): Tombstones;
18
27
  //#endregion
19
- //#region lib/core/collection.d.ts
20
- type DocumentId = string;
21
- type Collection = {
22
- documents: Record<DocumentId, Document>;
28
+ //#region lib/core/types.d.ts
29
+ declare const KEYS: {
30
+ readonly VAL: "~val";
31
+ readonly TS: "~ts";
23
32
  };
33
+ /**
34
+ * Base constraint for plain document shapes - any object with string keys.
35
+ */
36
+ type Document = Record<string, unknown>;
37
+ type Atom<T> = {
38
+ [KEYS.VAL]: T;
39
+ [KEYS.TS]: Stamp;
40
+ };
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>;
54
+ tombstones: Tombstones;
55
+ };
56
+ type StoreState = {
57
+ clock: Clock;
58
+ collections: Record<string, CollectionState<Document>>;
59
+ };
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>;
24
94
  //#endregion
25
95
  //#region lib/store/schema.d.ts
26
96
  /**
@@ -28,51 +98,144 @@ type Collection = {
28
98
  */
29
99
  type AnyObject = StandardSchemaV1<Record<string, any>>;
30
100
  type Output<T extends AnyObject> = StandardSchemaV1.InferOutput<T>;
31
- type Input<T extends AnyObject> = StandardSchemaV1.InferInput<T>;
101
+ type CollectionDef<T extends Document = Document, Id extends string = string> = {
102
+ readonly "~docType": T;
103
+ readonly "~idType": Id;
104
+ schema: AnyObject;
105
+ getId: (data: T) => Id;
106
+ };
107
+ /**
108
+ * Helper function to create a collection definition with proper type inference.
109
+ * This captures the schema output type directly as the document type.
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * const store = createStore({
114
+ * users: define(userSchema, (data) => data.id),
115
+ * });
116
+ * ```
117
+ */
118
+ declare function define<S extends AnyObject, Id extends string = string>(schema: S, getId: (data: Output<S>) => Id): CollectionDef<Output<S>, Id>;
119
+ /**
120
+ * Extract the document type from a CollectionDef
121
+ */
122
+ type DocType<C extends CollectionDef> = C["~docType"];
123
+ /**
124
+ * Extract the ID type from a CollectionDef
125
+ */
126
+ type IdType<C extends CollectionDef> = C["~idType"];
127
+ /**
128
+ * Configuration for all collections in a store.
129
+ * All collection definitions must be created using the `collection()` helper.
130
+ *
131
+ * Uses `any` for type parameters to allow any CollectionDef to be stored,
132
+ * while still preserving specific types through inference in createStore.
133
+ */
134
+ type StoreConfig = Record<string, CollectionDef<any, any>>;
135
+ /**
136
+ * Valid collection name from a store config
137
+ */
138
+ type CollectionName<T extends StoreConfig> = keyof T & string;
139
+ //#endregion
140
+ //#region lib/store/types.d.ts
141
+ type StoreChangeEvent<T extends StoreConfig> = { [K in keyof T]?: true };
32
142
  //#endregion
33
143
  //#region lib/store/store.d.ts
34
- type CollectionConfig<T extends AnyObject> = {
35
- schema: T;
36
- keyPath: keyof Output<T> & string;
144
+ type TransactionAPI<T extends StoreConfig> = {
145
+ get<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): DocType<T[N]> | undefined;
146
+ list<N extends CollectionName<T>>(collection: N): DocType<T[N]>[];
147
+ put<N extends CollectionName<T>>(collection: N, data: DocType<T[N]>): DocType<T[N]>;
148
+ patch<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>, data: Partial<DocType<T[N]>>): DocType<T[N]>;
149
+ remove<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): void;
37
150
  };
38
- type StoreSnapshot = {
39
- clock: Clock;
40
- collections: Record<string, Collection>;
41
- tombstones: Tombstones;
151
+ declare class Store<T extends StoreConfig> {
152
+ #private;
153
+ constructor(config: T);
154
+ get<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): DocType<T[N]> | undefined;
155
+ list<N extends CollectionName<T>>(collection: N): DocType<T[N]>[];
156
+ put<N extends CollectionName<T>>(collection: N, data: DocType<T[N]>): DocType<T[N]>;
157
+ patch<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>, data: Partial<DocType<T[N]>>): DocType<T[N]>;
158
+ remove<N extends CollectionName<T>>(collection: N, id: IdType<T[N]>): void;
159
+ subscribe(callback: (event: StoreChangeEvent<T>) => void): () => void;
160
+ getState(): StoreState;
161
+ merge(snapshot: StoreState): StoreChangeEvent<T>;
162
+ transact<R>(callback: (tx: TransactionAPI<T>) => R): R;
163
+ }
164
+ declare function createStore<T extends StoreConfig>(config: T): Store<T>;
165
+ //#endregion
166
+ //#region lib/middleware/idb-persister.d.ts
167
+ interface IPersister {
168
+ init(): Promise<void>;
169
+ dispose(): Promise<void>;
170
+ }
171
+ type PersistenceOptions = {
172
+ key: string;
173
+ storeName?: string;
174
+ debounceMs?: number;
175
+ channelName?: string;
176
+ serialize?: (state: StoreState) => string;
177
+ deserialize?: (serialized: string) => StoreState;
42
178
  };
43
- type StoreChangeEvent<T extends Record<string, CollectionConfig<AnyObject>>> = { [K in keyof T]: {
44
- type: "add";
45
- collection: K;
46
- id: DocumentId;
47
- data: Output<T[K]["schema"]>;
48
- } | {
49
- type: "update";
50
- collection: K;
51
- id: DocumentId;
52
- data: Output<T[K]["schema"]>;
53
- } | {
54
- type: "remove";
55
- collection: K;
56
- id: DocumentId;
57
- } | {
58
- type: "merge";
59
- collection: K;
60
- } }[keyof T];
61
- type StoreAPI<T extends Record<string, CollectionConfig<AnyObject>>> = {
62
- add<K$1 extends keyof T & string>(collection: K$1, data: Input<T[K$1]["schema"]>): void;
63
- get<K$1 extends keyof T & string>(collection: K$1, id: DocumentId): Output<T[K$1]["schema"]> | undefined;
64
- getAll<K$1 extends keyof T & string>(collection: K$1, options?: {
65
- where?: (item: Output<T[K$1]["schema"]>) => boolean;
66
- }): Output<T[K$1]["schema"]>[];
67
- update<K$1 extends keyof T & string>(collection: K$1, id: DocumentId, data: Partial<Input<T[K$1]["schema"]>>): void;
68
- remove<K$1 extends keyof T & string>(collection: K$1, id: DocumentId): void;
69
- getSnapshot(): StoreSnapshot;
70
- merge(snapshot: StoreSnapshot): void;
71
- onChange(listener: (event: StoreChangeEvent<T>) => void): () => void;
179
+ declare class IdbPersister<T extends StoreConfig> implements IPersister {
180
+ #private;
181
+ constructor(store: Store<T>, options: PersistenceOptions);
182
+ init(): Promise<void>;
183
+ dispose(): Promise<void>;
184
+ subscribe(listener: (serialized: string) => void): () => void;
185
+ }
186
+ //#endregion
187
+ //#region lib/middleware/debouncer.d.ts
188
+ /**
189
+ * A simple debouncer that delays callback execution until after
190
+ * a specified time has elapsed since the last trigger.
191
+ */
192
+ declare class Debouncer {
193
+ #private;
194
+ constructor(ms: number, callback: () => void | Promise<void>);
195
+ /**
196
+ * Trigger the debouncer. Resets the timer if already pending.
197
+ */
198
+ trigger(): void;
199
+ /**
200
+ * Cancel any pending execution without invoking the callback.
201
+ */
202
+ cancel(): void;
203
+ /**
204
+ * Immediately execute the callback if there's a pending timer,
205
+ * then cancel the timer. Does nothing if no timer is pending.
206
+ */
207
+ flush(): void | Promise<void>;
208
+ /**
209
+ * Check if there's a pending execution.
210
+ */
211
+ get pending(): boolean;
212
+ }
213
+ //#endregion
214
+ //#region lib/middleware/broadcast-sync.d.ts
215
+ type BroadcastSyncOptions = {
216
+ channelName: string;
217
+ onMessage: (state: StoreState) => void;
72
218
  };
73
- declare function createStore<T extends Record<string, CollectionConfig<AnyObject>>>(config: {
74
- collections: T;
75
- }): StoreAPI<T>;
219
+ /**
220
+ * Cross-tab synchronization via BroadcastChannel.
221
+ * Handles environments where BroadcastChannel is unavailable.
222
+ */
223
+ declare class BroadcastSync {
224
+ #private;
225
+ constructor(options: BroadcastSyncOptions);
226
+ /**
227
+ * Broadcast state to other tabs. Does nothing if BroadcastChannel is unavailable.
228
+ */
229
+ broadcast(state: StoreState): void;
230
+ /**
231
+ * Close the BroadcastChannel and clean up resources.
232
+ */
233
+ close(): void;
234
+ /**
235
+ * Check if BroadcastChannel is available and connected.
236
+ */
237
+ get available(): boolean;
238
+ }
76
239
  //#endregion
77
- export { type AnyObject, type CollectionConfig, type StoreAPI, type StoreChangeEvent, type StoreSnapshot, createStore };
240
+ export { type AnyObject, Atom, AtomizedDocument, BroadcastSync, type BroadcastSyncOptions, Clock, Collection, type CollectionDef, CollectionState, Debouncer, type DocType, Document, type IPersister, type IdType, IdbPersister, KEYS, type PersistenceOptions, Stamp, Store, type StoreChangeEvent, type StoreConfig, type StoreState, Tombstones, type TransactionAPI, advanceClock, asStamp, atomize, define as collection, createReadLens, createStore, isAtom, isAtomizedDocument, isCollection, isCollectionState, isDeleted, makeStamp, mergeCollections, mergeDocs, mergeTombstones, pack, unpack };
78
241
  //# sourceMappingURL=index.d.ts.map