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

[RFC] Plugin system #200

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -4,4 +4,4 @@ website/build
examples/*/dist
website/static/playground-dist
yarn-error.log
coverage/*
coverage
2 changes: 0 additions & 2 deletions docs/api-interfaceType.md
Expand Up @@ -25,5 +25,3 @@ const User = objectType({
},
});
```

If you need to modify the description or resolver defined by an interface, you can call the `modify` method on `objectType` to change these after the fact.
7 changes: 7 additions & 0 deletions docs/plugins.md
@@ -0,0 +1,7 @@
# Nexus Plugins

A "Plugin" is a way to extend the functionality of Nexus by tapping-into the
object/schema/type definitions for the GraphQL resolution lifecycle
in a way that is still type-safe.

To get you started, we have a few "plugins" that Nexus ships with out-of the box.
10 changes: 10 additions & 0 deletions examples/apollo-fullstack/src/fullstack-typegen.ts
Expand Up @@ -159,4 +159,14 @@ export interface NexusGenTypes {
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
abstractResolveReturn: NexusGenAbstractResolveReturnTypes;
}


declare global {
interface NexusGenPluginTypeConfig<TypeName extends string> {
}
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
}
interface NexusGenPluginSchemaConfig {
}
}
9 changes: 9 additions & 0 deletions examples/ghost/src/generated/ghost-nexus.ts
Expand Up @@ -156,3 +156,12 @@ export interface NexusGenTypes {
abstractTypes: NexusGenTypes["interfaceNames"] | NexusGenTypes["unionNames"];
abstractResolveReturn: NexusGenAbstractResolveReturnTypes;
}

declare global {
interface NexusGenPluginTypeConfig<TypeName extends string> {}
interface NexusGenPluginFieldConfig<
TypeName extends string,
FieldName extends string
> {}
interface NexusGenPluginSchemaConfig {}
}
10 changes: 10 additions & 0 deletions examples/githunt-api/src/githunt-typegen.ts
Expand Up @@ -184,4 +184,14 @@ export interface NexusGenTypes {
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
abstractResolveReturn: NexusGenAbstractResolveReturnTypes;
}


declare global {
interface NexusGenPluginTypeConfig<TypeName extends string> {
}
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
}
interface NexusGenPluginSchemaConfig {
}
}
2 changes: 1 addition & 1 deletion examples/kitchen-sink/src/kitchen-sink-definitions.ts
Expand Up @@ -182,7 +182,7 @@ export const Query = objectType({
resolve: () => "ok",
});
t.list.date("dateAsList", () => []);
t.collection("collectionField", {
t.collectionField("collectionField", {
type: Bar,
args: {
a: intArg(),
Expand Down
16 changes: 14 additions & 2 deletions examples/kitchen-sink/src/kitchen-sink-typegen.ts
Expand Up @@ -13,22 +13,24 @@ declare global {
}
declare global {
interface NexusGenCustomOutputMethods<TypeName extends string> {
collection<FieldName extends string>(fieldName: FieldName, opts: {
collectionField<FieldName extends string>(fieldName: FieldName, opts: {
type: NexusGenObjectNames | NexusGenInterfaceNames | core.NexusObjectTypeDef<string> | core.NexusInterfaceTypeDef<string>,
nodes: core.SubFieldResolver<TypeName, FieldName, "nodes">,
totalCount: core.SubFieldResolver<TypeName, FieldName, "totalCount">,
args?: core.ArgsRecord,
nullable?: boolean,
description?: string
}): void;
relayConnection<FieldName extends string>(fieldName: FieldName, opts: {
relayConnectionField
<FieldName extends string>(fieldName: FieldName, opts: {
type: NexusGenObjectNames | NexusGenInterfaceNames | core.NexusObjectTypeDef<string> | core.NexusInterfaceTypeDef<string>,
edges: core.SubFieldResolver<TypeName, FieldName, "edges">,
pageInfo: core.SubFieldResolver<TypeName, FieldName, "pageInfo">,
args?: Record<string, core.NexusArgDef<string>>,
nullable?: boolean,
description?: string
}): void

date<FieldName extends string>(fieldName: FieldName, ...opts: core.ScalarOutSpread<TypeName, FieldName>): void // "Date";
}
}
Expand Down Expand Up @@ -224,4 +226,14 @@ export interface NexusGenTypes {
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
abstractResolveReturn: NexusGenAbstractResolveReturnTypes;
}


declare global {
interface NexusGenPluginTypeConfig<TypeName extends string> {
}
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
}
interface NexusGenPluginSchemaConfig {
}
}
3 changes: 2 additions & 1 deletion examples/star-wars/src/schema.ts
@@ -1,6 +1,6 @@
import * as path from "path";
import * as allTypes from "./graphql";
import { makeSchema } from "nexus";
import { makeSchema, plugin } from "nexus";

/**
* Finally, we construct our schema (whose starting query type is the query
Expand All @@ -21,4 +21,5 @@ export const schema = makeSchema({
],
contextType: "swapi.ContextType",
},
plugins: [plugin.AuthorizationPlugin],
});
33 changes: 33 additions & 0 deletions examples/star-wars/src/star-wars-typegen.ts
Expand Up @@ -131,4 +131,37 @@ export interface NexusGenTypes {
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
abstractResolveReturn: NexusGenAbstractResolveReturnTypes;
}


import { core } from 'nexus';
import { GraphQLResolveInfo } from 'graphql';
export type AuthorizeResolver<
TypeName extends string,
FieldName extends string
> = (
root: core.RootValue<TypeName>,
args: core.ArgsValue<TypeName, FieldName>,
context: core.GetGen<"context">,
info: GraphQLResolveInfo
) => core.PromiseOrValue<boolean | Error>;

declare global {
interface NexusGenPluginTypeConfig<TypeName extends string> {
}
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {

/**
* Authorization for an individual field. Returning "true"
* or "Promise<true>" means the field can be accessed.
* Returning "false" or "Promise<false>" will respond
* with a "Not Authorized" error for the field. Returning
* or throwing an error will also prevent the resolver from
* executing.
*/
authorize?: AuthorizeResolver<TypeName, FieldName>

}
interface NexusGenPluginSchemaConfig {
}
}
14 changes: 12 additions & 2 deletions examples/ts-ast-reader/src/ts-ast-reader-typegen.ts
Expand Up @@ -17,8 +17,8 @@ export interface NexusGenInputs {
}

