Skip to content

Commit

Permalink
feat: support optional result props (#4)
Browse files Browse the repository at this point in the history
* feat: support optional result props

* fix: update return types

* refactor: reorganize files

* fix: process wait requests
  • Loading branch information
trs committed Sep 26, 2023
1 parent 24450d8 commit b168916
Show file tree
Hide file tree
Showing 49 changed files with 1,745 additions and 1,434 deletions.
24 changes: 0 additions & 24 deletions src/chargebee-client.service.ts

This file was deleted.

91 changes: 91 additions & 0 deletions src/chargebee-resource.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import type { ChargeBee } from "chargebee-typescript";

import type { RequestWrapper } from "chargebee-typescript/lib/request_wrapper";
import type { ListResult } from "chargebee-typescript/lib/list_result";
import type { Result } from "chargebee-typescript/lib/result";

import type {
ResourceResult,
ResultMethodName,
ProcessWaitMethodName,
ListResultMethodName,
ResolveResultReturn,
} from "./chargebee-resource.types";

export class ChargebeeResource {
constructor(protected readonly chargebee: ChargeBee) {}

protected request<
TResourceName extends keyof ChargeBee,
TMethodName extends keyof ChargeBee[TResourceName],
TReturning extends ResourceResult,
>(
resourceName: TResourceName,
methodName: TMethodName extends
| ResultMethodName<TResourceName, TMethodName>
| ProcessWaitMethodName<TResourceName, TMethodName>
? TMethodName
: never,
returning: TReturning,
) {
type MethodDefinition = ChargeBee[TResourceName][TMethodName] extends (
...args: unknown[]
) => RequestWrapper<Result>
? ChargeBee[TResourceName][TMethodName]
: never;

const functionDef = this.chargebee[resourceName][
methodName
] as MethodDefinition;

return async (...args: Parameters<MethodDefinition>) => {
return functionDef(...args)
.request()
.then(this.resolveResult(returning));
};
}

protected listRequest<
TResourceName extends keyof ChargeBee,
TMethodName extends keyof ChargeBee[TResourceName],
TReturning extends ResourceResult,
>(
resourceName: TResourceName,
methodName: TMethodName extends ListResultMethodName<
TResourceName,
TMethodName
>
? TMethodName
: never,
returning: TReturning,
) {
type MethodDefinition = ChargeBee[TResourceName][TMethodName] extends (
...args: unknown[]
) => RequestWrapper<ListResult>
? ChargeBee[TResourceName][TMethodName]
: never;

const functionDef = this.chargebee[resourceName][
methodName
] as MethodDefinition;

return async (...args: Parameters<MethodDefinition>) => {
return functionDef(...args)
.request()
.then((listResult) => {
const items = listResult.list.map(this.resolveResult(returning));
return {
items,
nextOffset: listResult.next_offset as string | undefined,
};
});
};
}

private resolveResult =
<TReturning extends ResourceResult>(returning: TReturning) =>
(result: Result) =>
Object.fromEntries(
Object.keys(returning).map((key) => [key, result[key as keyof Result]]),
) as ResolveResultReturn<TReturning>;
}
49 changes: 49 additions & 0 deletions src/chargebee-resource.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { ChargeBee } from "chargebee-typescript";

import type { RequestWrapper } from "chargebee-typescript/lib/request_wrapper";
import type { ListResult } from "chargebee-typescript/lib/list_result";
import type { Result } from "chargebee-typescript/lib/result";
import type { ProcessWait } from "chargebee-typescript/lib/process_wait";

export type ResultMethodName<
TResource extends keyof ChargeBee,
TMethod extends keyof ChargeBee[TResource],
> = ChargeBee[TResource][TMethod] extends (
...args: unknown[]
) => RequestWrapper<infer R>
? R extends Result
? TMethod
: "Method must return a RequestWrapper<Result>"
: never;

export type ListResultMethodName<
TResource extends keyof ChargeBee,
TMethod extends keyof ChargeBee[TResource],
> = ChargeBee[TResource][TMethod] extends (
...args: unknown[]
) => RequestWrapper<infer R>
? R extends ListResult
? TMethod
: "Method must return a RequestWrapper<ListResult>"
: never;

export type ProcessWaitMethodName<
TResource extends keyof ChargeBee,
TMethod extends keyof ChargeBee[TResource],
> = ChargeBee[TResource][TMethod] extends (...args: unknown[]) => ProcessWait
? TMethod
: "Method must return a ProcessWait";

export type ResourceResult = {
[K in keyof Result]?: {
optional: boolean;
};
};

export type ResolveResultReturn<T extends ResourceResult> = {
[K in keyof T]: K extends keyof Result
? T[K] extends { optional: true }
? Result[K] | undefined
: Result[K]
: never;
};
3 changes: 1 addition & 2 deletions src/chargebee.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Global, Module } from "@nestjs/common";

import { ConfigurableModuleClass } from "./chargebee.module-definition";
import { ChargebeeClientService } from "./chargebee-client.service";
import { ChargebeeService } from "./chargebee.service";

@Global()
@Module({
providers: [ChargebeeClientService, ChargebeeService],
providers: [ChargebeeService],
exports: [ChargebeeService],
})
export class ChargebeeModule extends ConfigurableModuleClass {}
24 changes: 20 additions & 4 deletions src/chargebee.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import { Injectable } from "@nestjs/common";
import { Inject, Injectable, Optional } from "@nestjs/common";
import { ChargeBee } from "chargebee-typescript";

import { ChargebeeClientService } from "./chargebee-client.service";
import { ChargebeeModuleOptions } from "./chargebee.interface";
import { CHARGEBEE_MODULE_OPTIONS_TOKEN } from "./chargebee.module-definition";
import { ChargebeeResourceWrapper } from "./chargebee-resource-wrapper.class";

@Injectable()
export class ChargebeeService extends ChargebeeResourceWrapper {
constructor(chargebeeClient: ChargebeeClientService) {
super(chargebeeClient.client);
constructor(
@Inject(CHARGEBEE_MODULE_OPTIONS_TOKEN)
options: ChargebeeModuleOptions,
@Optional()
client = configureChargebee(options),
) {
super(client);
}
}

function configureChargebee(options: ChargebeeModuleOptions) {
const client = new ChargeBee();
client.configure({
site: options.site,
api_key: options.apiKey,
});
return client;
}
Loading

0 comments on commit b168916

Please sign in to comment.