@twin.org/blob-storage-service 0.0.1-next.3 → 0.0.1-next.31

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.
@@ -1,11 +1,16 @@
1
- import { Guards, ComponentFactory, Is, Converter, GeneralError, Validation, Urn, NotFoundError } from '@twin.org/core';
1
+ import { HttpParameterHelper } from '@twin.org/api-models';
2
+ import { BlobStorageTypes, BlobStorageContexts, BlobStorageConnectorFactory } from '@twin.org/blob-storage-models';
3
+ import { StringHelper, Guards, ComponentFactory, Is, Converter, Coerce, GeneralError, Validation, ObjectHelper, Urn, NotFoundError } from '@twin.org/core';
4
+ import { SchemaOrgContexts, SchemaOrgTypes, SchemaOrgDataTypes } from '@twin.org/standards-schema-org';
2
5
  import { HttpStatusCode, HeaderTypes, MimeTypes, MimeTypeHelper } from '@twin.org/web';
3
- import { BlobStorageConnectorFactory } from '@twin.org/blob-storage-models';
4
- import { JsonLdHelper } from '@twin.org/data-json-ld';
6
+ import { Sha256 } from '@twin.org/crypto';
7
+ import { JsonLdHelper, JsonLdProcessor } from '@twin.org/data-json-ld';
8
+ import { ComparisonOperator, LogicalOperator, SortDirection, EntitySchemaHelper, property, entity, EntitySchemaFactory } from '@twin.org/entity';
5
9
  import { EntityStorageConnectorFactory } from '@twin.org/entity-storage-models';
6
10
  import { VaultConnectorFactory, VaultEncryptionType } from '@twin.org/vault-models';
7
- import { property, entity, EntitySchemaFactory, EntitySchemaHelper } from '@twin.org/entity';
8
11
 
12
+ // Copyright 2024 IOTA Stiftung.
13
+ // SPDX-License-Identifier: Apache-2.0.
9
14
  /**
10
15
  * The source used when communicating about these routes.
11
16
  */