export interface NexusGenEnums {
NodeFlags: 4194304 | 16384 | 3 | 2 | 64 | 12679168 | 8192 | 2048 | 32 | 512 | 262144 | 1024 | 256 | 128 | 8388608 | 65536 | 2097152 | 16777216 | 1 | 16 | 4 | 0 | 1572864 | 524288 | 1048576 | 1408 | 384 | 8 | 32768 | 131072 | 20480 | 4194816 | 4096
SyntaxKind: 118 | 54 | 69 | 49 | 120 | 185 | 187 | 169 | 197 | 212 | 119 | 63 | 41 | 62 | 40 | 121 | 58 | 201 | 122 | 55 | 70 | 50 | 146 | 9 | 204 | 186 | 218 | 123 | 73 | 229 | 285 | 191 | 160 | 71 | 51 | 246 | 271 | 74 | 274 | 75 | 240 | 209 | 76 | 19 | 23 | 21 | 57 | 314 | 27 | 149 | 205 | 175 | 7 | 77 | 157 | 124 | 166 | 161 | 78 | 228 | 317 | 79 | 236 | 125 | 152 | 272 | 80 | 198 | 81 | 82 | 223 | 25 | 24 | 190 | 83 | 220 | 316 | 1 | 243 | 84 | 278 | 35 | 33 | 37 | 59 | 36 | 34 | 52 | 254 | 255 | 85 | 257 | 221 | 211 | 86 | 259 | 87 | 88 | 59 | 28 | 60 | 118 | 109 | 288 | 299 | 73 | 8 | 148 | 18 | 73 | 14 | 0 | 2 | 163 | 226 | 89 | 227 | 225 | 144 | 239 | 196 | 90 | 165 | 158 | 126 | 145 | 32 | 67 | 68 | 48 | 47 | 30 | 273 | 72 | 91 | 222 | 109 | 250 | 249 | 248 | 92 | 253 | 183 | 180 | 162 | 127 | 176 | 93 | 287 | 94 | 241 | 110 | 174 | 128 | 289 | 300 | 302 | 301 | 296 | 303 | 294 | 292 | 291 | 293 | 304 | 310 | 305 | 298 | 299 | 308 | 306 | 309 | 288 | 297 | 307 | 290 | 295 | 267 | 268 | 263 | 266 | 260 | 270 | 264 | 262 | 265 | 261 | 269 | 11 | 12 | 129 | 233 | 71 | 71 | 71 | 147 | 117 | 310 | 310 | 147 | 14 | 71 | 108 | 17 | 147 | 7 | 183 | 31 | 66 | 46 | 29 | 28 | 111 | 182 | 181 | 315 | 214 | 156 | 155 | 61 | 45 | 39 | 258 | 245 | 244 | 130 | 3 | 256 | 252 | 247 | 251 | 131 | 132 | 192 | 95 | 4 | 213 | 14 | 312 | 96 | 135 | 8 | 184 | 136 | 188 | 147 | 210 | 18 | 22 | 20 | 171 | 112 | 151 | 195 | 177 | 313 | 65 | 43 | 60 | 44 | 38 | 203 | 202 | 113 | 189 | 275 | 154 | 153 | 114 | 115 | 148 | 56 | 133 | 13 | 134 | 172 | 97 | 230 | 217 | 26 | 159 | 137 | 6 | 276 | 2 | 64 | 42 | 284 | 277 | 208 | 116 | 138 | 10 | 98 | 99 | 232 | 139 | 311 | 215 | 193 | 206 | 15 | 16 | 216 | 17 | 100 | 178 | 101 | 234 | 53 | 102 | 103 | 235 | 170 | 242 | 194 | 140 | 168 | 199 | 104 | 179 | 150 | 163 | 167 | 164 | 141 | 173 | 142 | 0 | 143 | 282 | 280 | 279 | 286 | 283 | 281 | 237 | 238 | 219 | 105 | 200 | 106 | 107 | 224 | 5 | 108 | 231 | 207 | 117
NodeFlags: ts.NodeFlags
SyntaxKind: ts.SyntaxKind
}

