From 6c38c130b2d042178898c0f7a224183f9ad52d76 Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Wed, 8 Nov 2023 00:06:31 -0800 Subject: [PATCH] chore: refactor create verical router --- packages/cdk-core/verticals/accounting.ts | 48 ++++++++----------- packages/cdk-core/verticals/investment.ts | 58 ++++++++++------------- packages/cdk-core/verticals/new-mapper.ts | 41 ++++++++-------- 3 files changed, 66 insertions(+), 81 deletions(-) diff --git a/packages/cdk-core/verticals/accounting.ts b/packages/cdk-core/verticals/accounting.ts index 17675b93..defaa9c7 100644 --- a/packages/cdk-core/verticals/accounting.ts +++ b/packages/cdk-core/verticals/accounting.ts @@ -1,5 +1,5 @@ import type {MaybePromise} from '@usevenice/util' -import {z} from '@usevenice/util' +import {objectEntries, R, z} from '@usevenice/util' import type {IntegrationSchemas, IntHelpers} from '../integration.types' import type { @@ -7,7 +7,11 @@ import type { Pagination, VerticalRouterOpts, } from './new-mapper' -import {paginatedOutput, proxyListRemote, zPaginationParams} from './new-mapper' +import { + paginatedOutput, + proxyListRemoteRedux, + zPaginationParams, +} from './new-mapper' export const zAccounting = { account: z.object({ @@ -61,32 +65,20 @@ export interface AccountingMethods< // Guess it means accounting router also belongs in the engine backend... export function createAccountingRouter(opts: VerticalRouterOpts) { + const vertical = 'accounting' // We cannot use a single trpc procedure because neither openAPI nor trpc // supports switching output shape that depends on input - return opts.trpc.router({ - listAccounts: opts.remoteProcedure - .meta({ - openapi: {method: 'GET', path: '/accounting/accounts'}, - response: {vertical: 'accounting', entity: 'account', type: 'list'}, - }) - .input(zPaginationParams.nullish()) - .output(paginatedOutput(zAccounting.account)) - .query(proxyListRemote), - listExpenses: opts.remoteProcedure - .meta({ - openapi: {method: 'GET', path: '/accounting/expenses'}, - response: {vertical: 'accounting', entity: 'expense', type: 'list'}, - }) - .input(zPaginationParams.nullish()) - .output(paginatedOutput(zAccounting.expense)) - .query(proxyListRemote), - listVendors: opts.remoteProcedure - .meta({ - openapi: {method: 'GET', path: '/accounting/vendors'}, - response: {vertical: 'accounting', entity: 'vendor', type: 'list'}, - }) - .input(zPaginationParams.nullish()) - .output(paginatedOutput(zAccounting.vendor)) - .query(proxyListRemote), - }) + + return opts.trpc.router( + R.mapToObj(objectEntries(zAccounting), ([entityName, v]) => [ + `${vertical}_${entityName}_list`, + opts.remoteProcedure + .meta({openapi: {method: 'GET', path: `/${vertical}/${entityName}`}}) + .input(zPaginationParams.nullish()) + .output(paginatedOutput(v)) + .query(async ({input, ctx}) => + proxyListRemoteRedux({input, ctx, meta: {entityName, vertical}}), + ), + ]), + ) } diff --git a/packages/cdk-core/verticals/investment.ts b/packages/cdk-core/verticals/investment.ts index 7a3bb9d3..30158900 100644 --- a/packages/cdk-core/verticals/investment.ts +++ b/packages/cdk-core/verticals/investment.ts @@ -1,5 +1,8 @@ import type {MaybePromise} from '@usevenice/util' -import {z} from '@usevenice/util' +import {objectEntries, z} from '@usevenice/util' +// This is unfortunately quite duplicated... +// Guess it means accounting router also belongs in the engine backend... +import {R} from '@usevenice/util' import type {IntegrationSchemas, IntHelpers} from '../integration.types' import type { @@ -7,7 +10,11 @@ import type { Pagination, VerticalRouterOpts, } from './new-mapper' -import {paginatedOutput, proxyListRemote, zPaginationParams} from './new-mapper' +import { + paginatedOutput, + proxyListRemoteRedux, + zPaginationParams, +} from './new-mapper' export const zInvestment = { account: z.object({ @@ -50,36 +57,21 @@ export interface InvestmentMethods< ) => MaybePromise } -// This is unfortunately quite duplicated... -// Guess it means accounting router also belongs in the engine backend... - export function createInvestmentRouter(opts: VerticalRouterOpts) { - // We cannot use a single trpc procedure because neither openAPI nor trpc - // supports switching output shape that depends on input - return opts.trpc.router({ - listAccounts: opts.remoteProcedure - .meta({ - openapi: {method: 'GET', path: '/investment/accounts'}, - response: {vertical: 'investment', entity: 'account', type: 'list'}, - }) - .input(zPaginationParams.nullish()) - .output(paginatedOutput(zInvestment.account)) - .query(proxyListRemote), - listHoldings: opts.remoteProcedure - .meta({ - openapi: {method: 'GET', path: '/investment/holdings'}, - response: {vertical: 'investment', entity: 'holding', type: 'list'}, - }) - .input(zPaginationParams.nullish()) - .output(paginatedOutput(zInvestment.holding)) - .query(proxyListRemote), - listTransactions: opts.remoteProcedure - .meta({ - openapi: {method: 'GET', path: '/investment/transactions'}, - response: {vertical: 'investment', entity: 'transaction', type: 'list'}, - }) - .input(zPaginationParams.nullish()) - .output(paginatedOutput(zInvestment.transaction)) - .query(proxyListRemote), - }) + const vertical = 'investment' + + return opts.trpc.router( + R.mapToObj(objectEntries(zInvestment), ([entityName, v]) => [ + `${vertical}_${entityName}_list`, + opts.remoteProcedure + .meta({openapi: {method: 'GET', path: `/${vertical}/${entityName}`}}) + .input(zPaginationParams.nullish()) + .output(paginatedOutput(v)) + .query(async ({input, ctx}) => + proxyListRemoteRedux({input, ctx, meta: {entityName, vertical}}), + ), + ]), + // We cannot use a single trpc procedure because neither openAPI nor trpc + // supports switching output shape that depends on input + ) } diff --git a/packages/cdk-core/verticals/new-mapper.ts b/packages/cdk-core/verticals/new-mapper.ts index 7cc5f95c..232d5e7a 100644 --- a/packages/cdk-core/verticals/new-mapper.ts +++ b/packages/cdk-core/verticals/new-mapper.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import type { AnyProcedure, @@ -18,7 +17,6 @@ import {z} from '@usevenice/util' import type { remoteProcedure, RemoteProcedureContext, - RouterMeta, trpc, } from '../../engine-backend/router/_base' @@ -37,19 +35,21 @@ export interface VerticalRouterOpts { remoteProcedure: typeof remoteProcedure } -export async function proxyListRemote(opts: { +export async function proxyListRemoteRedux({ + input, + ctx, + meta: {entityName, vertical}, +}: { input: unknown ctx: RemoteProcedureContext + meta: {vertical: string; entityName: string} }) { - const meta = (opts as any).meta as RouterMeta - - const {input, ctx} = opts const instance = ctx.remote.provider.newInstance?.({ config: ctx.remote.config, settings: ctx.remote.settings, }) const implementation = ( - ctx.remote.provider.verticals?.[meta.response?.vertical!] as any + ctx.remote.provider.verticals?.[vertical as never] as any )?.list as Function if (typeof implementation !== 'function') { throw new TRPCError({ @@ -58,22 +58,23 @@ export async function proxyListRemote(opts: { }) } - const res = await implementation(instance, meta.response?.entity, input) + const res: PaginatedOutput = await implementation( + instance, + entityName, + input, + ) - if (meta.response?.type === 'list') { - const mapper = ( - ctx.remote.provider.streams?.[meta.response?.vertical] as any - )[meta.response?.entity] as (entity: unknown, settings: unknown) => any + const mapper = (ctx.remote.provider.streams?.[vertical as never] as any)[ + entityName + ] as (entity: unknown, settings: unknown) => any - return { - ...res, - items: (res as PaginatedOutput).items.map((item) => ({ - ...mapper(item, ctx.remote.settings), - _original: item, - })), - } + return { + ...res, + items: res.items.map((item) => ({ + ...mapper(item, ctx.remote.settings), + _original: item, + })), } - return res } export const zPaginationParams = z.object({