Skip to content

Commit

Permalink
Add new PothosError classes
Browse files Browse the repository at this point in the history
  • Loading branch information
hayes committed Feb 7, 2023
1 parent cd2c866 commit bf0385a
Show file tree
Hide file tree
Showing 69 changed files with 370 additions and 216 deletions.
16 changes: 16 additions & 0 deletions .changeset/ten-bottles-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@pothos/plugin-smart-subscriptions': minor
'@pothos/plugin-prisma-utils': minor
'@pothos/plugin-complexity': minor
'@pothos/plugin-dataloader': minor
'@pothos/plugin-scope-auth': minor
'@pothos/plugin-validation': minor
'@pothos/plugin-sub-graph': minor
'@pothos/plugin-errors': minor
'@pothos/plugin-prisma': minor
'@pothos/plugin-relay': minor
'@pothos/core': minor
'@pothos/deno': minor
---

Add new PothosError classes
21 changes: 11 additions & 10 deletions packages/core/src/build-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from 'graphql';
import type SchemaBuilder from './builder';
import ConfigStore from './config-store';
import { PothosError, PothosSchemaError } from './errors';
import { BasePlugin, MergedPlugins } from './plugins';
import BuiltinScalarRef from './refs/builtin-scalar';
import { ImplementableInputObjectRef } from './refs/input-object';
Expand Down Expand Up @@ -101,7 +102,7 @@ export default class BuildCache<Types extends SchemaTypes> {
).constructor.plugins[pluginName];

if (!Plugin) {
throw new Error(`No plugin named ${pluginName} was registered`);
throw new PothosError(`No plugin named ${pluginName} was registered`);
}

