@trestleinc/replicate 1.1.1 → 1.1.2-preview.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.
Files changed (91) hide show
  1. package/README.md +395 -146
  2. package/dist/client/index.d.ts +311 -19
  3. package/dist/client/index.js +4027 -0
  4. package/dist/component/_generated/api.d.ts +13 -17
  5. package/dist/component/_generated/api.js +24 -4
  6. package/dist/component/_generated/component.d.ts +79 -77
  7. package/dist/component/_generated/component.js +1 -0
  8. package/dist/component/_generated/dataModel.d.ts +12 -15
  9. package/dist/component/_generated/dataModel.js +1 -0
  10. package/dist/component/_generated/server.d.ts +19 -22
  11. package/dist/component/_generated/server.js +65 -1
  12. package/dist/component/_virtual/rolldown_runtime.js +18 -0
  13. package/dist/component/convex.config.d.ts +6 -2
  14. package/dist/component/convex.config.js +7 -3
  15. package/dist/component/logger.d.ts +10 -6
  16. package/dist/component/logger.js +25 -28
  17. package/dist/component/public.d.ts +70 -61
  18. package/dist/component/public.js +311 -295
  19. package/dist/component/schema.d.ts +53 -45
  20. package/dist/component/schema.js +26 -32
  21. package/dist/component/shared/types.d.ts +9 -0
  22. package/dist/component/shared/types.js +15 -0
  23. package/dist/server/index.d.ts +134 -13
  24. package/dist/server/index.js +368 -0
  25. package/dist/shared/index.d.ts +27 -3
  26. package/dist/shared/index.js +1 -2
  27. package/package.json +34 -29
  28. package/src/client/collection.ts +339 -306
  29. package/src/client/errors.ts +9 -9
  30. package/src/client/index.ts +13 -32
  31. package/src/client/logger.ts +2 -2
  32. package/src/client/merge.ts +37 -34
  33. package/src/client/persistence/custom.ts +84 -0
  34. package/src/client/persistence/index.ts +9 -46
  35. package/src/client/persistence/indexeddb.ts +111 -84
  36. package/src/client/persistence/memory.ts +3 -3
  37. package/src/client/persistence/sqlite/browser.ts +168 -0
  38. package/src/client/persistence/sqlite/native.ts +29 -0
  39. package/src/client/persistence/sqlite/schema.ts +124 -0
  40. package/src/client/persistence/types.ts +32 -28
  41. package/src/client/prose-schema.ts +55 -0
  42. package/src/client/prose.ts +28 -25
  43. package/src/client/replicate.ts +5 -5
  44. package/src/client/services/cursor.ts +109 -0
  45. package/src/component/_generated/component.ts +31 -29
  46. package/src/component/convex.config.ts +2 -2
  47. package/src/component/logger.ts +7 -7
  48. package/src/component/public.ts +225 -237
  49. package/src/component/schema.ts +18 -15
  50. package/src/server/builder.ts +20 -7
  51. package/src/server/index.ts +3 -5
  52. package/src/server/schema.ts +5 -5
  53. package/src/server/storage.ts +113 -59
  54. package/src/shared/index.ts +5 -5
  55. package/src/shared/types.ts +51 -14
  56. package/dist/client/collection.d.ts +0 -96
  57. package/dist/client/errors.d.ts +0 -59
  58. package/dist/client/logger.d.ts +0 -2
  59. package/dist/client/merge.d.ts +0 -77
  60. package/dist/client/persistence/adapters/index.d.ts +0 -8
  61. package/dist/client/persistence/adapters/opsqlite.d.ts +0 -46
  62. package/dist/client/persistence/adapters/sqljs.d.ts +0 -83
  63. package/dist/client/persistence/index.d.ts +0 -49
  64. package/dist/client/persistence/indexeddb.d.ts +0 -17
  65. package/dist/client/persistence/memory.d.ts +0 -16
  66. package/dist/client/persistence/sqlite-browser.d.ts +0 -51
  67. package/dist/client/persistence/sqlite-level.d.ts +0 -63
  68. package/dist/client/persistence/sqlite-rn.d.ts +0 -36
  69. package/dist/client/persistence/sqlite.d.ts +0 -47
  70. package/dist/client/persistence/types.d.ts +0 -42
  71. package/dist/client/prose.d.ts +0 -56
  72. package/dist/client/replicate.d.ts +0 -40
  73. package/dist/client/services/checkpoint.d.ts +0 -18
  74. package/dist/client/services/reconciliation.d.ts +0 -24
  75. package/dist/index.js +0 -1618
  76. package/dist/server/builder.d.ts +0 -94
  77. package/dist/server/schema.d.ts +0 -27
  78. package/dist/server/storage.d.ts +0 -80
  79. package/dist/server.js +0 -281
  80. package/dist/shared/types.d.ts +0 -50
  81. package/dist/shared/types.js +0 -6
  82. package/dist/shared.js +0 -6
  83. package/src/client/persistence/adapters/index.ts +0 -8
  84. package/src/client/persistence/adapters/opsqlite.ts +0 -54
  85. package/src/client/persistence/adapters/sqljs.ts +0 -128
  86. package/src/client/persistence/sqlite-browser.ts +0 -107
  87. package/src/client/persistence/sqlite-level.ts +0 -407
  88. package/src/client/persistence/sqlite-rn.ts +0 -44
  89. package/src/client/persistence/sqlite.ts +0 -160
  90. package/src/client/services/checkpoint.ts +0 -86
  91. package/src/client/services/reconciliation.ts +0 -108
@@ -0,0 +1,368 @@
1
+ import { v } from "convex/values";
2
+ import { defineTable, mutationGeneric, queryGeneric } from "convex/server";
3
+
4
+ //#region src/shared/types.ts
5
+ const SIZE_MULTIPLIERS = {
6
+ kb: 1024,
7
+ mb: 1024 ** 2,
8
+ gb: 1024 ** 3
9
+ };
10
+ const DURATION_MULTIPLIERS = {
11
+ m: 6e4,
12
+ h: 36e5,
13
+ d: 864e5
14
+ };
15
+ function parseSize(s) {
16
+ const match = /^(\d+)(kb|mb|gb)$/i.exec(s);
17
+ if (!match) throw new Error(`Invalid size: ${s}`);
18
+ const [, num, unit] = match;
19
+ return parseInt(num) * SIZE_MULTIPLIERS[unit.toLowerCase()];
20
+ }
21
+ function parseDuration(s) {
22
+ const match = /^(\d+)(m|h|d)$/i.exec(s);
23
+ if (!match) throw new Error(`Invalid duration: ${s}`);
24
+ const [, num, unit] = match;
25
+ return parseInt(num) * DURATION_MULTIPLIERS[unit.toLowerCase()];
26
+ }
27
+
28
+ //#endregion
29
+ //#region src/server/storage.ts
30
+ const BYTES_PER_MB = 1024 * 1024;
31
+ const MS_PER_HOUR = 3600 * 1e3;
32
+ const DEFAULT_SIZE_THRESHOLD_5MB = 5 * BYTES_PER_MB;
33
+ const DEFAULT_PEER_TIMEOUT_24H = 24 * MS_PER_HOUR;
34
+ var Replicate = class {
35
+ sizeThreshold;
36
+ peerTimeout;
37
+ constructor(component, collectionName, compaction) {
38
+ this.component = component;
39
+ this.collectionName = collectionName;
40
+ this.sizeThreshold = compaction?.sizeThreshold ? parseSize(compaction.sizeThreshold) : DEFAULT_SIZE_THRESHOLD_5MB;
41
+ this.peerTimeout = compaction?.peerTimeout ? parseDuration(compaction.peerTimeout) : DEFAULT_PEER_TIMEOUT_24H;
42
+ }
43
+ createStreamQuery(opts) {
44
+ const component = this.component;
45
+ const collection = this.collectionName;
46
+ return queryGeneric({
47
+ args: {
48
+ cursor: v.number(),
49
+ limit: v.optional(v.number()),
50
+ sizeThreshold: v.optional(v.number())
51
+ },
52
+ returns: v.object({
53
+ changes: v.array(v.object({
54
+ documentId: v.string(),
55
+ crdtBytes: v.bytes(),
56
+ seq: v.number(),
57
+ operationType: v.string()
58
+ })),
59
+ cursor: v.number(),
60
+ hasMore: v.boolean(),
61
+ compact: v.optional(v.string())
62
+ }),
63
+ handler: async (ctx, args) => {
64
+ if (opts?.evalRead) await opts.evalRead(ctx, collection);
65
+ const result = await ctx.runQuery(component.public.stream, {
66
+ collection,
67
+ cursor: args.cursor,
68
+ limit: args.limit,
69
+ sizeThreshold: args.sizeThreshold
70
+ });
71
+ if (opts?.onStream) await opts.onStream(ctx, result);
72
+ return result;
73
+ }
74
+ });
75
+ }
76
+ createSSRQuery(opts) {
77
+ const collection = this.collectionName;
78
+ const component = this.component;
79
+ return queryGeneric({
80
+ args: {},
81
+ returns: v.object({
82
+ documents: v.any(),
83
+ cursor: v.optional(v.number()),
84
+ count: v.number(),
85
+ crdtBytes: v.optional(v.bytes())
86
+ }),
87
+ handler: async (ctx) => {
88
+ if (opts?.evalRead) await opts.evalRead(ctx, collection);
89
+ let docs = await ctx.db.query(collection).collect();
90
+ if (opts?.transform) docs = await opts.transform(docs);
91
+ const response = {
92
+ documents: docs,
93
+ count: docs.length
94
+ };
95
+ if (opts?.includeCRDTState) {
96
+ const crdtState = await ctx.runQuery(component.public.getInitialState, { collection });
97
+ if (crdtState) {
98
+ response.crdtBytes = crdtState.crdtBytes;
99
+ response.cursor = crdtState.cursor;
100
+ }
101
+ }
102
+ return response;
103
+ }
104
+ });
105
+ }
106
+ createInsertMutation(opts) {
107
+ const component = this.component;
108
+ const collection = this.collectionName;
109
+ return mutationGeneric({
110
+ args: {
111
+ documentId: v.string(),
112
+ crdtBytes: v.bytes(),
113
+ materializedDoc: v.any()
114
+ },
115
+ returns: v.object({
116
+ success: v.boolean(),
117
+ seq: v.number()
118
+ }),
119
+ handler: async (ctx, args) => {
120
+ const doc = args.materializedDoc;
121
+ if (opts?.evalWrite) await opts.evalWrite(ctx, doc);
122
+ const result = await ctx.runMutation(component.public.insertDocument, {
123
+ collection,
124
+ documentId: args.documentId,
125
+ crdtBytes: args.crdtBytes
126
+ });
127
+ await ctx.db.insert(collection, {
128
+ id: args.documentId,
129
+ ...args.materializedDoc,
130
+ timestamp: Date.now()
131
+ });
132
+ if (opts?.onInsert) await opts.onInsert(ctx, doc);
133
+ return {
134
+ success: true,
135
+ seq: result.seq
136
+ };
137
+ }
138
+ });
139
+ }
140
+ createUpdateMutation(opts) {
141
+ const component = this.component;
142
+ const collection = this.collectionName;
143
+ return mutationGeneric({
144
+ args: {
145
+ documentId: v.string(),
146
+ crdtBytes: v.bytes(),
147
+ materializedDoc: v.any()
148
+ },
149
+ returns: v.object({
150
+ success: v.boolean(),
151
+ seq: v.number()
152
+ }),
153
+ handler: async (ctx, args) => {
154
+ const doc = args.materializedDoc;
155
+ if (opts?.evalWrite) await opts.evalWrite(ctx, doc);
156
+ const result = await ctx.runMutation(component.public.updateDocument, {
157
+ collection,
158
+ documentId: args.documentId,
159
+ crdtBytes: args.crdtBytes
160
+ });
161
+ const existing = await ctx.db.query(collection).withIndex("by_doc_id", (q) => q.eq("id", args.documentId)).first();
162
+ if (existing) await ctx.db.patch(existing._id, {
163
+ ...args.materializedDoc,
164
+ timestamp: Date.now()
165
+ });
166
+ if (opts?.onUpdate) await opts.onUpdate(ctx, doc);
167
+ return {
168
+ success: true,
169
+ seq: result.seq
170
+ };
171
+ }
172
+ });
173
+ }
174
+ createRemoveMutation(opts) {
175
+ const component = this.component;
176
+ const collection = this.collectionName;
177
+ return mutationGeneric({
178
+ args: {
179
+ documentId: v.string(),
180
+ crdtBytes: v.bytes()
181
+ },
182
+ returns: v.object({
183
+ success: v.boolean(),
184
+ seq: v.number()
185
+ }),
186
+ handler: async (ctx, args) => {
187
+ const documentId = args.documentId;
188
+ if (opts?.evalRemove) await opts.evalRemove(ctx, documentId);
189
+ const result = await ctx.runMutation(component.public.deleteDocument, {
190
+ collection,
191
+ documentId,
192
+ crdtBytes: args.crdtBytes
193
+ });
194
+ const existing = await ctx.db.query(collection).withIndex("by_doc_id", (q) => q.eq("id", documentId)).first();
195
+ if (existing) await ctx.db.delete(existing._id);
196
+ if (opts?.onRemove) await opts.onRemove(ctx, documentId);
197
+ return {
198
+ success: true,
199
+ seq: result.seq
200
+ };
201
+ }
202
+ });
203
+ }
204
+ createMarkMutation(opts) {
205
+ const component = this.component;
206
+ const collection = this.collectionName;
207
+ return mutationGeneric({
208
+ args: {
209
+ peerId: v.string(),
210
+ syncedSeq: v.number()
211
+ },
212
+ returns: v.null(),
213
+ handler: async (ctx, args) => {
214
+ if (opts?.evalWrite) await opts.evalWrite(ctx, args.peerId);
215
+ await ctx.runMutation(component.public.mark, {
216
+ collection,
217
+ peerId: args.peerId,
218
+ syncedSeq: args.syncedSeq
219
+ });
220
+ return null;
221
+ }
222
+ });
223
+ }
224
+ createCompactMutation(opts) {
225
+ const component = this.component;
226
+ const collection = this.collectionName;
227
+ return mutationGeneric({
228
+ args: {
229
+ documentId: v.string(),
230
+ snapshotBytes: v.bytes(),
231
+ stateVector: v.bytes(),
232
+ peerTimeout: v.optional(v.number())
233
+ },
234
+ returns: v.object({
235
+ success: v.boolean(),
236
+ removed: v.number(),
237
+ retained: v.number()
238
+ }),
239
+ handler: async (ctx, args) => {
240
+ if (opts?.evalWrite) await opts.evalWrite(ctx, args.documentId);
241
+ return await ctx.runMutation(component.public.compact, {
242
+ collection,
243
+ documentId: args.documentId,
244
+ snapshotBytes: args.snapshotBytes,
245
+ stateVector: args.stateVector,
246
+ peerTimeout: args.peerTimeout
247
+ });
248
+ }
249
+ });
250
+ }
251
+ createRecoveryQuery(opts) {
252
+ const component = this.component;
253
+ const collection = this.collectionName;
254
+ return queryGeneric({
255
+ args: { clientStateVector: v.bytes() },
256
+ returns: v.object({
257
+ diff: v.optional(v.bytes()),
258
+ serverStateVector: v.bytes(),
259
+ cursor: v.number()
260
+ }),
261
+ handler: async (ctx, args) => {
262
+ if (opts?.evalRead) await opts.evalRead(ctx, collection);
263
+ return await ctx.runQuery(component.public.recovery, {
264
+ collection,
265
+ clientStateVector: args.clientStateVector
266
+ });
267
+ }
268
+ });
269
+ }
270
+ };
271
+
272
+ //#endregion
273
+ //#region src/server/builder.ts
274
+ /**
275
+ * Create a replicate function bound to your component. Call this once in your
276
+ * convex/replicate.ts file, then use the returned function for all collections.
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * // convex/replicate.ts (create once)
281
+ * import { replicate } from '@trestleinc/replicate/server';
282
+ * import { components } from './_generated/api';
283
+ *
284
+ * export const tasks = replicate(components.replicate)<Task>({ collection: 'tasks' });
285
+ *
286
+ * // Or bind once and reuse:
287
+ * const r = replicate(components.replicate);
288
+ * export const tasks = r<Task>({ collection: 'tasks' });
289
+ * export const notebooks = r<Notebook>({ collection: 'notebooks' });
290
+ * ```
291
+ */
292
+ function replicate(component) {
293
+ return function boundReplicate(config) {
294
+ return replicateInternal(component, config);
295
+ };
296
+ }
297
+ /**
298
+ * Internal implementation for replicate.
299
+ */
300
+ function replicateInternal(component, config) {
301
+ const storage = new Replicate(component, config.collection, config.compaction);
302
+ return {
303
+ __collection: config.collection,
304
+ stream: storage.createStreamQuery({
305
+ evalRead: config.hooks?.evalRead,
306
+ onStream: config.hooks?.onStream
307
+ }),
308
+ material: storage.createSSRQuery({
309
+ evalRead: config.hooks?.evalRead,
310
+ transform: config.hooks?.transform
311
+ }),
312
+ recovery: storage.createRecoveryQuery({ evalRead: config.hooks?.evalRead }),
313
+ insert: storage.createInsertMutation({
314
+ evalWrite: config.hooks?.evalWrite,
315
+ onInsert: config.hooks?.onInsert
316
+ }),
317
+ update: storage.createUpdateMutation({
318
+ evalWrite: config.hooks?.evalWrite,
319
+ onUpdate: config.hooks?.onUpdate
320
+ }),
321
+ remove: storage.createRemoveMutation({
322
+ evalRemove: config.hooks?.evalRemove,
323
+ onRemove: config.hooks?.onRemove
324
+ }),
325
+ mark: storage.createMarkMutation({ evalWrite: config.hooks?.evalMark }),
326
+ compact: storage.createCompactMutation({ evalWrite: config.hooks?.evalCompact })
327
+ };
328
+ }
329
+
330
+ //#endregion
331
+ //#region src/server/schema.ts
332
+ const prose = () => v.object({
333
+ type: v.literal("doc"),
334
+ content: v.optional(v.array(v.any()))
335
+ });
336
+ /**
337
+ * Define a table with automatic timestamp field for replication.
338
+ * All replicated tables must have an `id` field and define a `by_doc_id` index.
339
+ *
340
+ * @example
341
+ * ```typescript
342
+ * // convex/schema.ts
343
+ * export default defineSchema({
344
+ * tasks: table(
345
+ * { id: v.string(), text: v.string(), isCompleted: v.boolean() },
346
+ * (t) => t.index('by_doc_id', ['id']).index('by_completed', ['isCompleted'])
347
+ * ),
348
+ * });
349
+ * ```
350
+ */
351
+ function table(userFields, applyIndexes) {
352
+ const tbl = defineTable({
353
+ ...userFields,
354
+ timestamp: v.number()
355
+ });
356
+ if (applyIndexes) return applyIndexes(tbl);
357
+ return tbl;
358
+ }
359
+
360
+ //#endregion
361
+ //#region src/server/index.ts
362
+ const schema = {
363
+ table,
364
+ prose
365
+ };
366
+
367
+ //#endregion
368
+ export { replicate, schema };
@@ -1,5 +1,29 @@
1
+ //#region src/shared/types.d.ts
2
+
3
+ /** ProseMirror-compatible JSON for XmlFragment serialization */
4
+ interface XmlFragmentJSON {
5
+ type: "doc";
6
+ content?: XmlNodeJSON[];
7
+ }
8
+ declare const PROSE_BRAND: unique symbol;
1
9
  /**
2
- * Shared types re-exported for top-level access
10
+ * Branded prose type for Zod schemas.
11
+ * Extends XmlFragmentJSON with a unique brand for type-level detection.
12
+ * Use the `prose()` helper from `@trestleinc/replicate/client` to create this type.
3
13
  */
