@lyrolab/nest-shared 0.0.2 → 1.0.2
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.
- package/.releaserc.json +25 -0
- package/CHANGELOG.md +19 -0
- package/README.md +30 -83
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.js +19 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/bull/index.d.ts +1 -0
- package/dist/bull/index.js +18 -0
- package/dist/bull/index.js.map +1 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.js +18 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/shared-cache.module.js +3 -1
- package/dist/cache/shared-cache.module.js.map +1 -1
- package/dist/database/index.d.ts +2 -0
- package/dist/database/index.js +19 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/shared-database.module.js +2 -2
- package/dist/database/shared-database.module.js.map +1 -1
- package/dist/queue/index.d.ts +4 -0
- package/dist/queue/index.js +21 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/shared-queue.module.d.ts +2 -0
- package/dist/queue/{queue.module.js → shared-queue.module.js} +6 -6
- package/dist/queue/shared-queue.module.js.map +1 -0
- package/dist/redis/index.d.ts +2 -0
- package/dist/redis/index.js +19 -0
- package/dist/redis/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +56 -24
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -1
- package/.nvmrc +0 -1
- package/.prettierrc +0 -5
- package/dist/index.d.ts +0 -12
- package/dist/index.js +0 -29
- package/dist/index.js.map +0 -1
- package/dist/queue/queue.module.d.ts +0 -2
- package/dist/queue/queue.module.js.map +0 -1
- package/dist/tsconfig.build.tsbuildinfo +0 -1
- package/nest-cli.json +0 -9
- package/src/ai/ai.module.ts +0 -8
- package/src/ai/services/ai.service.ts +0 -51
- package/src/app.module.ts +0 -8
- package/src/bull/shared-bull.module.ts +0 -27
- package/src/cache/shared-cache.module.ts +0 -30
- package/src/database/filters/typeorm-exception.filter.ts +0 -35
- package/src/database/helpers/find-main-path.ts +0 -22
- package/src/database/shared-database.module.ts +0 -137
- package/src/index.ts +0 -12
- package/src/queue/controllers/queue.controller.ts +0 -13
- package/src/queue/decorators/queue.decorator.ts +0 -3
- package/src/queue/models/dto/queue-add.dto.ts +0 -10
- package/src/queue/models/job-processor-interface.ts +0 -5
- package/src/queue/processors/queue.processor.ts +0 -53
- package/src/queue/queue.constants.ts +0 -1
- package/src/queue/queue.module.ts +0 -14
- package/src/queue/services/queue.service.ts +0 -17
- package/src/redis/redis.config.ts +0 -3
- package/src/redis/shared-redis.module.ts +0 -66
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -25
package/nest-cli.json
DELETED
package/src/ai/ai.module.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { CACHE_MANAGER } from "@nestjs/cache-manager"
|
|
2
|
-
import { Inject, Injectable } from "@nestjs/common"
|
|
3
|
-
import {
|
|
4
|
-
createOpenRouter,
|
|
5
|
-
OpenRouterProvider,
|
|
6
|
-
} from "@openrouter/ai-sdk-provider"
|
|
7
|
-
import {
|
|
8
|
-
LanguageModelV1,
|
|
9
|
-
LanguageModelV1Middleware,
|
|
10
|
-
wrapLanguageModel,
|
|
11
|
-
} from "ai"
|
|
12
|
-
import { Cache } from "cache-manager"
|
|
13
|
-
|
|
14
|
-
@Injectable()
|
|
15
|
-
export class AiService {
|
|
16
|
-
private readonly openrouter: OpenRouterProvider
|
|
17
|
-
private readonly openrouterChat: LanguageModelV1
|
|
18
|
-
|
|
19
|
-
constructor(@Inject(CACHE_MANAGER) private cache: Cache) {
|
|
20
|
-
this.openrouter = createOpenRouter({
|
|
21
|
-
apiKey: process.env.OPENROUTER_API_KEY,
|
|
22
|
-
})
|
|
23
|
-
this.openrouterChat = wrapLanguageModel({
|
|
24
|
-
model: this.openrouter.chat("google/gemini-2.0-flash-001"),
|
|
25
|
-
middleware: [{ wrapGenerate: (options) => this.wrapGenerate(options) }],
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get model() {
|
|
30
|
-
return this.openrouterChat
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
private async wrapGenerate({
|
|
34
|
-
doGenerate,
|
|
35
|
-
params,
|
|
36
|
-
}: Parameters<
|
|
37
|
-
NonNullable<LanguageModelV1Middleware["wrapGenerate"]>
|
|
38
|
-
>[0]): Promise<Awaited<ReturnType<LanguageModelV1["doGenerate"]>>> {
|
|
39
|
-
const cacheKey = "ai:" + JSON.stringify(params)
|
|
40
|
-
|
|
41
|
-
const cachedResult = await this.cache.get(cacheKey)
|
|
42
|
-
if (cachedResult) {
|
|
43
|
-
return cachedResult as Awaited<ReturnType<LanguageModelV1["doGenerate"]>>
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const result = await doGenerate()
|
|
47
|
-
|
|
48
|
-
await this.cache.set(cacheKey, result)
|
|
49
|
-
return result
|
|
50
|
-
}
|
|
51
|
-
}
|
package/src/app.module.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { BullModule } from "@nestjs/bullmq"
|
|
2
|
-
import { DynamicModule, Module } from "@nestjs/common"
|
|
3
|
-
import { ConfigModule } from "@nestjs/config"
|
|
4
|
-
import { SharedRedisModule } from "../redis/shared-redis.module"
|
|
5
|
-
import { RedisConfig } from "../redis/redis.config"
|
|
6
|
-
|
|
7
|
-
@Module({})
|
|
8
|
-
export class SharedBullModule {
|
|
9
|
-
static forRoot(): DynamicModule {
|
|
10
|
-
return {
|
|
11
|
-
module: SharedBullModule,
|
|
12
|
-
imports: [
|
|
13
|
-
SharedRedisModule,
|
|
14
|
-
BullModule.forRootAsync({
|
|
15
|
-
imports: [ConfigModule],
|
|
16
|
-
inject: [RedisConfig],
|
|
17
|
-
useFactory: (redisConfig: RedisConfig) => ({
|
|
18
|
-
connection: {
|
|
19
|
-
url: redisConfig.url,
|
|
20
|
-
},
|
|
21
|
-
}),
|
|
22
|
-
}),
|
|
23
|
-
],
|
|
24
|
-
exports: [BullModule],
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import KeyvRedis from "@keyv/redis"
|
|
2
|
-
import { CacheModule } from "@nestjs/cache-manager"
|
|
3
|
-
import { DynamicModule, Module } from "@nestjs/common"
|
|
4
|
-
import { ConfigService } from "@nestjs/config"
|
|
5
|
-
import { RedisConfig } from "../redis/redis.config"
|
|
6
|
-
import { SharedRedisModule } from "../redis/shared-redis.module"
|
|
7
|
-
|
|
8
|
-
@Module({})
|
|
9
|
-
export class SharedCacheModule {
|
|
10
|
-
static forRoot(): DynamicModule {
|
|
11
|
-
return {
|
|
12
|
-
module: SharedCacheModule,
|
|
13
|
-
imports: [
|
|
14
|
-
SharedRedisModule,
|
|
15
|
-
CacheModule.registerAsync({
|
|
16
|
-
isGlobal: true,
|
|
17
|
-
useFactory: (
|
|
18
|
-
configService: ConfigService,
|
|
19
|
-
redisConfig: RedisConfig,
|
|
20
|
-
) => ({
|
|
21
|
-
ttl: +configService.get("CACHE_TTL") * 1000,
|
|
22
|
-
stores: [new KeyvRedis(redisConfig.url)],
|
|
23
|
-
}),
|
|
24
|
-
inject: [ConfigService, RedisConfig],
|
|
25
|
-
}),
|
|
26
|
-
],
|
|
27
|
-
exports: [CacheModule],
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ExceptionFilter,
|
|
3
|
-
Catch,
|
|
4
|
-
ArgumentsHost,
|
|
5
|
-
NotFoundException,
|
|
6
|
-
Logger,
|
|
7
|
-
} from "@nestjs/common"
|
|
8
|
-
import { Response } from "express"
|
|
9
|
-
import { EntityNotFoundError } from "typeorm"
|
|
10
|
-
|
|
11
|
-
@Catch(EntityNotFoundError)
|
|
12
|
-
export class TypeOrmExceptionFilter implements ExceptionFilter {
|
|
13
|
-
private readonly logger = new Logger(TypeOrmExceptionFilter.name)
|
|
14
|
-
|
|
15
|
-
catch(exception: EntityNotFoundError, host: ArgumentsHost) {
|
|
16
|
-
const ctx = host.switchToHttp()
|
|
17
|
-
const response = ctx.getResponse<Response>()
|
|
18
|
-
|
|
19
|
-
this.logger.debug(`Original TypeORM error: ${exception.message}`)
|
|
20
|
-
|
|
21
|
-
const entityName = this.extractEntityName(exception.message)
|
|
22
|
-
const message = entityName ? `${entityName} not found` : "Entity not found"
|
|
23
|
-
|
|
24
|
-
const notFoundException = new NotFoundException(message)
|
|
25
|
-
|
|
26
|
-
response
|
|
27
|
-
.status(notFoundException.getStatus())
|
|
28
|
-
.json(notFoundException.getResponse())
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
private extractEntityName(errorMessage: string): string | null {
|
|
32
|
-
const match = errorMessage.match(/entity of type "([^"]+)"/)
|
|
33
|
-
return match ? match[1] : null
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "fs"
|
|
2
|
-
import { dirname, join } from "path"
|
|
3
|
-
|
|
4
|
-
export function findMainPath() {
|
|
5
|
-
const rootPath = findUp("package.json", process.cwd())
|
|
6
|
-
if (!rootPath) throw new Error("package.json not found")
|
|
7
|
-
return rootPath
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function findUp(path: string, cwd: string) {
|
|
11
|
-
const currentPath = cwd
|
|
12
|
-
const parentPath = dirname(currentPath)
|
|
13
|
-
if (parentPath === currentPath) {
|
|
14
|
-
return null
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (existsSync(join(currentPath, path))) {
|
|
18
|
-
return currentPath
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return findUp(path, parentPath)
|
|
22
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { DynamicModule, Module, OnModuleDestroy } from "@nestjs/common"
|
|
2
|
-
import { ConfigModule, ConfigService } from "@nestjs/config"
|
|
3
|
-
import { TypeOrmModule, TypeOrmModuleOptions } from "@nestjs/typeorm"
|
|
4
|
-
import { join } from "path"
|
|
5
|
-
import { findMainPath } from "./helpers/find-main-path"
|
|
6
|
-
import { GenericContainer, StartedTestContainer, Wait } from "testcontainers"
|
|
7
|
-
import { DataSource } from "typeorm"
|
|
8
|
-
|
|
9
|
-
type SharedDatabaseModuleOptions = {
|
|
10
|
-
entities?: string[]
|
|
11
|
-
migrations?: string[]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@Module({})
|
|
15
|
-
export class SharedDatabaseModule implements OnModuleDestroy {
|
|
16
|
-
private static testContainer: StartedTestContainer
|
|
17
|
-
private static testDataSource: DataSource
|
|
18
|
-
|
|
19
|
-
static forRoot(options: SharedDatabaseModuleOptions = {}): DynamicModule {
|
|
20
|
-
return {
|
|
21
|
-
module: SharedDatabaseModule,
|
|
22
|
-
imports: [
|
|
23
|
-
TypeOrmModule.forRootAsync({
|
|
24
|
-
imports: [ConfigModule],
|
|
25
|
-
inject: [ConfigService],
|
|
26
|
-
useFactory: async (configService: ConfigService) => {
|
|
27
|
-
const isTestEnvironment = process.env.NODE_ENV === "test"
|
|
28
|
-
|
|
29
|
-
if (isTestEnvironment) {
|
|
30
|
-
return await this.createTestConfiguration(options)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return this.createProductionConfiguration(configService, options)
|
|
34
|
-
},
|
|
35
|
-
}),
|
|
36
|
-
],
|
|
37
|
-
exports: [TypeOrmModule],
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private static async createTestConfiguration(
|
|
42
|
-
options: SharedDatabaseModuleOptions,
|
|
43
|
-
): Promise<TypeOrmModuleOptions> {
|
|
44
|
-
if (!this.testContainer) {
|
|
45
|
-
this.testContainer = await new GenericContainer("postgres")
|
|
46
|
-
.withExposedPorts(5432)
|
|
47
|
-
.withEnvironment({
|
|
48
|
-
POSTGRES_PASSWORD: "secret",
|
|
49
|
-
POSTGRES_DB: "test",
|
|
50
|
-
})
|
|
51
|
-
.withWaitStrategy(
|
|
52
|
-
Wait.forAll([
|
|
53
|
-
Wait.forListeningPorts(),
|
|
54
|
-
Wait.forLogMessage(
|
|
55
|
-
"database system is ready to accept connections",
|
|
56
|
-
),
|
|
57
|
-
]),
|
|
58
|
-
)
|
|
59
|
-
.start()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const connectionUri = `postgres://postgres:secret@localhost:${this.testContainer.getMappedPort(
|
|
63
|
-
5432,
|
|
64
|
-
)}/test`
|
|
65
|
-
|
|
66
|
-
const entities = options.entities || [
|
|
67
|
-
join(findMainPath(), "**/*.entity{.ts,.js}"),
|
|
68
|
-
]
|
|
69
|
-
|
|
70
|
-
const migrations = options.migrations || [
|
|
71
|
-
join(findMainPath(), "src/migrations/**/*.{ts,js}"),
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
if (!this.testDataSource) {
|
|
75
|
-
this.testDataSource = new DataSource({
|
|
76
|
-
type: "postgres",
|
|
77
|
-
url: connectionUri,
|
|
78
|
-
entities,
|
|
79
|
-
synchronize: true,
|
|
80
|
-
migrations,
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
await this.testDataSource.initialize()
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
type: "postgres",
|
|
88
|
-
url: connectionUri,
|
|
89
|
-
entities,
|
|
90
|
-
synchronize: true,
|
|
91
|
-
autoLoadEntities: true,
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private static createProductionConfiguration(
|
|
96
|
-
configService: ConfigService,
|
|
97
|
-
options: SharedDatabaseModuleOptions,
|
|
98
|
-
): TypeOrmModuleOptions {
|
|
99
|
-
return {
|
|
100
|
-
type: "postgres",
|
|
101
|
-
url: configService.get("DATABASE_URL"),
|
|
102
|
-
entities: options.entities || [
|
|
103
|
-
join(__dirname, "../../../**/*.entity{.ts,.js}"),
|
|
104
|
-
],
|
|
105
|
-
migrations: options.migrations || [
|
|
106
|
-
join(__dirname, "../../../migrations/**/*.{ts,js}"),
|
|
107
|
-
],
|
|
108
|
-
synchronize: false,
|
|
109
|
-
autoLoadEntities: true,
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
static getTestDataSource(): DataSource {
|
|
114
|
-
return this.testDataSource
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static async closeTestConnection(): Promise<void> {
|
|
118
|
-
if (this.testDataSource) {
|
|
119
|
-
await this.testDataSource.destroy()
|
|
120
|
-
}
|
|
121
|
-
if (this.testContainer) {
|
|
122
|
-
await this.testContainer.stop()
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
static async clearTestDatabase(): Promise<void> {
|
|
127
|
-
if (this.testDataSource) {
|
|
128
|
-
await this.testDataSource.synchronize(true)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async onModuleDestroy() {
|
|
133
|
-
if (SharedDatabaseModule.testDataSource) {
|
|
134
|
-
await SharedDatabaseModule.testDataSource.destroy()
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export * from "./ai/ai.module"
|
|
2
|
-
export * from "./ai/services/ai.service"
|
|
3
|
-
export * from "./bull/shared-bull.module"
|
|
4
|
-
export * from "./cache/shared-cache.module"
|
|
5
|
-
export * from "./database/shared-database.module"
|
|
6
|
-
export * from "./database/filters/typeorm-exception.filter"
|
|
7
|
-
export * from "./queue/queue.module"
|
|
8
|
-
export * from "./queue/services/queue.service"
|
|
9
|
-
export * from "./queue/models/job-processor-interface"
|
|
10
|
-
export * from "./queue/decorators/queue.decorator"
|
|
11
|
-
export * from "./redis/shared-redis.module"
|
|
12
|
-
export * from "./redis/redis.config"
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Body, Controller, Post } from "@nestjs/common"
|
|
2
|
-
import { QueueService } from "../services/queue.service"
|
|
3
|
-
import { QueueAddDto } from "../models/dto/queue-add.dto"
|
|
4
|
-
|
|
5
|
-
@Controller("queue")
|
|
6
|
-
export class QueueController {
|
|
7
|
-
constructor(private readonly queueService: QueueService) {}
|
|
8
|
-
|
|
9
|
-
@Post("add")
|
|
10
|
-
async add(@Body() body: QueueAddDto) {
|
|
11
|
-
return this.queueService.add(body.name, body.data)
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { InjectQueue, Processor, WorkerHost } from "@nestjs/bullmq"
|
|
2
|
-
import { DiscoveryService } from "@nestjs/core"
|
|
3
|
-
import { Job, Queue } from "bullmq"
|
|
4
|
-
import { JobProcessor } from "../decorators/queue.decorator"
|
|
5
|
-
import { JobProcessorInterface } from "../models/job-processor-interface"
|
|
6
|
-
import { DEFAULT_QUEUE } from "../queue.constants"
|
|
7
|
-
|
|
8
|
-
@Processor(DEFAULT_QUEUE, { concurrency: 100 })
|
|
9
|
-
export class QueueProcessor extends WorkerHost {
|
|
10
|
-
constructor(
|
|
11
|
-
private readonly discoveryService: DiscoveryService,
|
|
12
|
-
@InjectQueue(DEFAULT_QUEUE) private readonly queue: Queue,
|
|
13
|
-
) {
|
|
14
|
-
super()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async process(job: Job) {
|
|
18
|
-
const jobProcessor = this.jobProcessorFor(job.name)
|
|
19
|
-
if (!jobProcessor) return
|
|
20
|
-
|
|
21
|
-
const shouldProcess = await this.shouldProcessJob(job)
|
|
22
|
-
if (!shouldProcess) return
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
await jobProcessor.process(job)
|
|
26
|
-
} catch (error) {
|
|
27
|
-
console.error(error)
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
private jobProcessorFor(jobName: string) {
|
|
32
|
-
return this.discoveryService
|
|
33
|
-
.getProviders({ metadataKey: JobProcessor.KEY })
|
|
34
|
-
.find(
|
|
35
|
-
(provider) =>
|
|
36
|
-
this.discoveryService.getMetadataByDecorator(
|
|
37
|
-
JobProcessor,
|
|
38
|
-
provider,
|
|
39
|
-
) === jobName,
|
|
40
|
-
)?.instance as JobProcessorInterface
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private async shouldProcessJob(job: Job) {
|
|
44
|
-
if (!job.repeatJobKey) return true
|
|
45
|
-
|
|
46
|
-
const activeJobs = await this.queue.getActive()
|
|
47
|
-
const activeJobsOfSameCronjob = activeJobs.filter(
|
|
48
|
-
({ name, id }) => name === job.name && id !== job.id,
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
return activeJobsOfSameCronjob.length === 0
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const DEFAULT_QUEUE = "default"
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { BullModule } from "@nestjs/bullmq"
|
|
2
|
-
import { Module } from "@nestjs/common"
|
|
3
|
-
import { DiscoveryModule } from "@nestjs/core"
|
|
4
|
-
import { QueueProcessor } from "./processors/queue.processor"
|
|
5
|
-
import { DEFAULT_QUEUE } from "./queue.constants"
|
|
6
|
-
import { QueueService } from "./services/queue.service"
|
|
7
|
-
import { QueueController } from "./controllers/queue.controller"
|
|
8
|
-
@Module({
|
|
9
|
-
imports: [BullModule.registerQueue({ name: DEFAULT_QUEUE }), DiscoveryModule],
|
|
10
|
-
providers: [QueueService, QueueProcessor],
|
|
11
|
-
exports: [QueueService],
|
|
12
|
-
controllers: [QueueController],
|
|
13
|
-
})
|
|
14
|
-
export class QueueModule {}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { InjectQueue } from "@nestjs/bullmq"
|
|
2
|
-
import { Injectable } from "@nestjs/common"
|
|
3
|
-
import { Job, JobsOptions, Queue } from "bullmq"
|
|
4
|
-
import { DEFAULT_QUEUE } from "../queue.constants"
|
|
5
|
-
|
|
6
|
-
@Injectable()
|
|
7
|
-
export class QueueService {
|
|
8
|
-
constructor(@InjectQueue(DEFAULT_QUEUE) private readonly queue: Queue) {}
|
|
9
|
-
|
|
10
|
-
add(
|
|
11
|
-
name: string,
|
|
12
|
-
data: any,
|
|
13
|
-
opts?: JobsOptions,
|
|
14
|
-
): Promise<Job<any, any, string>> {
|
|
15
|
-
return this.queue.add(name, data, opts)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { DynamicModule, Module, OnModuleDestroy } from "@nestjs/common"
|
|
2
|
-
import { ConfigModule, ConfigService } from "@nestjs/config"
|
|
3
|
-
import { GenericContainer, StartedTestContainer, Wait } from "testcontainers"
|
|
4
|
-
import { RedisConfig } from "./redis.config"
|
|
5
|
-
|
|
6
|
-
@Module({})
|
|
7
|
-
export class SharedRedisModule implements OnModuleDestroy {
|
|
8
|
-
private static testContainer: StartedTestContainer | null = null
|
|
9
|
-
|
|
10
|
-
static forRoot(): DynamicModule {
|
|
11
|
-
return {
|
|
12
|
-
module: SharedRedisModule,
|
|
13
|
-
providers: [
|
|
14
|
-
{
|
|
15
|
-
provide: RedisConfig,
|
|
16
|
-
useFactory: async (configService: ConfigService) => {
|
|
17
|
-
const isTestEnvironment = process.env.NODE_ENV === "test"
|
|
18
|
-
|
|
19
|
-
if (isTestEnvironment) {
|
|
20
|
-
return new RedisConfig(await this.createTestConfiguration())
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return new RedisConfig(
|
|
24
|
-
this.createProductionConfiguration(configService),
|
|
25
|
-
)
|
|
26
|
-
},
|
|
27
|
-
inject: [ConfigService],
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
exports: [RedisConfig],
|
|
31
|
-
imports: [ConfigModule],
|
|
32
|
-
global: true,
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private static async createTestConfiguration() {
|
|
37
|
-
if (!this.testContainer) {
|
|
38
|
-
this.testContainer = await new GenericContainer("redis")
|
|
39
|
-
.withExposedPorts(6379)
|
|
40
|
-
.withWaitStrategy(
|
|
41
|
-
Wait.forAll([
|
|
42
|
-
Wait.forListeningPorts(),
|
|
43
|
-
Wait.forLogMessage("Ready to accept connections tcp"),
|
|
44
|
-
]),
|
|
45
|
-
)
|
|
46
|
-
.start()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return `redis://${this.testContainer.getHost()}:${this.testContainer.getMappedPort(6379)}`
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private static createProductionConfiguration(configService: ConfigService) {
|
|
53
|
-
return configService.get("REDIS_URL") as string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
static async closeTestConnection(): Promise<void> {
|
|
57
|
-
if (this.testContainer) {
|
|
58
|
-
await this.testContainer.stop()
|
|
59
|
-
this.testContainer = null
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async onModuleDestroy() {
|
|
64
|
-
await SharedRedisModule.closeTestConnection()
|
|
65
|
-
}
|
|
66
|
-
}
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"module": "commonjs",
|
|
4
|
-
"declaration": true,
|
|
5
|
-
"removeComments": true,
|
|
6
|
-
"emitDecoratorMetadata": true,
|
|
7
|
-
"experimentalDecorators": true,
|
|
8
|
-
"allowSyntheticDefaultImports": true,
|
|
9
|
-
"target": "ES2023",
|
|
10
|
-
"sourceMap": true,
|
|
11
|
-
"outDir": "./dist",
|
|
12
|
-
"baseUrl": "./",
|
|
13
|
-
"incremental": true,
|
|
14
|
-
"skipLibCheck": true,
|
|
15
|
-
"strictNullChecks": true,
|
|
16
|
-
"forceConsistentCasingInFileNames": true,
|
|
17
|
-
"noImplicitAny": true,
|
|
18
|
-
"strictBindCallApply": true,
|
|
19
|
-
"noFallthroughCasesInSwitch": true,
|
|
20
|
-
"paths": {
|
|
21
|
-
"@app/nest-shared": ["libs/nest-shared/src"],
|
|
22
|
-
"@app/nest-shared/*": ["libs/nest-shared/src/*"]
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|