Skip to content

Commit

Permalink
refactor: flatten destruction data from request
Browse files Browse the repository at this point in the history
  • Loading branch information
askuzminov committed Jan 19, 2021
1 parent 10d8575 commit a1b75a6
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 14 deletions.
23 changes: 23 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,17 @@ if (user.success) {
res.error.httpStatus // number?
);
}

// Destruction example for flatten style
const { data: me, error } = await grpc(whisk_api_user_v2_UserAPI_GetMe);

if (me) {
console.log(me.user?.email);
}

if (error) {
console.log(error.message);
}
```

#### Cancel requests
Expand Down Expand Up @@ -443,6 +454,18 @@ const item = await unwrap(
/* ... */
}
);

// throw as usual promise
const err = e => {
throw e;
};

try {
const request = grpc(whisk_api_user_v2_UserAPI_GetMe);
const email = await unwrap(request, data => data.user?.email, err);
} catch (e) {
console.error(e);
}
```
## Messages and typings
Expand Down
6 changes: 3 additions & 3 deletions src/http/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { send } from './devtool';
import { maskWrap } from './mask';
import { Chunk, ChunkType, chunkParse } from './parser';
import { StatusCode, fromHttpStatus } from './status';
import { Cancel, ConfigGRPC, GError, GRPC, GSuccess, LocalGRPC } from './types';
import { Cancel, ConfigGRPC, GError, GOutput, GRPC, LocalGRPC } from './types';
import { GRPC_MESSAGE, GRPC_STATUS, encodeRequest, safeJSON, toInt8 } from './utils';

