@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,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,116 @@ 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
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot,
305
+ blobStorageModels.BlobStorageContexts.ContextRoot,
306
+ blobStorageModels.BlobStorageContexts.ContextRootCommon
307
+ ],
308
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
309
+ [standardsSchemaOrg.SchemaOrgTypes.ItemListElement]: [
310
+ {
311
+ "@context": [
312
+ blobStorageModels.BlobStorageContexts.ContextRoot,
313
+ blobStorageModels.BlobStorageContexts.ContextRootCommon,
314
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot
315
+ ],
316
+ type: blobStorageModels.BlobStorageTypes.Entry,
317
+ id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
318
+ dateCreated: "2024-01-01T00:00:00Z",
319
+ encodingFormat: web.MimeTypes.Pdf,
320
+ blobSize: 42,
321
+ blobHash: "sha256:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
322
+ fileExtension: "pdf",
323
+ metadata: {
324
+ "@context": "https://schema.org",
325
+ "@type": "DigitalDocument",
326
+ name: "myfile.pdf"
327
+ },
328
+ blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
329
+ }
330
+ ]
331
+ }
332
+ }
333
+ }
334
+ ]
335
+ },
336
+ {
337
+ type: "IBlobStorageListResponse",
338
+ mimeType: web.MimeTypes.JsonLd,
339
+ examples: [
340
+ {
341
+ id: `${camelTypeName}ListResponseJsonLdExample`,
342
+ response: {
343
+ body: {
344
+ "@context": [
345
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot,
346
+ blobStorageModels.BlobStorageContexts.ContextRoot,
347
+ blobStorageModels.BlobStorageContexts.ContextRootCommon
348
+ ],
349
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
350
+ [standardsSchemaOrg.SchemaOrgTypes.ItemListElement]: [
351
+ {
352
+ "@context": [
353
+ blobStorageModels.BlobStorageContexts.ContextRoot,
354
+ blobStorageModels.BlobStorageContexts.ContextRootCommon,
355
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot
356
+ ],
357
+ type: blobStorageModels.BlobStorageTypes.Entry,
358
+ id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
359
+ dateCreated: "2024-01-01T00:00:00Z",
360
+ encodingFormat: web.MimeTypes.Pdf,
361
+ blobSize: 42,
362
+ blobHash: "sha256:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
363
+ fileExtension: "pdf",
364
+ metadata: {
365
+ "@context": "https://schema.org",
366
+ "@type": "DigitalDocument",
367
+ name: "myfile.pdf"
368
+ },
369
+ blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
370
+ }
371
+ ]
372
+ }
373
+ }
374
+ }
375
+ ]
376
+ },
377
+ {
378
+ type: "INotFoundResponse"
379
+ }
380
+ ]
381
+ };
225
382
  return [
226
383
  blobStorageCreateRoute,
227
384
  blobStorageGetRoute,
228
385
  blobStorageGetContentRoute,
229
386
  blobStorageUpdateRoute,
230
- blobStorageRemoveRoute
387
+ blobStorageRemoveRoute,
388
+ blobStorageListRoute
231
389
  ];
232
390
  }
