Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Commit

Permalink
chore: refactor vdk to export from vdk2
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyxiao committed Apr 19, 2024
1 parent bfcaf1c commit 192747b
Show file tree
Hide file tree
Showing 14 changed files with 78 additions and 221 deletions.
10 changes: 5 additions & 5 deletions connectors/connector-qbo/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ export const qboServer = {
switch (type) {
case 'account': {
const res = await qbo.getAll('Account').next()
return {hasNextPage: true, items: res.value?.entities ?? []}
return {has_next_page: true, items: res.value?.entities ?? []}
}
case 'expense': {
const res = await qbo.getAll('Purchase').next()
return {hasNextPage: true, items: res.value?.entities ?? []}
return {has_next_page: true, items: res.value?.entities ?? []}
}
case 'vendor': {
const res = await qbo.getAll('Vendor').next()
return {hasNextPage: true, items: res.value?.entities ?? []}
return {has_next_page: true, items: res.value?.entities ?? []}
}
default:
throw new Error(`Unknown type: ${type}`)
Expand All @@ -90,7 +90,7 @@ export const qboServer = {
switch (type) {
case 'account': {
const res = await qbo.getAll('Account').next()
return {hasNextPage: true, items: res.value?.entities ?? []}
return {has_next_page: true, items: res.value?.entities ?? []}
}
case 'transaction': {
async function* iterateEntities() {
Expand All @@ -110,7 +110,7 @@ export const qboServer = {
}
}
const res = await iterateEntities().next()
return {hasNextPage: true, items: res.value ?? []}
return {has_next_page: true, items: res.value ?? []}
}
default:
throw new Error(`Unknown type: ${type}`)
Expand Down
9 changes: 5 additions & 4 deletions kits/vdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"}
export * from './new-mapper'
// codegen:end
// // codegen:start {preset: barrel, include: "./{*.{ts,tsx},*/index.{ts,tsx}}", exclude: "./**/*.{d,spec,test,fixture,gen,node}.{ts,tsx}"}
// export * from './new-mapper'
// // codegen:end

export * from '@openint/zod'
// export * from '@openint/zod'
export * from '@openint/vdk2'
53 changes: 0 additions & 53 deletions kits/vdk/new-mapper.spec.ts

This file was deleted.

1 change: 1 addition & 0 deletions kits/vdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"description": "Vertical Development Kit",
"dependencies": {
"@openint/types": "workspace:*",
"@openint/vdk2": "workspace:*",
"@openint/zod": "workspace:*",
"@trpc/server": "10.40.0",
"remeda": "1.6.1"
Expand Down
101 changes: 1 addition & 100 deletions kits/vdk/new-mapper.ts → new-pattern/vdk2/deprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ import type {
MaybePromise,
} from '@trpc/server'
import {TRPCError} from '@trpc/server'
import * as R from 'remeda'
import type {PathsOf, StrictObj} from '@openint/types'
import {z} from '@openint/zod'
// FIXME: This is explicitly bypassing the package system because we have a circular
// dependency here which is not great but ....
import type {
remoteProcedure,
RemoteProcedureContext,
RouterMeta,
trpc,
} from '../../packages/engine-backend/router/_base'

export {RouterMeta, inferProcedureInput, inferProcedureOutput, StrictObj}
import type {PaginatedOutput} from './pagination'

export type RouterMap<TRouter extends AnyRouter, TOpts = {}> = {
[k in keyof TRouter as TRouter[k] extends AnyProcedure
Expand Down Expand Up @@ -116,97 +111,3 @@ export async function proxyListRemoteRedux({
})),
}
}

export const zPaginationParams = z.object({
limit: z.number().optional(),
offset: z.number().optional(),
})
export type Pagination = z.infer<typeof zPaginationParams>

export type PaginatedOutput<T extends {}> = z.infer<
ReturnType<typeof paginatedOutput<z.ZodObject<any, any, any, T>>>
>
export function paginatedOutput<ItemType extends z.AnyZodObject>(
itemSchema: ItemType,
) {
return z.object({
hasNextPage: z.boolean(),
items: z.array(itemSchema.extend({_original: z.unknown()})),
})
}

export const literal = <T>(literal: T) => ({literal})

export function mapper<
ZInputSchema extends z.ZodTypeAny,
ZOutputSchema extends z.ZodTypeAny,
TOut extends z.infer<ZOutputSchema> = z.infer<ZOutputSchema>,
TIn extends z.infer<ZInputSchema> = z.infer<ZInputSchema>,
>(
zInput: ZInputSchema,
zOutput: ZOutputSchema,
mapping: {
[k in keyof TOut]: // | ExtractKeyOfValueType<TIn, TOut[k]> // | Getter<ExtractKeyOfValueType<TIn, TOut[k]>> // | TOut[k] // Constant
| PathsOf<TIn> // Getter for the keypaths
| ReturnType<typeof literal<TOut[k]>> // literal value
| ((ext: TIn) => TOut[k]) // Function that can do whatever
},
) {
const meta = {
_in: undefined as TIn,
_out: undefined as TOut,
inputSchema: zInput,
outputSchema: zOutput,
mapping,
}
const apply = (input: TIn): TOut => applyMapper(meta, input)
apply._in = undefined as TIn
apply._out = undefined as TOut
apply.inputSchema = zInput
apply.outputSchema = zOutput
apply.mapping = mapping
return apply
}

export function applyMapper<
T extends Pick<
ReturnType<typeof mapper>,
'mapping' | '_in' | '_out' | 'inputSchema' | 'outputSchema'
>,
>(mapper: T, input: T['_in']): T['_out'] {
// This can probably be extracted into its own function without needint TIn and TOut even
return R.mapValues(mapper.mapping, (m, key) => {
if (typeof m === 'function') {
return m(input)
} else if (typeof m === 'object' && 'literal' in m) {
return m.literal
} else if (typeof m === 'string') {
return getValueAtKeyPath(input, m)
}
throw new Error(`Invalid mapping ${m as unknown} at ${key as string}`)
})
}

/**
* https://dev.to/pffigueiredo/typescript-utility-keyof-nested-object-2pa3
* We could probbaly use R.pathOr... but it is too well-typed for our needs 🤣
*/
function getValueAtKeyPath(object: unknown, path: string) {
const keys = path.split('.')
let result = object
for (const key of keys) {
if (result == null) {
return result
}
if (typeof result !== 'object') {
console.error(
`Cannot get value at keypath ${path} from non-object`,
object,
)
// TODO: Make object log properly
throw new TypeError(`Cannot get value at keypath ${path} from non-object`)
}
result = (result as Record<string, unknown>)[key]
}
return result
}
10 changes: 9 additions & 1 deletion new-pattern/vdk2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,12 @@ export * from './errors'

// re-exporting utiltities

export {uniq, uniqBy, mapValues, mapKeys, pick} from 'remeda'
export {mapKeys, mapValues, pick, uniq, uniqBy} from 'remeda'

// TODO: Remove me
export {
RouterMap,
VerticalRouterOpts,
proxyCallRemote,
proxyListRemoteRedux,
} from './deprecated'
16 changes: 15 additions & 1 deletion new-pattern/vdk2/mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ import type {StrictObjDeep} from './type-utils/StrictObj'

export const literal = <T>(literal: T) => ({literal})

// type abc = PathsOf<
// StrictObjDeep<
// Required<{
// Contact?: {
// ContactId: string
// Account?: {
// accountId?: string
// }
// }
// }>
// >
// >

export function mapper<
ZInputSchema extends z.ZodTypeAny,
ZOutputSchema extends z.ZodTypeAny,
Expand All @@ -16,7 +29,8 @@ export function mapper<
mapping:
| {
[k in keyof TOut]: // | ExtractKeyOfValueType<TIn, TOut[k]> // | Getter<ExtractKeyOfValueType<TIn, TOut[k]>> // | TOut[k] // Constant
| PathsOf<StrictObjDeep<TIn>> // Getter for the keypaths
| PathsOf<StrictObjDeep<Required<TIn>>> // Getter for the keypaths
// A bit of a hack as PathsOf<StrictObjDeep> does not work with optional props...
| ReturnType<typeof literal<TOut[k]>> // literal value
| ((ext: TIn) => TOut[k]) // Function that can do whatever on a property level
}
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions verticals/vertical-banking/adapters/qbo-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {QBOSDK, QBOSDKTypes} from '@openint/connector-qbo'
import type {StrictObj} from '@openint/vdk'
import {mapper, z, zCast} from '@openint/vdk'
import type {VerticalBanking} from '../banking'
import {zBanking} from '../banking'
Expand All @@ -8,7 +7,7 @@ type QBO = QBOSDKTypes['oas']['components']['schemas']

const mappers = {
category: mapper(
zCast<StrictObj<QBO['Account']>>(),
zCast<QBO['Account']>(),
zBanking.category.extend({_raw: z.unknown().optional()}),
{
id: 'Id',
Expand Down
3 changes: 1 addition & 2 deletions verticals/vertical-banking/adapters/xero-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {Oas_accounting, XeroSDK} from 'connectors/connector-xero'
import type {StrictObj} from '@openint/vdk'
import {mapper, z, zCast} from '@openint/vdk'
import type {VerticalBanking} from '../banking'
import {zBanking} from '../banking'
Expand All @@ -8,7 +7,7 @@ type Xero = Oas_accounting['components']['schemas']

const mappers = {
category: mapper(
zCast<StrictObj<Xero['Account']>>(),
zCast<Xero['Account']>(),
zBanking.category.extend({_raw: z.unknown().optional()}),
{
id: 'AccountID',
Expand Down
Loading

0 comments on commit 192747b

Please sign in to comment.