diff --git a/.eslintrc.yml b/.eslintrc.yml index 61b353521a..8e20c1ae72 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -449,9 +449,17 @@ overrides: project: ['tsconfig.json'] plugins: - '@typescript-eslint' + - 'eslint-plugin-tsdoc' extends: - plugin:import/typescript rules: + ########################################################################## + # `eslint-plugin-tsdoc` rule list based on `v0.2.x` + # https://github.com/microsoft/tsdoc/tree/master/eslint-plugin + ########################################################################## + + tsdoc/syntax: error + ########################################################################## # `@typescript-eslint/eslint-plugin` rule list based on `v4.28.x` ########################################################################## diff --git a/package-lock.json b/package-lock.json index 9f5faf5dce..aa4e3e4a14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "eslint-plugin-internal-rules": "file:./resources/eslint-internal-rules", "eslint-plugin-istanbul": "0.1.2", "eslint-plugin-node": "11.1.0", + "eslint-plugin-tsdoc": "0.2.14", "mocha": "9.0.1", "nyc": "15.1.0", "prettier": "2.3.2", @@ -2007,6 +2008,37 @@ "node": ">=8" } }, + "node_modules/@microsoft/tsdoc": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", + "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@microsoft/tsdoc-config/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3599,6 +3631,16 @@ "node": ">= 4" } }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", + "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "0.15.2" + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -4934,6 +4976,12 @@ "node": ">=12.0.0" } }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8920,6 +8968,36 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@microsoft/tsdoc": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", + "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + }, + "dependencies": { + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -10214,6 +10292,16 @@ } } }, + "eslint-plugin-tsdoc": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", + "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "0.15.2" + } + }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -11078,6 +11166,12 @@ "integrity": "sha512-efkLePxXjJk92hvN+2rS3tGJTRn8/tqXjmZvPI6LQ29xCj2sUF4zW8hkMsVe3jpTkxtMZ89xsKnz9FaRqNWM6g==", "dev": true }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 4559066cc8..df1ff4444d 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "eslint-plugin-internal-rules": "file:./resources/eslint-internal-rules", "eslint-plugin-istanbul": "0.1.2", "eslint-plugin-node": "11.1.0", + "eslint-plugin-tsdoc": "0.2.14", "mocha": "9.0.1", "nyc": "15.1.0", "prettier": "2.3.2", diff --git a/src/__testUtils__/dedent.ts b/src/__testUtils__/dedent.ts index 6a5e51b622..7fc6b46345 100644 --- a/src/__testUtils__/dedent.ts +++ b/src/__testUtils__/dedent.ts @@ -19,12 +19,14 @@ export function dedentString(string: string): string { * An ES6 string tag that fixes indentation and also trims string. * * Example usage: + * ```ts * const str = dedent` * { * test * } * `; * str === "{\n test\n}"; + * ``` */ export function dedent( strings: ReadonlyArray, diff --git a/src/__tests__/starWarsSchema.ts b/src/__tests__/starWarsSchema.ts index e915c98f39..2cc586a6ac 100644 --- a/src/__tests__/starWarsSchema.ts +++ b/src/__tests__/starWarsSchema.ts @@ -27,6 +27,7 @@ import { getFriends, getHero, getHuman, getDroid } from './starWarsData'; * Using our shorthand to describe type systems, the type system for our * Star Wars example is: * + * ```graphql * enum Episode { NEW_HOPE, EMPIRE, JEDI } * * interface Character { @@ -57,6 +58,7 @@ import { getFriends, getHero, getHuman, getDroid } from './starWarsData'; * human(id: String!): Human * droid(id: String!): Droid * } + * ``` * * We begin by setting up our schema. */ @@ -65,7 +67,9 @@ import { getFriends, getHero, getHuman, getDroid } from './starWarsData'; * The original trilogy consists of three movies. * * This implements the following type system shorthand: - * enum Episode { NEW_HOPE, EMPIRE, JEDI } + * ```graphql + * enum Episode { NEW_HOPE, EMPIRE, JEDI } + * ``` */ const episodeEnum = new GraphQLEnumType({ name: 'Episode', @@ -90,13 +94,15 @@ const episodeEnum = new GraphQLEnumType({ * Characters in the Star Wars trilogy are either humans or droids. * * This implements the following type system shorthand: - * interface Character { - * id: String! - * name: String - * friends: [Character] - * appearsIn: [Episode] - * secretBackstory: String - * } + * ```graphql + * interface Character { + * id: String! + * name: String + * friends: [Character] + * appearsIn: [Episode] + * secretBackstory: String + * } + * ``` */ const characterInterface: GraphQLInterfaceType = new GraphQLInterfaceType({ name: 'Character', @@ -141,13 +147,15 @@ const characterInterface: GraphQLInterfaceType = new GraphQLInterfaceType({ * We define our human type, which implements the character interface. * * This implements the following type system shorthand: - * type Human : Character { - * id: String! - * name: String - * friends: [Character] - * appearsIn: [Episode] - * secretBackstory: String - * } + * ```graphql + * type Human : Character { + * id: String! + * name: String + * friends: [Character] + * appearsIn: [Episode] + * secretBackstory: String + * } + * ``` */ const humanType = new GraphQLObjectType({ name: 'Human', @@ -190,14 +198,16 @@ const humanType = new GraphQLObjectType({ * The other type of character in Star Wars is a droid. * * This implements the following type system shorthand: - * type Droid : Character { - * id: String! - * name: String - * friends: [Character] - * appearsIn: [Episode] - * secretBackstory: String - * primaryFunction: String - * } + * ```graphql + * type Droid : Character { + * id: String! + * name: String + * friends: [Character] + * appearsIn: [Episode] + * secretBackstory: String + * primaryFunction: String + * } + * ``` */ const droidType = new GraphQLObjectType({ name: 'Droid', @@ -243,12 +253,13 @@ const droidType = new GraphQLObjectType({ * of the Star Wars trilogy, R2-D2, directly. * * This implements the following type system shorthand: - * type Query { - * hero(episode: Episode): Character - * human(id: String!): Human - * droid(id: String!): Droid - * } - * + * ```graphql + * type Query { + * hero(episode: Episode): Character + * human(id: String!): Human + * droid(id: String!): Droid + * } + * ``` */ const queryType = new GraphQLObjectType({ name: 'Query', diff --git a/src/error/GraphQLError.ts b/src/error/GraphQLError.ts index 89a82eef29..0e0c5dcb74 100644 --- a/src/error/GraphQLError.ts +++ b/src/error/GraphQLError.ts @@ -15,7 +15,7 @@ import { printLocation, printSourceLocation } from '../language/printLocation'; */ export class GraphQLError extends Error { /** - * An array of { line, column } locations within the source GraphQL document + * An array of `{ line, column }` locations within the source GraphQL document * which correspond to this error. * * Errors during validation often contain multiple locations, for example to diff --git a/src/error/formatError.ts b/src/error/formatError.ts index bc4cfed85c..259f24e559 100644 --- a/src/error/formatError.ts +++ b/src/error/formatError.ts @@ -21,7 +21,7 @@ export function formatError(error: GraphQLError): GraphQLFormattedError { } /** - * @see https://github.com/graphql/graphql-spec/blob/master/spec/Section%207%20--%20Response.md#errors + * See: https://spec.graphql.org/draft/#sec-Errors */ export interface GraphQLFormattedError { /** diff --git a/src/execution/collectFields.ts b/src/execution/collectFields.ts index 2da9440969..4d41b6803c 100644 --- a/src/execution/collectFields.ts +++ b/src/execution/collectFields.ts @@ -106,8 +106,8 @@ export function collectFields( } /** - * Determines if a field should be included based on the @include and @skip - * directives, where @skip has higher precedence than @include. + * Determines if a field should be included based on the `@include` and `@skip` + * directives, where `@skip` has higher precedence than `@include`. */ function shouldIncludeNode( variableValues: { [variable: string]: unknown }, diff --git a/src/execution/execute.ts b/src/execution/execute.ts index 4d7bc386db..f092a6a797 100644 --- a/src/execution/execute.ts +++ b/src/execution/execute.ts @@ -71,9 +71,9 @@ import { collectFields } from './collectFields'; * * "Selections" are the definitions that can appear legally and at * single level of the query. These include: - * 1) field references e.g "a" - * 2) fragment "spreads" e.g. "...c" - * 3) inline fragment "spreads" e.g. "...on Type { a }" + * 1) field references e.g `a` + * 2) fragment "spreads" e.g. `...c` + * 3) inline fragment "spreads" e.g. `...on Type { a }` */ /** @@ -201,7 +201,7 @@ export function executeSync(args: ExecutionArgs): ExecutionResult { } /** - * Given a completed execution context and data, build the { errors, data } + * Given a completed execution context and data, build the `{ errors, data }` * response defined by the "Response" section of the GraphQL specification. */ function buildResponse( diff --git a/src/index.ts b/src/index.ts index b9aec6a43a..be0eda9b0f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,8 +18,10 @@ * You may also import from each sub-directory directly. For example, the * following two import statements are equivalent: * - * import { parse } from 'graphql'; - * import { parse } from 'graphql/language'; + * ```ts + * import { parse } from 'graphql'; + * import { parse } from 'graphql/language'; + * ``` */ /** The GraphQL.js version info. */ diff --git a/src/jsutils/isIterableObject.ts b/src/jsutils/isIterableObject.ts index ac0cd2576c..5c9d6fb381 100644 --- a/src/jsutils/isIterableObject.ts +++ b/src/jsutils/isIterableObject.ts @@ -7,12 +7,13 @@ * TypedArray, etc. but excludes string literals. * * @example - * + * ```ts * isIterableObject([ 1, 2, 3 ]) // true * isIterableObject(new Map()) // true * isIterableObject('ABC') // false * isIterableObject({ key: 'value' }) // false * isIterableObject({ length: 1, 0: 'Alpha' }) // false + * ``` */ export function isIterableObject( maybeIterable: any, diff --git a/src/jsutils/keyMap.ts b/src/jsutils/keyMap.ts index 2425850b06..592a98c83d 100644 --- a/src/jsutils/keyMap.ts +++ b/src/jsutils/keyMap.ts @@ -6,22 +6,26 @@ import type { ObjMap } from './ObjMap'; * * This provides a convenient lookup for the array items if the key function * produces unique results. + * ```ts + * const phoneBook = [ + * { name: 'Jon', num: '555-1234' }, + * { name: 'Jenny', num: '867-5309' } + * ] * - * const phoneBook = [ - * { name: 'Jon', num: '555-1234' }, - * { name: 'Jenny', num: '867-5309' } - * ] + * const entriesByName = keyMap( + * phoneBook, + * entry => entry.name + * ) * - * // { Jon: { name: 'Jon', num: '555-1234' }, - * // Jenny: { name: 'Jenny', num: '867-5309' } } - * const entriesByName = keyMap( - * phoneBook, - * entry => entry.name - * ) + * // { + * // Jon: { name: 'Jon', num: '555-1234' }, + * // Jenny: { name: 'Jenny', num: '867-5309' } + * // } * - * // { name: 'Jenny', num: '857-6309' } - * const jennyEntry = entriesByName['Jenny'] + * const jennyEntry = entriesByName['Jenny'] * + * // { name: 'Jenny', num: '857-6309' } + * ``` */ export function keyMap( list: ReadonlyArray, diff --git a/src/jsutils/keyValMap.ts b/src/jsutils/keyValMap.ts index c6013aaa16..94d688c2c1 100644 --- a/src/jsutils/keyValMap.ts +++ b/src/jsutils/keyValMap.ts @@ -3,19 +3,19 @@ import type { ObjMap } from './ObjMap'; /** * Creates a keyed JS object from an array, given a function to produce the keys * and a function to produce the values from each item in the array. + * ```ts + * const phoneBook = [ + * { name: 'Jon', num: '555-1234' }, + * { name: 'Jenny', num: '867-5309' } + * ] * - * const phoneBook = [ - * { name: 'Jon', num: '555-1234' }, - * { name: 'Jenny', num: '867-5309' } - * ] - * - * // { Jon: '555-1234', Jenny: '867-5309' } - * const phonesByName = keyValMap( - * phoneBook, - * entry => entry.name, - * entry => entry.num - * ) - * + * // { Jon: '555-1234', Jenny: '867-5309' } + * const phonesByName = keyValMap( + * phoneBook, + * entry => entry.name, + * entry => entry.num + * ) + * ``` */ export function keyValMap( list: ReadonlyArray, diff --git a/src/language/lexer.ts b/src/language/lexer.ts index 53f6544acc..5fdb6466ef 100644 --- a/src/language/lexer.ts +++ b/src/language/lexer.ts @@ -108,11 +108,13 @@ export function isPunctuatorTokenKind(kind: TokenKindEnum): boolean { } /** + * ``` * SourceCharacter :: * - U+0009 (Horizontal Tab) * - U+000A (New Line) * - U+000D (Carriage Return) * - U+0020-U+FFFF + * ``` */ function isSourceCharacter(code: number): boolean { return ( @@ -296,9 +298,11 @@ function readNextToken(lexer: Lexer, start: number): Token { /** * Reads a comment token from the source file. * + * ``` * Comment :: # CommentChar* [lookahead != CommentChar] * * CommentChar :: SourceCharacter but not LineTerminator + * ``` */ function readComment(lexer: Lexer, start: number): Token { const body = lexer.source.body; @@ -334,6 +338,7 @@ function readComment(lexer: Lexer, start: number): Token { * Reads a number token from the source file, either a FloatValue or an IntValue * depending on whether a FractionalPart or ExponentPart is encountered. * + * ``` * IntValue :: IntegerPart [lookahead != {Digit, `.`, NameStart}] * * IntegerPart :: @@ -356,6 +361,7 @@ function readComment(lexer: Lexer, start: number): Token { * ExponentIndicator :: one of `e` `E` * * Sign :: one of + - + * ``` */ function readNumber(lexer: Lexer, start: number, firstCode: number): Token { const body = lexer.source.body; @@ -458,6 +464,7 @@ function readDigits(lexer: Lexer, start: number, firstCode: number): number { /** * Reads a single-quote string token from the source file. * + * ``` * StringValue :: * - `""` [lookahead != `"`] * - `"` StringCharacter+ `"` @@ -470,6 +477,7 @@ function readDigits(lexer: Lexer, start: number, firstCode: number): number { * EscapedUnicode :: /[0-9A-Fa-f]{4}/ * * EscapedCharacter :: one of `"` `\` `/` `b` `f` `n` `r` `t` + * ``` */ function readString(lexer: Lexer, start: number): Token { const body = lexer.source.body; @@ -584,14 +592,14 @@ function readHexDigit(code: number): number { /** * | Escaped Character | Code Point | Character Name | * | ----------------- | ---------- | ---------------------------- | - * | {`"`} | U+0022 | double quote | - * | {`\`} | U+005C | reverse solidus (back slash) | - * | {`/`} | U+002F | solidus (forward slash) | - * | {`b`} | U+0008 | backspace | - * | {`f`} | U+000C | form feed | - * | {`n`} | U+000A | line feed (new line) | - * | {`r`} | U+000D | carriage return | - * | {`t`} | U+0009 | horizontal tab | + * | `"` | U+0022 | double quote | + * | `\` | U+005C | reverse solidus (back slash) | + * | `/` | U+002F | solidus (forward slash) | + * | `b` | U+0008 | backspace | + * | `f` | U+000C | form feed | + * | `n` | U+000A | line feed (new line) | + * | `r` | U+000D | carriage return | + * | `t` | U+0009 | horizontal tab | */ function readEscapedCharacter(lexer: Lexer, position: number): EscapeSequence { const body = lexer.source.body; @@ -627,12 +635,14 @@ function readEscapedCharacter(lexer: Lexer, position: number): EscapeSequence { /** * Reads a block string token from the source file. * + * ``` * StringValue :: * - `"""` BlockStringCharacter* `"""` * * BlockStringCharacter :: * - SourceCharacter but not `"""` or `\"""` * - `\"""` + * ``` */ function readBlockString(lexer: Lexer, start: number): Token { const body = lexer.source.body; @@ -706,6 +716,7 @@ function readBlockString(lexer: Lexer, start: number): Token { /** * Reads an alphanumeric + underscore name from the source. * + * ``` * Name :: * - NameStart NameContinue* [lookahead != NameContinue] * @@ -717,6 +728,7 @@ function readBlockString(lexer: Lexer, start: number): Token { * - Letter * - Digit * - `_` + * ``` */ function readName(lexer: Lexer, start: number): Token { const body = lexer.source.body; @@ -747,19 +759,23 @@ function isNameStart(code: number): boolean { } /** + * ``` * Digit :: one of * - `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` + * ``` */ function isDigit(code: number): boolean { return code >= 0x0030 && code <= 0x0039; } /** + * ``` * Letter :: one of * - `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` * - `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z` * - `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m` * - `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z` + * ``` */ function isLetter(code: number): boolean { return ( diff --git a/src/language/parser.ts b/src/language/parser.ts index f2807b5c1f..7095cad1d1 100644 --- a/src/language/parser.ts +++ b/src/language/parser.ts @@ -90,10 +90,11 @@ export interface ParseOptions { * * The syntax is identical to normal, query-defined variables. For example: * - * fragment A($var: Boolean = false) on T { - * ... - * } - * + * ```graphql + * fragment A($var: Boolean = false) on T { + * ... + * } + * ``` */ allowLegacyFragmentVariables?: boolean; } @@ -346,7 +347,9 @@ export class Parser { } /** + * ``` * SelectionSet : { Selection+ } + * ``` */ parseSelectionSet(): SelectionSetNode { return this.node(this._lexer.token, { @@ -616,9 +619,11 @@ export class Parser { } /** + * ``` * ObjectValue[Const] : * - { } * - { ObjectField[?Const]+ } + * ``` */ parseObject(isConst: true): ConstObjectValueNode; parseObject(isConst: boolean): ObjectValueNode; @@ -666,7 +671,9 @@ export class Parser { } /** + * ``` * Directive[Const] : @ Name Arguments[?Const]? + * ``` */ parseDirective(isConst: true): ConstDirectiveNode; parseDirective(isConst: boolean): DirectiveNode; @@ -782,7 +789,9 @@ export class Parser { } /** + * ``` * SchemaDefinition : Description? schema Directives[Const]? { OperationTypeDefinition+ } + * ``` */ parseSchemaDefinition(): SchemaDefinitionNode { const start = this._lexer.token; @@ -869,7 +878,9 @@ export class Parser { } /** + * ``` * FieldsDefinition : { FieldDefinition+ } + * ``` */ parseFieldsDefinition(): Array { return this.optionalMany( @@ -1011,7 +1022,9 @@ export class Parser { } /** + * ``` * EnumValuesDefinition : { EnumValueDefinition+ } + * ``` */ parseEnumValuesDefinition(): Array { return this.optionalMany( @@ -1060,7 +1073,9 @@ export class Parser { } /** + * ``` * InputFieldsDefinition : { InputValueDefinition+ } + * ``` */ parseInputFieldsDefinition(): Array { return this.optionalMany( @@ -1109,9 +1124,11 @@ export class Parser { } /** + * ``` * SchemaExtension : * - extend schema Directives[Const]? { OperationTypeDefinition+ } * - extend schema Directives[Const] + * ``` */ parseSchemaExtension(): SchemaExtensionNode { const start = this._lexer.token; @@ -1283,8 +1300,10 @@ export class Parser { } /** + * ``` * DirectiveDefinition : * - Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations + * ``` */ parseDirectiveDefinition(): DirectiveDefinitionNode { const start = this._lexer.token; diff --git a/src/language/printer.ts b/src/language/printer.ts index 0d907fca39..2134ea1ee6 100644 --- a/src/language/printer.ts +++ b/src/language/printer.ts @@ -316,8 +316,7 @@ function join( } /** - * Given array, print each item on its own line, wrapped in an - * indented "{ }" block. + * Given array, print each item on its own line, wrapped in an indented `{ }` block. */ function block(array: Maybe>): string { return wrap('{\n', indent(join(array, '\n')), '\n}'); diff --git a/src/language/visitor.ts b/src/language/visitor.ts index c6ffa4c70b..458a7af2f3 100644 --- a/src/language/visitor.ts +++ b/src/language/visitor.ts @@ -178,24 +178,26 @@ export const BREAK: unknown = Object.freeze({}); * a new version of the AST with the changes applied will be returned from the * visit function. * - * const editedAST = visit(ast, { - * enter(node, key, parent, path, ancestors) { - * // @return - * // undefined: no action - * // false: skip visiting this node - * // visitor.BREAK: stop visiting altogether - * // null: delete this node - * // any value: replace this node with the returned value - * }, - * leave(node, key, parent, path, ancestors) { - * // @return - * // undefined: no action - * // false: no action - * // visitor.BREAK: stop visiting altogether - * // null: delete this node - * // any value: replace this node with the returned value - * } - * }); + * ```ts + * const editedAST = visit(ast, { + * enter(node, key, parent, path, ancestors) { + * // @return + * // undefined: no action + * // false: skip visiting this node + * // visitor.BREAK: stop visiting altogether + * // null: delete this node + * // any value: replace this node with the returned value + * }, + * leave(node, key, parent, path, ancestors) { + * // @return + * // undefined: no action + * // false: no action + * // visitor.BREAK: stop visiting altogether + * // null: delete this node + * // any value: replace this node with the returned value + * } + * }); + * ``` * * Alternatively to providing enter() and leave() functions, a visitor can * instead provide functions named the same as the kinds of AST nodes, or @@ -204,36 +206,41 @@ export const BREAK: unknown = Object.freeze({}); * * 1) Named visitors triggered when entering a node of a specific kind. * - * visit(ast, { - * Kind(node) { - * // enter the "Kind" node - * } - * }) + * ```ts + * visit(ast, { + * Kind(node) { + * // enter the "Kind" node + * } + * }) + * ``` * - * 2) Named visitors that trigger upon entering and leaving a node of - * a specific kind. + * 2) Named visitors that trigger upon entering and leaving a node of a specific kind. * - * visit(ast, { - * Kind: { - * enter(node) { - * // enter the "Kind" node - * } - * leave(node) { - * // leave the "Kind" node - * } - * } - * }) + * ```ts + * visit(ast, { + * Kind: { + * enter(node) { + * // enter the "Kind" node + * } + * leave(node) { + * // leave the "Kind" node + * } + * } + * }) + * ``` * * 3) Generic visitors that trigger upon entering and leaving any node. * - * visit(ast, { - * enter(node) { - * // enter any node - * }, - * leave(node) { - * // leave any node - * } - * }) + * ```ts + * visit(ast, { + * enter(node) { + * // enter any node + * }, + * leave(node) { + * // leave any node + * } + * }) + * ``` */ export function visit(root: N, visitor: ASTVisitor): N; export function visit(root: ASTNode, visitor: ASTReducer): R; diff --git a/src/type/definition.ts b/src/type/definition.ts index 6074fe1dfb..d4bc322c1e 100644 --- a/src/type/definition.ts +++ b/src/type/definition.ts @@ -332,14 +332,15 @@ export function assertAbstractType(type: unknown): GraphQLAbstractType { * * Example: * - * const PersonType = new GraphQLObjectType({ - * name: 'Person', - * fields: () => ({ - * parents: { type: new GraphQLList(PersonType) }, - * children: { type: new GraphQLList(PersonType) }, - * }) - * }) - * + * ```ts + * const PersonType = new GraphQLObjectType({ + * name: 'Person', + * fields: () => ({ + * parents: { type: new GraphQLList(PersonType) }, + * children: { type: new GraphQLList(PersonType) }, + * }) + * }) + * ``` */ export class GraphQLList { readonly ofType: T; @@ -377,13 +378,14 @@ export class GraphQLList { * * Example: * - * const RowType = new GraphQLObjectType({ - * name: 'Row', - * fields: () => ({ - * id: { type: new GraphQLNonNull(GraphQLString) }, - * }) - * }) - * + * ```ts + * const RowType = new GraphQLObjectType({ + * name: 'Row', + * fields: () => ({ + * id: { type: new GraphQLNonNull(GraphQLString) }, + * }) + * }) + * ``` * Note: the enforcement of non-nullability occurs within the executor. */ export class GraphQLNonNull { @@ -566,15 +568,16 @@ export interface GraphQLScalarTypeExtensions { * * Example: * - * const OddType = new GraphQLScalarType({ - * name: 'Odd', - * serialize(value) { - * if (value % 2 === 1) { - * return value; - * } - * } - * }); - * + * ```ts + * const OddType = new GraphQLScalarType({ + * name: 'Odd', + * serialize(value) { + * if (value % 2 === 1) { + * return value; + * } + * } + * }); + * ``` */ export class GraphQLScalarType { name: string; @@ -712,19 +715,21 @@ export interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { * * Example: * - * const AddressType = new GraphQLObjectType({ - * name: 'Address', - * fields: { - * street: { type: GraphQLString }, - * number: { type: GraphQLInt }, - * formatted: { - * type: GraphQLString, - * resolve(obj) { - * return obj.number + ' ' + obj.street - * } - * } + * ```ts + * const AddressType = new GraphQLObjectType({ + * name: 'Address', + * fields: { + * street: { type: GraphQLString }, + * number: { type: GraphQLInt }, + * formatted: { + * type: GraphQLString, + * resolve(obj) { + * return obj.number + ' ' + obj.street * } - * }); + * } + * } + * }); + * ``` * * When two types need to refer to each other, or a type needs to refer to * itself in a field, you can use a function expression (aka a closure or a @@ -732,14 +737,15 @@ export interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { * * Example: * - * const PersonType = new GraphQLObjectType({ - * name: 'Person', - * fields: () => ({ - * name: { type: GraphQLString }, - * bestFriend: { type: PersonType }, - * }) - * }); - * + * ```ts + * const PersonType = new GraphQLObjectType({ + * name: 'Person', + * fields: () => ({ + * name: { type: GraphQLString }, + * bestFriend: { type: PersonType }, + * }) + * }); + * ``` */ export class GraphQLObjectType { name: string; @@ -1097,13 +1103,14 @@ export interface GraphQLInterfaceTypeExtensions { * * Example: * - * const EntityType = new GraphQLInterfaceType({ - * name: 'Entity', - * fields: { - * name: { type: GraphQLString } - * } - * }); - * + * ```ts + * const EntityType = new GraphQLInterfaceType({ + * name: 'Entity', + * fields: { + * name: { type: GraphQLString } + * } + * }); + * ``` */ export class GraphQLInterfaceType { name: string; @@ -1220,19 +1227,20 @@ export interface GraphQLUnionTypeExtensions { * * Example: * - * const PetType = new GraphQLUnionType({ - * name: 'Pet', - * types: [ DogType, CatType ], - * resolveType(value) { - * if (value instanceof Dog) { - * return DogType; - * } - * if (value instanceof Cat) { - * return CatType; - * } - * } - * }); - * + * ```ts + * const PetType = new GraphQLUnionType({ + * name: 'Pet', + * types: [ DogType, CatType ], + * resolveType(value) { + * if (value instanceof Dog) { + * return DogType; + * } + * if (value instanceof Cat) { + * return CatType; + * } + * } + * }); + * ``` */ export class GraphQLUnionType { name: string; @@ -1348,14 +1356,16 @@ export interface GraphQLEnumTypeExtensions { * * Example: * - * const RGBType = new GraphQLEnumType({ - * name: 'RGB', - * values: { - * RED: { value: 0 }, - * GREEN: { value: 1 }, - * BLUE: { value: 2 } - * } - * }); + * ```ts + * const RGBType = new GraphQLEnumType({ + * name: 'RGB', + * values: { + * RED: { value: 0 }, + * GREEN: { value: 1 }, + * BLUE: { value: 2 } + * } + * }); + * ``` * * Note: If a value is not provided in a definition, the name of the enum value * will be used as its internal value. @@ -1591,15 +1601,16 @@ export interface GraphQLInputObjectTypeExtensions { * * Example: * - * const GeoPoint = new GraphQLInputObjectType({ - * name: 'GeoPoint', - * fields: { - * lat: { type: new GraphQLNonNull(GraphQLFloat) }, - * lon: { type: new GraphQLNonNull(GraphQLFloat) }, - * alt: { type: GraphQLFloat, defaultValue: 0 }, - * } - * }); - * + * ```ts + * const GeoPoint = new GraphQLInputObjectType({ + * name: 'GeoPoint', + * fields: { + * lat: { type: new GraphQLNonNull(GraphQLFloat) }, + * lon: { type: new GraphQLNonNull(GraphQLFloat) }, + * alt: { type: GraphQLFloat, defaultValue: 0 }, + * } + * }); + * ``` */ export class GraphQLInputObjectType { name: string; diff --git a/src/type/schema.ts b/src/type/schema.ts index f71765259d..9ed4c41b9e 100644 --- a/src/type/schema.ts +++ b/src/type/schema.ts @@ -67,10 +67,12 @@ export interface GraphQLSchemaExtensions { * * Example: * - * const MyAppSchema = new GraphQLSchema({ - * query: MyAppQueryRootType, - * mutation: MyAppMutationRootType, - * }) + * ```ts + * const MyAppSchema = new GraphQLSchema({ + * query: MyAppQueryRootType, + * mutation: MyAppMutationRootType, + * }) + * ``` * * Note: When the schema is constructed, by default only the types that are * reachable by traversing the root types are included, other types must be @@ -78,48 +80,51 @@ export interface GraphQLSchemaExtensions { * * Example: * - * const characterInterface = new GraphQLInterfaceType({ - * name: 'Character', - * ... - * }); + * ```ts + * const characterInterface = new GraphQLInterfaceType({ + * name: 'Character', + * ... + * }); * - * const humanType = new GraphQLObjectType({ - * name: 'Human', - * interfaces: [characterInterface], - * ... - * }); + * const humanType = new GraphQLObjectType({ + * name: 'Human', + * interfaces: [characterInterface], + * ... + * }); * - * const droidType = new GraphQLObjectType({ - * name: 'Droid', - * interfaces: [characterInterface], - * ... - * }); + * const droidType = new GraphQLObjectType({ + * name: 'Droid', + * interfaces: [characterInterface], + * ... + * }); * - * const schema = new GraphQLSchema({ - * query: new GraphQLObjectType({ - * name: 'Query', - * fields: { - * hero: { type: characterInterface, ... }, - * } - * }), - * ... - * // Since this schema references only the `Character` interface it's - * // necessary to explicitly list the types that implement it if - * // you want them to be included in the final schema. - * types: [humanType, droidType], - * }) + * const schema = new GraphQLSchema({ + * query: new GraphQLObjectType({ + * name: 'Query', + * fields: { + * hero: { type: characterInterface, ... }, + * } + * }), + * ... + * // Since this schema references only the `Character` interface it's + * // necessary to explicitly list the types that implement it if + * // you want them to be included in the final schema. + * types: [humanType, droidType], + * }) + * ``` * * Note: If an array of `directives` are provided to GraphQLSchema, that will be * the exact list of directives represented and allowed. If `directives` is not - * provided then a default set of the specified directives (e.g. @include and - * @skip) will be used. If you wish to provide *additional* directives to these + * provided then a default set of the specified directives (e.g. `@include` and + * `@skip`) will be used. If you wish to provide *additional* directives to these * specified directives, you must explicitly declare them. Example: * - * const MyAppSchema = new GraphQLSchema({ - * ... - * directives: specifiedDirectives.concat([ myCustomDirective ]), - * }) - * + * ```ts + * const MyAppSchema = new GraphQLSchema({ + * ... + * directives: specifiedDirectives.concat([ myCustomDirective ]), + * }) + * ``` */ export class GraphQLSchema { description: Maybe; diff --git a/src/utilities/printSchema.ts b/src/utilities/printSchema.ts index 42d48c6a6c..b9b6565587 100644 --- a/src/utilities/printSchema.ts +++ b/src/utilities/printSchema.ts @@ -98,11 +98,13 @@ function printSchemaDefinition(schema: GraphQLSchema): Maybe { * the same as any other type and can be named in any manner, however there is * a common naming convention: * + * ```graphql * schema { * query: Query * mutation: Mutation * subscription: Subscription * } + * ``` * * When using this naming convention, the schema description can be omitted. */ diff --git a/src/utilities/stripIgnoredCharacters.ts b/src/utilities/stripIgnoredCharacters.ts index f4f53aa042..139b93eaee 100644 --- a/src/utilities/stripIgnoredCharacters.ts +++ b/src/utilities/stripIgnoredCharacters.ts @@ -28,6 +28,7 @@ import { * * Query example: * + * ```graphql * query SomeQuery($foo: String!, $bar: String) { * someField(foo: $foo, bar: $bar) { * a @@ -37,13 +38,17 @@ import { * } * } * } + * ``` * * Becomes: * + * ```graphql * query SomeQuery($foo:String!$bar:String){someField(foo:$foo bar:$bar){a b{c d}}} + * ``` * * SDL example: * + * ```graphql * """ * Type description * """ @@ -53,10 +58,13 @@ import { * """ * bar: String * } + * ``` * * Becomes: * + * ```graphql * """Type description""" type Foo{"""Field description""" bar:String} + * ``` */ export function stripIgnoredCharacters(source: string | Source): string { const sourceObj = isSource(source) ? source : new Source(source); diff --git a/src/validation/validate.ts b/src/validation/validate.ts index 511942155f..f6bc7d0b7b 100644 --- a/src/validation/validate.ts +++ b/src/validation/validate.ts @@ -37,7 +37,7 @@ export function validate( rules: ReadonlyArray = specifiedRules, options: { maxErrors?: number } = { maxErrors: undefined }, - /** @deprecate will be removed in 17.0.0 */ + /** @deprecated will be removed in 17.0.0 */ typeInfo: TypeInfo = new TypeInfo(schema), ): ReadonlyArray { devAssert(documentAST, 'Must provide document.');