Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reusable prisma connections #671

Merged
merged 10 commits into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/chatty-hotels-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@pothos/plugin-prisma': minor
---

Add builder.prismaObjectField(s) method to extend prisma objects and simplify defining circular
relationships
13 changes: 13 additions & 0 deletions .changeset/grumpy-bugs-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@pothos/core': minor
'@pothos/deno': minor
'@pothos/plugin-dataloader': minor
'@pothos/plugin-directives': minor
'@pothos/plugin-errors': minor
'@pothos/plugin-federation': minor
'@pothos/plugin-prisma': minor
'@pothos/plugin-prisma-utils': minor
'@pothos/plugin-relay': minor
---

Add support for nested lists
7 changes: 7 additions & 0 deletions .changeset/popular-pears-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@pothos/deno': minor
'@pothos/plugin-prisma': minor
'@pothos/plugin-relay': minor
---

Add initial support for reusable prisma connections
17 changes: 13 additions & 4 deletions packages/core/src/config-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import BuiltinScalarRef from './refs/builtin-scalar';
import FieldRef from './refs/field';
import InputTypeRef from './refs/input';
import InputFieldRef from './refs/input-field';
import InputListRef from './refs/input-list';
import ListRef from './refs/list';
import OutputTypeRef from './refs/output';
import type {
ConfigurableRef,
Expand All @@ -31,6 +33,7 @@ import type {
SchemaTypes,
TypeParam,
} from './types';
import { unwrapListParam } from './utils';

export default class ConfigStore<Types extends SchemaTypes> {
typeConfigs = new Map<string, PothosTypeConfig>();
Expand Down Expand Up @@ -140,7 +143,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
throw new Error(`FieldRef ${String(ref)} has already been added to config store`);
}

const typeRefOrName = Array.isArray(typeParam) ? typeParam[0] : typeParam;
const typeRefOrName = unwrapListParam(typeParam);
const argRefs = Object.keys(args).map((argName) => {
const argRef = args[argName];

Expand Down Expand Up @@ -259,8 +262,10 @@ export default class ConfigStore<Types extends SchemaTypes> {
config = this.typeConfigs.get(ref)!;
} else if (this.refsToName.has(ref)) {
config = this.typeConfigs.get(this.refsToName.get(ref)!)!;
} else if (ref instanceof ListRef || ref instanceof InputListRef) {
throw new TypeError(`Expected a base type but got a ${ref.kind} of ${String(ref.listType)}`);
} else {
throw new Error(`Ref ${String(ref)} has not been implemented`);
throw new TypeError(`Ref ${String(ref)} has not been implemented`);
}

if (kind && config.graphqlKind !== kind) {
Expand Down Expand Up @@ -310,8 +315,12 @@ export default class ConfigStore<Types extends SchemaTypes> {

getOutputTypeRef(ref: ConfigurableRef<Types> | string) {
if (ref instanceof BaseTypeRef) {
if (ref.kind === 'InputObject') {
throw new TypeError(`Expected ${ref.name} to be an output type but got ${ref.name}`);
if (ref.kind === 'InputObject' || ref.kind === 'InputList') {
throw new TypeError(`Expected ${ref.name} to be an output type but got ${ref.kind}`);
}

if (ref.kind === 'List') {
throw new TypeError(`Expected ${ref.name} to be a base type but got a ${ref.kind}`);
}

return ref as OutputRef;
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/fieldUtils/input.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import InputFieldRef from '../refs/input-field';
import InputListRef from '../refs/input-list';
import type {
ArgBuilder,
FieldRequiredness,
InputShapeFromTypeParam,
InputTypeParam,
NormalizeArgs,
} from '../types';
import { InputType, SchemaTypes } from '../types';
Expand Down Expand Up @@ -84,6 +86,15 @@ export default class InputFieldBuilder<
this.typename = typename;
}

listRef = <T extends InputTypeParam<Types>, Required extends boolean = true>(
type: T,
options?: { required?: Required },
): InputListRef<Types, InputShapeFromTypeParam<Types, T, Required>[]> =>
new InputListRef<Types, InputShapeFromTypeParam<Types, T, Required>[]>(
type,
options?.required ?? true,
);

argBuilder(): ArgBuilder<Types> {
const builder = this.field.bind(this as never) as InputFieldBuilder<Types, 'Arg'>['field'];

Expand Down
13 changes: 12 additions & 1 deletion packages/core/src/fieldUtils/root.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ArgBuilder, InputFieldMap, NormalizeArgs } from '../types';
import ListRef from '../refs/list';
import type { ArgBuilder, InputFieldMap, NormalizeArgs, ShapeFromTypeParam } from '../types';
import {
FieldKind,
FieldNullability,
Expand Down Expand Up @@ -414,4 +415,14 @@ export default class RootFieldBuilder<
) {
return this.createField<Args, Type, Nullable>(options as never);
}

listRef<T extends TypeParam<Types>, Nullable extends boolean = false>(
type: T,
options?: { nullable?: Nullable },
): ListRef<Types, ShapeFromTypeParam<Types, T, Nullable>[]> {
return new ListRef<Types, ShapeFromTypeParam<Types, T, Nullable>[]>(
type,
options?.nullable ?? false,
);
}
}
14 changes: 14 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import InternalRootFieldBuilder from './fieldUtils/root';
import InternalSubscriptionFieldBuilder from './fieldUtils/subscription';
import InternalBaseTypeRef from './refs/base';
import InternalEnumRef from './refs/enum';
import InternalInputListRef from './refs/input-list';
import InternalInputObjectRef from './refs/input-object';
import InternalInterfaceRef from './refs/interface';
import InternalListRef from './refs/list';
import InternalObjectRef from './refs/object';
import InternalScalarRef from './refs/scalar';
import InternalUnionRef from './refs/union';
Expand Down Expand Up @@ -148,6 +150,12 @@ export const InputObjectRef = InternalInputObjectRef as new <T>(
name: string,
) => PothosSchemaTypes.InputObjectRef<T>;

export type InputListRef<Types extends SchemaTypes, T> = PothosSchemaTypes.InputListRef<Types, T>;
export const InputListRef = InternalInputListRef as new <Types extends SchemaTypes, T>(
name: string,
required: boolean,
) => PothosSchemaTypes.InputListRef<Types, T>;

export type InterfaceRef<T, P = T> = PothosSchemaTypes.InterfaceRef<T, P>;
export const InterfaceRef = InternalInterfaceRef as new <T, P = T>(
name: string,
Expand All @@ -168,6 +176,12 @@ export const UnionRef = InternalUnionRef as new <T, P = T>(
name: string,
) => PothosSchemaTypes.UnionRef<T, P>;

export type ListRef<Types extends SchemaTypes, T, P = T> = PothosSchemaTypes.ListRef<Types, T, P>;
export const ListRef = InternalListRef as new <Types extends SchemaTypes, T, P = T>(
name: string,
nullable: boolean,
) => PothosSchemaTypes.ListRef<Types, T, P>;

export { default as BuildCache } from './build-cache';
export { default as BuiltinScalarRef } from './refs/builtin-scalar';
export { default as FieldRef } from './refs/field';
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/refs/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ export default class BaseTypeRef implements PothosSchemaTypes.BaseTypeRef {
name;

constructor(
kind: 'Enum' | 'InputObject' | 'Interface' | 'Object' | 'Scalar' | 'Union',
kind:
| 'Enum'
| 'InputObject'
| 'Interface'
| 'Object'
| 'Scalar'
| 'Union'
| 'List'
| 'InputList',
name: string,
) {
this.kind = kind;
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/refs/input-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { inputShapeKey, InputTypeParam, SchemaTypes } from '../types';
import BaseTypeRef from './base';

export default class InputObjectRef<Types extends SchemaTypes, T>
extends BaseTypeRef
implements PothosSchemaTypes.InputListRef<Types, T>
{
override kind = 'InputList' as const;

[inputShapeKey]!: T;
listType: InputTypeParam<Types>;
required: boolean;

constructor(listType: InputTypeParam<Types>, required: boolean) {
super('InputList', `InputList<${String(listType)}>`);
this.listType = listType;
this.required = required;
}
}
21 changes: 21 additions & 0 deletions packages/core/src/refs/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { outputShapeKey, parentShapeKey, SchemaTypes, TypeParam } from '../types';
import BaseTypeRef from './base';

export default class ListRef<Types extends SchemaTypes, T, P = T>
extends BaseTypeRef
implements PothosSchemaTypes.ListRef<Types, T, P>
{
override kind = 'List' as const;

[outputShapeKey]!: T;
[parentShapeKey]!: P;

listType: TypeParam<Types>;
nullable: boolean;

constructor(listType: TypeParam<Types>, nullable: boolean) {
super('List', `List<${String(listType)}>`);
this.listType = listType;
this.nullable = nullable;
}
}
5 changes: 3 additions & 2 deletions packages/core/src/types/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,10 @@ export type PothosOutputFieldType<Types extends SchemaTypes> =
}
| {
kind: 'List';
type: PothosNameOutputFieldType<Types>;
type: PothosOutputFieldType<Types>;
nullable: boolean;
};

export type PothosNameOutputFieldType<Types extends SchemaTypes> = Exclude<
PothosOutputFieldType<Types>,
{ kind: 'List' }
Expand All @@ -190,7 +191,7 @@ export type PothosInputFieldType<Types extends SchemaTypes> =
}
| {
kind: 'List';
type: PothosNameInputFieldType<Types>;
type: PothosInputFieldType<Types>;
required: boolean;
};

Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/types/global/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import type InternalInputFieldBuilder from '../../fieldUtils/input';
import type InternalRootFieldBuilder from '../../fieldUtils/root';
import type InternalBaseRef from '../../refs/base';
import type InternalEnumRef from '../../refs/enum';
import type InternalInputListRef from '../../refs/input-list';
import type InternalInputObjectRef from '../../refs/input-object';
import type InternalInterfaceRef from '../../refs/interface';
import type InternalListRef from '../../refs/list';
import type InternalObjectRef from '../../refs/object';
import type InternalScalarRef from '../../refs/scalar';
import type InternalUnionRef from '../../refs/union';
Expand Down Expand Up @@ -52,9 +54,13 @@ declare global {
export interface BaseTypeRef extends InternalBaseRef {}
export interface EnumRef<T, U = T> extends InternalEnumRef<T, U> {}
export interface InputObjectRef<T> extends InternalInputObjectRef<T> {}
export interface InputListRef<Types extends SchemaTypes, T>
extends InternalInputListRef<Types, T> {}
export interface InterfaceRef<T, P = T> extends InternalInterfaceRef<T, P> {}
export interface ObjectRef<T, P = T> extends InternalObjectRef<T, P> {}
export interface ScalarRef<T, U, P = T> extends InternalScalarRef<T, U, P> {}
export interface UnionRef<T, P = T> extends InternalUnionRef<T, P> {}
export interface ListRef<Types extends SchemaTypes, T, P = T>
extends InternalListRef<Types, T, P> {}
}
}
2 changes: 1 addition & 1 deletion packages/core/src/types/type-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export interface OutputRef<T = unknown> {
export interface InputRef<T = unknown> {
[inputShapeKey]: T;
name: string;
kind: 'Enum' | 'InputObject' | 'Scalar';
kind: 'Enum' | 'InputObject' | 'Scalar' | 'InputList';
}

export type OutputType<Types extends SchemaTypes> =
Expand Down
53 changes: 52 additions & 1 deletion packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { OutputType, SchemaTypes, typeBrandKey } from '../types';
import InputListRef from '../refs/input-list';
import ListRef from '../refs/list';
import {
InputType,
InputTypeParam,
OutputType,
SchemaTypes,
typeBrandKey,
TypeParam,
} from '../types';

export * from './base64';
export * from './context-cache';
Expand Down Expand Up @@ -86,3 +95,45 @@ export function getTypeBrand(val: unknown) {

return null;
}

export function unwrapListParam<Types extends SchemaTypes>(
param: TypeParam<Types> | InputTypeParam<Types>,
): OutputType<Types> | InputType<Types> {
if (Array.isArray(param)) {
return unwrapListParam(param[0]);
}

if (param instanceof ListRef || param instanceof InputListRef) {
return unwrapListParam(param.listType as TypeParam<Types>);
}

return param;
}

export function unwrapOutputListParam<Types extends SchemaTypes>(
param: TypeParam<Types>,
): OutputType<Types> {
if (Array.isArray(param)) {
return unwrapOutputListParam(param[0]);
}

if (param instanceof ListRef) {
return unwrapOutputListParam(param.listType as TypeParam<Types>);
}

return param;
}

export function unwrapInputListParam<Types extends SchemaTypes>(
param: InputTypeParam<Types>,
): InputType<Types> {
if (Array.isArray(param)) {
return unwrapInputListParam(param[0]);
}

if (param instanceof InputListRef) {
return unwrapInputListParam(param.listType as InputTypeParam<Types>);
}

return param;
}
3 changes: 2 additions & 1 deletion packages/core/src/utils/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
PothosTypeConfig,
SchemaTypes,
} from '../types';
import { unwrapInputFieldType } from './params';

export interface InputTypeFieldsMapping<Types extends SchemaTypes, T> {
configs: Record<string, PothosInputFieldConfig<Types>>;
Expand Down Expand Up @@ -162,7 +163,7 @@ function internalMapInputFields<Types extends SchemaTypes, T>(
}

const inputFieldConfigs = buildCache.getInputTypeFieldConfigs(
inputField.type.kind === 'List' ? inputField.type.type.ref : inputField.type.ref,
unwrapInputFieldType(inputField.type),
);

if (!seenTypes.has(typeConfig.name)) {
Expand Down
Loading