@trestleinc/replicate 1.2.0-preview.1 → 1.2.0-preview.3
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 +131 -38
- package/dist/client/index.d.ts +96 -71
- package/dist/client/index.js +808 -695
- package/dist/component/_generated/component.d.ts +5 -17
- package/dist/component/convex.config.d.ts +2 -2
- package/dist/component/mutations.d.ts +28 -36
- package/dist/component/mutations.js +65 -83
- package/dist/component/schema.d.ts +5 -5
- package/dist/server/index.d.ts +15 -18
- package/dist/server/index.js +39 -51
- package/package.json +1 -1
- package/src/client/collection.ts +112 -77
- package/src/client/index.ts +9 -1
- package/src/client/merge.ts +1 -31
- package/src/client/ops.ts +0 -1
- package/src/client/persistence/index.ts +5 -7
- package/src/client/persistence/pglite.ts +168 -0
- package/src/client/prose.ts +113 -193
- package/src/client/services/actor.ts +197 -0
- package/src/client/services/awareness.ts +226 -114
- package/src/client/services/context.ts +21 -35
- package/src/client/services/engine.ts +31 -0
- package/src/client/services/errors.ts +36 -0
- package/src/client/services/manager.ts +159 -0
- package/src/client/services/runtime.ts +133 -0
- package/src/client/services/session.ts +21 -11
- package/src/component/_generated/component.ts +10 -16
- package/src/component/mutations.ts +74 -96
- package/src/server/collection.ts +2 -7
- package/src/server/replicate.ts +45 -53
- package/src/client/persistence/indexeddb.ts +0 -133
- package/src/client/persistence/sqlite/browser.ts +0 -168
- package/src/client/services/sync.ts +0 -122
package/README.md
CHANGED
|
@@ -145,8 +145,7 @@ export const {
|
|
|
145
145
|
mark,
|
|
146
146
|
compact,
|
|
147
147
|
sessions,
|
|
148
|
-
|
|
149
|
-
leave,
|
|
148
|
+
presence,
|
|
150
149
|
} = collection.create<Task>(components.replicate, 'tasks');
|
|
151
150
|
```
|
|
152
151
|
|
|
@@ -160,9 +159,8 @@ export const {
|
|
|
160
159
|
- `remove` - Dual-storage delete mutation (auto-compacts when threshold exceeded)
|
|
161
160
|
- `mark` - Report sync progress to server (peer tracking for safe compaction)
|
|
162
161
|
- `compact` - Manual compaction trigger (peer-aware, respects active peer sync state)
|
|
163
|
-
- `sessions` - Get connected sessions (presence query)
|
|
164
|
-
- `
|
|
165
|
-
- `leave` - Explicit disconnect mutation
|
|
162
|
+
- `sessions` - Get connected sessions with cursor positions (presence query)
|
|
163
|
+
- `presence` - Join/leave presence for collaborative editing (with cursor, user, profile)
|
|
166
164
|
|
|
167
165
|
### Step 4: Define Your Collection
|
|
168
166
|
|
|
@@ -173,7 +171,7 @@ Create a collection definition using `collection.create()`. This is SSR-safe bec
|
|
|
173
171
|
import { collection, persistence } from '@trestleinc/replicate/client';
|
|
174
172
|
import { ConvexClient } from 'convex/browser';
|
|
175
173
|
import { api } from '../../convex/_generated/api';
|
|
176
|
-
import
|
|
174
|
+
import { PGlite } from '@electric-sql/pglite';
|
|
177
175
|
import { z } from 'zod';
|
|
178
176
|
|
|
179
177
|
// Define your Zod schema (required)
|
|
@@ -189,8 +187,8 @@ export type Task = z.infer<typeof taskSchema>;
|
|
|
189
187
|
export const tasks = collection.create({
|
|
190
188
|
// Async factory - only called in browser during init()
|
|
191
189
|
persistence: async () => {
|
|
192
|
-
const
|
|
193
|
-
return persistence.
|
|
190
|
+
const db = new PGlite('idb://tasks');
|
|
191
|
+
return persistence.pglite(db, 'tasks');
|
|
194
192
|
},
|
|
195
193
|
// Sync factory - only called in browser during init()
|
|
196
194
|
config: () => ({
|
|
@@ -483,8 +481,7 @@ export const {
|
|
|
483
481
|
mark,
|
|
484
482
|
compact,
|
|
485
483
|
sessions,
|
|
486
|
-
|
|
487
|
-
leave,
|
|
484
|
+
presence,
|
|
488
485
|
} = collection.create<Task>(components.replicate, 'tasks', {
|
|
489
486
|
// Optional hooks for authorization and lifecycle events
|
|
490
487
|
hooks: {
|
|
@@ -526,10 +523,10 @@ export const {
|
|
|
526
523
|
|
|
527
524
|
### Rich Text / Prose Fields
|
|
528
525
|
|
|
529
|
-
For collaborative rich text editing, use
|
|
526
|
+
For collaborative rich text editing, use `schema.prose()` on both server and client:
|
|
530
527
|
|
|
531
528
|
```typescript
|
|
532
|
-
// convex/schema.ts
|
|
529
|
+
// convex/schema.ts (server)
|
|
533
530
|
import { schema } from '@trestleinc/replicate/server';
|
|
534
531
|
|
|
535
532
|
export default defineSchema({
|
|
@@ -541,14 +538,85 @@ export default defineSchema({
|
|
|
541
538
|
});
|
|
542
539
|
|
|
543
540
|
// Client: Extract plain text for search
|
|
544
|
-
import {
|
|
541
|
+
import { schema } from '@trestleinc/replicate/client';
|
|
545
542
|
|
|
546
|
-
const plainText = prose.extract(notebook.content);
|
|
543
|
+
const plainText = schema.prose.extract(notebook.content);
|
|
547
544
|
|
|
548
545
|
// Client: Get editor binding for ProseMirror/TipTap
|
|
549
546
|
const binding = await collection.utils.prose(notebookId, 'content');
|
|
550
547
|
```
|
|
551
548
|
|
|
549
|
+
**Important:** `collection.utils.prose()` is async and internally waits for the actor system to initialize before observing the Yjs fragment. This ensures the sync infrastructure is ready before collaborative editing begins.
|
|
550
|
+
|
|
551
|
+
```typescript
|
|
552
|
+
// React: Use useEffect with cleanup
|
|
553
|
+
useEffect(() => {
|
|
554
|
+
let binding: EditorBinding | null = null;
|
|
555
|
+
|
|
556
|
+
collection.utils.prose(docId, 'content').then((b) => {
|
|
557
|
+
binding = b;
|
|
558
|
+
// Initialize your editor with binding.fragment and binding.provider
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
return () => binding?.destroy();
|
|
562
|
+
}, [docId]);
|
|
563
|
+
|
|
564
|
+
// Svelte: Use onMount
|
|
565
|
+
onMount(async () => {
|
|
566
|
+
binding = await collection.utils.prose(docId, 'content');
|
|
567
|
+
// Initialize TipTap with binding.fragment
|
|
568
|
+
|
|
569
|
+
return () => binding?.destroy();
|
|
570
|
+
});
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
**Prose Options:**
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
interface ProseOptions {
|
|
577
|
+
user?: UserIdentity; // Collaborative presence identity
|
|
578
|
+
debounceMs?: number; // Sync debounce delay (default: 200ms)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
interface UserIdentity {
|
|
582
|
+
name?: string; // Display name for cursor labels
|
|
583
|
+
color?: string; // Cursor/selection color (hex, e.g., "#6366f1")
|
|
584
|
+
avatar?: string; // Avatar URL for presence indicators
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
**Configuration Examples:**
|
|
589
|
+
|
|
590
|
+
```typescript
|
|
591
|
+
// Minimal: Just get the binding with defaults
|
|
592
|
+
const binding = await collection.utils.prose(docId, 'content');
|
|
593
|
+
|
|
594
|
+
// With user presence for collaborative cursors
|
|
595
|
+
const binding = await collection.utils.prose(docId, 'content', {
|
|
596
|
+
user: {
|
|
597
|
+
name: 'Alice',
|
|
598
|
+
color: '#6366f1',
|
|
599
|
+
avatar: 'https://example.com/alice.jpg',
|
|
600
|
+
},
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// Custom debounce: 500ms for less frequent syncs
|
|
604
|
+
const binding = await collection.utils.prose(docId, 'content', {
|
|
605
|
+
debounceMs: 500,
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
// Real-time: No debounce (sync on every keystroke)
|
|
609
|
+
const binding = await collection.utils.prose(docId, 'content', {
|
|
610
|
+
debounceMs: 0,
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
// Full configuration
|
|
614
|
+
const binding = await collection.utils.prose(docId, 'content', {
|
|
615
|
+
user: { name: 'Alice', color: '#6366f1' },
|
|
616
|
+
debounceMs: 200,
|
|
617
|
+
});
|
|
618
|
+
```
|
|
619
|
+
|
|
552
620
|
### Persistence Providers
|
|
553
621
|
|
|
554
622
|
Choose the right storage backend for your platform. Persistence is configured in the `persistence` factory of `collection.create()`:
|
|
@@ -556,17 +624,38 @@ Choose the right storage backend for your platform. Persistence is configured in
|
|
|
556
624
|
```typescript
|
|
557
625
|
import { collection, persistence } from '@trestleinc/replicate/client';
|
|
558
626
|
|
|
559
|
-
// Browser
|
|
627
|
+
// Browser: PGlite (PostgreSQL in browser via IndexedDB)
|
|
560
628
|
export const tasks = collection.create({
|
|
561
629
|
persistence: async () => {
|
|
562
|
-
const
|
|
563
|
-
const
|
|
564
|
-
return persistence.
|
|
630
|
+
const { PGlite } = await import('@electric-sql/pglite');
|
|
631
|
+
const db = new PGlite('idb://my-app-db');
|
|
632
|
+
return persistence.pglite(db, 'tasks');
|
|
565
633
|
},
|
|
566
634
|
config: () => ({ /* ... */ }),
|
|
567
635
|
});
|
|
568
636
|
|
|
569
|
-
//
|
|
637
|
+
// Browser: PGlite singleton (shared across multiple collections)
|
|
638
|
+
// Use persistence.pglite.once() when you want one database for all collections
|
|
639
|
+
import { persistence } from '@trestleinc/replicate/client';
|
|
640
|
+
import { PGlite } from '@electric-sql/pglite';
|
|
641
|
+
|
|
642
|
+
// Create shared PGlite factory (module level)
|
|
643
|
+
const pglite = async () => {
|
|
644
|
+
const db = new PGlite('idb://my-app-db');
|
|
645
|
+
return persistence.pglite.once(db, 'my-app');
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
export const tasks = collection.create({
|
|
649
|
+
persistence: pglite, // Shared instance
|
|
650
|
+
config: () => ({ /* ... */ }),
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
export const comments = collection.create({
|
|
654
|
+
persistence: pglite, // Same shared instance
|
|
655
|
+
config: () => ({ /* ... */ }),
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
// React Native: Native SQLite (op-sqlite)
|
|
570
659
|
export const tasks = collection.create({
|
|
571
660
|
persistence: async () => {
|
|
572
661
|
const { open } = await import('@op-engineering/op-sqlite');
|
|
@@ -589,7 +678,9 @@ export const tasks = collection.create({
|
|
|
589
678
|
});
|
|
590
679
|
```
|
|
591
680
|
|
|
592
|
-
**
|
|
681
|
+
**PGlite** - PostgreSQL compiled to WASM, stored in IndexedDB. Full SQL support with reactive queries. Recommended for web apps.
|
|
682
|
+
|
|
683
|
+
**PGlite Singleton** - Use `persistence.pglite.once()` when multiple collections should share one database. Reference counted for proper cleanup.
|
|
593
684
|
|
|
594
685
|
**SQLite Native** - Uses op-sqlite for React Native. You create the database and pass it.
|
|
595
686
|
|
|
@@ -666,18 +757,18 @@ Creates a lazy-initialized collection with deferred persistence and config resol
|
|
|
666
757
|
```typescript
|
|
667
758
|
import { collection, persistence } from '@trestleinc/replicate/client';
|
|
668
759
|
import { ConvexClient } from 'convex/browser';
|
|
669
|
-
import
|
|
760
|
+
import { PGlite } from '@electric-sql/pglite';
|
|
670
761
|
|
|
671
762
|
export const tasks = collection.create({
|
|
672
763
|
persistence: async () => {
|
|
673
|
-
const
|
|
674
|
-
return persistence.
|
|
764
|
+
const db = new PGlite('idb://tasks');
|
|
765
|
+
return persistence.pglite(db, 'tasks');
|
|
675
766
|
},
|
|
676
767
|
config: () => ({
|
|
677
768
|
schema: taskSchema,
|
|
769
|
+
getKey: (task) => task.id,
|
|
678
770
|
convexClient: new ConvexClient(import.meta.env.VITE_CONVEX_URL),
|
|
679
771
|
api: api.tasks,
|
|
680
|
-
getKey: (task) => task.id,
|
|
681
772
|
}),
|
|
682
773
|
});
|
|
683
774
|
|
|
@@ -726,8 +817,8 @@ interface CollectionConfig<T> {
|
|
|
726
817
|
```typescript
|
|
727
818
|
export const tasks = collection.create({
|
|
728
819
|
persistence: async () => {
|
|
729
|
-
const
|
|
730
|
-
return persistence.
|
|
820
|
+
const db = new PGlite('idb://tasks');
|
|
821
|
+
return persistence.pglite(db, 'tasks');
|
|
731
822
|
},
|
|
732
823
|
config: () => ({
|
|
733
824
|
schema: taskSchema,
|
|
@@ -738,7 +829,7 @@ export const tasks = collection.create({
|
|
|
738
829
|
});
|
|
739
830
|
```
|
|
740
831
|
|
|
741
|
-
#### `prose.extract(proseJson)`
|
|
832
|
+
#### `schema.prose.extract(proseJson)`
|
|
742
833
|
|
|
743
834
|
Extract plain text from ProseMirror JSON.
|
|
744
835
|
|
|
@@ -749,9 +840,9 @@ Extract plain text from ProseMirror JSON.
|
|
|
749
840
|
|
|
750
841
|
**Example:**
|
|
751
842
|
```typescript
|
|
752
|
-
import {
|
|
843
|
+
import { schema } from '@trestleinc/replicate/client';
|
|
753
844
|
|
|
754
|
-
const plainText = prose.extract(task.content);
|
|
845
|
+
const plainText = schema.prose.extract(task.content);
|
|
755
846
|
```
|
|
756
847
|
|
|
757
848
|
#### Persistence Providers
|
|
@@ -760,13 +851,16 @@ const plainText = prose.extract(task.content);
|
|
|
760
851
|
import { persistence, type StorageAdapter } from '@trestleinc/replicate/client';
|
|
761
852
|
|
|
762
853
|
// Persistence providers (use in collection.create persistence factory)
|
|
763
|
-
persistence.
|
|
854
|
+
persistence.pglite(db, name) // Browser: PGlite (PostgreSQL in IndexedDB)
|
|
855
|
+
persistence.pglite.once(db, name) // Browser: PGlite singleton (shared across collections)
|
|
764
856
|
persistence.sqlite.native(db, name) // React Native: op-sqlite
|
|
765
857
|
persistence.memory() // Testing: in-memory (no persistence)
|
|
766
858
|
persistence.custom(adapter) // Custom: your StorageAdapter implementation
|
|
767
859
|
```
|
|
768
860
|
|
|
769
|
-
**`persistence.
|
|
861
|
+
**`persistence.pglite(db, name)`** - Browser persistence using PGlite (PostgreSQL compiled to WASM, stored in IndexedDB).
|
|
862
|
+
|
|
863
|
+
**`persistence.pglite.once(db, name)`** - Singleton PGlite instance for sharing across multiple collections. Reference counted for cleanup.
|
|
770
864
|
|
|
771
865
|
**`persistence.sqlite.native(db, name)`** - React Native SQLite using op-sqlite. You create the database and pass it.
|
|
772
866
|
|
|
@@ -828,7 +922,7 @@ import { collection } from '@trestleinc/replicate/server';
|
|
|
828
922
|
import { components } from './_generated/api';
|
|
829
923
|
|
|
830
924
|
export const {
|
|
831
|
-
stream, material, insert, update, remove, recovery, mark, compact, sessions,
|
|
925
|
+
stream, material, insert, update, remove, recovery, mark, compact, sessions, presence,
|
|
832
926
|
} = collection.create<Task>(components.replicate, 'tasks');
|
|
833
927
|
```
|
|
834
928
|
|
|
@@ -879,9 +973,8 @@ interface CollectionOptions<T> {
|
|
|
879
973
|
- `remove` - Dual-storage delete mutation (auto-compacts when threshold exceeded)
|
|
880
974
|
- `mark` - Peer sync tracking mutation (reports `syncedSeq` to server)
|
|
881
975
|
- `compact` - Manual compaction mutation (peer-aware, safe for active clients)
|
|
882
|
-
- `sessions` - Get connected sessions (presence query)
|
|
883
|
-
- `
|
|
884
|
-
- `leave` - Explicit disconnect mutation
|
|
976
|
+
- `sessions` - Get connected sessions with cursor positions (presence query)
|
|
977
|
+
- `presence` - Join/leave presence mutation (with cursor, user, profile)
|
|
885
978
|
|
|
886
979
|
#### `schema.table(userFields, applyIndexes?)`
|
|
887
980
|
|
|
@@ -925,7 +1018,7 @@ content: schema.prose() // Validates ProseMirror JSON structure
|
|
|
925
1018
|
import type { ProseValue } from '@trestleinc/replicate/shared';
|
|
926
1019
|
|
|
927
1020
|
// ProseValue - branded type for prose fields in Zod schemas
|
|
928
|
-
// Use
|
|
1021
|
+
// Use schema.prose() from client to create Zod fields of this type
|
|
929
1022
|
```
|
|
930
1023
|
|
|
931
1024
|
## React Native
|
|
@@ -966,11 +1059,11 @@ A full-featured offline-first issue tracker built with Replicate, demonstrating
|
|
|
966
1059
|
- [`examples/expo/`](./examples/expo/) - Expo (React Native, mobile)
|
|
967
1060
|
|
|
968
1061
|
**Web features demonstrated:**
|
|
969
|
-
- Offline-first with
|
|
1062
|
+
- Offline-first with PGlite persistence (PostgreSQL in IndexedDB)
|
|
970
1063
|
- Rich text editing with TipTap + Yjs collaboration
|
|
971
1064
|
- PWA with custom service worker
|
|
972
1065
|
- Real-time sync across devices
|
|
973
|
-
- Search with client-side text extraction (`prose.extract()`)
|
|
1066
|
+
- Search with client-side text extraction (`schema.prose.extract()`)
|
|
974
1067
|
|
|
975
1068
|
**Mobile features demonstrated (Expo):**
|
|
976
1069
|
- Native SQLite persistence (op-sqlite)
|
package/dist/client/index.d.ts
CHANGED
|
@@ -9,8 +9,39 @@ import * as effect_Types0 from "effect/Types";
|
|
|
9
9
|
import * as effect_Cause0 from "effect/Cause";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
|
|
12
|
+
//#region src/shared/types.d.ts
|
|
13
|
+
/** ProseMirror-compatible JSON for XmlFragment serialization */
|
|
14
|
+
interface XmlFragmentJSON {
|
|
15
|
+
type: "doc";
|
|
16
|
+
content?: XmlNodeJSON[];
|
|
17
|
+
}
|
|
18
|
+
declare const PROSE_BRAND: unique symbol;
|
|
19
|
+
/**
|
|
20
|
+
* Branded prose type for Zod schemas.
|
|
21
|
+
* Extends XmlFragmentJSON with a unique brand for type-level detection.
|
|
22
|
+
* Use the `prose()` helper from `@trestleinc/replicate/client` to create this type.
|
|
23
|
+
*/
|
|
24
|
+
interface ProseValue extends XmlFragmentJSON {
|
|
25
|
+
readonly [PROSE_BRAND]: typeof PROSE_BRAND;
|
|
26
|
+
}
|
|
27
|
+
/** ProseMirror node structure */
|
|
28
|
+
interface XmlNodeJSON {
|
|
29
|
+
type: string;
|
|
30
|
+
attrs?: Record<string, unknown>;
|
|
31
|
+
content?: XmlNodeJSON[];
|
|
32
|
+
text?: string;
|
|
33
|
+
marks?: {
|
|
34
|
+
type: string;
|
|
35
|
+
attrs?: Record<string, unknown>;
|
|
36
|
+
}[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Extract prose field names from T (fields typed as ProseValue).
|
|
40
|
+
* Used internally for type-safe prose field operations.
|
|
41
|
+
*/
|
|
42
|
+
type ProseFields<T> = { [K in keyof T]: T[K] extends ProseValue ? K : never }[keyof T];
|
|
43
|
+
//#endregion
|
|
12
44
|
//#region src/client/persistence/types.d.ts
|
|
13
|
-
|
|
14
45
|
/**
|
|
15
46
|
* Low-level storage adapter for custom backends (Chrome extension, localStorage, cloud).
|
|
16
47
|
* For SQLite, use `persistence.sqlite()` directly.
|
|
@@ -117,37 +148,12 @@ declare class NonRetriableError extends Error {
|
|
|
117
148
|
//#region src/client/services/seq.d.ts
|
|
118
149
|
type Seq = number;
|
|
119
150
|
//#endregion
|
|
120
|
-
//#region src/
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
151
|
+
//#region src/client/services/awareness.d.ts
|
|
152
|
+
interface UserIdentity {
|
|
153
|
+
name?: string;
|
|
154
|
+
color?: string;
|
|
155
|
+
avatar?: string;
|
|
125
156
|
}
|
|
126
|
-
declare const PROSE_BRAND: unique symbol;
|
|
127
|
-
/**
|
|
128
|
-
* Branded prose type for Zod schemas.
|
|
129
|
-
* Extends XmlFragmentJSON with a unique brand for type-level detection.
|
|
130
|
-
* Use the `prose()` helper from `@trestleinc/replicate/client` to create this type.
|
|
131
|
-
*/
|
|
132
|
-
interface ProseValue extends XmlFragmentJSON {
|
|
133
|
-
readonly [PROSE_BRAND]: typeof PROSE_BRAND;
|
|
134
|
-
}
|
|
135
|
-
/** ProseMirror node structure */
|
|
136
|
-
interface XmlNodeJSON {
|
|
137
|
-
type: string;
|
|
138
|
-
attrs?: Record<string, unknown>;
|
|
139
|
-
content?: XmlNodeJSON[];
|
|
140
|
-
text?: string;
|
|
141
|
-
marks?: {
|
|
142
|
-
type: string;
|
|
143
|
-
attrs?: Record<string, unknown>;
|
|
144
|
-
}[];
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Extract prose field names from T (fields typed as ProseValue).
|
|
148
|
-
* Used internally for type-safe prose field operations.
|
|
149
|
-
*/
|
|
150
|
-
type ProseFields<T> = { [K in keyof T]: T[K] extends ProseValue ? K : never }[keyof T];
|
|
151
157
|
//#endregion
|
|
152
158
|
//#region src/client/collection.d.ts
|
|
153
159
|
/** Server-rendered material data for SSR hydration */
|
|
@@ -171,8 +177,7 @@ interface ConvexCollectionApi {
|
|
|
171
177
|
compact: FunctionReference<"mutation">;
|
|
172
178
|
material?: FunctionReference<"query">;
|
|
173
179
|
sessions?: FunctionReference<"query">;
|
|
174
|
-
|
|
175
|
-
leave?: FunctionReference<"mutation">;
|
|
180
|
+
presence?: FunctionReference<"mutation">;
|
|
176
181
|
}
|
|
177
182
|
interface ConvexCollectionConfig<T extends object = object, TSchema extends StandardSchemaV1 = never, TKey extends string | number = string | number> extends BaseCollectionConfig<T, TKey, TSchema> {
|
|
178
183
|
schema: TSchema;
|
|
@@ -206,16 +211,18 @@ interface EditorBinding {
|
|
|
206
211
|
/** Cleanup - call when unmounting editor */
|
|
207
212
|
destroy(): void;
|
|
208
213
|
}
|
|
209
|
-
|
|
210
|
-
|
|
214
|
+
interface ProseOptions {
|
|
215
|
+
/** User identity for collaborative presence */
|
|
216
|
+
user?: UserIdentity;
|
|
211
217
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
* @
|
|
215
|
-
* @param field - The prose field name (must be in `prose` config)
|
|
216
|
-
* @returns Promise resolving to EditorBinding
|
|
218
|
+
* Debounce delay in milliseconds before syncing changes to server.
|
|
219
|
+
* Local changes are batched during this window for efficiency.
|
|
220
|
+
* @default 200
|
|
217
221
|
*/
|
|
218
|
-
|
|
222
|
+
debounceMs?: number;
|
|
223
|
+
}
|
|
224
|
+
interface ConvexCollectionUtils<T extends object> {
|
|
225
|
+
prose(document: string, field: ProseFields<T>, options?: ProseOptions): Promise<EditorBinding>;
|
|
219
226
|
}
|
|
220
227
|
type LazyCollectionConfig<TSchema extends z.ZodObject<z.ZodRawShape>> = Omit<ConvexCollectionConfig<z.infer<TSchema>, TSchema, string>, "persistence" | "material">;
|
|
221
228
|
interface LazyCollection<T extends object> {
|
|
@@ -240,8 +247,8 @@ declare function extract(content: unknown): string;
|
|
|
240
247
|
//#endregion
|
|
241
248
|
//#region src/client/prose.d.ts
|
|
242
249
|
declare function emptyProse(): ProseValue;
|
|
243
|
-
declare function prose
|
|
244
|
-
declare namespace prose
|
|
250
|
+
declare function prose(): z.ZodType<ProseValue>;
|
|
251
|
+
declare namespace prose {
|
|
245
252
|
var empty: typeof emptyProse;
|
|
246
253
|
}
|
|
247
254
|
//#endregion
|
|
@@ -262,23 +269,6 @@ declare namespace prose$1 {
|
|
|
262
269
|
*/
|
|
263
270
|
declare function memoryPersistence(): Persistence;
|
|
264
271
|
//#endregion
|
|
265
|
-
//#region src/client/persistence/sqlite/browser.d.ts
|
|
266
|
-
interface SqlJsDatabase {
|
|
267
|
-
run(sql: string, params?: unknown): unknown;
|
|
268
|
-
prepare(sql: string): {
|
|
269
|
-
bind(params?: unknown): void;
|
|
270
|
-
step(): boolean;
|
|
271
|
-
getAsObject(): Record<string, unknown>;
|
|
272
|
-
free(): void;
|
|
273
|
-
};
|
|
274
|
-
export(): Uint8Array;
|
|
275
|
-
close(): void;
|
|
276
|
-
}
|
|
277
|
-
interface SqlJsStatic {
|
|
278
|
-
Database: new (data?: ArrayLike<number> | Buffer | null) => SqlJsDatabase;
|
|
279
|
-
}
|
|
280
|
-
declare function createBrowserSqlitePersistence(SQL: SqlJsStatic, dbName: string): Promise<Persistence>;
|
|
281
|
-
//#endregion
|
|
282
272
|
//#region src/client/persistence/sqlite/native.d.ts
|
|
283
273
|
interface OPSQLiteDatabase {
|
|
284
274
|
execute(sql: string, params?: unknown[]): Promise<{
|
|
@@ -288,20 +278,52 @@ interface OPSQLiteDatabase {
|
|
|
288
278
|
}
|
|
289
279
|
declare function createNativeSqlitePersistence(db: OPSQLiteDatabase, _dbName: string): Promise<Persistence>;
|
|
290
280
|
//#endregion
|
|
291
|
-
//#region src/client/persistence/indexeddb.d.ts
|
|
292
|
-
declare function createIndexedDBPersistence(dbName: string): Promise<Persistence>;
|
|
293
|
-
//#endregion
|
|
294
281
|
//#region src/client/persistence/custom.d.ts
|
|
295
282
|
declare function createCustomPersistence(adapter: StorageAdapter): Persistence;
|
|
296
283
|
//#endregion
|
|
284
|
+
//#region src/client/persistence/pglite.d.ts
|
|
285
|
+
interface PGliteInterface {
|
|
286
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
|
|
287
|
+
rows: T[];
|
|
288
|
+
}>;
|
|
289
|
+
exec(sql: string): Promise<unknown>;
|
|
290
|
+
close(): Promise<void>;
|
|
291
|
+
}
|
|
292
|
+
declare function createPGlitePersistence(pg: PGliteInterface): Promise<Persistence>;
|
|
293
|
+
/**
|
|
294
|
+
* Creates a singleton PGlite persistence factory.
|
|
295
|
+
* Use this to ensure the PGlite WASM module is only loaded once,
|
|
296
|
+
* even when shared across multiple collections.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```typescript
|
|
300
|
+
* // src/lib/pglite.ts
|
|
301
|
+
* import { persistence } from "@trestleinc/replicate/client";
|
|
302
|
+
*
|
|
303
|
+
* export const pglite = persistence.pglite.once(async () => {
|
|
304
|
+
* const { PGlite } = await import("@electric-sql/pglite");
|
|
305
|
+
* const { live } = await import("@electric-sql/pglite/live");
|
|
306
|
+
* return PGlite.create({ dataDir: "idb://app", extensions: { live } });
|
|
307
|
+
* });
|
|
308
|
+
*
|
|
309
|
+
* // src/collections/useIntervals.ts
|
|
310
|
+
* import { pglite } from "$lib/pglite";
|
|
311
|
+
*
|
|
312
|
+
* export const intervals = collection.create({
|
|
313
|
+
* persistence: pglite,
|
|
314
|
+
* config: () => ({ ... }),
|
|
315
|
+
* });
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
declare function oncePGlitePersistence(factory: () => Promise<PGliteInterface>): () => Promise<Persistence>;
|
|
319
|
+
//#endregion
|
|
297
320
|
//#region src/client/persistence/index.d.ts
|
|
298
321
|
declare const persistence: {
|
|
299
|
-
readonly
|
|
300
|
-
|
|
301
|
-
readonly browser: typeof createBrowserSqlitePersistence;
|
|
302
|
-
readonly native: typeof createNativeSqlitePersistence;
|
|
322
|
+
readonly pglite: typeof createPGlitePersistence & {
|
|
323
|
+
once: typeof oncePGlitePersistence;
|
|
303
324
|
};
|
|
304
|
-
readonly
|
|
325
|
+
readonly sqlite: typeof createNativeSqlitePersistence;
|
|
326
|
+
readonly memory: typeof memoryPersistence;
|
|
305
327
|
readonly custom: typeof createCustomPersistence;
|
|
306
328
|
};
|
|
307
329
|
//#endregion
|
|
@@ -315,8 +337,11 @@ declare const errors: {
|
|
|
315
337
|
readonly CollectionNotReady: typeof CollectionNotReadyError;
|
|
316
338
|
readonly NonRetriable: typeof NonRetriableError;
|
|
317
339
|
};
|
|
318
|
-
declare const
|
|
319
|
-
|
|
340
|
+
declare const schema: {
|
|
341
|
+
readonly prose: typeof prose & {
|
|
342
|
+
extract: typeof extract;
|
|
343
|
+
empty: () => ProseValue;
|
|
344
|
+
};
|
|
320
345
|
};
|
|
321
346
|
//#endregion
|
|
322
|
-
export { type ConvexCollection, type EditorBinding, type Materialized, type Persistence, type Seq, type StorageAdapter, collection, errors, persistence,
|
|
347
|
+
export { type ConvexCollection, type EditorBinding, type Materialized, type Persistence, type ProseOptions, type Seq, type StorageAdapter, type UserIdentity, collection, errors, persistence, schema };
|