enhance(backend): DTOを導入

This commit is contained in:
Xeltica 2023-04-27 19:41:59 +09:00
parent ac205b9a9e
commit 06876c528d
8 changed files with 92 additions and 20 deletions

View File

@ -1,5 +1,11 @@
# CONTRIBUTING # CONTRIBUTING
Misskey Tools へのコントリビューションにご関心いただき、誠にありがとうございます。
このドキュメントでは、本プロジェクトの開発方針をまとめています。IssueやPull Requestの作成前に、必ずご一読ください。
なお、開発の進行に応じて、ドキュメントの内容は大きく変わることがあります。
## データベース スキーマの編集 ## データベース スキーマの編集
* TypeScriptのコーディング規約に一致するように、命名規則を定める * TypeScriptのコーディング規約に一致するように、命名規則を定める
@ -10,4 +16,10 @@
* `//` /2つだと整形時に削除されてしまうため注意 * `//` /2つだと整形時に削除されてしまうため注意
* schema.prisma を編集したら、次のコマンドを実行してSQLファイルを生成する * schema.prisma を編集したら、次のコマンドを実行してSQLファイルを生成する
* `prisma migrate dev --name 変更名` * `prisma migrate dev --name 変更名`
* 変更名は snake_case * 変更名は snake_case
## tRPCでのデータ返却時はDTOを渡すこと
意図しないデータの漏洩を防ぐため、フロントエンドへデータを渡す場合は、必ずDBの実データではなく、DTOへの変換を通してください。
また、実データを返すと、tRPCの型定義にPrismaの型が含まれてしまい、フロントエンド側からTypeScriptのエラー TS2742 が発生します。

View File

@ -0,0 +1,17 @@
import { Account } from '@prisma/client';
import { z } from 'zod';
export const accountDtoSchema = z.object({
id: z.string(),
name: z.string(),
isAdmin: z.boolean(),
}).strict();
export type AccountDto = z.infer<typeof accountDtoSchema>;
export const toAccountDto = (a: Account): AccountDto => ({
id: a.id,
name: a.name,
isAdmin: a.isAdmin,
});

View File

@ -0,0 +1,9 @@
import { currentTokenVersion } from 'tools-shared/dist/const';
import { z } from 'zod';
export const metaDtoSchema = z.object({
version: z.string(),
currentTokenVersion: z.literal(currentTokenVersion),
}).strict();
export type MetaDto = z.infer<typeof metaDtoSchema>;

View File

@ -0,0 +1,16 @@
import { MisskeySession } from '@prisma/client';
import { z } from 'zod';
export const misskeySessionDtoSchema = z.object({
id: z.string(),
username: z.string(),
host: z.string(),
}).strict();
export type MisskeySessionDto = z.infer<typeof misskeySessionDtoSchema>;
export const toMisskeySessionDto = (s: MisskeySession): MisskeySessionDto => ({
id: s.id,
username: s.username,
host: s.host,
});

View File

@ -3,13 +3,14 @@ import { TRPCError } from '@trpc/server';
import { middleware, procedure } from '@/server/api/trpc.js'; import { middleware, procedure } from '@/server/api/trpc.js';
const hasSession = middleware(({ next, ctx }) => { const hasSession = middleware(({ next, ctx }) => {
if (!ctx.account) { const { account } = ctx;
if (!account) {
throw new TRPCError({ code: 'UNAUTHORIZED' }); throw new TRPCError({ code: 'UNAUTHORIZED' });
} }
return next({ return next({
ctx: { ctx: {
token: ctx.token, token: ctx.token,
user: ctx.account, account: account,
}, },
}); });
}); });

View File

@ -1,17 +1,31 @@
import { TRPCError } from '@trpc/server';
import { z } from 'zod'; import { z } from 'zod';
import { accountDtoSchema, toAccountDto } from '../dto/account';
import { misskeySessionDtoSchema } from '../dto/misskey-session';
import { prisma } from '@/libs/prisma';
import { sessionProcedure } from '@/server/api/procedures/session.js'; import { sessionProcedure } from '@/server/api/procedures/session.js';
import { procedure, router } from '@/server/api/trpc.js'; import { router } from '@/server/api/trpc.js';
import { getAccountByAccessToken } from '@/services/accounts/get-account-by-access-token.js';
export const accountRouter = router({ export const accountRouter = router({
get: sessionProcedure.query(({ ctx }) => ctx.user), getMyself: sessionProcedure
getByToken: procedure.input(z.string()).query(async ({ input: token }) => { .output(accountDtoSchema)
const account = await getAccountByAccessToken(token); .query(({ ctx }) => {
if (!account) { return toAccountDto(ctx.account);
throw new TRPCError({ code: 'NOT_FOUND' }); }),
} getMisskeySessions: sessionProcedure
return account; .output(z.array(misskeySessionDtoSchema))
}), .query(async ({ ctx }) => {
const sessions = await prisma.misskeySession.findMany({
where: { accountId: ctx.account.id },
select: {
id: true,
username: true,
host: true,
},
});
return sessions;
}),
}); });

View File

@ -1,12 +1,15 @@
import { currentTokenVersion } from 'tools-shared/dist/const.js'; import { currentTokenVersion } from 'tools-shared/dist/const.js';
import { metaDtoSchema } from '../dto/meta';
import { meta } from '@/config'; import { meta } from '@/config';
import { procedure, router } from '@/server/api/trpc'; import { procedure, router } from '@/server/api/trpc';
export const metaRouter = router({ export const metaRouter = router({
get: procedure.query(() => ({ get: procedure
version: meta.version, .output(metaDtoSchema)
currentTokenVersion, .query(() => ({
})), version: meta.version,
currentTokenVersion,
})),
}); });

View File

@ -29,7 +29,7 @@ export const processLogin = async (misskeyUser: MkUser, host: string, misskeyTok
}, },
}, },
// Note: 少しでもデータ転送量を抑えるPrismaはcreateの後に絶対selectを実行してしまう // Note: 少しでもデータ転送量を抑えるPrismaはcreateの後に絶対selectを実行してしまう
select: {}, select: { id: true },
}); });
return accessToken; return accessToken;
} }