diff --git a/migrations/tenant/0008-users@add-editor-tools-remove-extensions.sql b/migrations/tenant/0008-users@add-editor-tools-remove-extensions.sql new file mode 100644 index 00000000..d7168f02 --- /dev/null +++ b/migrations/tenant/0008-users@add-editor-tools-remove-extensions.sql @@ -0,0 +1,22 @@ + +-- Adds "editor_tools" column at "users" if not exists +DO $$ +BEGIN + IF NOT EXISTS(SELECT * + FROM information_schema.columns + WHERE table_name='users' and column_name='editor_tools') + THEN + ALTER TABLE "public"."users" ADD COLUMN "editor_tools" jsonb; + END IF; +END $$; + +-- Removes "extensions" column at "users" if exists +DO $$ +BEGIN + IF EXISTS(SELECT * + FROM information_schema.columns + WHERE table_name='users' and column_name='extensions') + THEN + ALTER TABLE "public"."users" DROP COLUMN "extensions"; + END IF; +END $$; diff --git a/migrations/tenant/0009-editor-tools@rename-camelcase-to-underscore.sql b/migrations/tenant/0009-editor-tools@rename-camelcase-to-underscore.sql new file mode 100644 index 00000000..46c2de25 --- /dev/null +++ b/migrations/tenant/0009-editor-tools@rename-camelcase-to-underscore.sql @@ -0,0 +1,33 @@ +-- "editor_tools" table: + +-- Rename column "isDefault" to "is_default" if "isDefault" exists and "is_default" not exists +DO $$ +BEGIN + IF EXISTS(SELECT * + FROM information_schema.columns + WHERE table_name='editor_tools' and column_name='isDefault') + THEN + IF NOT EXISTS(SELECT * + FROM information_schema.columns + WHERE table_name='editor_tools' and column_name='is_default') + THEN + ALTER TABLE "public"."editor_tools" RENAME COLUMN "isDefault" TO "is_default"; + END IF; + END IF; +END $$; + +-- Rename column "exportName" to "export_name" if "exportName" exists and "export_name" not exists +DO $$ +BEGIN + IF EXISTS(SELECT * + FROM information_schema.columns + WHERE table_name='editor_tools' and column_name='exportName') + THEN + IF NOT EXISTS(SELECT * + FROM information_schema.columns + WHERE table_name='editor_tools' and column_name='export_name') + THEN + ALTER TABLE "public"."editor_tools" RENAME COLUMN "exportName" TO "export_name"; + END IF; + END IF; +END $$; diff --git a/src/domain/entities/user.ts b/src/domain/entities/user.ts index 08a7dc0c..32957ede 100644 --- a/src/domain/entities/user.ts +++ b/src/domain/entities/user.ts @@ -1,4 +1,4 @@ -import type UserExtensions from '@domain/entities/userExtensions.js'; +import type EditorTool from './editorTools'; /** * User entity @@ -30,8 +30,7 @@ export default interface User { photo?: string; /** - * Custom plugins from the marketplace that improve - * editor or notes environment + * Custom plugins ids from the marketplace that improve editor or notes environment */ - extensions?: UserExtensions; + editorTools?: EditorTool['id'][]; } diff --git a/src/domain/entities/userExtensions.ts b/src/domain/entities/userExtensions.ts deleted file mode 100644 index 4ee4acc4..00000000 --- a/src/domain/entities/userExtensions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type EditorTool from '@domain/entities/editorTools.js'; - -/** - * Tools that user uses in the editor while changing notes - */ -export interface UserEditorTool { - /** - * Unique tool identifier - */ - id: EditorTool['id']; -} - -/** - * Custom user extensions and plugin that expand the capabilities - * of the editor - */ -export default interface UserExtensions { - editorTools?: UserEditorTool[]; -} diff --git a/src/domain/index.ts b/src/domain/index.ts index 8e88151c..c061e04e 100644 --- a/src/domain/index.ts +++ b/src/domain/index.ts @@ -63,10 +63,14 @@ export function init(repositories: Repositories, appConfig: AppConfig): DomainSe repositories.userSessionRepository ); - const userService = new UserService(repositories.userRepository); - - const aiService = new AIService(repositories.aiRepository); const editorToolsService = new EditorToolsService(repositories.editorToolsRepository); + const userService = new UserService(repositories.userRepository, { + editorTools: editorToolsService, + /** + * @todo find a way how to resolve circular dependency + */ + }); + const aiService = new AIService(repositories.aiRepository); return { noteService, diff --git a/src/domain/service/editorTools.ts b/src/domain/service/editorTools.ts index a25e51d2..c0a14282 100644 --- a/src/domain/service/editorTools.ts +++ b/src/domain/service/editorTools.ts @@ -1,11 +1,12 @@ import type EditorToolsRepository from '@repository/editorTools.repository.js'; import type EditorTool from '@domain/entities/editorTools.js'; import { createEditorToolId } from '@infrastructure/utils/id.js'; +import type EditorToolsServiceSharedMethods from './shared/editorTools.js'; /** * Editor tools service */ -export default class EditorToolsService { +export default class EditorToolsService implements EditorToolsServiceSharedMethods { /** * User repository instance */ @@ -32,10 +33,17 @@ export default class EditorToolsService { * * @param editorToolIds - tool ids */ - public async getToolsByIds(editorToolIds: EditorTool['id'][] ): Promise { + public async getToolsByIds(editorToolIds: EditorTool['id'][]): Promise { return await this.repository.getToolsByIds(editorToolIds); } + /** + * Return tools that are available at Editor by default + */ + public async getDefaultTools(): Promise { + return await this.repository.getDefaultTools(); + } + /** * Adding custom editor tool * diff --git a/src/domain/service/shared/README.md b/src/domain/service/shared/README.md new file mode 100644 index 00000000..b7d2d0f0 --- /dev/null +++ b/src/domain/service/shared/README.md @@ -0,0 +1,30 @@ +# Shared Domain Services + +Sometimes you may want to call some domain method from other domain. We can inject them in constructor, but it creates a direct dependency. + +One way do decouple domains is to create a Shared Interfaces — domain will "expose" some public methods though it. You can call it "Contract". +So dependant domain will depend on it instead of direct dependency. + + +## Example + +```ts +interface DomainASharedMethods { + someMethodA: () => void; +} + +export type SharedDomainMethods = { + domainA: DomainASharedMethods; +}; + + +class DomainA implements DomainASharedMethods { + public someMethodA (){} +} + +class DomainB { + constructor(private readonly shared: SharedDomainMethods) { + this.shared.domainA.someMethodA(); // here we call method of Domain A, but without direct dependency + } +} +``` diff --git a/src/domain/service/shared/editorTools.ts b/src/domain/service/shared/editorTools.ts new file mode 100644 index 00000000..8f1d63a4 --- /dev/null +++ b/src/domain/service/shared/editorTools.ts @@ -0,0 +1,19 @@ +import type EditorTool from '@domain/entities/editorTools'; + +/** + * Which methods of Domain can be used by other domains + * Uses to decouple domains from each other + */ +export default interface EditorToolsServiceSharedMethods { + /** + * Return tools that are available at Editor by default + */ + getDefaultTools(): Promise; + + /** + * Get bunch of editor tools by their ids + * + * @param ids - tool ids to resolve + */ + getToolsByIds(ids: EditorTool['id'][]): Promise; +} diff --git a/src/domain/service/shared/index.ts b/src/domain/service/shared/index.ts new file mode 100644 index 00000000..11364d8f --- /dev/null +++ b/src/domain/service/shared/index.ts @@ -0,0 +1,5 @@ +import type EditorToolsServiceSharedMethods from './editorTools'; + +export type SharedDomainMethods = { + editorTools: EditorToolsServiceSharedMethods; +}; diff --git a/src/domain/service/user.ts b/src/domain/service/user.ts index f734bdb3..b54a0ea1 100644 --- a/src/domain/service/user.ts +++ b/src/domain/service/user.ts @@ -2,6 +2,7 @@ import type UserRepository from '@repository/user.repository.js'; import { Provider } from '@repository/user.repository.js'; import type User from '@domain/entities/user.js'; import type EditorTool from '@domain/entities/editorTools'; +import type { SharedDomainMethods } from './shared/index.js'; export { Provider @@ -20,8 +21,9 @@ export default class UserService { * User service constructor * * @param repository - user repository instance + * @param shared - shared domains */ - constructor(repository: UserRepository) { + constructor(repository: UserRepository, private readonly shared: SharedDomainMethods) { this.repository = repository; } @@ -47,15 +49,28 @@ export default class UserService { } /** - * Get user extensions that contains only editoTools for now - * TODO: Simplify extenisons + * Get user editor tools ids * * @param userId - user unique identifier */ - public async getUserExtensions(userId: User['id']): Promise { + public async getUserEditorTools(userId: User['id']): Promise { const user = await this.getUserById(userId); - return user?.extensions ?? {}; + if (user === null) { + throw new Error('User not found'); + } + + const userToolsIds = user.editorTools ?? []; + const defaultTools = await this.shared.editorTools.getDefaultTools(); + const uniqueDefaultEditorTools = defaultTools.filter(({ id }) => !userToolsIds.includes(id)); + const userTools = await this.shared.editorTools.getToolsByIds(userToolsIds) ?? []; + + /** + * Combine user tools and default tools + * + * @todo load tools in notes service + */ + return [...userTools, ...uniqueDefaultEditorTools]; } /** @@ -65,16 +80,14 @@ export default class UserService { */ public async addUserEditorTool({ userId, - editorToolId, + toolId, }: { userId: User['id'], - editorToolId: EditorTool['id'], + toolId: EditorTool['id'], }): Promise { return await this.repository.addUserEditorTool({ userId, - tool: { - id: editorToolId, - }, + toolId, }); } } diff --git a/src/presentation/http/router/user.ts b/src/presentation/http/router/user.ts index 2b1e120e..965f8076 100644 --- a/src/presentation/http/router/user.ts +++ b/src/presentation/http/router/user.ts @@ -30,7 +30,6 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don * Manage user data */ const userService = opts.userService; - const editorToolsService = opts.editorToolsService; /** * Get user by session @@ -63,7 +62,7 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don }); /** - * Get user extensions + * Get user editor tools */ fastify.get('/editor-tools', { config: { @@ -93,12 +92,10 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don }, async (request, reply) => { const userId = request.userId as number; - const userExtensions = await userService.getUserExtensions(userId); - const userEditorToolIds = userExtensions?.editorTools?.map(tools => tools.id) ?? []; - const editorTools = await editorToolsService.getToolsByIds(userEditorToolIds) ?? []; + const tools = await userService.getUserEditorTools(userId); return reply.send({ - data: editorTools, + data: tools, }); }); @@ -124,16 +121,16 @@ const UserRouter: FastifyPluginCallback = (fastify, opts, don }, }, }, async (request, reply) => { - const editorToolId = request.body.toolId; + const toolId = request.body.toolId; const userId = request.userId as number; await userService.addUserEditorTool({ userId, - editorToolId, + toolId, }); return reply.send({ - data: editorToolId, + data: toolId, }); }); diff --git a/src/presentation/http/schema/User.ts b/src/presentation/http/schema/User.ts index 9061d2f3..4f03ad48 100644 --- a/src/presentation/http/schema/User.ts +++ b/src/presentation/http/schema/User.ts @@ -10,4 +10,11 @@ export const UserSchema = { name: { type: 'string' }, photo: { type: 'string' }, }, + editorTools: { + type: 'array', + description: 'List of editor tools ids installed by user from Marketplace', + items: { + type: 'string', + }, + }, }; diff --git a/src/repository/editorTools.repository.ts b/src/repository/editorTools.repository.ts index 9a20d359..c29dbe12 100644 --- a/src/repository/editorTools.repository.ts +++ b/src/repository/editorTools.repository.ts @@ -34,6 +34,13 @@ export default class EditorToolsRepository { return tools; } + /** + * Get all default tools + */ + public async getDefaultTools(): Promise { + return await this.storage.getDefaultTools(); + } + /** * Get all editor tools */ diff --git a/src/repository/note.repository.ts b/src/repository/note.repository.ts index e2baa164..73677924 100644 --- a/src/repository/note.repository.ts +++ b/src/repository/note.repository.ts @@ -1,6 +1,5 @@ import type { Note, NoteCreationAttributes, NoteInternalId, NotePublicId } from '@domain/entities/note.js'; import type NoteStorage from '@repository/storage/note.storage.js'; -import type { NoteList } from '@domain/entities/noteList.js'; /** * Repository allows accessing data from business-logic (domain) level @@ -85,7 +84,6 @@ export default class NoteRepository { * @param id - note creator id * @param offset - number of skipped notes * @param limit - number of notes to get - * @returns { Promise } note */ public async getNoteListByCreatorId(id: number, offset: number, limit: number): Promise { return await this.storage.getNoteListByCreatorId(id, offset, limit); diff --git a/src/repository/storage/postgres/orm/sequelize/editorTools.ts b/src/repository/storage/postgres/orm/sequelize/editorTools.ts index f20d3c17..a431bb5d 100644 --- a/src/repository/storage/postgres/orm/sequelize/editorTools.ts +++ b/src/repository/storage/postgres/orm/sequelize/editorTools.ts @@ -13,7 +13,7 @@ export class EditorToolModel extends Model, Inf public declare id: EditorTool['id']; /** - * Custom name that uses in editor initiazliation. e.g. 'code' + * Custom name that uses in editor initialization. e.g. 'code' */ public declare name: EditorTool['name']; @@ -31,6 +31,11 @@ export class EditorToolModel extends Model, Inf * Editor tool sources */ public declare source: EditorTool['source']; + + /** + * Applies to user editor tools by default + */ + public declare isDefault: EditorTool['isDefault']; } /** @@ -85,6 +90,10 @@ export default class UserSequelizeStorage { type: DataTypes.JSON, allowNull: false, }, + isDefault: { + type: DataTypes.BOOLEAN, + allowNull: true, + }, }, { tableName: this.tableName, sequelize: this.database, @@ -101,16 +110,16 @@ export default class UserSequelizeStorage { title, exportName, source, + isDefault, }: EditorTool): Promise { - const editorTool = await this.model.create({ + return await this.model.create({ id, name, title, exportName, source, + isDefault, }); - - return editorTool; } /** @@ -119,23 +128,30 @@ export default class UserSequelizeStorage { * @param editorToolIds - tool ids */ public async getToolsByIds(editorToolIds: EditorTool['id'][]): Promise { - const editorTools = await this.model.findAll({ + return await this.model.findAll({ where: { id: { [Op.in]: editorToolIds, }, }, }); + } - return editorTools; + /** + * Get all default tools + */ + public async getDefaultTools(): Promise { + return await this.model.findAll({ + where: { + isDefault: true, + }, + }); } /** * Get all available editor tools */ public async getTools(): Promise { - const editorTools = await EditorToolModel.findAll(); - - return editorTools; + return await EditorToolModel.findAll(); } } diff --git a/src/repository/storage/postgres/orm/sequelize/index.ts b/src/repository/storage/postgres/orm/sequelize/index.ts index 93e3dc10..f8a2c9eb 100644 --- a/src/repository/storage/postgres/orm/sequelize/index.ts +++ b/src/repository/storage/postgres/orm/sequelize/index.ts @@ -28,6 +28,12 @@ export default class SequelizeOrm { this.conn = new Sequelize(this.config.dsn, { logging: databaseLogger.info.bind(databaseLogger), + define: { + /** + * Use snake_case for fields in db, but camelCase in code + */ + underscored: true, + }, }); } diff --git a/src/repository/storage/postgres/orm/sequelize/note.ts b/src/repository/storage/postgres/orm/sequelize/note.ts index 42e24449..03f40a3e 100644 --- a/src/repository/storage/postgres/orm/sequelize/note.ts +++ b/src/repository/storage/postgres/orm/sequelize/note.ts @@ -103,7 +103,6 @@ export default class NoteSequelizeStorage { }, { tableName: this.tableName, sequelize: this.database, - underscored: true, // use snake_case for fields in db }); } @@ -131,13 +130,11 @@ export default class NoteSequelizeStorage { * @returns { Note } - created note */ public async createNote(options: NoteCreationAttributes): Promise { - const createdNote = await this.model.create({ + return await this.model.create({ publicId: options.publicId, content: options.content, creatorId: options.creatorId, }); - - return createdNote; } /** @@ -170,20 +167,11 @@ export default class NoteSequelizeStorage { * @param id - internal id */ public async getNoteById(id: NoteInternalId): Promise { - const note = await this.model.findOne({ + return await this.model.findOne({ where: { id, }, }); - - /** - * If note not found, return null - */ - if (!note) { - return null; - } - - return note; } /** @@ -213,15 +201,13 @@ export default class NoteSequelizeStorage { * @returns { Promise } note */ public async getNoteListByCreatorId(creatorId: number, offset: number, limit: number): Promise { - const noteList = await this.model.findAll({ + return await this.model.findAll({ offset: offset, limit: limit, where: { creatorId, }, }); - - return noteList; } /** * Gets note by id @@ -256,12 +242,10 @@ export default class NoteSequelizeStorage { * @returns { Promise } found note */ public async getNoteByPublicId(publicId: NotePublicId): Promise { - const note = await this.model.findOne({ + return await this.model.findOne({ where: { publicId, }, }); - - return note; }; } diff --git a/src/repository/storage/postgres/orm/sequelize/noteSettings.ts b/src/repository/storage/postgres/orm/sequelize/noteSettings.ts index 04c8af68..2c36ba01 100644 --- a/src/repository/storage/postgres/orm/sequelize/noteSettings.ts +++ b/src/repository/storage/postgres/orm/sequelize/noteSettings.ts @@ -92,7 +92,6 @@ export default class NoteSettingsSequelizeStorage { tableName: this.tableName, sequelize: this.database, timestamps: false, - underscored: true, // use snake_case for fields in db }); } diff --git a/src/repository/storage/postgres/orm/sequelize/teams.ts b/src/repository/storage/postgres/orm/sequelize/teams.ts index ee241656..d6df080a 100644 --- a/src/repository/storage/postgres/orm/sequelize/teams.ts +++ b/src/repository/storage/postgres/orm/sequelize/teams.ts @@ -104,7 +104,6 @@ export default class TeamsSequelizeStorage { tableName: this.tableName, sequelize: this.database, timestamps: false, - underscored: true, // use snake_case for fields in db }); } diff --git a/src/repository/storage/postgres/orm/sequelize/user.ts b/src/repository/storage/postgres/orm/sequelize/user.ts index 242137c8..53585523 100644 --- a/src/repository/storage/postgres/orm/sequelize/user.ts +++ b/src/repository/storage/postgres/orm/sequelize/user.ts @@ -3,7 +3,7 @@ import { fn, col } from 'sequelize'; import { Model, DataTypes } from 'sequelize'; import type Orm from '@repository/storage/postgres/orm/sequelize/index.js'; import type User from '@domain/entities/user.js'; -import type { UserEditorTool } from '@domain/entities/userExtensions.js'; +import type EditorTool from '@domain/entities/editorTools'; /** * Query options for getting user @@ -47,9 +47,9 @@ export interface AddUserToolOptions { userId: User['id']; /** - * Editor tool data + * Editor tool identifier */ - tool: UserEditorTool; + toolId: EditorTool['id']; } /** @@ -62,9 +62,9 @@ interface RemoveUserEditorTool { userId: User['id']; /** - * Editor tool + * Editor tool identifier */ - editorTool: UserEditorTool; + toolId: EditorTool['id']; } /* eslint-disable @typescript-eslint/naming-convention */ @@ -91,7 +91,7 @@ export class UserModel extends Model, InferCreationAt /** * User created at */ - public declare created_at: Date; + public declare createdAt: Date; /** * User photo @@ -99,9 +99,9 @@ export class UserModel extends Model, InferCreationAt public declare photo: CreationOptional; /** - * + * List of tools ids installed by user from Marketplace */ - public declare extensions: CreationOptional; + public declare editorTools: CreationOptional; } /** @@ -149,15 +149,15 @@ export default class UserSequelizeStorage { type: DataTypes.STRING, allowNull: false, }, - created_at: { + createdAt: { type: DataTypes.DATE, allowNull: false, }, photo: { type: DataTypes.STRING, }, - extensions: { - type: DataTypes.JSON, + editorTools: { + type: DataTypes.ARRAY(DataTypes.STRING), }, }, { tableName: this.tableName, @@ -173,14 +173,14 @@ export default class UserSequelizeStorage { */ public async addUserEditorTool({ userId, - tool: editorTool, + toolId, }: AddUserToolOptions): Promise { await this.model.update({ - extensions: fn('array_append', col('editorTools'), editorTool), + editorTools: fn('array_append', col('editor_tools'), toolId), }, { where: { id: userId, - // TODO: Add check to unique editorTool id + // @todo Add check to unique editorTool id }, }); } @@ -192,10 +192,10 @@ export default class UserSequelizeStorage { */ public async removeUserEditorTool({ userId, - editorTool, + toolId, }: RemoveUserEditorTool): Promise { await this.model.update({ - extensions: fn('array_remove', col('editorTools'), editorTool), + editorTools: fn('array_remove', col('editor_tools'), toolId), }, { where: { id: userId, @@ -214,20 +214,12 @@ export default class UserSequelizeStorage { name, photo, }: InsertUserOptions): Promise { - const user = await this.model.create({ + return await this.model.create({ email, name, - created_at: new Date(), + createdAt: new Date(), photo, }); - - return { - id: user.id, - email: user.email, - name: user.name, - createdAt: user.created_at, - photo: user.photo, - }; } /** @@ -274,13 +266,6 @@ export default class UserSequelizeStorage { return null; } - return { - id: user.id, - email: user.email, - name: user.name, - createdAt: user.created_at, - photo: user.photo, - extensions: user.extensions, - }; + return user; } } diff --git a/src/repository/storage/postgres/orm/sequelize/userSession.ts b/src/repository/storage/postgres/orm/sequelize/userSession.ts index 317e1b07..e602b006 100644 --- a/src/repository/storage/postgres/orm/sequelize/userSession.ts +++ b/src/repository/storage/postgres/orm/sequelize/userSession.ts @@ -18,17 +18,17 @@ class UserSessionModel extends Model, InferCre /** * User id */ - public declare user_id: number; + public declare userId: number; /** * Refresh token */ - public declare refresh_token: string; + public declare refreshToken: string; /** * Refresh token expiration date */ - public declare refresh_token_expires_at: Date; + public declare refreshTokenExpiresAt: Date; } @@ -68,7 +68,7 @@ export default class UserSessionSequelizeStorage { autoIncrement: true, primaryKey: true, }, - user_id: { + userId: { type: DataTypes.INTEGER, allowNull: false, references: { @@ -76,12 +76,12 @@ export default class UserSessionSequelizeStorage { key: 'id', }, }, - refresh_token: { + refreshToken: { type: DataTypes.STRING, allowNull: false, unique: true, }, - refresh_token_expires_at: { + refreshTokenExpiresAt: { type: DataTypes.DATE, allowNull: false, }, @@ -101,18 +101,11 @@ export default class UserSessionSequelizeStorage { * @returns { UserSession } created user session */ public async create(userId: number, refreshToken: string, refreshTokenExpiresAt: Date): Promise { - const session = await this.model.create({ - user_id: userId, - refresh_token: refreshToken, - refresh_token_expires_at: refreshTokenExpiresAt, + return await this.model.create({ + userId: userId, + refreshToken: refreshToken, + refreshTokenExpiresAt: refreshTokenExpiresAt, }); - - return { - id: session.id, - userId: session.user_id, - refreshToken: session.refresh_token, - refreshTokenExpiresAt: session.refresh_token_expires_at, - }; } /** @@ -122,20 +115,9 @@ export default class UserSessionSequelizeStorage { * @returns { UserSession | null } found user session */ public async findByToken(token: string): Promise { - const session = await this.model.findOne({ - where: { refresh_token: token }, + return await this.model.findOne({ + where: { refreshToken: token }, }); - - if (!session) { - return null; - } - - return { - id: session.id, - userId: session.user_id, - refreshToken: session.refresh_token, - refreshTokenExpiresAt: session.refresh_token_expires_at, - }; } /** @@ -146,7 +128,9 @@ export default class UserSessionSequelizeStorage { */ public async removeByRefreshToken(refreshToken: string): Promise { await this.model.destroy({ - where: { refresh_token: refreshToken }, + where: { + refreshToken, + }, }); } } diff --git a/src/repository/user.repository.ts b/src/repository/user.repository.ts index 0705c2ef..f3018149 100644 --- a/src/repository/user.repository.ts +++ b/src/repository/user.repository.ts @@ -1,9 +1,9 @@ import type User from '@domain/entities/user.js'; -import type { UserEditorTool } from '@domain/entities/userExtensions.js'; import type UserStorage from '@repository/storage/user.storage.js'; import type GoogleApiTransport from '@repository/transport/google-api/index.js'; import type GetUserInfoResponsePayload from '@repository/transport/google-api/types/GetUserInfoResponsePayload.js'; import type { AddUserToolOptions } from '@repository/storage/postgres/orm/sequelize/user'; +import type EditorTool from '@domain/entities/editorTools'; /** * OAuth provider @@ -27,7 +27,7 @@ interface RemoveUserEditorToolOptions { /** * Editor tool identifier */ - editorToolId: UserEditorTool['id']; + toolId: EditorTool['id']; } /** @@ -127,10 +127,10 @@ export default class UserRepository { * * @param options - identifiers of user and tool */ - public async addUserEditorTool({ userId, tool }: AddUserToolOptions): Promise { + public async addUserEditorTool({ userId, toolId }: AddUserToolOptions): Promise { await this.storage.addUserEditorTool({ userId, - tool, + toolId, }); } @@ -139,22 +139,22 @@ export default class UserRepository { * * @param options - identifiers of user and tool */ - public async removeUserEditorTool({ userId, editorToolId }: RemoveUserEditorToolOptions): Promise { + public async removeUserEditorTool({ userId, toolId }: RemoveUserEditorToolOptions): Promise { const user = await this.getUserById(userId); if (!user) { - throw new Error('There is no user with such userId'); + throw new Error('There is no user with such id'); } - const editorTool = user.extensions?.editorTools?.find(tool => tool.id === editorToolId); + const editorTool = user.editorTools?.find(id => id === toolId); - if (!editorTool) { - throw new Error('User has no tool with such editorToolId'); + if (editorTool === undefined) { + throw new Error('User has no tool with such id'); } await this.storage.removeUserEditorTool({ userId, - editorTool, + toolId: editorTool, }); } }