4
- export type { FragmentValue, XmlFragmentJSON, XmlNodeJSON } from "./types.js";
5
- export { OperationType } from "./types.js";
14
+ interface ProseValue extends XmlFragmentJSON {
15
+ readonly [PROSE_BRAND]: typeof PROSE_BRAND;
16
+ }
17
+ /** ProseMirror node structure */
18
+ interface XmlNodeJSON {
19
+ type: string;
20
+ attrs?: Record<string, unknown>;
21
+ content?: XmlNodeJSON[];
22
+ text?: string;
23
+ marks?: {
24
+ type: string;
25
+ attrs?: Record<string, unknown>;
26
+ }[];
27
+ }
28
+ //#endregion
29
+ export { type ProseValue, type XmlFragmentJSON, type XmlNodeJSON };
@@ -1,2 +1 @@
1
- import { OperationType } from "./types.js";
2
- export { OperationType };
1
+ export { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trestleinc/replicate",
3
- "version": "1.1.1",
3
+ "version": "1.1.2-preview.0",
4
4
  "description": "Offline-first data replication with Yjs CRDTs and Convex",
5
5
  "repository": "github:trestleinc/replicate",
6
6
  "homepage": "https://github.com/trestleinc/replicate#readme",
@@ -19,21 +19,29 @@
19
19
  "type": "module",
20
20
  "private": false,
21
21
  "resolutions": {
22
- "convex": "^1.31.0"
22
+ "convex": "1.31.2",
23
+ "@standard-schema/spec": "1.1.0",
24
+ "zod": "4.2.1"
23
25
  },
24
26
  "overrides": {
25
- "convex": "^1.31.0"
27
+ "convex": "1.31.2",
28
+ "@standard-schema/spec": "1.1.0",
29
+ "zod": "4.2.1"
26
30
  },
27
31
  "scripts": {
28
- "build": "rslib build",
29
- "dev": "rslib build --watch",
30
- "clean": "rm -rf dist"
32
+ "build": "tsdown",
33
+ "dev": "tsdown --watch",
34
+ "clean": "rm -rf dist",
35
+ "lint": "eslint .",
36
+ "lint:fix": "eslint . --fix",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest"
31
39
  },
32
40
  "exports": {
33
41
  ".": {
34
42
  "import": {
35
43
  "types": "./dist/shared/index.d.ts",
36
- "default": "./dist/shared.js"
44
+ "default": "./dist/shared/index.js"
37
45
  }
38
46
  },
39
47
  "./package.json": "./package.json",
@@ -41,13 +49,13 @@
41
49
  "import": {
42
50
  "@convex-dev/component-source": "./src/client/index.ts",
43
51
  "types": "./dist/client/index.d.ts",
44
- "default": "./dist/index.js"
52
+ "default": "./dist/client/index.js"
45
53
  }
46
54
  },
47
55
  "./server": {
48
56
  "import": {
49
57
  "types": "./dist/server/index.d.ts",
50
- "default": "./dist/server.js"
58
+ "default": "./dist/server/index.js"
51
59
  }
52
60
  },
53
61
  "./convex.config": {
@@ -65,16 +73,13 @@
65
73
  "LICENSE"
66
74
  ],
67
75
  "dependencies": {
68
- "@effect/platform": "0.93.8",
69
- "@logtape/logtape": "1.2.2",
70
- "abstract-level": "3.1.1",
71
- "browser-level": "3.0.0",
72
- "effect": "3.19.12",
73
- "y-indexeddb": "9.0.12",
74
- "y-leveldb": "0.2.0"
76
+ "@effect/platform": "0.94.0",
77
+ "@logtape/logtape": "1.3.5",
78
+ "effect": "3.19.13"
75
79
  },
76
80
  "peerDependencies": {
77
- "@tanstack/db": "^0.5.0",
81
+ "@standard-schema/spec": "^1.1.0",
82
+ "@tanstack/db": "^0.5.15",
78
83
  "convex": "^1.31.0",
79
84
  "lib0": "^0.2.0",
80
85
  "yjs": "^13.6.0"
@@ -91,27 +96,27 @@
91
96
  "@convex-dev/eslint-plugin": "1.1.1",
92
97
  "@edge-runtime/vm": "5.0.0",
93
98
  "@microsoft/api-extractor": "7.55.2",
94
- "@rsbuild/plugin-eslint": "1.2.0",
95
- "@rsbuild/plugin-type-check": "1.3.2",
96
- "@rslib/core": "0.18.4",
99
+ "@standard-schema/spec": "1.1.0",
97
100
  "@stylistic/eslint-plugin": "5.6.1",
98
- "@tanstack/db": "0.5.12",
99
- "@types/node": "25.0.2",
101
+ "@tanstack/db": "0.5.15",
102
+ "@types/node": "25.0.3",
100
103
  "@types/sql.js": "1.4.9",
101
- "convex": "1.31.0",
104
+ "convex": "1.31.2",
102
105
  "dotenv": "17.2.3",
103
106
  "eslint": "9.39.2",
104
107
  "fake-indexeddb": "6.2.5",
105
108
  "globals": "16.5.0",
106
- "lib0": "0.2.114",
109
+ "lib0": "0.2.116",
110
+ "publint": "0.3.16",
111
+ "tsdown": "0.18.2",
107
112
  "typescript": "5.9.3",
108
- "typescript-eslint": "8.50.0",
109
- "yjs": "13.6.27",
110
- "zod": "4.1.13"
113
+ "typescript-eslint": "8.50.1",
114
+ "yjs": "13.6.28",
115
+ "zod": "4.2.1"
111
116
  },
112
- "main": "./dist/shared.js",
117
+ "main": "./dist/shared/index.js",
113
118
  "types": "./dist/shared/index.d.ts",
114
- "module": "./dist/shared.js",
119
+ "module": "./dist/shared/index.js",
115
120
  "publishConfig": {
116
121
  "access": "public"
117
122
  }