Skip to content

Commit 8c2bf6f

Browse files
committed
Add initial typings
1 parent d09e1f7 commit 8c2bf6f

File tree

4 files changed

+224
-2
lines changed

4 files changed

+224
-2
lines changed

index.d.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { FastifyPluginAsync } from 'fastify'
2+
import { GraphQLResolveInfo } from 'graphql'
3+
import { MercuriusContext } from 'mercurius'
4+
import { Options, SchemaObject } from 'ajv'
5+
6+
export interface MercuriusValidationHandlerMetadata {
7+
/**
8+
* The name of the associated GraphQL type.
9+
*/
10+
type: string;
11+
/**
12+
* The name of the associated GraphQL field.
13+
*/
14+
field: string;
15+
/**
16+
* The name of the associated GraphQL argument.
17+
*/
18+
argument: string;
19+
}
20+
21+
/**
22+
* The validation function to run when an argument is selected by the GraphQL operation.
23+
* Thrown errors will be caught and handled by `mercurius-validation`.
24+
*/
25+
export type MercuriusValidationHandler<TParent = any, TArgs = any, TContext = MercuriusContext> = (
26+
metadata: MercuriusValidationHandlerMetadata,
27+
value: any,
28+
parent: TParent,
29+
args: TArgs,
30+
context: TContext,
31+
info: GraphQLResolveInfo
32+
) => Promise<void>;
33+
34+
export type MercuriusValidationArgument<TParent = any, TArgs = any, TContext = MercuriusContext> = |
35+
SchemaObject |
36+
MercuriusValidationHandler<TParent, TArgs, TContext>;
37+
38+
export type MercuriusValidationField<TParent = any, TArgs = any, TContext = MercuriusContext> = Record<string, MercuriusValidationArgument<TParent, TArgs, TContext>> | SchemaObject
39+
40+
export type MercuriusValidationType<TParent = any, TArgs = any, TContext = MercuriusContext> = Record<string, MercuriusValidationField<TParent, TArgs, TContext>> & {
41+
__typeValidation?: SchemaObject
42+
}
43+
44+
export type MercuriusValidationSchema<TParent = any, TArgs = any, TContext = MercuriusContext> = Record<string, MercuriusValidationType<TParent, TArgs, TContext>>
45+
46+
export type MercuriusValidationMode = 'JSONSchema' | 'JTD'
47+
48+
export interface MercuriusValidationOptions<TParent = any, TArgs = any, TContext = MercuriusContext> extends Options {
49+
mode?: MercuriusValidationMode;
50+
schema?: MercuriusValidationSchema<TParent, TArgs, TContext>;
51+
}
52+
53+
/** Mercurius Validation is a plugin for `mercurius` that adds configurable validation support. */
54+
declare const mercuriusValidation: FastifyPluginAsync<MercuriusValidationOptions>
55+
56+
export default mercuriusValidation

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
"scripts": {
88
"unit": "tap --100 test/*.js",
99
"cov": "tap --coverage-report=html -J test/*.js",
10-
"lint": "npm run lint:standard",
10+
"lint": "npm run lint:standard && npm run lint:typescript",
1111
"lint:standard": "standard | snazzy",
1212
"lint:typescript": "standard --parser @typescript-eslint/parser --plugin @typescript-eslint/eslint-plugin index.d.ts test/types/*.ts | snazzy",
1313
"typescript": "tsd",
14-
"test": "npm run lint && npm run unit"
14+
"test": "npm run lint && npm run unit && npm run typescript"
1515
},
1616
"repository": {
1717
"type": "git",

test/types/index.test-d.ts

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { expectType } from 'tsd'
2+
import fastify from 'fastify'
3+
import { GraphQLResolveInfo } from 'graphql'
4+
import { MercuriusContext } from 'mercurius'
5+
import mercuriusValidation, { MercuriusValidationHandler, MercuriusValidationHandlerMetadata, MercuriusValidationOptions } from '../..'
6+
7+
const app = fastify()
8+
9+
// Register without options
10+
app.register(mercuriusValidation)
11+
app.register(mercuriusValidation, {})
12+
13+
// Register with AJV options
14+
app.register(mercuriusValidation, {
15+
coerceTypes: false
16+
})
17+
18+
// Use different modes
19+
app.register(mercuriusValidation, { mode: 'JTD' })
20+
app.register(mercuriusValidation, { mode: 'JSONSchema' })
21+
22+
// JSON Schema
23+
app.register(mercuriusValidation, {
24+
mode: 'JSONSchema',
25+
schema: {
26+
Filters: {
27+
text: { minLength: 1 }
28+
},
29+
Query: {
30+
message: {
31+
id: {
32+
minLength: 1
33+
}
34+
}
35+
}
36+
}
37+
})
38+
39+
// JTD
40+
app.register(mercuriusValidation, {
41+
mode: 'JTD',
42+
schema: {
43+
Filters: {
44+
text: { enum: ['hello', 'there'] }
45+
},
46+
Query: {
47+
message: {
48+
id: {
49+
type: 'uint8'
50+
}
51+
}
52+
}
53+
}
54+
})
55+
56+
// Function
57+
app.register(mercuriusValidation, {
58+
schema: {
59+
Query: {
60+
message: {
61+
async id (metadata, value, parent, args, context, info) {
62+
expectType<MercuriusValidationHandlerMetadata>(metadata)
63+
expectType<any>(value)
64+
expectType<any>(parent)
65+
expectType<any>(args)
66+
expectType<MercuriusContext>(context)
67+
expectType<GraphQLResolveInfo>(info)
68+
}
69+
}
70+
}
71+
}
72+
})
73+
74+
// Using options as object without generic
75+
interface CustomParent {
76+
parent: Record<string, any>;
77+
}
78+
79+
interface CustomArgs {
80+
arg: Record<string, any>;
81+
}
82+
83+
interface CustomContext extends MercuriusContext {
84+
hello?: string;
85+
}
86+
87+
const validationOptions: MercuriusValidationOptions = {
88+
schema: {
89+
Query: {
90+
message: {
91+
async id (
92+
metadata,
93+
value,
94+
parent: CustomParent,
95+
args: CustomArgs,
96+
context: CustomContext,
97+
info
98+
) {
99+
expectType<MercuriusValidationHandlerMetadata>(metadata)
100+
expectType<any>(value)
101+
expectType<CustomParent>(parent)
102+
expectType<CustomArgs>(args)
103+
expectType<CustomContext>(context)
104+
expectType<string | undefined>(context?.hello)
105+
expectType<GraphQLResolveInfo>(info)
106+
}
107+
}
108+
}
109+
}
110+
}
111+
112+
app.register(mercuriusValidation, validationOptions)
113+
114+
// 3. Using options as object with generics
115+
const authOptionsWithGenerics: MercuriusValidationOptions<CustomParent, CustomArgs, CustomContext> = {
116+
schema: {
117+
Query: {
118+
message: {
119+
async id (metadata, value, parent, args, context, info) {
120+
expectType<MercuriusValidationHandlerMetadata>(metadata)
121+
expectType<any>(value)
122+
expectType<CustomParent>(parent)
123+
expectType<CustomArgs>(args)
124+
expectType<CustomContext>(context)
125+
expectType<string | undefined>(context?.hello)
126+
expectType<GraphQLResolveInfo>(info)
127+
}
128+
}
129+
}
130+
}
131+
}
132+
133+
app.register(mercuriusValidation, authOptionsWithGenerics)
134+
135+
// 4. Creating functions using handler types
136+
const id: MercuriusValidationHandler<{}, {}, CustomContext> =
137+
async (metadata, value, parent, args, context, info) => {
138+
expectType<MercuriusValidationHandlerMetadata>(metadata)
139+
expectType<any>(value)
140+
expectType<{}>(parent)
141+
expectType<{}>(args)
142+
expectType<CustomContext>(context)
143+
expectType<GraphQLResolveInfo>(info)
144+
expectType<string | undefined>(context?.hello)
145+
}
146+
147+
app.register(mercuriusValidation, {
148+
schema: {
149+
Query: {
150+
message: {
151+
id
152+
}
153+
}
154+
}
155+
})

tsconfig.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es2018",
4+
"module": "commonjs",
5+
"noEmit": true,
6+
"strict": true,
7+
"esModuleInterop": true
8+
},
9+
"exclude": ["node_modules"],
10+
"files": ["./test/types/index.test-d.ts"]
11+
}

0 commit comments

Comments
 (0)