Skip to content

Instantly share code, notes, and snippets.

@freddi301
Last active January 7, 2019 22:43
Show Gist options
  • Select an option

  • Save freddi301/bfa17b28621032ed493793cd30d4b0da to your computer and use it in GitHub Desktop.

Select an option

Save freddi301/bfa17b28621032ed493793cd30d4b0da to your computer and use it in GitHub Desktop.
grapql in typescript
type DataTypeUnion = ObjectType<any> | ArrayType<any> | PrimitiveTypeUnion;
type PrimitiveTypeUnion = typeof string | typeof number | typeof boolean;
interface QueryType<
Params extends { [key: string]: PrimitiveTypeUnion },
T extends DataTypeUnion
> {
kind: "query";
params: Params;
result: T;
selector: [{ [K in keyof Params]: Params["type"] }, T["selector"][0]];
}
function query<
P extends { [key: string]: PrimitiveTypeUnion },
T extends DataTypeUnion
>(params: P, result: T): QueryType<P, T> {
return {
kind: "query",
params,
result,
selector: null as any,
};
}
interface ObjectType<
O extends Record<string, QueryType<any, any> | DataTypeUnion>
> {
kind: "object";
map: O;
selector: [
(h: ObjectSelectorHelpers<O>) => Record<string, FieldSelector<O, keyof O>>
];
}
function object<O extends Record<string, QueryType<any, any> | DataTypeUnion>>(
map: O,
): ObjectType<O> {
return {
kind: "object",
map,
selector: null as any,
};
}
interface FieldSelector<
O extends Record<string, QueryType<any, any> | DataTypeUnion>,
K extends keyof O
> {
key: K;
selector: O[K]["selector"];
}
type ObjectSelectorHelpers<
O extends Record<string, QueryType<any, any> | DataTypeUnion>
> = {
[K in keyof O]: O[K]["selector"] extends []
? FieldSelector<O, K>
: (...args: O[K]["selector"]) => FieldSelector<O, K>
};
interface ArrayType<T extends DataTypeUnion> {
kind: "array";
item: T;
selector: T["selector"];
}
function array<T extends DataTypeUnion>(item: T): ArrayType<T> {
return {
kind: "array",
item,
selector: item.selector,
};
}
interface PrimitiveType<T, Kind extends string> {
kind: Kind;
selector: [];
type: T;
}
function makePrimitiveType<T, Kind extends string>(
kind: Kind,
): PrimitiveType<T, Kind> {
return {
kind,
selector: [],
type: null as any,
};
}
const string = makePrimitiveType<string, "string">("string");
const number = makePrimitiveType<number, "number">("number");
const boolean = makePrimitiveType<boolean, "boolean">("boolean");
const Person = object({
name: string,
age: number,
});
const u: typeof Person.selector = [
({ name, age }) => ({
x: name,
age,
}),
];
const School = object({
teachers: array(Person),
kids: array(Person),
director: Person,
kid: query({ id: number }, Person),
});
const u2: typeof School.selector = [
({ director, teachers, kids, kid }) => ({
others: kids(({ name }) => ({ name })),
me: kid({ id: 42 }, ({ name, age }) => ({ name, power: age })),
devils: teachers(({ age }) => ({ ugliness: age })),
god: director(({ age }) => ({ universeAge: age })),
}),
];
// TODO: serialize selector
// TODO: deserialize selector
// TODO: validate
// TODO: create resolver
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment