@solidstarters/solid-core 1.2.4 → 1.2.6

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 (46) hide show
  1. package/dist/commands/refresh-model.command.js +2 -2
  2. package/dist/commands/refresh-model.command.js.map +1 -1
  3. package/dist/commands/refresh-module.command.js +2 -2
  4. package/dist/commands/refresh-module.command.js.map +1 -1
  5. package/dist/commands/seed.command.d.ts.map +1 -1
  6. package/dist/commands/seed.command.js +2 -1
  7. package/dist/commands/seed.command.js.map +1 -1
  8. package/dist/config/{redis.options.d.ts → cache.options.d.ts} +1 -1
  9. package/dist/config/cache.options.d.ts.map +1 -0
  10. package/dist/config/cache.options.js +36 -0
  11. package/dist/config/cache.options.js.map +1 -0
  12. package/dist/config/common.config.d.ts +5 -4
  13. package/dist/config/common.config.d.ts.map +1 -1
  14. package/dist/config/common.config.js +0 -2
  15. package/dist/config/common.config.js.map +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/services/file.service.d.ts +2 -0
  19. package/dist/services/file.service.d.ts.map +1 -1
  20. package/dist/services/file.service.js +14 -0
  21. package/dist/services/file.service.js.map +1 -1
  22. package/dist/services/rabbitmq-publisher.service.d.ts +3 -1
  23. package/dist/services/rabbitmq-publisher.service.d.ts.map +1 -1
  24. package/dist/services/rabbitmq-publisher.service.js +27 -26
  25. package/dist/services/rabbitmq-publisher.service.js.map +1 -1
  26. package/dist/services/rabbitmq-subscriber.service.d.ts +4 -2
  27. package/dist/services/rabbitmq-subscriber.service.d.ts.map +1 -1
  28. package/dist/services/rabbitmq-subscriber.service.js +20 -25
  29. package/dist/services/rabbitmq-subscriber.service.js.map +1 -1
  30. package/dist/solid-core-cli.module.js +2 -2
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +1 -1
  33. package/src/commands/refresh-model.command.ts +2 -2
  34. package/src/commands/refresh-module.command.ts +2 -2
  35. package/src/commands/seed.command.ts +2 -1
  36. package/src/config/cache.options.ts +36 -0
  37. package/src/config/common.config.ts +6 -2
  38. package/src/index.ts +1 -1
  39. package/src/services/file.service.ts +13 -4
  40. package/src/services/rabbitmq-publisher.service.ts +30 -9
  41. package/src/services/rabbitmq-subscriber.service.ts +23 -14
  42. package/src/solid-core-cli.module.ts +1 -1
  43. package/dist/config/redis.options.d.ts.map +0 -1
  44. package/dist/config/redis.options.js +0 -22
  45. package/dist/config/redis.options.js.map +0 -1
  46. package/src/config/redis.options.ts +0 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,7 +37,7 @@ export class RefreshModelCommand extends CommandRunner {
37
37
  }
38
38
 
39
39
  @Option({
40
- flags: '-id, --modelId [model ID]',
40
+ flags: '-id, --id [model ID]',
41
41
  description: 'Model ID from the ss_model_metadata table',
42
42
  })
