@solidstarters/solid-core 1.2.149 → 1.2.151

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.
Files changed (82) hide show
  1. package/dist/dtos/create-scheduled-job.dto.d.ts +1 -0
  2. package/dist/dtos/create-scheduled-job.dto.d.ts.map +1 -1
  3. package/dist/dtos/create-scheduled-job.dto.js +5 -1
  4. package/dist/dtos/create-scheduled-job.dto.js.map +1 -1
  5. package/dist/dtos/create-user.dto.js +3 -3
  6. package/dist/dtos/create-user.dto.js.map +1 -1
  7. package/dist/dtos/update-scheduled-job.dto.d.ts +1 -0
  8. package/dist/dtos/update-scheduled-job.dto.d.ts.map +1 -1
  9. package/dist/dtos/update-scheduled-job.dto.js +5 -1
  10. package/dist/dtos/update-scheduled-job.dto.js.map +1 -1
  11. package/dist/entities/scheduled-job.entity.d.ts +2 -0
  12. package/dist/entities/scheduled-job.entity.d.ts.map +1 -1
  13. package/dist/entities/scheduled-job.entity.js +8 -1
  14. package/dist/entities/scheduled-job.entity.js.map +1 -1
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts.map +1 -1
  20. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js +4 -1
  21. package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js.map +1 -1
  22. package/dist/repository/scheduled-job.repository.d.ts +29 -0
  23. package/dist/repository/scheduled-job.repository.d.ts.map +1 -0
  24. package/dist/repository/scheduled-job.repository.js +85 -0
  25. package/dist/repository/scheduled-job.repository.js.map +1 -0
  26. package/dist/seeders/module-metadata-seeder.service.d.ts +4 -1
  27. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  28. package/dist/seeders/module-metadata-seeder.service.js +20 -2
  29. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  30. package/dist/seeders/seed-data/solid-core-metadata.json +156 -78
  31. package/dist/services/ai-interaction.service.d.ts +1 -1
  32. package/dist/services/ai-interaction.service.d.ts.map +1 -1
  33. package/dist/services/ai-interaction.service.js +4 -3
  34. package/dist/services/ai-interaction.service.js.map +1 -1
  35. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts.map +1 -1
  36. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js +16 -12
  37. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js.map +1 -1
  38. package/dist/services/media.service.d.ts.map +1 -1
  39. package/dist/services/media.service.js +2 -2
  40. package/dist/services/media.service.js.map +1 -1
  41. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +3 -2
  42. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
  43. package/dist/services/mediaStorageProviders/file-storage-provider.js +6 -4
  44. package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
  45. package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
  46. package/dist/services/scheduled-jobs/scheduler.service.js +1 -1
  47. package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
  48. package/dist/services/textract.service.d.ts +20 -0
  49. package/dist/services/textract.service.d.ts.map +1 -0
  50. package/dist/services/textract.service.js +199 -0
  51. package/dist/services/textract.service.js.map +1 -0
  52. package/dist/solid-core.module.d.ts.map +1 -1
  53. package/dist/solid-core.module.js +7 -0
  54. package/dist/solid-core.module.js.map +1 -1
  55. package/dist/subscribers/scheduled-job.subscriber.d.ts +19 -0
  56. package/dist/subscribers/scheduled-job.subscriber.d.ts.map +1 -0
  57. package/dist/subscribers/scheduled-job.subscriber.js +175 -0
  58. package/dist/subscribers/scheduled-job.subscriber.js.map +1 -0
  59. package/dist/tsconfig.tsbuildinfo +1 -1
  60. package/package.json +2 -1
  61. package/src/dtos/create-scheduled-job.dto.ts +3 -0
  62. package/src/dtos/create-user.dto.ts +2 -2
  63. package/src/dtos/update-scheduled-job.dto.ts +3 -0
  64. package/src/entities/scheduled-job.entity.ts +7 -2
  65. package/src/index.ts +1 -0
  66. package/src/jobs/database/trigger-mcp-client-subscriber-database.service.ts +8 -1
  67. package/src/repository/scheduled-job.repository.ts +94 -0
  68. package/src/seeders/module-metadata-seeder.service.ts +20 -1
  69. package/src/seeders/seed-data/solid-core-metadata.json +156 -78
  70. package/src/services/ai-interaction.service.ts +4 -3
  71. package/src/services/computed-fields/entity/concat-entity-computed-field-provider.service.ts +28 -18
  72. package/src/services/media.service.ts +2 -3
  73. package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +2 -2
  74. package/src/services/mediaStorageProviders/file-storage-provider.ts +4 -4
  75. package/src/services/scheduled-jobs/scheduler.service.ts +2 -2
  76. package/src/services/textract.service.ts +189 -0
  77. package/src/solid-core.module.ts +7 -0
  78. package/src/subscribers/scheduled-job.subscriber.ts +176 -0
  79. package/src/# computed field pending issues.md +0 -3
  80. package/src/services/pending_import_issues +0 -3
  81. package/src/services/question-data-providers/test.sql +0 -1
  82. package/test.json +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"file-s3-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-s3-storage-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable, Logger } from \"@nestjs/common\";\nimport { ConfigService, ConfigType } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { FileService } from \"src/services/file.service\";\nimport { Readable } from \"stream\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport commonConfig from \"src/config/common.config\";\n\n@Injectable()\nexport class FileS3StorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileS3StorageProvider.name);\n\n constructor(\n // @Inject(appBuilderConfig.KEY)\n // private readonly appBuilderConfiguration: ConfigType<typeof appBuilderConfig>,\n private readonly configService: ConfigService,\n readonly fileService: FileService,\n readonly mediaRepository: MediaRepository,\n @Inject(commonConfig.KEY)\n private readonly commonConfiguration: ConfigType<typeof commonConfig>,\n ) { }\n\n storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n throw new Error(\"Method not implemented.\");\n }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n\n // TODO: Check if the mediaStorageProvider (s3 in this case) is configured with a public bucket or not. \n // If private bucket then we need to return a \"signed-url\", the timeout for the signed url can be configured in the media storage provider entity and modified using the CRUD interface.\n // Add the full URL to the media\n for (const m of media) {\n const storageMeta = m.mediaStorageProviderMetadata;\n if (storageMeta.isPublic === false) {\n // Generate signed URL\n const expiryInSeconds = (storageMeta.signedUrlExpiry ?? 60) * 60; // default 5 min\n m['_full_url'] = await this.fileService.getSignedUrl(m.relativeUri, expiryInSeconds, storageMeta?.bucketName);\n } else {\n // Public S3 or local filesystem: use normal URL\n m['_full_url'] = this.getFullFilePath(m);\n }\n }\n\n return media;\n // media.forEach(m => {\n // m['_full_url'] = this.getFullFilePath(m);\n // });\n // return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n files.forEach(async (file) => {\n const fileName = this.getFileName(file);\n // Store the file in the configured S3 Bucket\n let awsFileUrl;\n if (mediaFieldMetadata.mediaStorageProvider.isPublic === true) {\n awsFileUrl = await this.fileService.copyToS3WithPublic(file.path, file.mimetype, fileName, mediaFieldMetadata.mediaStorageProvider.bucketName,);\n } else {\n awsFileUrl = await this.fileService.copyToS3(file.path, file.mimetype, fileName, mediaFieldMetadata.mediaStorageProvider.bucketName,);\n }\n await this.fileService.deleteFile(file.path);\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia({\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: awsFileUrl,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n });\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n existingMedia.forEach(media => {\n this.fileService.deleteFromS3(media.relativeUri, mediaFieldMetadata.mediaStorageProvider.bucketName); //TODO\n });\n }\n\n //TODO: Move this to a app builder config\n private getFullFilePath(media: Media): string {\n // https://lunarismedia.s3.ap-south-1.amazonaws.com/LUNARIS_CP_REGISTRATION_CREATIVE.jpg\n return `https://${media.mediaStorageProviderMetadata.bucketName}.s3.${this.configService.get('S3_AWS_REGION_NAME')}.amazonaws.com/${media.relativeUri}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n}"]}
