feat: better server lint (#2850)
* feat: add stylistic eslint plugin * feat: add missing line return * feat: secure line-break style * feat: disallow break before else * feat: line between class members * feat: better new line lint rule
This commit is contained in:
@ -10,26 +10,31 @@ class TestClass {
|
||||
describe('CastToLogLevelArray Decorator', () => {
|
||||
it('should cast "log" to ["log"]', () => {
|
||||
const transformedClass = plainToClass(TestClass, { logLevels: 'log' });
|
||||
|
||||
expect(transformedClass.logLevels).toStrictEqual(['log']);
|
||||
});
|
||||
|
||||
it('should cast "error" to ["error"]', () => {
|
||||
const transformedClass = plainToClass(TestClass, { logLevels: 'error' });
|
||||
|
||||
expect(transformedClass.logLevels).toStrictEqual(['error']);
|
||||
});
|
||||
|
||||
it('should cast "warn" to ["warn"]', () => {
|
||||
const transformedClass = plainToClass(TestClass, { logLevels: 'warn' });
|
||||
|
||||
expect(transformedClass.logLevels).toStrictEqual(['warn']);
|
||||
});
|
||||
|
||||
it('should cast "debug" to ["debug"]', () => {
|
||||
const transformedClass = plainToClass(TestClass, { logLevels: 'debug' });
|
||||
|
||||
expect(transformedClass.logLevels).toStrictEqual(['debug']);
|
||||
});
|
||||
|
||||
it('should cast "verbose" to ["verbose"]', () => {
|
||||
const transformedClass = plainToClass(TestClass, { logLevels: 'verbose' });
|
||||
|
||||
expect(transformedClass.logLevels).toStrictEqual(['verbose']);
|
||||
});
|
||||
|
||||
@ -37,6 +42,7 @@ describe('CastToLogLevelArray Decorator', () => {
|
||||
const transformedClass = plainToClass(TestClass, {
|
||||
logLevels: 'verbose,error,warn',
|
||||
});
|
||||
|
||||
expect(transformedClass.logLevels).toStrictEqual([
|
||||
'verbose',
|
||||
'error',
|
||||
@ -46,6 +52,7 @@ describe('CastToLogLevelArray Decorator', () => {
|
||||
|
||||
it('should cast "toto" to undefined', () => {
|
||||
const transformedClass = plainToClass(TestClass, { logLevels: 'toto' });
|
||||
|
||||
expect(transformedClass.logLevels).toBeUndefined();
|
||||
});
|
||||
|
||||
@ -53,6 +60,7 @@ describe('CastToLogLevelArray Decorator', () => {
|
||||
const transformedClass = plainToClass(TestClass, {
|
||||
logLevels: 'verbose,error,toto',
|
||||
});
|
||||
|
||||
expect(transformedClass.logLevels).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -10,21 +10,25 @@ class TestClass {
|
||||
describe('CastToPositiveNumber Decorator', () => {
|
||||
it('should cast number to number', () => {
|
||||
const transformedClass = plainToClass(TestClass, { numberProperty: 123 });
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(123);
|
||||
});
|
||||
|
||||
it('should cast string to number', () => {
|
||||
const transformedClass = plainToClass(TestClass, { numberProperty: '123' });
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(123);
|
||||
});
|
||||
|
||||
it('should cast null to undefined', () => {
|
||||
const transformedClass = plainToClass(TestClass, { numberProperty: null });
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should cast negative number to undefined', () => {
|
||||
const transformedClass = plainToClass(TestClass, { numberProperty: -12 });
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(undefined);
|
||||
});
|
||||
|
||||
@ -32,6 +36,7 @@ describe('CastToPositiveNumber Decorator', () => {
|
||||
const transformedClass = plainToClass(TestClass, {
|
||||
numberProperty: undefined,
|
||||
});
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(undefined);
|
||||
});
|
||||
|
||||
@ -39,6 +44,7 @@ describe('CastToPositiveNumber Decorator', () => {
|
||||
const transformedClass = plainToClass(TestClass, {
|
||||
numberProperty: 'toto',
|
||||
});
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(undefined);
|
||||
});
|
||||
|
||||
@ -46,6 +52,7 @@ describe('CastToPositiveNumber Decorator', () => {
|
||||
const transformedClass = plainToClass(TestClass, {
|
||||
numberProperty: '-123',
|
||||
});
|
||||
|
||||
expect(transformedClass.numberProperty).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
@ -13,5 +13,6 @@ const toBoolean = (value: any) => {
|
||||
if (['false', 'off', 'no', '0'].includes(value.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@ -10,5 +10,6 @@ const toNumber = (value: any) => {
|
||||
if (typeof value === 'string') {
|
||||
return isNaN(+value) ? undefined : toNumber(+value);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
export class IsAWSRegionConstraint implements ValidatorConstraintInterface {
|
||||
validate(region: string) {
|
||||
const regex = /^[a-z]{2}-[a-z]+-\d{1}$/;
|
||||
|
||||
return regex.test(region); // Returns true if region matches regex
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ export class IsDurationConstraint implements ValidatorConstraintInterface {
|
||||
validate(duration: string) {
|
||||
const regex =
|
||||
/^-?[0-9]+(.[0-9]+)?(m(illiseconds?)?|s(econds?)?|h((ou)?rs?)?|d(ays?)?|w(eeks?)?|M(onths?)?|y(ears?)?)?$/;
|
||||
|
||||
return regex.test(duration); // Returns true if duration matches regex
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,6 +159,7 @@ export const validate = (config: Record<string, unknown>) => {
|
||||
const validatedConfig = plainToClass(EnvironmentVariables, config);
|
||||
|
||||
const errors = validateSync(validatedConfig);
|
||||
|
||||
assert(!errors.length, errors.toString());
|
||||
|
||||
return validatedConfig;
|
||||
|
||||
@ -33,6 +33,7 @@ export class FileStorageModule {
|
||||
provide: STORAGE_DRIVER,
|
||||
useFactory: async (...args: any[]) => {
|
||||
const config = await options.useFactory(...args);
|
||||
|
||||
return config?.type === 's3'
|
||||
? new S3Driver(config.options)
|
||||
: new LocalDriver(config.options);
|
||||
|
||||
@ -67,6 +67,7 @@ const loggerModuleFactory = async (
|
||||
environmentService: EnvironmentService,
|
||||
): Promise<LoggerModuleOptions> => {
|
||||
const type = environmentService.getLoggerDriver();
|
||||
|
||||
switch (type) {
|
||||
case LoggerDriver.Console: {
|
||||
return {
|
||||
@ -100,6 +101,7 @@ const messageQueueModuleFactory = async (
|
||||
switch (type) {
|
||||
case MessageQueueType.PgBoss: {
|
||||
const connectionString = environmentService.getPGDatabaseUrl();
|
||||
|
||||
return {
|
||||
type: MessageQueueType.PgBoss,
|
||||
options: {
|
||||
@ -110,6 +112,7 @@ const messageQueueModuleFactory = async (
|
||||
case MessageQueueType.BullMQ: {
|
||||
const host = environmentService.getRedisHost();
|
||||
const port = environmentService.getRedisPort();
|
||||
|
||||
return {
|
||||
type: MessageQueueType.BullMQ,
|
||||
options: {
|
||||
|
||||
@ -32,6 +32,7 @@ export class LoggerModule {
|
||||
provide: LOGGER_DRIVER,
|
||||
useFactory: async (...args: any[]) => {
|
||||
const config = await options.useFactory(...args);
|
||||
|
||||
return config?.type === LoggerDriver.Console
|
||||
? new ConsoleLogger()
|
||||
: new SentryDriver(config.options);
|
||||
|
||||
@ -7,6 +7,7 @@ export class MemoryStorageDefaultSerializer<T>
|
||||
if (typeof item !== 'string') {
|
||||
throw new Error('DefaultSerializer can only serialize strings');
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ export class BullMQDriver implements MessageQueueDriver {
|
||||
async stop() {
|
||||
const workers = Object.values(this.workerMap);
|
||||
const queues = Object.values(this.queueMap);
|
||||
|
||||
await Promise.all([
|
||||
...queues.map((q) => q.close()),
|
||||
...workers.map((w) => w.close()),
|
||||
@ -40,6 +41,7 @@ export class BullMQDriver implements MessageQueueDriver {
|
||||
const worker = new Worker(queueName, async (job) => {
|
||||
await handler(job as { data: T; id: string });
|
||||
});
|
||||
|
||||
this.workerMap[queueName] = worker;
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ export class PgBossDriver implements MessageQueueDriver {
|
||||
constructor(options: PgBossDriverOptions) {
|
||||
this.pgBoss = new PgBoss(options);
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.pgBoss.stop();
|
||||
}
|
||||
|
||||
@ -30,11 +30,15 @@ export class MessageQueueModule {
|
||||
provide: QUEUE_DRIVER,
|
||||
useFactory: async (...args: any[]) => {
|
||||
const config = await options.useFactory(...args);
|
||||
|
||||
if (config.type === MessageQueueType.PgBoss) {
|
||||
const boss = new PgBossDriver(config.options);
|
||||
|
||||
await boss.init();
|
||||
|
||||
return boss;
|
||||
}
|
||||
|
||||
return new BullMQDriver(config.options);
|
||||
},
|
||||
inject: options.inject || [],
|
||||
|
||||
Reference in New Issue
Block a user