@@ -4,6 +4,7 @@ import card, { Card, MasterTag, Tag } from '@hcengineering/card'
4
4
import core , {
5
5
Association ,
6
6
Attribute ,
7
+ BlobType ,
7
8
Class ,
8
9
Doc ,
9
10
Enum ,
@@ -29,7 +30,6 @@ export interface UnifiedDocProcessResult {
29
30
30
31
export class UnifiedDocProcessor {
31
32
private readonly metadataStorage = new MetadataStorage ( )
32
-
33
33
async importFromDirectory ( directoryPath : string ) : Promise < UnifiedDocProcessResult > {
34
34
const result : UnifiedDocProcessResult = {
35
35
docs : new Map ( ) ,
@@ -173,7 +173,11 @@ export class UnifiedDocProcessor {
173
173
masterTagAttrs : Map < string , UnifiedDoc < Attribute < MasterTag > > > ,
174
174
parentCardId ?: Ref < Card >
175
175
) : Promise < void > {
176
- const cardWithRelations = await this . createCardWithRelations ( cardProps , cardPath , masterTagId , masterTagRelations , masterTagAttrs , parentCardId , blobs )
176
+ if ( cardProps . blobs !== undefined ) {
177
+ await this . createBlobs ( cardProps . blobs , cardPath , result )
178
+ }
179
+
180
+ const cardWithRelations = await this . createCardWithRelations ( cardProps , cardPath , masterTagId , masterTagRelations , masterTagAttrs , result . files , parentCardId )
177
181
178
182
if ( cardWithRelations . length > 0 ) {
179
183
const docs = result . docs . get ( cardPath ) ?? [ ]
@@ -184,7 +188,7 @@ export class UnifiedDocProcessor {
184
188
await this . applyTags ( card , cardProps , cardPath , result )
185
189
186
190
if ( cardProps . attachments !== undefined ) {
187
- await this . processAttachments ( cardProps . attachments , cardPath , card , result )
191
+ await this . createAttachments ( cardProps . attachments , cardPath , card , result )
188
192
}
189
193
190
194
const cardDir = path . join ( path . dirname ( cardPath ) , path . basename ( cardPath , '.md' ) )
@@ -387,10 +391,12 @@ export class UnifiedDocProcessor {
387
391
masterTagId : Ref < MasterTag > ,
388
392
masterTagRelations : Map < string , RelationMetadata > , // todo: rename to masterTagsAssociations
389
393
masterTagAttrs : Map < string , UnifiedDoc < Attribute < MasterTag > > > ,
394
+ blobFiles : Map < string , UnifiedFile > ,
390
395
parentCardId ?: Ref < Card >
391
396
) : Promise < UnifiedDoc < Doc > [ ] > {
392
- const { _class, title, tags : rawTags , ...customProperties } = cardHeader
397
+ const { _class, title, blobs : rawBlobs , tags : rawTags , ...customProperties } = cardHeader
393
398
const tags = rawTags !== undefined ? ( Array . isArray ( rawTags ) ? rawTags : [ rawTags ] ) : [ ]
399
+ const blobs = rawBlobs !== undefined ? ( Array . isArray ( rawBlobs ) ? rawBlobs : [ rawBlobs ] ) : [ ]
394
400
395
401
const cardId = this . metadataStorage . getIdByAbsolutePath ( cardPath ) as Ref < Card >
396
402
const cardProps : Record < string , any > = {
@@ -400,6 +406,24 @@ export class UnifiedDocProcessor {
400
406
parent : parentCardId
401
407
}
402
408
409
+ if ( blobs . length > 0 ) {
410
+ const blobProps : Record < string , BlobType > = { }
411
+ for ( const blob of blobs ) {
412
+ const blobPath = path . resolve ( path . dirname ( cardPath ) , blob )
413
+ const blobFile = blobFiles . get ( blobPath )
414
+ if ( blobFile === undefined ) {
415
+ throw new Error ( 'Blob file not found: ' + blobPath + ' from:' + cardPath )
416
+ }
417
+ blobProps [ blobFile . _id ] = {
418
+ file : blobFile . _id ,
419
+ type : blobFile . type ,
420
+ name : blobFile . name ,
421
+ metadata : { } // todo: blobFile.metadata
422
+ }
423
+ }
424
+ cardProps . blobs = blobProps
425
+ }
426
+
403
427
const tagAssociations = new Map < string , RelationMetadata > ( )
404
428
for ( const tag of tags ) {
405
429
const tagPath = path . resolve ( path . dirname ( cardPath ) , tag )
@@ -510,28 +534,15 @@ export class UnifiedDocProcessor {
510
534
}
511
535
}
512
536
513
- private async processAttachments (
537
+ private async createAttachments (
514
538
attachments : string [ ] ,
515
539
cardPath : string ,
516
540
card : UnifiedDoc < Card > ,
517
541
result : UnifiedDocProcessResult
518
542
) : Promise < void > {
519
543
for ( const attachment of attachments ) {
520
544
const attachmentPath = path . resolve ( path . dirname ( cardPath ) , attachment )
521
- const attachmentName = path . basename ( attachmentPath )
522
- const fileId = this . metadataStorage . getIdByAbsolutePath ( attachmentPath ) as Ref < PlatformBlob >
523
- const type = contentType ( attachmentPath )
524
- const size = fs . statSync ( attachmentPath ) . size
525
-
526
- const file : UnifiedFile = {
527
- _id : fileId , // id for datastore
528
- name : attachmentName ,
529
- blobProvider : async ( ) => {
530
- const data = fs . readFileSync ( attachmentPath )
531
- const props = type !== false ? { type } : undefined
532
- return new Blob ( [ data ] , props )
533
- }
534
- }
545
+ const file = await this . createFile ( attachmentPath )
535
546
result . files . set ( attachmentPath , file )
536
547
537
548
const attachmentId = this . metadataStorage . getIdByAbsolutePath ( attachmentPath ) as Ref < Attachment >
@@ -542,18 +553,53 @@ export class UnifiedDocProcessor {
542
553
space : core . space . Workspace ,
543
554
attachedTo : card . props . _id as Ref < Card > ,
544
555
attachedToClass : card . _class ,
545
- file : fileId ,
546
- name : attachmentName ,
556
+ file : file . _id ,
557
+ name : file . name ,
547
558
collection : 'attachments' ,
548
559
lastModified : Date . now ( ) ,
549
- type : type !== false ? type : 'application/octet-stream' ,
550
- size
560
+ type : file . type ,
561
+ size : file . size
551
562
}
552
563
}
553
564
result . docs . set ( attachmentPath , [ attachmentDoc ] )
554
565
}
555
566
}
556
567
568
+ private async createBlobs (
569
+ blobs : string [ ] ,
570
+ cardPath : string ,
571
+ result : UnifiedDocProcessResult
572
+ ) : Promise < void > {
573
+ for ( const blob of blobs ) {
574
+ const blobPath = path . resolve ( path . dirname ( cardPath ) , blob )
575
+ const file = await this . createFile ( blobPath )
576
+ result . files . set ( blobPath , file )
577
+ }
578
+ }
579
+
580
+ private async createFile (
581
+ fileAbsPath : string
582
+ ) : Promise < UnifiedFile > {
583
+ // const fileAbsPath = path.resolve(path.dirname(currentPath), filePath)
584
+ const fileName = path . basename ( fileAbsPath )
585
+ const fileId = this . metadataStorage . getIdByAbsolutePath ( fileAbsPath ) as Ref < PlatformBlob >
586
+ const type = contentType ( fileName )
587
+ const size = fs . statSync ( fileAbsPath ) . size
588
+
589
+ const file : UnifiedFile = {
590
+ _id : fileId , // id for datastore
591
+ name : fileName ,
592
+ type : type !== false ? type : 'application/octet-stream' ,
593
+ size, // todo: make sure this one is needed
594
+ blobProvider : async ( ) => {
595
+ const data = fs . readFileSync ( fileAbsPath )
596
+ const props = type !== false ? { type } : undefined
597
+ return new Blob ( [ data ] , props )
598
+ }
599
+ }
600
+ return file
601
+ }
602
+
557
603
private async createAssociation (
558
604
yamlPath : string ,
559
605
yamlConfig : Record < string , any >
0 commit comments