1
+ {"version":3,"file":"file-s3-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-s3-storage-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable, Logger } from \"@nestjs/common\";\nimport { ConfigService, ConfigType } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { FileService } from \"src/services/file.service\";\nimport { Readable } from \"stream\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport commonConfig from \"src/config/common.config\";\n\n@Injectable()\nexport class FileS3StorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileS3StorageProvider.name);\n\n constructor(\n // @Inject(appBuilderConfig.KEY)\n // private readonly appBuilderConfiguration: ConfigType<typeof appBuilderConfig>,\n private readonly configService: ConfigService,\n readonly fileService: FileService,\n readonly mediaRepository: MediaRepository,\n @Inject(commonConfig.KEY)\n private readonly commonConfiguration: ConfigType<typeof commonConfig>,\n ) { }\n\n storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n throw new Error(\"Method not implemented.\");\n }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n\n // TODO: Check if the mediaStorageProvider (s3 in this case) is configured with a public bucket or not. \n // If private bucket then we need to return a \"signed-url\", the timeout for the signed url can be configured in the media storage provider entity and modified using the CRUD interface.\n // Add the full URL to the media\n for (const m of media) {\n const storageMeta = m.mediaStorageProviderMetadata;\n if (storageMeta.isPublic === false) {\n // Generate signed URL\n const expiryInSeconds = (storageMeta.signedUrlExpiry ?? 60) * 60; // default 5 min\n m['_full_url'] = await this.fileService.getSignedUrl(m.relativeUri, expiryInSeconds, storageMeta?.bucketName);\n } else {\n // Public S3 or local filesystem: use normal URL\n m['_full_url'] = this.getFullFilePath(m);\n }\n }\n\n return media;\n // media.forEach(m => {\n // m['_full_url'] = this.getFullFilePath(m);\n // });\n // return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n for (const file of files) {\n const fileName = this.getFileName(file);\n // Store the file in the configured S3 Bucket\n let awsFileUrl;\n if (mediaFieldMetadata.mediaStorageProvider.isPublic === true) {\n awsFileUrl = await this.fileService.copyToS3WithPublic(file.path, file.mimetype, fileName, mediaFieldMetadata.mediaStorageProvider.bucketName,);\n } else {\n awsFileUrl = await this.fileService.copyToS3(file.path, file.mimetype, fileName, mediaFieldMetadata.mediaStorageProvider.bucketName,);\n }\n await this.fileService.deleteFile(file.path);\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia({\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: awsFileUrl,\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n existingMedia.forEach(media => {\n this.fileService.deleteFromS3(media.relativeUri, mediaFieldMetadata.mediaStorageProvider.bucketName); //TODO\n });\n }\n\n //TODO: Move this to a app builder config\n private getFullFilePath(media: Media): string {\n // https://lunarismedia.s3.ap-south-1.amazonaws.com/LUNARIS_CP_REGISTRATION_CREATIVE.jpg\n return `https://${media.mediaStorageProviderMetadata.bucketName}.s3.${this.configService.get('S3_AWS_REGION_NAME')}.amazonaws.com/${media.relativeUri}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n}"]}
@@ -38,7 +38,7 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
38
38
  throw new Error("Entity must be an instance of CommonEntity");
39
39
  }
40
40
  const result = [];
41
- files.forEach(async (file) => {
41
+ for (const file of files) {
42
42
  const fileStoragePath = this.getFullFilePath(this.getFileName(file));
43
43
  await this.fileService.copyFile(file.path, fileStoragePath);
44
44
  await this.fileService.deleteFile(file.path);
@@ -54,7 +54,8 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
54
54
  });
55
55
  result.push(mediaEntity);
56
56
  this.logger.debug(`Stored media with`, mediaEntity);
57
- });
57
+ }
58
+ ;
58
59
  return result;
59
60
  }
60
61
  async storeStreams(streamPairs, entity, mediaFieldMetadata) {
@@ -62,7 +63,7 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
62
63
  throw new Error("Entity must be an instance of CommonEntity");
63
64
  }
64
65
  const result = [];
65
- streamPairs.forEach(async (pair) => {
66
+ for (const pair of streamPairs) {
66
67
  const stream = pair[0];
67
68
  const fileName = pair[1];
68
69
  this.fileService.writeStreamToFile(stream, this.getFullFilePath(fileName));
@@ -74,7 +75,8 @@ let FileStorageProvider = FileStorageProvider_1 = class FileStorageProvider {
74
75
  fieldMetadataId: mediaFieldMetadata.id
75
76
  });
76
77
  this.logger.debug(`Stored media with`, mediaEntity);
77
- });
78
+ }
79
+ ;
78
80
  return result;
79
81
  }