export interface NexusGenRootTypes {
Expand Down Expand Up @@ -1593,4 +1593,14 @@ export interface NexusGenTypes {
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
abstractResolveReturn: NexusGenAbstractResolveReturnTypes;
}


declare global {
interface NexusGenPluginTypeConfig<TypeName extends string> {
}
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
}
interface NexusGenPluginSchemaConfig {
}
}
2 changes: 2 additions & 0 deletions jest.config.js
Expand Up @@ -15,4 +15,6 @@ module.exports = {
moduleNameMapper: {
"package.json": "<rootDir>/tests/stubs/package.json",
},
collectCoverageFrom: ["<rootDir>/src/**/*.ts"],
coverageReporters: ["lcov", "text", "html"],
};
17 changes: 10 additions & 7 deletions package.json
@@ -1,15 +1,15 @@
{
"name": "nexus",
"version": "0.12.0-beta.6",
"version": "0.12.0-beta.7",
"main": "dist",
"types": "dist",
"license": "MIT",
"description": "Scalable, strongly typed GraphQL schema development",
"homepage": "https://nexus.js.org",
"scripts": {
"dev": "yarn link-examples && tsc -w",
"test": "jest",
"test:ci": "jest -i",
"test": "jest --watch",
"test:ci": "jest -i --coverage",
"build": "tsc && prettier --write 'dist/**/*.ts'",
"lint": "tslint -p tsconfig.json",
"clean": "rm -rf dist",
Expand Down Expand Up @@ -39,23 +39,26 @@
"tslib": "^1.9.3"
},
"devDependencies": {
"@types/graphql": "14.0.7",
"@types/graphql": "^14.2.2",
"@types/jest": "^23.3.7",
"@types/node": "^10.12.2",
"@types/prettier": "^1.15.2",
"graphql": "^14.0.2",
"@types/graphql-iso-date": "^3.3.1",
"graphql": "^14.2.0",
"husky": "^1.1.2",
"jest": "^23.6.0",
"lint-staged": "^7.3.0",
"prettier": "^1.16.0",
"ts-jest": "^23.10.4",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"graphql-iso-date": "3.6.1",
"tslint-config-prettier": "^1.15.0",
"typescript": "^3.4.5"
"typescript": "^3.4.5",
"source-map-support": "^0.5.12"
},
"peerDependencies": {
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0"
"graphql": "^14.2.0"
},
"husky": {
"hooks": {
Expand Down