Skip to content

Commit

Permalink
integrate feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt committed Aug 25, 2019
1 parent fc5ab57 commit ec8542d
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 8 deletions.
38 changes: 31 additions & 7 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ import {
NexusExtendInputTypeConfig,
} from "./definitions/extendInputType";
import { DynamicInputMethodDef, DynamicOutputMethodDef } from "./dynamicMethod";
import { DynamicOutputPropertyDef } from "./dynamicProperty";
import {
DynamicOutputPropertyDef,
DynamicInputPropertyDef,
} from "./dynamicProperty";

export type Maybe<T> = T | null;

Expand Down Expand Up @@ -266,6 +269,11 @@ export type DynamicOutputProperties = Record<
DynamicOutputPropertyDef<string>
>;

export type DynamicInputProperties = Record<
string,
DynamicInputPropertyDef<string>
>;

/**
* Builds all of the types, properly accounts for any using "mix".
* Since the enum types are resolved synchronously, these need to guard for
Expand Down Expand Up @@ -325,6 +333,11 @@ export class SchemaBuilder {
*/
protected dynamicOutputProperties: DynamicOutputProperties = {};

/**
* Add dynamic input properties
*/
protected dynamicInputProperties: DynamicInputProperties = {};

/**
* All types that need to be traversed for children types
*/
Expand Down Expand Up @@ -1143,18 +1156,27 @@ export class SchemaBuilder {
return obj;
}

// MARK
addDynamicInputFields(block: InputDefinitionBlock<any>, isList: boolean) {
eachObj(this.dynamicInputFields, (val, methodName) => {
if (typeof val === "string") {
return this.addDynamicScalar(methodName, val, block);
}

// At this point `methodName` identifier name can be a misnormer. If the
// given factory returns a function then methodName is accurate, but not
// if the factory returns something else. For example it may return an
// object of methods (aka. methods under a namespace/field/property)
// in which case a better identifier might be `namespace`, `propName`, ...
Object.defineProperty(block, methodName, {
// @ts-ignore
block[methodName] = (...args: any[]) => {
const config = isList ? [args[0], { list: isList, ...args[1] }] : args;
return val.value.factory({
args: config,
typeDef: block,
builder: this,
typeName: block.typeName,
});
};
});

eachObj(this.dynamicInputProperties, (val, propertyName) => {
Object.defineProperty(block, propertyName, {
get() {
return val.value.factory({
args: [],
Expand All @@ -1168,6 +1190,7 @@ export class SchemaBuilder {
});
}

// MARK
addDynamicOutputMembers(block: OutputDefinitionBlock<any>, isList: boolean) {
eachObj(this.dynamicOutputFields, (val, methodName) => {
if (typeof val === "string") {
Expand Down Expand Up @@ -1198,6 +1221,7 @@ export class SchemaBuilder {
});
}

// MARK
addDynamicScalar(
methodName: string,
typeName: string,
Expand Down
45 changes: 44 additions & 1 deletion src/dynamicProperty.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { withNexusSymbol, NexusTypes } from "./definitions/_types";
import { BaseExtensionConfig } from "./dynamicMethod";
import { SchemaBuilder } from "./builder";
import { OutputDefinitionBlock } from "./definitions/definitionBlocks";
import {
OutputDefinitionBlock,
InputDefinitionBlock,
} from "./definitions/definitionBlocks";

//
// Ouput
//

export type OutputPropertyFactoryConfig<T> = {
builder: SchemaBuilder;
Expand Down Expand Up @@ -43,3 +50,39 @@ export function dynamicOutputProperty<T extends string>(
) {
return new DynamicOutputPropertyDef(config.name, config);
}

//
// Input
//

export type InputFactoryConfig<T> = {
args: any[];
builder: SchemaBuilder;
typeDef: InputDefinitionBlock<any>;
/**
* The name of the type this field is being declared on
*/
typeName: string;
};

export type InputConfig<T extends string> = BaseExtensionConfig<T> & {
/**
* Invoked when the property is accessed (as a getter)
*/
factory(config: InputFactoryConfig<T>): any;
};

export class DynamicInputPropertyDef<Name extends string> {
constructor(readonly name: Name, protected config: InputConfig<Name>) {}
get value() {
return this.config;
}
}

/**
* Same as the outputFieldExtension, but for fields that
* should be added on as input types.
*/
export function dynamicInputProperty<T extends string>(config: InputConfig<T>) {
return new DynamicInputPropertyDef(config.name, config);
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export {
FieldType,
} from "./typegenTypeHelpers";
export { dynamicInputMethod, dynamicOutputMethod } from "./dynamicMethod";
export { dynamicInputProperty, dynamicOutputProperty } from "./dynamicProperty";
export { core, blocks, ext };
import * as core from "./core";
import * as blocks from "./blocks";
Expand Down

0 comments on commit ec8542d

Please sign in to comment.