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

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