export const grpcCancel = (): Cancel => {
Expand Down Expand Up @@ -38,7 +38,7 @@ export const grpcHTTP = ({
field: Service<T, K>,
values = {} as ServiceRequest<Service<T, K>>,
{ cancel, onDownload, onUpload, mask, timeout }: LocalGRPC<T> = {}
): Promise<GSuccess<ServiceResponse<Service<T, K>>> | GError> => {
): Promise<GOutput<ServiceResponse<Service<T, K>>>> => {
if (isString(cancel) && isFunction(cancels[cancel])) {
cancels[cancel]();
delete cancels[cancel];
Expand Down Expand Up @@ -69,7 +69,7 @@ export const grpcHTTP = ({
let sendData: FieldGet<T> = values;

// eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
return new Promise<GSuccess<ServiceResponse<Service<T, K>>> | GError>(async callback => {
return new Promise<GOutput<ServiceResponse<Service<T, K>>>>(async callback => {
const time = timeout ?? timeoutConfig;

if (isNumber(time) && time > 0) {
Expand Down
26 changes: 23 additions & 3 deletions src/http/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ import { Field, FieldGet, Service, ServiceRequest, ServiceResponse } from '../ty
export type GSuccess<T> = {
success: true;
data: T;
error?: {
data?: unknown;
message?: string;
httpStatus?: number;
grpcCode?: number;
};
};

export type GError = {
success: false;
data?: undefined;
error: {
data?: unknown;
message?: string;
Expand All @@ -19,6 +26,19 @@ export type GError = {
};
};

export type GResult<T> = {
success: never;
data?: T;
error?: {
data?: unknown;
message?: string;
httpStatus?: number;
grpcCode?: number;
};
};

export type GOutput<T> = GSuccess<T> | GError | GResult<T>;

type LoggerFn = (message?: any, ...optionalParams: any[]) => void;

export interface ConfigGRPC {
Expand All @@ -33,7 +53,7 @@ export interface ConfigGRPC {
info: LoggerFn;
};
transformRequest?<T>(params: { xhr: XMLHttpRequest; data: T }): T | void | Promise<T | void>;
transformResponse?<T>(params: { data: GSuccess<T> | GError }): GSuccess<T> | GError | Promise<GSuccess<T> | GError>;
transformResponse?<T>(params: { data: GOutput<T> }): GOutput<T> | Promise<GOutput<T>>;
}

export interface Cancel {
Expand Down Expand Up @@ -63,13 +83,13 @@ export type GRPC = <T extends Field, K extends Field>(
...[field, values, options]: {} extends ServiceRequest<Service<T, K>>
? [Service<T, K>, ServiceRequest<Service<T, K>>?, LocalGRPC<T>?]
: [Service<T, K>, ServiceRequest<Service<T, K>>, LocalGRPC<T>?]
) => Promise<GSuccess<ServiceResponse<Service<T, K>>> | GError>;
) => Promise<GOutput<ServiceResponse<Service<T, K>>>>;

export type GRPCDeep = <T extends Field, K extends Field>(
...[field, values, options]: {} extends ServiceRequestDeep<Service<T, K>>
? [Service<T, K>, ServiceRequestDeep<Service<T, K>>?, LocalGRPC<T>?]
: [Service<T, K>, ServiceRequestDeep<Service<T, K>>, LocalGRPC<T>?]
) => Promise<GSuccess<ServiceResponseDeep<Service<DeepReadonly<T>, DeepReadonly<K>>>> | GError>;
) => Promise<GOutput<ServiceResponseDeep<Service<DeepReadonly<T>, DeepReadonly<K>>>>>;

// ...[method, params]: T[P]['request'] extends undefined ? [P] : [P, T[P]['request']]

Expand Down
10 changes: 5 additions & 5 deletions src/http/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isArray, isArrayBuffer, isDate, isObject, isPresent } from '@whisklabs/typeguards';

import { GError, GSuccess } from './types';
import { GError, GOutput } from './types';

export const HEADER_SIZE = 5;
export const GRPC_STATUS = 'grpc-status';
Expand Down Expand Up @@ -101,21 +101,21 @@ export function cloneInternal(source: unknown, objs: unknown[]): unknown {
}

export function unwrap<K, S, E>(
result: GError | GSuccess<K> | Promise<GError | GSuccess<K>>,
result: GOutput<K> | Promise<GOutput<K>>,
onSuccess: (data: K) => S | Promise<S>,
onError: ((error: GError['error']) => E | Promise<E>) | undefined
): Promise<S | E>;
export function unwrap<K, S>(
result: GError | GSuccess<K> | Promise<GError | GSuccess<K>>,
result: GOutput<K> | Promise<GOutput<K>>,
onSuccess: (data: K) => S | Promise<S>
): Promise<S | undefined>;
export function unwrap<K, E>(
result: GError | GSuccess<K> | Promise<GError | GSuccess<K>>,
result: GOutput<K> | Promise<GOutput<K>>,
onSuccess: undefined,
onError: ((error: GError['error']) => E | Promise<E>) | undefined
): Promise<E | undefined>;
export async function unwrap<K, S, E>(
result: GError | GSuccess<K> | Promise<GError | GSuccess<K>>,
result: GOutput<K> | Promise<GOutput<K>>,
onSuccess: ((data: K) => S | Promise<S> | undefined) | undefined,
onError?: (error: GError['error']) => E | Promise<E>
): Promise<S | E | undefined> {
Expand Down
11 changes: 8 additions & 3 deletions tests/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ const TOKEN = '123';
}
);

const { data, error } = res;

console.log(data?.user?.email);
console.log(error?.httpStatus);

if (res.success) {
console.log(res.data.user?.hasPassword);
} else {
Expand All @@ -150,7 +155,7 @@ const TOKEN = '123';

const userEmail = await unwrap(
grpc(whisk_api_user_v2_UserAPI_UpdateSettings, { id: 'abc' }),
data => data.user?.email,
d => d.user?.email,
e => {
console.log(e);
return 1000;
Expand All @@ -161,15 +166,15 @@ const TOKEN = '123';

const userEmailStrict = await unwrap(
grpc(whisk_api_user_v2_UserAPI_UpdateSettings, { id: 'abc' }),
data => data.user?.email ?? 'Default',
d => d.user?.email ?? 'Default',
() => 'Nobody'
);

console.log(userEmailStrict);

const userEmailShort = await unwrap(
grpc(whisk_api_user_v2_UserAPI_UpdateSettings, { id: 'abc' }),
data => data.user?.email ?? 'User'
d => d.user?.email ?? 'User'
);

console.log(userEmailShort);
Expand Down

0 comments on commit a1b75a6

Please sign in to comment.