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