@twin.org/document-management-service 0.0.1-next.11 → 0.0.1-next.13

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.
@@ -224,7 +224,101 @@ function generateRestRoutesDocumentManagement(baseRouteName, componentName) {
224
224
  }
225
225
  ]
226
226
  };
227
- const documentManagementRemoveRoute = {
227
+ const documentManagementGetRevisionRoute = {
228
+ operationId: "DocumentManagementGetRevision",
229
+ summary: "Get the data for a document revision from document management",
230
+ tag: tagsDocumentManagement[0].name,
231
+ method: "GET",
232
+ path: `${baseRouteName}/:auditableItemGraphDocumentId/:revision`,
233
+ handler: async (httpRequestContext, request) => documentManagementGetRevision(httpRequestContext, componentName, request),
234
+ requestType: {
235
+ type: "IDocumentManagementGetRequest",
236
+ examples: [
237
+ {
238
+ id: "DocumentManagementGetRevisionRequestExample",
239
+ request: {
240
+ pathParams: {
241
+ auditableItemGraphDocumentId: "aig:123456",
242
+ revision: "1"
243
+ }
244
+ }
245
+ }
246
+ ]
247
+ },
248
+ responseType: [
249
+ {
250
+ type: "IDocumentManagementGetRevisionResponse",
251
+ examples: [
252
+ {
253
+ id: "DocumentManagementGetRevisionResponseExample",
254
+ response: {
255
+ body: {
256
+ "@context": [
257
+ documentManagementModels.DocumentContexts.ContextRoot,
258
+ documentManagementModels.DocumentContexts.ContextRootCommon,
259
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot
260
+ ],
261
+ type: documentManagementModels.DocumentTypes.Document,
262
+ id: "2721000:0",
263
+ documentId: "2721000",
264
+ documentIdFormat: "bol",
265
+ documentCode: standardsUnece.UneceDocumentCodes.BillOfLading,
266
+ documentRevision: 1,
267
+ blobStorageId: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
268
+ blobHash: "sha256:123456",
269
+ dateCreated: "2024-01-01T00:00:00Z",
270
+ annotationObject: {
271
+ "@context": "https://schema.org",
272
+ "@type": "DigitalDocument",
273
+ name: "myfile.pdf"
274
+ },
275
+ nodeIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363",
276
+ userIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363"
277
+ }
278
+ }
279
+ }
280
+ ]
281
+ },
282
+ {
283
+ type: "IDocumentManagementGetRevisionResponse",
284
+ mimeType: web.MimeTypes.JsonLd,
285
+ examples: [
286
+ {
287
+ id: "DocumentManagementGetRevisionResponseExample",
288
+ response: {
289
+ body: {
290
+ "@context": [
291
+ documentManagementModels.DocumentContexts.ContextRoot,
292
+ documentManagementModels.DocumentContexts.ContextRootCommon,
293
+ standardsSchemaOrg.SchemaOrgContexts.ContextRoot
294
+ ],
295
+ type: documentManagementModels.DocumentTypes.Document,
296
+ id: "2721000:0",
297
+ documentId: "2721000",
298
+ documentIdFormat: "bol",
299
+ documentCode: standardsUnece.UneceDocumentCodes.BillOfLading,
300
+ documentRevision: 1,
301
+ blobStorageId: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
302
+ blobHash: "sha256:123456",
303
+ dateCreated: "2024-01-01T00:00:00Z",
304
+ annotationObject: {
305
+ "@context": "https://schema.org",
306
+ "@type": "DigitalDocument",
307
+ name: "myfile.pdf"
308
+ },
309
+ nodeIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363",
310
+ userIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363"
311
+ }
312
+ }
313
+ }
314
+ ]
315
+ },
316
+ {
317
+ type: "INotFoundResponse"
318
+ }
319
+ ]
320
+ };
321
+ const documentManagementRemoveRevisionRoute = {
228
322
  operationId: "DocumentManagementRemove",
229
323
  summary: "Remove an document from an auditable item graph vertex",
230
324
  tag: tagsDocumentManagement[0].name,
@@ -343,7 +437,8 @@ function generateRestRoutesDocumentManagement(baseRouteName, componentName) {
343
437
  documentManagementCreateRoute,
344
438
  documentManagementUpdateRoute,
345
439
  documentManagementGetRoute,
346
- documentManagementRemoveRoute,
440
+ documentManagementGetRevisionRoute,
441
+ documentManagementRemoveRevisionRoute,
347
442
  documentManagementQueryRoute
348
443
  ];
349
444
  }
@@ -388,7 +483,9 @@ async function documentManagementGet(httpRequestContext, componentName, request)
388
483
  includeBlobStorageMetadata: core.Coerce.boolean(request.query?.includeBlobStorageMetadata),
389
484
  includeBlobStorageData: core.Coerce.boolean(request.query?.includeBlobStorageData),
390
485
  includeAttestation: core.Coerce.boolean(request.query?.includeAttestation),
391
- includeRemoved: core.Coerce.boolean(request.query?.includeRemoved)
486
+ includeRemoved: core.Coerce.boolean(request.query?.includeRemoved),
487
+ extractRuleGroupId: request.query?.extractRuleGroupId,
488
+ extractMimeType: request.query?.extractMimeType
392
489
  }, request.query?.cursor, core.Coerce.integer(request.query?.pageSize), httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
393
490
  return {
394
491
  headers: {
@@ -398,7 +495,36 @@ async function documentManagementGet(httpRequestContext, componentName, request)
398
495
  };
399
496
  }
