NESTJS上でのDI‐in電報ロボットによるモジュールへのリファクタリングモノリス応用
155569 ワード
リンク
https://github.com/EndyKaufman/kaufman-bot - ボットのソースコード
https://telegram.me/DevelopKaufmanBot - 現在のロボット
作品の説明
現在のアプリケーションはモノリスとして構築されますが、NPMレジストリにすべてのコードを発行したいと思います.
これを行うには、すべてのソースを段階的に変換して再設定する必要があります.
このポストでは、そのやり方を教えてあげます.
現状
npm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
見ることができるように、より多くのモジュールは言語スイッチャを参照します.
そして、私たちは、主なモジュールがPrismaを通してデータベースで働くということを知っています.
を削除します
主な原因は、定数変数"DefaultChord Language "です
我々は、言語スイッチャーからそれを削除する必要があります
libs/language swither/server/src/lib/language swither config/language swither.設定.TS
export const LANGUAGE_SWITHER_CONFIG = 'LANGUAGE_SWITHER_CONFIG';
export interface LanguageSwitherConfig {
title: string;
name: string;
descriptions: string;
usage: string[];
spyWords: string[];
removeWords?: string[];
category: string;
}
その後、プロジェクトで多くのファイルを壊しました
現在、我々はmfaastをデフォルトの言語を' en 'に置き換えます
置換ファイルの例
LIBS/事実発生器/サーバ/src/lib/事実発生器サービス/ru事実発生器.サービスTS
すべての置換後、wee別のグラフを参照してください
npm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
データベースからコアへの作業の移動
ライブラリを新規作成
npm run -- nx g @nrwl/nest:lib prisma/server
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run -- nx g @nrwl/nest:lib prisma/server
> [email protected] nx
> nx "g" "@nrwl/nest:lib" "prisma/server"
CREATE libs/prisma/server/README.md
CREATE libs/prisma/server/.babelrc
CREATE libs/prisma/server/src/index.ts
CREATE libs/prisma/server/tsconfig.json
CREATE libs/prisma/server/tsconfig.lib.json
UPDATE tsconfig.base.json
CREATE libs/prisma/server/project.json
UPDATE workspace.json
CREATE libs/prisma/server/.eslintrc.json
CREATE libs/prisma/server/jest.config.js
CREATE libs/prisma/server/tsconfig.spec.json
CREATE libs/prisma/server/src/lib/prisma-server.module.ts
このライブラリにPrismaクライアントモジュールを移動するmv libs/core/server/src/lib/prisma-client libs/prisma/server/src/lib
rm -rf libs/prisma/server/src/lib/prisma-server.module.ts
npm run generate
使用するすべてのインポートを置換します
使用するすべてのインポートを置換します
すべての置換後、別のグラフを参照してくださいすべてのデータベースを参照してください
npm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
デバッグメッセージコマンドからprismaの使用を削除する
デバッグメッセージストレージを更新する
LIBS/デバッグメッセージ/サーバ/src/lib/デバッグメッセージサービス/デバッグメッセージ.ストレージ.TS
export const DEBUG_MESSAGES_STORAGE = 'DEBUG_MESSAGES_STORAGE';
export type DebugMessagesStorageProvider = Pick<
DebugMessagesStorage,
'getDebugModeOfUser' | 'setDebugModeOfUser'
>;
export class DebugMessagesStorage {
private readonly debugModeOfUsers: Record<number, boolean> = {};
async getDebugModeOfUser(telegramUserId: number): Promise<boolean> {
const currentDebugMode = this.debugModeOfUsers[telegramUserId];
if (currentDebugMode) {
return currentDebugMode;
}
return false;
}
async setDebugModeOfUser(userId: number, debugMode: boolean): Promise<void> {
this.debugModeOfUsers[userId] = debugMode;
}
}
更新サービス
LIBS/デバッグメッセージ/サーバ/src/lib/デバッグメッセージサービス/デバッグメッセージ.サービスTS
import {
BotCommandsEnum,
BotCommandsProvider,
BotCommandsProviderActionMsg,
BotCommandsProviderActionResultType,
BotCommandsToolsService,
OnAfterBotCommands,
OnBeforeBotCommands,
} from '@kaufman-bot/core/server';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { CustomInject } from 'nestjs-custom-injector';
import { TranslatesService } from 'nestjs-translates';
import {
DebugMessagesConfig,
DEBUG_MESSAGES_CONFIG,
} from '../debug-messages-config/debug-messages.config';
import { DebugMessagesCommandsEnum } from '../debug-messages-types/debug-messages-commands';
import {
DebugMessagesStorageProvider,
DEBUG_MESSAGES_STORAGE,
} from './debug-messages.storage';
import { DebugService } from './debug.service';
@Injectable()
export class DebugMessagesService
implements BotCommandsProvider, OnBeforeBotCommands, OnAfterBotCommands
{
private readonly logger = new Logger(DebugMessagesService.name);
@CustomInject(DEBUG_MESSAGES_STORAGE)
private readonly debugMessagesStorage!: DebugMessagesStorageProvider;
constructor(
@Inject(DEBUG_MESSAGES_CONFIG)
private readonly debugMessagesConfig: DebugMessagesConfig,
private readonly translatesService: TranslatesService,
private readonly commandToolsService: BotCommandsToolsService,
private readonly debugService: DebugService,
private readonly botCommandsToolsService: BotCommandsToolsService
) {}
...
更新モジュール
LIBS/デバッグメッセージ/サーバ/src/lib/デバッグメッセージ.モジュールです.TS
import {
BotCommandsCategory,
BotCommandsModule,
BOT_COMMANDS_PROVIDER,
} from '@kaufman-bot/core/server';
import { DynamicModule, Module } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { CustomInjectorModule } from 'nestjs-custom-injector';
import { TranslatesModule } from 'nestjs-translates';
import {
DebugMessagesConfig,
DEBUG_MESSAGES_CONFIG,
} from './debug-messages-config/debug-messages.config';
import { DebugMessagesService } from './debug-messages-services/debug-messages.service';
import {
DebugMessagesStorage,
DEBUG_MESSAGES_STORAGE,
} from './debug-messages-services/debug-messages.storage';
import { DebugService } from './debug-messages-services/debug.service';
@Module({
imports: [TranslatesModule, BotCommandsModule],
providers: [
{ provide: DEBUG_MESSAGES_STORAGE, useClass: DebugMessagesStorage },
DebugService,
],
exports: [
TranslatesModule,
BotCommandsModule,
DEBUG_MESSAGES_STORAGE,
DebugService,
],
})
export class DebugMessagesModule {
static forRoot(): DynamicModule {
return {
module: DebugMessagesModule,
imports: [
CustomInjectorModule.forFeature({
imports: [DebugMessagesModule],
providers: [
{
provide: DEBUG_MESSAGES_CONFIG,
useValue: <DebugMessagesConfig>{
title: getText('Debug messages'),
name: 'debug',
usage: [
getText('debug on'),
getText('debug off'),
getText('debug state'),
getText('debug help'),
],
descriptions: getText(
'Commands for enable and disable debug mode'
),
spyWords: [getText('debug')],
category: BotCommandsCategory.system,
},
},
{
provide: BOT_COMMANDS_PROVIDER,
useClass: DebugMessagesService,
},
],
exports: [DEBUG_MESSAGES_CONFIG],
}),
],
};
}
}
デバッグモジュールを追加します
アプリケーションでPrisma統合モジュールを作成する
アプリケーション/サーバ/src/app/integrations/prisma/prisma統合.モジュールです.TS
import { DEBUG_MESSAGES_STORAGE } from '@kaufman-bot/debug-messages/server';
import { PrismaClientModule } from '@kaufman-bot/prisma/server';
import { DynamicModule, Module } from '@nestjs/common';
import { PrismaDebugMessagesStorage } from './prisma-integrations/prisma-debug-messages.storage';
import { PrismaDialogflowStorage } from './prisma-integrations/prisma-dialogflow.storage';
import { PrismaFirstMeetingStorage } from './prisma-integrations/prisma-first-meeting.storage';
import { PrismaLanguageSwitherStorage } from './prisma-integrations/prisma-language-swither.storage';
@Module({})
export class PrismaIntegrationsModule {
static forRoot(): DynamicModule {
return {
module: PrismaIntegrationsModule,
imports: [PrismaClientModule],
providers: [
{
provide: DEBUG_MESSAGES_STORAGE,
useClass: PrismaDebugMessagesStorage,
},
],
exports: [
DEBUG_MESSAGES_STORAGE,
],
};
}
}
の作成を実装するimport { DebugMessagesStorageProvider } from '@kaufman-bot/debug-messages/server';
import { PrismaClientService } from '@kaufman-bot/prisma/server';
import { Injectable } from '@nestjs/common';
@Injectable()
export class PrismaDebugMessagesStorage
implements DebugMessagesStorageProvider
{
private readonly debugModeOfUsers: Record<number, boolean> = {};
constructor(private readonly prismaClientService: PrismaClientService) {}
async getDebugModeOfUser(telegramUserId: number): Promise<boolean> {
const currentDebugMode = this.debugModeOfUsers[telegramUserId];
if (currentDebugMode) {
return currentDebugMode;
}
try {
const currentDebugModeFromDatabase =
await this.prismaClientService.user.findFirst({
where: { telegramId: telegramUserId.toString() },
rejectOnNotFound: true,
});
this.debugModeOfUsers[telegramUserId] =
currentDebugModeFromDatabase.debugMode;
return this.debugModeOfUsers[telegramUserId];
} catch (error) {
return false;
}
}
async setDebugModeOfUser(userId: number, debugMode: boolean): Promise<void> {
await this.prismaClientService.user.upsert({
create: { telegramId: userId.toString(), debugMode },
update: { debugMode },
where: { telegramId: userId.toString() },
});
this.debugModeOfUsers[userId] = debugMode;
}
}
更新アプリモジュールアプリ/サーバ/src/app/app.モジュールです.TS
...
import { PrismaIntegrationsModule } from './integrations/prisma/prisma-integrations.module';
const TELEGRAM_BOT_WEB_HOOKS_DOMAIN = env
.get('TELEGRAM_BOT_WEB_HOOKS_DOMAIN')
.asString();
const TELEGRAM_BOT_WEB_HOOKS_PATH = env
.get('TELEGRAM_BOT_WEB_HOOKS_PATH')
.asString();
const BOT_NAMES = env.get('BOT_NAMES').required().asArray();
const BOT_NAMES_RU = env.get('BOT_NAMES_RU').required().asArray();
@Module({
imports: [
TelegrafModule.forRoot({
token: env.get('TELEGRAM_BOT_TOKEN').required().asString(),
launchOptions: {
dropPendingUpdates: true,
...(TELEGRAM_BOT_WEB_HOOKS_DOMAIN && TELEGRAM_BOT_WEB_HOOKS_PATH
? {
webhook: {
domain: TELEGRAM_BOT_WEB_HOOKS_DOMAIN,
hookPath: TELEGRAM_BOT_WEB_HOOKS_PATH,
},
}
: {}),
},
}),
PrismaClientModule.forRoot({
databaseUrl: env.get('SERVER_POSTGRES_URL').required().asString(),
logging: 'long_queries',
maxQueryExecutionTime: 5000,
}),
PrismaIntegrationsModule.forRoot(),
...
すべての置換後、wee別のグラフを参照してください
npm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
言語swither命令からのPRISMAの使用法の削除
更新ストレージサービス
Libs/言語のスイープ/サーバ/src/lib/言語スイーサーサービス/言語swither.ストレージ.TS
export const LANGUAGE_SWITHER_STORAGE = 'LANGUAGE_SWITHER_STORAGE';
export type LanguageSwitherStorageProvider = Pick<
LanguageSwitherStorage,
'getLanguageOfUser' | 'setLanguageOfUser'
>;
export class LanguageSwitherStorage {
private readonly languageOfUsers: Record<number, string> = {};
async getLanguageOfUser(telegramUserId: number): Promise<string | null> {
const currentLanguageCode = this.languageOfUsers[telegramUserId];
if (currentLanguageCode) {
return currentLanguageCode;
}
return null;
}
async setLanguageOfUser(
telegramUserId: number,
langCode: string
): Promise<void> {
this.languageOfUsers[telegramUserId] = langCode;
}
}
スイッチ・ストレージアプリケーション/サーバ/src/app/integrations/prisma/prisma統合サービス/prisma言語swither.ストレージ.TS
import { LanguageSwitherStorageProvider } from '@kaufman-bot/language-swither/server';
import { PrismaClientService } from '@kaufman-bot/prisma/server';
import { Injectable } from '@nestjs/common';
@Injectable()
export class PrismaLanguageSwitherStorage
implements LanguageSwitherStorageProvider
{
private readonly languageOfUsers: Record<number, string> = {};
constructor(private readonly prismaClientService: PrismaClientService) {}
async getLanguageOfUser(telegramUserId: number): Promise<string | null> {
const currentLanguageCode = this.languageOfUsers[telegramUserId];
if (currentLanguageCode) {
return currentLanguageCode;
}
try {
const currentLanguageCodeFromDatabase =
await this.prismaClientService.user.findFirst({
where: { telegramId: telegramUserId.toString() },
rejectOnNotFound: true,
});
this.languageOfUsers[telegramUserId] =
currentLanguageCodeFromDatabase.langCode;
return this.languageOfUsers[telegramUserId];
} catch (error) {
return null;
}
}
async setLanguageOfUser(
telegramUserId: number,
langCode: string
): Promise<void> {
await this.prismaClientService.user.upsert({
create: { telegramId: telegramUserId.toString(), langCode },
update: { langCode },
where: { telegramId: telegramUserId.toString() },
});
this.languageOfUsers[telegramUserId] = langCode;
}
}
PrimsManugrationsモジュールへのPrismalGanguageの使用方法アプリケーション/サーバ/src/app/integrations/prisma/prisma統合サービス/prisma統合.モジュールです.TS
import { DEBUG_MESSAGES_STORAGE } from '@kaufman-bot/debug-messages/server';
import { LANGUAGE_SWITHER_STORAGE } from '@kaufman-bot/language-swither/server';
import { PrismaClientModule } from '@kaufman-bot/prisma/server';
import { DynamicModule, Module } from '@nestjs/common';
import { PrismaDebugMessagesStorage } from './prisma-integrations/prisma-debug-messages.storage';
import { PrismaDialogflowStorage } from './prisma-integrations/prisma-dialogflow.storage';
import { PrismaFirstMeetingStorage } from './prisma-integrations/prisma-first-meeting.storage';
import { PrismaLanguageSwitherStorage } from './prisma-integrations/prisma-language-swither.storage';
@Module({})
export class PrismaIntegrationsModule {
static forRoot(): DynamicModule {
return {
module: PrismaIntegrationsModule,
imports: [PrismaClientModule],
providers: [
{
provide: DEBUG_MESSAGES_STORAGE,
useClass: PrismaDebugMessagesStorage,
},
{
provide: LANGUAGE_SWITHER_STORAGE,
useClass: PrismaLanguageSwitherStorage,
},
],
exports: [
DEBUG_MESSAGES_STORAGE,
LANGUAGE_SWITHER_STORAGE,
],
};
}
}
更新サービスLibs/言語のスイープ/サーバ/src/lib/言語スイーサーサービス/言語swither.サービスTS
import {
BotCommandsEnum,
BotCommandsProvider,
BotCommandsProviderActionMsg,
BotCommandsProviderActionResultType,
BotCommandsToolsService,
OnBeforeBotCommands,
} from '@kaufman-bot/core/server';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { CustomInject } from 'nestjs-custom-injector';
import { TranslatesService, TranslatesStorage } from 'nestjs-translates';
import {
LanguageSwitherConfig,
LANGUAGE_SWITHER_CONFIG,
} from '../language-swither-config/language-swither.config';
import { LanguageSwitherCommandsEnum } from '../language-swither-types/language-swither-commands';
import {
LanguageSwitherStorage,
LANGUAGE_SWITHER_STORAGE,
} from './language-swither.storage';
@Injectable()
export class LanguageSwitherService
implements BotCommandsProvider, OnBeforeBotCommands
{
private readonly logger = new Logger(LanguageSwitherService.name);
@CustomInject(LANGUAGE_SWITHER_STORAGE)
private readonly languageSwitherStorage!: LanguageSwitherStorage;
constructor(
@Inject(LANGUAGE_SWITHER_CONFIG)
private readonly languageSwitherConfig: LanguageSwitherConfig,
private readonly translatesService: TranslatesService,
private readonly translatesStorage: TranslatesStorage,
private readonly botCommandsToolsService: BotCommandsToolsService
) {}
...
更新モジュールリブス/言語スイープ/サーバ/src/lib/言語swither.モジュールです.TS
import {
BotCommandsCategory,
BotCommandsModule,
BOT_COMMANDS_PROVIDER,
} from '@kaufman-bot/core/server';
import { DynamicModule, Module } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { CustomInjectorModule } from 'nestjs-custom-injector';
import { TranslatesModule } from 'nestjs-translates';
import {
LanguageSwitherConfig,
LANGUAGE_SWITHER_CONFIG,
} from './language-swither-config/language-swither.config';
import { LanguageSwitherService } from './language-swither-services/language-swither.service';
import {
LanguageSwitherStorage,
LANGUAGE_SWITHER_STORAGE,
} from './language-swither-services/language-swither.storage';
@Module({
imports: [TranslatesModule, BotCommandsModule],
providers: [
{ provide: LANGUAGE_SWITHER_STORAGE, useClass: LanguageSwitherStorage },
LanguageSwitherStorage,
],
exports: [TranslatesModule, BotCommandsModule, LANGUAGE_SWITHER_STORAGE],
})
...
すべての置換後、wee別のグラフを参照してくださいnpm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
ダイアログフローコマンドからのPRISMAの使用法の削除
ダイアログを更新
LIBS/ダイアログ/サーバ/src/lib/ダイアログフローサービス/ダイアログフロー.ストレージ.TS
import { Injectable } from '@nestjs/common';
import {
DialogflowSessionRequestsMetadata,
DialogflowSessionResponsesMetadata,
} from '../dialogflow-types/dialogflow-session-metadata';
export type SessionOfUsers = {
sessionId: string;
responsesMetadata: DialogflowSessionResponsesMetadata;
requestsMetadata: DialogflowSessionRequestsMetadata;
};
export const DIALOGFLOW_STORAGE = 'DIALOGFLOW_STORAGE';
export type DialogflowStorageProvider = Pick<
DialogflowStorage,
| 'getUserSession'
| 'appendToUserSession'
| 'resetUserSession'
| 'setUserSession'
>;
@Injectable()
export class DialogflowStorage {
private readonly sessionOfUsers: Record<number, SessionOfUsers> = {};
async getUserSession({
telegramUserId,
projectId,
}: {
telegramUserId: number;
projectId: string;
createIfNotExists?: boolean;
}): Promise<SessionOfUsers | null> {
const currentSessionOfUsers: SessionOfUsers =
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })];
if (currentSessionOfUsers) {
return currentSessionOfUsers;
}
return null;
}
async appendToUserSession({
telegramUserId,
projectId,
sessionOfUsers,
}: {
telegramUserId: number;
projectId: string;
sessionOfUsers: SessionOfUsers;
}): Promise<void> {
const currentSessionOfUsers: SessionOfUsers =
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] || {};
currentSessionOfUsers.requestsMetadata = [
...(currentSessionOfUsers.requestsMetadata || []),
...(sessionOfUsers.requestsMetadata || []),
];
currentSessionOfUsers.responsesMetadata = [
...(currentSessionOfUsers.responsesMetadata || []),
...sessionOfUsers.responsesMetadata,
];
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: sessionOfUsers.sessionId,
requestsMetadata: currentSessionOfUsers.requestsMetadata,
responsesMetadata: currentSessionOfUsers.responsesMetadata,
};
}
async setUserSession({
telegramUserId,
projectId,
sessionOfUsers,
}: {
telegramUserId: number;
projectId: string;
sessionOfUsers: SessionOfUsers;
}): Promise<void> {
const currentSessionOfUsers: SessionOfUsers =
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] || {};
currentSessionOfUsers.requestsMetadata = [
...(sessionOfUsers?.requestsMetadata || []),
];
currentSessionOfUsers.responsesMetadata = [
...(sessionOfUsers.responsesMetadata || []),
];
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: sessionOfUsers.sessionId,
requestsMetadata: currentSessionOfUsers.requestsMetadata,
responsesMetadata: currentSessionOfUsers.responsesMetadata,
};
}
async resetUserSession({
telegramUserId,
projectId,
}: {
telegramUserId: number;
projectId: string;
}) {
try {
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: 'sessionId',
requestsMetadata: [],
responsesMetadata: [],
};
} catch (error) {
null;
}
}
private getKey({
telegramUserId,
projectId,
}: {
telegramUserId: number;
projectId: string;
}) {
return `${telegramUserId}_${projectId}`;
}
}
を追加しますアプリケーション/サーバ/src/app/integrations/prisma/prisma統合サービス/prismaダイアログフロー.ストレージ.TS
import {
DialogflowStorageProvider,
SessionOfUsers,
} from '@kaufman-bot/dialogflow/server';
import { PrismaClientService } from '@kaufman-bot/prisma/server';
import { Injectable } from '@nestjs/common';
@Injectable()
export class PrismaDialogflowStorage implements DialogflowStorageProvider {
private readonly sessionOfUsers: Record<number, SessionOfUsers> = {};
constructor(private readonly prismaClientService: PrismaClientService) {}
async getUserSession({
telegramUserId,
projectId,
}: {
telegramUserId: number;
projectId: string;
createIfNotExists?: boolean;
}): Promise<SessionOfUsers | null> {
const currentSessionOfUsers: SessionOfUsers =
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })];
if (currentSessionOfUsers) {
return currentSessionOfUsers;
}
try {
const currentFromDatabase =
await this.prismaClientService.dialogflowSession.findFirst({
where: {
User: { telegramId: telegramUserId.toString() },
projectId,
},
rejectOnNotFound: true,
});
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: currentFromDatabase.sessionId,
requestsMetadata: currentFromDatabase.requestsMetadata,
responsesMetadata: currentFromDatabase.responsesMetadata,
};
return this.sessionOfUsers[this.getKey({ telegramUserId, projectId })];
} catch (error) {
return null;
}
}
async appendToUserSession({
telegramUserId,
projectId,
sessionOfUsers,
}: {
telegramUserId: number;
projectId: string;
sessionOfUsers: SessionOfUsers;
}): Promise<void> {
const user = await this.getUser(telegramUserId);
const currentSessionOfUsers: SessionOfUsers =
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] || {};
currentSessionOfUsers.requestsMetadata = [
...(currentSessionOfUsers.requestsMetadata || []),
...(sessionOfUsers.requestsMetadata || []),
];
currentSessionOfUsers.responsesMetadata = [
...(currentSessionOfUsers.responsesMetadata || []),
...sessionOfUsers.responsesMetadata,
];
await this.prismaClientService.dialogflowSession.upsert({
create: {
userId: user.id,
projectId,
sessionId: sessionOfUsers.sessionId,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestsMetadata: currentSessionOfUsers.requestsMetadata as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
responsesMetadata: currentSessionOfUsers.responsesMetadata as any,
},
update: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestsMetadata: currentSessionOfUsers.requestsMetadata as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
responsesMetadata: currentSessionOfUsers.responsesMetadata as any,
},
where: {
userId_projectId_sessionId: {
projectId,
userId: user.id,
sessionId: sessionOfUsers.sessionId,
},
},
});
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: sessionOfUsers.sessionId,
requestsMetadata: currentSessionOfUsers.requestsMetadata,
responsesMetadata: currentSessionOfUsers.responsesMetadata,
};
}
async setUserSession({
telegramUserId,
projectId,
sessionOfUsers,
}: {
telegramUserId: number;
projectId: string;
sessionOfUsers: SessionOfUsers;
}): Promise<void> {
const user = await this.getUser(telegramUserId);
const currentSessionOfUsers: SessionOfUsers =
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] || {};
currentSessionOfUsers.requestsMetadata = [
...(sessionOfUsers?.requestsMetadata || []),
];
currentSessionOfUsers.responsesMetadata = [
...(sessionOfUsers.responsesMetadata || []),
];
await this.prismaClientService.dialogflowSession.upsert({
create: {
userId: user.id,
projectId,
sessionId: sessionOfUsers.sessionId,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestsMetadata: currentSessionOfUsers.requestsMetadata as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
responsesMetadata: currentSessionOfUsers.responsesMetadata as any,
},
update: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestsMetadata: currentSessionOfUsers.requestsMetadata as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
responsesMetadata: currentSessionOfUsers.responsesMetadata as any,
},
where: {
userId_projectId_sessionId: {
projectId,
userId: user.id,
sessionId: sessionOfUsers.sessionId,
},
},
});
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: sessionOfUsers.sessionId,
requestsMetadata: currentSessionOfUsers.requestsMetadata,
responsesMetadata: currentSessionOfUsers.responsesMetadata,
};
}
async resetUserSession({
telegramUserId,
projectId,
}: {
telegramUserId: number;
projectId: string;
}) {
try {
const defaultUserSession =
await this.prismaClientService.dialogflowSession.findFirst({
where: {
User: { telegramId: telegramUserId.toString() },
projectId,
},
});
if (defaultUserSession) {
await this.prismaClientService.dialogflowSession.updateMany({
data: {
requestsMetadata: [],
responsesMetadata: [],
},
where: {
sessionId: defaultUserSession.sessionId,
projectId,
},
});
this.sessionOfUsers[this.getKey({ telegramUserId, projectId })] = {
sessionId: defaultUserSession.sessionId,
requestsMetadata: [],
responsesMetadata: [],
};
}
} catch (error) {
null;
}
}
private async getUser(telegramUserId: number) {
let user;
try {
user = await this.prismaClientService.user.findFirst({
select: { id: true },
where: { telegramId: telegramUserId.toString() },
rejectOnNotFound: true,
});
} catch (error) {
user = await this.prismaClientService.user.create({
data: { telegramId: telegramUserId.toString() },
});
}
return user;
}
private getKey({
telegramUserId,
projectId,
}: {
telegramUserId: number;
projectId: string;
}) {
return `${telegramUserId}_${projectId}`;
}
}
更新プログラムアプリケーション/サーバ/src/app/integrations/prisma/prisma統合.モジュールです.TS
import { DEBUG_MESSAGES_STORAGE } from '@kaufman-bot/debug-messages/server';
import { DIALOGFLOW_STORAGE } from '@kaufman-bot/dialogflow/server';
import { LANGUAGE_SWITHER_STORAGE } from '@kaufman-bot/language-swither/server';
import { PrismaClientModule } from '@kaufman-bot/prisma/server';
import { DynamicModule, Module } from '@nestjs/common';
import { PrismaDebugMessagesStorage } from './prisma-integrations/prisma-debug-messages.storage';
import { PrismaDialogflowStorage } from './prisma-integrations/prisma-dialogflow.storage';
import { PrismaFirstMeetingStorage } from './prisma-integrations/prisma-first-meeting.storage';
import { PrismaLanguageSwitherStorage } from './prisma-integrations/prisma-language-swither.storage';
@Module({})
export class PrismaIntegrationsModule {
static forRoot(): DynamicModule {
return {
module: PrismaIntegrationsModule,
imports: [PrismaClientModule],
providers: [
{
provide: DEBUG_MESSAGES_STORAGE,
useClass: PrismaDebugMessagesStorage,
},
{
provide: LANGUAGE_SWITHER_STORAGE,
useClass: PrismaLanguageSwitherStorage,
},
{
provide: DIALOGFLOW_STORAGE,
useClass: PrismaDialogflowStorage,
},
],
exports: [
DEBUG_MESSAGES_STORAGE,
LANGUAGE_SWITHER_STORAGE,
DIALOGFLOW_STORAGE,
],
};
}
}
ダイアログを更新LIBS/ダイアログ/サーバ/src/lib/ダイアログフローサービス/ダイアログフロー.サービスTS
import dialogflow, { protos } from '@google-cloud/dialogflow';
import {
BotCommandsEnum,
BotCommandsProvider,
BotCommandsProviderActionMsg,
BotCommandsProviderActionResultType,
BotCommandsToolsService,
OnAfterBotCommands,
} from '@kaufman-bot/core/server';
import { DebugService } from '@kaufman-bot/debug-messages/server';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CustomInject } from 'nestjs-custom-injector';
import { v4 } from 'uuid';
import {
DialogflowConfig,
DIALOGFLOW_CONFIG,
} from '../dialogflow-config/dialogflow.config';
import { DialogflowStorage, DIALOGFLOW_STORAGE } from './dialogflow.storage';
export const DISABLE_DIALOGFLOW_COMMANDS = 'DISABLE_DIALOGFLOW_COMMANDS';
@Injectable()
export class DialogflowService
implements BotCommandsProvider, OnAfterBotCommands
{
private readonly logger = new Logger(DialogflowService.name);
@CustomInject(DIALOGFLOW_STORAGE)
private readonly dialogflowStorage!: DialogflowStorage;
constructor(
@Inject(DIALOGFLOW_CONFIG)
private readonly dialogflowConfig: DialogflowConfig,
private readonly botCommandsToolsService: BotCommandsToolsService,
private readonly debugService: DebugService
) {}
...
すべての置換後、wee別のグラフを参照してください
npm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
最初のミーティングストレージコマンドからPriSMAの使用を削除する
更新ストレージ
LIBS/最初の会議/サーバー/SRC/lib/最初の会議サービス/最初の会議.ストレージ.TS
import { FirstMeeting } from '@prisma/client';
export const FIRST_MEETING_STORAGE = 'FIRST_MEETING_STORAGE';
export type FirstMeetingStorageProvider = Pick<
FirstMeetingStorage,
| 'createUserFirstMeeting'
| 'getUserFirstMeeting'
| 'pathUserFirstMeeting'
| 'removeUserFirstMeeting'
>;
export class FirstMeetingStorage {
private readonly firstMeetingOfUsers: Record<number, FirstMeeting> = {};
async getUserFirstMeeting({
telegramUserId,
}: {
telegramUserId: number;
}): Promise<FirstMeeting | null> {
const currentFirstMeetingOfUsers: FirstMeeting =
this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
if (currentFirstMeetingOfUsers) {
return currentFirstMeetingOfUsers;
}
return null;
}
async createUserFirstMeeting(telegramUserId: number) {
this.firstMeetingOfUsers[this.getKey({ telegramUserId })] = {
firstname: '',
lastname: '',
gender: 'Male',
status: 'StartMeeting',
};
return this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
}
async removeUserFirstMeeting({ telegramUserId }: { telegramUserId: number }) {
delete this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
}
async pathUserFirstMeeting({
telegramUserId,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
firstMeeting,
}: {
telegramUserId: number;
firstMeeting: Partial<FirstMeeting>;
}) {
let currentUserFirstMeeting = await this.getUserFirstMeeting({
telegramUserId,
});
if (!currentUserFirstMeeting) {
currentUserFirstMeeting = await this.createUserFirstMeeting(
telegramUserId
);
}
delete this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
this.firstMeetingOfUsers[this.getKey({ telegramUserId })] =
await this.getUserFirstMeeting({ telegramUserId });
}
private getKey({ telegramUserId }: { telegramUserId: number }) {
return telegramUserId.toString();
}
}
更新サービスLIBS/最初の会議/サーバー/SRC/lib/最初の会議サービス/最初の会議.サービスTS
import {
BotCommandsEnum,
BotCommandsProvider,
BotCommandsProviderActionMsg,
BotCommandsProviderActionResultType,
BotCommandsToolsService,
OnContextBotCommands,
} from '@kaufman-bot/core/server';
import { Inject, Injectable } from '@nestjs/common';
import { FirstMeeting } from '@prisma/client';
import { getText } from 'class-validator-multi-lang';
import { CustomInject } from 'nestjs-custom-injector';
import { TranslatesService } from 'nestjs-translates';
import {
FirstMeetingConfig,
FIRST_MEETING_CONFIG,
} from '../first-meeting-config/first-meeting.config';
import { FirstMeetingStorage } from './first-meeting.storage';
export const DISABLE_FIRST_MEETING_COMMANDS = 'DISABLE_FIRST_MEETING_COMMANDS';
@Injectable()
export class FirstMeetingService
implements BotCommandsProvider, OnContextBotCommands
{
@CustomInject(FirstMeetingStorage)
private readonly firstMeetingStorage!: FirstMeetingStorage;
constructor(
@Inject(FIRST_MEETING_CONFIG)
private readonly firstMeetingConfig: FirstMeetingConfig,
private readonly botCommandsToolsService: BotCommandsToolsService,
private readonly translatesService: TranslatesService
) {}
...
更新モジュールリブス/ファーストミーティング/サーバー/src/lib/初対面.モジュールです.TS
import {
BotCommandsCategory,
BotCommandsModule,
BOT_COMMANDS_PROVIDER,
} from '@kaufman-bot/core/server';
import { DynamicModule, Module } from '@nestjs/common';
import { getText } from 'class-validator-multi-lang';
import { TranslatesModule } from 'nestjs-translates';
import {
FirstMeetingConfig,
FIRST_MEETING_CONFIG,
} from './first-meeting-config/first-meeting.config';
import { FirstMeetingService } from './first-meeting-services/first-meeting.service';
import {
FirstMeetingStorage,
FIRST_MEETING_STORAGE,
} from './first-meeting-services/first-meeting.storage';
@Module({
imports: [TranslatesModule, BotCommandsModule],
providers: [
{ provide: FIRST_MEETING_STORAGE, useClass: FirstMeetingStorage },
],
exports: [TranslatesModule, BotCommandsModule, FIRST_MEETING_STORAGE],
})
export class FirstMeetingModule {
...
ストレージの実装を作成するアプリケーション/サーバ/src/app/integrations/prisma/prisma統合サービス/prisma最初の会議.ストレージ.TS
import { FirstMeetingStorageProvider } from '@kaufman-bot/first-meeting/server';
import { PrismaClientService } from '@kaufman-bot/prisma/server';
import { Injectable } from '@nestjs/common';
import { FirstMeeting } from '@prisma/client';
@Injectable()
export class PrismaFirstMeetingStorage implements FirstMeetingStorageProvider {
private readonly firstMeetingOfUsers: Record<number, FirstMeeting> = {};
constructor(private readonly prismaClientService: PrismaClientService) {}
async getUserFirstMeeting({
telegramUserId,
}: {
telegramUserId: number;
}): Promise<FirstMeeting | null> {
const currentFirstMeetingOfUsers: FirstMeeting =
this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
if (currentFirstMeetingOfUsers) {
return currentFirstMeetingOfUsers;
}
let databaseFirstMeetingOfUsers: FirstMeeting | null = null;
try {
databaseFirstMeetingOfUsers =
await this.prismaClientService.firstMeeting.findFirst({
where: {
User: { telegramId: telegramUserId.toString() },
},
rejectOnNotFound: true,
});
this.firstMeetingOfUsers[this.getKey({ telegramUserId })] =
databaseFirstMeetingOfUsers;
return this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
} catch (error) {
return null;
}
}
async createUserFirstMeeting(telegramUserId: number) {
return await this.prismaClientService.firstMeeting.create({
data: {
firstname: '',
lastname: '',
gender: 'Male',
status: 'StartMeeting',
User: {
connectOrCreate: {
create: { telegramId: telegramUserId.toString() },
where: { telegramId: telegramUserId.toString() },
},
},
},
});
}
async removeUserFirstMeeting({ telegramUserId }: { telegramUserId: number }) {
delete this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
await this.prismaClientService.firstMeeting.deleteMany({
where: {
User: { telegramId: telegramUserId.toString() },
},
});
}
async pathUserFirstMeeting({
telegramUserId,
firstMeeting,
}: {
telegramUserId: number;
firstMeeting: Partial<FirstMeeting>;
}) {
let currentUserFirstMeeting = await this.getUserFirstMeeting({
telegramUserId,
});
if (!currentUserFirstMeeting) {
currentUserFirstMeeting = await this.createUserFirstMeeting(
telegramUserId
);
}
await this.prismaClientService.firstMeeting.updateMany({
data: {
...currentUserFirstMeeting,
...firstMeeting,
updatedAt: new Date(),
},
where: {
User: { telegramId: telegramUserId.toString() },
},
});
delete this.firstMeetingOfUsers[this.getKey({ telegramUserId })];
this.firstMeetingOfUsers[this.getKey({ telegramUserId })] =
await this.getUserFirstMeeting({ telegramUserId });
}
private getKey({ telegramUserId }: { telegramUserId: number }) {
return telegramUserId.toString();
}
}
更新プログラムアプリケーション/サーバ/src/app/integrations/prisma/prisma統合.モジュールです.TS
import { DEBUG_MESSAGES_STORAGE } from '@kaufman-bot/debug-messages/server';
import { DIALOGFLOW_STORAGE } from '@kaufman-bot/dialogflow/server';
import { FIRST_MEETING_STORAGE } from '@kaufman-bot/first-meeting/server';
import { LANGUAGE_SWITHER_STORAGE } from '@kaufman-bot/language-swither/server';
import { PrismaClientModule } from '@kaufman-bot/prisma/server';
import { DynamicModule, Module } from '@nestjs/common';
import { PrismaDebugMessagesStorage } from './prisma-integrations/prisma-debug-messages.storage';
import { PrismaDialogflowStorage } from './prisma-integrations/prisma-dialogflow.storage';
import { PrismaFirstMeetingStorage } from './prisma-integrations/prisma-first-meeting.storage';
import { PrismaLanguageSwitherStorage } from './prisma-integrations/prisma-language-swither.storage';
@Module({})
export class PrismaIntegrationsModule {
static forRoot(): DynamicModule {
return {
module: PrismaIntegrationsModule,
imports: [PrismaClientModule],
providers: [
{
provide: DEBUG_MESSAGES_STORAGE,
useClass: PrismaDebugMessagesStorage,
},
{
provide: LANGUAGE_SWITHER_STORAGE,
useClass: PrismaLanguageSwitherStorage,
},
{
provide: DIALOGFLOW_STORAGE,
useClass: PrismaDialogflowStorage,
},
{
provide: FIRST_MEETING_STORAGE,
useClass: PrismaFirstMeetingStorage,
},
],
exports: [
DEBUG_MESSAGES_STORAGE,
LANGUAGE_SWITHER_STORAGE,
DIALOGFLOW_STORAGE,
FIRST_MEETING_STORAGE,
],
};
}
}
すべての置換後、wee別のグラフを参照してくださいnpm run nx -- graph
endy@endy-virtual-machine:~/Projects/current/kaufman-bot$ npm run nx -- graph
> [email protected] nx
> nx "graph"
> NX Project graph started at http://127.0.0.1:4211
ご覧のように、データベースを操作するためのPrismaライブラリは他のライブラリへのリンクはありません.
プロジェクトは現在NPMレジストリに公開される準備が整いました.
次のポストでは、NPMレジストリ内のすべてのライブラリを公開します.
Reference
この問題について(NESTJS上でのDI‐in電報ロボットによるモジュールへのリファクタリングモノリス応用), 我々は、より多くの情報をここで見つけました https://dev.to/endykaufman/refactoring-monolith-application-to-modules-with-di-in-telegram-bot-on-nestjs-2llcテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol