document-drive 1.19.0 → 1.20.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 (252) hide show
  1. package/README.md +4 -0
  2. package/dist/index.d.ts +28 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +18 -0
  5. package/dist/src/cache/memory.d.ts +10 -0
  6. package/dist/src/cache/memory.d.ts.map +1 -0
  7. package/dist/src/cache/memory.js +26 -0
  8. package/dist/src/cache/redis.d.ts +14 -0
  9. package/dist/src/cache/redis.d.ts.map +1 -0
  10. package/dist/src/cache/redis.js +40 -0
  11. package/dist/src/cache/types.d.ts +7 -0
  12. package/dist/src/cache/types.d.ts.map +1 -0
  13. package/dist/src/cache/types.js +1 -0
  14. package/dist/src/drive-document-model/constants.d.ts +2 -0
  15. package/dist/src/drive-document-model/constants.d.ts.map +1 -0
  16. package/dist/src/drive-document-model/constants.js +1 -0
  17. package/dist/src/drive-document-model/gen/actions.d.ts +7 -0
  18. package/dist/src/drive-document-model/gen/actions.d.ts.map +1 -0
  19. package/dist/src/drive-document-model/gen/actions.js +2 -0
  20. package/dist/src/drive-document-model/gen/constants.d.ts +7 -0
  21. package/dist/src/drive-document-model/gen/constants.d.ts.map +1 -0
  22. package/dist/src/drive-document-model/gen/constants.js +16 -0
  23. package/dist/src/drive-document-model/gen/creators.d.ts +3 -0
  24. package/dist/src/drive-document-model/gen/creators.d.ts.map +1 -0
  25. package/dist/src/drive-document-model/gen/creators.js +2 -0
  26. package/dist/src/drive-document-model/gen/document-model.d.ts +3 -0
  27. package/dist/src/drive-document-model/gen/document-model.d.ts.map +1 -0
  28. package/dist/src/drive-document-model/gen/document-model.js +210 -0
  29. package/dist/src/drive-document-model/gen/drive/actions.d.ts +12 -0
  30. package/dist/src/drive-document-model/gen/drive/actions.d.ts.map +1 -0
  31. package/dist/src/drive-document-model/gen/drive/actions.js +1 -0
  32. package/dist/src/drive-document-model/gen/drive/creators.d.ts +11 -0
  33. package/dist/src/drive-document-model/gen/drive/creators.d.ts.map +1 -0
  34. package/dist/src/drive-document-model/gen/drive/creators.js +10 -0
  35. package/dist/src/drive-document-model/gen/drive/error.d.ts +2 -0
  36. package/dist/src/drive-document-model/gen/drive/error.d.ts.map +1 -0
  37. package/dist/src/drive-document-model/gen/drive/error.js +1 -0
  38. package/dist/src/drive-document-model/gen/drive/object.d.ts +14 -0
  39. package/dist/src/drive-document-model/gen/drive/object.d.ts.map +1 -0
  40. package/dist/src/drive-document-model/gen/drive/object.js +28 -0
  41. package/dist/src/drive-document-model/gen/drive/operations.d.ts +14 -0
  42. package/dist/src/drive-document-model/gen/drive/operations.d.ts.map +1 -0
  43. package/dist/src/drive-document-model/gen/drive/operations.js +1 -0
  44. package/dist/src/drive-document-model/gen/node/actions.d.ts +11 -0
  45. package/dist/src/drive-document-model/gen/node/actions.d.ts.map +1 -0
  46. package/dist/src/drive-document-model/gen/node/actions.js +1 -0
  47. package/dist/src/drive-document-model/gen/node/creators.d.ts +10 -0
  48. package/dist/src/drive-document-model/gen/node/creators.d.ts.map +1 -0
  49. package/dist/src/drive-document-model/gen/node/creators.js +9 -0
  50. package/dist/src/drive-document-model/gen/node/error.d.ts +2 -0
  51. package/dist/src/drive-document-model/gen/node/error.d.ts.map +1 -0
  52. package/dist/src/drive-document-model/gen/node/error.js +1 -0
  53. package/dist/src/drive-document-model/gen/node/object.d.ts +13 -0
  54. package/dist/src/drive-document-model/gen/node/object.d.ts.map +1 -0
  55. package/dist/src/drive-document-model/gen/node/object.js +25 -0
  56. package/dist/src/drive-document-model/gen/node/operations.d.ts +13 -0
  57. package/dist/src/drive-document-model/gen/node/operations.d.ts.map +1 -0
  58. package/dist/src/drive-document-model/gen/node/operations.js +1 -0
  59. package/dist/src/drive-document-model/gen/object.d.ts +21 -0
  60. package/dist/src/drive-document-model/gen/object.d.ts.map +1 -0
  61. package/dist/src/drive-document-model/gen/object.js +28 -0
  62. package/dist/src/drive-document-model/gen/reducer.d.ts +4 -0
  63. package/dist/src/drive-document-model/gen/reducer.d.ts.map +1 -0
  64. package/dist/src/drive-document-model/gen/reducer.js +74 -0
  65. package/dist/src/drive-document-model/gen/schema/types.d.ts +176 -0
  66. package/dist/src/drive-document-model/gen/schema/types.d.ts.map +1 -0
  67. package/dist/src/drive-document-model/gen/schema/types.js +1 -0
  68. package/dist/src/drive-document-model/gen/schema/zod.d.ts +87 -0
  69. package/dist/src/drive-document-model/gen/schema/zod.d.ts.map +1 -0
  70. package/dist/src/drive-document-model/gen/schema/zod.js +203 -0
  71. package/dist/src/drive-document-model/gen/types.d.ts +9 -0
  72. package/dist/src/drive-document-model/gen/types.d.ts.map +1 -0
  73. package/dist/src/drive-document-model/gen/types.js +1 -0
  74. package/dist/src/drive-document-model/gen/utils.d.ts +10 -0
  75. package/dist/src/drive-document-model/gen/utils.d.ts.map +1 -0
  76. package/dist/src/drive-document-model/gen/utils.js +27 -0
  77. package/dist/src/drive-document-model/index.d.ts +2 -0
  78. package/dist/src/drive-document-model/index.d.ts.map +1 -0
  79. package/dist/src/drive-document-model/index.js +1 -0
  80. package/dist/src/drive-document-model/module.d.ts +3 -0
  81. package/dist/src/drive-document-model/module.d.ts.map +1 -0
  82. package/dist/src/drive-document-model/module.js +12 -0
  83. package/dist/src/drive-document-model/src/reducers/drive.d.ts +8 -0
  84. package/dist/src/drive-document-model/src/reducers/drive.d.ts.map +1 -0
  85. package/dist/src/drive-document-model/src/reducers/drive.js +37 -0
  86. package/dist/src/drive-document-model/src/reducers/node.d.ts +8 -0
  87. package/dist/src/drive-document-model/src/reducers/node.d.ts.map +1 -0
  88. package/dist/src/drive-document-model/src/reducers/node.js +185 -0
  89. package/dist/src/drive-document-model/src/utils.d.ts +34 -0
  90. package/dist/src/drive-document-model/src/utils.d.ts.map +1 -0
  91. package/dist/src/drive-document-model/src/utils.js +146 -0
  92. package/dist/src/queue/base.d.ts +43 -0
  93. package/dist/src/queue/base.d.ts.map +1 -0
  94. package/dist/src/queue/base.js +241 -0
  95. package/dist/src/queue/redis.d.ts +28 -0
  96. package/dist/src/queue/redis.d.ts.map +1 -0
  97. package/dist/src/queue/redis.js +110 -0
  98. package/dist/src/queue/types.d.ts +55 -0
  99. package/dist/src/queue/types.d.ts.map +1 -0
  100. package/dist/src/queue/types.js +6 -0
  101. package/dist/src/read-mode/errors.d.ts +12 -0
  102. package/dist/src/read-mode/errors.d.ts.map +1 -0
  103. package/dist/src/read-mode/errors.js +17 -0
  104. package/dist/src/read-mode/server.d.ts +4 -0
  105. package/dist/src/read-mode/server.d.ts.map +1 -0
  106. package/dist/src/read-mode/server.js +78 -0
  107. package/dist/src/read-mode/service.d.ts +18 -0
  108. package/dist/src/read-mode/service.d.ts.map +1 -0
  109. package/dist/src/read-mode/service.js +112 -0
  110. package/dist/src/read-mode/types.d.ts +35 -0
  111. package/dist/src/read-mode/types.d.ts.map +1 -0
  112. package/dist/src/read-mode/types.js +1 -0
  113. package/dist/src/server/base-server.d.ts +112 -0
  114. package/dist/src/server/base-server.d.ts.map +1 -0
  115. package/dist/src/server/base-server.js +1280 -0
  116. package/dist/src/server/builder.d.ts +30 -0
  117. package/dist/src/server/builder.d.ts.map +1 -0
  118. package/dist/src/server/builder.js +89 -0
  119. package/dist/src/server/constants.d.ts +2 -0
  120. package/dist/src/server/constants.d.ts.map +1 -0
  121. package/dist/src/server/constants.js +1 -0
  122. package/dist/src/server/error.d.ts +30 -0
  123. package/dist/src/server/error.d.ts.map +1 -0
  124. package/dist/src/server/error.js +47 -0
  125. package/dist/src/server/event-emitter.d.ts +8 -0
  126. package/dist/src/server/event-emitter.d.ts.map +1 -0
  127. package/dist/src/server/event-emitter.js +10 -0
  128. package/dist/src/server/listener/index.d.ts +2 -0
  129. package/dist/src/server/listener/index.d.ts.map +1 -0
  130. package/dist/src/server/listener/index.js +1 -0
  131. package/dist/src/server/listener/listener-manager.d.ts +27 -0
  132. package/dist/src/server/listener/listener-manager.d.ts.map +1 -0
  133. package/dist/src/server/listener/listener-manager.js +401 -0
  134. package/dist/src/server/listener/transmitter/factory.d.ts +8 -0
  135. package/dist/src/server/listener/transmitter/factory.d.ts.map +1 -0
  136. package/dist/src/server/listener/transmitter/factory.js +25 -0
  137. package/dist/src/server/listener/transmitter/internal.d.ts +34 -0
  138. package/dist/src/server/listener/transmitter/internal.d.ts.map +1 -0
  139. package/dist/src/server/listener/transmitter/internal.js +87 -0
  140. package/dist/src/server/listener/transmitter/pull-responder.d.ts +38 -0
  141. package/dist/src/server/listener/transmitter/pull-responder.d.ts.map +1 -0
  142. package/dist/src/server/listener/transmitter/pull-responder.js +256 -0
  143. package/dist/src/server/listener/transmitter/switchboard-push.d.ts +9 -0
  144. package/dist/src/server/listener/transmitter/switchboard-push.d.ts.map +1 -0
  145. package/dist/src/server/listener/transmitter/switchboard-push.js +77 -0
  146. package/dist/src/server/listener/transmitter/types.d.ts +20 -0
  147. package/dist/src/server/listener/transmitter/types.d.ts.map +1 -0
  148. package/dist/src/server/listener/transmitter/types.js +1 -0
  149. package/dist/src/server/listener/util.d.ts +2 -0
  150. package/dist/src/server/listener/util.d.ts.map +1 -0
  151. package/dist/src/server/listener/util.js +22 -0
  152. package/dist/src/server/sync-manager.d.ts +30 -0
  153. package/dist/src/server/sync-manager.d.ts.map +1 -0
  154. package/dist/src/server/sync-manager.js +287 -0
  155. package/dist/src/server/types.d.ts +308 -0
  156. package/dist/src/server/types.d.ts.map +1 -0
  157. package/dist/src/server/types.js +12 -0
  158. package/dist/src/server/utils.d.ts +8 -0
  159. package/dist/src/server/utils.d.ts.map +1 -0
  160. package/dist/src/server/utils.js +47 -0
  161. package/dist/src/storage/base.d.ts +36 -0
  162. package/dist/src/storage/base.d.ts.map +1 -0
  163. package/dist/src/storage/base.js +4 -0
  164. package/dist/src/storage/browser.d.ts +36 -0
  165. package/dist/src/storage/browser.d.ts.map +1 -0
  166. package/dist/src/storage/browser.js +155 -0
  167. package/dist/src/storage/filesystem.d.ts +33 -0
  168. package/dist/src/storage/filesystem.d.ts.map +1 -0
  169. package/dist/src/storage/filesystem.js +197 -0
  170. package/dist/src/storage/memory.d.ts +33 -0
  171. package/dist/src/storage/memory.d.ts.map +1 -0
  172. package/dist/src/storage/memory.js +139 -0
  173. package/dist/src/storage/prisma.d.ts +67 -0
  174. package/dist/src/storage/prisma.d.ts.map +1 -0
  175. package/dist/src/storage/prisma.js +445 -0
  176. package/dist/src/storage/sequelize.d.ts +32 -0
  177. package/dist/src/storage/sequelize.d.ts.map +1 -0
  178. package/dist/src/storage/sequelize.js +373 -0
  179. package/dist/src/storage/types.d.ts +43 -0
  180. package/dist/src/storage/types.d.ts.map +1 -0
  181. package/dist/src/storage/types.js +1 -0
  182. package/dist/src/utils/default-drives-manager.d.ts +29 -0
  183. package/dist/src/utils/default-drives-manager.d.ts.map +1 -0
  184. package/dist/src/utils/default-drives-manager.js +208 -0
  185. package/dist/src/utils/graphql.d.ts +34 -0
  186. package/dist/src/utils/graphql.d.ts.map +1 -0
  187. package/dist/src/utils/graphql.js +183 -0
  188. package/dist/src/utils/logger.d.ts +27 -0
  189. package/dist/src/utils/logger.d.ts.map +1 -0
  190. package/dist/src/utils/logger.js +105 -0
  191. package/dist/src/utils/migrations.d.ts +4 -0
  192. package/dist/src/utils/migrations.d.ts.map +1 -0
  193. package/dist/src/utils/migrations.js +41 -0
  194. package/dist/src/utils/misc.d.ts +11 -0
  195. package/dist/src/utils/misc.d.ts.map +1 -0
  196. package/dist/src/utils/misc.js +43 -0
  197. package/dist/src/utils/run-asap.d.ts +12 -0
  198. package/dist/src/utils/run-asap.d.ts.map +1 -0
  199. package/dist/src/utils/run-asap.js +131 -0
  200. package/dist/test/document-helpers/utils.d.ts +8 -0
  201. package/dist/test/document-helpers/utils.d.ts.map +1 -0
  202. package/dist/test/document-helpers/utils.js +21 -0
  203. package/dist/test/utils.d.ts +48 -0
  204. package/dist/test/utils.d.ts.map +1 -0
  205. package/dist/test/utils.js +132 -0
  206. package/dist/test/vitest-setup.d.ts +2 -0
  207. package/dist/test/vitest-setup.d.ts.map +1 -0
  208. package/dist/test/vitest-setup.js +4 -0
  209. package/dist/tsconfig.tsbuildinfo +1 -0
  210. package/dist/vitest.config.d.ts +3 -0
  211. package/dist/vitest.config.d.ts.map +1 -0
  212. package/dist/vitest.config.js +20 -0
  213. package/package.json +20 -38
  214. package/src/cache/index.ts +0 -2
  215. package/src/cache/memory.ts +0 -33
  216. package/src/cache/redis.ts +0 -56
  217. package/src/cache/types.ts +0 -9
  218. package/src/index.ts +0 -4
  219. package/src/queue/base.ts +0 -320
  220. package/src/queue/index.ts +0 -2
  221. package/src/queue/redis.ts +0 -144
  222. package/src/queue/types.ts +0 -79
  223. package/src/read-mode/errors.ts +0 -19
  224. package/src/read-mode/index.ts +0 -125
  225. package/src/read-mode/service.ts +0 -207
  226. package/src/read-mode/types.ts +0 -108
  227. package/src/server/error.ts +0 -70
  228. package/src/server/index.ts +0 -2444
  229. package/src/server/listener/index.ts +0 -2
  230. package/src/server/listener/manager.ts +0 -652
  231. package/src/server/listener/transmitter/index.ts +0 -4
  232. package/src/server/listener/transmitter/internal.ts +0 -143
  233. package/src/server/listener/transmitter/pull-responder.ts +0 -462
  234. package/src/server/listener/transmitter/switchboard-push.ts +0 -125
  235. package/src/server/listener/transmitter/types.ts +0 -27
  236. package/src/server/types.ts +0 -596
  237. package/src/server/utils.ts +0 -82
  238. package/src/storage/base.ts +0 -81
  239. package/src/storage/browser.ts +0 -238
  240. package/src/storage/filesystem.ts +0 -297
  241. package/src/storage/index.ts +0 -2
  242. package/src/storage/memory.ts +0 -211
  243. package/src/storage/prisma.ts +0 -653
  244. package/src/storage/sequelize.ts +0 -498
  245. package/src/storage/types.ts +0 -97
  246. package/src/utils/default-drives-manager.ts +0 -341
  247. package/src/utils/document-helpers.ts +0 -21
  248. package/src/utils/graphql.ts +0 -301
  249. package/src/utils/index.ts +0 -90
  250. package/src/utils/logger.ts +0 -38
  251. package/src/utils/migrations.ts +0 -58
  252. package/src/utils/run-asap.ts +0 -156