400
497
  /**
401
- * UPdate the document from the auditable item graph vertex.
498
+ * Get the document revision from the auditable item graph vertex.
499
+ * @param httpRequestContext The request context for the API.
500
+ * @param componentName The name of the component to use in the routes.
501
+ * @param request The request.
502
+ * @returns The response object with additional http response properties.
503
+ */
504
+ async function documentManagementGetRevision(httpRequestContext, componentName, request) {
505
+ core.Guards.object(ROUTES_SOURCE, "request", request);
506
+ core.Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
507
+ core.Guards.stringValue(ROUTES_SOURCE, "request.pathParams.auditableItemGraphDocumentId", request.pathParams.auditableItemGraphDocumentId);
508
+ const revision = core.Coerce.integer(request.pathParams.revision);
509
+ core.Guards.integer(ROUTES_SOURCE, "revision", revision);
510
+ const mimeType = request.headers?.[web.HeaderTypes.Accept] === web.MimeTypes.JsonLd ? "jsonld" : "json";
511
+ const component = core.ComponentFactory.get(componentName);
512
+ const result = await component.getRevision(request.pathParams.auditableItemGraphDocumentId, revision, {
513
+ includeBlobStorageMetadata: core.Coerce.boolean(request.query?.includeBlobStorageMetadata),
514
+ includeBlobStorageData: core.Coerce.boolean(request.query?.includeBlobStorageData),
515
+ includeAttestation: core.Coerce.boolean(request.query?.includeAttestation),
516
+ extractRuleGroupId: request.query?.extractRuleGroupId,
517
+ extractMimeType: request.query?.extractMimeType
518
+ }, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
519
+ return {
520
+ headers: {
521
+ [web.HeaderTypes.ContentType]: mimeType === "json" ? web.MimeTypes.Json : web.MimeTypes.JsonLd
522
+ },
523
+ body: result
524
+ };
525
+ }
526
+ /**
527
+ * Update the document from the auditable item graph vertex.
402
528
  * @param httpRequestContext The request context for the API.
403
529
  * @param componentName The name of the component to use in the routes.
404
530
  * @param request The request.
@@ -550,7 +676,7 @@ class DocumentManagementService {
550
676
  standardsSchemaOrg.SchemaOrgContexts.ContextRoot
551
677
  ],
552
678
  type: documentManagementModels.DocumentTypes.Document,
553
- id: `${documentId}:0`,
679
+ id: this.createDocumentId(documentId, 0),
554
680
  documentId,
555
681
  documentIdFormat,
556
682
  documentCode,
@@ -604,12 +730,13 @@ class DocumentManagementService {
604
730
  core.Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
605
731
  core.Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
606
732
  try {
607
- const documentVertex = await this._auditableItemGraphComponent.get(auditableItemGraphDocumentId);
733
+ const documentVertex = await this._auditableItemGraphComponent.get(auditableItemGraphDocumentId, { includeDeleted: true });
608
734
  if (core.Is.empty(documentVertex.resources)) {
609
735
  throw new core.NotFoundError(this.CLASS_NAME, "documentRevisionNone");
610
736
  }
611
737
  const documents = await this.getDocumentsFromVertex(documentVertex);
612
738
  const latestRevision = documents.documents[0];
739
+ documentVertex.resources = documentVertex.resources.filter(r => core.Is.empty(r.dateDeleted));
613
740
  if (core.Is.empty(latestRevision)) {
614
741
  throw new core.NotFoundError(this.CLASS_NAME, "documentRevisionNone");
615
742
  }
@@ -640,7 +767,7 @@ class DocumentManagementService {
640
767
  const blobStorageId = await this._blobStorageComponent.create(core.Converter.bytesToBase64(blob), undefined, undefined, undefined, undefined, userIdentity, nodeIdentity);
641
768
  const newRevision = core.ObjectHelper.clone(latestRevision);
642
769
  newRevision.documentRevision++;
643
- newRevision.id = `${newRevision.documentId}:${newRevision.documentRevision}`;
770
+ newRevision.id = this.createDocumentId(newRevision.documentId, newRevision.documentRevision);
644
771
  newRevision.blobHash = newBlobHash;
645
772
  newRevision.blobStorageId = blobStorageId;
646
773
  newRevision.annotationObject = annotationObject;
@@ -714,6 +841,43 @@ class DocumentManagementService {
714
841
  throw new core.GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
715
842
  }
716
843
  }
844
+ /**
845
+ * Get a document revision using it's auditable item graph vertex id.
846
+ * @param auditableItemGraphDocumentId The auditable item graph vertex id which contains the document.
847
+ * @param revision The revision id for the document.
848
+ * @param options Additional options for the get operation.
849
+ * @param options.includeBlobStorageMetadata Flag to include the blob storage metadata for the document, defaults to false.
850
+ * @param options.includeBlobStorageData Flag to include the blob storage data for the document, defaults to false.
851
+ * @param options.includeAttestation Flag to include the attestation information for the document, defaults to false.
852
+ * @param options.extractRuleGroupId If provided will extract data from the document using the specified rule group id.
853
+ * @param options.extractMimeType By default extraction will auto detect the mime type of the document, this can be used to override the detection.
854
+ * @param userIdentity The identity to perform the auditable item graph operation with.
855
+ * @param nodeIdentity The node identity to use for vault operations.
856
+ * @returns The documents and revisions if requested, ordered by revision descending, cursor is set if there are more document revisions.
857
+ */
858
+ async getRevision(auditableItemGraphDocumentId, revision, options, userIdentity, nodeIdentity) {
859
+ core.Urn.guard(this.CLASS_NAME, "auditableItemGraphDocumentId", auditableItemGraphDocumentId);
860
+ core.Guards.integer(this.CLASS_NAME, "revision", revision);
861
+ try {
862
+ const documentVertex = await this._auditableItemGraphComponent.get(auditableItemGraphDocumentId, { includeDeleted: true });
863
+ if (core.Is.empty(documentVertex.resources)) {
864
+ throw new core.NotFoundError(this.CLASS_NAME, "documentRevisionNone");
865
+ }
866
+ documentVertex.resources = documentVertex.resources.filter(d => d.resourceObject?.documentRevision === revision);
867
+ if (documentVertex.resources.length === 0) {
868
+ throw new core.NotFoundError(this.CLASS_NAME, "documentRevisionNotFound", revision.toString());
869
+ }
870
+ // Populate the document and revisions with the options set
871
+ const docList = await this.getDocumentsFromVertex(documentVertex, options, undefined, undefined, userIdentity, nodeIdentity);
872
+ return dataJsonLd.JsonLdProcessor.compact(docList.documents[0], docList.documents[0]["@context"]);
873
+ }
874
+ catch (error) {
875
+ if (core.BaseError.someErrorName(error, "NotFoundError")) {
876
+ throw error;
877
+ }
878
+ throw new core.GeneralError(this.CLASS_NAME, "getRevisionFailed", undefined, error);
879
+ }
880
+ }
717
881
  /**
718
882
  * Remove an auditable item graph vertex using it's id.
719
883
  * The document dateDeleted will be set, but can still be queried with the includeRemoved flag.
@@ -961,6 +1125,7 @@ class DocumentManagementService {
961
1125
  for (let i = 0; i < slicedResources.length; i++) {
962
1126
  const document = slicedResources[i].resourceObject;
963
1127
  if (core.Is.object(document)) {
1128
+ document.dateDeleted = slicedResources[i].dateDeleted;
964
1129
  docList.documents.push(document);
965
1130
  const blobRequired = includeBlobStorageMetadata || includeBlobStorageData;
966
1131
  if (blobRequired || extractData) {
@@ -1028,6 +1193,17 @@ class DocumentManagementService {
1028
1193
  };
1029
1194
  return this._attestationComponent.create(documentAttestation, undefined, userIdentity, nodeIdentity);
1030
1195
  }
1196
+ /**
1197
+ * Create a document id from the document id and revision.
1198
+ * @param documentId The document id to create.
1199
+ * @param revision The revision of the document.
1200
+ * @returns The document id.
1201
+ * @internal
1202
+ */
1203
+ createDocumentId(documentId, revision) {
1204
+ const documentIdHash = core.Converter.bytesToBase64Url(crypto.Sha256.sum256(core.Converter.utf8ToBytes(documentId)));
1205
+ return `document:${documentIdHash}:${revision}`;
1206
+ }
1031
1207
  }