plugins[pluginName] = new Plugin(this, pluginName);
Expand Down Expand Up @@ -134,7 +135,7 @@ export default class BuildCache<Types extends SchemaTypes> {
const builtType = this.types.get(typeConfig.name) as GraphQLInputObjectType | undefined;

if (!builtType) {
throw new Error(`Input type ${typeConfig.name} has not been built yet`);
throw new PothosSchemaError(`Input type ${typeConfig.name} has not been built yet`);
}

const fields = builtType.getFields();
Expand Down Expand Up @@ -259,7 +260,7 @@ export default class BuildCache<Types extends SchemaTypes> {

private addType(ref: string, type: GraphQLNamedType) {
if (this.types.has(ref)) {
throw new Error(
throw new PothosSchemaError(
`reference or name has already been used to create another type (${type.name})`,
);
}
Expand Down Expand Up @@ -429,7 +430,7 @@ export default class BuildCache<Types extends SchemaTypes> {
return this.getInterfaceFields(type);
}

throw new Error(`Type ${type.name} does not have fields to resolve`);
throw new PothosSchemaError(`Type ${type.name} does not have fields to resolve`);
}

private getInputFields(type: GraphQLInputObjectType): GraphQLInputFieldConfigMap {
Expand Down Expand Up @@ -458,7 +459,7 @@ export default class BuildCache<Types extends SchemaTypes> {
const type = this.getType(ref);

if (type instanceof GraphQLInputObjectType) {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${String(ref)} to be an output type but it was defined as an InputObject`,
);
}
Expand All @@ -470,23 +471,23 @@ export default class BuildCache<Types extends SchemaTypes> {
const type = this.getType(ref);

if (!type) {
throw new TypeError(`Missing implementation of for type ${String(ref)}`);
throw new PothosSchemaError(`Missing implementation of for type ${String(ref)}`);
}

if (type instanceof GraphQLObjectType) {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${ImplementableInputObjectRef} to be an input type but it was defined as a GraphQLObjectType`,
);
}

if (type instanceof GraphQLInterfaceType) {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${ImplementableInputObjectRef} to be an input type but it was defined as a GraphQLInterfaceType`,
);
}

if (type instanceof GraphQLUnionType) {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${String(ref)} to be an input type but it was defined as an GraphQLUnionType`,
);
}
Expand Down Expand Up @@ -538,7 +539,7 @@ export default class BuildCache<Types extends SchemaTypes> {
break;
}

throw new Error(`Expected ${String(ref)} to be of type ${kind}`);
throw new PothosSchemaError(`Expected ${String(ref)} to be of type ${kind}`);
}

private buildObject(
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from 'graphql';
import BuildCache from './build-cache';
import ConfigStore from './config-store';
import { PothosError, PothosSchemaError } from './errors';
import InputFieldBuilder from './fieldUtils/input';
import InterfaceFieldBuilder from './fieldUtils/interface';
import MutationFieldBuilder from './fieldUtils/mutation';
Expand Down Expand Up @@ -111,7 +112,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
plugin: PluginConstructorMap<SchemaTypes>[T],
) {
if (!this.allowPluginReRegistration && this.plugins[name]) {
throw new Error(`Received multiple implementations for plugin ${name}`);
throw new PothosError(`Received multiple implementations for plugin ${name}`);
}

this.plugins[name] = plugin;
Expand All @@ -131,7 +132,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
: (options as { name?: string }).name ?? (param as { name: string }).name;

if (name === 'Query' || name === 'Mutation' || name === 'Subscription') {
throw new Error(`Invalid object name ${name} use .create${name}Type() instead`);
throw new PothosSchemaError(`Invalid object name ${name} use .create${name}Type() instead`);
}

const ref =
Expand Down
57 changes: 35 additions & 22 deletions packages/core/src/config-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
GraphQLScalarType,
GraphQLString,
} from 'graphql';
import { PothosError, PothosSchemaError } from './errors';
import BaseTypeRef from './refs/base';
import BuiltinScalarRef from './refs/builtin-scalar';
import FieldRef from './refs/field';
Expand Down Expand Up @@ -116,7 +117,9 @@ export default class ConfigStore<Types extends SchemaTypes> {
typeConfig.kind === 'Mutation' ||
typeConfig.kind === 'Subscription'
) {
throw new Error(`Can not add interfaces to ${typeName} because it is a ${typeConfig.kind}`);
throw new PothosSchemaError(
`Can not add interfaces to ${typeName} because it is a ${typeConfig.kind}`,
);
}

typeConfig.interfaces = [
Expand All @@ -140,7 +143,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
) => PothosFieldConfig<Types>,
) {
if (this.fieldRefs.has(ref)) {
throw new Error(`FieldRef ${String(ref)} has already been added to config store`);
throw new PothosSchemaError(`FieldRef ${String(ref)} has already been added to config store`);
}

const typeRefOrName = unwrapListParam(typeParam);
Expand Down Expand Up @@ -192,18 +195,18 @@ export default class ConfigStore<Types extends SchemaTypes> {
): Extract<PothosFieldConfig<Types>, { graphqlKind: T }> {
if (!this.fieldRefs.has(ref)) {
if (this.pendingFields.has(ref)) {
throw new Error(
throw new PothosSchemaError(
`Missing implementation for ${this.describeRef(this.pendingFields.get(ref)!)}`,
);
}

throw new Error(`Missing definition for ${String(ref)}`);
throw new PothosSchemaError(`Missing definition for ${String(ref)}`);
}

const config = this.fieldRefs.get(ref)!(name, parentField, typeConfig);

if (kind && config.graphqlKind !== kind) {
throw new TypeError(
throw new PothosError(
`Expected ref for field named ${name} to resolve to a ${kind} type, but got ${config.graphqlKind}`,
);
}
Expand All @@ -213,7 +216,7 @@ export default class ConfigStore<Types extends SchemaTypes> {

associateRefWithName(ref: ConfigurableRef<Types>, name: string) {
if (!this.typeConfigs.has(name)) {
throw new Error(`${name} has not been implemented yet`);
throw new PothosSchemaError(`${name} has not been implemented yet`);
}

this.refsToName.set(ref, name);
Expand All @@ -231,7 +234,9 @@ export default class ConfigStore<Types extends SchemaTypes> {
const { name } = config;

if (this.typeConfigs.has(name)) {
throw new Error(`Duplicate typename: Another type with name ${name} already exists.`);
throw new PothosSchemaError(
`Duplicate typename: Another type with name ${name} already exists.`,
);
}

this.typeConfigs.set(config.name, config);
Expand All @@ -257,19 +262,23 @@ export default class ConfigStore<Types extends SchemaTypes> {

if (typeof ref === 'string') {
if (!this.typeConfigs.has(ref)) {
throw new Error(`Type ${String(ref)} has not been implemented`);
throw new PothosSchemaError(`Type ${String(ref)} has not been implemented`);
}
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)}`);
throw new PothosSchemaError(
`Expected a base type but got a ${ref.kind} of ${String(ref.listType)}`,
);
} else {
throw new TypeError(`Ref ${String(ref)} has not been implemented`);
throw new PothosSchemaError(`Ref ${String(ref)} has not been implemented`);
}

if (kind && config.graphqlKind !== kind) {
throw new TypeError(`Expected ref to resolve to a ${kind} type, but got ${config.kind}`);
throw new PothosSchemaError(
`Expected ref to resolve to a ${kind} type, but got ${config.kind}`,
);
}

return config as Extract<PothosTypeConfig, { kind: T }>;
Expand All @@ -278,7 +287,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
getInputTypeRef(ref: ConfigurableRef<Types> | string) {
if (ref instanceof BaseTypeRef) {
if (ref.kind !== 'InputObject' && ref.kind !== 'Enum' && ref.kind !== 'Scalar') {
throw new TypeError(`Expected ${ref.name} to be an input type but got ${ref.kind}`);
throw new PothosSchemaError(`Expected ${ref.name} to be an input type but got ${ref.kind}`);
}

return ref as InputRef;
Expand All @@ -297,7 +306,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
config.graphqlKind !== 'Enum' &&
config.graphqlKind !== 'Scalar'
) {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${config.name} to be an input type but got ${config.graphqlKind}`,
);
}
Expand All @@ -316,11 +325,13 @@ export default class ConfigStore<Types extends SchemaTypes> {
getOutputTypeRef(ref: ConfigurableRef<Types> | string) {
if (ref instanceof BaseTypeRef) {
if (ref.kind === 'InputObject' || ref.kind === 'InputList') {
throw new TypeError(`Expected ${ref.name} to be an output type but got ${ref.kind}`);
throw new PothosSchemaError(
`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}`);
throw new PothosSchemaError(`Expected ${ref.name} to be a base type but got a ${ref.kind}`);
}

return ref as OutputRef;
Expand All @@ -335,7 +346,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
const config = this.typeConfigs.get(ref)!;

if (config.graphqlKind === 'InputObject') {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${config.name} to be an output type but got ${config.graphqlKind}`,
);
}
Expand All @@ -353,14 +364,14 @@ export default class ConfigStore<Types extends SchemaTypes> {

onTypeConfig(ref: ConfigurableRef<Types>, cb: (config: PothosTypeConfig) => void) {
if (!ref) {
throw new Error(`${String(ref)} is not a valid type ref`);
throw new PothosSchemaError(`${String(ref)} is not a valid type ref`);
}
if (this.refsToName.has(ref)) {
cb(this.getTypeConfig(ref));
} else if (typeof ref === 'string' && this.typeConfigs.has(ref)) {
cb(this.typeConfigs.get(ref)!);
} else if (!this.pending) {
throw new Error(`Ref ${String(ref)} has not been implemented`);
throw new PothosSchemaError(`Ref ${String(ref)} has not been implemented`);
} else if (this.pendingRefResolutions.has(ref)) {
this.pendingRefResolutions.get(ref)!.push(cb);
} else {
Expand Down Expand Up @@ -392,7 +403,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
const fields = this.fields.get(name)!;

if (kind && typeConfig.graphqlKind !== kind) {
throw new TypeError(
throw new PothosSchemaError(
`Expected ${name} to be a ${kind} type, but found ${typeConfig.graphqlKind}`,
);
}
Expand All @@ -410,7 +421,7 @@ export default class ConfigStore<Types extends SchemaTypes> {
fns.forEach((fn) => void fn());

if (this.pendingRefResolutions.size > 0) {
throw new Error(
throw new PothosSchemaError(
`Missing implementations for some references (${[...this.pendingRefResolutions.keys()]
.map((ref) => this.describeRef(ref))
.join(', ')}).`,
Expand Down Expand Up @@ -495,11 +506,13 @@ export default class ConfigStore<Types extends SchemaTypes> {
const existingFields = this.getFields(typeConfig.name);

if (existingFields.has(fieldName)) {
throw new Error(`Duplicate field definition for field ${fieldName} in ${typeConfig.name}`);
throw new PothosSchemaError(
`Duplicate field definition for field ${fieldName} in ${typeConfig.name}`,
);
}

if (fieldConfig.graphqlKind !== typeConfig.graphqlKind) {
throw new TypeError(
throw new PothosSchemaError(
`${typeConfig.name}.${fieldName} was defined as a ${fieldConfig.graphqlKind} field but ${typeConfig.name} is a ${typeConfig.graphqlKind}`,
);
}
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-disable max-classes-per-file */

export class PothosError extends Error {
constructor(message: string) {
super(message);
this.name = 'PothosError';
}
}

export class PothosSchemaError extends PothosError {
constructor(message: string) {
super(message);
this.name = 'PothosSchemaError';
}
}

export class PothosValidationError extends PothosError {
constructor(message: string) {
super(message);
this.name = 'PothosValidationError';
}
}
5 changes: 4 additions & 1 deletion packages/core/src/fieldUtils/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defaultFieldResolver } from 'graphql';
import { PothosSchemaError } from '../errors';
import FieldRef from '../refs/field';
import type {
FieldKind,
Expand Down Expand Up @@ -67,7 +68,9 @@ export default class BaseFieldUtil<Types extends SchemaTypes, ParentShape, Kind
let resolve =
(options as { resolve?: (...argList: unknown[]) => unknown }).resolve ??
(() => {
throw new Error(`Not implemented: No resolver found for ${this.typename}.${name}`);
throw new PothosSchemaError(
`Not implemented: No resolver found for ${this.typename}.${name}`,
);
});

if (options.extensions?.pothosExposedField === name) {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import InternalScalarRef from './refs/scalar';
import InternalUnionRef from './refs/union';
import type { FieldKind, NormalizeSchemeBuilderOptions, RootName, SchemaTypes } from './types';

export * from './errors';
export * from './plugins';
export * from './types';
export * from './utils';
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
GraphQLTypeResolver,
} from 'graphql';
import type BuildCache from '../build-cache';
import { PothosError } from '../errors';
import type {
PothosEnumValueConfig,
PothosInputFieldConfig,
Expand Down Expand Up @@ -168,7 +169,7 @@ export class BasePlugin<Types extends SchemaTypes, T extends object = object> {
* @return {object} - The data object for the current request
*/
protected createRequestData(context: Types['Context']): T {
throw new Error('createRequestData not implemented');
throw new PothosError('createRequestData not implemented');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/utils/base64.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const getGlobalThis = () => {
// @ts-ignore
if (typeof window !== 'undefined') return window;
if (typeof global !== 'undefined') return global;
if (typeof this !== 'undefined') return this!;
if (this !== undefined) return this!;
throw new Error('Unable to locate global `this`');
};

Expand Down
Loading

0 comments on commit bf0385a

Please sign in to comment.