{"id":13700865,"url":"https://github.com/confuser/graphql-constraint-directive","last_synced_at":"2025-09-20T04:49:46.210Z","repository":{"id":32435619,"uuid":"133671294","full_name":"confuser/graphql-constraint-directive","owner":"confuser","description":"Validate GraphQL fields","archived":false,"fork":false,"pushed_at":"2025-09-06T18:57:30.000Z","size":707,"stargazers_count":573,"open_issues_count":44,"forks_count":74,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-09-06T20:39:20.336Z","etag":null,"topics":["constraint","directive","graphql","nodejs","validation","validator"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/confuser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-05-16T13:39:48.000Z","updated_at":"2025-08-09T15:44:53.000Z","dependencies_parsed_at":"2024-04-25T02:30:37.307Z","dependency_job_id":"90ba2cef-cd3e-48e9-856c-d2c94650b2a6","html_url":"https://github.com/confuser/graphql-constraint-directive","commit_stats":{"total_commits":142,"total_committers":35,"mean_commits":4.057142857142857,"dds":0.704225352112676,"last_synced_commit":"ab74e81f7583f2cce7ee4f22862952398fdb2faf"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/confuser/graphql-constraint-directive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confuser%2Fgraphql-constraint-directive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confuser%2Fgraphql-constraint-directive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confuser%2Fgraphql-constraint-directive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confuser%2Fgraphql-constraint-directive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/confuser","download_url":"https://codeload.github.com/confuser/graphql-constraint-directive/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confuser%2Fgraphql-constraint-directive/sbom","scorecard":{"id":302403,"data":{"date":"2025-08-11","repo":{"name":"github.com/confuser/graphql-constraint-directive","commit":"e81aa64bdb158a20f1c36e275912c9f4bc1bbebc"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":4,"reason":"5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yaml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/confuser/graphql-constraint-directive/build.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yaml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/confuser/graphql-constraint-directive/build.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yaml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/confuser/graphql-constraint-directive/build.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yaml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/confuser/graphql-constraint-directive/build.yaml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yaml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/confuser/graphql-constraint-directive/build.yaml/master?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   1 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: ISC License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"11 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-9pv7-vfvm-6vr7","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-c76h-2ccp-4975","Warn: Project is vulnerable to: GHSA-cxrh-j4jr-qwg3"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T21:02:10.523Z","repository_id":32435619,"created_at":"2025-08-17T21:02:10.523Z","updated_at":"2025-08-17T21:02:10.523Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276047233,"owners_count":25575881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-20T02:00:10.207Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constraint","directive","graphql","nodejs","validation","validator"],"created_at":"2024-08-02T20:01:03.894Z","updated_at":"2025-09-20T04:49:46.176Z","avatar_url":"https://github.com/confuser.png","language":"JavaScript","funding_links":[],"categories":["Implementations","JavaScript"],"sub_categories":["JavaScript/TypeScript"],"readme":"# graphql-constraint-directive\n\n[![Build Status](https://github.com/confuser/graphql-constraint-directive/actions/workflows/build.yaml/badge.svg)](https://github.com/confuser/graphql-constraint-directive/actions/workflows/build.yaml)\n[![Coverage Status](https://coveralls.io/repos/github/confuser/graphql-constraint-directive/badge.svg?branch=master)](https://coveralls.io/github/confuser/graphql-constraint-directive?branch=master)\n[![Known Vulnerabilities](https://snyk.io/test/github/confuser/graphql-constraint-directive/badge.svg?targetFile=package.json)](https://snyk.io/test/github/confuser/graphql-constraint-directive?targetFile=package.json)\n\nAllows using @constraint as a directive to validate input data. Inspired by [Constraints Directives RFC](https://github.com/APIs-guru/graphql-constraints-spec) and OpenAPI\n\n## Install\n```\nnpm install graphql-constraint-directive\n```\n\nFor GraphQL v15 and below, use v2 of this package\n\n```\nnpm install graphql-constraint-directive@v2\n```\n\n## Usage\nThere are multiple ways to make use of the constraint directive in your project. Below outlines the benefits and caveats. Please choose the most appropriate to your use case.\n\n### Schema wrapper\n\nImplementation based on schema wrappers - basic scalars are wrapped as custom scalars with validations.\n\n#### Benefits\n* based on `graphql` library, works everywhere\n* posibility to also validate GraphQL response data\n\n#### Caveats\n* modifies GraphQL schema, basic scalars (Int, Float, String) are replaced by custom scalars\n\n```js\nconst { constraintDirective, constraintDirectiveTypeDefs } = require('graphql-constraint-directive')\nconst express = require('express')\nconst { ApolloServer } = require('apollo-server-express')\nconst { makeExecutableSchema } = require('@graphql-tools/schema')\nconst typeDefs = `\n  type Query {\n    books: [Book]\n  }\n  type Book {\n    title: String\n  }\n  type Mutation {\n    createBook(input: BookInput): Book\n  }\n  input BookInput {\n    title: String! @constraint(minLength: 5, format: \"email\")\n  }`\n\nlet schema = makeExecutableSchema({\n  typeDefs: [constraintDirectiveTypeDefs, typeDefs],\n})\nschema = constraintDirective()(schema)\n\nconst app = express()\nconst server = new ApolloServer({ schema })\n\nawait server.start()\n\nserver.applyMiddleware({ app })\n\n```\n\n### Server plugin\n\nImplementation based on server plugin. Common server plugins are implemented,\nfunction `validateQuery(schema, query, variables, operationName)` can be used to implement additional plugins.\n\n#### Benefits\n* schema stays unmodified\n\n#### Caveats\n* runs only in supported servers\n* validates only GraphQL query, not response data\n\n#### Envelop\n\nUse as an [Envelop plugin](https://www.envelop.dev) in supported frameworks, e.g. [GraphQL Yoga](https://www.graphql-yoga.com/).\nFunctionality is plugged in `execute` phase\n\nThis plugin requires the following dependencies installed in your project:\n* `@envelop/core` - `^2.0.0`\n\n```js\nconst { createEnvelopQueryValidationPlugin, constraintDirectiveTypeDefs } = require('graphql-constraint-directive')\nconst express = require('express')\nconst { createServer } = require('@graphql-yoga/node')\nconst { makeExecutableSchema } = require('@graphql-tools/schema')\n\nconst typeDefs = `\n  type Query {\n    books: [Book]\n  }\n  type Book {\n    title: String\n  }\n  type Mutation {\n    createBook(input: BookInput): Book\n  }\n  input BookInput {\n    title: String! @constraint(minLength: 5, format: \"email\")\n  }`\n\nlet schema = makeExecutableSchema({\n  typeDefs: [constraintDirectiveTypeDefs, typeDefs],\n})\n\nconst app = express()\n\nconst yoga = createServer({\n    schema,\n    plugins: [createEnvelopQueryValidationPlugin()],\n    graphiql: false\n})\n\napp.use('/', yoga)\n\napp.listen(4000);\n```\n\n#### Apollo 3 Server\n\nAs an [Apollo 3 Server](https://www.apollographql.com/docs/apollo-server/v3) plugin\n\nThis plugin requires the following dependencies installed in your project:\n* dependencies required for your selected Apollo Server 3 variant\n\n```js\nconst { createApolloQueryValidationPlugin, constraintDirectiveTypeDefs } = require('graphql-constraint-directive')\nconst express = require('express')\nconst { ApolloServer } = require('apollo-server-express')\nconst { makeExecutableSchema } = require('@graphql-tools/schema')\n\nconst typeDefs = `\n  type Query {\n    books: [Book]\n  }\n  type Book {\n    title: String\n  }\n  type Mutation {\n    createBook(input: BookInput): Book\n  }\n  input BookInput {\n    title: String! @constraint(minLength: 5, format: \"email\")\n  }`\n\nlet schema = makeExecutableSchema({\n  typeDefs: [constraintDirectiveTypeDefs, typeDefs],\n})\n\nconst plugins = [\n  createApolloQueryValidationPlugin({\n    schema\n  })\n]\n\nconst app = express()\nconst server = new ApolloServer({\n  schema,\n  plugins\n})\n\nawait server.start()\n\nserver.applyMiddleware({ app })\n```\n\n#### Apollo 4 Server\n\nAs an [Apollo 4 Server](https://www.apollographql.com/docs/apollo-server/v4) plugin\n\nThis plugin requires the following dependencies installed in your project:\n* `@apollo/server` - `^4.0.0`\n* `graphql-tag` - `^2.0.0`\n\n```js\nconst { createApollo4QueryValidationPlugin, constraintDirectiveTypeDefs } = require('graphql-constraint-directive/apollo4')\nconst { ApolloServer } = require('@apollo/server')\nconst { startStandaloneServer } = require('@apollo/server/standalone');\nconst { makeExecutableSchema } = require('@graphql-tools/schema')\n\nconst typeDefs = `\n  type Query {\n    books: [Book]\n  }\n  type Book {\n    title: String\n  }\n  type Mutation {\n    createBook(input: BookInput): Book\n  }\n  input BookInput {\n    title: String! @constraint(minLength: 5, format: \"email\")\n  }`\n\nlet schema = makeExecutableSchema({\n  typeDefs: [constraintDirectiveTypeDefs, typeDefs],\n})\n\nconst plugins = [\n  createApollo4QueryValidationPlugin()\n]\n\nconst server = new ApolloServer({\n  schema,\n  plugins\n})\n\nawait startStandaloneServer(server);\n```\n#### Apollo 4 Subgraph server\n\nThere is a small change required to make the Apollo Server quickstart work when trying to build an [Apollo Subgraph Server](https://www.apollographql.com/docs/federation/building-supergraphs/subgraphs-apollo-server/).\nWe must use the `buildSubgraphSchema` function to build a schema that can be passed to an Apollo Gateway/supergraph, instead of `makeExecuteableSchema`. This uses `makeExecutableSchema` under the hood.\n\nThis plugin requires the following dependencies installed in your project:\n* `@apollo/server` - `^4.0.0`\n* `graphql-tag` - `^2.0.0`\n\n```ts\nimport { ApolloServer } from '@apollo/server';\nimport { startStandaloneServer } from '@apollo/server/standalone';\nimport { buildSubgraphSchema } from '@apollo/subgraph';\nimport { createApollo4QueryValidationPlugin, constraintDirectiveTypeDefsGql } from 'graphql-constraint-directive/apollo4';\n\nconst typeDefs = gql`\n  extend schema @link(url: \"https://specs.apollo.dev/federation/v2.0\", import: [\"@key\", \"@shareable\"])\n\n  type Query {\n    books: [Book]\n  }\n  type Book {\n    title: String\n  }\n  type Mutation {\n    createBook(input: BookInput): Book\n  }\n  input BookInput {\n    title: String! @constraint(minLength: 5, format: \"email\")\n  }\n`;\n\nconst schema = buildSubgraphSchema({\n  typeDefs: [constraintDirectiveTypeDefsGql, typeDefs]\n});\n\nconst plugins = [\n  createApollo4QueryValidationPlugin()\n]\n\nconst server = new ApolloServer({\n  schema,\n  plugins\n});\n\nawait startStandaloneServer(server);\n```\n\n#### Express\n\n*This implementation is untested now, as [`express-graphql` module](https://github.com/graphql/express-graphql) is not maintained anymore.*\n\nAs a [Validation rule](https://graphql.org/graphql-js/validation/) when query `variables` are available\n\n```js\nconst { createQueryValidationRule, constraintDirectiveTypeDefs } = require('graphql-constraint-directive')\nconst express = require('express')\nconst { graphqlHTTP } = require('express-graphql')\nconst { makeExecutableSchema } = require('@graphql-tools/schema')\n\nconst typeDefs = `\n  type Query {\n    books: [Book]\n  }\n  type Book {\n    title: String\n  }\n  type Mutation {\n    createBook(input: BookInput): Book\n  }\n  input BookInput {\n    title: String! @constraint(minLength: 5, format: \"email\")\n  }`\n\nlet schema = makeExecutableSchema({\n  typeDefs: [constraintDirectiveTypeDefs, typeDefs],\n})\n\nconst app = express()\n\napp.use(\n  '/api',\n  graphqlHTTP(async (request, response, { variables }) =\u003e ({\n    schema,\n    validationRules: [\n      createQueryValidationRule({\n        variables\n      })\n    ]\n  }))\n)\napp.listen(4000);\n\n```\n### Schema documentation\n\nYou can use the provided schema transformation to automatically add `@constraint` documentation into fields and arguments descriptions. By default directives are not typically present in the exposed introspected schema\n\n```js\nconst { constraintDirectiveTypeDefs, constraintDirectiveDocumentation } = require('graphql-constraint-directive')\nconst { makeExecutableSchema } = require('@graphql-tools/schema')\n\nconst typeDefs = ...\n\nlet schema = makeExecutableSchema({\n      typeDefs: [constraintDirectiveTypeDefs, typeDefs]\n})\n\nschema = constraintDirectiveDocumentation()(schema);\n\n// any constraint directive handler implementation\n```\n\nThis transformation appends `constraint documentation header`, and then a list of `constraint conditions descriptions` to the description of each field and argument where the `@constraint` directive is used.\n\nOriginal schema:\n```graphql\n\"\"\"\nExisting field or argument description.\n\"\"\"\nfieldOrArgument: String @constraint(minLength: 10, maxLength: 50)\n```\n\nTransformed schema:\n```graphql\n\"\"\"\nExisting field or argument description.\n\n*Constraints:*\n* Minimum length: `10`\n* Maximum length: `50`\n\"\"\"\nfieldOrArgument: String @constraint(minLength: 10, maxLength: 50)\n```\n\n[CommonMark](https://spec.commonmark.org) is used in the desccription for better readability.\n\nIf `constraint documentation header` already exists in the field or argument description, then\nconstraint documentation is not appended. This allows you to override constraint description\nwhen necessary, or use this in a chain of subgraph/supergraph schemes.\n\nBoth `constraint documentation header` and `constraint conditions descriptions` can be customized\nduring the transformation creation, eg. to localize them.\n\n```js\nschema = constraintDirectiveDocumentation(\n  {\n    header: '*Changed header:*',\n    descriptionsMap: {\n      minLength: 'Changed Minimum length',\n      maxLength: 'Changed Maximum length',\n      startsWith: 'Changed Starts with',\n      endsWith: 'Changed Ends with',\n      contains: 'Changed Contains',\n      notContains: 'Changed Doesn\\'t contain',\n      pattern: 'Changed Must match RegEx pattern',\n      format: 'Changed Must match format',\n      min: 'Changed Minimum value',\n      max: 'Changed Maximum value',\n      exclusiveMin: 'Changed Grater than',\n      exclusiveMax: 'Changed Less than',\n      multipleOf: 'Changed Must be a multiple of',\n      minItems: 'Changed Minimum number of items',\n      maxItems: 'Changed Maximum number of items'\n    }\n  }\n)(schema);\n```\n\n\n## API\n### String\n#### minLength\n```@constraint(minLength: 5)```\nRestrict to a minimum length\n\n#### maxLength\n```@constraint(maxLength: 5)```\nRestrict to a maximum length\n\n#### startsWith\n```@constraint(startsWith: \"foo\")```\nEnsure value starts with foo\n\n#### endsWith\n```@constraint(endsWith: \"foo\")```\nEnsure value ends with foo\n\n#### contains\n```@constraint(contains: \"foo\")```\nEnsure value contains foo\n\n#### notContains\n```@constraint(notContains: \"foo\")```\nEnsure value does not contain foo\n\n#### pattern\n```@constraint(pattern: \"^[0-9a-zA-Z]*$\")```\nEnsure value matches regex, e.g. alphanumeric\n\n#### format\n```@constraint(format: \"email\")```\nEnsure value is in a particular format\n\nSupported formats:\n- byte: Base64\n- date-time: RFC 3339\n- date: ISO 8601\n- email\n- ipv4\n- ipv6\n- uri\n- uuid\n\n#### Custom Format\nYou can add your own custom formats by passing a `formats` object to the plugin options. See example below.\n\n```@constraint(format: \"my-custom-format\")```\n\n```js\nconst formats = {\n  'my-custom-format': (value) =\u003e {\n    if (value === 'foo') {\n      return true\n    }\n\n    throw new GraphQLError('Value must be foo')\n  }\n};\n\n// Envelop\ncreateEnvelopQueryValidationPlugin({ formats })\n\n// Apollo 3 Server\ncreateApolloQueryValidationPlugin({ formats })\n\n// Apollo 4 Server\ncreateApollo4QueryValidationPlugin({ formats })\n```\n\n### Int/Float\n#### min\n```@constraint(min: 3)```\nEnsure value is greater than or equal to\n\n#### max\n```@constraint(max: 3)```\nEnsure value is less than or equal to\n\n#### exclusiveMin\n```@constraint(exclusiveMin: 3)```\nEnsure value is greater than\n\n#### exclusiveMax\n```@constraint(exclusiveMax: 3)```\nEnsure value is less than\n\n#### multipleOf\n```@constraint(multipleOf: 10)```\nEnsure value is a multiple\n\n### Array/List\n\n#### minItems\n```@constraint(minItems: 3)```\nRestrict array/List to a minimum length\n\n#### maxItems\n```@constraint(maxItems: 3)```\nRestrict array/List to a maximum length\n\n### ConstraintDirectiveError\nEach validation error throws a `ConstraintDirectiveError`. Combined with a formatError function, this can be used to customise error messages.\n\n```js\n{\n  code: 'ERR_GRAPHQL_CONSTRAINT_VALIDATION',\n  fieldName: 'theFieldName',\n  context: [ { arg: 'argument name which failed', value: 'value of argument' } ]\n}\n```\n\n```js\nconst formatError = function (error) {\n  const code = error?.originalError?.originalError?.code || error?.originalError?.code || error?.code\n  if (code === 'ERR_GRAPHQL_CONSTRAINT_VALIDATION') {\n    // return a custom object\n  }\n\n  return error\n}\n\napp.use('/graphql', bodyParser.json(), graphqlExpress({ schema, formatError }))\n\n```\n\n#### Apollo Server 3\nThrows a [`UserInputError`](https://www.apollographql.com/docs/apollo-server/data/errors/#bad_user_input) for each validation error.\n\n#### Apollo Server 4\nThrows a prefilled `GraphQLError` with `extensions.code` set to `BAD_USER_INPUT` and http status code `400`.\nIn case of more validation errors, top level error is generic with `Query is invalid, for details see extensions.validationErrors` message,\ndetailed errors are stored in `extensions.validationErrors` of this error.\n\n#### Envelop\nThe Envelop plugin throws a prefilled `GraphQLError` for each validation error.\n\n### uniqueTypeName\n```@constraint(uniqueTypeName: \"Unique_Type_Name\")```\nOverride the unique type name generate by the library to the one passed as an argument.\nHas meaning only for `Schema wrapper` implementation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconfuser%2Fgraphql-constraint-directive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconfuser%2Fgraphql-constraint-directive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconfuser%2Fgraphql-constraint-directive/lists"}