@twin.org/blob-storage-service 0.0.1-next.9 → 0.0.1
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.
- package/dist/cjs/index.cjs +472 -97
- package/dist/esm/index.mjs +475 -101
- package/dist/types/blobStorageRoutes.d.ts +10 -2
- package/dist/types/blobStorageService.d.ts +46 -28
- package/dist/types/entities/blobStorageEntry.d.ts +55 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/models/IBlobStorageServiceConfig.d.ts +1 -2
- package/dist/types/models/IBlobStorageServiceConstructorOptions.d.ts +19 -0
- package/docs/changelog.md +161 -1
- package/docs/open-api/spec.json +1230 -1853
- package/docs/reference/classes/BlobStorageEntry.md +109 -0
- package/docs/reference/classes/BlobStorageService.md +170 -55
- package/docs/reference/functions/blobStorageCreate.md +9 -3
- package/docs/reference/functions/blobStorageGet.md +9 -3
- package/docs/reference/functions/blobStorageGetContent.md +9 -3
- package/docs/reference/functions/blobStorageList.md +31 -0
- package/docs/reference/functions/blobStorageRemove.md +9 -3
- package/docs/reference/functions/blobStorageUpdate.md +9 -3
- package/docs/reference/functions/generateRestRoutesBlobStorage.md +15 -7
- package/docs/reference/index.md +3 -1
- package/docs/reference/interfaces/IBlobStorageServiceConfig.md +1 -7
- package/docs/reference/interfaces/IBlobStorageServiceConstructorOptions.md +33 -0
- package/locales/en.json +2 -1
- package/package.json +15 -13
- package/dist/types/entities/blobMetadata.d.ts +0 -30
- package/docs/reference/classes/BlobMetadata.md +0 -61
package/dist/cjs/index.cjs
CHANGED
|
@@ -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
|
|
8
|
+
var crypto = require('@twin.org/crypto');
|
|
6
9
|
var dataJsonLd = require('@twin.org/data-json-ld');
|
|
7
10
|
var entity = require('@twin.org/entity');
|
|
8
11
|
var entityStorageModels = require('@twin.org/entity-storage-models');
|
|
9
12
|
var vaultModels = require('@twin.org/vault-models');
|
|
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
|
*/
|
|
@@ -50,7 +55,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
50
55
|
body: {
|
|
51
56
|
blob: "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==",
|
|
52
57
|
metadata: {
|
|
53
|
-
"@context": "
|
|
58
|
+
"@context": "https://schema.org",
|
|
54
59
|
"@type": "DigitalDocument",
|
|
55
60
|
name: "myfile.pdf"
|
|
56
61
|
}
|
|
@@ -93,7 +98,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
93
98
|
id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
|
|
94
99
|
},
|
|
95
100
|
query: {
|
|
96
|
-
includeContent: true
|
|
101
|
+
includeContent: "true"
|
|
97
102
|
}
|
|
98
103
|
}
|
|
99
104
|
}
|
|
@@ -107,8 +112,51 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
107
112
|
id: `${camelTypeName}GetResponseExample`,
|
|
108
113
|
response: {
|
|
109
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",
|
|
110
127
|
metadata: {
|
|
111
|
-
"@context": "
|
|
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",
|
|
112
160
|
"@type": "DigitalDocument",
|
|
113
161
|
name: "myfile.pdf"
|
|
114
162
|
},
|
|
@@ -140,7 +188,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
140
188
|
id: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70"
|
|
141
189
|
},
|
|
142
190
|
query: {
|
|
143
|
-
download: true,
|
|
191
|
+
download: "true",
|
|
144
192
|
filename: "my-file.pdf"
|
|
145
193
|
}
|
|
146
194
|
}
|
|
@@ -154,7 +202,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
154
202
|
examples: [
|
|
155
203
|
{
|
|
156
204
|
id: `${camelTypeName}GetContentResponseExample`,
|
|
157
|
-
description: `The content of the blob, which will be a specific mime type if one can be detected from the content (or set as
|
|
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}.`,
|
|
158
206
|
response: {
|
|
159
207
|
body: new Uint8Array()
|
|
160
208
|
}
|
|
@@ -184,7 +232,7 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
184
232
|
},
|
|
185
233
|
body: {
|
|
186
234
|
metadata: {
|
|
187
|
-
"@context": "
|
|
235
|
+
"@context": "https://schema.org",
|
|
188
236
|
"@type": "DigitalDocument",
|
|
189
237
|
name: "myfile.pdf"
|
|
190
238
|
}
|
|
@@ -228,12 +276,116 @@ function generateRestRoutesBlobStorage(baseRouteName, componentName, options) {
|
|
|
228
276
|
}
|
|
229
277
|
]
|
|
230
278
|
};
|
|
279
|
+
const blobStorageListRoute = {
|
|
280
|
+
operationId: `${camelTypeName}Query`,
|
|
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
|
+
};
|
|
231
382
|
return [
|
|
232
383
|
blobStorageCreateRoute,
|
|
233
384
|
blobStorageGetRoute,
|
|
234
385
|
blobStorageGetContentRoute,
|
|
235
386
|
blobStorageUpdateRoute,
|
|
236
|
-
blobStorageRemoveRoute
|
|
387
|
+
blobStorageRemoveRoute,
|
|
388
|
+
blobStorageListRoute
|
|
237
389
|
];
|
|
238
390
|
}
|
|
239
391
|
/**
|
|
@@ -248,7 +400,11 @@ async function blobStorageCreate(httpRequestContext, componentName, request) {
|
|
|
248
400
|
core.Guards.object(ROUTES_SOURCE, "request.body", request.body);
|
|
249
401
|
core.Guards.stringBase64(ROUTES_SOURCE, "request.body.blob", request.body.blob);
|
|
250
402
|
const component = core.ComponentFactory.get(componentName);
|
|
251
|
-
const id = await component.create(request.body.blob, request.body.
|
|
403
|
+
const id = await component.create(request.body.blob, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, {
|
|
404
|
+
disableEncryption: request.body.disableEncryption,
|
|
405
|
+
overrideVaultKeyId: request.body.overrideVaultKeyId,
|
|
406
|
+
namespace: request.body.namespace
|
|
407
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
252
408
|
return {
|
|
253
409
|
statusCode: web.HttpStatusCode.created,
|
|
254
410
|
headers: {
|
|
@@ -267,9 +423,17 @@ async function blobStorageGet(httpRequestContext, componentName, request) {
|
|
|
267
423
|
core.Guards.object(ROUTES_SOURCE, "request", request);
|
|
268
424
|
core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
269
425
|
core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
426
|
+
const mimeType = request.headers?.[web.HeaderTypes.Accept] === web.MimeTypes.JsonLd ? "jsonld" : "json";
|
|
270
427
|
const component = core.ComponentFactory.get(componentName);
|
|
271
|
-
const result = await component.get(request.pathParams.id,
|
|
428
|
+
const result = await component.get(request.pathParams.id, {
|
|
429
|
+
includeContent: core.Coerce.boolean(request.query?.includeContent),
|
|
430
|
+
decompress: core.Coerce.boolean(request.query?.decompress),
|
|
431
|
+
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
432
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
272
433
|
return {
|
|
434
|
+
headers: {
|
|
435
|
+
[web.HeaderTypes.ContentType]: mimeType === "json" ? web.MimeTypes.Json : web.MimeTypes.JsonLd
|
|
436
|
+
},
|
|
273
437
|
body: result
|
|
274
438
|
};
|
|
275
439
|
}
|
|
@@ -285,18 +449,34 @@ async function blobStorageGetContent(httpRequestContext, componentName, request)
|
|
|
285
449
|
core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
286
450
|
core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
287
451
|
const component = core.ComponentFactory.get(componentName);
|
|
288
|
-
const
|
|
289
|
-
const
|
|
452
|
+
const decompress = core.Coerce.boolean(request.query?.decompress);
|
|
453
|
+
const download = core.Coerce.boolean(request.query?.download) ?? false;
|
|
454
|
+
const result = await component.get(request.pathParams.id, {
|
|
455
|
+
includeContent: true,
|
|
456
|
+
decompress,
|
|
457
|
+
overrideVaultKeyId: request.query?.overrideVaultKeyId
|
|
458
|
+
}, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
459
|
+
const encodingFormat = result?.encodingFormat ?? web.MimeTypes.OctetStream;
|
|
460
|
+
let compressedEncodingFormat;
|
|
461
|
+
let compressedExtension = "";
|
|
462
|
+
// If the entry is compressed and we are not decompressing
|
|
463
|
+
// we need to override the encoding format to the compressed type
|
|
464
|
+
// and append an additional extension to the filename.
|
|
465
|
+
if (result.compression && !decompress) {
|
|
466
|
+
compressedEncodingFormat =
|
|
467
|
+
result.compression === blobStorageModels.BlobStorageCompressionType.Gzip ? web.MimeTypes.Gzip : web.MimeTypes.Zlib;
|
|
468
|
+
compressedExtension = `.${web.MimeTypeHelper.defaultExtension(compressedEncodingFormat)}`;
|
|
469
|
+
}
|
|
290
470
|
let filename = request.query?.filename;
|
|
291
471
|
if (!core.Is.stringValue(filename)) {
|
|
292
|
-
filename = `file.${result.
|
|
472
|
+
filename = `file.${result.fileExtension ?? web.MimeTypeHelper.defaultExtension(encodingFormat)}${compressedExtension}`;
|
|
293
473
|
}
|
|
294
474
|
return {
|
|
295
475
|
body: core.Is.stringBase64(result.blob) ? core.Converter.base64ToBytes(result.blob) : new Uint8Array(),
|
|
296
476
|
attachment: {
|
|
297
|
-
mimeType,
|
|
477
|
+
mimeType: compressedEncodingFormat ?? encodingFormat,
|
|
298
478
|
filename,
|
|
299
|
-
inline: !
|
|
479
|
+
inline: !download
|
|
300
480
|
}
|
|
301
481
|
};
|
|
302
482
|
}
|
|
@@ -312,7 +492,7 @@ async function blobStorageUpdate(httpRequestContext, componentName, request) {
|
|
|
312
492
|
core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
313
493
|
core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.id", request.pathParams.id);
|
|
314
494
|
const component = core.ComponentFactory.get(componentName);
|
|
315
|
-
await component.update(request.pathParams.id, request.body.
|
|
495
|
+
await component.update(request.pathParams.id, request.body.encodingFormat, request.body.fileExtension, request.body.metadata, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
|
|
316
496
|
return {
|
|
317
497
|
statusCode: web.HttpStatusCode.noContent
|
|
318
498
|
};
|
|
@@ -334,6 +514,25 @@ async function blobStorageRemove(httpRequestContext, componentName, request) {
|
|
|
334
514
|
statusCode: web.HttpStatusCode.noContent
|
|
335
515
|
};
|
|
336
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* List the entries from blob storage.
|
|
519
|
+
* @param httpRequestContext The request context for the API.
|
|
520
|
+
* @param componentName The name of the component to use in the routes.
|
|
521
|
+
* @param request The request.
|
|
522
|
+
* @returns The response object with additional http response properties.
|
|
523
|
+
*/
|
|
524
|
+
async function blobStorageList(httpRequestContext, componentName, request) {
|
|
525
|
+
core.Guards.object(ROUTES_SOURCE, "request", request);
|
|
526
|
+
const mimeType = request.headers?.[web.HeaderTypes.Accept] === web.MimeTypes.JsonLd ? "jsonld" : "json";
|
|
527
|
+
const component = core.ComponentFactory.get(componentName);
|
|
528
|
+
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);
|
|
529
|
+
return {
|
|
530
|
+
headers: {
|
|
531
|
+
[web.HeaderTypes.ContentType]: mimeType === "json" ? web.MimeTypes.Json : web.MimeTypes.JsonLd
|
|
532
|
+
},
|
|
533
|
+
body: result
|
|
534
|
+
};
|
|
535
|
+
}
|
|
337
536
|
|
|
338
537
|
// Copyright 2024 IOTA Stiftung.
|
|
339
538
|
// SPDX-License-Identifier: Apache-2.0.
|
|
@@ -359,7 +558,7 @@ class BlobStorageService {
|
|
|
359
558
|
* The storage connector for the metadata.
|
|
360
559
|
* @internal
|
|
361
560
|
*/
|
|
362
|
-
|
|
561
|
+
_entryEntityStorage;
|
|
363
562
|
/**
|
|
364
563
|
* The vault connector for the encryption, can be undefined if no encryption required.
|
|
365
564
|
* @internal
|
|
@@ -382,86 +581,104 @@ class BlobStorageService {
|
|
|
382
581
|
_includeUserIdentity;
|
|
383
582
|
/**
|
|
384
583
|
* Create a new instance of BlobStorageService.
|
|
385
|
-
* @param options The
|
|
386
|
-
* @param options.metadataEntityStorageType The type of the storage connector for the metadata, defaults to "blob-metadata".
|
|
387
|
-
* @param options.vaultConnectorType The type of the vault connector for encryption, if undefined no encryption will be performed.
|
|
388
|
-
* @param options.config The configuration for the service.
|
|
584
|
+
* @param options The options for the service.
|
|
389
585
|
*/
|
|
390
586
|
constructor(options) {
|
|
391
587
|
const names = blobStorageModels.BlobStorageConnectorFactory.names();
|
|
392
588
|
if (names.length === 0) {
|
|
393
589
|
throw new core.GeneralError(this.CLASS_NAME, "noConnectors");
|
|
394
590
|
}
|
|
395
|
-
this.
|
|
591
|
+
this._entryEntityStorage = entityStorageModels.EntityStorageConnectorFactory.get(options?.entryEntityStorageType ?? "blob-storage-entry");
|
|
396
592
|
if (core.Is.stringValue(options?.vaultConnectorType)) {
|
|
397
|
-
this._vaultConnector = vaultModels.VaultConnectorFactory.
|
|
593
|
+
this._vaultConnector = vaultModels.VaultConnectorFactory.get(options.vaultConnectorType);
|
|
398
594
|
}
|
|
399
595
|
this._defaultNamespace = options?.config?.defaultNamespace ?? names[0];
|
|
400
|
-
this._vaultKeyId = options?.config?.vaultKeyId
|
|
596
|
+
this._vaultKeyId = options?.config?.vaultKeyId;
|
|
401
597
|
this._includeNodeIdentity = options?.config?.includeNodeIdentity ?? true;
|
|
402
598
|
this._includeUserIdentity = options?.config?.includeUserIdentity ?? true;
|
|
599
|
+
standardsSchemaOrg.SchemaOrgDataTypes.registerRedirects();
|
|
403
600
|
}
|
|
404
601
|
/**
|
|
405
602
|
* Create the blob with some metadata.
|
|
406
603
|
* @param blob The data for the blob in base64 format.
|
|
407
|
-
* @param
|
|
408
|
-
* @param
|
|
604
|
+
* @param encodingFormat Mime type for the blob, will be detected if left undefined.
|
|
605
|
+
* @param fileExtension Extension for the blob, will be detected if left undefined.
|
|
409
606
|
* @param metadata Data for the custom metadata as JSON-LD.
|
|
410
|
-
* @param
|
|
607
|
+
* @param options Optional options for the creation of the blob.
|
|
608
|
+
* @param options.disableEncryption Disables encryption if enabled by default.
|
|
609
|
+
* @param options.overrideVaultKeyId Use a different vault key id for encryption, if not provided the default vault key id will be used.
|
|
610
|
+
* @param options.compress Optional compression type to use for the blob, defaults to no compression.*
|
|
611
|
+
* @param options.namespace The namespace to use for storing, defaults to component configured namespace.
|
|
411
612
|
* @param userIdentity The user identity to use with storage operations.
|
|
412
613
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
413
614
|
* @returns The id of the stored blob in urn format.
|
|
414
615
|
*/
|
|
415
|
-
async create(blob,
|
|
616
|
+
async create(blob, encodingFormat, fileExtension, metadata, options, userIdentity, nodeIdentity) {
|
|
416
617
|
core.Guards.stringBase64(this.CLASS_NAME, "blob", blob);
|
|
417
618
|
if (this._includeUserIdentity) {
|
|
418
619
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
419
620
|
}
|
|
420
|
-
|
|
621
|
+
const disableEncryption = options?.disableEncryption ?? false;
|
|
622
|
+
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
623
|
+
const encryptionEnabled = !disableEncryption && core.Is.stringValue(vaultKeyId);
|
|
624
|
+
if (this._includeNodeIdentity || encryptionEnabled) {
|
|
421
625
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
422
626
|
}
|
|
423
627
|
try {
|
|
424
|
-
const connectorNamespace = namespace ?? this._defaultNamespace;
|
|
628
|
+
const connectorNamespace = options?.namespace ?? this._defaultNamespace;
|
|
425
629
|
const blobStorageConnector = blobStorageModels.BlobStorageConnectorFactory.get(connectorNamespace);
|
|
426
630
|
// Convert the base64 data into bytes
|
|
427
631
|
let storeBlob = core.Converter.base64ToBytes(blob);
|
|
632
|
+
const blobSize = storeBlob.length;
|
|
428
633
|
// See if we can detect the mime type and default extension for the data.
|
|
429
634
|
// If not already supplied by the caller. We have to perform this operation
|
|
430
635
|
// on the unencrypted data.
|
|
431
|
-
if (!core.Is.stringValue(
|
|
432
|
-
|
|
636
|
+
if (!core.Is.stringValue(encodingFormat)) {
|
|
637
|
+
encodingFormat = await web.MimeTypeHelper.detect(storeBlob);
|
|
433
638
|
}
|
|
434
|
-
if (!core.Is.stringValue(
|
|
435
|
-
|
|
639
|
+
if (!core.Is.stringValue(fileExtension) && core.Is.stringValue(encodingFormat)) {
|
|
640
|
+
fileExtension = await web.MimeTypeHelper.defaultExtension(encodingFormat);
|
|
436
641
|
}
|
|
437
642
|
if (core.Is.object(metadata)) {
|
|
438
643
|
const validationFailures = [];
|
|
439
644
|
dataJsonLd.JsonLdHelper.validate(metadata, validationFailures);
|
|
440
645
|
core.Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
|
|
441
646
|
}
|
|
647
|
+
const blobHash = `sha256:${core.Converter.bytesToBase64(crypto.Sha256.sum256(storeBlob))}`;
|
|
648
|
+
if (!core.Is.empty(options?.compress)) {
|
|
649
|
+
storeBlob = await core.Compression.compress(storeBlob, options.compress);
|
|
650
|
+
}
|
|
442
651
|
// If we have a vault connector then encrypt the data.
|
|
443
|
-
if (
|
|
444
|
-
|
|
652
|
+
if (encryptionEnabled) {
|
|
653
|
+
if (core.Is.empty(this._vaultConnector)) {
|
|
654
|
+
throw new core.GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
655
|
+
}
|
|
656
|
+
storeBlob = await this._vaultConnector.encrypt(`${nodeIdentity}/${vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, storeBlob);
|
|
445
657
|
}
|
|
446
658
|
// Set the blob in the storage connector, which may now be encrypted
|
|
447
659
|
const blobId = await blobStorageConnector.set(storeBlob);
|
|
448
|
-
// Now store the
|
|
449
|
-
const
|
|
660
|
+
// Now store the entry in entity storage
|
|
661
|
+
const blobEntry = {
|
|
450
662
|
id: blobId,
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
663
|
+
dateCreated: new Date(Date.now()).toISOString(),
|
|
664
|
+
blobSize,
|
|
665
|
+
blobHash,
|
|
666
|
+
encodingFormat,
|
|
667
|
+
fileExtension,
|
|
668
|
+
metadata,
|
|
669
|
+
isEncrypted: encryptionEnabled,
|
|
670
|
+
compression: options?.compress
|
|
454
671
|
};
|
|
455
672
|
const conditions = [];
|
|
456
673
|
if (this._includeUserIdentity) {
|
|
457
|
-
core.ObjectHelper.propertySet(
|
|
674
|
+
core.ObjectHelper.propertySet(blobEntry, "userIdentity", userIdentity);
|
|
458
675
|
conditions.push({ property: "userIdentity", value: userIdentity });
|
|
459
676
|
}
|
|
460
677
|
if (this._includeNodeIdentity) {
|
|
461
|
-
core.ObjectHelper.propertySet(
|
|
678
|
+
core.ObjectHelper.propertySet(blobEntry, "nodeIdentity", nodeIdentity);
|
|
462
679
|
conditions.push({ property: "nodeIdentity", value: nodeIdentity });
|
|
463
680
|
}
|
|
464
|
-
await this.
|
|
681
|
+
await this._entryEntityStorage.set(blobEntry, conditions);
|
|
465
682
|
return blobId;
|
|
466
683
|
}
|
|
467
684
|
catch (error) {
|
|
@@ -469,16 +686,21 @@ class BlobStorageService {
|
|
|
469
686
|
}
|
|
470
687
|
}
|
|
471
688
|
/**
|
|
472
|
-
* Get the blob
|
|
689
|
+
* Get the blob entry.
|
|
473
690
|
* @param id The id of the blob to get in urn format.
|
|
474
|
-
* @param
|
|
691
|
+
* @param options Optional options for the retrieval of the blob.
|
|
692
|
+
* @param options.includeContent Include the content, or just get the metadata.
|
|
693
|
+
* @param options.overrideVaultKeyId Use a different vault key id for decryption, if not provided the default vault key id will be used.
|
|
694
|
+
* @param options.decompress If the content should be decompressed, if it was compressed when stored, defaults to true.
|
|
475
695
|
* @param userIdentity The user identity to use with storage operations.
|
|
476
696
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
477
|
-
* @returns The
|
|
697
|
+
* @returns The entry and data for the blob if it can be found.
|
|
478
698
|
* @throws Not found error if the blob cannot be found.
|
|
479
699
|
*/
|
|
480
|
-
async get(id,
|
|
700
|
+
async get(id, options, userIdentity, nodeIdentity) {
|
|
481
701
|
core.Urn.guard(this.CLASS_NAME, "id", id);
|
|
702
|
+
const includeContent = options?.includeContent ?? false;
|
|
703
|
+
const vaultKeyId = options?.overrideVaultKeyId ?? this._vaultKeyId;
|
|
482
704
|
const conditions = [];
|
|
483
705
|
if (this._includeUserIdentity) {
|
|
484
706
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
@@ -497,7 +719,7 @@ class BlobStorageService {
|
|
|
497
719
|
});
|
|
498
720
|
}
|
|
499
721
|
try {
|
|
500
|
-
const
|
|
722
|
+
const blobEntry = await this.internalGet(id, userIdentity, nodeIdentity);
|
|
501
723
|
let returnBlob;
|
|
502
724
|
if (includeContent) {
|
|
503
725
|
const blobStorageConnector = this.getConnector(id);
|
|
@@ -505,17 +727,20 @@ class BlobStorageService {
|
|
|
505
727
|
if (core.Is.undefined(returnBlob)) {
|
|
506
728
|
throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
507
729
|
}
|
|
508
|
-
// If
|
|
509
|
-
|
|
510
|
-
|
|
730
|
+
// If the data is encrypted then decrypt it.
|
|
731
|
+
const decryptionEnabled = blobEntry.isEncrypted && core.Is.stringValue(vaultKeyId);
|
|
732
|
+
if (decryptionEnabled) {
|
|
733
|
+
if (core.Is.empty(this._vaultConnector)) {
|
|
734
|
+
throw new core.GeneralError(this.CLASS_NAME, "vaultConnectorNotConfigured");
|
|
735
|
+
}
|
|
736
|
+
returnBlob = await this._vaultConnector.decrypt(`${nodeIdentity}/${vaultKeyId}`, vaultModels.VaultEncryptionType.ChaCha20Poly1305, returnBlob);
|
|
737
|
+
}
|
|
738
|
+
if (!core.Is.empty(blobEntry.compression) && (options?.decompress ?? true)) {
|
|
739
|
+
returnBlob = await core.Compression.decompress(returnBlob, blobEntry.compression);
|
|
511
740
|
}
|
|
512
741
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
mimeType: blobMetadata?.mimeType,
|
|
516
|
-
extension: blobMetadata?.extension,
|
|
517
|
-
metadata: blobMetadata?.metadata
|
|
518
|
-
};
|
|
742
|
+
const jsonLd = this.entryToJsonLd(blobEntry, returnBlob);
|
|
743
|
+
return dataJsonLd.JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
|
|
519
744
|
}
|
|
520
745
|
catch (error) {
|
|
521
746
|
throw new core.GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
|
|
@@ -523,16 +748,16 @@ class BlobStorageService {
|
|
|
523
748
|
}
|
|
524
749
|
/**
|
|
525
750
|
* Update the blob with metadata.
|
|
526
|
-
* @param id The id of the blob
|
|
527
|
-
* @param
|
|
528
|
-
* @param
|
|
751
|
+
* @param id The id of the blob entry to update.
|
|
752
|
+
* @param encodingFormat Mime type for the blob, will be detected if left undefined.
|
|
753
|
+
* @param fileExtension Extension for the blob, will be detected if left undefined.
|
|
529
754
|
* @param metadata Data for the custom metadata as JSON-LD.
|
|
530
755
|
* @param userIdentity The user identity to use with storage operations.
|
|
531
756
|
* @param nodeIdentity The node identity to use with storage operations.
|
|
532
757
|
* @returns Nothing.
|
|
533
758
|
* @throws Not found error if the blob cannot be found.
|
|
534
759
|
*/
|
|
535
|
-
async update(id,
|
|
760
|
+
async update(id, encodingFormat, fileExtension, metadata, userIdentity, nodeIdentity) {
|
|
536
761
|
core.Urn.guard(this.CLASS_NAME, "id", id);
|
|
537
762
|
if (this._includeUserIdentity) {
|
|
538
763
|
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
@@ -541,8 +766,8 @@ class BlobStorageService {
|
|
|
541
766
|
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
542
767
|
}
|
|
543
768
|
try {
|
|
544
|
-
const
|
|
545
|
-
if (core.Is.undefined(
|
|
769
|
+
const blobEntry = await this._entryEntityStorage.get(id);
|
|
770
|
+
if (core.Is.undefined(blobEntry)) {
|
|
546
771
|
throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
547
772
|
}
|
|
548
773
|
if (core.Is.object(metadata)) {
|
|
@@ -550,23 +775,29 @@ class BlobStorageService {
|
|
|
550
775
|
await dataJsonLd.JsonLdHelper.validate(metadata, validationFailures);
|
|
551
776
|
core.Validation.asValidationError(this.CLASS_NAME, "metadata", validationFailures);
|
|
552
777
|
}
|
|
553
|
-
// Now store the
|
|
554
|
-
const
|
|
555
|
-
id:
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
778
|
+
// Now store the entry in entity storage
|
|
779
|
+
const updatedBlobEntry = {
|
|
780
|
+
id: blobEntry.id,
|
|
781
|
+
dateCreated: blobEntry.dateCreated,
|
|
782
|
+
dateModified: new Date(Date.now()).toISOString(),
|
|
783
|
+
blobSize: blobEntry.blobSize,
|
|
784
|
+
blobHash: blobEntry.blobHash,
|
|
785
|
+
encodingFormat: encodingFormat ?? blobEntry.encodingFormat,
|
|
786
|
+
fileExtension: fileExtension ?? blobEntry.fileExtension,
|
|
787
|
+
metadata: metadata ?? blobEntry.metadata,
|
|
788
|
+
isEncrypted: blobEntry.isEncrypted,
|
|
789
|
+
compression: blobEntry.compression
|
|
559
790
|
};
|
|
560
791
|
const conditions = [];
|
|
561
792
|
if (this._includeUserIdentity) {
|
|
562
|
-
core.ObjectHelper.propertySet(
|
|
793
|
+
core.ObjectHelper.propertySet(updatedBlobEntry, "userIdentity", userIdentity);
|
|
563
794
|
conditions.push({ property: "userIdentity", value: userIdentity });
|
|
564
795
|
}
|
|
565
796
|
if (this._includeNodeIdentity) {
|
|
566
|
-
core.ObjectHelper.propertySet(
|
|
797
|
+
core.ObjectHelper.propertySet(updatedBlobEntry, "nodeIdentity", nodeIdentity);
|
|
567
798
|
conditions.push({ property: "nodeIdentity", value: nodeIdentity });
|
|
568
799
|
}
|
|
569
|
-
await this.
|
|
800
|
+
await this._entryEntityStorage.set(updatedBlobEntry, conditions);
|
|
570
801
|
}
|
|
571
802
|
catch (error) {
|
|
572
803
|
throw new core.GeneralError(this.CLASS_NAME, "updateFailed", undefined, error);
|
|
@@ -596,7 +827,7 @@ class BlobStorageService {
|
|
|
596
827
|
if (this._includeNodeIdentity) {
|
|
597
828
|
conditions.push({ property: "nodeIdentity", value: nodeIdentity });
|
|
598
829
|
}
|
|
599
|
-
await this.
|
|
830
|
+
await this._entryEntityStorage.remove(id, conditions);
|
|
600
831
|
const removed = await blobStorageConnector.remove(id);
|
|
601
832
|
if (!removed) {
|
|
602
833
|
throw new core.NotFoundError(this.CLASS_NAME, "blobNotFound", id);
|
|
@@ -606,6 +837,69 @@ class BlobStorageService {
|
|
|
606
837
|
throw new core.GeneralError(this.CLASS_NAME, "removeFailed", undefined, error);
|
|
607
838
|
}
|
|
608
839
|
}
|
|
840
|
+
/**
|
|
841
|
+
* Query all the blob storage entries which match the conditions.
|
|
842
|
+
* @param conditions The conditions to match for the entries.
|
|
843
|
+
* @param orderBy The order for the results, defaults to created.
|
|
844
|
+
* @param orderByDirection The direction for the order, defaults to descending.
|
|
845
|
+
* @param cursor The cursor to request the next page of entries.
|
|
846
|
+
* @param pageSize The suggested number of entries to return in each chunk, in some scenarios can return a different amount.
|
|
847
|
+
* @param userIdentity The user identity to use with storage operations.
|
|
848
|
+
* @param nodeIdentity The node identity to use with storage operations.
|
|
849
|
+
* @returns All the entries for the storage matching the conditions,
|
|
850
|
+
* and a cursor which can be used to request more entities.
|
|
851
|
+
*/
|
|
852
|
+
async query(conditions, orderBy, orderByDirection, cursor, pageSize, userIdentity, nodeIdentity) {
|
|
853
|
+
const finalConditions = {
|
|
854
|
+
conditions: [],
|
|
855
|
+
logicalOperator: entity.LogicalOperator.And
|
|
856
|
+
};
|
|
857
|
+
if (this._includeNodeIdentity) {
|
|
858
|
+
core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
|
|
859
|
+
finalConditions.conditions.push({
|
|
860
|
+
property: "nodeIdentity",
|
|
861
|
+
comparison: entity.ComparisonOperator.Equals,
|
|
862
|
+
value: nodeIdentity
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
if (this._includeUserIdentity) {
|
|
866
|
+
core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
|
|
867
|
+
finalConditions.conditions.push({
|
|
868
|
+
property: "userIdentity",
|
|
869
|
+
comparison: entity.ComparisonOperator.Equals,
|
|
870
|
+
value: userIdentity
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
if (!core.Is.empty(conditions)) {
|
|
874
|
+
finalConditions.conditions.push(conditions);
|
|
875
|
+
}
|
|
876
|
+
const orderProperty = orderBy ?? "dateCreated";
|
|
877
|
+
const orderDirection = orderByDirection ?? entity.SortDirection.Descending;
|
|
878
|
+
const result = await this._entryEntityStorage.query(finalConditions.conditions.length > 0 ? finalConditions : undefined, [
|
|
879
|
+
{
|
|
880
|
+
property: orderProperty,
|
|
881
|
+
sortDirection: orderDirection
|
|
882
|
+
}
|
|
883
|
+
], undefined, cursor, pageSize);
|
|
884
|
+
let context = [
|
|
885
|
+
standardsSchemaOrg.SchemaOrgContexts.ContextRoot,
|
|
886
|
+
blobStorageModels.BlobStorageContexts.ContextRoot,
|
|
887
|
+
blobStorageModels.BlobStorageContexts.ContextRootCommon
|
|
888
|
+
];
|
|
889
|
+
const entriesJsonLd = [];
|
|
890
|
+
for (const entry of result.entities) {
|
|
891
|
+
// The entries are never Partial as we don't allow custom property requests.
|
|
892
|
+
entriesJsonLd.push(this.entryToJsonLd(entry));
|
|
893
|
+
context = dataJsonLd.JsonLdProcessor.combineContexts(context, entry.metadata?.["@context"]);
|
|
894
|
+
}
|
|
895
|
+
const jsonLd = {
|
|
896
|
+
"@context": context,
|
|
897
|
+
type: standardsSchemaOrg.SchemaOrgTypes.ItemList,
|
|
898
|
+
[standardsSchemaOrg.SchemaOrgTypes.ItemListElement]: entriesJsonLd,
|
|
899
|
+
[standardsSchemaOrg.SchemaOrgTypes.NextItem]: result.cursor
|
|
900
|
+
};
|
|
901
|
+
return dataJsonLd.JsonLdProcessor.compact(jsonLd, jsonLd["@context"]);
|
|
902
|
+
}
|
|
609
903
|
/**
|
|
610
904
|
* Get the connector from the uri.
|
|
611
905
|
* @param id The id of the blob storage item in urn format.
|
|
@@ -651,17 +945,17 @@ class BlobStorageService {
|
|
|
651
945
|
}
|
|
652
946
|
let entity$1;
|
|
653
947
|
if (conditions.length === 0) {
|
|
654
|
-
entity$1 = await this.
|
|
948
|
+
entity$1 = await this._entryEntityStorage.get(id);
|
|
655
949
|
}
|
|
656
950
|
else {
|
|
657
|
-
const schema = this.
|
|
951
|
+
const schema = this._entryEntityStorage.getSchema();
|
|
658
952
|
const primaryKey = entity.EntitySchemaHelper.getPrimaryKey(schema);
|
|
659
953
|
conditions.unshift({
|
|
660
954
|
property: primaryKey.property,
|
|
661
955
|
comparison: entity.ComparisonOperator.Equals,
|
|
662
956
|
value: id
|
|
663
957
|
});
|
|
664
|
-
const results = await this.
|
|
958
|
+
const results = await this._entryEntityStorage.query({
|
|
665
959
|
conditions,
|
|
666
960
|
logicalOperator: entity.LogicalOperator.And
|
|
667
961
|
}, undefined, undefined, undefined, 1);
|
|
@@ -670,32 +964,83 @@ class BlobStorageService {
|
|
|
670
964
|
if (core.Is.empty(entity$1)) {
|
|
671
965
|
throw new core.NotFoundError(this.CLASS_NAME, "entityNotFound", id);
|
|
672
966
|
}
|
|
673
|
-
core.ObjectHelper.
|
|
674
|
-
|
|
675
|
-
|
|
967
|
+
return core.ObjectHelper.omit(entity$1, ["nodeIdentity", "userIdentity"]);
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Convert the entry to JSON-LD.
|
|
971
|
+
* @param entry The entry to convert.
|
|
972
|
+
* @param blob The optional blob to return.
|
|
973
|
+
* @returns The JSON-LD representation of the entry.
|
|
974
|
+
* @internal
|
|
975
|
+
*/
|
|
976
|
+
entryToJsonLd(entry, blob) {
|
|
977
|
+
const jsonLd = {
|
|
978
|
+
"@context": dataJsonLd.JsonLdProcessor.combineContexts([
|
|
979
|
+
blobStorageModels.BlobStorageContexts.ContextRoot,
|
|
980
|
+
blobStorageModels.BlobStorageContexts.ContextRootCommon,
|
|
981
|
+
standardsSchemaOrg.SchemaOrgContexts.ContextRoot
|
|
982
|
+
], entry?.metadata?.["@context"]),
|
|
983
|
+
id: entry.id,
|
|
984
|
+
type: blobStorageModels.BlobStorageTypes.Entry,
|
|
985
|
+
dateCreated: entry.dateCreated,
|
|
986
|
+
dateModified: entry.dateModified,
|
|
987
|
+
blobSize: entry.blobSize,
|
|
988
|
+
blobHash: entry.blobHash,
|
|
989
|
+
encodingFormat: entry?.encodingFormat,
|
|
990
|
+
fileExtension: entry?.fileExtension,
|
|
991
|
+
metadata: entry?.metadata,
|
|
992
|
+
blob: core.Is.uint8Array(blob) ? core.Converter.bytesToBase64(blob) : undefined,
|
|
993
|
+
isEncrypted: entry.isEncrypted,
|
|
994
|
+
compression: entry.compression
|
|
995
|
+
};
|
|
996
|
+
return jsonLd;
|
|
676
997
|
}
|
|
677
998
|
}
|
|
678
999
|
|
|
679
1000
|
/**
|
|
680
|
-
* Class representing
|
|
1001
|
+
* Class representing entry for the blob storage.
|
|
681
1002
|
*/
|
|
682
|
-
exports.
|
|
1003
|
+
exports.BlobStorageEntry = class BlobStorageEntry {
|
|
683
1004
|
/**
|
|
684
1005
|
* The id for the blob.
|
|
685
1006
|
*/
|
|
686
1007
|
id;
|
|
1008
|
+
/**
|
|
1009
|
+
* The date/time when the entry was created.
|
|
1010
|
+
*/
|
|
1011
|
+
dateCreated;
|
|
1012
|
+
/**
|
|
1013
|
+
* The date/time when the entry was modified.
|
|
1014
|
+
*/
|
|
1015
|
+
dateModified;
|
|
1016
|
+
/**
|
|
1017
|
+
* The length of the data in the blob.
|
|
1018
|
+
*/
|
|
1019
|
+
blobSize;
|
|
1020
|
+
/**
|
|
1021
|
+
* The hash of the data in the blob.
|
|
1022
|
+
*/
|
|
1023
|
+
blobHash;
|
|
687
1024
|
/**
|
|
688
1025
|
* The mime type for the blob.
|
|
689
1026
|
*/
|
|
690
|
-
|
|
1027
|
+
encodingFormat;
|
|
691
1028
|
/**
|
|
692
1029
|
* The extension.
|
|
693
1030
|
*/
|
|
694
|
-
|
|
1031
|
+
fileExtension;
|
|
695
1032
|
/**
|
|
696
1033
|
* The metadata for the blob as JSON-LD.
|
|
697
1034
|
*/
|
|
698
1035
|
metadata;
|
|
1036
|
+
/**
|
|
1037
|
+
* Is the entry encrypted.
|
|
1038
|
+
*/
|
|
1039
|
+
isEncrypted;
|
|
1040
|
+
/**
|
|
1041
|
+
* Is the entry compressed.
|
|
1042
|
+
*/
|
|
1043
|
+
compression;
|
|
699
1044
|
/**
|
|
700
1045
|
* The user identity that created the blob.
|
|
701
1046
|
*/
|
|
@@ -708,30 +1053,59 @@ exports.BlobMetadata = class BlobMetadata {
|
|
|
708
1053
|
__decorate([
|
|
709
1054
|
entity.property({ type: "string", isPrimary: true }),
|
|
710
1055
|
__metadata("design:type", String)
|
|
711
|
-
], exports.
|
|
1056
|
+
], exports.BlobStorageEntry.prototype, "id", void 0);
|
|
712
1057
|
__decorate([
|
|
713
|
-
entity.property({ type: "string" }),
|
|
1058
|
+
entity.property({ type: "string", format: "date-time", sortDirection: entity.SortDirection.Descending }),
|
|
714
1059
|
__metadata("design:type", String)
|
|
715
|
-
], exports.
|
|
1060
|
+
], exports.BlobStorageEntry.prototype, "dateCreated", void 0);
|
|
1061
|
+
__decorate([
|
|
1062
|
+
entity.property({
|
|
1063
|
+
type: "string",
|
|
1064
|
+
format: "date-time",
|
|
1065
|
+
sortDirection: entity.SortDirection.Descending,
|
|
1066
|
+
optional: true
|
|
1067
|
+
}),
|
|
1068
|
+
__metadata("design:type", String)
|
|
1069
|
+
], exports.BlobStorageEntry.prototype, "dateModified", void 0);
|
|
1070
|
+
__decorate([
|
|
1071
|
+
entity.property({ type: "number" }),
|
|
1072
|
+
__metadata("design:type", Number)
|
|
1073
|
+
], exports.BlobStorageEntry.prototype, "blobSize", void 0);
|
|
716
1074
|
__decorate([
|
|
717
1075
|
entity.property({ type: "string" }),
|
|
718
1076
|
__metadata("design:type", String)
|
|
719
|
-
], exports.
|
|
1077
|
+
], exports.BlobStorageEntry.prototype, "blobHash", void 0);
|
|
1078
|
+
__decorate([
|
|
1079
|
+
entity.property({ type: "string", optional: true }),
|
|
1080
|
+
__metadata("design:type", String)
|
|
1081
|
+
], exports.BlobStorageEntry.prototype, "encodingFormat", void 0);
|
|
1082
|
+
__decorate([
|
|
1083
|
+
entity.property({ type: "string", optional: true }),
|
|
1084
|
+
__metadata("design:type", String)
|
|
1085
|
+
], exports.BlobStorageEntry.prototype, "fileExtension", void 0);
|
|
720
1086
|
__decorate([
|
|
721
|
-
entity.property({ type: "object", itemTypeRef: "IJsonLdNodeObject" }),
|
|
1087
|
+
entity.property({ type: "object", itemTypeRef: "IJsonLdNodeObject", optional: true }),
|
|
722
1088
|
__metadata("design:type", Object)
|
|
723
|
-
], exports.
|
|
1089
|
+
], exports.BlobStorageEntry.prototype, "metadata", void 0);
|
|
724
1090
|
__decorate([
|
|
725
|
-
entity.property({ type: "
|
|
1091
|
+
entity.property({ type: "boolean" }),
|
|
1092
|
+
__metadata("design:type", Boolean)
|
|
1093
|
+
], exports.BlobStorageEntry.prototype, "isEncrypted", void 0);
|
|
1094
|
+
__decorate([
|
|
1095
|
+
entity.property({ type: "string", optional: true }),
|
|
726
1096
|
__metadata("design:type", String)
|
|
727
|
-
], exports.
|
|
1097
|
+
], exports.BlobStorageEntry.prototype, "compression", void 0);
|
|
728
1098
|
__decorate([
|
|
729
|
-
entity.property({ type: "string" }),
|
|
1099
|
+
entity.property({ type: "string", optional: true }),
|
|
1100
|
+
__metadata("design:type", String)
|
|
1101
|
+
], exports.BlobStorageEntry.prototype, "userIdentity", void 0);
|
|
1102
|
+
__decorate([
|
|
1103
|
+
entity.property({ type: "string", optional: true }),
|
|
730
1104
|
__metadata("design:type", String)
|
|
731
|
-
], exports.
|
|
732
|
-
exports.
|
|
1105
|
+
], exports.BlobStorageEntry.prototype, "nodeIdentity", void 0);
|
|
1106
|
+
exports.BlobStorageEntry = __decorate([
|
|
733
1107
|
entity.entity()
|
|
734
|
-
], exports.
|
|
1108
|
+
], exports.BlobStorageEntry);
|
|
735
1109
|
|
|
736
1110
|
/**
|
|
737
1111
|
* These are dummy entry points for the blob storage service.
|
|
@@ -753,13 +1127,14 @@ const restEntryPoints = [
|
|
|
753
1127
|
* Initialize the schema for the blob storage entities.
|
|
754
1128
|
*/
|
|
755
1129
|
function initSchema() {
|
|
756
|
-
entity.EntitySchemaFactory.register("
|
|
1130
|
+
entity.EntitySchemaFactory.register("BlobStorageEntry", () => entity.EntitySchemaHelper.getSchema(exports.BlobStorageEntry));
|
|
757
1131
|
}
|
|
758
1132
|
|
|
759
1133
|
exports.BlobStorageService = BlobStorageService;
|
|
760
1134
|
exports.blobStorageCreate = blobStorageCreate;
|
|
761
1135
|
exports.blobStorageGet = blobStorageGet;
|
|
762
1136
|
exports.blobStorageGetContent = blobStorageGetContent;
|
|
1137
|
+
exports.blobStorageList = blobStorageList;
|
|
763
1138
|
exports.blobStorageRemove = blobStorageRemove;
|
|
764
1139
|
exports.blobStorageUpdate = blobStorageUpdate;
|
|
765
1140
|
exports.generateRestRoutesBlobStorage = generateRestRoutesBlobStorage;
|