1032
1208
 
1033
1209
  const restEntryPoints = [
@@ -1042,6 +1218,7 @@ const restEntryPoints = [
1042
1218
  exports.DocumentManagementService = DocumentManagementService;
1043
1219
  exports.documentManagementCreate = documentManagementCreate;
1044
1220
  exports.documentManagementGet = documentManagementGet;
1221
+ exports.documentManagementGetRevision = documentManagementGetRevision;
1045
1222
  exports.documentManagementQuery = documentManagementQuery;
1046
1223
  exports.documentManagementRemove = documentManagementRemove;
1047
1224
  exports.documentManagementUpdate = documentManagementUpdate;
@@ -222,7 +222,101 @@ function generateRestRoutesDocumentManagement(baseRouteName, componentName) {
222
222
  }
223
223
  ]
224
224
  };
225
- const documentManagementRemoveRoute = {
225
+ const documentManagementGetRevisionRoute = {
226
+ operationId: "DocumentManagementGetRevision",
227
+ summary: "Get the data for a document revision from document management",
228
+ tag: tagsDocumentManagement[0].name,
229
+ method: "GET",
230
+ path: `${baseRouteName}/:auditableItemGraphDocumentId/:revision`,
231
+ handler: async (httpRequestContext, request) => documentManagementGetRevision(httpRequestContext, componentName, request),
232
+ requestType: {
233
+ type: "IDocumentManagementGetRequest",
234
+ examples: [
235
+ {
236
+ id: "DocumentManagementGetRevisionRequestExample",
237
+ request: {
238
+ pathParams: {
239
+ auditableItemGraphDocumentId: "aig:123456",
240
+ revision: "1"
241
+ }
242
+ }
243
+ }
244
+ ]
245
+ },
246
+ responseType: [
247
+ {
248
+ type: "IDocumentManagementGetRevisionResponse",
249
+ examples: [
250
+ {
251
+ id: "DocumentManagementGetRevisionResponseExample",
252
+ response: {
253
+ body: {
254
+ "@context": [
255
+ DocumentContexts.ContextRoot,
256
+ DocumentContexts.ContextRootCommon,
257
+ SchemaOrgContexts.ContextRoot
258
+ ],
259
+ type: DocumentTypes.Document,
260
+ id: "2721000:0",
261
+ documentId: "2721000",
262
+ documentIdFormat: "bol",
263
+ documentCode: UneceDocumentCodes.BillOfLading,
264
+ documentRevision: 1,
265
+ blobStorageId: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
266
+ blobHash: "sha256:123456",
267
+ dateCreated: "2024-01-01T00:00:00Z",
268
+ annotationObject: {
269
+ "@context": "https://schema.org",
270
+ "@type": "DigitalDocument",
271
+ name: "myfile.pdf"
272
+ },
273
+ nodeIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363",
274
+ userIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363"
275
+ }
276
+ }
277
+ }
278
+ ]
279
+ },
280
+ {
281
+ type: "IDocumentManagementGetRevisionResponse",
282
+ mimeType: MimeTypes.JsonLd,
283
+ examples: [
284
+ {
285
+ id: "DocumentManagementGetRevisionResponseExample",
286
+ response: {
287
+ body: {
288
+ "@context": [
289
+ DocumentContexts.ContextRoot,
290
+ DocumentContexts.ContextRootCommon,
291
+ SchemaOrgContexts.ContextRoot
292
+ ],
293
+ type: DocumentTypes.Document,
294
+ id: "2721000:0",
295
+ documentId: "2721000",
296
+ documentIdFormat: "bol",
297
+ documentCode: UneceDocumentCodes.BillOfLading,
298
+ documentRevision: 1,
299
+ blobStorageId: "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
300
+ blobHash: "sha256:123456",
301
+ dateCreated: "2024-01-01T00:00:00Z",
302
+ annotationObject: {
303
+ "@context": "https://schema.org",
304
+ "@type": "DigitalDocument",
305
+ name: "myfile.pdf"
306
+ },
307
+ nodeIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363",
308
+ userIdentity: "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363"
309
+ }
310
+ }
311
+ }
312
+ ]
313
+ },
314
+ {
315
+ type: "INotFoundResponse"
316
+ }
317
+ ]
318
+ };
319
+ const documentManagementRemoveRevisionRoute = {
226
320
  operationId: "DocumentManagementRemove",
227
321
  summary: "Remove an document from an auditable item graph vertex",
228
322
  tag: tagsDocumentManagement[0].name,
@@ -341,7 +435,8 @@ function generateRestRoutesDocumentManagement(baseRouteName, componentName) {
341
435
  documentManagementCreateRoute,
342
436
  documentManagementUpdateRoute,
343
437
  documentManagementGetRoute,
344
- documentManagementRemoveRoute,
438
+ documentManagementGetRevisionRoute,
439
+ documentManagementRemoveRevisionRoute,
345
440
  documentManagementQueryRoute
346
441
  ];
347
442
  }
@@ -386,7 +481,9 @@ async function documentManagementGet(httpRequestContext, componentName, request)
386
481
  includeBlobStorageMetadata: Coerce.boolean(request.query?.includeBlobStorageMetadata),
387
482
  includeBlobStorageData: Coerce.boolean(request.query?.includeBlobStorageData),
388
483
  includeAttestation: Coerce.boolean(request.query?.includeAttestation),
389
- includeRemoved: Coerce.boolean(request.query?.includeRemoved)
484
+ includeRemoved: Coerce.boolean(request.query?.includeRemoved),
485
+ extractRuleGroupId: request.query?.extractRuleGroupId,
486
+ extractMimeType: request.query?.extractMimeType
390
487
  }, request.query?.cursor, Coerce.integer(request.query?.pageSize), httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
