@webda/fs 4.0.0-beta.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.
@@ -0,0 +1,423 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import * as fs from "fs";
36
+ import * as path from "path";
37
+ import { Store, StoreNotFoundError, StoreParameters, UpdateConditionFailError, MemoryRepository, EventRepository, InstanceCache, useModelMetadata } from "@webda/core";
38
+ import { JSONUtils } from "@webda/utils";
39
+ /** Configuration parameters for the JSON-file-backed store. */
40
+ export class FileStoreParameters extends StoreParameters {
41
+ /**
42
+ * Local path where to store all `json` files
43
+ */
44
+ folder;
45
+ /**
46
+ * Parameter sent to JSON.stringify when storing the json
47
+ */
48
+ beautify;
49
+ }
50
+ /**
51
+ * A Map-like storage backend backed by filesystem JSON files.
52
+ * Keys are UUIDs; values are JSON strings of stored objects.
53
+ */
54
+ class FileBackedMap extends Map {
55
+ folder;
56
+ extension;
57
+ /** Create a new FileBackedMap.
58
+ * @param folder - the directory to store files in
59
+ * @param extension - the file extension to use
60
+ */
61
+ constructor(folder, extension = ".json") {
62
+ super();
63
+ this.folder = folder;
64
+ this.extension = extension;
65
+ }
66
+ /**
67
+ * Build the full filesystem path for a given key.
68
+ *
69
+ * @param key - the storage key
70
+ * @returns the full file path
71
+ */
72
+ filePath(key) {
73
+ return path.join(this.folder, `${key}${this.extension}`);
74
+ }
75
+ /**
76
+ * Check whether a JSON file exists for the given key.
77
+ *
78
+ * @param key - the storage key
79
+ * @returns true if the file exists
80
+ */
81
+ has(key) {
82
+ return fs.existsSync(this.filePath(key));
83
+ }
84
+ /**
85
+ * Read and return the JSON content for a key, or undefined if missing.
86
+ *
87
+ * @param key - the storage key
88
+ * @returns the JSON content or undefined
89
+ */
90
+ get(key) {
91
+ const p = this.filePath(key);
92
+ if (!fs.existsSync(p))
93
+ return undefined;
94
+ return fs.readFileSync(p, "utf-8");
95
+ }
96
+ /**
97
+ * Write a JSON string value to the file for the given key.
98
+ *
99
+ * @param key - the storage key
100
+ * @param value - the JSON string to write
101
+ * @returns this map for chaining
102
+ */
103
+ set(key, value) {
104
+ fs.writeFileSync(this.filePath(key), value, "utf-8");
105
+ return this;
106
+ }
107
+ /**
108
+ * Remove the JSON file for the given key, returning true if it existed.
109
+ *
110
+ * @param key - the storage key
111
+ * @returns true if the file was deleted
112
+ */
113
+ delete(key) {
114
+ const p = this.filePath(key);
115
+ if (!fs.existsSync(p))
116
+ return false;
117
+ fs.unlinkSync(p);
118
+ return true;
119
+ }
120
+ /** Delete all JSON files in the backing folder. */
121
+ clear() {
122
+ if (fs.existsSync(this.folder)) {
123
+ for (const f of fs.readdirSync(this.folder)) {
124
+ if (f.endsWith(this.extension)) {
125
+ fs.unlinkSync(path.join(this.folder, f));
126
+ }
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Iterate over all stored keys by listing JSON files in the folder.
132
+ *
133
+ * @returns an iterator of storage keys
134
+ */
135
+ keys() {
136
+ if (!fs.existsSync(this.folder))
137
+ return [].values();
138
+ const ext = this.extension;
139
+ const files = fs
140
+ .readdirSync(this.folder)
141
+ .filter(f => f.endsWith(ext))
142
+ .map(f => f.slice(0, f.length - ext.length));
143
+ return files.values();
144
+ }
145
+ /**
146
+ * Iterate over all key-value pairs stored in the folder.
147
+ *
148
+ * @returns an iterator of key-value pairs
149
+ */
150
+ [Symbol.iterator]() {
151
+ const entries = [...this.keys()].map(key => [key, this.get(key)]);
152
+ return entries.values();
153
+ }
154
+ }
155
+ /**
156
+ * Simple file storage of object
157
+ *
158
+ * Storage structure
159
+ * /folder/{uuid}
160
+ *
161
+ * Parameters:
162
+ * folder: to store to
163
+ *
164
+ * @category CoreServices
165
+ * @WebdaModda
166
+ */
167
+ let FileStore = (() => {
168
+ let _classSuper = Store;
169
+ let _instanceExtraInitializers = [];
170
+ let _getRepository_decorators;
171
+ return class FileStore extends _classSuper {
172
+ static {
173
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
174
+ _getRepository_decorators = [InstanceCache()];
175
+ __esDecorate(this, null, _getRepository_decorators, { kind: "method", name: "getRepository", static: false, private: false, access: { has: obj => "getRepository" in obj, get: obj => obj.getRepository }, metadata: _metadata }, null, _instanceExtraInitializers);
176
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
177
+ }
178
+ static EXTENSION = ".json";
179
+ /**
180
+ * Load the parameters for a service
181
+ *
182
+ * @param params - raw parameter values
183
+ * @returns the loaded parameters
184
+ */
185
+ loadParameters(params) {
186
+ return new FileStoreParameters().load(params);
187
+ }
188
+ /**
189
+ * Create the storage folder if does not exist
190
+ */
191
+ computeParameters() {
192
+ super.computeParameters();
193
+ if (!fs.existsSync(this.parameters.folder)) {
194
+ fs.mkdirSync(this.parameters.folder);
195
+ }
196
+ }
197
+ /**
198
+ * Get the file path of an object
199
+ *
200
+ * @param uid - the object unique identifier
201
+ * @returns the file path
202
+ */
203
+ file(uid) {
204
+ return `${this.parameters.folder}/${uid}${FileStore.EXTENSION}`;
205
+ }
206
+ /**
207
+ * @override
208
+ */
209
+ async _exists(uid) {
210
+ return fs.existsSync(this.file(uid));
211
+ }
212
+ /**
213
+ * @override
214
+ */
215
+ async find(query) {
216
+ const files = fs
217
+ .readdirSync(this.parameters.folder)
218
+ .filter(file => {
219
+ return !fs.statSync(path.join(this.parameters.folder, file)).isDirectory();
220
+ })
221
+ .map(f => f.substring(0, f.length - FileStore.EXTENSION.length))
222
+ .sort();
223
+ // Use the repository for this store's model to simulate a find
224
+ const repo = this.getRepository(this._models[0]);
225
+ return MemoryRepository.simulateFind(query, files, repo);
226
+ }
227
+ /**
228
+ * @override
229
+ */
230
+ async _create(uuid, object) {
231
+ const fh = fs.openSync(this.file(uuid), "wx");
232
+ fs.writeSync(fh, JSON.stringify(object, undefined, this.parameters.beautify));
233
+ fs.closeSync(fh);
234
+ return object;
235
+ }
236
+ /**
237
+ * Store in file the object
238
+ *
239
+ * @param uuid - the object unique identifier
240
+ * @param object - the object to persist
241
+ * @returns the persisted object
242
+ */
243
+ async persist(uuid, object) {
244
+ fs.writeFileSync(this.file(uuid), JSON.stringify(object, undefined, this.parameters.beautify));
245
+ return object;
246
+ }
247
+ /**
248
+ * Verify optimistic locking update condition
249
+ *
250
+ * @param uuid - the object unique identifier
251
+ * @param stored - the currently stored object
252
+ * @param writeConditionField - field to check for condition
253
+ * @param writeCondition - expected value of the field
254
+ */
255
+ checkUpdateCondition(uuid, stored, writeConditionField, writeCondition) {
256
+ if (writeConditionField && stored[writeConditionField] !== writeCondition) {
257
+ throw new UpdateConditionFailError(uuid, writeConditionField, writeCondition);
258
+ }
259
+ }
260
+ /**
261
+ * Verify collection item update condition
262
+ *
263
+ * @param stored - the currently stored object
264
+ * @param prop - the collection property name
265
+ * @param itemWriteConditionField - field to check on the item
266
+ * @param itemWriteCondition - expected value of the field
267
+ * @param index - index of the item in the collection
268
+ */
269
+ checkCollectionUpdateCondition(stored, prop, itemWriteConditionField, itemWriteCondition, index) {
270
+ if (itemWriteCondition !== undefined &&
271
+ Array.isArray(stored[prop]) &&
272
+ index < stored[prop].length &&
273
+ stored[prop][index][itemWriteConditionField] !== itemWriteCondition) {
274
+ throw new UpdateConditionFailError(stored.uuid || stored._id || "unknown", itemWriteConditionField, itemWriteCondition);
275
+ }
276
+ }
277
+ /**
278
+ * @override
279
+ */
280
+ async _upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate) {
281
+ let data;
282
+ try {
283
+ data = JSONUtils.loadFile(this.file(uid));
284
+ }
285
+ catch (err) {
286
+ throw new StoreNotFoundError(uid, this.getName());
287
+ }
288
+ if (data === undefined) {
289
+ throw new StoreNotFoundError(uid, this.getName());
290
+ }
291
+ this.checkCollectionUpdateCondition(data, prop, itemWriteConditionField, itemWriteCondition, index);
292
+ data[prop] ??= [];
293
+ if (typeof index === "number") {
294
+ data[prop][index] = item;
295
+ }
296
+ else {
297
+ data[prop].push(item);
298
+ }
299
+ data._lastUpdate = updateDate;
300
+ return this.persist(uid, data);
301
+ }
302
+ /**
303
+ * @override
304
+ */
305
+ async _removeAttribute(uuid, attribute, writeCondition, writeConditionField) {
306
+ const res = await this._get(uuid, true);
307
+ this.checkUpdateCondition(uuid, res, writeConditionField, writeCondition);
308
+ delete res[attribute];
309
+ await this.persist(uuid, res);
310
+ }
311
+ /**
312
+ * @override
313
+ */
314
+ async _deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate) {
315
+ const res = await this._get(uid, true);
316
+ this.checkCollectionUpdateCondition(res, prop, itemWriteConditionField, itemWriteCondition, index);
317
+ res[prop].splice(index, 1);
318
+ res._lastUpdate = updateDate;
319
+ return this.persist(uid, res);
320
+ }
321
+ /**
322
+ * @override
323
+ */
324
+ async _delete(uid) {
325
+ const filePath = this.file(uid);
326
+ if (fs.existsSync(filePath)) {
327
+ fs.unlinkSync(filePath);
328
+ }
329
+ }
330
+ /**
331
+ * @override
332
+ */
333
+ async _patch(object, uid, writeCondition, writeConditionField) {
334
+ const stored = await this._get(uid, true);
335
+ this.checkUpdateCondition(uid, stored, writeConditionField, writeCondition);
336
+ for (const prop in object) {
337
+ stored[prop] = object[prop];
338
+ }
339
+ return this.persist(uid, stored);
340
+ }
341
+ /**
342
+ * @override
343
+ */
344
+ async _update(object, uid, writeCondition, writeConditionField) {
345
+ const stored = await this._get(uid, true);
346
+ this.checkUpdateCondition(uid, stored, writeConditionField, writeCondition);
347
+ return this.persist(uid, object);
348
+ }
349
+ /**
350
+ * @override
351
+ */
352
+ async getAll(uids) {
353
+ if (!uids) {
354
+ uids = [];
355
+ const files = fs.readdirSync(this.parameters.folder);
356
+ for (const file in files) {
357
+ uids.push(files[file].substring(0, files[file].length - FileStore.EXTENSION.length));
358
+ }
359
+ }
360
+ const result = [];
361
+ for (const i in uids) {
362
+ const model = this._get(uids[i]);
363
+ result.push(model);
364
+ }
365
+ return (await Promise.all(result)).filter(f => f !== undefined);
366
+ }
367
+ /**
368
+ * @override
369
+ */
370
+ async _get(uid, raiseIfNotFound = false) {
371
+ const res = await this._exists(uid);
372
+ if (res) {
373
+ const data = JSON.parse(fs.readFileSync(this.file(uid)).toString());
374
+ if (this.parameters.strict && this._modelsHierarchy[data.__type] !== 0) {
375
+ return undefined;
376
+ }
377
+ return data;
378
+ }
379
+ else if (raiseIfNotFound) {
380
+ throw new StoreNotFoundError(uid, this.getName());
381
+ }
382
+ }
383
+ /**
384
+ * @override
385
+ */
386
+ async _incrementAttributes(uid, params, updateDate) {
387
+ const stored = await this._get(uid, true);
388
+ params.forEach(({ property: prop, value }) => {
389
+ if (stored[prop] === undefined) {
390
+ stored[prop] = 0;
391
+ }
392
+ stored._lastUpdate = updateDate;
393
+ stored[prop] += value;
394
+ });
395
+ stored._lastUpdate = updateDate;
396
+ return this.persist(uid, stored);
397
+ }
398
+ /**
399
+ * @override
400
+ */
401
+ getRepository(model) {
402
+ const meta = useModelMetadata(model);
403
+ const storage = new FileBackedMap(this.parameters.folder, FileStore.EXTENSION);
404
+ const inner = new MemoryRepository(model, meta.PrimaryKey, undefined, storage);
405
+ // Wrap in EventRepository so typed CRUD events fire; consumers reach them
406
+ // via useRepository(model).on(...). simulateFind() only calls repo.get(),
407
+ // which EventRepository proxies, so find() is unaffected.
408
+ return new EventRepository(model, meta.PrimaryKey, inner);
409
+ }
410
+ /**
411
+ * @override
412
+ */
413
+ async __clean() {
414
+ (await import("fs-extra")).emptyDirSync(this.parameters.folder);
415
+ }
416
+ constructor() {
417
+ super(...arguments);
418
+ __runInitializers(this, _instanceExtraInitializers);
419
+ }
420
+ };
421
+ })();
422
+ export { FileStore };
423
+ //# sourceMappingURL=filestore.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filestore.service.js","sourceRoot":"","sources":["../src/filestore.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EACL,KAAK,EAEL,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,+DAA+D;AAC/D,MAAM,OAAO,mBAAoB,SAAQ,eAAe;IACtD;;OAEG;IACH,MAAM,CAAS;IACf;;OAEG;IACH,QAAQ,CAAmB;CAC5B;AAED;;;GAGG;AACH,MAAM,aAAc,SAAQ,GAAmB;IAMnC,MAAM;IACN,SAAS;IANnB;;;OAGG;IACH,YACU,MAAc,EACd,SAAS,GAAW,OAAO;QAEnC,KAAK,EAAE,CAAC;sBAHA,MAAM;yBACN,SAAS;IAGnB,CAAC;IAED;;;;;OAKG;IACK,QAAQ,CAAC,GAAW;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAC,GAAW;QACb,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACxC,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACH,GAAG,CAAC,GAAW,EAAE,KAAa;QAC5B,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,GAAW;QAChB,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mDAAmD;IACnD,KAAK;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC/B,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC3C,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;QAC3B,MAAM,KAAK,GAAG,EAAE;aACb,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC;aACxB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;aAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/C,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC;QACf,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAE,CAAqB,CAAC,CAAC;QACvF,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;IAC1B,CAAC;CACF;AAED;;;;;;;;;;;GAWG;IACU,SAAS;sBAA8D,KAAK;;;iBAA5E,SAA+D,SAAQ,WAAQ;;;yCAgRzF,aAAa,EAAE;YAChB,0LAAA,aAAa,6DAQZ;;;QAxRD,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC;QAE3B;;;;;WAKG;QACH,cAAc,CAAC,MAAW;YACxB,OAAU,IAAI,mBAAmB,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,CAAC;QAED;;WAEG;QACH,iBAAiB;YACf,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED;;;;;WAKG;QACH,IAAI,CAAC,GAAG;YACN,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;QAClE,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,OAAO,CAAC,GAAG;YACf,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,IAAI,CAAC,KAAoB;YAC7B,MAAM,KAAK,GAAG,EAAE;iBACb,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;iBACnC,MAAM,CAAC,IAAI,CAAC,EAAE;gBACb,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YAC7E,CAAC,CAAC;iBACD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;iBAC/D,IAAI,EAAE,CAAC;YAEV,+DAA+D;YAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAA0B,CAAC;YAC1E,OAAO,gBAAgB,CAAC,YAAY,CAAC,KAAY,EAAE,KAAK,EAAE,IAAW,CAAC,CAAC;QACzE,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,MAAW;YACrC,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;YAC9C,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC9E,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACjB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED;;;;;;WAMG;QACO,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,MAAW;YAC/C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC/F,OAAO,MAAM,CAAC;QAChB,CAAC;QAED;;;;;;;WAOG;QACO,oBAAoB,CAAC,IAAY,EAAE,MAAW,EAAE,mBAA4B,EAAE,cAAoB;YAC1G,IAAI,mBAAmB,IAAI,MAAM,CAAC,mBAAmB,CAAC,KAAK,cAAc,EAAE,CAAC;gBAC1E,MAAM,IAAI,wBAAwB,CAAC,IAAW,EAAE,mBAAmB,EAAE,cAAc,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;QAED;;;;;;;;WAQG;QACO,8BAA8B,CACtC,MAAW,EACX,IAAY,EACZ,uBAA+B,EAC/B,kBAAuB,EACvB,KAAa;YAEb,IACE,kBAAkB,KAAK,SAAS;gBAChC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC3B,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;gBAC3B,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,uBAAuB,CAAC,KAAK,kBAAkB,EACnE,CAAC;gBACD,MAAM,IAAI,wBAAwB,CAChC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,IAAK,SAAiB,EAC/C,uBAAuB,EACvB,kBAAkB,CACnB,CAAC;YACJ,CAAC;QACH,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,uBAAuB,CAC3B,GAAW,EACX,IAAY,EACZ,IAAS,EACT,KAAa,EACb,kBAAuB,EACvB,uBAA+B,EAC/B,UAAgB;YAEhB,IAAI,IAAS,CAAC;YACd,IAAI,CAAC;gBACH,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,kBAAkB,CAAC,GAAU,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC;YACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,MAAM,IAAI,kBAAkB,CAAC,GAAU,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC;YACD,IAAI,CAAC,8BAA8B,CAAC,IAAI,EAAE,IAAI,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;YACpG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;YAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,gBAAgB,CAAC,IAAY,EAAE,SAAiB,EAAE,cAAoB,EAAE,mBAA4B;YACxG,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,GAAG,EAAE,mBAAmB,EAAE,cAAc,CAAC,CAAC;YAC1E,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC;YACtB,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,yBAAyB,CAC7B,GAAW,EACX,IAAY,EACZ,KAAa,EACb,kBAAuB,EACvB,uBAA+B,EAC/B,UAAgB;YAEhB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACvC,IAAI,CAAC,8BAA8B,CAAC,GAAG,EAAE,IAAI,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;YACnG,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC3B,GAAG,CAAC,WAAW,GAAG,UAAU,CAAC;YAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,OAAO,CAAC,GAAW;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,MAAM,CAAC,MAAW,EAAE,GAAW,EAAE,cAAoB,EAAE,mBAA4B;YACvF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,mBAAmB,EAAE,cAAc,CAAC,CAAC;YAC5E,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,cAAoB,EAAE,mBAA4B;YACxF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,mBAAmB,EAAE,cAAc,CAAC,CAAC;YAC5E,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,MAAM,CAAC,IAAe;YAC1B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,GAAG,EAAE,CAAC;gBACV,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBACrD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;gBACvF,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YACD,OAAO,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;QAClE,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,eAAe,GAAY,KAAK;YACtD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACpE,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBACvE,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;iBAAM,IAAI,eAAe,EAAE,CAAC;gBAC3B,MAAM,IAAI,kBAAkB,CAAC,GAAU,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,oBAAoB,CACxB,GAAW,EACX,MAA6C,EAC7C,UAAgB;YAEhB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;gBAC3C,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;oBAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnB,CAAC;gBACD,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;YACxB,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC;YAChC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QAED;;WAEG;QAEH,aAAa,CAAuB,KAAQ;YAC1C,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;YAC/E,MAAM,KAAK,GAAG,IAAI,gBAAgB,CAAI,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,OAAc,CAAC,CAAC;YACzF,0EAA0E;YAC1E,0EAA0E;YAC1E,0DAA0D;YAC1D,OAAO,IAAI,eAAe,CAAI,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,CAA6B,CAAC;QAC3F,CAAC;QAED;;WAEG;QACH,KAAK,CAAC,OAAO;YACX,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;;;YAhSU,mDAAS;;;;SAAT,SAAS"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./filebinary.service.js";
2
+ export * from "./filequeue.service.js";
3
+ export * from "./filestore.service.js";
4
+ export * from "./socketpubsub.service.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./filebinary.service.js";
2
+ export * from "./filequeue.service.js";
3
+ export * from "./filestore.service.js";
4
+ export * from "./socketpubsub.service.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,150 @@
1
+ import { PubSubService, ServiceParameters } from "@webda/core";
2
+ import { CancelablePromise } from "@webda/utils";
3
+ import * as net from "net";
4
+ /**
5
+ * Configuration for {@link SocketPubSubService}.
6
+ */
7
+ export declare class SocketPubSubParameters extends ServiceParameters {
8
+ /**
9
+ * Filesystem path of the unix-domain socket. The first peer to bind this
10
+ * path becomes the broker; subsequent peers connect as clients.
11
+ */
12
+ path: string;
13
+ /**
14
+ * Reconnect delay in milliseconds when the broker disconnects. A small
15
+ * random jitter is added on top to avoid stampedes when several clients
16
+ * race to bind a new socket.
17
+ *
18
+ * @default 100
19
+ */
20
+ reconnectDelay?: number;
21
+ /**
22
+ * @override
23
+ * @param params - the input parameters
24
+ * @returns this
25
+ */
26
+ load(params?: any): this;
27
+ }
28
+ interface Subscriber<T> {
29
+ callback: (event: T) => Promise<void>;
30
+ proto?: {
31
+ new (): T;
32
+ };
33
+ }
34
+ /**
35
+ * Pub/sub backed by a unix-domain socket. Designed for single-host IPC:
36
+ * one peer binds the socket file and acts as broker, fanning each
37
+ * published message out to every connected client; other peers connect as
38
+ * clients. Any peer can publish — non-broker publishers send through the
39
+ * socket and the broker fanouts. Every connected peer (publisher
40
+ * included) receives every message, so the in-process semantics match the
41
+ * cross-process ones.
42
+ *
43
+ * If the broker disconnects, surviving clients reconnect after a short
44
+ * randomized delay; one of them wins the bind race and becomes the new
45
+ * broker. Stale socket files left by killed brokers are detected via
46
+ * `connect()` returning ECONNREFUSED and unlinked before re-binding.
47
+ *
48
+ * Wire format: 4-byte big-endian uint32 length prefix followed by a UTF-8
49
+ * JSON payload.
50
+ *
51
+ * @WebdaModda SocketPubSub
52
+ */
53
+ export default class SocketPubSubService<T = any, K extends SocketPubSubParameters = SocketPubSubParameters> extends PubSubService<T, K> {
54
+ /**
55
+ * Broker-mode listener. Set when this peer is the broker, undefined
56
+ * otherwise. Mutually exclusive with {@link clientSocket}.
57
+ */
58
+ protected server?: net.Server;
59
+ /**
60
+ * Outbound socket to the broker, when this peer is a client.
61
+ */
62
+ protected clientSocket?: net.Socket;
63
+ /**
64
+ * Active subscriber sockets the broker fans messages out to.
65
+ */
66
+ protected subscribers: Set<net.Socket>;
67
+ /**
68
+ * Local callback registrations made via {@link consume}. The broker
69
+ * dispatches to these directly; client-mode peers feed them from the
70
+ * broker socket's incoming frames.
71
+ */
72
+ protected callbacks: Set<Subscriber<T>>;
73
+ /**
74
+ * Set during {@link stop} so disconnect handlers don't try to reconnect
75
+ * after we've torn down.
76
+ */
77
+ protected stopping: boolean;
78
+ /**
79
+ * @override
80
+ * @returns this service
81
+ */
82
+ init(): Promise<this>;
83
+ /**
84
+ * Connect to an existing broker, or bind ourselves as broker if there
85
+ * isn't one. Handles the EADDRINUSE race by retrying as a client.
86
+ */
87
+ protected connect(): Promise<void>;
88
+ /**
89
+ * Bind the socket file and start listening. On every accepted connection
90
+ * we frame-decode incoming bytes, fanout the raw frame to all OTHER
91
+ * subscribers, and dispatch the parsed payload to local callbacks.
92
+ * @param path - filesystem path of the unix socket
93
+ * @returns resolves once the listener is up
94
+ */
95
+ protected bindAsBroker(path: string): Promise<void>;
96
+ /**
97
+ * Open a client socket to the broker.
98
+ * @param path - filesystem path of the unix socket
99
+ * @returns resolves once connected, rejects on the first connection error
100
+ */
101
+ protected connectAsClient(path: string): Promise<void>;
102
+ /**
103
+ * Schedule a reconnect attempt after a randomized backoff. The jitter
104
+ * keeps surviving clients from all racing to bind the new socket on the
105
+ * same tick.
106
+ */
107
+ protected handleBrokerDisconnect(): void;
108
+ /**
109
+ * Write a framed payload to every subscriber except the optional sender
110
+ * (used to avoid echoing a client's own message back to it via the
111
+ * broker — the client receives it via its local callback dispatch
112
+ * instead).
113
+ * @param buf - the unframed JSON payload bytes
114
+ * @param except - optional socket to exclude from fanout
115
+ */
116
+ protected fanout(buf: Buffer, except?: net.Socket): void;
117
+ /**
118
+ * Decode a JSON frame and run every registered callback against it.
119
+ * Errors thrown by callbacks are swallowed (logged + counted) so one bad
120
+ * subscriber doesn't break others.
121
+ * @param buf - the unframed JSON payload bytes
122
+ */
123
+ protected dispatchToCallbacks(buf: Buffer): void;
124
+ /**
125
+ * @override
126
+ * @param event - the event to publish
127
+ */
128
+ sendMessage(event: T): Promise<void>;
129
+ /**
130
+ * @override
131
+ * @returns 0 — pub/sub is transient, no queueing
132
+ */
133
+ size(): Promise<number>;
134
+ /**
135
+ * @override
136
+ * @param callback - invoked with each event received
137
+ * @param eventPrototype - optional class to rehydrate JSON into
138
+ * @param onBind - invoked once the subscription is registered
139
+ * @returns a cancelable subscription handle
140
+ */
141
+ consume(callback: (event: T) => Promise<void>, eventPrototype?: {
142
+ new (): T;
143
+ }, onBind?: () => void): CancelablePromise;
144
+ /**
145
+ * @override
146
+ */
147
+ stop(): Promise<void>;
148
+ }
149
+ export { SocketPubSubService };
150
+ //# sourceMappingURL=socketpubsub.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socketpubsub.service.d.ts","sourceRoot":"","sources":["../src/socketpubsub.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAa,MAAM,cAAc,CAAC;AAG5D,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAG3B;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,iBAAiB;IAC3D;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,IAAI,CAAC,MAAM,GAAE,GAAQ,GAAG,IAAI,CAI3B;CACF;AAED,UAAU,UAAU,CAAC,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,CAAA;KAAE,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB,CACtC,CAAC,GAAG,GAAG,EACP,CAAC,SAAS,sBAAsB,GAAG,sBAAsB,CACzD,SAAQ,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3B;;;OAGG;IACH,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;IAC9B;;OAEG;IACH,SAAS,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;IACpC;;OAEG;IACH,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAa;IACnD;;;;OAIG;IACH,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAa;IACpD;;;OAGG;IACH,SAAS,CAAC,QAAQ,UAAS;IAE3B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAI1B;IAED;;;OAGG;IACH,UAAgB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BvC;IAED;;;;;;OAMG;IACH,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBlD;IAED;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBrD;IAED;;;;OAIG;IACH,SAAS,CAAC,sBAAsB,IAAI,IAAI,CAQvC;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAMvD;IAED;;;;;OAKG;IACH,SAAS,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAuB/C;IAED;;;OAGG;IACG,WAAW,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAezC;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAE5B;IAED;;;;;;OAMG;IACH,OAAO,CACL,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACrC,cAAc,CAAC,EAAE;QAAE,QAAQ,CAAC,CAAA;KAAE,EAC9B,MAAM,CAAC,EAAE,MAAM,IAAI,GAClB,iBAAiB,CAenB;IAED;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAoB1B;CACF;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC"}