80
82
  async delete(entity, mediaFieldMetadata) {
@@ -1 +1 @@
1
- {"version":3,"file":"file-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-storage-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { ConfigService } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport { FileService } from \"src/services/file.service\";\nimport { Readable } from \"stream\";\n\n@Injectable()\nexport class FileStorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileStorageProvider.name);\n\n constructor(\n // @Inject(appBuilderConfig.KEY)\n // private readonly appBuilderConfiguration: ConfigType<typeof appBuilderConfig>,\n private readonly configService: ConfigService,\n readonly fileService: FileService,\n readonly mediaRepository: MediaRepository\n\n ) { }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // Add the full URL to the media\n media.forEach(m => {\n m['_full_url'] = `${process.env.BASE_URL}/${this.getFullFilePath(m.relativeUri)}`;\n });\n return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n files.forEach(async (file) => {\n // Store the file in the configured file storage directory\n const fileStoragePath = this.getFullFilePath(this.getFileName(file));\n await this.fileService.copyFile(file.path, fileStoragePath);\n await this.fileService.deleteFile(file.path);\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia({\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: this.getFileName(file),\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n });\n return result;\n }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n streamPairs.forEach(async (pair) => {\n const stream = pair[0];\n const fileName = pair[1];\n this.fileService.writeStreamToFile(stream, this.getFullFilePath(fileName));\n const mediaEntity = await this.mediaRepository.createMedia({\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: fileName,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\n this.logger.debug(`Stored media with`, mediaEntity);\n });\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n existingMedia.forEach(media => {\n this.fileService.deleteFile(this.getFullFilePath(media.relativeUri));\n });\n }\n\n private getFullFilePath(fileName: string): string {\n return `${this.configService.get('app-builder.fileStorageDir')}/${fileName}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n}"]}
1
+ {"version":3,"file":"file-storage-provider.js","sourceRoot":"","sources":["../../../src/services/mediaStorageProviders/file-storage-provider.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,2CAA+C;AAC/C,gEAA0D;AAI1D,wEAAkE;AAClE,kDAAwD;AAIjD,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAG5B,YAGqB,aAA4B,EACpC,WAAwB,EACxB,eAAgC;QAFxB,kBAAa,GAAb,aAAa,CAAe;QACpC,gBAAW,GAAX,WAAW,CAAa;QACxB,oBAAe,GAAf,eAAe,CAAiB;QAPrC,WAAM,GAAG,IAAI,eAAM,CAAC,qBAAmB,CAAC,IAAI,CAAC,CAAC;IASlD,CAAC;IAEL,KAAK,CAAC,QAAQ,CAAC,MAAS,EAAE,kBAAiC;QACvD,IAAI,CAAC,CAAC,MAAM,YAAY,4BAAY,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,0CAA0C,CAAC,MAAM,CAAC,EAAE,EAAE,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAErL,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACd,CAAC,CAAC,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;QACtF,CAAC,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAA4B,EAAE,MAAS,EAAE,kBAAiC;QAClF,IAAI,CAAC,CAAC,MAAM,YAAY,4BAAY,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAEvB,MAAM,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;YACrE,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YAC5D,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAG7C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;gBACvD,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,eAAe,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE;gBAC5C,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,gBAAgB,EAAE,IAAI,CAAC,YAAY;gBACnC,8BAA8B,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,EAAE;gBAC1E,eAAe,EAAE,kBAAkB,CAAC,EAAE;aACzC,CAAqB,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC;QAAA,CAAC;QACF,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,WAAiC,EAAE,MAAS,EAAE,kBAAiC;QAC9F,IAAI,CAAC,CAAC,MAAM,YAAY,4BAAY,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,MAAM,GAAY,EAAE,CAAC;QAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC3E,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;gBACvD,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,eAAe,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE;gBAC5C,WAAW,EAAE,QAAQ;gBACrB,8BAA8B,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,EAAE;gBAC1E,eAAe,EAAE,kBAAkB,CAAC,EAAE;aACzC,CAAqB,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC;QAAA,CAAC;QACF,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAS,EAAE,kBAAiC;QACrD,IAAI,CAAC,CAAC,MAAM,YAAY,4BAAY,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,0CAA0C,CAAC,MAAM,CAAC,EAAE,EAAE,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAC7L,IAAI,CAAC,eAAe,CAAC,4CAA4C,CAAC,MAAM,CAAC,EAAE,EAAE,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjI,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC1B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,eAAe,CAAC,QAAgB;QACpC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,4BAA4B,CAAC,IAAI,QAAQ,EAAE,CAAC;IACjF,CAAC;IAEO,WAAW,CAAC,IAAyB;QACzC,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;IACnD,CAAC;CACJ,CAAA;AA3FY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;qCAO2B,sBAAa;QACvB,0BAAW;QACP,kCAAe;GARpC,mBAAmB,CA2F/B","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { ConfigService } from \"@nestjs/config\";\nimport { CommonEntity } from \"src/entities/common.entity\";\nimport { FieldMetadata } from \"src/entities/field-metadata.entity\";\nimport { Media } from \"src/entities/media.entity\";\nimport { MediaStorageProvider } from \"src/interfaces\";\nimport { MediaRepository } from \"src/repository/media.repository\";\nimport { FileService } from \"src/services/file.service\";\nimport { Readable } from \"stream\";\n\n@Injectable()\nexport class FileStorageProvider<T> implements MediaStorageProvider<T> {\n private logger = new Logger(FileStorageProvider.name);\n\n constructor(\n // @Inject(appBuilderConfig.KEY)\n // private readonly appBuilderConfiguration: ConfigType<typeof appBuilderConfig>,\n private readonly configService: ConfigService,\n readonly fileService: FileService,\n readonly mediaRepository: MediaRepository\n\n ) { }\n\n async retrieve(entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const media = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n // Add the full URL to the media\n media.forEach(m => {\n m['_full_url'] = `${process.env.BASE_URL}/${this.getFullFilePath(m.relativeUri)}`;\n });\n return media;\n }\n\n async store(files: Express.Multer.File[], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n for (const file of files) {\n // Store the file in the configured file storage directory\n const fileStoragePath = this.getFullFilePath(this.getFileName(file));\n await this.fileService.copyFile(file.path, fileStoragePath);\n await this.fileService.deleteFile(file.path);\n\n // Create an entry in the media table\n const mediaEntity = await this.mediaRepository.createMedia({\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: this.getFileName(file),\n mimeType: file.mimetype,\n fileSize: file.size,\n originalFileName: file.originalname,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\n result.push(mediaEntity);\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async storeStreams(streamPairs: [Readable, string][], entity: T, mediaFieldMetadata: FieldMetadata): Promise<Media[]> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const result: Media[] = [];\n for (const pair of streamPairs) {\n const stream = pair[0];\n const fileName = pair[1];\n this.fileService.writeStreamToFile(stream, this.getFullFilePath(fileName));\n const mediaEntity = await this.mediaRepository.createMedia({\n entityId: entity.id,\n modelMetadataId: mediaFieldMetadata.model.id,\n relativeUri: fileName,\n mediaStorageProviderMetadataId: mediaFieldMetadata.mediaStorageProvider.id,\n fieldMetadataId: mediaFieldMetadata.id\n }) as unknown as Media;\n this.logger.debug(`Stored media with`, mediaEntity);\n };\n return result;\n }\n\n async delete(entity: T, mediaFieldMetadata: FieldMetadata): Promise<void> {\n if (!(entity instanceof CommonEntity)) {\n throw new Error(\"Entity must be an instance of CommonEntity\"); //FIXME This needs to be handled through generics. e.g T extends CommonEntity\n }\n const existingMedia = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id, ['mediaStorageProviderMetadata']);\n this.mediaRepository.deleteByEntityIdAndFieldIdAndModelMetadataId(entity.id, mediaFieldMetadata.id, mediaFieldMetadata.model.id);\n existingMedia.forEach(media => {\n this.fileService.deleteFile(this.getFullFilePath(media.relativeUri));\n });\n }\n\n private getFullFilePath(fileName: string): string {\n return `${this.configService.get('app-builder.fileStorageDir')}/${fileName}`;\n }\n\n private getFileName(file: Express.Multer.File): string {\n return `${file.filename}-${file.originalname}`;\n }\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.service.d.ts","sourceRoot":"","sources":["../../../src/services/scheduled-jobs/scheduler.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,UAAU,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAIjE,qBACa,oBAAqB,YAAW,iBAAiB;IAKtD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa;IALlC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;gBAI3C,gBAAgB,EAAE,UAAU,CAAC,YAAY,CAAC,EAC1C,aAAa,EAAE,aAAa;IAI3C,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDvC,OAAO,CAAC,YAAY;IAmCpB,OAAO,CAAC,gBAAgB;CAyB3B"}
1
+ {"version":3,"file":"scheduler.service.d.ts","sourceRoot":"","sources":["../../../src/services/scheduled-jobs/scheduler.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,UAAU,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAIjE,qBACa,oBAAqB,YAAW,iBAAiB;IAKtD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa;IALlC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyC;gBAI3C,gBAAgB,EAAE,UAAU,CAAC,YAAY,CAAC,EAC1C,aAAa,EAAE,aAAa;IAI3C,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAmDvC,OAAO,CAAC,YAAY;IAmCpB,OAAO,CAAC,gBAAgB;CAyB3B"}
@@ -36,7 +36,7 @@ let SchedulerServiceImpl = SchedulerServiceImpl_1 = class SchedulerServiceImpl {
36
36
  },
37
37
  {
38
38
  isActive: true,
39
- nextRunAt: null,
39
+ nextRunAt: (0, typeorm_2.IsNull)(),
40
40
  },
41
41
  ],
42
42
  });
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.service.js","sourceRoot":"","sources":["../../../src/services/scheduled-jobs/scheduler.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger, Inject } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { LessThanOrEqual, Repository } from 'typeorm';\n\nimport { ISchedulerService } from './scheduler.interface';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { ScheduledJob } from 'src/entities/scheduled-job.entity';\nimport { IScheduledJob } from './scheduled-job.interface';\nimport { Cron, CronExpression } from '@nestjs/schedule';\n\n@Injectable()\nexport class SchedulerServiceImpl implements ISchedulerService {\n private readonly logger = new Logger(SchedulerServiceImpl.name);\n\n constructor(\n @InjectRepository(ScheduledJob)\n private readonly scheduledJobRepo: Repository<ScheduledJob>,\n private readonly solidRegistry: SolidRegistry,\n ) { }\n\n @Cron(CronExpression.EVERY_MINUTE)\n async runScheduledJobs(): Promise<void> {\n const now = new Date();\n\n // this.logger.log(`[${now.getTime()}]: scheduler service started run...`);\n const dueJobs = await this.scheduledJobRepo.find({\n where: [\n {\n isActive: true,\n nextRunAt: LessThanOrEqual(now),\n },\n // Newly created jobs are also picked for examination \n {\n isActive: true,\n nextRunAt: null,\n },\n ],\n });\n\n // this.logger.log(`[${now.getTime()}]: scheduler service identified ${dueJobs.length} jobs to run...`);\n\n for (const job of dueJobs) {\n this.logger.log(`[${now.getTime()}]: scheduler service attempting to run job ${job.job}`);\n try {\n if (!this.shouldRunNow(job, now)) {\n this.logger.log(`[${now.getTime()}]: scheduler service skipping job ${job.job}`);\n continue;\n }\n\n const handler = this.solidRegistry.getScheduledJobProviderInstance(job.job);\n if (!handler) {\n // this.logger.warn(`[${now.getTime()}]: scheduler service skipping because job handler not found: ${job.job}`);\n continue;\n }\n\n // this.logger.log(`[${now.getTime()}]: scheduler service about to run job ${job.job}`);\n await handler.execute(job);\n // this.logger.log(`[${now.getTime()}]: scheduler service finished running job ${job.job}`);\n\n job.isActive = true;\n job.lastRunAt = now;\n job.nextRunAt = this.computeNextRunAt(job, now);\n this.logger.log(`[${now.getTime()}]: scheduler service coomputed next run for ${job.job} as ${job.nextRunAt}`);\n\n await this.scheduledJobRepo.save(job);\n this.logger.log(`[${now.getTime()}]: scheduler service finished running job: ${job.job}`);\n } catch (err) {\n this.logger.error(`[${now.getTime()}]: scheduler service failed to run job ${job.job}`, err.stack);\n }\n }\n }\n\n private shouldRunNow(job: ScheduledJob, now: Date): boolean {\n const today = now.toISOString().split('T')[0]; // yyyy-mm-dd\n const timeNow = now.toTimeString().slice(0, 5); // hh:mm\n\n // 1. Check startDate / endDate\n if (job.startDate && new Date(today) < new Date(job.startDate)) return false;\n if (job.endDate && new Date(today) > new Date(job.endDate)) return false;\n\n // 2. Check startTime / endTime\n if (job.startTime) {\n const jobStart = job.startTime.toTimeString().slice(0, 5);\n if (timeNow < jobStart) return false;\n }\n if (job.endTime) {\n const jobEnd = job.endTime.toTimeString().slice(0, 5);\n if (timeNow > jobEnd) return false;\n }\n\n // 3. Check dayOfWeek (for weekly)\n if (job.frequency.toLowerCase() === 'weekly' && job.dayOfWeek) {\n const todayName = now.toLocaleString('en-US', { weekday: 'long' }); // e.g., \"Monday\"\n // const days = job.dayOfWeek.split(',').map(d => d.trim());\n const days = JSON.parse(job.dayOfWeek) as string[];\n if (!days.includes(todayName)) return false;\n }\n\n // 4. Check dayOfMonth (for monthly)\n if (job.frequency.toLowerCase() === 'monthly' && job.dayOfMonth) {\n const dom = now.getDate();\n if (dom !== job.dayOfMonth) return false;\n }\n\n return true;\n }\n\n private computeNextRunAt(job: ScheduledJob, from: Date): Date {\n const base = new Date(from);\n\n switch (job.frequency.toLowerCase()) {\n // case 'once':\n // return null; // don't reschedule\n case 'every minute':\n return new Date(base.getTime() + 1 * 60 * 1000);\n case 'hourly':\n return new Date(base.getTime() + 60 * 60 * 1000);\n case 'daily':\n return new Date(base.getTime() + 24 * 60 * 60 * 1000);\n case 'weekly':\n return new Date(base.getTime() + 7 * 24 * 60 * 60 * 1000);\n case 'monthly':\n const next = new Date(base);\n next.setMonth(base.getMonth() + 1);\n return next;\n // case 'custom':\n // // Optional: let job handler decide via metadata or registry\n // return new Date(base.getTime() + 24 * 60 * 60 * 1000);\n default:\n return new Date(base.getTime() + 24 * 60 * 60 * 1000);\n }\n }\n}"]}
1
+ {"version":3,"file":"scheduler.service.js","sourceRoot":"","sources":["../../../src/services/scheduled-jobs/scheduler.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAA4D;AAC5D,6CAAmD;AACnD,qCAA8D;AAG9D,iEAA2D;AAC3D,8EAAiE;AAEjE,+CAAwD;AAGjD,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAG7B,YAEI,gBAA2D,EAC1C,aAA4B;QAD5B,qBAAgB,GAAhB,gBAAgB,CAA0B;QAC1C,kBAAa,GAAb,aAAa,CAAe;QALhC,WAAM,GAAG,IAAI,eAAM,CAAC,sBAAoB,CAAC,IAAI,CAAC,CAAC;IAM5D,CAAC;IAGC,AAAN,KAAK,CAAC,gBAAgB;QAClB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QAGvB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;YAC7C,KAAK,EAAE;gBACH;oBACI,QAAQ,EAAE,IAAI;oBACd,SAAS,EAAE,IAAA,yBAAe,EAAC,GAAG,CAAC;iBAClC;gBAED;oBACI,QAAQ,EAAE,IAAI;oBACd,SAAS,EAAE,IAAA,gBAAM,GAAE;iBACtB;aACJ;SACJ,CAAC,CAAC;QAIH,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,8CAA8C,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC;gBACD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;oBAC/B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,qCAAqC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;oBACjF,SAAS;gBACb,CAAC;gBAED,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,+BAA+B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC5E,IAAI,CAAC,OAAO,EAAE,CAAC;oBAEX,SAAS;gBACb,CAAC;gBAGD,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAG3B,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACpB,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC;gBACpB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAChD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,+CAA+C,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;gBAE/G,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,8CAA8C,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YAC9F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,0CAA0C,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;YACvG,CAAC;QACL,CAAC;IACL,CAAC;IAEO,YAAY,CAAC,GAAiB,EAAE,GAAS;QAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAG/C,IAAI,GAAG,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7E,IAAI,GAAG,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QAGzE,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,IAAI,OAAO,GAAG,QAAQ;gBAAE,OAAO,KAAK,CAAC;QACzC,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACtD,IAAI,OAAO,GAAG,MAAM;gBAAE,OAAO,KAAK,CAAC;QACvC,CAAC;QAGD,IAAI,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,QAAQ,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAC5D,MAAM,SAAS,GAAG,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAEnE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAa,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,OAAO,KAAK,CAAC;QAChD,CAAC;QAGD,IAAI,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YAC9D,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC;YAC1B,IAAI,GAAG,KAAK,GAAG,CAAC,UAAU;gBAAE,OAAO,KAAK,CAAC;QAC7C,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,gBAAgB,CAAC,GAAiB,EAAE,IAAU;QAClD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5B,QAAQ,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;YAGlC,KAAK,cAAc;gBACf,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YACpD,KAAK,QAAQ;gBACT,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YACrD,KAAK,OAAO;gBACR,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1D,KAAK,QAAQ;gBACT,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAC9D,KAAK,SAAS;gBACV,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC;gBACnC,OAAO,IAAI,CAAC;YAIhB;gBACI,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;CACJ,CAAA;AAzHY,oDAAoB;AAUvB;IADL,IAAA,eAAI,EAAC,yBAAc,CAAC,YAAY,CAAC;;;;4DAkDjC;+BA3DQ,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IAKJ,WAAA,IAAA,0BAAgB,EAAC,mCAAY,CAAC,CAAA;qCACI,oBAAU;QACb,8BAAa;GANxC,oBAAoB,CAyHhC","sourcesContent":["import { Injectable, Logger, Inject } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { IsNull, LessThanOrEqual, Repository } from 'typeorm';\n\nimport { ISchedulerService } from './scheduler.interface';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { ScheduledJob } from 'src/entities/scheduled-job.entity';\nimport { IScheduledJob } from './scheduled-job.interface';\nimport { Cron, CronExpression } from '@nestjs/schedule';\n\n@Injectable()\nexport class SchedulerServiceImpl implements ISchedulerService {\n private readonly logger = new Logger(SchedulerServiceImpl.name);\n\n constructor(\n @InjectRepository(ScheduledJob)\n private readonly scheduledJobRepo: Repository<ScheduledJob>,\n private readonly solidRegistry: SolidRegistry,\n ) { }\n\n @Cron(CronExpression.EVERY_MINUTE)\n async runScheduledJobs(): Promise<void> {\n const now = new Date();\n\n // this.logger.log(`[${now.getTime()}]: scheduler service started run...`);\n const dueJobs = await this.scheduledJobRepo.find({\n where: [\n {\n isActive: true,\n nextRunAt: LessThanOrEqual(now),\n },\n // Newly created jobs are also picked for examination \n {\n isActive: true,\n nextRunAt: IsNull(),\n },\n ],\n });\n\n // this.logger.log(`[${now.getTime()}]: scheduler service identified ${dueJobs.length} jobs to run...`);\n\n for (const job of dueJobs) {\n this.logger.log(`[${now.getTime()}]: scheduler service attempting to run job ${job.job}`);\n try {\n if (!this.shouldRunNow(job, now)) {\n this.logger.log(`[${now.getTime()}]: scheduler service skipping job ${job.job}`);\n continue;\n }\n\n const handler = this.solidRegistry.getScheduledJobProviderInstance(job.job);\n if (!handler) {\n // this.logger.warn(`[${now.getTime()}]: scheduler service skipping because job handler not found: ${job.job}`);\n continue;\n }\n\n // this.logger.log(`[${now.getTime()}]: scheduler service about to run job ${job.job}`);\n await handler.execute(job);\n // this.logger.log(`[${now.getTime()}]: scheduler service finished running job ${job.job}`);\n\n job.isActive = true;\n job.lastRunAt = now;\n job.nextRunAt = this.computeNextRunAt(job, now);\n this.logger.log(`[${now.getTime()}]: scheduler service coomputed next run for ${job.job} as ${job.nextRunAt}`);\n\n await this.scheduledJobRepo.save(job);\n this.logger.log(`[${now.getTime()}]: scheduler service finished running job: ${job.job}`);\n } catch (err) {\n this.logger.error(`[${now.getTime()}]: scheduler service failed to run job ${job.job}`, err.stack);\n }\n }\n }\n\n private shouldRunNow(job: ScheduledJob, now: Date): boolean {\n const today = now.toISOString().split('T')[0]; // yyyy-mm-dd\n const timeNow = now.toTimeString().slice(0, 5); // hh:mm\n\n // 1. Check startDate / endDate\n if (job.startDate && new Date(today) < new Date(job.startDate)) return false;\n if (job.endDate && new Date(today) > new Date(job.endDate)) return false;\n\n // 2. Check startTime / endTime\n if (job.startTime) {\n const jobStart = job.startTime.toTimeString().slice(0, 5);\n if (timeNow < jobStart) return false;\n }\n if (job.endTime) {\n const jobEnd = job.endTime.toTimeString().slice(0, 5);\n if (timeNow > jobEnd) return false;\n }\n\n // 3. Check dayOfWeek (for weekly)\n if (job.frequency.toLowerCase() === 'weekly' && job.dayOfWeek) {\n const todayName = now.toLocaleString('en-US', { weekday: 'long' }); // e.g., \"Monday\"\n // const days = job.dayOfWeek.split(',').map(d => d.trim());\n const days = JSON.parse(job.dayOfWeek) as string[];\n if (!days.includes(todayName)) return false;\n }\n\n // 4. Check dayOfMonth (for monthly)\n if (job.frequency.toLowerCase() === 'monthly' && job.dayOfMonth) {\n const dom = now.getDate();\n if (dom !== job.dayOfMonth) return false;\n }\n\n return true;\n }\n\n private computeNextRunAt(job: ScheduledJob, from: Date): Date {\n const base = new Date(from);\n\n switch (job.frequency.toLowerCase()) {\n // case 'once':\n // return null; // don't reschedule\n case 'every minute':\n return new Date(base.getTime() + 1 * 60 * 1000);\n case 'hourly':\n return new Date(base.getTime() + 60 * 60 * 1000);\n case 'daily':\n return new Date(base.getTime() + 24 * 60 * 60 * 1000);\n case 'weekly':\n return new Date(base.getTime() + 7 * 24 * 60 * 60 * 1000);\n case 'monthly':\n const next = new Date(base);\n next.setMonth(base.getMonth() + 1);\n return next;\n // case 'custom':\n // // Optional: let job handler decide via metadata or registry\n // return new Date(base.getTime() + 24 * 60 * 60 * 1000);\n default:\n return new Date(base.getTime() + 24 * 60 * 60 * 1000);\n }\n }\n}"]}
@@ -0,0 +1,20 @@
1
+ import { ConfigType } from '@nestjs/config';
2
+ import commonConfig from '../config/common.config';
3
+ import { Block as TextractBlock } from '@aws-sdk/client-textract';
4
+ export declare class TextractService {
5
+ private readonly commonConfiguration;
6
+ private readonly logger;
7
+ private readonly textractClient;
8
+ private readonly s3Client;
9
+ constructor(commonConfiguration: ConfigType<typeof commonConfig>);
10
+ private isValidS3Config;
11
+ uploadToS3(localPath: string, bucket: string, key: string): Promise<void>;
12
+ startTextDetection(bucket: string, key: string): Promise<string>;
13
+ getAllPages(jobId: string): Promise<any[]>;
14
+ private sleep;
15
+ startDocumentAnalysis(bucket: string, key: string, featureTypes?: ('TABLES' | 'FORMS')[]): Promise<string>;
16
+ getAllAnalysisBlocks(jobId: string): Promise<TextractBlock[]>;
17
+ collatePageWiseTextFromBlocks(blocks: TextractBlock[]): Record<string, string>;
18
+ analyzePdfInS3ToPageWiseText(bucket: string, key: string): Promise<Record<string, string>>;
19
+ }
20
+ //# sourceMappingURL=textract.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textract.service.d.ts","sourceRoot":"","sources":["../../src/services/textract.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,YAA6B,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAMH,KAAK,IAAI,aAAa,EACzB,MAAM,0BAA0B,CAAC;AAIlC,qBACa,eAAe;IAOpB,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IANxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAC3D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;gBAIf,mBAAmB,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC;IAoBzE,OAAO,CAAC,eAAe;IAIjB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAUzD,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYhE,WAAW,CAAC,KAAK,EAAE,MAAM;IA0B/B,OAAO,CAAC,KAAK;IAQP,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,CAAC,QAAQ,GAAG,OAAO,CAAC,EAAwB,GAAG,OAAO,CAAC,MAAM,CAAC;IAa/H,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IA8BnE,6BAA6B,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkCxE,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAQnG"}
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
45
+ return function (target, key) { decorator(target, key, paramIndex); }
46
+ };
47
+ var __importDefault = (this && this.__importDefault) || function (mod) {
48
+ return (mod && mod.__esModule) ? mod : { "default": mod };
49
+ };
50
+ var TextractService_1;
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.TextractService = void 0;
53
+ const common_1 = require("@nestjs/common");
54
+ const common_config_1 = __importDefault(require("../config/common.config"));
55
+ const client_textract_1 = require("@aws-sdk/client-textract");
56
+ const client_s3_1 = require("@aws-sdk/client-s3");
57
+ const fs = __importStar(require("node:fs"));
58
+ let TextractService = TextractService_1 = class TextractService {
59
+ constructor(commonConfiguration) {
60
+ this.commonConfiguration = commonConfiguration;
61
+ this.logger = new common_1.Logger(TextractService_1.name);
62
+ if (!this.isValidS3Config(this.commonConfiguration.awsS3Credentials)) {
63
+ return;
64
+ }
65
+ this.s3Client = new client_s3_1.S3Client({
66
+ region: this.commonConfiguration.awsS3Credentials.S3_AWS_REGION_NAME,
67
+ credentials: {
68
+ accessKeyId: this.commonConfiguration.awsS3Credentials.S3_AWS_ACCESS_KEY,
69
+ secretAccessKey: this.commonConfiguration.awsS3Credentials.S3_AWS_SECRET_KEY,
70
+ },
71
+ });
72
+ this.textractClient = new client_textract_1.TextractClient({
73
+ region: this.commonConfiguration.awsS3Credentials.S3_AWS_REGION_NAME,
74
+ credentials: {
75
+ accessKeyId: this.commonConfiguration.awsS3Credentials.S3_AWS_ACCESS_KEY,
76
+ secretAccessKey: this.commonConfiguration.awsS3Credentials.S3_AWS_SECRET_KEY,
77
+ },
78
+ });
79
+ }
80
+ isValidS3Config(config) {
81
+ return !!config.S3_AWS_ACCESS_KEY && !!config.S3_AWS_SECRET_KEY && !!config.S3_AWS_REGION_NAME;
82
+ }
83
+ async uploadToS3(localPath, bucket, key) {
84
+ const body = fs.createReadStream(localPath);
85
+ await this.s3Client.send(new client_s3_1.PutObjectCommand({
86
+ Bucket: bucket,
87
+ Key: key,
88
+ Body: body,
89
+ ContentType: 'application/pdf',
90
+ }));
91
+ }
92
+ async startTextDetection(bucket, key) {
93
+ const res = await this.textractClient.send(new client_textract_1.StartDocumentTextDetectionCommand({
94
+ DocumentLocation: { S3Object: { Bucket: bucket, Name: key } },
95
+ }));
96
+ if (!res.JobId)
97
+ throw new Error('Failed to start Textract job');
98
+ return res.JobId;
99
+ }
100
+ async getAllPages(jobId) {
101
+ let status = 'IN_PROGRESS';
102
+ while (status === 'IN_PROGRESS') {
103
+ await this.sleep(3000);
104
+ const head = await this.textractClient.send(new client_textract_1.GetDocumentTextDetectionCommand({ JobId: jobId, MaxResults: 1 }));
105
+ status = head.JobStatus || 'IN_PROGRESS';
106
+ if (status === 'FAILED')
107
+ throw new Error('Textract job failed');
108
+ if (status === 'SUCCEEDED')
109
+ break;
110
+ }
111
+ const pages = [];
112
+ let nextToken = undefined;
113
+ do {
114
+ const res = await this.textractClient.send(new client_textract_1.GetDocumentTextDetectionCommand({
115
+ JobId: jobId,
116
+ NextToken: nextToken,
117
+ }));
118
+ pages.push(res);
119
+ nextToken = res.NextToken;
120
+ } while (nextToken);
121
+ return pages;
122
+ }
123
+ sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
124
+ async startDocumentAnalysis(bucket, key, featureTypes = ['TABLES', 'FORMS']) {
125
+ const res = await this.textractClient.send(new client_textract_1.StartDocumentAnalysisCommand({
126
+ DocumentLocation: { S3Object: { Bucket: bucket, Name: key } },
127
+ FeatureTypes: featureTypes,
128
+ }));
129
+ if (!res.JobId)
130
+ throw new Error('Failed to start Textract analysis job');
131
+ return res.JobId;
132
+ }
133
+ async getAllAnalysisBlocks(jobId) {
134
+ let status = 'IN_PROGRESS';
135
+ while (status === 'IN_PROGRESS') {
136
+ await this.sleep(3000);
137
+ const head = await this.textractClient.send(new client_textract_1.GetDocumentAnalysisCommand({ JobId: jobId, MaxResults: 1 }));
138
+ status = head.JobStatus || 'IN_PROGRESS';
139
+ if (status === 'FAILED')
140
+ throw new Error('Textract analysis job failed');
141
+ if (status === 'SUCCEEDED')
142
+ break;
143
+ }
144
+ const blocks = [];
145
+ let nextToken = undefined;
146
+ do {
147
+ const res = await this.textractClient.send(new client_textract_1.GetDocumentAnalysisCommand({
148
+ JobId: jobId,
149
+ NextToken: nextToken,
150
+ }));
151
+ if (res.Blocks?.length)
152
+ blocks.push(...res.Blocks);
153
+ nextToken = res.NextToken;
154
+ } while (nextToken);
155
+ return blocks;
156
+ }
157
+ collatePageWiseTextFromBlocks(blocks) {
158
+ const byPage = new Map();
159
+ for (const b of blocks ?? []) {
160
+ if (b.BlockType === 'LINE' && b.Text) {
161
+ const page = b.Page ?? 1;
162
+ if (!byPage.has(page))
163
+ byPage.set(page, []);
164
+ byPage.get(page).push(b);
165
+ }
166
+ }
167
+ const pages = Array.from(byPage.keys()).sort((a, b) => a - b);
168
+ const result = {};
169
+ for (const p of pages) {
170
+ const lines = byPage.get(p);
171
+ lines.sort((a, b) => {
172
+ const at = a.Geometry?.BoundingBox?.Top ?? 0;
173
+ const bt = b.Geometry?.BoundingBox?.Top ?? 0;
174
+ if (Math.abs(at - bt) > 0.002)
175
+ return at - bt;
176
+ const al = a.Geometry?.BoundingBox?.Left ?? 0;
177
+ const bl = b.Geometry?.BoundingBox?.Left ?? 0;
178
+ return al - bl;
179
+ });
180
+ result[`page_${p}`] = lines.map((l) => l.Text).join('\n');
181
+ }
182
+ return result;
183
+ }
184
+ async analyzePdfInS3ToPageWiseText(bucket, key) {
185
+ this.logger.debug(`Starting DocumentAnalysis for s3://${bucket}/${key}`);
186
+ const jobId = await this.startDocumentAnalysis(bucket, key, ['TABLES', 'FORMS']);
187
+ const blocks = await this.getAllAnalysisBlocks(jobId);
188
+ const pageWise = this.collatePageWiseTextFromBlocks(blocks);
189
+ this.logger.debug(`Completed DocumentAnalysis for s3://${bucket}/${key} with ${Object.keys(pageWise).length} pages`);
190
+ return pageWise;
191
+ }
192
+ };
193
+ exports.TextractService = TextractService;
194
+ exports.TextractService = TextractService = TextractService_1 = __decorate([
195
+ (0, common_1.Injectable)(),
196
+ __param(0, (0, common_1.Inject)(common_config_1.default.KEY)),
197
+ __metadata("design:paramtypes", [void 0])
198
+ ], TextractService);
199
+ //# sourceMappingURL=textract.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textract.service.js","sourceRoot":"","sources":["../../src/services/textract.service.ts"],"names":[],"mappings":"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","sourcesContent":["// src/services/textract.service.ts\nimport { Inject, Injectable, Logger } from '@nestjs/common';\nimport { ConfigType } from '@nestjs/config';\nimport commonConfig, { AwsS3Config } from '../config/common.config';\nimport {\n TextractClient,\n StartDocumentTextDetectionCommand,\n GetDocumentTextDetectionCommand,\n StartDocumentAnalysisCommand,\n GetDocumentAnalysisCommand,\n Block as TextractBlock,\n} from '@aws-sdk/client-textract';\nimport { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';\nimport * as fs from 'node:fs';\n\n@Injectable()\nexport class TextractService {\n private readonly logger = new Logger(TextractService.name);\n private readonly textractClient: TextractClient;\n private readonly s3Client: S3Client;\n\n constructor(\n @Inject(commonConfig.KEY)\n private readonly commonConfiguration: ConfigType<typeof commonConfig>,\n ) {\n if (!this.isValidS3Config(this.commonConfiguration.awsS3Credentials)) { return }\n this.s3Client = new S3Client({\n region: this.commonConfiguration.awsS3Credentials.S3_AWS_REGION_NAME,\n credentials: {\n accessKeyId: this.commonConfiguration.awsS3Credentials.S3_AWS_ACCESS_KEY,\n secretAccessKey: this.commonConfiguration.awsS3Credentials.S3_AWS_SECRET_KEY,\n },\n });\n\n this.textractClient = new TextractClient({\n region: this.commonConfiguration.awsS3Credentials.S3_AWS_REGION_NAME,\n credentials: {\n accessKeyId: this.commonConfiguration.awsS3Credentials.S3_AWS_ACCESS_KEY,\n secretAccessKey: this.commonConfiguration.awsS3Credentials.S3_AWS_SECRET_KEY,\n },\n });\n }\n\n private isValidS3Config(config: AwsS3Config): boolean {\n return !!config.S3_AWS_ACCESS_KEY && !!config.S3_AWS_SECRET_KEY && !!config.S3_AWS_REGION_NAME;\n }\n\n async uploadToS3(localPath: string, bucket: string, key: string) {\n const body = fs.createReadStream(localPath);\n await this.s3Client.send(new PutObjectCommand({\n Bucket: bucket,\n Key: key,\n Body: body,\n ContentType: 'application/pdf',\n }));\n }\n\n async startTextDetection(bucket: string, key: string): Promise<string> {\n const res = await this.textractClient.send(new StartDocumentTextDetectionCommand({\n DocumentLocation: { S3Object: { Bucket: bucket, Name: key } },\n }));\n if (!res.JobId) throw new Error('Failed to start Textract job');\n return res.JobId;\n }\n\n /**\n * Polls Textract until SUCCEEDED and returns page chunks (with pagination handled).\n * Returns an array where each item corresponds to one GetDocumentTextDetection response page.\n */\n async getAllPages(jobId: string) {\n // poll\n let status = 'IN_PROGRESS';\n while (status === 'IN_PROGRESS') {\n await this.sleep(3000);\n const head = await this.textractClient.send(new GetDocumentTextDetectionCommand({ JobId: jobId, MaxResults: 1 }));\n status = head.JobStatus || 'IN_PROGRESS';\n if (status === 'FAILED') throw new Error('Textract job failed');\n if (status === 'SUCCEEDED') break;\n }\n\n // paginate\n const pages: any[] = [];\n let nextToken: string | undefined = undefined;\n do {\n const res = await this.textractClient.send(new GetDocumentTextDetectionCommand({\n JobId: jobId,\n NextToken: nextToken,\n }));\n pages.push(res);\n nextToken = res.NextToken;\n } while (nextToken);\n\n return pages;\n }\n\n private sleep(ms: number) { return new Promise(r => setTimeout(r, ms)); }\n\n // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n // New set of methods used for document analysis, not just text detection\n // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n /**\n * Start async DocumentAnalysis (better for specs: TABLES + FORMS).\n */\n async startDocumentAnalysis(bucket: string, key: string, featureTypes: ('TABLES' | 'FORMS')[] = ['TABLES', 'FORMS']): Promise<string> {\n const res = await this.textractClient.send(new StartDocumentAnalysisCommand({\n DocumentLocation: { S3Object: { Bucket: bucket, Name: key } },\n FeatureTypes: featureTypes,\n }));\n if (!res.JobId) throw new Error('Failed to start Textract analysis job');\n return res.JobId;\n }\n\n /**\n * Wait for analysis job to finish, then fetch ALL pages (handles NextToken).\n * Returns a flat array of Blocks from all result pages.\n */\n async getAllAnalysisBlocks(jobId: string): Promise<TextractBlock[]> {\n // poll\n let status = 'IN_PROGRESS';\n while (status === 'IN_PROGRESS') {\n await this.sleep(3000);\n const head = await this.textractClient.send(new GetDocumentAnalysisCommand({ JobId: jobId, MaxResults: 1 }));\n status = head.JobStatus || 'IN_PROGRESS';\n if (status === 'FAILED') throw new Error('Textract analysis job failed');\n if (status === 'SUCCEEDED') break;\n }\n\n // paginate + collect blocks\n const blocks: TextractBlock[] = [];\n let nextToken: string | undefined = undefined;\n do {\n const res = await this.textractClient.send(new GetDocumentAnalysisCommand({\n JobId: jobId,\n NextToken: nextToken,\n }));\n if (res.Blocks?.length) blocks.push(...res.Blocks);\n nextToken = res.NextToken;\n } while (nextToken);\n\n return blocks;\n }\n\n /**\n * Collate LINE blocks into page-wise plain text,\n * sorted roughly top-to-bottom then left-to-right for better reading order.\n */\n collatePageWiseTextFromBlocks(blocks: TextractBlock[]): Record<string, string> {\n const byPage = new Map<number, TextractBlock[]>();\n\n for (const b of blocks ?? []) {\n if (b.BlockType === 'LINE' && b.Text) {\n const page = (b as any).Page ?? 1;\n if (!byPage.has(page)) byPage.set(page, []);\n byPage.get(page)!.push(b);\n }\n }\n\n const pages = Array.from(byPage.keys()).sort((a, b) => a - b);\n const result: Record<string, string> = {};\n\n for (const p of pages) {\n const lines = byPage.get(p)!;\n lines.sort((a: any, b: any) => {\n const at = a.Geometry?.BoundingBox?.Top ?? 0;\n const bt = b.Geometry?.BoundingBox?.Top ?? 0;\n if (Math.abs(at - bt) > 0.002) return at - bt; // row order\n const al = a.Geometry?.BoundingBox?.Left ?? 0;\n const bl = b.Geometry?.BoundingBox?.Left ?? 0;\n return al - bl; // within row\n });\n result[`page_${p}`] = lines.map((l: any) => l.Text).join('\\n');\n }\n\n return result;\n }\n\n /**\n * Convenience: Run recommended flow end-to-end on a PDF in S3\n * and get `{ page_1: \"...\", page_2: \"...\" }`.\n */\n async analyzePdfInS3ToPageWiseText(bucket: string, key: string): Promise<Record<string, string>> {\n this.logger.debug(`Starting DocumentAnalysis for s3://${bucket}/${key}`);\n const jobId = await this.startDocumentAnalysis(bucket, key, ['TABLES', 'FORMS']);\n const blocks = await this.getAllAnalysisBlocks(jobId);\n const pageWise = this.collatePageWiseTextFromBlocks(blocks);\n this.logger.debug(`Completed DocumentAnalysis for s3://${bucket}/${key} with ${Object.keys(pageWise).length} pages`);\n return pageWise;\n }\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"solid-core.module.d.ts","sourceRoot":"","sources":["../src/solid-core.module.ts"],"names":[],"mappings":"AA+QA,qBAmVa,eAAe;CAAI"}
1
+ {"version":3,"file":"solid-core.module.d.ts","sourceRoot":"","sources":["../src/solid-core.module.ts"],"names":[],"mappings":"AAkRA,qBAuVa,eAAe;CAAI"}
@@ -255,10 +255,13 @@ const solid_add_field_mcp_tool_response_handler_service_1 = require("./services/
255
255
  const view_metadata_repository_1 = require("./repository/view-metadata.repository");
256
256
  const solid_save_model_layout_mcp_tool_response_handler_service_1 = require("./services/mcp-tool-response-handlers/solid-save-model-layout-mcp-tool-response-handler.service");
257
257
  const noops_entity_computed_field_provider_service_1 = require("./services/computed-fields/entity/noops-entity-computed-field-provider.service");
258
+ const scheduled_job_repository_1 = require("./repository/scheduled-job.repository");
259
+ const scheduled_job_subscriber_1 = require("./subscribers/scheduled-job.subscriber");
258
260
  const alpha_num_external_id_computed_field_provider_1 = require("./services/computed-fields/entity/alpha-num-external-id-computed-field-provider");
259
261
  const mail_factory_1 = require("./factories/mail.factory");
260
262
  const TwilioSMSService_1 = require("./services/sms/TwilioSMSService");
261
263
  const poller_service_1 = require("./services/poller.service");
264
+ const textract_service_1 = require("./services/textract.service");
262
265
  let SolidCoreModule = class SolidCoreModule {
263
266
  };
264
267
  exports.SolidCoreModule = SolidCoreModule;
@@ -421,6 +424,7 @@ exports.SolidCoreModule = SolidCoreModule = __decorate([
421
424
  core_1.Reflector,
422
425
  core_1.MetadataScanner,
423
426
  file_service_1.FileService,
427
+ textract_service_1.TextractService,
424
428
  solid_registry_1.SolidRegistry,
425
429
  seed_command_1.SeedCommand,
426
430
  smtp_email_service_1.SMTPEMailService,
@@ -550,6 +554,8 @@ exports.SolidCoreModule = SolidCoreModule = __decorate([
550
554
  solid_add_field_mcp_tool_response_handler_service_1.SolidAddFieldMcpToolResponseHandler,
551
555
  view_metadata_repository_1.ViewMetadataRepository,
552
556
  solid_save_model_layout_mcp_tool_response_handler_service_1.SolidCreateModelLayoutMcpToolResponseHandler,
557
+ scheduled_job_repository_1.ScheduledJobRepository,
558
+ scheduled_job_subscriber_1.ScheduledJobSubscriber,
553
559
  alpha_num_external_id_computed_field_provider_1.AlphaNumExternalIdComputationProvider,
554
560
  mail_factory_1.MailFactory,
555
561
  ],
@@ -564,6 +570,7 @@ exports.SolidCoreModule = SolidCoreModule = __decorate([
564
570
  crud_service_1.CRUDService,
565
571
  platform_express_1.MulterModule,
566
572
  file_service_1.FileService,
573
+ textract_service_1.TextractService,
567
574
  solid_registry_1.SolidRegistry,
568
575
  smtp_email_service_1.SMTPEMailService,
569
576
  elastic_email_service_1.ElasticEmailService,