graphql-zeus
graphql-zeus copied to clipboard
Node Client Generator fails to compile
Hi
Great library. I am using graphql-zues to generate graphql string and use apollo client to make http request. Now i want to use zeus Chain method for making api calls.
Client code generated with command zeus http://localhost:8081/v1/graphql ./libs/zeus/src/lib/ --node has compilation error
i think issue is with my installation need help.
Generate Code
/* eslint-disable */
import { AllTypesProps, ReturnTypes, Ops } from './const';
import fetch, { Response } from 'node-fetch';
import WebSocket from 'ws';
export const HOST = "http://localhost:8081/v1/graphql"
export const HEADERS = {}
export const apiSubscription = (options: chainOptions) => (query: string) => {
try {
const queryString = options[0] + '?query=' + encodeURIComponent(query);
const wsString = queryString.replace('http', 'ws');
const host = (options.length > 1 && options[1]?.websocket?.[0]) || wsString;
const webSocketOptions = options[1]?.websocket || [host];
const ws = new WebSocket(...webSocketOptions);
return {
ws,
on: (e: (args: any) => void) => {
ws.onmessage = (event: any) => {
if (event.data) {
const parsed = JSON.parse(event.data);
const data = parsed.data;
return e(data);
}
};
},
off: (e: (args: any) => void) => {
ws.onclose = e;
},
error: (e: (args: any) => void) => {
ws.onerror = e;
},
open: (e: () => void) => {
ws.onopen = e;
},
};
} catch {
throw new Error('No websockets implemented');
}
};
const handleFetchResponse = (response: Response): Promise<GraphQLResponse> => {
if (!response.ok) {
return new Promise((_, reject) => {
response
.text()
.then((text) => {
try {
reject(JSON.parse(text));
} catch (err) {
reject(text);
}
})
.catch(reject);
});
}
return response.json() as Promise<GraphQLResponse>;
};
export const apiFetch =
(options: fetchOptions) =>
(query: string, variables: Record<string, unknown> = {}) => {
const fetchOptions = options[1] || {};
if (fetchOptions.method && fetchOptions.method === 'GET') {
return fetch(`${options[0]}?query=${encodeURIComponent(query)}`, fetchOptions)
.then(handleFetchResponse)
.then((response: GraphQLResponse) => {
if (response.errors) {
throw new GraphQLError(response);
}
return response.data;
});
}
return fetch(`${options[0]}`, {
body: JSON.stringify({ query, variables }),
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
...fetchOptions,
})
.then(handleFetchResponse)
.then((response: GraphQLResponse) => {
if (response.errors) {
throw new GraphQLError(response);
}
return response.data;
});
};
export const InternalsBuildQuery = ({
ops,
props,
returns,
options,
scalars,
}: {
props: AllTypesPropsType;
returns: ReturnTypesType;
ops: Operations;
options?: OperationOptions;
scalars?: ScalarDefinition;
}) => {
const ibb = (
k: string,
o: InputValueType | VType,
p = '',
root = true,
vars: Array<{ name: string; graphQLType: string }> = [],
): string => {
const keyForPath = purifyGraphQLKey(k);
const newPath = [p, keyForPath].join(SEPARATOR);
if (!o) {
return '';
}
if (typeof o === 'boolean' || typeof o === 'number') {
return k;
}
if (typeof o === 'string') {
return `${k} ${o}`;
}
if (Array.isArray(o)) {
const args = InternalArgsBuilt({
props,
returns,
ops,
scalars,
vars,
})(o[0], newPath);
return `${ibb(args ? `${k}(${args})` : k, o[1], p, false, vars)}`;
}
if (k === '__alias') {
return Object.entries(o)
.map(([alias, objectUnderAlias]) => {
if (typeof objectUnderAlias !== 'object' || Array.isArray(objectUnderAlias)) {
throw new Error(
'Invalid alias it should be __alias:{ YOUR_ALIAS_NAME: { OPERATION_NAME: { ...selectors }}}',
);
}
const operationName = Object.keys(objectUnderAlias)[0];
const operation = objectUnderAlias[operationName];
return ibb(`${alias}:${operationName}`, operation, p, false, vars);
})
.join('\n');
}
const hasOperationName = root && options?.operationName ? ' ' + options.operationName : '';
const keyForDirectives = o.__directives ?? '';
const query = `{${Object.entries(o)
.filter(([k]) => k !== '__directives')
.map((e) => ibb(...e, [p, `field<>${keyForPath}`].join(SEPARATOR), false, vars))
.join('\n')}}`;
if (!root) {
return `${k} ${keyForDirectives}${hasOperationName} ${query}`;
}
const varsString = vars.map((v) => `${v.name}: ${v.graphQLType}`).join(', ');
return `${k} ${keyForDirectives}${hasOperationName}${varsString ? `(${varsString})` : ''} ${query}`;
};
return ibb;
};
export const Thunder =
(fn: FetchFunction) =>
<O extends keyof typeof Ops, SCLR extends ScalarDefinition, R extends keyof ValueTypes = GenericOperation<O>>(
operation: O,
graphqlOptions?: ThunderGraphQLOptions<SCLR>,
) =>
<Z extends ValueTypes[R]>(o: Z | ValueTypes[R], ops?: OperationOptions & { variables?: Record<string, unknown> }) =>
fn(
Zeus(operation, o, {
operationOptions: ops,
scalars: graphqlOptions?.scalars,
}),
ops?.variables,
).then((data) => {
if (graphqlOptions?.scalars) {
return decodeScalarsInResponse({
response: data,
initialOp: operation,
initialZeusQuery: o as VType,
returns: ReturnTypes,
scalars: graphqlOptions.scalars,
ops: Ops,
});
}
return data;
}) as Promise<InputType<GraphQLTypes[R], Z, SCLR>>;
export const Chain = (...options: chainOptions) => Thunder(apiFetch(options));
export const SubscriptionThunder =
(fn: SubscriptionFunction) =>
<O extends keyof typeof Ops, SCLR extends ScalarDefinition, R extends keyof ValueTypes = GenericOperation<O>>(
operation: O,
graphqlOptions?: ThunderGraphQLOptions<SCLR>,
) =>
<Z extends ValueTypes[R]>(o: Z | ValueTypes[R], ops?: OperationOptions & { variables?: ExtractVariables<Z> }) => {
const returnedFunction = fn(
Zeus(operation, o, {
operationOptions: ops,
scalars: graphqlOptions?.scalars,
}),
) as SubscriptionToGraphQL<Z, GraphQLTypes[R], SCLR>;
if (returnedFunction?.on && graphqlOptions?.scalars) {
const wrapped = returnedFunction.on;
returnedFunction.on = (fnToCall: (args: InputType<GraphQLTypes[R], Z, SCLR>) => void) =>
wrapped((data: InputType<GraphQLTypes[R], Z, SCLR>) => {
if (graphqlOptions?.scalars) {
return fnToCall(
decodeScalarsInResponse({
response: data,
initialOp: operation,
initialZeusQuery: o as VType,
returns: ReturnTypes,
scalars: graphqlOptions.scalars,
ops: Ops,
}),
);
}
return fnToCall(data);
});
}
return returnedFunction;
};
export const Subscription = (...options: chainOptions) => SubscriptionThunder(apiSubscription(options));
export const Zeus = <
Z extends ValueTypes[R],
O extends keyof typeof Ops,
R extends keyof ValueTypes = GenericOperation<O>,
>(
operation: O,
o: Z | ValueTypes[R],
ops?: {
operationOptions?: OperationOptions;
scalars?: ScalarDefinition;
},
) =>
InternalsBuildQuery({
props: AllTypesProps,
returns: ReturnTypes,
ops: Ops,
options: ops?.operationOptions,
scalars: ops?.scalars,
})(operation, o as VType);
export const ZeusSelect = <T>() => ((t: unknown) => t) as SelectionFunction<T>;
export const Selector = <T extends keyof ValueTypes>(key: T) => key && ZeusSelect<ValueTypes[T]>();
export const TypeFromSelector = <T extends keyof ValueTypes>(key: T) => key && ZeusSelect<ValueTypes[T]>();
export const Gql = Chain(HOST, {
headers: {
'Content-Type': 'application/json',
...HEADERS,
},
});
export const ZeusScalars = ZeusSelect<ScalarCoders>();
compile time error
TS2339: Property 'method' does not exist on type 'unknown'.
62 | (query: string, variables: Record<string, unknown> = {}) => {
63 | const fetchOptions = options[1] || {};
> 64 | if (fetchOptions.method && fetchOptions.method === 'GET') {
| ^^^^^^
65 | return fetch(`${options[0]}?query=${encodeURIComponent(query)}`, fetchOptions)
66 | .then(handleFetchResponse)
67 | .then((response: GraphQLResponse) => {
ERROR in ./libs/zeus/src/lib/zeus/index.ts:64:45
TS2339: Property 'method' does not exist on type 'unknown'.
62 | (query: string, variables: Record<string, unknown> = {}) => {
63 | const fetchOptions = options[1] || {};
> 64 | if (fetchOptions.method && fetchOptions.method === 'GET') {
| ^^^^^^
65 | return fetch(`${options[0]}?query=${encodeURIComponent(query)}`, fetchOptions)
66 | .then(handleFetchResponse)
67 | .then((response: GraphQLResponse) => {
ERROR in ./libs/zeus/src/lib/zeus/index.ts:80:7
TS2698: Spread types may only be created from object types.
78 | 'Content-Type': 'application/json',
79 | },
> 80 | ...fetchOptions,
| ^^^^^^^^^^^^^^^
81 | })
82 | .then(handleFetchResponse)
83 | .then((response: GraphQLResponse) => {
ERROR in ./libs/zeus/src/lib/zeus/index.ts:252:3
TS2345: Argument of type '[string, { headers: { 'Content-Type': string; }; }]' is not assignable to parameter of type 'chainOptions'.
Type '[string, { headers: { 'Content-Type': string; }; }]' is not assignable to type '[unknown, { websocket?: [address: string | URL, protocols?: string | string[], options?: ClientOptions | ClientRequestArgs]; }]'.
Type at position 1 in source is not compatible with type at position 1 in target.
Type '{ headers: { 'Content-Type': string; }; }' is not assignable to type '{ websocket?: [address: string | URL, protocols?: string | string[], options?: ClientOptions | ClientRequestArgs]; }'.
Object literal may only specify known properties, and 'headers' does not exist in type '{ websocket?: [address: string | URL, protocols?: string | string[], options?: ClientOptions | ClientRequestArgs]; }'.
250 | export const TypeFromSelector = <T extends keyof ValueTypes>(key: T) => key && ZeusSelect<ValueTypes[T]>();
251 | export const Gql = Chain(HOST, {
> 252 | headers: {
| ^^^^^^^^^^
> 253 | 'Content-Type': 'application/json',
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 254 | ...HEADERS,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 255 | },
| ^^^^
256 | });
257 |
258 | export const ZeusScalars = ZeusSelect<ScalarCoders>();```
Node version - v18.13.0
Typescript version - 4.8.4
graphql-zeus version - 5.2.4
I'm seeing this as well but only when building a node project with docker.