391
488
  return {
392
489
  headers: {
@@ -396,7 +493,36 @@ async function documentManagementGet(httpRequestContext, componentName, request)
396
493
  };
397
494
  }
398
495
  /**
399
- * UPdate the document from the auditable item graph vertex.
496
+ * Get the document revision from the auditable item graph vertex.
497
+ * @param httpRequestContext The request context for the API.
498
+ * @param componentName The name of the component to use in the routes.
499
+ * @param request The request.
500
+ * @returns The response object with additional http response properties.
501
+ */
502
+ async function documentManagementGetRevision(httpRequestContext, componentName, request) {
503
+ Guards.object(ROUTES_SOURCE, "request", request);
504
+ Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
505
+ Guards.stringValue(ROUTES_SOURCE, "request.pathParams.auditableItemGraphDocumentId", request.pathParams.auditableItemGraphDocumentId);
506
+ const revision = Coerce.integer(request.pathParams.revision);
507
+ Guards.integer(ROUTES_SOURCE, "revision", revision);
508
+ const mimeType = request.headers?.[HeaderTypes.Accept] === MimeTypes.JsonLd ? "jsonld" : "json";
509
+ const component = ComponentFactory.get(componentName);
510
+ const result = await component.getRevision(request.pathParams.auditableItemGraphDocumentId, revision, {
511
+ includeBlobStorageMetadata: Coerce.boolean(request.query?.includeBlobStorageMetadata),
512
+ includeBlobStorageData: Coerce.boolean(request.query?.includeBlobStorageData),
513
+ includeAttestation: Coerce.boolean(request.query?.includeAttestation),
514
+ extractRuleGroupId: request.query?.extractRuleGroupId,
515
+ extractMimeType: request.query?.extractMimeType
516
+ }, httpRequestContext.userIdentity, httpRequestContext.nodeIdentity);
517
+ return {
518
+ headers: {
519
+ [HeaderTypes.ContentType]: mimeType === "json" ? MimeTypes.Json : MimeTypes.JsonLd
520
+ },
521
+ body: result
522
+ };
523
+ }
524
+ /**
525
+ * Update the document from the auditable item graph vertex.
400
526
  * @param httpRequestContext The request context for the API.
401
527
  * @param componentName The name of the component to use in the routes.
402
528
  * @param request The request.
@@ -548,7 +674,7 @@ class DocumentManagementService {
548
674
  SchemaOrgContexts.ContextRoot
549
675
  ],
550
676
  type: DocumentTypes.Document,
551
- id: `${documentId}:0`,
677
+ id: this.createDocumentId(documentId, 0),
552
678
  documentId,
553
679
  documentIdFormat,
554
680
  documentCode,
@@ -602,12 +728,13 @@ class DocumentManagementService {
602
728
  Guards.stringValue(this.CLASS_NAME, "userIdentity", userIdentity);
603
729
  Guards.stringValue(this.CLASS_NAME, "nodeIdentity", nodeIdentity);
604
730
  try {
605
- const documentVertex = await this._auditableItemGraphComponent.get(auditableItemGraphDocumentId);
731
+ const documentVertex = await this._auditableItemGraphComponent.get(auditableItemGraphDocumentId, { includeDeleted: true });
606
732
  if (Is.empty(documentVertex.resources)) {
607
733
  throw new NotFoundError(this.CLASS_NAME, "documentRevisionNone");
608
734
  }
609
735
  const documents = await this.getDocumentsFromVertex(documentVertex);
610
736
  const latestRevision = documents.documents[0];
737
+ documentVertex.resources = documentVertex.resources.filter(r => Is.empty(r.dateDeleted));
611
738
  if (Is.empty(latestRevision)) {
612
739
  throw new NotFoundError(this.CLASS_NAME, "documentRevisionNone");
613
740
  }
@@ -638,7 +765,7 @@ class DocumentManagementService {
638
765
  const blobStorageId = await this._blobStorageComponent.create(Converter.bytesToBase64(blob), undefined, undefined, undefined, undefined, userIdentity, nodeIdentity);
639
766
  const newRevision = ObjectHelper.clone(latestRevision);
640
767
  newRevision.documentRevision++;
641
- newRevision.id = `${newRevision.documentId}:${newRevision.documentRevision}`;
768
+ newRevision.id = this.createDocumentId(newRevision.documentId, newRevision.documentRevision);
642
769
  newRevision.blobHash = newBlobHash;
643
770
  newRevision.blobStorageId = blobStorageId;
644
771
  newRevision.annotationObject = annotationObject;
@@ -712,6 +839,43 @@ class DocumentManagementService {
712
839
  throw new GeneralError(this.CLASS_NAME, "getFailed", undefined, error);
713
840
  }
714
841
  }
842
+ /**
843
+ * Get a document revision using it's auditable item graph vertex id.
844
+ * @param auditableItemGraphDocumentId The auditable item graph vertex id which contains the document.
845
+ * @param revision The revision id for the document.
846
+ * @param options Additional options for the get operation.
847
+ * @param options.includeBlobStorageMetadata Flag to include the blob storage metadata for the document, defaults to false.
848
+ * @param options.includeBlobStorageData Flag to include the blob storage data for the document, defaults to false.
849
+ * @param options.includeAttestation Flag to include the attestation information for the document, defaults to false.
850
+ * @param options.extractRuleGroupId If provided will extract data from the document using the specified rule group id.
851
+ * @param options.extractMimeType By default extraction will auto detect the mime type of the document, this can be used to override the detection.
852
+ * @param userIdentity The identity to perform the auditable item graph operation with.
853
+ * @param nodeIdentity The node identity to use for vault operations.
854
+ * @returns The documents and revisions if requested, ordered by revision descending, cursor is set if there are more document revisions.
855
+ */
856
+ async getRevision(auditableItemGraphDocumentId, revision, options, userIdentity, nodeIdentity) {
857
+ Urn.guard(this.CLASS_NAME, "auditableItemGraphDocumentId", auditableItemGraphDocumentId);
858
+ Guards.integer(this.CLASS_NAME, "revision", revision);
859
+ try {
860
+ const documentVertex = await this._auditableItemGraphComponent.get(auditableItemGraphDocumentId, { includeDeleted: true });
861
+ if (Is.empty(documentVertex.resources)) {
862
+ throw new NotFoundError(this.CLASS_NAME, "documentRevisionNone");
863
+ }
864
+ documentVertex.resources = documentVertex.resources.filter(d => d.resourceObject?.documentRevision === revision);
865
+ if (documentVertex.resources.length === 0) {
866
+ throw new NotFoundError(this.CLASS_NAME, "documentRevisionNotFound", revision.toString());
867
+ }
868
+ // Populate the document and revisions with the options set
869
+ const docList = await this.getDocumentsFromVertex(documentVertex, options, undefined, undefined, userIdentity, nodeIdentity);
870
+ return JsonLdProcessor.compact(docList.documents[0], docList.documents[0]["@context"]);
871
+ }
872
+ catch (error) {
873
+ if (BaseError.someErrorName(error, "NotFoundError")) {
874
+ throw error;
875
+ }
876
+ throw new GeneralError(this.CLASS_NAME, "getRevisionFailed", undefined, error);
877
+ }
878
+ }
715
879
  /**
716
880
  * Remove an auditable item graph vertex using it's id.
717
881
  * The document dateDeleted will be set, but can still be queried with the includeRemoved flag.
@@ -959,6 +1123,7 @@ class DocumentManagementService {
959
1123
  for (let i = 0; i < slicedResources.length; i++) {
960
1124
  const document = slicedResources[i].resourceObject;
961
1125
  if (Is.object(document)) {
1126
+ document.dateDeleted = slicedResources[i].dateDeleted;
962
1127
  docList.documents.push(document);
963
1128
  const blobRequired = includeBlobStorageMetadata || includeBlobStorageData;
964
1129
  if (blobRequired || extractData) {
@@ -1026,6 +1191,17 @@ class DocumentManagementService {
1026
1191
  };
1027
1192
  return this._attestationComponent.create(documentAttestation, undefined, userIdentity, nodeIdentity);
1028
1193
  }
1194
+ /**
1195
+ * Create a document id from the document id and revision.
1196
+ * @param documentId The document id to create.
1197
+ * @param revision The revision of the document.
1198
+ * @returns The document id.
1199
+ * @internal
1200
+ */
1201
+ createDocumentId(documentId, revision) {
1202
+ const documentIdHash = Converter.bytesToBase64Url(Sha256.sum256(Converter.utf8ToBytes(documentId)));
1203
+ return `document:${documentIdHash}:${revision}`;
1204
+ }
1029
1205
  }
