@meshagent/meshagent 0.0.11 → 0.0.12

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 (127) hide show
  1. package/dist/browser/agent-client.d.ts +88 -0
  2. package/dist/browser/agent-client.js +174 -0
  3. package/dist/browser/agent.d.ts +103 -0
  4. package/dist/browser/agent.js +229 -0
  5. package/dist/browser/client.d.ts +90 -0
  6. package/dist/browser/client.js +449 -0
  7. package/dist/browser/completer.d.ts +9 -0
  8. package/dist/browser/completer.js +25 -0
  9. package/dist/browser/data-types.d.ts +44 -0
  10. package/dist/browser/data-types.js +119 -0
  11. package/dist/browser/database-client.d.ts +77 -0
  12. package/dist/browser/database-client.js +113 -0
  13. package/dist/browser/developer-client.d.ts +13 -0
  14. package/dist/browser/developer-client.js +35 -0
  15. package/dist/browser/document.d.ts +84 -0
  16. package/dist/browser/document.js +531 -0
  17. package/dist/browser/entrypoint.d.ts +49722 -0
  18. package/dist/browser/entrypoint.js +8659 -0
  19. package/dist/browser/event-emitter.d.ts +13 -0
  20. package/dist/browser/event-emitter.js +38 -0
  21. package/dist/browser/helpers.d.ts +26 -0
  22. package/dist/browser/helpers.js +79 -0
  23. package/dist/browser/index.d.ts +24 -0
  24. package/dist/browser/index.js +40 -0
  25. package/dist/browser/messaging-client.d.ts +76 -0
  26. package/dist/browser/messaging-client.js +248 -0
  27. package/dist/browser/participant-token.d.ts +36 -0
  28. package/dist/browser/participant-token.js +104 -0
  29. package/dist/browser/participant.d.ts +18 -0
  30. package/dist/browser/participant.js +42 -0
  31. package/dist/browser/protocol.d.ts +87 -0
  32. package/dist/browser/protocol.js +305 -0
  33. package/dist/browser/queues-client.d.ts +26 -0
  34. package/dist/browser/queues-client.js +47 -0
  35. package/dist/browser/requirement.d.ts +25 -0
  36. package/dist/browser/requirement.js +49 -0
  37. package/dist/browser/response.d.ts +60 -0
  38. package/dist/browser/response.js +138 -0
  39. package/dist/browser/room-client.d.ts +43 -0
  40. package/dist/browser/room-client.js +109 -0
  41. package/dist/browser/room-event.d.ts +60 -0
  42. package/dist/browser/room-event.js +82 -0
  43. package/dist/browser/room-server-client.d.ts +19 -0
  44. package/dist/browser/room-server-client.js +50 -0
  45. package/dist/browser/runtime.d.ts +6 -0
  46. package/dist/browser/runtime.js +8 -0
  47. package/dist/browser/schema.d.ts +83 -0
  48. package/dist/browser/schema.js +321 -0
  49. package/dist/browser/storage-client.d.ts +38 -0
  50. package/dist/browser/storage-client.js +86 -0
  51. package/dist/browser/stream-controller.d.ts +8 -0
  52. package/dist/browser/stream-controller.js +55 -0
  53. package/dist/browser/sync-client.d.ts +33 -0
  54. package/dist/browser/sync-client.js +123 -0
  55. package/dist/browser/utils.d.ts +14 -0
  56. package/dist/browser/utils.js +59 -0
  57. package/dist/node/agent-client.d.ts +88 -0
  58. package/dist/node/agent-client.js +174 -0
  59. package/dist/node/agent.d.ts +103 -0
  60. package/dist/node/agent.js +229 -0
  61. package/dist/node/client.d.ts +90 -0
  62. package/dist/node/client.js +449 -0
  63. package/dist/node/completer.d.ts +9 -0
  64. package/dist/node/completer.js +25 -0
  65. package/dist/node/data-types.d.ts +44 -0
  66. package/dist/node/data-types.js +119 -0
  67. package/dist/node/database-client.d.ts +77 -0
  68. package/dist/node/database-client.js +113 -0
  69. package/dist/node/developer-client.d.ts +13 -0
  70. package/dist/node/developer-client.js +35 -0
  71. package/dist/node/document.d.ts +84 -0
  72. package/dist/node/document.js +531 -0
  73. package/dist/node/entrypoint.d.ts +49722 -0
  74. package/dist/node/entrypoint.js +6321 -0
  75. package/dist/node/event-emitter.d.ts +13 -0
  76. package/dist/node/event-emitter.js +38 -0
  77. package/dist/node/helpers.d.ts +26 -0
  78. package/dist/node/helpers.js +79 -0
  79. package/dist/node/index.d.ts +24 -0
  80. package/dist/node/index.js +40 -0
  81. package/dist/node/messaging-client.d.ts +76 -0
  82. package/dist/node/messaging-client.js +248 -0
  83. package/dist/node/participant-token.d.ts +36 -0
  84. package/dist/node/participant-token.js +104 -0
  85. package/dist/node/participant.d.ts +18 -0
  86. package/dist/node/participant.js +42 -0
  87. package/dist/node/protocol.d.ts +87 -0
  88. package/dist/node/protocol.js +305 -0
  89. package/dist/node/queues-client.d.ts +26 -0
  90. package/dist/node/queues-client.js +47 -0
  91. package/dist/node/requirement.d.ts +25 -0
  92. package/dist/node/requirement.js +49 -0
  93. package/dist/node/response.d.ts +60 -0
  94. package/dist/node/response.js +138 -0
  95. package/dist/node/room-client.d.ts +43 -0
  96. package/dist/node/room-client.js +109 -0
  97. package/dist/node/room-event.d.ts +60 -0
  98. package/dist/node/room-event.js +82 -0
  99. package/dist/node/room-server-client.d.ts +19 -0
  100. package/dist/node/room-server-client.js +50 -0
  101. package/dist/node/runtime.d.ts +6 -0
  102. package/dist/node/runtime.js +8 -0
  103. package/dist/node/schema.d.ts +83 -0
  104. package/dist/node/schema.js +321 -0
  105. package/dist/node/storage-client.d.ts +38 -0
  106. package/dist/node/storage-client.js +86 -0
  107. package/dist/node/stream-controller.d.ts +8 -0
  108. package/dist/node/stream-controller.js +55 -0
  109. package/dist/node/sync-client.d.ts +33 -0
  110. package/dist/node/sync-client.js +123 -0
  111. package/dist/node/utils.d.ts +14 -0
  112. package/dist/node/utils.js +59 -0
  113. package/package.json +36 -22
  114. package/README.md +0 -0
  115. package/babel.config.cjs +0 -3
  116. package/client.js +0 -422
  117. package/dist/entrypoint.js +0 -11262
  118. package/dist/entrypoint.js.map +0 -7
  119. package/document-server-client.js +0 -246
  120. package/entrypoint.js +0 -11568
  121. package/index.js +0 -2
  122. package/protocol.js +0 -459
  123. package/server.js +0 -310
  124. package/test/assert.js +0 -19
  125. package/test/document-server-client.test.js +0 -33
  126. package/test/document.test.js +0 -313
  127. package/test/protocol.test.js +0 -64
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MeshSchema = exports.ElementType = exports.ChildProperty = exports.ValueProperty = exports.ElementProperty = exports.SimpleValue = exports.MeshSchemaValidationException = void 0;
4
+ class MeshSchemaValidationException extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "MeshSchemaValidationException";
8
+ }
9
+ }
10
+ exports.MeshSchemaValidationException = MeshSchemaValidationException;
11
+ var SimpleValue;
12
+ (function (SimpleValue) {
13
+ SimpleValue["number"] = "number";
14
+ SimpleValue["string"] = "string";
15
+ SimpleValue["nullValue"] = "null";
16
+ SimpleValue["boolean"] = "boolean";
17
+ })(SimpleValue || (exports.SimpleValue = SimpleValue = {}));
18
+ (function (SimpleValue) {
19
+ function fromString(val) {
20
+ switch (val) {
21
+ case "number":
22
+ return SimpleValue.number;
23
+ case "string":
24
+ return SimpleValue.string;
25
+ case "null":
26
+ return SimpleValue.nullValue;
27
+ case "boolean":
28
+ return SimpleValue.boolean;
29
+ default:
30
+ return null;
31
+ }
32
+ }
33
+ SimpleValue.fromString = fromString;
34
+ })(SimpleValue || (exports.SimpleValue = SimpleValue = {}));
35
+ class ElementProperty {
36
+ constructor({ name, description }) {
37
+ this.name = name;
38
+ this.description = description;
39
+ }
40
+ }
41
+ exports.ElementProperty = ElementProperty;
42
+ class ValueProperty extends ElementProperty {
43
+ constructor({ name, description, type, enumValues }) {
44
+ super({ name, description });
45
+ this.type = type;
46
+ this.enumValues = enumValues;
47
+ }
48
+ validate(_) {
49
+ }
50
+ toJson() {
51
+ const obj = {
52
+ [this.name]: {
53
+ type: this.type,
54
+ },
55
+ };
56
+ if (this.description) {
57
+ obj[this.name].description = this.description;
58
+ }
59
+ if (this.enumValues) {
60
+ obj[this.name].enum = this.enumValues;
61
+ }
62
+ return obj;
63
+ }
64
+ }
65
+ exports.ValueProperty = ValueProperty;
66
+ class ChildProperty extends ElementProperty {
67
+ constructor({ name, description, childTagNames, ordered = false }) {
68
+ super({ name, description });
69
+ this._childTagNames = childTagNames;
70
+ this.ordered = ordered;
71
+ }
72
+ validate(schema) {
73
+ for (const item of this._childTagNames) {
74
+ schema.element(item);
75
+ }
76
+ }
77
+ isTagAllowed(tagName) {
78
+ return this._childTagNames.includes(tagName);
79
+ }
80
+ get childTagNames() {
81
+ return this._childTagNames;
82
+ }
83
+ toJson() {
84
+ const base = {};
85
+ if (this.description) {
86
+ base["description"] = this.description;
87
+ }
88
+ if (this.ordered) {
89
+ return {
90
+ [this.name]: {
91
+ ...base,
92
+ type: "array",
93
+ prefixItems: this._childTagNames.map((p) => ({ $ref: `#/$defs/${p}` })),
94
+ items: false,
95
+ },
96
+ };
97
+ }
98
+ else {
99
+ return {
100
+ [this.name]: {
101
+ ...base,
102
+ type: "array",
103
+ items: {
104
+ anyOf: this._childTagNames.map((p) => ({ $ref: `#/$defs/${p}` })),
105
+ },
106
+ },
107
+ };
108
+ }
109
+ }
110
+ }
111
+ exports.ChildProperty = ChildProperty;
112
+ class ElementType {
113
+ constructor(params) {
114
+ this._propertyLookup = new Map();
115
+ this._tagName = params.tagName;
116
+ this._description = params.description;
117
+ this._properties = [...params.properties];
118
+ for (const p of this._properties) {
119
+ if (p instanceof ChildProperty) {
120
+ if (this._childPropertyName) {
121
+ throw new MeshSchemaValidationException("Only one child property is allowed");
122
+ }
123
+ this._childPropertyName = p.name;
124
+ }
125
+ if (this._propertyLookup.has(p.name)) {
126
+ throw new MeshSchemaValidationException(`Duplicate property ${p.name}`);
127
+ }
128
+ this._propertyLookup.set(p.name, p);
129
+ }
130
+ }
131
+ static fromJson(json) {
132
+ const description = json["description"];
133
+ const propertiesMap = json["properties"];
134
+ if (!propertiesMap || Object.keys(propertiesMap).length === 0) {
135
+ throw new MeshSchemaValidationException("Invalid schema json: no properties found");
136
+ }
137
+ const [tagName, typeJson] = Object.entries(propertiesMap)[0];
138
+ if (!typeJson || typeof typeJson !== "object") {
139
+ throw new MeshSchemaValidationException("typeJson must be an object");
140
+ }
141
+ const innerProps = typeJson["properties"];
142
+ const resultProps = [];
143
+ for (const [propName, pVal] of Object.entries(innerProps)) {
144
+ const pMap = pVal;
145
+ const propDescription = pMap["description"];
146
+ const pType = pMap["type"];
147
+ if (pType === "array") {
148
+ if (pMap["prefixItems"]) {
149
+ const prefixItems = pMap["prefixItems"];
150
+ const childTagNames = [];
151
+ for (const refObj of prefixItems) {
152
+ const refStr = refObj["$ref"];
153
+ const prefix = "#/$defs/";
154
+ const childTagName = refStr.startsWith(prefix)
155
+ ? refStr.substring(prefix.length)
156
+ : refStr;
157
+ childTagNames.push(childTagName);
158
+ }
159
+ resultProps.push(new ChildProperty({
160
+ name: propName,
161
+ description: propDescription,
162
+ childTagNames,
163
+ ordered: true,
164
+ }));
165
+ }
166
+ else if (pMap["items"] &&
167
+ typeof pMap["items"] === "object" &&
168
+ pMap["items"]["anyOf"]) {
169
+ const anyOf = pMap["items"]["anyOf"];
170
+ const childTagNames = [];
171
+ for (const refObj of anyOf) {
172
+ const refStr = refObj["$ref"];
173
+ const prefix = "#/$defs/";
174
+ const childTagName = refStr.startsWith(prefix)
175
+ ? refStr.substring(prefix.length)
176
+ : refStr;
177
+ childTagNames.push(childTagName);
178
+ }
179
+ resultProps.push(new ChildProperty({
180
+ name: propName,
181
+ description: propDescription,
182
+ childTagNames,
183
+ ordered: false,
184
+ }));
185
+ }
186
+ else {
187
+ throw new MeshSchemaValidationException("Invalid array type encountered");
188
+ }
189
+ }
190
+ else {
191
+ const valTypeStr = pType;
192
+ const valType = SimpleValue.fromString(valTypeStr);
193
+ if (!valType) {
194
+ throw new MeshSchemaValidationException(`Invalid value type: ${valTypeStr}`);
195
+ }
196
+ const enumVal = pMap["enum"];
197
+ resultProps.push(new ValueProperty({
198
+ name: propName,
199
+ description: propDescription,
200
+ type: valType,
201
+ enumValues: enumVal,
202
+ }));
203
+ }
204
+ }
205
+ return new ElementType({ tagName, description, properties: resultProps });
206
+ }
207
+ toJson() {
208
+ const props = {};
209
+ const required = [];
210
+ for (const p of this._properties) {
211
+ required.push(p.name);
212
+ const pJson = p.toJson();
213
+ const propValue = pJson[p.name];
214
+ props[p.name] = propValue;
215
+ }
216
+ return {
217
+ type: "object",
218
+ additionalProperties: false,
219
+ description: this._description,
220
+ required: [this._tagName],
221
+ properties: {
222
+ [this._tagName]: {
223
+ type: "object",
224
+ additionalProperties: false,
225
+ required,
226
+ properties: props,
227
+ },
228
+ },
229
+ };
230
+ }
231
+ validate(schema) {
232
+ for (const p of this._properties) {
233
+ p.validate(schema);
234
+ }
235
+ }
236
+ get childPropertyName() {
237
+ return this._childPropertyName;
238
+ }
239
+ get tagName() {
240
+ return this._tagName;
241
+ }
242
+ get description() {
243
+ return this._description;
244
+ }
245
+ get properties() {
246
+ return this._properties;
247
+ }
248
+ property(name) {
249
+ const found = this._propertyLookup.get(name);
250
+ if (!found) {
251
+ throw new Error(`Property is not in schema: ${name}`);
252
+ }
253
+ return found;
254
+ }
255
+ }
256
+ exports.ElementType = ElementType;
257
+ class MeshSchema {
258
+ constructor(params) {
259
+ this.elementsByTagName = {};
260
+ const { rootTagName, elements } = params;
261
+ this._rootTagName = rootTagName;
262
+ this._elements = elements;
263
+ for (const t of elements) {
264
+ if (this.elementsByTagName[t.tagName]) {
265
+ throw new MeshSchemaValidationException(`${t.tagName} was found more than once`);
266
+ }
267
+ this.elementsByTagName[t.tagName] = t;
268
+ }
269
+ if (!this.elementsByTagName[rootTagName]) {
270
+ throw new MeshSchemaValidationException(`${rootTagName} was not found in tags`);
271
+ }
272
+ this.validate();
273
+ }
274
+ static fromJson(json) {
275
+ const elements = [];
276
+ const rootTagRef = json["$root_tag_ref"];
277
+ const prefix = "#/$defs/";
278
+ const rootTagName = rootTagRef.startsWith(prefix)
279
+ ? rootTagRef.substring(prefix.length)
280
+ : rootTagRef;
281
+ const defs = json["$defs"];
282
+ for (const elementJson of Object.values(defs)) {
283
+ elements.push(ElementType.fromJson(elementJson));
284
+ }
285
+ return new MeshSchema({ rootTagName, elements });
286
+ }
287
+ toJson() {
288
+ const defs = {};
289
+ for (const t of this._elements) {
290
+ defs[t.tagName] = t.toJson();
291
+ }
292
+ const rootElementJson = this.root.toJson();
293
+ const result = {
294
+ "$root_tag_ref": `#/$defs/${this._rootTagName}`,
295
+ "$defs": defs,
296
+ };
297
+ for (const [k, v] of Object.entries(rootElementJson)) {
298
+ result[k] = v;
299
+ }
300
+ return result;
301
+ }
302
+ element(name) {
303
+ const el = this.elementsByTagName[name];
304
+ if (!el) {
305
+ throw new MeshSchemaValidationException(`Element not found: ${name}`);
306
+ }
307
+ return el;
308
+ }
309
+ validate() {
310
+ for (const e of this._elements) {
311
+ e.validate(this);
312
+ }
313
+ }
314
+ get root() {
315
+ return this.elementsByTagName[this._rootTagName];
316
+ }
317
+ get elements() {
318
+ return this._elements;
319
+ }
320
+ }
321
+ exports.MeshSchema = MeshSchema;
@@ -0,0 +1,38 @@
1
+ import { RoomClient } from "./room-client";
2
+ import { RoomEvent } from "./room-event";
3
+ import { FileResponse } from "./response";
4
+ import { EventEmitter } from "./event-emitter";
5
+ export declare class FileHandle {
6
+ id: number;
7
+ constructor({ id }: {
8
+ id: number;
9
+ });
10
+ }
11
+ declare class StorageEntry {
12
+ name: string;
13
+ isFolder: boolean;
14
+ constructor({ name, isFolder }: {
15
+ name: string;
16
+ isFolder: boolean;
17
+ });
18
+ nameWithoutExtension(): string;
19
+ }
20
+ export declare class StorageClient extends EventEmitter<RoomEvent> {
21
+ private client;
22
+ constructor({ room }: {
23
+ room: RoomClient;
24
+ });
25
+ private _handleFileUpdated;
26
+ private _handleFileDeleted;
27
+ list(path: string): Promise<StorageEntry[]>;
28
+ delete(path: string): Promise<void>;
29
+ open(path: string, { overwrite }: {
30
+ overwrite: boolean;
31
+ }): Promise<FileHandle>;
32
+ exists(path: string): Promise<boolean>;
33
+ write(handle: FileHandle, bytes: Uint8Array): Promise<void>;
34
+ close(handle: FileHandle): Promise<void>;
35
+ download(path: string): Promise<FileResponse>;
36
+ downloadUrl(path: string): Promise<string>;
37
+ }
38
+ export {};
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StorageClient = exports.FileHandle = void 0;
4
+ const room_event_1 = require("./room-event");
5
+ const utils_1 = require("./utils");
6
+ const event_emitter_1 = require("./event-emitter");
7
+ class FileHandle {
8
+ constructor({ id }) {
9
+ this.id = id;
10
+ }
11
+ }
12
+ exports.FileHandle = FileHandle;
13
+ class StorageEntry {
14
+ constructor({ name, isFolder }) {
15
+ this.name = name;
16
+ this.isFolder = isFolder;
17
+ }
18
+ nameWithoutExtension() {
19
+ const segments = this.name
20
+ .replace(/^\/+/, '')
21
+ .replace(/\/+$/, '')
22
+ .split(/\/+/);
23
+ return (segments[segments.length - 1] || "")
24
+ .replace(/\.[^/.]+$/, "");
25
+ }
26
+ }
27
+ class StorageClient extends event_emitter_1.EventEmitter {
28
+ constructor({ room }) {
29
+ super();
30
+ this.client = room;
31
+ this.client.protocol.addHandler("storage.file.deleted", this._handleFileDeleted.bind(this));
32
+ this.client.protocol.addHandler("storage.file.updated", this._handleFileUpdated.bind(this));
33
+ }
34
+ async _handleFileUpdated(protocol, messageId, type, bytes) {
35
+ const raw = utils_1.decoder.decode(bytes || new Uint8Array());
36
+ const data = JSON.parse(raw);
37
+ const event = new room_event_1.FileUpdatedEvent({ path: data["path"] });
38
+ this.client.emit(event);
39
+ this.emit('file.updated', event);
40
+ }
41
+ async _handleFileDeleted(protocol, messageId, type, bytes) {
42
+ const raw = utils_1.decoder.decode(bytes || new Uint8Array());
43
+ const data = JSON.parse(raw);
44
+ const event = new room_event_1.FileDeletedEvent({ path: data["path"] });
45
+ this.client.emit(event);
46
+ this.emit('file.deleted', event);
47
+ }
48
+ async list(path) {
49
+ const response = (await this.client.sendRequest("storage.list", { path }));
50
+ const files = response.json["files"];
51
+ const entries = files.map((f) => {
52
+ return new StorageEntry({
53
+ name: f["name"],
54
+ isFolder: f["is_folder"],
55
+ });
56
+ });
57
+ entries.sort((a, b) => a.name.localeCompare(b.name));
58
+ return entries;
59
+ }
60
+ async delete(path) {
61
+ await this.client.sendRequest("storage.delete", { path });
62
+ }
63
+ async open(path, { overwrite = false }) {
64
+ const response = (await this.client.sendRequest("storage.open", { path, overwrite }));
65
+ return new FileHandle({ id: response.json["handle"] });
66
+ }
67
+ async exists(path) {
68
+ const result = (await this.client.sendRequest("storage.exists", { path }));
69
+ return result.json["exists"];
70
+ }
71
+ async write(handle, bytes) {
72
+ await this.client.sendRequest("storage.write", { handle: handle.id }, bytes);
73
+ }
74
+ async close(handle) {
75
+ await this.client.sendRequest("storage.close", { handle: handle.id });
76
+ }
77
+ async download(path) {
78
+ const response = (await this.client.sendRequest("storage.download", { path }));
79
+ return response;
80
+ }
81
+ async downloadUrl(path) {
82
+ const response = (await this.client.sendRequest("storage.download_url", { path }));
83
+ return response.json["url"];
84
+ }
85
+ }
86
+ exports.StorageClient = StorageClient;
@@ -0,0 +1,8 @@
1
+ export declare class StreamController<T> {
2
+ private closed;
3
+ get stream(): AsyncIterable<T>;
4
+ private queue;
5
+ private waiters;
6
+ add(value: T): void;
7
+ close(): void;
8
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StreamController = void 0;
4
+ class StreamController {
5
+ constructor() {
6
+ this.closed = false;
7
+ this.queue = [];
8
+ this.waiters = [];
9
+ }
10
+ get stream() {
11
+ const self = this;
12
+ return {
13
+ [Symbol.asyncIterator]() {
14
+ return {
15
+ async next() {
16
+ if (self.queue.length > 0) {
17
+ return {
18
+ done: false,
19
+ value: self.queue.shift()
20
+ };
21
+ }
22
+ if (self.closed) {
23
+ return {
24
+ done: true,
25
+ value: undefined
26
+ };
27
+ }
28
+ return new Promise((resolve) => {
29
+ self.waiters.push(resolve);
30
+ });
31
+ },
32
+ };
33
+ },
34
+ };
35
+ }
36
+ add(value) {
37
+ if (this.closed)
38
+ return;
39
+ if (this.waiters.length > 0) {
40
+ const waiter = this.waiters.shift();
41
+ waiter({ done: false, value });
42
+ }
43
+ else {
44
+ this.queue.push(value);
45
+ }
46
+ }
47
+ close() {
48
+ this.closed = true;
49
+ while (this.waiters.length > 0) {
50
+ const waiter = this.waiters.shift();
51
+ waiter({ done: true, value: undefined });
52
+ }
53
+ }
54
+ }
55
+ exports.StreamController = StreamController;
@@ -0,0 +1,33 @@
1
+ import { EventEmitter } from "./event-emitter";
2
+ import { RoomClient } from "./room-client";
3
+ import { MeshDocument } from "./room-server-client";
4
+ export interface SyncClientEvent {
5
+ type: string;
6
+ doc: MeshDocument;
7
+ }
8
+ export declare class QueuedSync {
9
+ path: string;
10
+ base64: string;
11
+ constructor({ path, base64 }: {
12
+ path: string;
13
+ base64: string;
14
+ });
15
+ }
16
+ export declare class SyncClient extends EventEmitter<SyncClientEvent> {
17
+ private client;
18
+ private _connectingDocuments;
19
+ private _changesToSync;
20
+ private _connectedDocuments;
21
+ constructor({ room }: {
22
+ room: RoomClient;
23
+ });
24
+ start(): void;
25
+ dispose(): void;
26
+ private _handleSync;
27
+ create(path: string, json?: Record<string, any>): Promise<void>;
28
+ open(path: string, { create }?: {
29
+ create?: boolean;
30
+ }): Promise<MeshDocument>;
31
+ close(path: string): Promise<void>;
32
+ sync(path: string, data: Uint8Array): Promise<void>;
33
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SyncClient = exports.QueuedSync = void 0;
4
+ const event_emitter_1 = require("./event-emitter");
5
+ const schema_1 = require("./schema");
6
+ const stream_controller_1 = require("./stream-controller");
7
+ const room_server_client_1 = require("./room-server-client");
8
+ const utils_1 = require("./utils");
9
+ const runtime_1 = require("./runtime");
10
+ const completer_1 = require("./completer");
11
+ ;
12
+ class QueuedSync {
13
+ constructor({ path, base64 }) {
14
+ this.path = path;
15
+ this.base64 = base64;
16
+ }
17
+ }
18
+ exports.QueuedSync = QueuedSync;
19
+ class SyncClient extends event_emitter_1.EventEmitter {
20
+ constructor({ room }) {
21
+ super();
22
+ this._connectingDocuments = {};
23
+ this._changesToSync = new stream_controller_1.StreamController();
24
+ this._connectedDocuments = {};
25
+ this.client = room;
26
+ this.client.protocol.addHandler("room.sync", this._handleSync.bind(this));
27
+ }
28
+ start() {
29
+ this.client.protocol.start();
30
+ (async () => {
31
+ for await (const message of this._changesToSync.stream) {
32
+ console.log(`sending changes to backend ${message.base64}`);
33
+ await this.client.sendRequest("room.sync", { path: message.path }, utils_1.encoder.encode(message.base64));
34
+ }
35
+ })();
36
+ }
37
+ dispose() {
38
+ super.dispose();
39
+ this._changesToSync.close();
40
+ }
41
+ async _handleSync(protocol, messageId, data, bytes) {
42
+ console.log("GOT SYNC");
43
+ const headerStr = (0, utils_1.splitMessageHeader)(bytes || new Uint8Array());
44
+ const payload = (0, utils_1.splitMessagePayload)(bytes || new Uint8Array());
45
+ const header = JSON.parse(headerStr);
46
+ const path = header["path"];
47
+ const isConnecting = this._connectingDocuments[path];
48
+ if (isConnecting) {
49
+ await isConnecting;
50
+ }
51
+ if (this._connectedDocuments[path]) {
52
+ const rc = this._connectedDocuments[path];
53
+ const doc = rc.ref;
54
+ const base64 = utils_1.decoder.decode(payload);
55
+ console.log(`GOT SYNC ${base64}`);
56
+ (0, runtime_1.applyBackendChanges)(doc.id, base64);
57
+ this.emit("synced", { type: "sync", doc });
58
+ if (!doc.isSynchronized) {
59
+ doc.setSynchronizedComplete();
60
+ }
61
+ }
62
+ else {
63
+ throw new room_server_client_1.RoomServerException(`received change for a document that is not connected: ${path}`);
64
+ }
65
+ }
66
+ async create(path, json) {
67
+ await this.client.sendRequest("room.create", { path, json });
68
+ }
69
+ async open(path, { create = true } = {}) {
70
+ const pending = this._connectingDocuments[path];
71
+ if (pending) {
72
+ await pending;
73
+ }
74
+ if (this._connectedDocuments[path]) {
75
+ const rc = this._connectedDocuments[path];
76
+ rc.count++;
77
+ return rc.ref;
78
+ }
79
+ const c = new completer_1.Completer();
80
+ this._connectingDocuments[path] = c.fut;
81
+ try {
82
+ const result = (await this.client.sendRequest("room.connect", { path, create }));
83
+ const schema = schema_1.MeshSchema.fromJson(result.json["schema"]);
84
+ console.log(JSON.stringify(schema.toJson()));
85
+ const doc = new room_server_client_1.MeshDocument({
86
+ schema,
87
+ sendChangesToBackend: (base64Str) => {
88
+ this._changesToSync.add({ path, base64: base64Str });
89
+ },
90
+ });
91
+ const rc = new utils_1.RefCount(doc);
92
+ this._connectedDocuments[path] = rc;
93
+ this.emit("connected", { type: "connect", doc });
94
+ c.complete();
95
+ return doc;
96
+ }
97
+ catch (err) {
98
+ c.completeError(err);
99
+ throw err;
100
+ }
101
+ finally {
102
+ delete this._connectingDocuments[path];
103
+ }
104
+ }
105
+ async close(path) {
106
+ const rc = this._connectedDocuments[path];
107
+ if (!rc) {
108
+ throw new room_server_client_1.RoomServerException(`Not connected to ${path}`);
109
+ }
110
+ const doc = rc.ref;
111
+ rc.count--;
112
+ if (rc.count === 0) {
113
+ delete this._connectedDocuments[path];
114
+ await this.client.sendRequest("room.disconnect", { path });
115
+ (0, runtime_1.unregisterDocument)(doc.id);
116
+ }
117
+ this.emit("closed", { type: "close", doc });
118
+ }
119
+ async sync(path, data) {
120
+ await this.client.sendRequest("room.sync", { path }, data);
121
+ }
122
+ }
123
+ exports.SyncClient = SyncClient;
@@ -0,0 +1,14 @@
1
+ import { TextDecoder, TextEncoder } from "@kayahr/text-encoding";
2
+ declare const encoder: TextEncoder;
3
+ declare const decoder: TextDecoder;
4
+ export { encoder, decoder };
5
+ export declare function splitMessagePayload(packet: Uint8Array): Uint8Array;
6
+ export declare function splitMessageHeader(packet: Uint8Array): string;
7
+ export declare function packMessage(request: Record<string, any>, data?: Uint8Array): Uint8Array;
8
+ export declare function mergeUint8Arrays(...arrays: Uint8Array[]): Uint8Array;
9
+ export declare function blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer>;
10
+ export declare class RefCount<T> {
11
+ ref: T;
12
+ count: number;
13
+ constructor(ref: T);
14
+ }