233
391
  /**
@@ -242,11 +400,11 @@ async function blobStorageCreate(httpRequestContext, componentName, request) {
242
400
  core.Guards.object(ROUTES_SOURCE, "request.body", request.body);
243
401
  core.Guards.stringBase64(ROUTES_SOURCE, "request.body.blob", request.body.blob);
244
402
  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);
403
+ 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
404
  return {
247
405
  statusCode: web.HttpStatusCode.created,
248
406
  headers: {
249
- Location: id
407
+ location: id
250
408
  }
251
409
  };
252
410
  }
@@ -261,9 +419,13 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
261
419
  core.Guards.object(ROUTES_SOURCE, "request", request);
262
420
  core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
263
421
  core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
422
+ const mimeType = request.headers?.[web.HeaderTypes.Accept] === web.MimeTypes.JsonLd ? "jsonld" : "json";
264
423
  const component = core.ComponentFactory.get(componentName);
265
- const result = await component.get(request.pathParams.id, request.query?.includeContent ?? false, httpRequestContext.nodeIdentity);
424
+ const result = await component.get(request.pathParams.id, request.query?.includeContent ?? false, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
266
425
  return {
426
+ headers: {
427
+ [web.HeaderTypes.ContentType]: mimeType === "json" ? web.MimeTypes.Json : web.MimeTypes.JsonLd
428
+ },
267
429
  body: result
268
430
  };
269
431
  }
@@ -279,16 +441,16 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
279
441
  core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
280
442
  core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
281
443
  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;
444
+ const result = await component.get(request.pathParams.id, true, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
445
+ const encodingFormat = result?.encodingFormat ?? web.MimeTypes.OctetStream;
284
446
  let filename = request.query?.filename;
285
447
  if (!core.Is.stringValue(filename)) {
286
- filename = `file.${result.extension ?? web.MimeTypeHelper.defaultExtension(mimeType)}`;
448
+ filename = `file.${result.fileExtension ?? web.MimeTypeHelper.defaultExtension(encodingFormat)}`;
287
449
  }
288
450
  return {
289
451
  body: core.Is.stringBase64(result.blob) ? core.Converter.base64ToBytes(result.blob) : new Uint8Array(),
290
452
  attachment: {
291
- mimeType,
453
+ mimeType: encodingFormat,
292
454
  filename,
293
455
  inline: !(request.query?.download ?? false)
294
456
  }
@@ -306,7 +468,7 @@ async function blobStorageUpdate(httpRequestContext, componentName, request) {
306
468
  core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
307
469
  core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
308
470
  const component = core.ComponentFactory.get(componentName);
309
- await component.update(request.pathParams.id, request.body.mimeType, request.body.extension, request.body.metadata);
471
+ await component.update(request.pathParams.id, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
310
472
  return {
311
473
  statusCode: web.HttpStatusCode.noContent
312
474
  };
@@ -323,11 +485,30 @@ async function blobStorageRemove(httpRequestContext, componentName, request) {
323
485
  core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
324
486
  core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
325
487
  const component = core.ComponentFactory.get(componentName);
326
- await component.remove(request.pathParams.id);
488
+ await component.remove(request.pathParams.id, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
327
489
  return {
328
490
  statusCode: web.HttpStatusCode.noContent
329
491
  };
330
492
  }
493
+ /**
494
+ * List the entries from blob storage.
495
+ * @param httpRequestContext The request context for the API.
496
+ * @param componentName The name of the component to use in the routes.
497
+ * @param request The request.
498
+ * @returns The response object with additional http response properties.
499
+ */
500
+ async function blobStorageList(httpRequestContext, componentName, request) {
501
+ core.Guards.object(ROUTES_SOURCE, "request", request);
502
+ const mimeType = request.headers?.[web.HeaderTypes.Accept] === web.MimeTypes.JsonLd ? "jsonld" : "json";
503
+ const component = core.ComponentFactory.get(componentName);
504
+ 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);
505
+ return {
506
+ headers: {
507
+ [web.HeaderTypes.ContentType]: mimeType === "json" ? web.MimeTypes.Json : web.MimeTypes.JsonLd
508
+ },
509
+ body: result
510
+ };
511
+ }
331
512
 
332
513
  // Copyright 2024 IOTA Stiftung.
333
514
  // SPDX-License-Identifier: Apache-2.0.
@@ -353,7 +534,7 @@ class BlobStorageService {
353
534
  * The storage connector for the metadata.
354
535
  * @internal
355
536
  */
356
- _metadataEntityStorage;
537
+ _entryEntityStorage;
357
538
  /**
358
539
  * The vault connector for the encryption, can be undefined if no encryption required.
359
540
  * @internal
@@ -364,38 +545,52 @@ class BlobStorageService {
364
545
  * @internal
365
546
  */
366
547
  _vaultKeyId;
548
+ /**
549
+ * Include the node identity when performing storage operations, defaults to true.
550
+ * @internal
551
+ */
552
+ _includeNodeIdentity;
553
+ /**
554
+ * Include the user identity when performing storage operations, defaults to true.
555
+ * @internal
556
+ */
557
+ _includeUserIdentity;
367
558
  /**
368
559
  * 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.
560
+ * @param options The options for the service.
373
561
  */
374
562
  constructor(options) {
375
563
  const names = blobStorageModels.BlobStorageConnectorFactory.names();
376
564
  if (names.length === 0) {
377
565
  throw new core.GeneralError(this.CLASS_NAME, "noConnectors");
378
566
  }
379
- this._metadataEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.metadataEntityStorageType ?? "blob-metadata");
567
+ this._entryEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.entryEntityStorageType ?? "blob-storage-entry");
380
568
  if (core.Is.stringValue(options?.vaultConnectorType)) {
381
569
  this._vaultConnector = vaultModels.VaultConnectorFactory.getIfExists(options.vaultConnectorType);
382
570
  }
