@trestleinc/replicate 0.1.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 (39) hide show
  1. package/LICENSE +201 -0
  2. package/LICENSE.package +201 -0
  3. package/README.md +871 -0
  4. package/dist/client/collection.d.ts +94 -0
  5. package/dist/client/index.d.ts +18 -0
  6. package/dist/client/logger.d.ts +3 -0
  7. package/dist/client/storage.d.ts +143 -0
  8. package/dist/component/_generated/api.js +5 -0
  9. package/dist/component/_generated/server.js +9 -0
  10. package/dist/component/convex.config.d.ts +2 -0
  11. package/dist/component/convex.config.js +3 -0
  12. package/dist/component/public.d.ts +99 -0
  13. package/dist/component/public.js +135 -0
  14. package/dist/component/schema.d.ts +22 -0
  15. package/dist/component/schema.js +22 -0
  16. package/dist/index.js +375 -0
  17. package/dist/server/index.d.ts +17 -0
  18. package/dist/server/replication.d.ts +122 -0
  19. package/dist/server/schema.d.ts +73 -0
  20. package/dist/server/ssr.d.ts +79 -0
  21. package/dist/server.js +96 -0
  22. package/dist/ssr.js +19 -0
  23. package/package.json +108 -0
  24. package/src/client/collection.ts +550 -0
  25. package/src/client/index.ts +31 -0
  26. package/src/client/logger.ts +31 -0
  27. package/src/client/storage.ts +206 -0
  28. package/src/component/_generated/api.d.ts +95 -0
  29. package/src/component/_generated/api.js +23 -0
  30. package/src/component/_generated/dataModel.d.ts +60 -0
  31. package/src/component/_generated/server.d.ts +149 -0
  32. package/src/component/_generated/server.js +90 -0
  33. package/src/component/convex.config.ts +3 -0
  34. package/src/component/public.ts +212 -0
  35. package/src/component/schema.ts +16 -0
  36. package/src/server/index.ts +26 -0
  37. package/src/server/replication.ts +244 -0
  38. package/src/server/schema.ts +97 -0
  39. package/src/server/ssr.ts +106 -0