@@ -0,0 +1,47 @@
1
+ export function buildRevisionsFilter(strands, driveId, documentId) {
2
+ return strands.reduce((acc, s) => {
3
+ if (!(s.driveId === driveId && s.documentId === documentId)) {
4
+ return acc;
5
+ }
6
+ acc[s.scope] = s.operations[s.operations.length - 1]?.index ?? -1;
7
+ return acc;
8
+ }, {});
9
+ }
10
+ export function buildDocumentRevisionsFilter(document) {
11
+ return Object.entries(document.operations).reduce((acc, [scope, operations]) => {
12
+ acc[scope] = operations.at(-1)?.index ?? -1;
13
+ return acc;
14
+ }, {});
15
+ }
16
+ export function filterOperationsByRevision(operations, revisions) {
17
+ if (!revisions) {
18
+ return operations;
19
+ }
20
+ return Object.keys(operations).reduce((acc, scope) => {
21
+ const revision = revisions[scope];
22
+ if (revision !== undefined) {
23
+ acc[scope] = operations[scope].filter((op) => op.index <= revision);
24
+ }
25
+ return acc;
26
+ }, { global: [], local: [] });
27
+ }
28
+ export function isAtRevision(document, revisions) {
29
+ return (!revisions ||
30
+ Object.entries(revisions).find(([scope, revision]) => {
31
+ const operation = document.operations[scope].at(-1);
32
+ if (revision === -1) {
33
+ return operation !== undefined;
34
+ }
35
+ return operation?.index !== revision;
36
+ }) === undefined);
37
+ }
38
+ export function isAfterRevision(document, revisions) {
39
+ return (!revisions ||
40
+ Object.entries(revisions).every(([scope, revision]) => {
41
+ const operation = document.operations[scope].at(-1);
42
+ if (revision === -1) {
43
+ return operation !== undefined;
44
+ }
45
+ return operation && operation.index > revision;
46
+ }));
47
+ }
@@ -0,0 +1,36 @@
1
+ import { DocumentDriveAction, DocumentDriveDocument } from "#drive-document-model/gen/types";
2
+ import { SynchronizationUnitQuery } from "#server/types";
3
+ import type { DocumentHeader, Operation, OperationFromDocument, PHDocument } from "document-model";
4
+ import { IDriveStorage, IStorage, IStorageDelegate } from "./types.js";
5
+ declare abstract class BaseStorage implements IStorage {
6
+ abstract checkDocumentExists(drive: string, id: string): Promise<boolean>;
7
+ abstract getDocuments(drive: string): Promise<string[]>;
8
+ abstract getDocument<TDocument extends PHDocument>(drive: string, id: string): Promise<TDocument>;
9
+ abstract createDocument(drive: string, id: string, document: PHDocument): Promise<void>;
10
+ abstract addDocumentOperations(drive: string, id: string, operations: Operation[], header: DocumentHeader): Promise<void>;
11
+ abstract addDocumentOperationsWithTransaction<TDocument extends PHDocument>(drive: string, id: string, callback: (document: TDocument) => Promise<{
12
+ operations: OperationFromDocument<TDocument>[];
13
+ header: DocumentHeader;
14
+ }>): Promise<void>;
15
+ abstract deleteDocument(drive: string, id: string): Promise<void>;
16
+ abstract getOperationResultingState<TGlobalState, TLocalState>(drive: string, id: string, index: number, scope: string, branch: string): Promise<TGlobalState | TLocalState | undefined>;
17
+ abstract setStorageDelegate?(delegate: IStorageDelegate): void;
18
+ abstract getSynchronizationUnitsRevision(units: SynchronizationUnitQuery[]): Promise<{
19
+ driveId: string;
20
+ documentId: string;
21
+ scope: string;
22
+ branch: string;
23
+ lastUpdated: string;
24
+ revision: number;
25
+ }[]>;
26
+ }
27
+ export declare abstract class BaseDriveStorage extends BaseStorage implements IDriveStorage {
28
+ abstract getDrives(): Promise<string[]>;
29
+ abstract getDrive(id: string): Promise<DocumentDriveDocument>;
30
+ abstract getDriveBySlug(slug: string): Promise<DocumentDriveDocument>;
31
+ abstract createDrive(id: string, drive: DocumentDriveDocument): Promise<void>;
32
+ abstract deleteDrive(id: string): Promise<void>;
33
+ abstract addDriveOperations(id: string, operations: Operation<DocumentDriveAction>[], header: DocumentHeader): Promise<void>;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/storage/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ class BaseStorage {
2
+ }
3
+ export class BaseDriveStorage extends BaseStorage {
4
+ }
@@ -0,0 +1,36 @@
1
+ import { DocumentDriveAction, DocumentDriveDocument } from "#drive-document-model/gen/types";
2
+ import { SynchronizationUnitQuery } from "#server/types";
3
+ import type { DocumentHeader, Operation, PHDocument } from "document-model";
4
+ import { IDriveStorage } from "./types.js";
5
+ export declare class BrowserStorage implements IDriveStorage {
6
+ private db;
7
+ static DBName: string;
8
+ static SEP: string;
9
+ static DRIVES_KEY: string;
10
+ constructor(namespace?: string);
11
+ buildKey(...args: string[]): string;
12
+ checkDocumentExists(drive: string, id: string): Promise<boolean>;
13
+ getDocuments(drive: string): Promise<string[]>;
14
+ getDocument<TDocument extends PHDocument>(driveId: string, id: string): Promise<TDocument>;
15
+ createDocument(drive: string, id: string, document: PHDocument): Promise<void>;
16
+ deleteDocument(drive: string, id: string): Promise<void>;
17
+ clearStorage(): Promise<void>;
18
+ addDocumentOperations(drive: string, id: string, operations: Operation[], header: DocumentHeader): Promise<void>;
19
+ getDrives(): Promise<string[]>;
20
+ getDrive(id: string): Promise<DocumentDriveDocument>;
21
+ getDriveBySlug(slug: string): Promise<DocumentDriveDocument>;
22
+ createDrive(id: string, drive: DocumentDriveDocument): Promise<void>;
23
+ deleteDrive(id: string): Promise<void>;
24
+ addDriveOperations(id: string, operations: Operation<DocumentDriveAction>[], header: DocumentHeader): Promise<void>;
25
+ getSynchronizationUnitsRevision(units: SynchronizationUnitQuery[]): Promise<{
26
+ driveId: string;
27
+ documentId: string;
28
+ scope: string;
29
+ branch: string;
30
+ lastUpdated: string;
31
+ revision: number;
32
+ }[]>;
33
+ migrateOperationSignatures(): Promise<void>;
34
+ private migrateDocument;
35
+ }
36
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../src/storage/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAGzD,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EAET,UAAU,EACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,cAAe,YAAW,aAAa;IAClD,OAAO,CAAC,EAAE,CAAuB;IAEjC,MAAM,CAAC,MAAM,SAAqB;IAClC,MAAM,CAAC,GAAG,SAAO;IACjB,MAAM,CAAC,UAAU,SAAY;gBAEjB,SAAS,CAAC,EAAE,MAAM;IAU9B,QAAQ,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE;IAIpB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOhE,YAAY,CAAC,KAAK,EAAE,MAAM;IAS1B,WAAW,CAAC,SAAS,SAAS,UAAU,EAC5C,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,SAAS,CAAC;IAUf,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU;IAI9D,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAIxC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,qBAAqB,CACzB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAgBV,SAAS;IAUT,QAAQ,CAAC,EAAE,EAAE,MAAM;IAWnB,cAAc,CAAC,IAAI,EAAE,MAAM;IAa3B,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB;IAKpD,WAAW,CAAC,EAAE,EAAE,MAAM;IAQtB,kBAAkB,CACtB,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,SAAS,CAAC,mBAAmB,CAAC,EAAE,EAC5C,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAaV,+BAA+B,CACnC,KAAK,EAAE,wBAAwB,EAAE,GAChC,OAAO,CACR;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,EAAE,CACJ;IA6CK,0BAA0B;YAYlB,eAAe;CAU9B"}
@@ -0,0 +1,155 @@
1
+ import { DriveNotFoundError } from "#server/error";
2
+ import { migrateDocumentOperationSignatures } from "#utils/migrations";
3
+ import { mergeOperations } from "#utils/misc";
4
+ import LocalForage from "localforage";
5
+ export class BrowserStorage {
6
+ db;
7
+ static DBName = "DOCUMENT_DRIVES";
8
+ static SEP = ":";
9
+ static DRIVES_KEY = "DRIVES";
10
+ constructor(namespace) {
11
+ this.db = LocalForage.ready().then(() => LocalForage.createInstance({
12
+ name: namespace
13
+ ? `${namespace}:${BrowserStorage.DBName}`
14
+ : BrowserStorage.DBName,
15
+ }));
16
+ }
17
+ buildKey(...args) {
18
+ return args.join(BrowserStorage.SEP);
19
+ }
20
+ async checkDocumentExists(drive, id) {
21
+ const document = await (await this.db).getItem(this.buildKey(drive, id));
22
+ return !!document;
23
+ }
24
+ async getDocuments(drive) {
25
+ const db = await this.db;
26
+ const keys = await db.keys();
27
+ const driveKey = `${drive}${BrowserStorage.SEP}`;
28
+ return keys
29
+ .filter((key) => key.startsWith(driveKey))
30
+ .map((key) => key.slice(driveKey.length));
31
+ }
32
+ async getDocument(driveId, id) {
33
+ const document = await (await this.db).getItem(this.buildKey(driveId, id));
34
+ if (!document) {
35
+ throw new Error(`Document with id ${id} not found`);
36
+ }
37
+ return document;
38
+ }
39
+ async createDocument(drive, id, document) {
40
+ await (await this.db).setItem(this.buildKey(drive, id), document);
41
+ }
42
+ async deleteDocument(drive, id) {
43
+ await (await this.db).removeItem(this.buildKey(drive, id));
44
+ }
45
+ async clearStorage() {
46
+ return (await this.db).clear();
47
+ }
48
+ async addDocumentOperations(drive, id, operations, header) {
49
+ const document = await this.getDocument(drive, id);
50
+ if (!document) {
51
+ throw new Error(`Document with id ${id} not found`);
52
+ }
53
+ const mergedOperations = mergeOperations(document.operations, operations);
54
+ const db = await this.db;
55
+ await db.setItem(this.buildKey(drive, id), {
56
+ ...document,
57
+ ...header,
58
+ operations: mergedOperations,
59
+ });
60
+ }
61
+ async getDrives() {
62
+ const db = await this.db;
63
+ const keys = await db.keys();
64
+ return keys
65
+ .filter((key) => key.startsWith(BrowserStorage.DRIVES_KEY))
66
+ .map((key) => key.slice(BrowserStorage.DRIVES_KEY.length + BrowserStorage.SEP.length));
67
+ }
68
+ async getDrive(id) {
69
+ const db = await this.db;
70
+ const drive = await db.getItem(this.buildKey(BrowserStorage.DRIVES_KEY, id));
71
+ if (!drive) {
72
+ throw new DriveNotFoundError(id);
73
+ }
74
+ return drive;
75
+ }
76
+ async getDriveBySlug(slug) {
77
+ // get oldes drives first
78
+ const drives = (await this.getDrives()).reverse();
79
+ for (const drive of drives) {
80
+ const driveData = await this.getDrive(drive);
81
+ if (driveData.initialState.state.global.slug === slug) {
82
+ return this.getDrive(drive);
83
+ }
84
+ }
85
+ throw new Error(`Drive with slug ${slug} not found`);
86
+ }
87
+ async createDrive(id, drive) {
88
+ const db = await this.db;
89
+ await db.setItem(this.buildKey(BrowserStorage.DRIVES_KEY, id), drive);
90
+ }
91
+ async deleteDrive(id) {
92
+ const documents = await this.getDocuments(id);
93
+ await Promise.all(documents.map((doc) => this.deleteDocument(id, doc)));
94
+ return (await this.db).removeItem(this.buildKey(BrowserStorage.DRIVES_KEY, id));
95
+ }
96
+ async addDriveOperations(id, operations, header) {
97
+ const drive = await this.getDrive(id);
98
+ const mergedOperations = mergeOperations(drive.operations, operations);
99
+ const db = await this.db;
100
+ await db.setItem(this.buildKey(BrowserStorage.DRIVES_KEY, id), {
101
+ ...drive,
102
+ ...header,
103
+ operations: mergedOperations,
104
+ });
105
+ return;
106
+ }
107
+ async getSynchronizationUnitsRevision(units) {
108
+ const results = await Promise.allSettled(units.map(async (unit) => {
109
+ try {
110
+ const document = await (unit.documentId
111
+ ? this.getDocument(unit.driveId, unit.documentId)
112
+ : this.getDrive(unit.driveId));
113
+ if (!document) {
114
+ return undefined;
115
+ }
116
+ const operation = document.operations[unit.scope].at(-1);
117
+ if (operation) {
118
+ return {
119
+ driveId: unit.driveId,
120
+ documentId: unit.documentId,
121
+ scope: unit.scope,
122
+ branch: unit.branch,
123
+ lastUpdated: operation.timestamp,
124
+ revision: operation.index,
125
+ };
126
+ }
127
+ }
128
+ catch {
129
+ return undefined;
130
+ }
131
+ }));
132
+ return results.reduce((acc, curr) => {
133
+ if (curr.status === "fulfilled" && curr.value !== undefined) {
134
+ acc.push(curr.value);
135
+ }
136
+ return acc;
137
+ }, []);
138
+ }
139
+ // migrates all stored operations from legacy signature to signatures array
140
+ async migrateOperationSignatures() {
141
+ const drives = await this.getDrives();
142
+ for (const drive of drives) {
143
+ await this.migrateDocument(BrowserStorage.DRIVES_KEY, drive);
144
+ const documents = await this.getDocuments(drive);
145
+ await Promise.all(documents.map(async (docId) => this.migrateDocument(drive, docId)));
146
+ }
147
+ }
148
+ async migrateDocument(drive, id) {
149
+ const document = await this.getDocument(drive, id);
150
+ const migratedDocument = migrateDocumentOperationSignatures(document);
151
+ if (migratedDocument !== document) {
152
+ return (await this.db).setItem(this.buildKey(drive, id), migratedDocument);
153
+ }
154
+ }
155
+ }
@@ -0,0 +1,33 @@
1
+ import { DocumentDriveAction, DocumentDriveDocument } from "#drive-document-model/gen/types";
2
+ import { SynchronizationUnitQuery } from "#server/types";
3
+ import { DocumentHeader, Operation, PHDocument } from "document-model";
4
+ import { IDriveStorage } from "./types.js";
5
+ export declare class FilesystemStorage implements IDriveStorage {
6
+ private basePath;
7
+ private drivesPath;
8
+ private static DRIVES_DIR;
9
+ constructor(basePath: string);
10
+ private _buildDocumentPath;
11
+ getDocuments(drive: string): Promise<string[]>;
12
+ checkDocumentExists(drive: string, id: string): Promise<boolean>;
13
+ getDocument<TDocument extends PHDocument>(drive: string, id: string): Promise<TDocument>;
14
+ createDocument(drive: string, id: string, document: PHDocument): Promise<void>;
15
+ clearStorage(): Promise<void>;
16
+ deleteDocument(drive: string, id: string): Promise<void>;
17
+ addDocumentOperations(drive: string, id: string, operations: Operation[], header: DocumentHeader): Promise<void>;
18
+ getDrives(): Promise<string[]>;
19
+ getDrive(id: string): Promise<DocumentDriveDocument>;
20
+ getDriveBySlug(slug: string): Promise<DocumentDriveDocument>;
21
+ createDrive(id: string, drive: DocumentDriveDocument): Promise<void>;
22
+ deleteDrive(id: string): Promise<void>;
23
+ addDriveOperations(id: string, operations: Operation<DocumentDriveAction>[], header: DocumentHeader): Promise<void>;
24
+ getSynchronizationUnitsRevision(units: SynchronizationUnitQuery[]): Promise<{
25
+ driveId: string;
26
+ documentId: string;
27
+ scope: string;
28
+ branch: string;
29
+ lastUpdated: string;
30
+ revision: number;
31
+ }[]>;
32
+ }
33
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../../src/storage/filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EACL,cAAc,EACd,SAAS,EAET,UAAU,EACX,MAAM,gBAAgB,CAAC;AAaxB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAe3C,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAY;gBAEzB,QAAQ,EAAE,MAAM;IAO5B,OAAO,CAAC,kBAAkB;IAOpB,YAAY,CAAC,KAAK,EAAE,MAAM;IA2BhC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK1D,WAAW,CAAC,SAAS,SAAS,UAAU,EAC5C,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,SAAS,CAAC;IAWf,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU;IAS9D,YAAY;IAmCZ,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAIxC,qBAAqB,CACzB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE,cAAc;IAgBlB,SAAS;IAmBT,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAQpD,cAAc,CAAC,IAAI,EAAE,MAAM;IAkBjC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB;IAI9C,WAAW,CAAC,EAAE,EAAE,MAAM;IAQtB,kBAAkB,CACtB,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,SAAS,CAAC,mBAAmB,CAAC,EAAE,EAC5C,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAcV,+BAA+B,CACnC,KAAK,EAAE,wBAAwB,EAAE,GAChC,OAAO,CACR;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,EAAE,CACJ;CA2CF"}
@@ -0,0 +1,197 @@
1
+ import { DriveNotFoundError } from "#server/error";
2
+ import { mergeOperations } from "#utils/misc";
3
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "fs";
4
+ import fs from "fs/promises";
5
+ import stringify from "json-stringify-deterministic";
6
+ import path from "path";
7
+ import sanitize from "sanitize-filename";
8
+ function ensureDir(dir) {
9
+ if (!existsSync(dir)) {
10
+ mkdirSync(dir, { recursive: true });
11
+ }
12
+ }
13
+ export class FilesystemStorage {
14
+ basePath;
15
+ drivesPath;
16
+ static DRIVES_DIR = "drives";
17
+ constructor(basePath) {
18
+ this.basePath = basePath;
19
+ ensureDir(this.basePath);
20
+ this.drivesPath = path.join(this.basePath, FilesystemStorage.DRIVES_DIR);
21
+ ensureDir(this.drivesPath);
22
+ }
23
+ _buildDocumentPath(...args) {
24
+ return `${path.join(this.basePath, ...args.map((arg) => sanitize(arg)))}.json`;
25
+ }
26
+ async getDocuments(drive) {
27
+ let files = [];
28
+ try {
29
+ files = readdirSync(path.join(this.basePath, drive), {
30
+ withFileTypes: true,
31
+ });
32
+ }
33
+ catch (error) {
34
+ // if folder is not found then drive has no documents
35
+ if (error.code !== "ENOENT") {
36
+ throw error;
37
+ }
38
+ }
39
+ const documents = [];
40
+ for (const file of files.filter((file) => file.isFile())) {
41
+ try {
42
+ const documentId = path.parse(file.name).name;
43
+ // checks if file is document
44
+ await this.getDocument(drive, documentId);
45
+ documents.push(documentId);
46
+ }
47
+ catch {
48
+ /* Ignore invalid document*/
49
+ }
50
+ }
51
+ return documents;
52
+ }
53
+ checkDocumentExists(drive, id) {
54
+ const documentExists = existsSync(this._buildDocumentPath(drive, id));
55
+ return Promise.resolve(documentExists);
56
+ }
57
+ async getDocument(drive, id) {
58
+ try {
59
+ const content = readFileSync(this._buildDocumentPath(drive, id), {
60
+ encoding: "utf-8",
61
+ });
62
+ return JSON.parse(content);
63
+ }
64
+ catch (error) {
65
+ throw new Error(`Document with id ${id} not found`);
66
+ }
67
+ }
68
+ async createDocument(drive, id, document) {
69
+ const documentPath = this._buildDocumentPath(drive, id);
70
+ ensureDir(path.dirname(documentPath));
71
+ writeFileSync(documentPath, stringify(document), {
72
+ encoding: "utf-8",
73
+ });
74
+ return Promise.resolve();
75
+ }
76
+ async clearStorage() {
77
+ const drivesPath = path.join(this.basePath, FilesystemStorage.DRIVES_DIR);
78
+ // delete content of drives directory
79
+ const drives = (await fs.readdir(drivesPath, {
80
+ withFileTypes: true,
81
+ recursive: true,
82
+ })).filter((dirent) => !!dirent.name);
83
+ await Promise.all(drives.map(async (dirent) => {
84
+ await fs.rm(path.join(drivesPath, dirent.name), {
85
+ recursive: true,
86
+ });
87
+ }));
88
+ // delete files in basePath
89
+ const files = (await fs.readdir(this.basePath, { withFileTypes: true })).filter((file) => file.name !== FilesystemStorage.DRIVES_DIR && !!file.name);
90
+ await Promise.all(files.map(async (dirent) => {
91
+ await fs.rm(path.join(this.basePath, dirent.name), {
92
+ recursive: true,
93
+ });
94
+ }));
95
+ }
96
+ async deleteDocument(drive, id) {
97
+ return fs.rm(this._buildDocumentPath(drive, id));
98
+ }
99
+ async addDocumentOperations(drive, id, operations, header) {
100
+ const document = await this.getDocument(drive, id);
101
+ if (!document) {
102
+ throw new Error(`Document with id ${id} not found`);
103
+ }
104
+ const mergedOperations = mergeOperations(document.operations, operations);
105
+ await this.createDocument(drive, id, {
106
+ ...document,
107
+ ...header,
108
+ operations: mergedOperations,
109
+ });
110
+ }
111
+ async getDrives() {
112
+ const files = readdirSync(this.drivesPath, {
113
+ withFileTypes: true,
114
+ });
115
+ const drives = [];
116
+ for (const file of files.filter((file) => file.isFile())) {
117
+ try {
118
+ const driveId = path.parse(file.name).name;
119
+ // checks if file is drive
120
+ await this.getDrive(driveId);
121
+ drives.push(driveId);
122
+ }
123
+ catch {
124
+ /* Ignore invalid drive document found on drives dir */
125
+ }
126
+ }
127
+ return drives;
128
+ }
129
+ async getDrive(id) {
130
+ try {
131
+ return await this.getDocument(FilesystemStorage.DRIVES_DIR, id);
132
+ }
133
+ catch {
134
+ throw new DriveNotFoundError(id);
135
+ }
136
+ }
137
+ async getDriveBySlug(slug) {
138
+ // get oldes drives first
139
+ const drives = (await this.getDrives()).reverse();
140
+ for (const drive of drives) {
141
+ const { initialState: { state: { global: { slug: driveSlug }, }, }, } = await this.getDrive(drive);
142
+ if (driveSlug === slug) {
143
+ return this.getDrive(drive);
144
+ }
145
+ }
146
+ throw new Error(`Drive with slug ${slug} not found`);
147
+ }
148
+ createDrive(id, drive) {
149
+ return this.createDocument(FilesystemStorage.DRIVES_DIR, id, drive);
150
+ }
151
+ async deleteDrive(id) {
152
+ const documents = await this.getDocuments(id);
153
+ await this.deleteDocument(FilesystemStorage.DRIVES_DIR, id);
154
+ await Promise.all(documents.map((document) => this.deleteDocument(id, document)));
155
+ }
156
+ async addDriveOperations(id, operations, header) {
157
+ const drive = await this.getDrive(id);
158
+ const mergedOperations = mergeOperations(drive.operations, operations);
159
+ await this.createDrive(id, {
160
+ ...drive,
161
+ ...header,
162
+ operations: mergedOperations,
163
+ });
164
+ }
165
+ async getSynchronizationUnitsRevision(units) {
166
+ const results = await Promise.allSettled(units.map(async (unit) => {
167
+ try {
168
+ const document = await (unit.documentId
169
+ ? this.getDocument(unit.driveId, unit.documentId)
170
+ : this.getDrive(unit.driveId));
171
+ if (!document) {
172
+ return undefined;
173
+ }
174
+ const operation = document.operations[unit.scope].at(-1);
175
+ if (operation) {
176
+ return {
177
+ driveId: unit.driveId,
178
+ documentId: unit.documentId,
179
+ scope: unit.scope,
180
+ branch: unit.branch,
181
+ lastUpdated: operation.timestamp,
182
+ revision: operation.index,
183
+ };
184
+ }
185
+ }
186
+ catch {
187
+ return undefined;
188
+ }
189
+ }));
190
+ return results.reduce((acc, curr) => {
191
+ if (curr.status === "fulfilled" && curr.value !== undefined) {
192
+ acc.push(curr.value);
193
+ }
194
+ return acc;
195
+ }, []);
196
+ }
197
+ }
@@ -0,0 +1,33 @@
1
+ import { DocumentDriveDocument } from "#drive-document-model/gen/types";
2
+ import { SynchronizationUnitQuery } from "#server/types";
3
+ import { DocumentHeader, Operation, OperationFromDocument, PHDocument } from "document-model";
4
+ import { IDriveStorage } from "./types.js";
5
+ export declare class MemoryStorage implements IDriveStorage {
6
+ private documents;
7
+ private drives;
8
+ private slugToDriveId;
9
+ constructor();
10
+ checkDocumentExists(drive: string, id: string): Promise<boolean>;
11
+ getDocuments(drive: string): Promise<string[]>;
12
+ getDocument<TDocument extends PHDocument>(driveId: string, id: string): Promise<TDocument>;
13
+ saveDocument(drive: string, id: string, document: PHDocument): Promise<void>;
14
+ clearStorage(): Promise<void>;
15
+ createDocument(drive: string, id: string, document: PHDocument): Promise<void>;
16
+ addDocumentOperations(drive: string, id: string, operations: Operation[], header: DocumentHeader): Promise<void>;
17
+ deleteDocument(drive: string, id: string): Promise<void>;
18
+ getDrives(): Promise<string[]>;
19
+ getDrive(id: string): Promise<DocumentDriveDocument>;
20
+ getDriveBySlug(slug: string): Promise<DocumentDriveDocument>;
21
+ createDrive(id: string, drive: DocumentDriveDocument): Promise<void>;
22
+ addDriveOperations(id: string, operations: OperationFromDocument<DocumentDriveDocument>[], header: DocumentHeader): Promise<void>;
23
+ deleteDrive(id: string): Promise<void>;
24
+ getSynchronizationUnitsRevision(units: SynchronizationUnitQuery[]): Promise<{
25
+ driveId: string;
26
+ documentId: string;
27
+ scope: string;
28
+ branch: string;
29
+ lastUpdated: string;
30
+ revision: number;
31
+ }[]>;
32
+ }
33
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/storage/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EACL,cAAc,EACd,SAAS,EACT,qBAAqB,EAErB,UAAU,EACX,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,aAAc,YAAW,aAAa;IACjD,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,aAAa,CAA8B;;IAOnD,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI1D,YAAY,CAAC,KAAK,EAAE,MAAM;IAI1B,WAAW,CAAC,SAAS,SAAS,UAAU,EAC5C,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,SAAS,CAAC;IAaf,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU;IAK5D,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU;IA0B9D,qBAAqB,CACzB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,SAAS,EAAE,EACvB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAeV,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAOxC,SAAS;IAIT,QAAQ,CAAC,EAAE,EAAE,MAAM;IAQnB,cAAc,CAAC,IAAI,EAAE,MAAM;IAQ3B,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB;IASpD,kBAAkB,CACtB,EAAE,EAAE,MAAM,EACV,UAAU,EAAE,qBAAqB,CAAC,qBAAqB,CAAC,EAAE,EAC1D,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAcV,WAAW,CAAC,EAAE,EAAE,MAAM;IAKtB,+BAA+B,CACnC,KAAK,EAAE,wBAAwB,EAAE,GAChC,OAAO,CACR;QACE,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,EAAE,CACJ;CA2CF"}