43
43
  parseModelId(val: string): number {
@@ -46,7 +46,7 @@ export class RefreshModelCommand extends CommandRunner {
46
46
 
47
47
  // Accept the module name as an argument
48
48
  @Option({
49
- flags: '-n, --modelName [model name]',
49
+ flags: '-n, --name [model name]',
50
50
  description: 'Model Name from the ss_model_metadata table',
51
51
  })
52
52
  parseModelName(val: string): string {
@@ -37,7 +37,7 @@ export class RefreshModuleCommand extends CommandRunner {
37
37
 
38
38
 
39
39
  @Option({
40
- flags: '-id, --moduleId [module ID]',
40
+ flags: '-id, --id [module ID]',
41
41
  description: 'Module ID from the ss_module_metadata table',
42
42
  })
43
43
  parseModuleId(val: string): number {
@@ -46,7 +46,7 @@ export class RefreshModuleCommand extends CommandRunner {
46
46
 
47
47
  // Accept the module name as an argument
48
48
  @Option({
49
- flags: '-n, --moduleName [module name]',
49
+ flags: '-n, --name [module name]',
50
50
  description: 'Module Name from the ss_module_metadata table',
51
51
  })
52
52
  parseModuleName(val: string): string {
@@ -46,7 +46,8 @@ export class SeedCommand extends CommandRunner {
46
46
  @Option({
47
47
  flags: '-s, --seeder [seeder name]',
48
48
  description: 'The seeder to run.',
49
- required: true
49
+ required: true,
50
+ defaultValue: 'ModuleMetadataSeederService'
50
51
  })
51
52
  parseString(val: string): string {
52
53
  return val;
@@ -0,0 +1,36 @@
1
+ import { CacheModuleAsyncOptions } from '@nestjs/cache-manager';
2
+ import { ConfigModule, ConfigService } from '@nestjs/config';
3
+ import { redisStore } from 'cache-manager-redis-store';
4
+ import { isNumber } from 'class-validator';
5
+
6
+ export const RedisOptions: CacheModuleAsyncOptions = {
7
+ isGlobal: true,
8
+ imports: [ConfigModule],
9
+ useFactory: async (configService: ConfigService) => {
10
+ if (!isRedisConfigured(configService)) {
11
+ return {
12
+ ttl: 0
13
+ } // This defaults to in-memory cache
14
+ }
15
+ const store = await createRedisStore(configService);
16
+ return {
17
+ store: () => store,
18
+ };
19
+ },
20
+ inject: [ConfigService],
21
+ };
22
+
23
+ async function createRedisStore(configService: ConfigService<Record<string, unknown>, false>) {
24
+ return await redisStore({
25
+ socket: {
26
+ host: configService.get<string>('REDIS_HOST'),
27
+ port: parseInt(configService.get<string>('REDIS_PORT')!),
28
+ },
29
+ });
30
+ }
31
+
32
+ function isRedisConfigured(configService: ConfigService): boolean {
33
+ const host = configService.get<string>('REDIS_HOST');
34
+ const port = configService.get<string>('REDIS_PORT');
35
+ return host && port && isNumber(parseInt(port));
36
+ }
@@ -36,9 +36,13 @@ export default registerAs('common', () => {
36
36
  awsS3Credentials: {
37
37
  S3_AWS_ACCESS_KEY: process.env.S3_AWS_ACCESS_KEY,
38
38
  S3_AWS_SECRET_KEY: process.env.S3_AWS_SECRET_KEY,
39
- S3_AWS_BUCKET_NAME: process.env.S3_AWS_BUCKET_NAME,
40
- S3_AWS_REGION_HOST: process.env.S3_AWS_REGION_HOST,
41
39
  S3_AWS_REGION_NAME: process.env.S3_AWS_REGION_NAME
42
40
  }
43
41
  };
44
42
  });
43
+
44
+ export interface AwsS3Config {
45
+ S3_AWS_ACCESS_KEY: string;
46
+ S3_AWS_SECRET_KEY: string;
47
+ S3_AWS_REGION_NAME: string;
48
+ }
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@ export * from './commands/seed.command'
8
8
  export * from './config/app-builder.config'
9
9
  export * from './config/common.config'
10
10
  export * from './config/iam.config'
11
- export * from './config/redis.options'
11
+ export * from './config/cache.options'
12
12
 
13
13
  export * from './decorators/active-user.decorator'
14
14
  export * from './decorators/auth.decorator'
@@ -3,7 +3,7 @@ import * as fs from 'fs';
3
3
  // import * as AWS from 'aws-sdk';
4
4
  import { S3Client, PutObjectCommand, DeleteObjectCommand, ObjectCannedACL } from '@aws-sdk/client-s3';
5
5
  import { ConfigType } from '@nestjs/config';
6
- import commonConfig from '../config/common.config';
6
+ import commonConfig, { AwsS3Config } from '../config/common.config';
7
7
 
8
8
 
9
9
 
@@ -18,14 +18,13 @@ export class FileService {
18
18
  private readonly commonConfiguration: ConfigType<typeof commonConfig>,
19
19
 
20
20
  ) {
21
+ if (!this.isValidS3Config(this.commonConfiguration.awsS3Credentials)) { return }
21
22
  this.s3Client = new S3Client({
22
23
  region: this.commonConfiguration.awsS3Credentials.S3_AWS_REGION_NAME,
23
24
  credentials: {
24
25
  accessKeyId: this.commonConfiguration.awsS3Credentials.S3_AWS_ACCESS_KEY,
25
26
  secretAccessKey: this.commonConfiguration.awsS3Credentials.S3_AWS_SECRET_KEY,
26
27
  },
27
- // endpoint: `https://${process.env.S3_AWS_BUCKET_NAME}.s3.${process.env.S3_AWS_REGION_NAME}.amazonaws.com`, // Correct regional endpoint
28
-
29
28
  });
30
29
  }
31
30
 
@@ -84,6 +83,7 @@ export class FileService {
84
83
  }
85
84
 
86
85
  async copyToS3(filePath: string, ContentType: string, fileName: string, bucketName: string): Promise<string> {
86
+ this.checkIfS3ClientExists();
87
87
  try {
88
88
  // Read Image File TO Fetch Buffer
89
89
  const data = await this.readImageFile(filePath);
@@ -109,7 +109,12 @@ export class FileService {
109
109
  }
110
110
  }
111
111
 
112
+ private checkIfS3ClientExists() {
113
+ if (!this.s3Client) { throw new Error('S3 Client not initialized. Please check the S3 configuration'); }
114
+ }
115
+
112
116
  async copyToS3WithPublic(filePath: string, ContentType: string, fileName: string, bucketName: string): Promise<string> {
117
+ this.checkIfS3ClientExists();
113
118
  try {
114
119
  // Read Image File TO Fetch Buffer
115
120
  const data = await this.readImageFile(filePath);
@@ -136,7 +141,7 @@ export class FileService {
136
141
  }
137
142
 
138
143
  async deleteFromS3(fileName: string, bucketName: string): Promise<string> {
139
-
144
+ this.checkIfS3ClientExists();
140
145
  const params = {
141
146
  Bucket: bucketName, // your S3 bucket name
142
147
  Key: fileName // the name of the file you want to delete
@@ -146,4 +151,8 @@ export class FileService {
146
151
  const response = await this.s3Client.send(command);
147
152
  return fileName
148
153
  }
154
+
155
+ private isValidS3Config(config: AwsS3Config): boolean {
156
+ return !!config.S3_AWS_ACCESS_KEY && !!config.S3_AWS_SECRET_KEY && !!config.S3_AWS_REGION_NAME;
157
+ }
149
158
  }
@@ -1,30 +1,50 @@
1
- import { v4 as uuidv4 } from 'uuid';
2
- import { Injectable, Logger } from '@nestjs/common';
1
+ import { Logger } from '@nestjs/common';
3
2
  import * as amqp from 'amqplib';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ import { QueuesModuleOptions } from "../interfaces";
4
5
  import { QueueMessage, QueuePublisher } from '../interfaces/mq';
5
6
  import { MqMessageQueueService } from './mq-message-queue.service';
6
7
  import { MqMessageService } from './mq-message.service';
7
- import { QueuesModuleOptions } from "../interfaces";
8
8
 
9
- @Injectable()
10
9
  export abstract class RabbitMqPublisher<T> implements QueuePublisher<T> { // TODO This can be made a generic type for better type visibility
11
10
  private readonly logger = new Logger(RabbitMqPublisher.name);
11
+ private readonly url: string;
12
+ private readonly serviceRole: string;
12
13
 
13
14
  constructor(
14
15
  protected readonly mqMessageService: MqMessageService,
15
16
  protected readonly mqMessageQueueService: MqMessageQueueService,
16
17
  ) {
17
- const url = process.env.QUEUES_RABBIT_MQ_URL;
18
- this.logger.debug(`RabbitMqPublisher instance created with options: ${JSON.stringify(this.options())} and url: ${url}`);
18
+ this.url = process.env.QUEUES_RABBIT_MQ_URL;
19
+ this.serviceRole = process.env.QUEUES_SERVICE_ROLE;
20
+ if (!this.url) {
21
+ this.logger.debug('RabbitMqPublisher url is not defined in the environment variables');
22
+ }
23
+ if (!this.serviceRole) {
24
+ this.logger.debug('Queue service Role is not defined in the environment variables');
25
+ }
26
+ this.logger.debug(`RabbitMqPublisher instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);
19
27
  }
20
28
 
21
29
  abstract options(): QueuesModuleOptions;
22
30
 
23
31
  async publish(message: QueueMessage<T>): Promise<string> {
24
- const url = process.env.QUEUES_RABBIT_MQ_URL;
25
- this.logger.debug(`RabbitMqPublisher publishing with options: ${JSON.stringify(this.options())} and url: ${url}`);
32
+ if (!this.url) {
33
+ this.logger.error('RabbitMqPublisher url is not defined in the environment variables');
34
+ throw new Error('RabbitMqPublisher url is not defined in the environment variables');
35
+ }
36
+ if (!this.serviceRole) {
37
+ this.logger.error('Queue service Role is not defined in the environment variables');
38
+ throw new Error('Queue service Role is not defined in the environment variables');
39
+ }
40
+ if (this.serviceRole === 'subscriber') {
41
+ this.logger.error('Queue service Role is subscriber, cannot publish messages');
42
+ throw new Error('Queue service Role is subscriber, cannot publish messages');
43
+ }
44
+
45
+ this.logger.debug(`RabbitMqPublisher publishing with options: ${JSON.stringify(this.options())} and url: ${this.url}`);
26
46
 
27
- const connection = await amqp.connect(url);
47
+ const connection = await amqp.connect(this.url);
28
48
  // this.logger.debug(`RabbitMqPublisher publisher connected options: ${JSON.stringify(this.options())} and url: ${url}`);
29
49
 
30
50
  const channel = await connection.createChannel();
@@ -117,5 +137,6 @@ export abstract class RabbitMqPublisher<T> implements QueuePublisher<T> { // TOD
117
137
  }
118
138
 
119
139
  }
140
+
120
141
 
121
142
  }
@@ -1,41 +1,50 @@
1
- import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
1
+ import { Logger, OnModuleInit } from '@nestjs/common';
2
2
  import * as amqp from 'amqplib';
3
+ import { QueuesModuleOptions } from "../interfaces";
3
4
  import { QueueMessage, QueueSubscriber } from '../interfaces/mq';
4
- import { MqMessageService } from './mq-message.service';
5
5
  import { MqMessageQueueService } from './mq-message-queue.service';
6
- import { QueuesModuleOptions } from "../interfaces";
6
+ import { MqMessageService } from './mq-message.service';
7
7
 
8
8
 
9
- @Injectable()
10
9
  export abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscriber<T> { // TODO This can be made a generic type for better type visibility
11
10
  private readonly logger = new Logger(RabbitMqSubscriber.name);
11
+ private readonly url: string;
12
+ private readonly serviceRole: string;
12
13
 
13
14
  constructor(
14
15
  protected readonly mqMessageService: MqMessageService,
15
16
  protected readonly mqMessageQueueService: MqMessageQueueService,
16
17
  ) {
18
+ this.url = process.env.QUEUES_RABBIT_MQ_URL;
19
+ this.serviceRole = process.env.SERVICE_ROLE;
20
+ if (!this.url) {
21
+ this.logger.debug('RabbitMqPublisher url is not defined in the environment variables');
22
+ }
23
+ if (!this.serviceRole) {
24
+ this.logger.debug('Queue service Role is not defined in the environment variables');
25
+ }
26
+ this.logger.debug(`RabbitMqSubscriber instance created with options: ${JSON.stringify(this.options())} and url: ${this.url}`);
17
27
  }
18
28
 
19
29
  abstract subscribe(message: QueueMessage<T>);
20
30
 
21
31
  abstract options(): QueuesModuleOptions;
22
32
 
23
- // setReceiveHandler(receiveHandler: (message: any) => Promise<any>): void {
24
- // this.options.receive = receiveHandler; // Overwrite the default receive handler
25
- // }
26
-
27
33
  async onModuleInit(): Promise<void> {
28
34
  // we will start subscriber only if the current service role is subscriber.
29
- if (['both', 'subscriber'].includes(process.env.QUEUES_SERVICE_ROLE)) {
30
-
31
- const url = process.env.QUEUES_RABBIT_MQ_URL;
32
- if (!url) {
35
+ if (['both', 'subscriber'].includes(this.serviceRole)) {
36
+ if (!this.url) {
37
+ this.logger.error('RabbitMqPublisher url is not defined in the environment variables');
38
+ throw new Error('RabbitMqPublisher url is not defined in the environment variables');
39
+ }
40
+
41
+ if (!this.url) {
33
42
  this.logger.warn(`Unable to create RabbitMqSubscriber instance: ${JSON.stringify(this.options())} as rabbitmq url is not configured.`);
34
43
  return;
35
44
  }
36
45
 
37
46
  // this.logger.debug(`RabbitMqSubscriber instance created with options: ${JSON.stringify(this.options())} and url: ${url}`);
38
- const connection = await amqp.connect(url);
47
+ const connection = await amqp.connect(this.url);
39
48
  // this.logger.debug(`RabbitMqSubscriber connection established: ${JSON.stringify(this.options())} and url: ${url}`);
40
49
 
41
50
  const channel = await connection.createChannel();
@@ -104,7 +113,7 @@ export abstract class RabbitMqSubscriber<T> implements OnModuleInit, QueueSubscr
104
113
  {},
105
114
  );
106
115
 
107
- this.logger.debug(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(this.options())} and url: ${url}`);
116
+ this.logger.debug(`RabbitMqSubscriber ready to consume messages: ${JSON.stringify(this.options())} and url: ${this.url}`);
108
117
  }
109
118
 
110
119
  }
@@ -5,7 +5,7 @@ import { WinstonLoggerConfig } from './winston.logger';
5
5
  import { WinstonModule } from 'nest-winston';
6
6
  import { CacheModule } from '@nestjs/cache-manager';
7
7
  import { EventEmitterModule } from '@nestjs/event-emitter';
8
- import { RedisOptions } from './config/redis.options';
8
+ import { RedisOptions } from './config/cache.options';
9
9
  import { ConfigModule } from '@nestjs/config';
10
10
  import Joi from '@hapi/joi';
11
11
 
@@ -1 +0,0 @@
1
- {"version":3,"file":"redis.options.d.ts","sourceRoot":"","sources":["../../src/config/redis.options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAIhE,eAAO,MAAM,YAAY,EAAE,uBAe1B,CAAC"}
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RedisOptions = void 0;
4
- const config_1 = require("@nestjs/config");
5
- const cache_manager_redis_store_1 = require("cache-manager-redis-store");
6
- exports.RedisOptions = {
7
- isGlobal: true,
8
- imports: [config_1.ConfigModule],
9
- useFactory: async (configService) => {
10
- const store = await (0, cache_manager_redis_store_1.redisStore)({
11
- socket: {
12
- host: configService.get('REDIS_HOST'),
13
- port: parseInt(configService.get('REDIS_PORT')),
14
- },
15
- });
16
- return {
17
- store: () => store,
18
- };
19
- },
20
- inject: [config_1.ConfigService],
21
- };
22
- //# sourceMappingURL=redis.options.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"redis.options.js","sourceRoot":"","sources":["../../src/config/redis.options.ts"],"names":[],"mappings":";;;AACA,2CAA6D;AAC7D,yEAAuD;AAE1C,QAAA,YAAY,GAA4B;IACjD,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,CAAC,qBAAY,CAAC;IACvB,UAAU,EAAE,KAAK,EAAE,aAA4B,EAAE,EAAE;QAC/C,MAAM,KAAK,GAAG,MAAM,IAAA,sCAAU,EAAC;YAC3B,MAAM,EAAE;gBACJ,IAAI,EAAE,aAAa,CAAC,GAAG,CAAS,YAAY,CAAC;gBAC7C,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAS,YAAY,CAAE,CAAC;aAC3D;SACJ,CAAC,CAAC;QACH,OAAO;YACH,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK;SACrB,CAAC;IACN,CAAC;IACD,MAAM,EAAE,CAAC,sBAAa,CAAC;CAC1B,CAAC"}
@@ -1,20 +0,0 @@
1
- import { CacheModuleAsyncOptions } from '@nestjs/cache-manager';
2
- import { ConfigModule, ConfigService } from '@nestjs/config';
3
- import { redisStore } from 'cache-manager-redis-store';
4
-
5
- export const RedisOptions: CacheModuleAsyncOptions = {
6
- isGlobal: true,
7
- imports: [ConfigModule],
8
- useFactory: async (configService: ConfigService) => {
9
- const store = await redisStore({
10
- socket: {
11
- host: configService.get<string>('REDIS_HOST'),
12
- port: parseInt(configService.get<string>('REDIS_PORT')!),
13
- },
14
- });
15
- return {
16
- store: () => store,
17
- };
18
- },
19
- inject: [ConfigService],
20
- };