@twin.org/synchronised-storage-service 0.0.1-next.9 → 0.0.3-next.2

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 (55) hide show
  1. package/dist/es/data/verifiableStorageKeys.json +5 -0
  2. package/dist/es/entities/syncSnapshotEntry.js +93 -0
  3. package/dist/es/entities/syncSnapshotEntry.js.map +1 -0
  4. package/dist/es/helpers/blobStorageHelper.js +185 -0
  5. package/dist/es/helpers/blobStorageHelper.js.map +1 -0
  6. package/dist/es/helpers/changeSetHelper.js +215 -0
  7. package/dist/es/helpers/changeSetHelper.js.map +1 -0
  8. package/dist/es/helpers/localSyncStateHelper.js +384 -0
  9. package/dist/es/helpers/localSyncStateHelper.js.map +1 -0
  10. package/dist/es/helpers/remoteSyncStateHelper.js +560 -0
  11. package/dist/es/helpers/remoteSyncStateHelper.js.map +1 -0
  12. package/dist/es/helpers/versions.js +6 -0
  13. package/dist/es/helpers/versions.js.map +1 -0
  14. package/dist/es/index.js +13 -0
  15. package/dist/es/index.js.map +1 -0
  16. package/dist/es/models/ISyncPointerStore.js +4 -0
  17. package/dist/es/models/ISyncPointerStore.js.map +1 -0
  18. package/dist/es/models/ISyncSnapshot.js +4 -0
  19. package/dist/es/models/ISyncSnapshot.js.map +1 -0
  20. package/dist/es/models/ISyncState.js +2 -0
  21. package/dist/es/models/ISyncState.js.map +1 -0
  22. package/dist/es/models/ISynchronisedStorageServiceConfig.js +4 -0
  23. package/dist/es/models/ISynchronisedStorageServiceConfig.js.map +1 -0
  24. package/dist/es/models/ISynchronisedStorageServiceConstructorOptions.js +2 -0
  25. package/dist/es/models/ISynchronisedStorageServiceConstructorOptions.js.map +1 -0
  26. package/dist/es/restEntryPoints.js +10 -0
  27. package/dist/es/restEntryPoints.js.map +1 -0
  28. package/dist/es/schema.js +11 -0
  29. package/dist/es/schema.js.map +1 -0
  30. package/dist/es/synchronisedStorageRoutes.js +142 -0
  31. package/dist/es/synchronisedStorageRoutes.js.map +1 -0
  32. package/dist/es/synchronisedStorageService.js +512 -0
  33. package/dist/es/synchronisedStorageService.js.map +1 -0
  34. package/dist/types/entities/syncSnapshotEntry.d.ts +3 -3
  35. package/dist/types/helpers/blobStorageHelper.d.ts +3 -3
  36. package/dist/types/helpers/changeSetHelper.d.ts +16 -32
  37. package/dist/types/helpers/localSyncStateHelper.d.ts +11 -11
  38. package/dist/types/helpers/remoteSyncStateHelper.d.ts +18 -14
  39. package/dist/types/index.d.ts +10 -10
  40. package/dist/types/models/ISyncState.d.ts +1 -1
  41. package/dist/types/models/ISynchronisedStorageServiceConfig.d.ts +7 -8
  42. package/dist/types/models/ISynchronisedStorageServiceConstructorOptions.d.ts +6 -6
  43. package/dist/types/synchronisedStorageRoutes.d.ts +1 -1
  44. package/dist/types/synchronisedStorageService.d.ts +17 -21
  45. package/docs/architecture.md +168 -12
  46. package/docs/changelog.md +149 -0
  47. package/docs/open-api/spec.json +62 -57
  48. package/docs/reference/classes/SyncSnapshotEntry.md +4 -10
  49. package/docs/reference/classes/SynchronisedStorageService.md +38 -50
  50. package/docs/reference/interfaces/ISynchronisedStorageServiceConfig.md +11 -17
  51. package/docs/reference/interfaces/ISynchronisedStorageServiceConstructorOptions.md +8 -8
  52. package/locales/en.json +7 -15
  53. package/package.json +26 -9
  54. package/dist/cjs/index.cjs +0 -2235
  55. package/dist/esm/index.mjs +0 -2227
