mercurius-js / validation Goto Github PK
View Code? Open in Web Editor NEWAdds configurable validation support to Mercurius.
License: MIT License
Adds configurable validation support to Mercurius.
License: MIT License
I am using @mercuriusjs/federation and mercurius-codegen to build a subgraph. I follow implementation directed by the doc. But always get the following errors
src/__generated-types__.ts:209:33 - error TS2304: Cannot find name '_Service'.
209 _Service: ResolverTypeWrapper<_Service>;
~~~~~~~~
src/__generated-types__.ts:223:13 - error TS2304: Cannot find name '_Service'.
223 _Service: _Service;
~~~~~~~~
src/__generated-types__.ts:277:19 - error TS2304: Cannot find name 'Query_entitiesArgs'.
277 RequireFields<Query_entitiesArgs, "representations">
~~~~~~~~~~~~~~~~~~
src/__generated-types__.ts:356:52 - error TS2304: Cannot find name '_Service'.
356 sdl?: LoaderResolver<Maybe<Scalars["String"]>, _Service, {}, TContext>;
In my code typescript is not angry anywhere.
Here is my server.ts file
import Fastify, { FastifyRequest, FastifyReply } from "fastify";
import mercurius from "mercurius";
import mercuriusCodegen from "mercurius-codegen";
import { buildFederationSchema } from "@mercuriusjs/federation";
//
import { userTypeDefs } from "./user/user.schema";
import { userResolvers } from "./user/user.resolvers";
//###########################################################################
const app = Fastify();
const PORT = 4001;
const buildContext = async (req: FastifyRequest, _reply: FastifyReply) => {
return {
authorization: req.headers.authorization,
};
};
type PromiseType<T> = T extends PromiseLike<infer U> ? U : T;
declare module "mercurius" {
interface MercuriusContext
extends PromiseType<ReturnType<typeof buildContext>> {}
}
app.register(mercurius, {
schema: buildFederationSchema(userTypeDefs, {
isGateway: false,
}),
resolvers: userResolvers,
context: buildContext,
});
mercuriusCodegen(app, {
// Commonly relative to your root package.json
targetPath: "./src/__generated-types__.ts",
// operationsGlob: "./src/graphql/operations/*.gql",
// codegenConfig: {
// loadersCustomParentTypes: {
// Human: "never",
// },
// },
}).catch(console.error);
// Start server
app.get("/", async function (req, reply) {
const query = "{ _service { sdl } }";
return app.graphql(query);
});
app.listen({ port: PORT });
I don't know what is going wrong there. I cannot modify generated-types.ts file since it is generated automatically when I start the server.
As title, if I use extendSchema
after registering mercurius-validation
, it no longer works.
${mercuriusValidation.graphQLTypeDefs}
type Query {
foo(page: Pagination!): Int!
}
input Pagination {
skip: Int @constraint(minimum: 0)
take: Int @constraint(minimum: 1)
}
await fastify.register(mercurius, {
schema,
resolvers,
path: "/graphql",
graphiql: false
});
await fastify.register(mercuriusValidation);
// From another plugin
fastify.graphql.extendSchema(schema);
ERROR: onGatewayReplaceSchema hook not supported! thrown
UPD. Found a workaround by setting directiveValidation: false
, in my case it doesn't matter as I don't use directive mercurius validation.
For gql type CreateInput
args nums
and description
are optional, so we can pass { nums: null, description: null }
in CreateInput
:
input CreateInput {
description: String
nums: [Int!]
}
Validation:
CreateInput : {
nums: {
type: 'array',
nullable: true,
maxItems: 10,
uniqueItems: true,
items: { type: 'integer', minimum: 0, maximum: 9 },
},
description: { type: 'string', maxLength: 1000 }
},
For some reason I get error when { nums: null }
is passed as argument while { description: null }
or { nums: [] }
works:
"message": "Failed Validation on arguments for field 'Mutation.smthCreate'",
"stack":
ValidationError: Failed Validation on arguments for field 'Mutation.smthCreate'
at node_modules\.pnpm\[email protected]\node_modules\mercurius-validation\lib\validators\validator.js:32:15
at executeField (node_modules\.pnpm\[email protected]\node_modules\graphql\execution\execute.js:481:20)
at node_modules\.pnpm\[email protected]\node_modules\graphql\execution\execute.js:377:22
at promiseReduce (node_modules\.pnpm\[email protected]\node_modules\graphql\jsutils\promiseReduce.js:23:9)
at executeFieldsSerially (node_modules\.pnpm\[email protected]\node_modules\graphql\execution\execute.js:373:43)
at executeOperation (node_modules\.pnpm\[email protected]\node_modules\graphql\execution\execute.js:347:14)
at execute (node_modules\.pnpm\[email protected]\node_modules\graphql\execution\execute.js:136:20)
at Object.fastifyGraphQl [as graphql] (node_modules\.pnpm\[email protected][email protected]\node_modules\mercurius\index.js:654:29)
at _Reply.graphql (node_modules\.pnpm\[email protected][email protected]\node_modules\mercurius\index.js:340:16)
at executeQuery (node_modules\.pnpm\[email protected][email protected]\node_modules\mercurius\lib\routes.js:224:18)
"path": [
"smthCreate"
],
"locations": [
{
"line": 3,
"column": 3
}
],
"extensions": {
"name": "ValidationError",
"details": [
{
"instancePath": "/input/nums",
"schemaPath": "https://mercurius.dev/validation/CreateInput/properties/nums/type",
"keyword": "type",
"params": {
"type": "array"
},
"message": "must be array",
"schema": "array",
"parentSchema": {
"type": "array",
"maxItems": 10,
"uniqueItems": true,
"items": {
"type": "integer",
"minimum": 0,
"maximum": 9
},
"$id": "https://mercurius.dev/validation/CreateInput/nums"
},
"data": null
}
]
}
}
Hey! Opening up an issue here to discuss a basic initial implementation of the plugin off the back of: mercurius-js/mercurius#509
Current state of play:
@mcollina when you discussed with @simone-sanfratello about writing a validation plugin, did you talk about any alternative approaches that could be worth looking at?
as titled
Make it able to add custom scalar inferring types, so far it only support 3 types
GraphQLString <=> { type: 'string' }
GraphQLInt <=> { type: 'integer' }
GraphQLFloat <=> { type: 'number' }
Validation errors mean the client sent something invalid, so they should result in a 400 status code but instead they result in a 500 status code.
Library versions:
Example:
HTTP/1.1 500 Internal Server Error
cache-control: no-cache
content-type: application/json; charset=utf-8
content-length: 605
Date: Wed, 29 Jun 2022 19:36:33 GMT
Connection: close
{
"errors": [
{
"message": "Failed Validation on arguments for field 'Query.uploadFile'",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"uploadFile"
],
"extensions": {
"name": "ValidationError",
"code": "MER_VALIDATION_ERR_FAILED_VALIDATION",
"details": [
{
"instancePath": "/key/name",
"schemaPath": "https://mercurius.dev/validation/FileKey/properties/name/pattern",
"keyword": "pattern",
"params": {
"pattern": "^[^/]+$"
},
"message": "must match pattern \"^[^/]+$\"",
"schema": "^[^/]+$",
"parentSchema": {
"pattern": "^[^/]+$",
"type": "string",
"$id": "https://mercurius.dev/validation/FileKey/name"
},
"data": "foo/icon.png"
}
]
}
}
],
"data": null
}
According to GraphQL spec optional input values (that is, the one without exclamation mark) can receive a null value that is different than not providing any input (see http://spec.graphql.org/October2021/#sec-Null-Value).
Mercurius supports this behaviour and will correctly transform any null value input to null.
mercurius-validation instead transforms the null value into an empty string.
This is because:
The problem is mercurius-validation is inferring the wrong type and not taking nullable types into consideration.
The inferJSONSchemaType
functionion (https://github.com/mercurius-js/validation/blob/main/lib/utils.js#L38-L49) should return different json schema types based on whether the original GraphQL type was nullable or not.
I.e. { type: 'string' }
for String!
and { type: ['string', 'null'] }
for String
.
This issue may be caused by getTypeInfo
(https://github.com/mercurius-js/validation/blob/main/lib/utils.js#L51-L54) which removes the nullable information from the type.
Code to reproduce the issue: https://gist.github.com/paolochiodi/93a75b1b1cd551a745b6d8d77f83e1a4
Expected behaviour: no failure
Current behaviour: returns error due to assertion failing.
Removing Mercurius-validation by commenting out line https://gist.github.com/paolochiodi/93a75b1b1cd551a745b6d8d77f83e1a4#file-index-js-L29 will make the code run
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.