1030
1206
 
1031
1207
  const restEntryPoints = [
@@ -1037,4 +1213,4 @@ const restEntryPoints = [
1037
1213
  }
1038
1214
  ];
1039
1215
 
1040
- export { DocumentManagementService, documentManagementCreate, documentManagementGet, documentManagementQuery, documentManagementRemove, documentManagementUpdate, generateRestRoutesDocumentManagement, restEntryPoints, tagsDocumentManagement };
1216
+ export { DocumentManagementService, documentManagementCreate, documentManagementGet, documentManagementGetRevision, documentManagementQuery, documentManagementRemove, documentManagementUpdate, generateRestRoutesDocumentManagement, restEntryPoints, tagsDocumentManagement };
@@ -1,5 +1,5 @@
1
1
  import type { ICreatedResponse, IHttpRequestContext, INoContentResponse, IRestRoute, ITag } from "@twin.org/api-models";
2
- import { type IDocumentManagementCreateRequest, type IDocumentManagementGetRequest, type IDocumentManagementGetResponse, type IDocumentManagementQueryRequest, type IDocumentManagementQueryResponse, type IDocumentManagementRemoveRequest, type IDocumentManagementUpdateRequest } from "@twin.org/document-management-models";
2
+ import { type IDocumentManagementGetRevisionRequest, type IDocumentManagementGetRevisionResponse, type IDocumentManagementCreateRequest, type IDocumentManagementGetRequest, type IDocumentManagementGetResponse, type IDocumentManagementQueryRequest, type IDocumentManagementQueryResponse, type IDocumentManagementRemoveRequest, type IDocumentManagementUpdateRequest } from "@twin.org/document-management-models";
3
3
  /**
4
4
  * The tag to associate with the routes.
5
5
  */
