@n8n/crdt 0.2.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 (59) hide show
  1. package/LICENSE.md +88 -0
  2. package/LICENSE_EE.md +27 -0
  3. package/README.md +155 -0
  4. package/dist/awareness/index.d.ts +1 -0
  5. package/dist/awareness/index.js +6 -0
  6. package/dist/awareness/index.js.map +1 -0
  7. package/dist/awareness/yjs-awareness.d.ts +17 -0
  8. package/dist/awareness/yjs-awareness.js +66 -0
  9. package/dist/awareness/yjs-awareness.js.map +1 -0
  10. package/dist/build.tsbuildinfo +1 -0
  11. package/dist/index.d.ts +15 -0
  12. package/dist/index.js +59 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/protocol.d.ts +22 -0
  15. package/dist/protocol.js +74 -0
  16. package/dist/protocol.js.map +1 -0
  17. package/dist/providers/yjs.d.ts +5 -0
  18. package/dist/providers/yjs.js +307 -0
  19. package/dist/providers/yjs.js.map +1 -0
  20. package/dist/sync/base-sync-provider.d.ts +24 -0
  21. package/dist/sync/base-sync-provider.js +82 -0
  22. package/dist/sync/base-sync-provider.js.map +1 -0
  23. package/dist/sync/index.d.ts +2 -0
  24. package/dist/sync/index.js +7 -0
  25. package/dist/sync/index.js.map +1 -0
  26. package/dist/sync/types.d.ts +12 -0
  27. package/dist/sync/types.js +3 -0
  28. package/dist/sync/types.js.map +1 -0
  29. package/dist/transports/index.d.ts +5 -0
  30. package/dist/transports/index.js +12 -0
  31. package/dist/transports/index.js.map +1 -0
  32. package/dist/transports/message-port.d.ts +18 -0
  33. package/dist/transports/message-port.js +72 -0
  34. package/dist/transports/message-port.js.map +1 -0
  35. package/dist/transports/mock.d.ts +18 -0
  36. package/dist/transports/mock.js +52 -0
  37. package/dist/transports/mock.js.map +1 -0
  38. package/dist/transports/types.d.ts +10 -0
  39. package/dist/transports/types.js +3 -0
  40. package/dist/transports/types.js.map +1 -0
  41. package/dist/transports/websocket.d.ts +41 -0
  42. package/dist/transports/websocket.js +175 -0
  43. package/dist/transports/websocket.js.map +1 -0
  44. package/dist/transports/worker.d.ts +28 -0
  45. package/dist/transports/worker.js +108 -0
  46. package/dist/transports/worker.js.map +1 -0
  47. package/dist/types.d.ts +120 -0
  48. package/dist/types.js +25 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/undo/index.d.ts +1 -0
  51. package/dist/undo/index.js +7 -0
  52. package/dist/undo/index.js.map +1 -0
  53. package/dist/undo/yjs-undo-manager.d.ts +26 -0
  54. package/dist/undo/yjs-undo-manager.js +145 -0
  55. package/dist/undo/yjs-undo-manager.js.map +1 -0
  56. package/dist/utils.d.ts +3 -0
  57. package/dist/utils.js +31 -0
  58. package/dist/utils.js.map +1 -0
  59. package/package.json +54 -0
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.YjsUndoManager = exports.YjsRemoteOrigin = exports.YjsUndoManagerOrigin = void 0;
37
+ const Y = __importStar(require("yjs"));
38
+ exports.YjsUndoManagerOrigin = Symbol('local-undo-tracked');
39
+ exports.YjsRemoteOrigin = Symbol('remote-no-track');
40
+ class YjsUndoManager {
41
+ constructor(yDoc, options = {}) {
42
+ this.stackChangeHandlers = new Set();
43
+ this.destroyed = false;
44
+ this.lastMeta = null;
45
+ this.prevCanUndo = false;
46
+ this.prevCanRedo = false;
47
+ this.handleStackChange = () => {
48
+ if (this.destroyed)
49
+ return;
50
+ this.notifyIfChanged();
51
+ };
52
+ this.handleStackItemPopped = (event) => {
53
+ if (this.destroyed)
54
+ return;
55
+ this.lastMeta = event.stackItem.meta;
56
+ this.notifyIfChanged();
57
+ };
58
+ const { captureTimeout = 500 } = options;
59
+ const scope = [];
60
+ const typeNames = [];
61
+ yDoc.share.forEach((type, name) => {
62
+ scope.push(type);
63
+ typeNames.push(name);
64
+ });
65
+ if (scope.length === 0) {
66
+ const dummyScope = yDoc.getMap('__undo_scope__');
67
+ scope.push(dummyScope);
68
+ }
69
+ this.undoManager = new Y.UndoManager(scope, {
70
+ captureTimeout,
71
+ trackedOrigins: new Set([exports.YjsUndoManagerOrigin, null]),
72
+ });
73
+ this.undoManager.on('stack-item-added', this.handleStackChange);
74
+ this.undoManager.on('stack-item-popped', this.handleStackItemPopped);
75
+ }
76
+ notifyIfChanged() {
77
+ const canUndo = this.canUndo();
78
+ const canRedo = this.canRedo();
79
+ if (canUndo !== this.prevCanUndo || canRedo !== this.prevCanRedo) {
80
+ this.prevCanUndo = canUndo;
81
+ this.prevCanRedo = canRedo;
82
+ const event = { canUndo, canRedo };
83
+ for (const handler of this.stackChangeHandlers) {
84
+ handler(event);
85
+ }
86
+ }
87
+ }
88
+ undo() {
89
+ if (this.destroyed || !this.canUndo())
90
+ return false;
91
+ this.undoManager.undo();
92
+ return true;
93
+ }
94
+ redo() {
95
+ if (this.destroyed || !this.canRedo())
96
+ return false;
97
+ this.undoManager.redo();
98
+ return true;
99
+ }
100
+ canUndo() {
101
+ if (this.destroyed)
102
+ return false;
103
+ return this.undoManager.undoStack.length > 0;
104
+ }
105
+ canRedo() {
106
+ if (this.destroyed)
107
+ return false;
108
+ return this.undoManager.redoStack.length > 0;
109
+ }
110
+ stopCapturing() {
111
+ this.undoManager.stopCapturing();
112
+ }
113
+ clear() {
114
+ this.undoManager.clear();
115
+ this.lastMeta = null;
116
+ this.notifyIfChanged();
117
+ }
118
+ onStackChange(handler) {
119
+ this.stackChangeHandlers.add(handler);
120
+ return () => {
121
+ this.stackChangeHandlers.delete(handler);
122
+ };
123
+ }
124
+ setMeta(key, value) {
125
+ const currentItem = this.undoManager.undoStack[this.undoManager.undoStack.length - 1];
126
+ if (currentItem) {
127
+ currentItem.meta.set(key, value);
128
+ }
129
+ }
130
+ getMeta(key) {
131
+ return this.lastMeta?.get(key);
132
+ }
133
+ destroy() {
134
+ if (this.destroyed)
135
+ return;
136
+ this.destroyed = true;
137
+ this.undoManager.off('stack-item-added', this.handleStackChange);
138
+ this.undoManager.off('stack-item-popped', this.handleStackItemPopped);
139
+ this.undoManager.destroy();
140
+ this.stackChangeHandlers.clear();
141
+ this.lastMeta = null;
142
+ }
143
+ }
144
+ exports.YjsUndoManager = YjsUndoManager;
145
+ //# sourceMappingURL=yjs-undo-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yjs-undo-manager.js","sourceRoot":"","sources":["../../src/undo/yjs-undo-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CRDTDoc } from './types';
2
+ export declare function seedValueDeep(doc: CRDTDoc, value: unknown): unknown;
3
+ export declare function toJSON(value: unknown): unknown;
package/dist/utils.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.seedValueDeep = seedValueDeep;
4
+ exports.toJSON = toJSON;
5
+ function seedValueDeep(doc, value) {
6
+ if (Array.isArray(value)) {
7
+ const arr = doc.createArray();
8
+ for (const item of value) {
9
+ arr.push(seedValueDeep(doc, item));
10
+ }
11
+ return arr;
12
+ }
13
+ if (value !== null && typeof value === 'object') {
14
+ const map = doc.createMap();
15
+ for (const [k, v] of Object.entries(value)) {
16
+ map.set(k, seedValueDeep(doc, v));
17
+ }
18
+ return map;
19
+ }
20
+ return value;
21
+ }
22
+ function toJSON(value) {
23
+ if (value === null || value === undefined) {
24
+ return value;
25
+ }
26
+ if (typeof value === 'object' && 'toJSON' in value && typeof value.toJSON === 'function') {
27
+ return value.toJSON();
28
+ }
29
+ return value;
30
+ }
31
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;AAsBA,sCAmBC;AASD,wBAWC;AAvCD,SAAgB,aAAa,CAAC,GAAY,EAAE,KAAc;IACzD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAuB,GAAG,CAAC,WAAW,EAAE,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACjD,MAAM,GAAG,GAAqB,GAAG,CAAC,SAAS,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAGD,OAAO,KAAK,CAAC;AACd,CAAC;AASD,SAAgB,MAAM,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACd,CAAC;IAGD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1F,OAAQ,KAAmC,CAAC,MAAM,EAAE,CAAC;IACtD,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@n8n/crdt",
3
+ "version": "0.2.0",
4
+ "description": "CRDT abstraction layer for n8n collaborative editing",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/**/*",
17
+ "LICENSE.md",
18
+ "LICENSE_EE.md"
19
+ ],
20
+ "dependencies": {
21
+ "y-protocols": "^1.0.7",
22
+ "yjs": "^13.6.20"
23
+ },
24
+ "devDependencies": {
25
+ "vitest": "^3.1.3",
26
+ "vitest-websocket-mock": "^0.5.0",
27
+ "@n8n/vitest-config": "1.6.0",
28
+ "@n8n/typescript-config": "1.3.0"
29
+ },
30
+ "license": "SEE LICENSE IN LICENSE.md",
31
+ "homepage": "https://n8n.io",
32
+ "author": {
33
+ "name": "Jan Oberhauser",
34
+ "email": "jan@n8n.io"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/n8n-io/n8n.git"
39
+ },
40
+ "scripts": {
41
+ "clean": "rimraf dist .turbo",
42
+ "dev": "pnpm watch",
43
+ "typecheck": "tsc --noEmit",
44
+ "build": "tsc -p tsconfig.build.json",
45
+ "format": "biome format --write .",
46
+ "format:check": "biome ci .",
47
+ "lint": "eslint . --quiet",
48
+ "lint:fix": "eslint . --fix",
49
+ "watch": "tsc -p tsconfig.build.json --watch",
50
+ "test": "vitest run",
51
+ "test:unit": "vitest run",
52
+ "test:dev": "vitest --silent=false"
53
+ }
54
+ }