383
571
  this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
384
572
  this._vaultKeyId = options?.config?.vaultKeyId ?? "blob-storage";
573
+ this._includeNodeIdentity = options?.config?.includeNodeIdentity ?? true;
574
+ this._includeUserIdentity = options?.config?.includeUserIdentity ?? true;
575
+ standardsSchemaOrg.SchemaOrgDataTypes.registerRedirects();
385
576
  }
386
577
  /**
387
578
  * Create the blob with some metadata.
388
579
  * @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.
580
+ * @param encodingFormat Mime type for the blob, will be detected if left undefined.
581
+ * @param fileExtension Extension for the blob, will be detected if left undefined.
391
582
  * @param metadata Data for the custom metadata as JSON-LD.
392
583
  * @param namespace The namespace to use for storing, defaults to component configured namespace.
393
- * @param nodeIdentity The node identity which controls the vault key.
584
+ * @param userIdentity The user identity to use with storage operations.
585
+ * @param nodeIdentity The node identity to use with storage operations.
394
586
  * @returns The id of the stored blob in urn format.
395
587
  */
396
- async create(blob, mimeType, extension, metadata, namespace, nodeIdentity) {
588
+ async create(blob, encodingFormat, fileExtension, metadata, namespace, userIdentity, nodeIdentity) {
397
589
  core.Guards.stringBase64(this.CLASS_NAME, "blob", blob);
398
- if (this._vaultConnector) {
590
+ if (this._includeUserIdentity) {
591
+ core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
592
+ }
593
+ if (this._includeNodeIdentity || core.Is.notEmpty(this._vaultConnector)) {
399
594
  core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
400
595
  }
401
596
  try {
@@ -403,32 +598,48 @@ class BlobStorageService {
403
598
  const blobStorageConnector = blobStorageModels.BlobStorageConnectorFactory.get(connectorNamespace);
404
599
  // Convert the base64 data into bytes
405
600
  let storeBlob = core.Converter.base64ToBytes(blob);
601
+ const blobSize = storeBlob.length;
406
602
  // See if we can detect the mime type and default extension for the data.
407
603
  // If not already supplied by the caller. We have to perform this operation
408
604
  // on the unencrypted data.
409
- if (!core.Is.stringValue(mimeType)) {
410
- mimeType = await web.MimeTypeHelper.detect(storeBlob);
605
+ if (!core.Is.stringValue(encodingFormat)) {
606
+ encodingFormat = await web.MimeTypeHelper.detect(storeBlob);
411
607
  }
412
- if (!core.Is.stringValue(extension) && core.Is.stringValue(mimeType)) {
413
- extension = await web.MimeTypeHelper.defaultExtension(mimeType);
608
+ if (!core.Is.stringValue(fileExtension) && core.Is.stringValue(encodingFormat)) {
609
+ fileExtension = await web.MimeTypeHelper.defaultExtension(encodingFormat);
414
610
  }
415
611
  if (core.Is.object(metadata)) {
416
612
  const validationFailures = [];
417
613
  dataJsonLd.JsonLdHelper.validate(metadata, validationFailures);
418
614
  core.Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
419
615
  }
616
+ const blobHash = `sha256:${core.Converter.bytesToBase64(crypto.Sha256.sum256(storeBlob))}`;
420
617
  // If we have a vault connector then encrypt the data.
421
618
  if (this._vaultConnector) {
422
619
  storeBlob = await this._vaultConnector.encrypt(`${nodeIdentity}/${this._vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, storeBlob);
423
620
  }
424
621
  // Set the blob in the storage connector, which may now be encrypted
425
622
  const blobId = await blobStorageConnector.set(storeBlob);
426
- await this._metadataEntityStorage.set({
623
+ // Now store the entry in entity storage
624
+ const blobEntry = {
427
625
  id: blobId,
428
- mimeType,
429
- extension,
626
+ dateCreated: new Date(Date.now()).toISOString(),
627
+ blobSize,
628
+ blobHash,
629
+ encodingFormat,
630
+ fileExtension,
430
631
  metadata
431
- });
632
+ };
633
+ const conditions = [];
634
+ if (this._includeUserIdentity) {
635
+ core.ObjectHelper.propertySet(blobEntry, "userIdentity", userIdentity);
636
+ conditions.push({ property: "userIdentity", value: userIdentity });
637
+ }
638
+ if (this._includeNodeIdentity) {
639
+ core.ObjectHelper.propertySet(blobEntry, "nodeIdentity", nodeIdentity);
640
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
641
+ }
642
+ await this._entryEntityStorage.set(blobEntry, conditions);
432
643
  return blobId;
433
644
  }
434
645
  catch (error) {
@@ -436,21 +647,35 @@ class BlobStorageService {
436
647
  }
437
648
  }
438
649
  /**
439
- * Get the blob and metadata.
650
+ * Get the blob entry.
440
651
  * @param id The id of the blob to get in urn format.
441
652
  * @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.
653
+ * @param userIdentity The user identity to use with storage operations.
654
+ * @param nodeIdentity The node identity to use with storage operations.
655
+ * @returns The entry and data for the blob if it can be found.
444
656
  * @throws Not found error if the blob cannot be found.
445
657
  */
446
- async get(id, includeContent, nodeIdentity) {
658
+ async get(id, includeContent, userIdentity, nodeIdentity) {
447
659
  core.Urn.guard(this.CLASS_NAME, "id", id);
448
- if (this._vaultConnector && includeContent) {
660
+ const conditions = [];
661
+ if (this._includeUserIdentity) {
662
+ core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
663
+ conditions.push({
664
+ property: "userIdentity",
665
+ comparison: entity.ComparisonOperator.Equals,
666
+ value: userIdentity
667
+ });
668
+ }
669
+ if (this._includeNodeIdentity || (core.Is.notEmpty(this._vaultConnector) && includeContent)) {
449
670
  core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
671
+ conditions.push({
672
+ property: "nodeIdentity",
673
+ comparison: entity.ComparisonOperator.Equals,
674
+ value: nodeIdentity
675
+ });
450
676
  }
451
677
  try {
452
- // Get the metadata
453
- const blobMetadata = await this._metadataEntityStorage.get(id);
678
+ const blobEntry = await this.internalGet(id, userIdentity, nodeIdentity);
454
679
  let returnBlob;
455
680
  if (includeContent) {
456
681
  const blobStorageConnector = this.getConnector(id);
@@ -463,12 +688,8 @@ class BlobStorageService {
463
688
  returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${this._vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, returnBlob);
464
689
  }
465
690
  }
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
- };
691
+ const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
692
+ return dataJsonLd.JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
472
693
  }
473
694
  catch (error) {
474
695
  throw new core.GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
@@ -476,18 +697,26 @@ class BlobStorageService {
476
697
  }
477
698
  /**
478
699
  * 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.
700
+ * @param id The id of the blob entry to update.
701
+ * @param encodingFormat Mime type for the blob, will be detected if left undefined.
702
+ * @param fileExtension Extension for the blob, will be detected if left undefined.
482
703
  * @param metadata Data for the custom metadata as JSON-LD.
704
+ * @param userIdentity The user identity to use with storage operations.
705
+ * @param nodeIdentity The node identity to use with storage operations.
483
706
  * @returns Nothing.
484
707
  * @throws Not found error if the blob cannot be found.
485
708
  */
486
- async update(id, mimeType, extension, metadata) {
709
+ async update(id, encodingFormat, fileExtension, metadata, userIdentity, nodeIdentity) {
487
710
  core.Urn.guard(this.CLASS_NAME, "id", id);
711
+ if (this._includeUserIdentity) {
712
+ core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
713
+ }
714
+ if (this._includeNodeIdentity || core.Is.notEmpty(this._vaultConnector)) {
715
+ core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
716
+ }
488
717
  try {
489
- const blobMetadata = await this._metadataEntityStorage.get(id);
490
- if (core.Is.undefined(blobMetadata)) {
718
+ const blobEntry = await this._entryEntityStorage.get(id);
719
+ if (core.Is.undefined(blobEntry)) {
491
720
  throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
492
721
  }
493
722
  if (core.Is.object(metadata)) {
@@ -495,12 +724,27 @@ class BlobStorageService {
495
724
  await dataJsonLd.JsonLdHelper.validate(metadata, validationFailures);
496
725
  core.Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
497
726
  }
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
- });
727
+ // Now store the entry in entity storage
728
+ const updatedBlobEntry = {
729
+ id: blobEntry.id,
730
+ dateCreated: blobEntry.dateCreated,
731
+ dateModified: new Date(Date.now()).toISOString(),
732
+ blobSize: blobEntry.blobSize,
733
+ blobHash: blobEntry.blobHash,
734
+ encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
735
+ fileExtension: fileExtension ?? blobEntry.fileExtension,
736
+ metadata: metadata ?? blobEntry.metadata
737
+ };
738
+ const conditions = [];
739
+ if (this._includeUserIdentity) {
740
+ core.ObjectHelper.propertySet(updatedBlobEntry, "userIdentity", userIdentity);
741
+ conditions.push({ property: "userIdentity", value: userIdentity });
742
+ }
743
+ if (this._includeNodeIdentity) {
744
+ core.ObjectHelper.propertySet(updatedBlobEntry, "nodeIdentity", nodeIdentity);
745
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
746
+ }
747
+ await this._entryEntityStorage.set(updatedBlobEntry, conditions);
504
748
  }
505
749
  catch (error) {
506
750
  throw new core.GeneralError(this.CLASS_NAME, "updateFailed", undefined, error);
@@ -509,22 +753,104 @@ class BlobStorageService {
509
753
  /**
510
754
  * Remove the blob.
511
755
  * @param id The id of the blob to remove in urn format.
756
+ * @param userIdentity The user identity to use with storage operations.
757
+ * @param nodeIdentity The node identity to use with storage operations.
512
758
  * @returns Nothing.
513
759
  */
514
- async remove(id) {
760
+ async remove(id, userIdentity, nodeIdentity) {
515
761
  core.Urn.guard(this.CLASS_NAME, "id", id);
762
+ if (this._includeUserIdentity) {
763
+ core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
764
+ }
765
+ if (this._includeNodeIdentity || core.Is.notEmpty(this._vaultConnector)) {
766
+ core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
767
+ }
516
768
  try {
517
769
  const blobStorageConnector = this.getConnector(id);
770
+ const conditions = [];
771
+ if (this._includeUserIdentity) {
772
+ conditions.push({ property: "userIdentity", value: userIdentity });
773
+ }
774
+ if (this._includeNodeIdentity) {
775
+ conditions.push({ property: "nodeIdentity", value: nodeIdentity });
776
+ }
777
+ await this._entryEntityStorage.remove(id, conditions);
518
778
  const removed = await blobStorageConnector.remove(id);
519
779
  if (!removed) {
520
780
  throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
521
781
  }
522
- await this._metadataEntityStorage.remove(id);
523
782
  }
524
783
  catch (error) {
525
784
  throw new core.GeneralError(this.CLASS_NAME, "removeFailed", undefined, error);
526
785
  }
527
786
  }
787
+ /**
788
+ * Query all the blob storage entries which match the conditions.
789
+ * @param conditions The conditions to match for the entries.
790
+ * @param orderBy The order for the results, defaults to created.
791
+ * @param orderByDirection The direction for the order, defaults to descending.
792
+ * @param cursor The cursor to request the next page of entries.
793
+ * @param pageSize The suggested number of entries to return in each chunk, in some scenarios can return a different amount.
794
+ * @param userIdentity The user identity to use with storage operations.
795
+ * @param nodeIdentity The node identity to use with storage operations.
796
+ * @returns All the entries for the storage matching the conditions,
797
+ * and a cursor which can be used to request more entities.
798
+ */
799
+ async query(conditions, orderBy, orderByDirection, cursor, pageSize, userIdentity, nodeIdentity) {
800
+ const finalConditions = {
801
+ conditions: [],
802
+ logicalOperator: entity.LogicalOperator.And
803
+ };
804
+ if (this._includeNodeIdentity) {
805
+ core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
806
+ finalConditions.conditions.push({
807
+ property: "nodeIdentity",
808
+ comparison: entity.ComparisonOperator.Equals,
809
+ value: nodeIdentity
810
+ });
811
+ }
812
+ if (this._includeUserIdentity) {
813
+ core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
814
+ finalConditions.conditions.push({
815
+ property: "userIdentity",
816
+ comparison: entity.ComparisonOperator.Equals,
817
+ value: userIdentity
818
+ });
819
+ }
820
+ if (!core.Is.empty(conditions)) {
821
+ finalConditions.conditions.push(conditions);
822
+ }
823
+ const orderProperty = orderBy ?? "dateCreated";
824
+ const orderDirection = orderByDirection ?? entity.SortDirection.Descending;
825
+ const result = await this._entryEntityStorage.query(finalConditions.conditions.length > 0 ? finalConditions : undefined, [
826
+ {
827
+ property: orderProperty,
828
+ sortDirection: orderDirection
829
+ }
830
+ ], undefined, cursor, pageSize);
831
+ for (const entity of result.entities) {
832
+ core.ObjectHelper.propertyDelete(entity, "nodeIdentity");
833
+ core.ObjectHelper.propertyDelete(entity, "userIdentity");
834
+ }
835
+ let context = [
836
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot,
837
+ blobStorageModels.BlobStorageContexts.ContextRoot,
838
+ blobStorageModels.BlobStorageContexts.ContextRootCommon
839
+ ];
840
+ const entriesJsonLd = [];
841
+ for (const entry of result.entities) {
842
+ // The entries are never Partial as we don't allow custom property requests.
843
+ entriesJsonLd.push(this.entryToJsonLd(entry));
844
+ context = dataJsonLd.JsonLdProcessor.combineContexts(context, entry.metadata?.["@context"]);
845
+ }
846
+ const jsonLd = {
847
+ "@context": context,
848
+ type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
849
+ [standardsSchemaOrg.SchemaOrgTypes.ItemListElement]: entriesJsonLd,
850
+ [standardsSchemaOrg.SchemaOrgTypes.NextItem]: result.cursor
851
+ };
852
+ return dataJsonLd.JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
853
+ }
528
854
  /**
529
855
  * Get the connector from the uri.
530
856
  * @param id The id of the blob storage item in urn format.
@@ -541,53 +867,190 @@ class BlobStorageService {
541
867
  }
542
868
  return blobStorageModels.BlobStorageConnectorFactory.get(idUri.namespaceMethod());
543
869
  }
870
+ /**
871
+ * Get an entity.
872
+ * @param id The id of the entity to get, or the index value if secondaryIndex is set.
873
+ * @param secondaryIndex Get the item using a secondary index.
874
+ * @param userIdentity The user identity to use with storage operations.
875
+ * @param nodeIdentity The node identity to use with storage operations.
876
+ * @returns The object if it can be found or throws.
877
+ * @internal
878
+ */
879
+ async internalGet(id, userIdentity, nodeIdentity) {
880
+ const conditions = [];
881
+ if (this._includeUserIdentity) {
882
+ core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
883
+ conditions.push({
884
+ property: "userIdentity",
885
+ comparison: entity.ComparisonOperator.Equals,
886
+ value: userIdentity
887
+ });
888
+ }
889
+ if (this._includeNodeIdentity) {
890
+ core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
891
+ conditions.push({
892
+ property: "nodeIdentity",
893
+ comparison: entity.ComparisonOperator.Equals,
894
+ value: nodeIdentity
895
+ });
896
+ }
897
+ let entity$1;
898
+ if (conditions.length === 0) {
899
+ entity$1 = await this._entryEntityStorage.get(id);
900
+ }
901
+ else {
902
+ const schema = this._entryEntityStorage.getSchema();
903
+ const primaryKey = entity.EntitySchemaHelper.getPrimaryKey(schema);
904
+ conditions.unshift({
905
+ property: primaryKey.property,
906
+ comparison: entity.ComparisonOperator.Equals,
907
+ value: id
908
+ });
909
+ const results = await this._entryEntityStorage.query({
910
+ conditions,
911
+ logicalOperator: entity.LogicalOperator.And
912
+ }, undefined, undefined, undefined, 1);
913
+ entity$1 = results.entities[0];
914
+ }
915
+ if (core.Is.empty(entity$1)) {
916
+ throw new core.NotFoundError(this.CLASS_NAME, "entityNotFound", id);
917
+ }
918
+ core.ObjectHelper.propertyDelete(entity$1, "nodeIdentity");
919
+ core.ObjectHelper.propertyDelete(entity$1, "userIdentity");
920
+ return entity$1;
921
+ }
922
+ /**
923
+ * Convert the entry to JSON-LD.
924
+ * @param entry The entry to convert.
925
+ * @param blob The optional blob to return.
926
+ * @returns The JSON-LD representation of the entry.
927
+ * @internal
928
+ */
929
+ entryToJsonLd(entry, blob) {
930
+ const jsonLd = {
931
+ "@context": dataJsonLd.JsonLdProcessor.combineContexts([
932
+ blobStorageModels.BlobStorageContexts.ContextRoot,
933
+ blobStorageModels.BlobStorageContexts.ContextRootCommon,
934
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot
935
+ ], entry?.metadata?.["@context"]),
936
+ id: entry.id,
937
+ type: blobStorageModels.BlobStorageTypes.Entry,
938
+ dateCreated: entry.dateCreated,
939
+ dateModified: entry.dateModified,
940
+ blobSize: entry.blobSize,
941
+ blobHash: entry.blobHash,
942
+ encodingFormat: entry?.encodingFormat,
943
+ fileExtension: entry?.fileExtension,
944
+ metadata: entry?.metadata,
945
+ blob: core.Is.uint8Array(blob) ? core.Converter.bytesToBase64(blob) : undefined
946
+ };
947
+ return jsonLd;
948
+ }
544
949
  }
545
950
 
546
951
  /**
547
- * Class representing metadata for the blob storage.
952
+ * Class representing entry for the blob storage.
548
953
  */
549
- exports.BlobMetadata = class BlobMetadata {
954
+ exports.BlobStorageEntry = class BlobStorageEntry {
550
955
  /**
551
956
  * The id for the blob.
552
957
  */
553
958
  id;
959
+ /**
960
+ * The date/time when the entry was created.
961
+ */
962
+ dateCreated;
963
+ /**
964
+ * The date/time when the entry was modified.
965
+ */
966
+ dateModified;
967
+ /**
968
+ * The length of the data in the blob.
969
+ */
970
+ blobSize;
971
+ /**
972
+ * The hash of the data in the blob.
973
+ */
974
+ blobHash;
554
975
  /**
555
976
  * The mime type for the blob.
556
977
  */
557
- mimeType;
978
+ encodingFormat;
558
979
  /**
559
980
  * The extension.
560
981
  */
561
- extension;
982
+ fileExtension;
562
983
  /**
563
984
  * The metadata for the blob as JSON-LD.
564
985
  */
565
986
  metadata;
987
+ /**
988
+ * The user identity that created the blob.
989
+ */
990
+ userIdentity;
991
+ /**
992
+ * The node identity that created the blob.
993
+ */
994
+ nodeIdentity;
566
995
  };
567
996
  __decorate([
568
997
  entity.property({ type: "string", isPrimary: true }),
569
998
  __metadata("design:type", String)
570
- ], exports.BlobMetadata.prototype, "id", void 0);
999
+ ], exports.BlobStorageEntry.prototype, "id", void 0);
571
1000
  __decorate([
572
- entity.property({ type: "string" }),
1001
+ entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
1002
+ __metadata("design:type", String)
1003
+ ], exports.BlobStorageEntry.prototype, "dateCreated", void 0);
1004
+ __decorate([
1005
+ entity.property({
1006
+ type: "string",
1007
+ format: "date-time",
1008
+ sortDirection: entity.SortDirection.Descending,
1009
+ optional: true
1010
+ }),
573
1011
  __metadata("design:type", String)
574
- ], exports.BlobMetadata.prototype, "mimeType", void 0);
1012
+ ], exports.BlobStorageEntry.prototype, "dateModified", void 0);
1013
+ __decorate([
1014
+ entity.property({ type: "number" }),
1015
+ __metadata("design:type", Number)
1016
+ ], exports.BlobStorageEntry.prototype, "blobSize", void 0);
575
1017
  __decorate([
576
1018
  entity.property({ type: "string" }),
577
1019
  __metadata("design:type", String)
578
- ], exports.BlobMetadata.prototype, "extension", void 0);
1020
+ ], exports.BlobStorageEntry.prototype, "blobHash", void 0);
579
1021
  __decorate([
580
- entity.property({ type: "object", itemTypeRef: "IJsonLdNodeObject" }),
1022
+ entity.property({ type: "string", optional: true }),
1023
+ __metadata("design:type", String)
1024
+ ], exports.BlobStorageEntry.prototype, "encodingFormat", void 0);
1025
+ __decorate([
1026
+ entity.property({ type: "string", optional: true }),
1027
+ __metadata("design:type", String)
1028
+ ], exports.BlobStorageEntry.prototype, "fileExtension", void 0);
1029
+ __decorate([
1030
+ entity.property({ type: "object", itemTypeRef: "IJsonLdNodeObject", optional: true }),
581
1031
  __metadata("design:type", Object)
582
- ], exports.BlobMetadata.prototype, "metadata", void 0);
583
- exports.BlobMetadata = __decorate([
1032
+ ], exports.BlobStorageEntry.prototype, "metadata", void 0);
1033
+ __decorate([
1034
+ entity.property({ type: "string", optional: true }),
1035
+ __metadata("design:type", String)
1036
+ ], exports.BlobStorageEntry.prototype, "userIdentity", void 0);
1037
+ __decorate([
1038
+ entity.property({ type: "string", optional: true }),
1039
+ __metadata("design:type", String)
1040
+ ], exports.BlobStorageEntry.prototype, "nodeIdentity", void 0);
1041
+ exports.BlobStorageEntry = __decorate([
584
1042
  entity.entity()
585
- ], exports.BlobMetadata);
1043
+ ], exports.BlobStorageEntry);
586
1044
 
1045
+ /**
1046
+ * These are dummy entry points for the blob storage service.
1047
+ * In reality your application would create its own entry points based on the
1048
+ * blob types it wants to store, using a custom defaultBaseRoute.
1049
+ */
587
1050
  const restEntryPoints = [
588
1051
  {
589
- name: "blobStorage",
590
- defaultBaseRoute: "blob",
1052
+ name: "blob-storage",
1053
+ defaultBaseRoute: "blob-storage",
591
1054
  tags: tagsBlobStorage,
592
1055
  generateRoutes: generateRestRoutesBlobStorage
593
1056
  }
@@ -599,13 +1062,14 @@ const restEntryPoints = [
599
1062
  * Initialize the schema for the blob storage entities.
600
1063
  */
601
1064
  function initSchema() {
602
- entity.EntitySchemaFactory.register("BlobMetadata", () => entity.EntitySchemaHelper.getSchema(exports.BlobMetadata));
1065
+ entity.EntitySchemaFactory.register("BlobStorageEntry", () => entity.EntitySchemaHelper.getSchema(exports.BlobStorageEntry));
603
1066
  }
604
1067
 
605
1068
  exports.BlobStorageService = BlobStorageService;
606
1069
  exports.blobStorageCreate = blobStorageCreate;
607
1070
  exports.blobStorageGet = blobStorageGet;
608
1071
  exports.blobStorageGetContent = blobStorageGetContent;
1072
+ exports.blobStorageList = blobStorageList;
609
1073
  exports.blobStorageRemove = blobStorageRemove;
610
1074
  exports.blobStorageUpdate = blobStorageUpdate;
611
1075
  exports.generateRestRoutesBlobStorage = generateRestRoutesBlobStorage;