@@ -28,7 +28,15 @@ export declare function documentManagementCreate(httpRequestContext: IHttpReques
28
28
  */
29
29
  export declare function documentManagementGet(httpRequestContext: IHttpRequestContext, componentName: string, request: IDocumentManagementGetRequest): Promise<IDocumentManagementGetResponse>;
30
30
  /**
31
- * UPdate the document from the auditable item graph vertex.
31
+ * Get the document revision from the auditable item graph vertex.
32
+ * @param httpRequestContext The request context for the API.
33
+ * @param componentName The name of the component to use in the routes.
34
+ * @param request The request.
35
+ * @returns The response object with additional http response properties.
36
+ */
37
+ export declare function documentManagementGetRevision(httpRequestContext: IHttpRequestContext, componentName: string, request: IDocumentManagementGetRevisionRequest): Promise<IDocumentManagementGetRevisionResponse>;
38
+ /**
39
+ * Update the document from the auditable item graph vertex.
32
40
  * @param httpRequestContext The request context for the API.
33
41
  * @param componentName The name of the component to use in the routes.
34
42
  * @param request The request.
@@ -1,6 +1,6 @@
1
1
  import { type IAuditableItemGraphVertexList } from "@twin.org/auditable-item-graph-models";
2
2
  import { type IJsonLdNodeObject } from "@twin.org/data-json-ld";
3
- import { type IDocumentList, type IDocumentManagementComponent } from "@twin.org/document-management-models";
3
+ import { type IDocument, type IDocumentList, type IDocumentManagementComponent } from "@twin.org/document-management-models";
4
4
  import { UneceDocumentCodes } from "@twin.org/standards-unece";
5
5
  import type { IDocumentManagementServiceConstructorOptions } from "./models/IDocumentManagementStorageServiceConstructorOptions";
6
6
  /**
@@ -88,6 +88,27 @@ export declare class DocumentManagementService implements IDocumentManagementCom
88
88
  extractRuleGroupId?: string;
89
89
  extractMimeType?: string;
90
90
  }, cursor?: string, pageSize?: number, userIdentity?: string, nodeIdentity?: string): Promise<IDocumentList>;
91
+ /**
92
+ * Get a document revision using it's auditable item graph vertex id.
93
+ * @param auditableItemGraphDocumentId The auditable item graph vertex id which contains the document.
94
+ * @param revision The revision id for the document.
95
+ * @param options Additional options for the get operation.
96
+ * @param options.includeBlobStorageMetadata Flag to include the blob storage metadata for the document, defaults to false.
97
+ * @param options.includeBlobStorageData Flag to include the blob storage data for the document, defaults to false.
98
+ * @param options.includeAttestation Flag to include the attestation information for the document, defaults to false.
99
+ * @param options.extractRuleGroupId If provided will extract data from the document using the specified rule group id.
100
+ * @param options.extractMimeType By default extraction will auto detect the mime type of the document, this can be used to override the detection.
101
+ * @param userIdentity The identity to perform the auditable item graph operation with.
102
+ * @param nodeIdentity The node identity to use for vault operations.
103
+ * @returns The documents and revisions if requested, ordered by revision descending, cursor is set if there are more document revisions.
104
+ */
105
+ getRevision(auditableItemGraphDocumentId: string, revision: number, options?: {
106
+ includeBlobStorageMetadata?: boolean;
107
+ includeBlobStorageData?: boolean;
108
+ includeAttestation?: boolean;
109
+ extractRuleGroupId?: string;
110
+ extractMimeType?: string;
111
+ }, userIdentity?: string, nodeIdentity?: string): Promise<IDocument>;
91
112
  /**
92
113
  * Remove an auditable item graph vertex using it's id.
93
114
  * The document dateDeleted will be set, but can still be queried with the includeRemoved flag.
package/docs/changelog.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @twin.org/document-management-service - Changelog
2
2
 
3
+ ## [0.0.1-next.13](https://github.com/twinfoundation/document-management/compare/document-management-service-v0.0.1-next.12...document-management-service-v0.0.1-next.13) (2025-04-30)
4
+
5
+
6
+ ### Features
7
+
8
+ * populate dateDeleted from aig resource object ([ce91cf1](https://github.com/twinfoundation/document-management/commit/ce91cf1385c4370ec6924435349213abf776f3e5))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/document-management-models bumped from 0.0.1-next.12 to 0.0.1-next.13
16
+
17
+ ## [0.0.1-next.12](https://github.com/twinfoundation/document-management/compare/document-management-service-v0.0.1-next.11...document-management-service-v0.0.1-next.12) (2025-04-30)
18
+
19
+
20
+ ### Features
21
+
22
+ * get document revision ([080eddc](https://github.com/twinfoundation/document-management/commit/080eddcc024c622dda6bb36f60f5fa80a86cf5bb))
23
+
24
+
25
+ ### Dependencies
26
+
27
+ * The following workspace dependencies were updated
28
+ * dependencies
29
+ * @twin.org/document-management-models bumped from 0.0.1-next.11 to 0.0.1-next.12
30
+
3
31
  ## [0.0.1-next.11](https://github.com/twinfoundation/document-management/compare/document-management-service-v0.0.1-next.10...document-management-service-v0.0.1-next.11) (2025-04-28)
4
32
 
5
33
 
@@ -698,6 +698,191 @@
698
698
  }
699
699
  },
700
700
  "/document-management/{auditableItemGraphDocumentId}/{revision}": {
701
+ "get": {
702
+ "operationId": "DocumentManagementGetRevision",
703
+ "summary": "Get the data for a document revision from document management",
704
+ "tags": [
705
+ "Document Management"
706
+ ],
707
+ "parameters": [
708
+ {
709
+ "name": "auditableItemGraphDocumentId",
710
+ "description": "",
711
+ "in": "path",
712
+ "required": true,
713
+ "schema": {
714
+ "type": "string"
715
+ },
716
+ "style": "simple",
717
+ "example": "aig:123456"
718
+ },
719
+ {
720
+ "name": "revision",
721
+ "description": "",
722
+ "in": "path",
723
+ "required": true,
724
+ "schema": {
725
+ "type": "string"
726
+ },
727
+ "style": "simple",
728
+ "example": "1"
729
+ }
730
+ ],
731
+ "security": [
732
+ {
733
+ "jwtBearerAuthScheme": []
734
+ }
735
+ ],
736
+ "responses": {
737
+ "200": {
738
+ "description": "Response to get a document revision from an auditable item graph vertex.",
739
+ "content": {
740
+ "application/json": {
741
+ "schema": {
742
+ "$ref": "#/components/schemas/Document"
743
+ },
744
+ "examples": {
745
+ "DocumentManagementGetRevisionResponseExample": {
746
+ "value": {
747
+ "@context": [
748
+ "https://schema.twindev.org/documents/",
749
+ "https://schema.twindev.org/common/",
750
+ "https://schema.org"
751
+ ],
752
+ "type": "Document",
753
+ "id": "2721000:0",
754
+ "documentId": "2721000",
755
+ "documentIdFormat": "bol",
756
+ "documentCode": "unece:DocumentCodeList#705",
757
+ "documentRevision": 1,
758
+ "blobStorageId": "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
759
+ "blobHash": "sha256:123456",
760
+ "dateCreated": "2024-01-01T00:00:00Z",
761
+ "annotationObject": {
762
+ "@context": "https://schema.org",
763
+ "@type": "DigitalDocument",
764
+ "name": "myfile.pdf"
765
+ },
766
+ "nodeIdentity": "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363",
767
+ "userIdentity": "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363"
768
+ }
769
+ }
770
+ }
771
+ },
772
+ "application/ld+json": {
773
+ "schema": {
774
+ "$ref": "#/components/schemas/Document"
775
+ },
776
+ "examples": {
777
+ "DocumentManagementGetRevisionResponseExample": {
778
+ "value": {
779
+ "@context": [
780
+ "https://schema.twindev.org/documents/",
781
+ "https://schema.twindev.org/common/",
782
+ "https://schema.org"
783
+ ],
784
+ "type": "Document",
785
+ "id": "2721000:0",
786
+ "documentId": "2721000",
787
+ "documentIdFormat": "bol",
788
+ "documentCode": "unece:DocumentCodeList#705",
789
+ "documentRevision": 1,
790
+ "blobStorageId": "blob-memory:c57d94b088f4c6d2cb32ded014813d0c786aa00134c8ee22f84b1e2545602a70",
791
+ "blobHash": "sha256:123456",
792
+ "dateCreated": "2024-01-01T00:00:00Z",
793
+ "annotationObject": {
794
+ "@context": "https://schema.org",
795
+ "@type": "DigitalDocument",
796
+ "name": "myfile.pdf"
797
+ },
798
+ "nodeIdentity": "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363",
799
+ "userIdentity": "did:entity-storage:0x6363636363636363636363636363636363636363636363636363636363636363"
800
+ }
801
+ }
802
+ }
803
+ }
804
+ }
805
+ },
806
+ "400": {
807
+ "description": "The server cannot process the request, see the content for more details.",
808
+ "content": {
809
+ "application/json": {
810
+ "schema": {
811
+ "$ref": "#/components/schemas/Error"
812
+ },
813
+ "examples": {
814
+ "exampleResponse": {
815
+ "value": {
816
+ "name": "GeneralError",
817
+ "message": "component.error",
818
+ "properties": {
819
+ "foo": "bar"
820
+ }
821
+ }
822
+ }
823
+ }
824
+ }
825
+ }
826
+ },
827
+ "401": {
828
+ "description": "You are not authorized to use the API or no credentials were supplied, see the content for more details.",
829
+ "content": {
830
+ "application/json": {
831
+ "schema": {
832
+ "$ref": "#/components/schemas/Error"
833
+ },
834
+ "examples": {
835
+ "exampleResponse": {
836
+ "value": {
837
+ "name": "UnauthorizedError",
838
+ "message": "component.error"
839
+ }
840
+ }
841
+ }
842
+ }
843
+ }
844
+ },
845
+ "404": {
846
+ "description": "The resource you tried to access does not exist, see the content for more details.",
847
+ "content": {
848
+ "application/json": {
849
+ "schema": {
850
+ "$ref": "#/components/schemas/NotFoundResponse"
851
+ },
852
+ "examples": {
853
+ "exampleResponse": {
854
+ "value": {
855
+ "name": "NotFoundError",
856
+ "message": "component.error",
857
+ "properties": {
858
+ "notFoundId": "1"
859
+ }
860
+ }
861
+ }
862
+ }
863
+ }
864
+ }
865
+ },
866
+ "500": {
867
+ "description": "The server has encountered a situation it does not know how to handle, see the content for more details.",
868
+ "content": {
869
+ "application/json": {
870
+ "schema": {
871
+ "$ref": "#/components/schemas/Error"
872
+ },
873
+ "examples": {
874
+ "exampleResponse": {
875
+ "value": {
876
+ "name": "InternalServerError",
877
+ "message": "component.error"
878
+ }
879
+ }
880
+ }
881
+ }
882
+ }
883
+ }
884
+ }
885
+ },
701
886
  "delete": {
702
887
  "operationId": "DocumentManagementRemove",
703
888
  "summary": "Remove an document from an auditable item graph vertex",
@@ -288,6 +288,84 @@ The documents and revisions if requested, ordered by revision descending, cursor
288
288
 
289
289
  ***
290
290
 
291
+ ### getRevision()
292
+
293
+ > **getRevision**(`auditableItemGraphDocumentId`, `revision`, `options?`, `userIdentity?`, `nodeIdentity?`): `Promise`\<`IDocument`\>
294
+
295
+ Get a document revision using it's auditable item graph vertex id.
296
+
297
+ #### Parameters
298
+
299
+ ##### auditableItemGraphDocumentId
300
+
301
+ `string`
302
+
303
+ The auditable item graph vertex id which contains the document.
304
+
305
+ ##### revision
306
+
307
+ `number`
308
+
309
+ The revision id for the document.
310
+
311
+ ##### options?
312
+
313
+ Additional options for the get operation.
314
+
315
+ ###### includeBlobStorageMetadata?
316
+
317
+ `boolean`
318
+
319
+ Flag to include the blob storage metadata for the document, defaults to false.
320
+
321
+ ###### includeBlobStorageData?
322
+
323
+ `boolean`
324
+
325
+ Flag to include the blob storage data for the document, defaults to false.
326
+
327
+ ###### includeAttestation?
328
+
329
+ `boolean`
330
+
331
+ Flag to include the attestation information for the document, defaults to false.
332
+
333
+ ###### extractRuleGroupId?
334
+
335
+ `string`
336
+
337
+ If provided will extract data from the document using the specified rule group id.
338
+
339
+ ###### extractMimeType?
340
+
341
+ `string`
342
+
343
+ By default extraction will auto detect the mime type of the document, this can be used to override the detection.
344
+
345
+ ##### userIdentity?
346
+
347
+ `string`
348
+
349
+ The identity to perform the auditable item graph operation with.
350
+
351
+ ##### nodeIdentity?
352
+
353
+ `string`
354
+
355
+ The node identity to use for vault operations.
356
+
357
+ #### Returns
358
+
359
+ `Promise`\<`IDocument`\>
360
+
361
+ The documents and revisions if requested, ordered by revision descending, cursor is set if there are more document revisions.
362
+
363
+ #### Implementation of
364
+
365
+ `IDocumentManagementComponent.getRevision`
366
+
367
+ ***
368
+
291
369
  ### removeRevision()
292
370
 
293
371
  > **removeRevision**(`auditableItemGraphDocumentId`, `revision`, `userIdentity?`, `nodeIdentity?`): `Promise`\<`void`\>
@@ -0,0 +1,31 @@
1
+ # Function: documentManagementGetRevision()
2
+
3
+ > **documentManagementGetRevision**(`httpRequestContext`, `componentName`, `request`): `Promise`\<`IDocumentManagementGetRevisionResponse`\>
4
+
5
+ Get the document revision from the auditable item graph vertex.
6
+
7
+ ## Parameters
8
+
9
+ ### httpRequestContext
10
+
11
+ `IHttpRequestContext`
12
+
13
+ The request context for the API.
14
+
15
+ ### componentName
16
+
17
+ `string`
18
+
19
+ The name of the component to use in the routes.
20
+
21
+ ### request
22
+
23
+ `IDocumentManagementGetRevisionRequest`
24
+
25
+ The request.
26
+
27
+ ## Returns
28
+
29
+ `Promise`\<`IDocumentManagementGetRevisionResponse`\>
30
+
31
+ The response object with additional http response properties.
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **documentManagementUpdate**(`httpRequestContext`, `componentName`, `request`): `Promise`\<`INoContentResponse`\>
4
4
 
5
- UPdate the document from the auditable item graph vertex.
5
+ Update the document from the auditable item graph vertex.
6
6
 
7
7
  ## Parameters
8
8
 
@@ -19,6 +19,7 @@
19
19
  - [generateRestRoutesDocumentManagement](functions/generateRestRoutesDocumentManagement.md)
20
20
  - [documentManagementCreate](functions/documentManagementCreate.md)
21
21
  - [documentManagementGet](functions/documentManagementGet.md)
22
+ - [documentManagementGetRevision](functions/documentManagementGetRevision.md)
22
23
  - [documentManagementUpdate](functions/documentManagementUpdate.md)
23
24
  - [documentManagementRemove](functions/documentManagementRemove.md)
24
25
  - [documentManagementQuery](functions/documentManagementQuery.md)
package/locales/en.json CHANGED
@@ -4,10 +4,11 @@
4
4
  "createFailed": "Failed to create document",
5
5
  "updateFailed": "Failed to update document",
6
6
  "getFailed": "Failed to get document",
7
+ "getRevisionFailed": "Failed to get document revision",
7
8
  "removeRevision": "Failed to remove document revision",
8
9
  "queryFailed": "Failed to query document",
9
10
  "documentRevisionNone": "There are no revisions in the document",
10
- "documentRevisionNotFound": "There is no revision number \"{revision}\" in the document",
11
+ "documentRevisionNotFound": "There is no revision number \"{notFoundId}\" in the document",
11
12
  "namespaceMismatch": "The namespace in the urn \"{id}\" does not match the namespace of the Document Management component \"{namespace}\""
12
13
  }
13
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/document-management-service",
3
- "version": "0.0.1-next.11",
3
+ "version": "0.0.1-next.13",
4
4
  "description": "Document management contract implementation and REST endpoint definitions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,7 +22,7 @@
22
22
  "@twin.org/crypto": "next",
23
23
  "@twin.org/data-json-ld": "next",
24
24
  "@twin.org/data-processing-models": "next",
25
- "@twin.org/document-management-models": "0.0.1-next.11",
25
+ "@twin.org/document-management-models": "0.0.1-next.13",
26
26
  "@twin.org/entity": "next",
27
27
  "@twin.org/entity-storage-models": "next",
28
28
  "@twin.org/nameof": "next",