@@ -23,13 +28,19 @@ const tagsBlobStorage = [
23
28
  * The REST routes for blob storage.
24
29
  * @param baseRouteName Prefix to prepend to the paths.
25
30
  * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
31
+ * @param options Additional options for the routes.
32
+ * @param options.typeName Optional type name to use in the routes, defaults to Blob Storage.
33
+ * @param options.tagName Optional name to use in OpenAPI spec for tag.
26
34
  * @returns The generated routes.
27
35
  */
28
- function generateRestRoutesBlobStorage(baseRouteName, componentName) {
36
+ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
37
+ const typeName = options?.typeName ?? "Blob Storage";
38
+ const lowerName = typeName.toLowerCase();
39
+ const camelTypeName = StringHelper.camelCase(typeName);
29
40
  const blobStorageCreateRoute = {
30
- operationId: "blobStorageCreate",
31
- summary: "Create a blob in to storage",
32
- tag: tagsBlobStorage[0].name,
41
+ operationId: `${camelTypeName}Create`,
42
+ summary: `Create an entry in ${lowerName}`,
43
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
33
44
  method: "POST",
34
45
  path: `${baseRouteName}/`,
35
46
  handler: async (httpRequestContext, request) => blobStorageCreate(httpRequestContext, componentName, request),
@@ -37,12 +48,12 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
37
48
  type: "IBlobStorageCreateRequest",
38
49
  examples: [
39
50
  {
40
- id: "blobStorageCreateExample",
51
+ id: `${camelTypeName}CreateRequestExample`,
41
52
  request: {
42
53
  body: {
43
54
  blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==",
44
55
  metadata: {
45
- "@context": "http://schema.org/",
56
+ "@context": "https://schema.org",
46
57
  "@type": "DigitalDocument",
47
58
  name: "myfile.pdf"
48
59
  }
@@ -56,7 +67,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
56
67
  type: "ICreatedResponse",
57
68
  examples: [
58
69
  {
59
- id: "blobStorageCreateResponseExample",
70
+ id: `${camelTypeName}CreateResponseExample`,
60
71
  response: {
61
72
  statusCode: HttpStatusCode.created,
62
73
  headers: {
@@ -69,9 +80,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
69
80
  ]
70
81
  };
71
82
  const blobStorageGetRoute = {
72
- operationId: "blobStorageGet",
73
- summary: "Get the blob metadata from storage",
74
- tag: tagsBlobStorage[0].name,
83
+ operationId: `${camelTypeName}Get`,
84
+ summary: `Get the metadata for an item from ${lowerName}`,
85
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
75
86
  method: "GET",
76
87
  path: `${baseRouteName}/:id`,
77
88
  handler: async (httpRequestContext, request) => blobStorageGet(httpRequestContext, componentName, request),
@@ -79,7 +90,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
79
90
  type: "IBlobStorageGetRequest",
80
91
  examples: [
81
92
  {
82
- id: "blobStorageGetRequestExample",
93
+ id: `${camelTypeName}GetRequestExample`,
83
94
  request: {
84
95
  pathParams: {
85
96
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -96,11 +107,54 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
96
107
  type: "IBlobStorageGetResponse",
97
108
  examples: [
98
109
  {
99
- id: "blobStorageGetResponseExample",
110
+ id: `${camelTypeName}GetResponseExample`,
100
111
  response: {
101
112
  body: {
113
+ "@context": [
114
+ BlobStorageContexts.ContextRoot,
115
+ BlobStorageContexts.ContextRootCommon,
116
+ SchemaOrgContexts.ContextRoot
117
+ ],
118
+ type: BlobStorageTypes.Entry,
119
+ id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
120
+ dateCreated: "2024-01-01T00:00:00Z",
121
+ encodingFormat: MimeTypes.Pdf,
122
+ blobSize: 42,
123
+ blobHash: "sha256:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
124
+ fileExtension: "pdf",
102
125
  metadata: {
103
- "@context": "http://schema.org/",
126
+ "@context": "https://schema.org",
127
+ "@type": "DigitalDocument",
128
+ name: "myfile.pdf"
129
+ },
130
+ blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
131
+ }
132
+ }
133
+ }
134
+ ]
135
+ },
136
+ {
137
+ type: "IBlobStorageGetResponse",
138
+ mimeType: MimeTypes.JsonLd,
139
+ examples: [
140
+ {
141
+ id: `${camelTypeName}GetResponseJsonLdExample`,
142
+ response: {
143
+ body: {
144
+ "@context": [
145
+ BlobStorageContexts.ContextRoot,
146
+ BlobStorageContexts.ContextRootCommon,
147
+ SchemaOrgContexts.ContextRoot
148
+ ],
149
+ type: BlobStorageTypes.Entry,
150
+ id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
151
+ dateCreated: "2024-01-01T00:00:00Z",
152
+ encodingFormat: MimeTypes.Pdf,
153
+ blobSize: 42,
154
+ blobHash: "sha256:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
155
+ fileExtension: "pdf",
156
+ metadata: {
157
+ "@context": "https://schema.org",
104
158
  "@type": "DigitalDocument",
105
159
  name: "myfile.pdf"
106
160
  },
@@ -116,9 +170,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
116
170
  ]
117
171
  };
118
172
  const blobStorageGetContentRoute = {
119
- operationId: "blobStorageGetContent",
120
- summary: "Get the blob from storage",
121
- tag: tagsBlobStorage[0].name,
173
+ operationId: `${camelTypeName}GetContent`,
174
+ summary: `Get the content for an item in ${lowerName}`,
175
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
122
176
  method: "GET",
123
177
  path: `${baseRouteName}/:id/content`,
124
178
  handler: async (httpRequestContext, request) => blobStorageGetContent(httpRequestContext, componentName, request),
@@ -126,7 +180,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
126
180
  type: "IBlobStorageGetRequest",
127
181
  examples: [
128
182
  {
129
- id: "blobStorageGetContentRequestExample",
183
+ id: `${camelTypeName}GetContentRequestExample`,
130
184
  request: {
131
185
  pathParams: {
132
186
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -145,8 +199,8 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
145
199
  mimeType: MimeTypes.OctetStream,
146
200
  examples: [
147
201
  {
148
- id: "blobStorageGetContentResponseExample",
149
- description: `The content of the blob, which will be a specific mime type if one can be detected from the content (or set as mimeType in the metadata), or defaults to ${MimeTypes.OctetStream}.`,
202
+ id: `${camelTypeName}GetContentResponseExample`,
203
+ description: `The content of the blob, which will be a specific mime type if one can be detected from the content (or set as encodingFormat in the entry), or defaults to ${MimeTypes.OctetStream}.`,
150
204
  response: {
151
205
  body: new Uint8Array()
152
206
  }
@@ -159,9 +213,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
159
213
  ]
160
214
  };
161
215
  const blobStorageUpdateRoute = {
162
- operationId: "blobStorageUpdate",
163
- summary: "Update a blob metadata in storage",
164
- tag: tagsBlobStorage[0].name,
216
+ operationId: `${camelTypeName}Update`,
217
+ summary: `Update the metadata for an item in ${lowerName}`,
218
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
165
219
  method: "PUT",
166
220
  path: `${baseRouteName}/:id`,
167
221
  handler: async (httpRequestContext, request) => blobStorageUpdate(httpRequestContext, componentName, request),
@@ -169,14 +223,14 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
169
223
  type: "IBlobStorageUpdateRequest",
170
224
  examples: [
171
225
  {
172
- id: "blobStorageUpdateExample",
226
+ id: `${camelTypeName}UpdateRequestExample`,
173
227
  request: {
174
228
  pathParams: {
175
229
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
176
230
  },
177
231
  body: {
178
232
  metadata: {
179
- "@context": "http://schema.org/",
233
+ "@context": "https://schema.org",
180
234
  "@type": "DigitalDocument",
181
235
  name: "myfile.pdf"
182
236
  }
@@ -192,9 +246,9 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
192
246
  ]
193
247
  };
194
248
  const blobStorageRemoveRoute = {
195
- operationId: "blobStorageRemove",
196
- summary: "Remove the blob from storage",
197
- tag: tagsBlobStorage[0].name,
249
+ operationId: `${camelTypeName}Remove`,
250
+ summary: `Remove an item from ${lowerName}`,
251
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
198
252
  method: "DELETE",
199
253
  path: `${baseRouteName}/:id`,
200
254
  handler: async (httpRequestContext, request) => blobStorageRemove(httpRequestContext, componentName, request),
@@ -202,7 +256,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
202
256
  type: "IBlobStorageRemoveRequest",
203
257
  examples: [
204
258
  {
205
- id: "blobStorageRemoveRequestExample",
259
+ id: `${camelTypeName}RemoveRequestExample`,
206
260
  request: {
207
261
  pathParams: {
208
262
  id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
@@ -220,12 +274,116 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName) {
220
274
  }
221
275
  ]
222
276
  };
277
+ const blobStorageListRoute = {
278
+ operationId: `${camelTypeName}Get`,
279
+ summary: `Query the items from ${lowerName}`,
280
+ tag: options?.tagName ?? tagsBlobStorage[0].name,
281
+ method: "GET",
282
+ path: `${baseRouteName}/`,
283
+ handler: async (httpRequestContext, request) => blobStorageList(httpRequestContext, componentName, request),
284
+ requestType: {
285
+ type: "IBlobStorageListRequest",
286
+ examples: [
287
+ {
288
+ id: `${camelTypeName}ListRequestExample`,
289
+ request: {}
290
+ }
291
+ ]
292
+ },
293
+ responseType: [
294
+ {
295
+ type: "IBlobStorageListResponse",
296
+ examples: [
297
+ {
298
+ id: `${camelTypeName}ListResponseExample`,
299
+ response: {
300
+ body: {
301
+ "@context": [
302
+ SchemaOrgContexts.ContextRoot,
303
+ BlobStorageContexts.ContextRoot,
304
+ BlobStorageContexts.ContextRootCommon
305
+ ],
306
+ type: SchemaOrgTypes.ItemList,
307
+ [SchemaOrgTypes.ItemListElement]: [
308
+ {
309
+ "@context": [
310
+ BlobStorageContexts.ContextRoot,
311
+ BlobStorageContexts.ContextRootCommon,
312
+ SchemaOrgContexts.ContextRoot
313
+ ],
314
+ type: BlobStorageTypes.Entry,
315
+ id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
316
+ dateCreated: "2024-01-01T00:00:00Z",
317
+ encodingFormat: MimeTypes.Pdf,
318
+ blobSize: 42,
319
+ blobHash: "sha256:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
320
+ fileExtension: "pdf",
321
+ metadata: {
322
+ "@context": "https://schema.org",
323
+ "@type": "DigitalDocument",
324
+ name: "myfile.pdf"
325
+ },
326
+ blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
327
+ }
328
+ ]
329
+ }
330
+ }
331
+ }
332
+ ]
333
+ },
334
+ {
335
+ type: "IBlobStorageListResponse",
336
+ mimeType: MimeTypes.JsonLd,
337
+ examples: [
338
+ {
339
+ id: `${camelTypeName}ListResponseJsonLdExample`,
340
+ response: {
341
+ body: {
342
+ "@context": [
343
+ SchemaOrgContexts.ContextRoot,
344
+ BlobStorageContexts.ContextRoot,
345
+ BlobStorageContexts.ContextRootCommon
346
+ ],
347
+ type: SchemaOrgTypes.ItemList,
348
+ [SchemaOrgTypes.ItemListElement]: [
349
+ {
350
+ "@context": [
351
+ BlobStorageContexts.ContextRoot,
352
+ BlobStorageContexts.ContextRootCommon,
353
+ SchemaOrgContexts.ContextRoot
354
+ ],
355
+ type: BlobStorageTypes.Entry,
356
+ id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
357
+ dateCreated: "2024-01-01T00:00:00Z",
358
+ encodingFormat: MimeTypes.Pdf,
359
+ blobSize: 42,
360
+ blobHash: "sha256:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
361
+ fileExtension: "pdf",
362
+ metadata: {
363
+ "@context": "https://schema.org",
364
+ "@type": "DigitalDocument",
365
+ name: "myfile.pdf"
366
+ },
367
+ blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
368
+ }
369
+ ]
370
+ }
371
+ }
372
+ }
373
+ ]
374
+ },
375
+ {
376
+ type: "INotFoundResponse"
377
+ }
378
+ ]
379
+ };
223
380
  return [
224
381
  blobStorageCreateRoute,
225
382
  blobStorageGetRoute,
226
383
  blobStorageGetContentRoute,
227
384
  blobStorageUpdateRoute,
228
- blobStorageRemoveRoute
385
+ blobStorageRemoveRoute,
386
+ blobStorageListRoute
229
387
  ];
230
388
  }
231
389
  /**
@@ -240,11 +398,11 @@ async function blobStorageCreate(httpRequestContext, componentName, request) {
240
398
  Guards.object(ROUTES_SOURCE, "request.body", request.body);
241
399
  Guards.stringBase64(ROUTES_SOURCE, "request.body.blob", request.body.blob);
242
400
  const component = ComponentFactory.get(componentName);
243
- const id = await component.create(request.body.blob, request.body.mimeType, request.body.extension, request.body.metadata, request.body.namespace, httpRequestContext.nodeIdentity);
401
+ const id = await component.create(request.body.blob, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, request.body.namespace, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
244
402
  return {
245
403
  statusCode: HttpStatusCode.created,
246
404
  headers: {
247
- Location: id
405
+ location: id
248
406
  }
249
407
  };
250
408
  }
@@ -259,9 +417,13 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
259
417
  Guards.object(ROUTES_SOURCE, "request", request);
260
418
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
261
419
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
420
+ const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
262
421
  const component = ComponentFactory.get(componentName);
263
- const result = await component.get(request.pathParams.id, request.query?.includeContent ?? false, httpRequestContext.nodeIdentity);
422
+ const result = await component.get(request.pathParams.id, request.query?.includeContent ?? false, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
264
423
  return {
424
+ headers: {
425
+ [HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
426
+ },
265
427
  body: result
266
428
  };
267
429
  }
@@ -277,16 +439,16 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
277
439
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
278
440
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
279
441
  const component = ComponentFactory.get(componentName);
280
- const result = await component.get(request.pathParams.id, true, httpRequestContext.nodeIdentity);
281
- const mimeType = result?.mimeType ?? MimeTypes.OctetStream;
442
+ const result = await component.get(request.pathParams.id, true, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
443
+ const encodingFormat = result?.encodingFormat ?? MimeTypes.OctetStream;
282
444
  let filename = request.query?.filename;
283
445
  if (!Is.stringValue(filename)) {
284
- filename = `file.${result.extension ?? MimeTypeHelper.defaultExtension(mimeType)}`;
446
+ filename = `file.${result.fileExtension ?? MimeTypeHelper.defaultExtension(encodingFormat)}`;
285
447
  }
286
448
  return {
287
449
  body: Is.stringBase64(result.blob) ? Converter.base64ToBytes(result.blob) : new Uint8Array(),
288
450
  attachment: {
289
- mimeType,
451
+ mimeType: encodingFormat,
290
452
  filename,
291
453
  inline: !(request.query?.download ?? false)
292
454
  }
@@ -304,7 +466,7 @@ async function blobStorageUpdate(httpRequestContext, componentName, request) {
304
466
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
305
467
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
306
468
  const component = ComponentFactory.get(componentName);
307
- await component.update(request.pathParams.id, request.body.mimeType, request.body.extension, request.body.metadata);
469
+ await component.update(request.pathParams.id, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
308
470
  return {
309
471
  statusCode: HttpStatusCode.noContent
310
472
  };
@@ -321,11 +483,30 @@ async function blobStorageRemove(httpRequestContext, componentName, request) {
321
483
  Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
322
484
  Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
323
485
  const component = ComponentFactory.get(componentName);
324
- await component.remove(request.pathParams.id);
486
+ await component.remove(request.pathParams.id, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
325
487
  return {
326
488
  statusCode: HttpStatusCode.noContent
327
489
  };
328
490
  }
491
+ /**
492
+ * List the entries from blob storage.
493
+ * @param httpRequestContext The request context for the API.
494
+ * @param componentName The name of the component to use in the routes.
495
+ * @param request The request.
496
+ * @returns The response object with additional http response properties.
497
+ */
498
+ async function blobStorageList(httpRequestContext, componentName, request) {
499
+ Guards.object(ROUTES_SOURCE, "request", request);
500
+ const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
501
+ const component = ComponentFactory.get(componentName);
502
+ const result = await component.query(HttpParameterHelper.objectFromString(request.query?.conditions), request.query?.orderBy, request.query?.orderByDirection, request.query?.cursor, Coerce.number(request.query?.pageSize), httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
503
+ return {
504
+ headers: {
505
+ [HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
506
+ },
507
+ body: result
508
+ };
509
+ }
329
510
 
330
511
  // Copyright 2024 IOTA Stiftung.
331
512
  // SPDX-License-Identifier: Apache-2.0.
@@ -351,7 +532,7 @@ class BlobStorageService {
351
532
  * The storage connector for the metadata.
352
533
  * @internal
353
534
  */
354
- _metadataEntityStorage;
535
+ _entryEntityStorage;
355
536
  /**
356
537
  * The vault connector for the encryption, can be undefined if no encryption required.
357
538
  * @internal
@@ -362,38 +543,52 @@ class BlobStorageService {
362
543
  * @internal
363
544
  */
364
545
  _vaultKeyId;
546
+ /**
547
+ * Include the node identity when performing storage operations, defaults to true.
548
+ * @internal
549
+ */
550
+ _includeNodeIdentity;
551
+ /**
552
+ * Include the user identity when performing storage operations, defaults to true.
553
+ * @internal
554
+ */
555
+ _includeUserIdentity;
365
556
  /**
366
557
  * Create a new instance of BlobStorageService.
367
- * @param options The dependencies for the service.
368
- * @param options.metadataEntityStorageType The type of the storage connector for the metadata, defaults to "blob-metadata".
369
- * @param options.vaultConnectorType The type of the vault connector for encryption, if undefined no encryption will be performed.
370
- * @param options.config The configuration for the service.
558
+ * @param options The options for the service.
371
559
  */
372
560
  constructor(options) {
373
561
  const names = BlobStorageConnectorFactory.names();
374
562
  if (names.length === 0) {
375
563
  throw new GeneralError(this.CLASS_NAME, "noConnectors");
376
564
  }
377
- this._metadataEntityStorage = EntityStorageConnectorFactory.get(options?.metadataEntityStorageType ?? "blob-metadata");
565
+ this._entryEntityStorage = EntityStorageConnectorFactory.get(options?.entryEntityStorageType ?? "blob-storage-entry");
378
566
  if (Is.stringValue(options?.vaultConnectorType)) {
379
567
  this._vaultConnector = VaultConnectorFactory.getIfExists(options.vaultConnectorType);
380
568
  }
381
569
  this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
382
570
  this._vaultKeyId = options?.config?.vaultKeyId ?? "blob-storage";
571
+ this._includeNodeIdentity = options?.config?.includeNodeIdentity ?? true;
572
+ this._includeUserIdentity = options?.config?.includeUserIdentity ?? true;
573
+ SchemaOrgDataTypes.registerRedirects();
383
574
  }
384
575
  /**
385
576
  * Create the blob with some metadata.
386
577
  * @param blob The data for the blob in base64 format.
387
- * @param mimeType Mime type for the blob, will be detected if left undefined.
388
- * @param extension Extension for the blob, will be detected if left undefined.
578
+ * @param encodingFormat Mime type for the blob, will be detected if left undefined.
579
+ * @param fileExtension Extension for the blob, will be detected if left undefined.
389
580
  * @param metadata Data for the custom metadata as JSON-LD.
390
581
  * @param namespace The namespace to use for storing, defaults to component configured namespace.
391
- * @param nodeIdentity The node identity which controls the vault key.
582
+ * @param userIdentity The user identity to use with storage operations.
583
+ * @param nodeIdentity The node identity to use with storage operations.
392
584
  * @returns The id of the stored blob in urn format.
393
585
  */
394
- async create(blob, mimeType, extension, metadata, namespace, nodeIdentity) {
586
+ async create(blob, encodingFormat, fileExtension, metadata, namespace, userIdentity, nodeIdentity) {
395
587
  Guards.stringBase64(this.CLASS_NAME, "blob", blob);
396
- if (this._vaultConnector) {
588
+ if (this._includeUserIdentity) {
589
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
590
+ }
591
+ if (this._includeNodeIdentity || Is.notEmpty(this._vaultConnector)) {
397
592
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
398
593
  }
399
594
  try {
@@ -401,32 +596,48 @@ class BlobStorageService {
401
596
  const blobStorageConnector = BlobStorageConnectorFactory.get(connectorNamespace);
402
597
  // Convert the base64 data into bytes
403
598
  let storeBlob = Converter.base64ToBytes(blob);
599
+ const blobSize = storeBlob.length;
404
600
  // See if we can detect the mime type and default extension for the data.
405
601
  // If not already supplied by the caller. We have to perform this operation
406
602
  // on the unencrypted data.
407
- if (!Is.stringValue(mimeType)) {
408
- mimeType = await MimeTypeHelper.detect(storeBlob);
603
+ if (!Is.stringValue(encodingFormat)) {
604
+ encodingFormat = await MimeTypeHelper.detect(storeBlob);
409
605
  }
410
- if (!Is.stringValue(extension) && Is.stringValue(mimeType)) {
411
- extension = await MimeTypeHelper.defaultExtension(mimeType);
606
+ if (!Is.stringValue(fileExtension) && Is.stringValue(encodingFormat)) {
607
+ fileExtension = await MimeTypeHelper.defaultExtension(encodingFormat);
412
608
  }
413
609
  if (Is.object(metadata)) {
414
610
  const validationFailures = [];
415
611
  JsonLdHelper.validate(metadata, validationFailures);
416
612
  Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
417
613
  }
614
+ const blobHash = `sha256:${Converter.bytesToBase64(Sha256.sum256(storeBlob))}`;
418
615
  // If we have a vault connector then encrypt the data.
419
616
  if (this._vaultConnector) {
420
617
  storeBlob = await this._vaultConnector.encrypt(`${nodeIdentity}/${this._vaultKeyId}`, VaultEncryptionType.ChaCha20Poly1305, storeBlob);
421
618
  }
422
619
  // Set the blob in the storage connector, which may now be encrypted
423
620
  const blobId = await blobStorageConnector.set(storeBlob);
424
- await this._metadataEntityStorage.set({
621
+ // Now store the entry in entity storage
622
+ const blobEntry = {
425
623
  id: blobId,
426
- mimeType,
427
- extension,
624
+ dateCreated: new Date(Date.now()).toISOString(),
625
+ blobSize,
626
+ blobHash,
627
+ encodingFormat,
628
+ fileExtension,
428
629
  metadata
429
- });
630
+ };
631
+ const conditions = [];
632
+ if (this._includeUserIdentity) {
633
+ ObjectHelper.propertySet(blobEntry, "userIdentity", userIdentity);
634
+ conditions.push({ property: "userIdentity", value: userIdentity });
635
+ }
636
+ if (this._includeNodeIdentity) {
637
+ ObjectHelper.propertySet(blobEntry, "nodeIdentity", nodeIdentity);
638
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
639
+ }
640
+ await this._entryEntityStorage.set(blobEntry, conditions);
430
641
  return blobId;
431
642
  }
432
643
  catch (error) {
@@ -434,21 +645,35 @@ class BlobStorageService {
434
645
  }
435
646
  }
436
647
  /**
437
- * Get the blob and metadata.
648
+ * Get the blob entry.
438
649
  * @param id The id of the blob to get in urn format.
439
650
  * @param includeContent Include the content, or just get the metadata.
440
- * @param nodeIdentity The node identity which controls the vault key.
441
- * @returns The metadata and data for the blob if it can be found.
651
+ * @param userIdentity The user identity to use with storage operations.
652
+ * @param nodeIdentity The node identity to use with storage operations.
653
+ * @returns The entry and data for the blob if it can be found.
442
654
  * @throws Not found error if the blob cannot be found.
443
655
  */
444
- async get(id, includeContent, nodeIdentity) {
656
+ async get(id, includeContent, userIdentity, nodeIdentity) {
445
657
  Urn.guard(this.CLASS_NAME, "id", id);
446
- if (this._vaultConnector && includeContent) {
658
+ const conditions = [];
659
+ if (this._includeUserIdentity) {
660
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
661
+ conditions.push({
662
+ property: "userIdentity",
663
+ comparison: ComparisonOperator.Equals,
664
+ value: userIdentity
665
+ });
666
+ }
667
+ if (this._includeNodeIdentity || (Is.notEmpty(this._vaultConnector) && includeContent)) {
447
668
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
669
+ conditions.push({
670
+ property: "nodeIdentity",
671
+ comparison: ComparisonOperator.Equals,
672
+ value: nodeIdentity
673
+ });
448
674
  }
449
675
  try {
450
- // Get the metadata
451
- const blobMetadata = await this._metadataEntityStorage.get(id);
676
+ const blobEntry = await this.internalGet(id, userIdentity, nodeIdentity);
452
677
  let returnBlob;
453
678
  if (includeContent) {
454
679
  const blobStorageConnector = this.getConnector(id);
@@ -461,12 +686,8 @@ class BlobStorageService {
461
686
  returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${this._vaultKeyId}`, VaultEncryptionType.ChaCha20Poly1305, returnBlob);
462
687
  }
463
688
  }
464
- return {
465
- blob: Is.uint8Array(returnBlob) ? Converter.bytesToBase64(returnBlob) : undefined,
466
- mimeType: blobMetadata?.mimeType,
467
- extension: blobMetadata?.extension,
468
- metadata: blobMetadata?.metadata
469
- };
689
+ const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
690
+ return JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
470
691
  }
471
692
  catch (error) {
472
693
  throw new GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
@@ -474,18 +695,26 @@ class BlobStorageService {
474
695
  }
475
696
  /**
476
697
  * Update the blob with metadata.
477
- * @param id The id of the blob metadata to update.
478
- * @param mimeType Mime type for the blob, will be detected if left undefined.
479
- * @param extension Extension for the blob, will be detected if left undefined.
698
+ * @param id The id of the blob entry to update.
699
+ * @param encodingFormat Mime type for the blob, will be detected if left undefined.
700
+ * @param fileExtension Extension for the blob, will be detected if left undefined.
480
701
  * @param metadata Data for the custom metadata as JSON-LD.
702
+ * @param userIdentity The user identity to use with storage operations.
703
+ * @param nodeIdentity The node identity to use with storage operations.
481
704
  * @returns Nothing.
482
705
  * @throws Not found error if the blob cannot be found.
483
706
  */
484
- async update(id, mimeType, extension, metadata) {
707
+ async update(id, encodingFormat, fileExtension, metadata, userIdentity, nodeIdentity) {
485
708
  Urn.guard(this.CLASS_NAME, "id", id);
709
+ if (this._includeUserIdentity) {
710
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
711
+ }
712
+ if (this._includeNodeIdentity || Is.notEmpty(this._vaultConnector)) {
713
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
714
+ }
486
715
  try {
487
- const blobMetadata = await this._metadataEntityStorage.get(id);
488
- if (Is.undefined(blobMetadata)) {
716
+ const blobEntry = await this._entryEntityStorage.get(id);
717
+ if (Is.undefined(blobEntry)) {
489
718
  throw new NotFoundError(this.CLASS_NAME, "blobNotFound", id);
490
719
  }
491
720
  if (Is.object(metadata)) {
@@ -493,12 +722,27 @@ class BlobStorageService {
493
722
  await JsonLdHelper.validate(metadata, validationFailures);
494
723
  Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
495
724
  }
496
- await this._metadataEntityStorage.set({
497
- id: blobMetadata.id,
498
- mimeType: mimeType ?? blobMetadata.mimeType,
499
- extension: extension ?? blobMetadata.extension,
500
- metadata: metadata ?? blobMetadata.metadata
501
- });
725
+ // Now store the entry in entity storage
726
+ const updatedBlobEntry = {
727
+ id: blobEntry.id,
728
+ dateCreated: blobEntry.dateCreated,
729
+ dateModified: new Date(Date.now()).toISOString(),
730
+ blobSize: blobEntry.blobSize,
731
+ blobHash: blobEntry.blobHash,
732
+ encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
733
+ fileExtension: fileExtension ?? blobEntry.fileExtension,
734
+ metadata: metadata ?? blobEntry.metadata
735
+ };
736
+ const conditions = [];
737
+ if (this._includeUserIdentity) {
738
+ ObjectHelper.propertySet(updatedBlobEntry, "userIdentity", userIdentity);
739
+ conditions.push({ property: "userIdentity", value: userIdentity });
740
+ }
741
+ if (this._includeNodeIdentity) {
742
+ ObjectHelper.propertySet(updatedBlobEntry, "nodeIdentity", nodeIdentity);
743
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
744
+ }
745
+ await this._entryEntityStorage.set(updatedBlobEntry, conditions);
502
746
  }
503
747
  catch (error) {
504
748
  throw new GeneralError(this.CLASS_NAME, "updateFailed", undefined, error);
@@ -507,22 +751,104 @@ class BlobStorageService {
507
751
  /**
508
752
  * Remove the blob.
509
753
  * @param id The id of the blob to remove in urn format.
754
+ * @param userIdentity The user identity to use with storage operations.
755
+ * @param nodeIdentity The node identity to use with storage operations.
510
756
  * @returns Nothing.
511
757
  */
512
- async remove(id) {
758
+ async remove(id, userIdentity, nodeIdentity) {
513
759
  Urn.guard(this.CLASS_NAME, "id", id);
760
+ if (this._includeUserIdentity) {
761
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
762
+ }
763
+ if (this._includeNodeIdentity || Is.notEmpty(this._vaultConnector)) {
764
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
765
+ }
514
766
  try {
515
767
  const blobStorageConnector = this.getConnector(id);
768
+ const conditions = [];
769
+ if (this._includeUserIdentity) {
770
+ conditions.push({ property: "userIdentity", value: userIdentity });
771
+ }
772
+ if (this._includeNodeIdentity) {
773
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
774
+ }
775
+ await this._entryEntityStorage.remove(id, conditions);
516
776
  const removed = await blobStorageConnector.remove(id);
517
777
  if (!removed) {
518
778
  throw new NotFoundError(this.CLASS_NAME, "blobNotFound", id);
519
779
  }
520
- await this._metadataEntityStorage.remove(id);
521
780
  }
522
781
  catch (error) {
523
782
  throw new GeneralError(this.CLASS_NAME, "removeFailed", undefined, error);
524
783
  }
525
784
  }
785
+ /**
786
+ * Query all the blob storage entries which match the conditions.
787
+ * @param conditions The conditions to match for the entries.
788
+ * @param orderBy The order for the results, defaults to created.
789
+ * @param orderByDirection The direction for the order, defaults to descending.
790
+ * @param cursor The cursor to request the next page of entries.
791
+ * @param pageSize The suggested number of entries to return in each chunk, in some scenarios can return a different amount.
792
+ * @param userIdentity The user identity to use with storage operations.
793
+ * @param nodeIdentity The node identity to use with storage operations.
794
+ * @returns All the entries for the storage matching the conditions,
795
+ * and a cursor which can be used to request more entities.
796
+ */
797
+ async query(conditions, orderBy, orderByDirection, cursor, pageSize, userIdentity, nodeIdentity) {
798
+ const finalConditions = {
799
+ conditions: [],
800
+ logicalOperator: LogicalOperator.And
801
+ };
802
+ if (this._includeNodeIdentity) {
803
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
804
+ finalConditions.conditions.push({
805
+ property: "nodeIdentity",
806
+ comparison: ComparisonOperator.Equals,
807
+ value: nodeIdentity
808
+ });
809
+ }
810
+ if (this._includeUserIdentity) {
811
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
812
+ finalConditions.conditions.push({
813
+ property: "userIdentity",
814
+ comparison: ComparisonOperator.Equals,
815
+ value: userIdentity
816
+ });
817
+ }
818
+ if (!Is.empty(conditions)) {
819
+ finalConditions.conditions.push(conditions);
820
+ }
821
+ const orderProperty = orderBy ?? "dateCreated";
822
+ const orderDirection = orderByDirection ?? SortDirection.Descending;
823
+ const result = await this._entryEntityStorage.query(finalConditions.conditions.length > 0 ? finalConditions : undefined, [
824
+ {
825
+ property: orderProperty,
826
+ sortDirection: orderDirection
827
+ }
828
+ ], undefined, cursor, pageSize);
829
+ for (const entity of result.entities) {
830
+ ObjectHelper.propertyDelete(entity, "nodeIdentity");
831
+ ObjectHelper.propertyDelete(entity, "userIdentity");
832
+ }
833
+ let context = [
834
+ SchemaOrgContexts.ContextRoot,
835
+ BlobStorageContexts.ContextRoot,
836
+ BlobStorageContexts.ContextRootCommon
837
+ ];
838
+ const entriesJsonLd = [];
839
+ for (const entry of result.entities) {
840
+ // The entries are never Partial as we don't allow custom property requests.
841
+ entriesJsonLd.push(this.entryToJsonLd(entry));
842
+ context = JsonLdProcessor.combineContexts(context, entry.metadata?.["@context"]);
843
+ }
844
+ const jsonLd = {
845
+ "@context": context,
846
+ type: SchemaOrgTypes.ItemList,
847
+ [SchemaOrgTypes.ItemListElement]: entriesJsonLd,
848
+ [SchemaOrgTypes.NextItem]: result.cursor
849
+ };
850
+ return JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
851
+ }
526
852
  /**
527
853
  * Get the connector from the uri.
528
854
  * @param id The id of the blob storage item in urn format.
@@ -539,53 +865,190 @@ class BlobStorageService {
539
865
  }
540
866
  return BlobStorageConnectorFactory.get(idUri.namespaceMethod());
541
867
  }
868
+ /**
869
+ * Get an entity.
870
+ * @param id The id of the entity to get, or the index value if secondaryIndex is set.
871
+ * @param secondaryIndex Get the item using a secondary index.
872
+ * @param userIdentity The user identity to use with storage operations.
873
+ * @param nodeIdentity The node identity to use with storage operations.
874
+ * @returns The object if it can be found or throws.
875
+ * @internal
876
+ */
877
+ async internalGet(id, userIdentity, nodeIdentity) {
878
+ const conditions = [];
879
+ if (this._includeUserIdentity) {
880
+ Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
881
+ conditions.push({
882
+ property: "userIdentity",
883
+ comparison: ComparisonOperator.Equals,
884
+ value: userIdentity
885
+ });
886
+ }
887
+ if (this._includeNodeIdentity) {
888
+ Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
889
+ conditions.push({
890
+ property: "nodeIdentity",
891
+ comparison: ComparisonOperator.Equals,
892
+ value: nodeIdentity
893
+ });
894
+ }
895
+ let entity;
896
+ if (conditions.length === 0) {
897
+ entity = await this._entryEntityStorage.get(id);
898
+ }
899
+ else {
900
+ const schema = this._entryEntityStorage.getSchema();
901
+ const primaryKey = EntitySchemaHelper.getPrimaryKey(schema);
902
+ conditions.unshift({
903
+ property: primaryKey.property,
904
+ comparison: ComparisonOperator.Equals,
905
+ value: id
906
+ });
907
+ const results = await this._entryEntityStorage.query({
908
+ conditions,
909
+ logicalOperator: LogicalOperator.And
910
+ }, undefined, undefined, undefined, 1);
911
+ entity = results.entities[0];
912
+ }
913
+ if (Is.empty(entity)) {
914
+ throw new NotFoundError(this.CLASS_NAME, "entityNotFound", id);
915
+ }
916
+ ObjectHelper.propertyDelete(entity, "nodeIdentity");
917
+ ObjectHelper.propertyDelete(entity, "userIdentity");
918
+ return entity;
919
+ }
920
+ /**
921
+ * Convert the entry to JSON-LD.
922
+ * @param entry The entry to convert.
923
+ * @param blob The optional blob to return.
924
+ * @returns The JSON-LD representation of the entry.
925
+ * @internal
926
+ */
927
+ entryToJsonLd(entry, blob) {
928
+ const jsonLd = {
929
+ "@context": JsonLdProcessor.combineContexts([
930
+ BlobStorageContexts.ContextRoot,
931
+ BlobStorageContexts.ContextRootCommon,
932
+ SchemaOrgContexts.ContextRoot
933
+ ], entry?.metadata?.["@context"]),
934
+ id: entry.id,
935
+ type: BlobStorageTypes.Entry,
936
+ dateCreated: entry.dateCreated,
937
+ dateModified: entry.dateModified,
938
+ blobSize: entry.blobSize,
939
+ blobHash: entry.blobHash,
940
+ encodingFormat: entry?.encodingFormat,
941
+ fileExtension: entry?.fileExtension,
942
+ metadata: entry?.metadata,
943
+ blob: Is.uint8Array(blob) ? Converter.bytesToBase64(blob) : undefined
944
+ };
945
+ return jsonLd;
946
+ }
542
947
  }
543
948
 
544
949
  /**
545
- * Class representing metadata for the blob storage.
950
+ * Class representing entry for the blob storage.
546
951
  */
547
- let BlobMetadata = class BlobMetadata {
952
+ let BlobStorageEntry = class BlobStorageEntry {
548
953
  /**
549
954
  * The id for the blob.
550
955
  */
551
956
  id;
957
+ /**
958
+ * The date/time when the entry was created.
959
+ */
960
+ dateCreated;
961
+ /**
962
+ * The date/time when the entry was modified.
963
+ */
964
+ dateModified;
965
+ /**
966
+ * The length of the data in the blob.
967
+ */
968
+ blobSize;
969
+ /**
970
+ * The hash of the data in the blob.
971
+ */
972
+ blobHash;
552
973
  /**
553
974
  * The mime type for the blob.
554
975
  */
555
- mimeType;
976
+ encodingFormat;
556
977
  /**
557
978
  * The extension.
558
979
  */
559
- extension;
980
+ fileExtension;
560
981
  /**
561
982
  * The metadata for the blob as JSON-LD.
562
983
  */
563
984
  metadata;
985
+ /**
986
+ * The user identity that created the blob.
987
+ */
988
+ userIdentity;
989
+ /**
990
+ * The node identity that created the blob.
991
+ */
992
+ nodeIdentity;
564
993
  };
565
994
  __decorate([
566
995
  property({ type: "string", isPrimary: true }),
567
996
  __metadata("design:type", String)
568
- ], BlobMetadata.prototype, "id", void 0);
997
+ ], BlobStorageEntry.prototype, "id", void 0);
569
998
  __decorate([
570
- property({ type: "string" }),
999
+ property({ type: "string", format: "date-time", sortDirection: SortDirection.Descending }),
571
1000
  __metadata("design:type", String)
572
- ], BlobMetadata.prototype, "mimeType", void 0);
1001
+ ], BlobStorageEntry.prototype, "dateCreated", void 0);
1002
+ __decorate([
1003
+ property({
1004
+ type: "string",
1005
+ format: "date-time",
1006
+ sortDirection: SortDirection.Descending,
1007
+ optional: true
1008
+ }),
1009
+ __metadata("design:type", String)
1010
+ ], BlobStorageEntry.prototype, "dateModified", void 0);
1011
+ __decorate([
1012
+ property({ type: "number" }),
1013
+ __metadata("design:type", Number)
1014
+ ], BlobStorageEntry.prototype, "blobSize", void 0);
573
1015
  __decorate([
574
1016
  property({ type: "string" }),
575
1017
  __metadata("design:type", String)
576
- ], BlobMetadata.prototype, "extension", void 0);
1018
+ ], BlobStorageEntry.prototype, "blobHash", void 0);
1019
+ __decorate([
1020
+ property({ type: "string", optional: true }),
1021
+ __metadata("design:type", String)
1022
+ ], BlobStorageEntry.prototype, "encodingFormat", void 0);
1023
+ __decorate([
1024
+ property({ type: "string", optional: true }),
1025
+ __metadata("design:type", String)
1026
+ ], BlobStorageEntry.prototype, "fileExtension", void 0);
577
1027
  __decorate([
578
- property({ type: "object", itemTypeRef: "IJsonLdNodeObject" }),
1028
+ property({ type: "object", itemTypeRef: "IJsonLdNodeObject", optional: true }),
579
1029
  __metadata("design:type", Object)
580
- ], BlobMetadata.prototype, "metadata", void 0);
581
- BlobMetadata = __decorate([
1030
+ ], BlobStorageEntry.prototype, "metadata", void 0);
1031
+ __decorate([
1032
+ property({ type: "string", optional: true }),
1033
+ __metadata("design:type", String)
1034
+ ], BlobStorageEntry.prototype, "userIdentity", void 0);
1035
+ __decorate([
1036
+ property({ type: "string", optional: true }),
1037
+ __metadata("design:type", String)
1038
+ ], BlobStorageEntry.prototype, "nodeIdentity", void 0);
1039
+ BlobStorageEntry = __decorate([
582
1040
  entity()
583
- ], BlobMetadata);
1041
+ ], BlobStorageEntry);
584
1042
 
1043
+ /**
1044
+ * These are dummy entry points for the blob storage service.
1045
+ * In reality your application would create its own entry points based on the
1046
+ * blob types it wants to store, using a custom defaultBaseRoute.
1047
+ */
585
1048
  const restEntryPoints = [
586
1049
  {
587
- name: "blobStorage",
588
- defaultBaseRoute: "blob",
1050
+ name: "blob-storage",
1051
+ defaultBaseRoute: "blob-storage",
589
1052
  tags: tagsBlobStorage,
590
1053
  generateRoutes: generateRestRoutesBlobStorage
591
1054
  }
@@ -597,7 +1060,7 @@ const restEntryPoints = [
597
1060
  * Initialize the schema for the blob storage entities.
598
1061
  */
599
1062
  function initSchema() {
600
- EntitySchemaFactory.register("BlobMetadata", () => EntitySchemaHelper.getSchema(BlobMetadata));
1063
+ EntitySchemaFactory.register("BlobStorageEntry", () => EntitySchemaHelper.getSchema(BlobStorageEntry));
601
1064
  }
602
1065
 
603
- export { BlobMetadata, BlobStorageService, blobStorageCreate, blobStorageGet, blobStorageGetContent, blobStorageRemove, blobStorageUpdate, generateRestRoutesBlobStorage, initSchema, restEntryPoints, tagsBlobStorage };
1066
+ export { BlobStorageEntry, BlobStorageService, blobStorageCreate, blobStorageGet, blobStorageGetContent, blobStorageList, blobStorageRemove, blobStorageUpdate, generateRestRoutesBlobStorage, initSchema, restEntryPoints, tagsBlobStorage };