@@ -0,0 +1,13 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export * from "./entities/syncSnapshotEntry.js";
4
+ export * from "./models/ISynchronisedStorageServiceConfig.js";
5
+ export * from "./models/ISynchronisedStorageServiceConstructorOptions.js";
6
+ export * from "./models/ISyncPointerStore.js";
7
+ export * from "./models/ISyncSnapshot.js";
8
+ export * from "./models/ISyncState.js";
9
+ export * from "./restEntryPoints.js";
10
+ export * from "./schema.js";
11
+ export * from "./synchronisedStorageRoutes.js";
12
+ export * from "./synchronisedStorageService.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,2DAA2D,CAAC;AAC1E,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/syncSnapshotEntry.js\";\nexport * from \"./models/ISynchronisedStorageServiceConfig.js\";\nexport * from \"./models/ISynchronisedStorageServiceConstructorOptions.js\";\nexport * from \"./models/ISyncPointerStore.js\";\nexport * from \"./models/ISyncSnapshot.js\";\nexport * from \"./models/ISyncState.js\";\nexport * from \"./restEntryPoints.js\";\nexport * from \"./schema.js\";\nexport * from \"./synchronisedStorageRoutes.js\";\nexport * from \"./synchronisedStorageService.js\";\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ISyncPointerStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISyncPointerStore.js","sourceRoot":"","sources":["../../../src/models/ISyncPointerStore.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The object definition for the sync pointer store.\n */\nexport interface ISyncPointerStore {\n\t/**\n\t * The version of the sync pointer store.\n\t */\n\tversion: string;\n\n\t/**\n\t * The mapping from storage keys to sync pointers.\n\t */\n\tsyncPointers: { [key: string]: string };\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ISyncSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISyncSnapshot.js","sourceRoot":"","sources":["../../../src/models/ISyncSnapshot.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The object definition for a sync snapshot.\n */\nexport interface ISyncSnapshot {\n\t/**\n\t * The version of the sync state.\n\t */\n\tversion: string;\n\n\t/**\n\t * The id of the snapshot.\n\t */\n\tid: string;\n\n\t/**\n\t * The date the snapshot was created.\n\t */\n\tdateCreated: string;\n\n\t/**\n\t * The date the snapshot was last modified.\n\t */\n\tdateModified: string;\n\n\t/**\n\t * Is this a consolidated snapshot?\n\t */\n\tisConsolidated: boolean;\n\n\t/**\n\t * The epoch of the snapshot.\n\t */\n\tepoch: number;\n\n\t/**\n\t * The ids of the storage for the change sets in the snapshot.\n\t */\n\tchangeSetStorageIds: string[];\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ISyncState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISyncState.js","sourceRoot":"","sources":["../../../src/models/ISyncState.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ISyncSnapshot } from \"./ISyncSnapshot.js\";\n\n/**\n * The object definition for a sync state.\n */\nexport interface ISyncState {\n\t/**\n\t * The version of the sync state.\n\t */\n\tversion: string;\n\n\t/**\n\t * The storage type contained in the sync state.\n\t */\n\tstorageKey: string;\n\n\t/**\n\t * The snapshots.\n\t */\n\tsnapshots: ISyncSnapshot[];\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ISynchronisedStorageServiceConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISynchronisedStorageServiceConfig.js","sourceRoot":"","sources":["../../../src/models/ISynchronisedStorageServiceConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the Synchronised Storage Service.\n */\nexport interface ISynchronisedStorageServiceConfig {\n\t/**\n\t * How often to check for entity updates in minutes.\n\t * @default 5\n\t */\n\tentityUpdateIntervalMinutes?: number;\n\n\t/**\n\t * Interval to perform consolidation of changesets, only used if this is a trusted node.\n\t * @default 60\n\t */\n\tconsolidationIntervalMinutes?: number;\n\n\t/**\n\t * The number of entities to process in a single consolidation batch, only used if this is a trusted node.\n\t * @default 1000\n\t */\n\tconsolidationBatchSize?: number;\n\n\t/**\n\t * The maximum number of consolidations to keep in storage, only used if this is a trusted node.\n\t * @default 5\n\t */\n\tmaxConsolidations?: number;\n\n\t/**\n\t * The encryption key id from the vault to use for blob storage, only required for trusted nodes, untrusted nodes will request the key.\n\t * @default synchronised-storage-blob-encryption-key\n\t */\n\tblobStorageEncryptionKeyId?: string;\n\n\t/**\n\t * The verifiable storage key to use, already expected to be created.\n\t * if the key is not found in the keys.json it is considered to be a custom verifiable storage id.\n\t * @default local\n\t */\n\tverifiableStorageKeyId: \"mainnet\" | \"testnet\" | \"devnet\" | string;\n\n\t/**\n\t * Override the default trust generator.\n\t */\n\toverrideTrustGeneratorType?: string;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ISynchronisedStorageServiceConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISynchronisedStorageServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ISynchronisedStorageServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ISynchronisedStorageServiceConfig } from \"./ISynchronisedStorageServiceConfig.js\";\n\n/**\n * Options for the Synchronised Storage Service constructor.\n */\nexport interface ISynchronisedStorageServiceConstructorOptions {\n\t/**\n\t * The logging component.\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The event bus component type.\n\t */\n\teventBusComponentType?: string;\n\n\t/**\n\t * The vault connector type.\n\t */\n\tvaultConnectorType?: string;\n\n\t/**\n\t * The entity storage connector type to use for sync snapshots.\n\t * @default sync-snapshot-entry\n\t */\n\tsyncSnapshotStorageConnectorType?: string;\n\n\t/**\n\t * The blob storage connector used for remote sync state.\n\t * @default blob-storage\n\t */\n\tblobStorageConnectorType?: string;\n\n\t/**\n\t * The verifiable storage connector type to use for decentralised state.\n\t * @default verifiable-storage\n\t */\n\tverifiableStorageConnectorType?: string;\n\n\t/**\n\t * The task scheduler component.\n\t * @default task-scheduler\n\t */\n\ttaskSchedulerComponentType?: string;\n\n\t/**\n\t * The type of the trust component.\n\t * @default trust\n\t */\n\ttrustComponentType?: string;\n\n\t/**\n\t * The synchronised entity storage component type to use if this node is not trusted.\n\t * If this is set, this node uses it as the trusted node to store changesets.\n\t */\n\ttrustedSynchronisedStorageComponentType?: string;\n\n\t/**\n\t * The configuration for the connector.\n\t */\n\tconfig: ISynchronisedStorageServiceConfig;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import { generateRestRoutesSynchronisedStorage, tagsSynchronisedStorage } from "./synchronisedStorageRoutes.js";
2
+ export const restEntryPoints = [
3
+ {
4
+ name: "synchronised-storage",
5
+ defaultBaseRoute: "synchronised-storage",
6
+ tags: tagsSynchronisedStorage,
7
+ generateRoutes: generateRestRoutesSynchronisedStorage
8
+ }
9
+ ];
10
+ //# sourceMappingURL=restEntryPoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restEntryPoints.js","sourceRoot":"","sources":["../../src/restEntryPoints.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,qCAAqC,EACrC,uBAAuB,EACvB,MAAM,gCAAgC,CAAC;AAExC,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD;QACC,IAAI,EAAE,sBAAsB;QAC5B,gBAAgB,EAAE,sBAAsB;QACxC,IAAI,EAAE,uBAAuB;QAC7B,cAAc,EAAE,qCAAqC;KACrD;CACD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRestRouteEntryPoint } from \"@twin.org/api-models\";\nimport {\n\tgenerateRestRoutesSynchronisedStorage,\n\ttagsSynchronisedStorage\n} from \"./synchronisedStorageRoutes.js\";\n\nexport const restEntryPoints: IRestRouteEntryPoint[] = [\n\t{\n\t\tname: \"synchronised-storage\",\n\t\tdefaultBaseRoute: \"synchronised-storage\",\n\t\ttags: tagsSynchronisedStorage,\n\t\tgenerateRoutes: generateRestRoutesSynchronisedStorage\n\t}\n];\n"]}
@@ -0,0 +1,11 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { EntitySchemaFactory, EntitySchemaHelper } from "@twin.org/entity";
4
+ import { SyncSnapshotEntry } from "./entities/syncSnapshotEntry.js";
5
+ /**
6
+ * Initialize the schema for the synchronised service.
7
+ */
8
+ export function initSchema() {
9
+ EntitySchemaFactory.register("SyncSnapshotEntry", () => EntitySchemaHelper.getSchema(SyncSnapshotEntry));
10
+ }
11
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/schema.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE;;GAEG;AACH,MAAM,UAAU,UAAU;IACzB,mBAAmB,CAAC,QAAQ,sBAA8B,GAAG,EAAE,CAC9D,kBAAkB,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAC/C,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { EntitySchemaFactory, EntitySchemaHelper } from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { SyncSnapshotEntry } from \"./entities/syncSnapshotEntry.js\";\n\n/**\n * Initialize the schema for the synchronised service.\n */\nexport function initSchema(): void {\n\tEntitySchemaFactory.register(nameof<SyncSnapshotEntry>(), () =>\n\t\tEntitySchemaHelper.getSchema(SyncSnapshotEntry)\n\t);\n}\n"]}
@@ -0,0 +1,142 @@
1
+ import { ComponentFactory, Guards } from "@twin.org/core";
2
+ import { SynchronisedStorageContexts, SynchronisedStorageTypes } from "@twin.org/synchronised-storage-models";
3
+ import { HeaderHelper, HeaderTypes, HttpStatusCode } from "@twin.org/web";
4
+ /**
5
+ * The source used when communicating about these routes.
6
+ */
7
+ const ROUTES_SOURCE = "synchronisedStorageRoutes";
8
+ /**
9
+ * The tag to associate with the routes.
10
+ */
11
+ export const tagsSynchronisedStorage = [
12
+ {
13
+ name: "Synchronised Storage",
14
+ description: "Endpoints which are modelled to access a synchronised storage contract."
15
+ }
16
+ ];
17
+ /**
18
+ * The REST routes for synchronised storage.
19
+ * @param baseRouteName Prefix to prepend to the paths.
20
+ * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
21
+ * @returns The generated routes.
22
+ */
23
+ export function generateRestRoutesSynchronisedStorage(baseRouteName, componentName) {
24
+ const syncChangeSetRoute = {
25
+ operationId: "synchronisedStorageSyncChangeSetRequest",
26
+ summary: "Request that the node perform a sync request for a changeset.",
27
+ tag: tagsSynchronisedStorage[0].name,
28
+ method: "POST",
29
+ path: `${baseRouteName}/sync-changeset`,
30
+ handler: async (httpRequestContext, request) => synchronisedStorageSyncChangeSetRequest(httpRequestContext, componentName, request),
31
+ requestType: {
32
+ type: "ISyncChangeSetRequest",
33
+ examples: [
34
+ {
35
+ id: "synchronisedStorageSyncChangeSetRequestExample",
36
+ request: {
37
+ headers: {
38
+ [HeaderTypes.Authorization]: "z3V32BP9ShC...z3V32BP9ShC"
39
+ },
40
+ body: {
41
+ "@context": SynchronisedStorageContexts.ContextRoot,
42
+ type: SynchronisedStorageTypes.ChangeSet,
43
+ id: "0909090909090909090909090909090909090909090909090909090909090909",
44
+ dateCreated: "2025-05-29T01:00:00.000Z",
45
+ dateModified: "2025-05-29T01:00:00.000Z",
46
+ nodeId: "did:entity-storage:0xd2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2",
47
+ changes: [
48
+ {
49
+ entity: {
50
+ dateModified: "2025-01-01T00:00:00.000Z"
51
+ },
52
+ id: "test-id-1",
53
+ operation: "set"
54
+ }
55
+ ],
56
+ storageKey: "test-type"
57
+ }
58
+ }
59
+ }
60
+ ]
61
+ },
62
+ responseType: [
63
+ {
64
+ type: "INoContentResponse"
65
+ }
66
+ ],
67
+ skipAuth: true
68
+ };
69
+ const getDecryptionKeyRoute = {
70
+ operationId: "synchronisedStorageGetDecryptionKeyRequest",
71
+ summary: "Request the decryption key.",
72
+ tag: tagsSynchronisedStorage[0].name,
73
+ method: "POST",
74
+ path: `${baseRouteName}/decryption-key`,
75
+ handler: async (httpRequestContext, request) => synchronisedStorageGetDecryptionKeyRequest(httpRequestContext, componentName, request),
76
+ requestType: {
77
+ type: "ISyncChangeSetRequest",
78
+ examples: [
79
+ {
80
+ id: "synchronisedStorageSyncGetDecryptionKeyRequestExample",
81
+ request: {}
82
+ }
83
+ ]
84
+ },
85
+ responseType: [
86
+ {
87
+ type: "ISyncDecryptionKeyResponse",
88
+ examples: [
89
+ {
90
+ id: "synchronisedStorageSyncGetDecryptionKeyResponseExample",
91
+ response: {
92
+ body: {
93
+ decryptionKey: "z5efBErQs3YBLZoH7jgKMQaRc9YjAxA5XSYKmW3FmTBDw9WionT2NS2x1SMvcRyBvw53cSSoaCT1xQH9tkWngGCX3"
94
+ }
95
+ }
96
+ }
97
+ ]
98
+ },
99
+ {
100
+ type: "IUnauthorizedResponse"
101
+ }
102
+ ],
103
+ skipAuth: true
104
+ };
105
+ return [syncChangeSetRoute, getDecryptionKeyRoute];
106
+ }
107
+ /**
108
+ * Perform the sync change set operation.
109
+ * @param httpRequestContext The request context for the API.
110
+ * @param componentName The name of the component to use in the routes.
111
+ * @param request The request.
112
+ * @returns The response object with additional http response properties.
113
+ */
114
+ export async function synchronisedStorageSyncChangeSetRequest(httpRequestContext, componentName, request) {
115
+ Guards.object(ROUTES_SOURCE, "request.headers", request.headers);
116
+ Guards.object(ROUTES_SOURCE, "request", request);
117
+ Guards.object(ROUTES_SOURCE, "request.body", request.body);
118
+ const component = ComponentFactory.get(componentName);
119
+ await component.syncChangeSet(request.body, HeaderHelper.extractBearer(httpRequestContext.serverRequest.headers?.[HeaderTypes.Authorization]));
120
+ return {
121
+ statusCode: HttpStatusCode.noContent
122
+ };
123
+ }
124
+ /**
125
+ * Request the decryption key.
126
+ * @param httpRequestContext The request context for the API.
127
+ * @param componentName The name of the component to use in the routes.
128
+ * @param request The request.
129
+ * @returns The response object with additional http response properties.
130
+ */
131
+ export async function synchronisedStorageGetDecryptionKeyRequest(httpRequestContext, componentName, request) {
132
+ Guards.object(ROUTES_SOURCE, "request.headers", request.headers);
133
+ Guards.object(ROUTES_SOURCE, "request", request);
134
+ const component = ComponentFactory.get(componentName);
135
+ const key = await component.getDecryptionKey(HeaderHelper.extractBearer(httpRequestContext.serverRequest.headers?.[HeaderTypes.Authorization]));
136
+ return {
137
+ body: {
138
+ decryptionKey: key
139
+ }
140
+ };
141
+ }
142
+ //# sourceMappingURL=synchronisedStorageRoutes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synchronisedStorageRoutes.js","sourceRoot":"","sources":["../../src/synchronisedStorageRoutes.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EACN,2BAA2B,EAC3B,wBAAwB,EAKxB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE1E;;GAEG;AACH,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAW;IAC9C;QACC,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,yEAAyE;KACtF;CACD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,qCAAqC,CACpD,aAAqB,EACrB,aAAqB;IAErB,MAAM,kBAAkB,GAA0D;QACjF,WAAW,EAAE,yCAAyC;QACtD,OAAO,EAAE,+DAA+D;QACxE,GAAG,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC,IAAI;QACpC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG,aAAa,iBAAiB;QACvC,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAC9C,uCAAuC,CAAC,kBAAkB,EAAE,aAAa,EAAE,OAAO,CAAC;QACpF,WAAW,EAAE;YACZ,IAAI,yBAAiC;YACrC,QAAQ,EAAE;gBACT;oBACC,EAAE,EAAE,gDAAgD;oBACpD,OAAO,EAAE;wBACR,OAAO,EAAE;4BACR,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,2BAA2B;yBACxD;wBACD,IAAI,EAAE;4BACL,UAAU,EAAE,2BAA2B,CAAC,WAAW;4BACnD,IAAI,EAAE,wBAAwB,CAAC,SAAS;4BACxC,EAAE,EAAE,kEAAkE;4BACtE,WAAW,EAAE,0BAA0B;4BACvC,YAAY,EAAE,0BAA0B;4BACxC,MAAM,EACL,uFAAuF;4BACxF,OAAO,EAAE;gCACR;oCACC,MAAM,EAAE;wCACP,YAAY,EAAE,0BAA0B;qCACxC;oCACD,EAAE,EAAE,WAAW;oCACf,SAAS,EAAE,KAAK;iCAChB;6BACD;4BACD,UAAU,EAAE,WAAW;yBACvB;qBACD;iBACD;aACD;SACD;QACD,YAAY,EAAE;YACb;gBACC,IAAI,sBAA8B;aAClC;SACD;QACD,QAAQ,EAAE,IAAI;KACd,CAAC;IAEF,MAAM,qBAAqB,GAAsE;QAChG,WAAW,EAAE,4CAA4C;QACzD,OAAO,EAAE,6BAA6B;QACtC,GAAG,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC,IAAI;QACpC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG,aAAa,iBAAiB;QACvC,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,EAAE,CAC9C,0CAA0C,CAAC,kBAAkB,EAAE,aAAa,EAAE,OAAO,CAAC;QACvF,WAAW,EAAE;YACZ,IAAI,yBAAiC;YACrC,QAAQ,EAAE;gBACT;oBACC,EAAE,EAAE,uDAAuD;oBAC3D,OAAO,EAAE,EAAE;iBACX;aACD;SACD;QACD,YAAY,EAAE;YACb;gBACC,IAAI,8BAAsC;gBAC1C,QAAQ,EAAE;oBACT;wBACC,EAAE,EAAE,wDAAwD;wBAC5D,QAAQ,EAAE;4BACT,IAAI,EAAE;gCACL,aAAa,EACZ,2FAA2F;6BAC5F;yBACD;qBACD;iBACD;aACD;YACD;gBACC,IAAI,yBAAiC;aACrC;SACD;QACD,QAAQ,EAAE,IAAI;KACd,CAAC;IAEF,OAAO,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uCAAuC,CAC5D,kBAAuC,EACvC,aAAqB,EACrB,OAA8B;IAE9B,MAAM,CAAC,MAAM,CACZ,aAAa,qBAEb,OAAO,CAAC,OAAO,CACf,CAAC;IACF,MAAM,CAAC,MAAM,CAAwB,aAAa,aAAmB,OAAO,CAAC,CAAC;IAC9E,MAAM,CAAC,MAAM,CAAgC,aAAa,kBAAwB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhG,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAgC,aAAa,CAAC,CAAC;IACrF,MAAM,SAAS,CAAC,aAAa,CAC5B,OAAO,CAAC,IAAI,EACZ,YAAY,CAAC,aAAa,CACzB,kBAAkB,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,CACrE,CACD,CAAC;IACF,OAAO;QACN,UAAU,EAAE,cAAc,CAAC,SAAS;KACpC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0CAA0C,CAC/D,kBAAuC,EACvC,aAAqB,EACrB,OAAkC;IAElC,MAAM,CAAC,MAAM,CACZ,aAAa,qBAEb,OAAO,CAAC,OAAO,CACf,CAAC;IACF,MAAM,CAAC,MAAM,CAA4B,aAAa,aAAmB,OAAO,CAAC,CAAC;IAElF,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAgC,aAAa,CAAC,CAAC;IACrF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,gBAAgB,CAC3C,YAAY,CAAC,aAAa,CACzB,kBAAkB,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,CACrE,CACD,CAAC;IACF,OAAO;QACN,IAAI,EAAE;YACL,aAAa,EAAE,GAAG;SAClB;KACD,CAAC;AACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIHttpRequestContext,\n\tINoContentResponse,\n\tIRestRoute,\n\tITag,\n\tIUnauthorizedResponse\n} from \"@twin.org/api-models\";\nimport { ComponentFactory, Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\tSynchronisedStorageContexts,\n\tSynchronisedStorageTypes,\n\ttype ISyncChangeSetRequest,\n\ttype ISyncDecryptionKeyRequest,\n\ttype ISyncDecryptionKeyResponse,\n\ttype ISynchronisedStorageComponent\n} from \"@twin.org/synchronised-storage-models\";\nimport { HeaderHelper, HeaderTypes, HttpStatusCode } from \"@twin.org/web\";\n\n/**\n * The source used when communicating about these routes.\n */\nconst ROUTES_SOURCE = \"synchronisedStorageRoutes\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsSynchronisedStorage: ITag[] = [\n\t{\n\t\tname: \"Synchronised Storage\",\n\t\tdescription: \"Endpoints which are modelled to access a synchronised storage contract.\"\n\t}\n];\n\n/**\n * The REST routes for synchronised storage.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesSynchronisedStorage(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst syncChangeSetRoute: IRestRoute<ISyncChangeSetRequest, INoContentResponse> = {\n\t\toperationId: \"synchronisedStorageSyncChangeSetRequest\",\n\t\tsummary: \"Request that the node perform a sync request for a changeset.\",\n\t\ttag: tagsSynchronisedStorage[0].name,\n\t\tmethod: \"POST\",\n\t\tpath: `${baseRouteName}/sync-changeset`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tsynchronisedStorageSyncChangeSetRequest(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<ISyncChangeSetRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"synchronisedStorageSyncChangeSetRequestExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t[HeaderTypes.Authorization]: \"z3V32BP9ShC...z3V32BP9ShC\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\"@context\": SynchronisedStorageContexts.ContextRoot,\n\t\t\t\t\t\t\ttype: SynchronisedStorageTypes.ChangeSet,\n\t\t\t\t\t\t\tid: \"0909090909090909090909090909090909090909090909090909090909090909\",\n\t\t\t\t\t\t\tdateCreated: \"2025-05-29T01:00:00.000Z\",\n\t\t\t\t\t\t\tdateModified: \"2025-05-29T01:00:00.000Z\",\n\t\t\t\t\t\t\tnodeId:\n\t\t\t\t\t\t\t\t\"did:entity-storage:0xd2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2\",\n\t\t\t\t\t\t\tchanges: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tentity: {\n\t\t\t\t\t\t\t\t\t\tdateModified: \"2025-01-01T00:00:00.000Z\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tid: \"test-id-1\",\n\t\t\t\t\t\t\t\t\toperation: \"set\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tstorageKey: \"test-type\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<INoContentResponse>()\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\tconst getDecryptionKeyRoute: IRestRoute<ISyncDecryptionKeyRequest, ISyncDecryptionKeyResponse> = {\n\t\toperationId: \"synchronisedStorageGetDecryptionKeyRequest\",\n\t\tsummary: \"Request the decryption key.\",\n\t\ttag: tagsSynchronisedStorage[0].name,\n\t\tmethod: \"POST\",\n\t\tpath: `${baseRouteName}/decryption-key`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tsynchronisedStorageGetDecryptionKeyRequest(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<ISyncChangeSetRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"synchronisedStorageSyncGetDecryptionKeyRequestExample\",\n\t\t\t\t\trequest: {}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<ISyncDecryptionKeyResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"synchronisedStorageSyncGetDecryptionKeyResponseExample\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\tdecryptionKey:\n\t\t\t\t\t\t\t\t\t\"z5efBErQs3YBLZoH7jgKMQaRc9YjAxA5XSYKmW3FmTBDw9WionT2NS2x1SMvcRyBvw53cSSoaCT1xQH9tkWngGCX3\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: nameof<IUnauthorizedResponse>()\n\t\t\t}\n\t\t],\n\t\tskipAuth: true\n\t};\n\n\treturn [syncChangeSetRoute, getDecryptionKeyRoute];\n}\n\n/**\n * Perform the sync change set operation.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function synchronisedStorageSyncChangeSetRequest(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: ISyncChangeSetRequest\n): Promise<INoContentResponse> {\n\tGuards.object<ISyncChangeSetRequest[\"headers\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.headers),\n\t\trequest.headers\n\t);\n\tGuards.object<ISyncChangeSetRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object<ISyncChangeSetRequest[\"body\"]>(ROUTES_SOURCE, nameof(request.body), request.body);\n\n\tconst component = ComponentFactory.get<ISynchronisedStorageComponent>(componentName);\n\tawait component.syncChangeSet(\n\t\trequest.body,\n\t\tHeaderHelper.extractBearer(\n\t\t\thttpRequestContext.serverRequest.headers?.[HeaderTypes.Authorization]\n\t\t)\n\t);\n\treturn {\n\t\tstatusCode: HttpStatusCode.noContent\n\t};\n}\n\n/**\n * Request the decryption key.\n * @param httpRequestContext The request context for the API.\n * @param componentName The name of the component to use in the routes.\n * @param request The request.\n * @returns The response object with additional http response properties.\n */\nexport async function synchronisedStorageGetDecryptionKeyRequest(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: ISyncDecryptionKeyRequest\n): Promise<ISyncDecryptionKeyResponse> {\n\tGuards.object<ISyncChangeSetRequest[\"headers\"]>(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.headers),\n\t\trequest.headers\n\t);\n\tGuards.object<ISyncDecryptionKeyRequest>(ROUTES_SOURCE, nameof(request), request);\n\n\tconst component = ComponentFactory.get<ISynchronisedStorageComponent>(componentName);\n\tconst key = await component.getDecryptionKey(\n\t\tHeaderHelper.extractBearer(\n\t\t\thttpRequestContext.serverRequest.headers?.[HeaderTypes.Authorization]\n\t\t)\n\t);\n\treturn {\n\t\tbody: {\n\t\t\tdecryptionKey: key\n\t\t}\n\t};\n}\n"]}