package/dist/server.js ADDED
@@ -0,0 +1,96 @@
1
+ import { defineTable } from "convex/server";
2
+ import { v } from "convex/values";
3
+ function cleanDocument(doc) {
4
+ return Object.fromEntries(Object.entries(doc).filter(([_, value])=>null != value));
5
+ }
6
+ async function insertDocumentHelper(ctx, components, tableName, args) {
7
+ const timestamp = Date.now();
8
+ await ctx.runMutation(components.replicate.public.insertDocument, {
9
+ collectionName: tableName,
10
+ documentId: args.id,
11
+ crdtBytes: args.crdtBytes,
12
+ version: args.version
13
+ });
14
+ const db = ctx.db;
15
+ const cleanDoc = cleanDocument(args.materializedDoc);
16
+ await db.insert(tableName, {
17
+ id: args.id,
18
+ ...cleanDoc,
19
+ version: args.version,
20
+ timestamp
21
+ });
22
+ return {
23
+ success: true,
24
+ metadata: {
25
+ documentId: args.id,
26
+ timestamp,
27
+ version: args.version,
28
+ collectionName: tableName
29
+ }
30
+ };
31
+ }
32
+ async function updateDocumentHelper(ctx, components, tableName, args) {
33
+ const timestamp = Date.now();
34
+ await ctx.runMutation(components.replicate.public.updateDocument, {
35
+ collectionName: tableName,
36
+ documentId: args.id,
37
+ crdtBytes: args.crdtBytes,
38
+ version: args.version
39
+ });
40
+ const db = ctx.db;
41
+ const existing = await db.query(tableName).withIndex('by_user_id', (q)=>q.eq('id', args.id)).first();
42
+ if (!existing) throw new Error(`Document ${args.id} not found in table ${tableName}`);
43
+ const cleanDoc = cleanDocument(args.materializedDoc);
44
+ await db.patch(existing._id, {
45
+ ...cleanDoc,
46
+ version: args.version,
47
+ timestamp
48
+ });
49
+ return {
50
+ success: true,
51
+ metadata: {
52
+ documentId: args.id,
53
+ timestamp,
54
+ version: args.version,
55
+ collectionName: tableName
56
+ }
57
+ };
58
+ }
59
+ async function deleteDocumentHelper(ctx, components, tableName, args) {
60
+ const timestamp = Date.now();
61
+ await ctx.runMutation(components.replicate.public.deleteDocument, {
62
+ collectionName: tableName,
63
+ documentId: args.id,
64
+ crdtBytes: args.crdtBytes,
65
+ version: args.version
66
+ });
67
+ const db = ctx.db;
68
+ const existing = await db.query(tableName).withIndex('by_user_id', (q)=>q.eq('id', args.id)).first();
69
+ if (existing) await db.delete(existing._id);
70
+ return {
71
+ success: true,
72
+ metadata: {
73
+ documentId: args.id,
74
+ timestamp,
75
+ version: args.version,
76
+ collectionName: tableName
77
+ }
78
+ };
79
+ }
80
+ async function streamHelper(ctx, components, tableName, args) {
81
+ return ctx.runQuery(components.replicate.public.stream, {
82
+ collectionName: tableName,
83
+ checkpoint: args.checkpoint,
84
+ limit: args.limit
85
+ });
86
+ }
87
+ function replicatedTable(userFields, applyIndexes) {
88
+ const tableWithMetadata = defineTable({
89
+ ...userFields,
90
+ version: v.number(),
91
+ timestamp: v.number()
92
+ });
93
+ if (applyIndexes) return applyIndexes(tableWithMetadata);
94
+ return tableWithMetadata;
95
+ }
96
+ export { deleteDocumentHelper, insertDocumentHelper, replicatedTable, streamHelper, updateDocumentHelper };
package/dist/ssr.js ADDED
@@ -0,0 +1,19 @@
1
+ async function loadCollection(httpClient, config) {
2
+ const result = await httpClient.query(config.api.stream, {
3
+ collectionName: config.collection,
4
+ checkpoint: {
5
+ lastModified: 0
6
+ },
7
+ limit: config.limit ?? 100
8
+ });
9
+ const items = [];
10
+ for (const change of result.changes){
11
+ const item = {
12
+ id: change.documentId,
13
+ ...change.document
14
+ };
15
+ items.push(item);
16
+ }
17
+ return items;
18
+ }
19
+ export { loadCollection };
package/package.json ADDED
@@ -0,0 +1,108 @@
1
+ {
2
+ "name": "@trestleinc/replicate",
3
+ "version": "0.1.0",
4
+ "description": "Offline-first data replication with Yjs CRDTs and Convex",
5
+ "repository": "github:trestleinc/convex-replicate",
6
+ "homepage": "https://github.com/trestleinc/convex-replicate#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/trestleinc/convex-replicate/issues"
9
+ },
10
+ "license": "Apache-2.0",
11
+ "keywords": [
12
+ "convex",
13
+ "replicate",
14
+ "crdt",
15
+ "yjs",
16
+ "offline-first",
17
+ "tanstack"
18
+ ],
19
+ "type": "module",
20
+ "private": false,
21
+ "resolutions": {
22
+ "convex": "1.28.2"
23
+ },
24
+ "overrides": {
25
+ "convex": "1.28.2"
26
+ },
27
+ "exports": {
28
+ "./package.json": "./package.json",
29
+ "./client": {
30
+ "import": {
31
+ "@convex-dev/component-source": "./src/client/index.ts",
32
+ "types": "./dist/client/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "./server": {
37
+ "import": {
38
+ "types": "./dist/server/index.d.ts",
39
+ "default": "./dist/server.js"
40
+ }
41
+ },
42
+ "./ssr": {
43
+ "import": {
44
+ "types": "./dist/server/ssr.d.ts",
45
+ "default": "./dist/ssr.js"
46
+ }
47
+ },
48
+ "./convex.config": {
49
+ "import": {
50
+ "@convex-dev/component-source": "./src/component/convex.config.ts",
51
+ "types": "./dist/component/convex.config.d.ts",
52
+ "default": "./dist/component/convex.config.js"
53
+ }
54
+ }
55
+ },
56
+ "files": [
57
+ "dist",
58
+ "src",
59
+ "README.md",
60
+ "LICENSE"
61
+ ],
62
+ "dependencies": {
63
+ "yjs": "13.6.27",
64
+ "@tanstack/offline-transactions": "0.1.3",
65
+ "@logtape/logtape": "1.1.2"
66
+ },
67
+ "peerDependencies": {
68
+ "convex": "1.28.2",
69
+ "@tanstack/db": "0.4.20"
70
+ },
71
+ "devDependencies": {
72
+ "@biomejs/biome": "2.3.4",
73
+ "@rslib/core": "0.17.1",
74
+ "@semantic-release/changelog": "6.0.3",
75
+ "@semantic-release/exec": "7.1.0",
76
+ "@semantic-release/git": "10.0.1",
77
+ "@semantic-release/github": "12.0.1",
78
+ "@tanstack/db": "0.4.20",
79
+ "@types/node": "24.10.0",
80
+ "convex": "1.28.2",
81
+ "semantic-release": "25.0.1",
82
+ "typescript": "5.9.3",
83
+ "zod": "4.1.12"
84
+ },
85
+ "main": "./dist/index.js",
86
+ "types": "./dist/client/index.d.ts",
87
+ "module": "./dist/index.js",
88
+ "publishConfig": {
89
+ "access": "public"
90
+ },
91
+ "scripts": {
92
+ "build": "rslib build",
93
+ "dev": "rslib build --watch",
94
+ "clean": "rm -rf dist",
95
+ "typecheck": "tsc --noEmit",
96
+ "dev:example": "cd examples/tanstack-start && pnpm run dev",
97
+ "build:example": "cd examples/tanstack-start && pnpm run build",
98
+ "lint": "biome lint .",
99
+ "lint:fix": "biome lint --write .",
100
+ "format": "biome format --write .",
101
+ "format:check": "biome format .",
102
+ "check": "biome check .",
103
+ "check:fix": "biome check --write .",
104
+ "version-packages": "node scripts/version-packages.js",
105
+ "publish:npm": "pnpm run build && pnpm run check:fix && pnpm publish --access public",
106
+ "prepublish": "pnpm run build && pnpm run check:fix"
107
+ }
108
+ }