Skip to content

Commit

Permalink
Annotate code base with JSDoc comments (#1759)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielrearden committed Jul 14, 2020
1 parent 02956a7 commit df52bf8
Show file tree
Hide file tree
Showing 29 changed files with 663 additions and 15 deletions.
109 changes: 108 additions & 1 deletion packages/graphql-tag-pluck/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,98 @@ import createVisitor from './visitor';
import traverse from '@babel/traverse';
import { freeText } from './utils';

/**
* Additional options for determining how a file is parsed.
*/
export interface GraphQLTagPluckOptions {
/**
* Additional options for determining how a file is parsed.An array of packages that are responsible for exporting the GraphQL string parser function. The following modules are supported by default:
* ```js
* {
* modules: [
* {
* // import gql from 'graphql-tag'
* name: 'graphql-tag',
* },
* {
* name: 'graphql-tag.macro',
* },
* {
* // import { graphql } from 'gatsby'
* name: 'gatsby',
* identifier: 'graphql',
* },
* {
* name: 'apollo-server-express',
* identifier: 'gql',
* },
* {
* name: 'apollo-server',
* identifier: 'gql',
* },
* {
* name: 'react-relay',
* identifier: 'graphql',
* },
* {
* name: 'apollo-boost',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-koa',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-hapi',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-fastify',
* identifier: 'gql',
* },
* {
* name: ' apollo-server-lambda',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-micro',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-azure-functions',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-cloud-functions',
* identifier: 'gql',
* },
* {
* name: 'apollo-server-cloudflare',
* identifier: 'gql',
* },
* ];
* }
* ```
*/
modules?: Array<{ name: string; identifier?: string }>;
/**
* The magic comment anchor to look for when parsing GraphQL strings. Defaults to `graphql`.
*/
gqlMagicComment?: string;
/**
* Allows to use a global identifier instead of a module import.
* ```js
* // `graphql` is a global function
* export const usersQuery = graphql`
* {
* users {
* id
* name
* }
* }
* `;
* ```
*/
globalGqlIdentifierName?: string | string[];
}

Expand All @@ -20,6 +109,15 @@ function parseWithVue(vueTemplateCompiler: typeof import('vue-template-compiler'
return parsed.script ? parsed.script.content : '';
}

/**
* Asynchronously plucks GraphQL template literals from a single file.
*
* Supported file extensions include: `.js`, `.jsx`, `.ts`, `.tsx`, `.flow`, `.flow.js`, `.flow.jsx`, `.vue`
*
* @param filePath Path to the file containing the code. Required to detect the file type
* @param code The contents of the file being parsed.
* @param options Additional options for determining how a file is parsed.
*/
export const gqlPluckFromCodeString = async (
filePath: string,
code: string,
Expand All @@ -36,6 +134,15 @@ export const gqlPluckFromCodeString = async (
return parseCode({ code, filePath, options });
};

/**
* Synchronously plucks GraphQL template literals from a single file
*
* Supported file extensions include: `.js`, `.jsx`, `.ts`, `.tsx`, `.flow`, `.flow.js`, `.flow.jsx`, `.vue`
*
* @param filePath Path to the file containing the code. Required to detect the file type
* @param code The contents of the file being parsed.
* @param options Additional options for determining how a file is parsed.
*/
export const gqlPluckFromCodeStringSync = (
filePath: string,
code: string,
Expand Down Expand Up @@ -85,7 +192,7 @@ function extractExtension(filePath: string) {

if (fileExt) {
if (!supportedExtensions.includes(fileExt)) {
throw TypeError(`Provided file type must be one of ${supportedExtensions.join(', ')}`);
throw TypeError(`Provided file type must be one of ${supportedExtensions.join(', ')} `);
}
}

Expand Down
21 changes: 21 additions & 0 deletions packages/load-files/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,25 @@ function extractExports(fileExport: any, exportNames: string[]): any | null {
return fileExport;
}

/**
* Additional options for loading files
*/
export interface LoadFilesOptions {
// Extensions to explicitly ignore. Defaults to `['spec', 'test', 'd', 'map']`
ignoredExtensions?: string[];
// Extensions to include when loading files. Defaults to `['gql', 'graphql', 'graphqls', 'ts', 'js']`
extensions?: string[];
// Load files using `require` regardless of the file extension
useRequire?: boolean;
// An alternative to `require` to use if `require` would be used to load a file
requireMethod?: any;
// Additional options to pass to globby
globOptions?: GlobbyOptions;
// Named exports to extract from each file. Defaults to ['typeDefs', 'schema']
exportNames?: string[];
// Load files from nested directories. Set to `false` to only search the top-level directory.
recursive?: boolean;
// Set to `true` to ignore files named `index.js` and `index.ts`
ignoreIndex?: boolean;
}

Expand All @@ -97,6 +108,11 @@ const LoadFilesDefaultOptions: LoadFilesOptions = {
ignoreIndex: false,
};

/**
* Synchronously loads files using the provided glob pattern.
* @param pattern Glob pattern or patterns to use when loading files
* @param options Additional options
*/
export function loadFilesSync<T = any>(
pattern: string | string[],
options: LoadFilesOptions = LoadFilesDefaultOptions
Expand Down Expand Up @@ -188,6 +204,11 @@ const checkExtension = (
return false;
};

/**
* Asynchronously loads files using the provided glob pattern.
* @param pattern Glob pattern or patterns to use when loading files
* @param options Additional options
*/
export async function loadFiles(
pattern: string | string[],
options: LoadFilesOptions = LoadFilesDefaultOptions
Expand Down
31 changes: 27 additions & 4 deletions packages/load/src/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,44 @@ import { Source } from '@graphql-tools/utils';
import { Kind } from 'graphql';
import { LoadTypedefsOptions, loadTypedefs, loadTypedefsSync, UnnormalizedTypeDefPointer } from './load-typedefs';

/**
* Kinds of AST nodes that are included in executable documents
*/
export const OPERATION_KINDS = [Kind.OPERATION_DEFINITION, Kind.FRAGMENT_DEFINITION];

/**
* Kinds of AST nodes that are included in type system definition documents
*/
export const NON_OPERATION_KINDS = Object.keys(Kind)
.reduce((prev, v) => [...prev, Kind[v]], [])
.filter(v => !OPERATION_KINDS.includes(v));

/**
* Asynchronously loads executable documents (i.e. operations and fragments) from
* the provided pointers. The pointers may be individual files or a glob pattern.
* The files themselves may be `.graphql` files or `.js` and `.ts` (in which
* case they will be parsed using graphql-tag-pluck).
* @param pointerOrPointers Pointers to the files to load the documents from
* @param options Additional options
*/
export function loadDocuments(
documentDef: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
pointerOrPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
options: LoadTypedefsOptions
): Promise<Source[]> {
return loadTypedefs(documentDef, { noRequire: true, filterKinds: NON_OPERATION_KINDS, ...options });
return loadTypedefs(pointerOrPointers, { noRequire: true, filterKinds: NON_OPERATION_KINDS, ...options });
}

/**
* Synchronously loads executable documents (i.e. operations and fragments) from
* the provided pointers. The pointers may be individual files or a glob pattern.
* The files themselves may be `.graphql` files or `.js` and `.ts` (in which
* case they will be parsed using graphql-tag-pluck).
* @param pointerOrPointers Pointers to the files to load the documents from
* @param options Additional options
*/
export function loadDocumentsSync(
documentDef: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
pointerOrPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
options: LoadTypedefsOptions
): Source[] {
return loadTypedefsSync(documentDef, { noRequire: true, filterKinds: NON_OPERATION_KINDS, ...options });
return loadTypedefsSync(pointerOrPointers, { noRequire: true, filterKinds: NON_OPERATION_KINDS, ...options });
}
3 changes: 3 additions & 0 deletions packages/load/src/filter-document-kind.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { debugLog } from '@graphql-tools/utils';
import { DocumentNode, DefinitionNode, Kind } from 'graphql';

/**
* @internal
*/
export const filterKind = (content: DocumentNode, filterKinds: null | string[]) => {
if (content && content.definitions && content.definitions.length && filterKinds && filterKinds.length > 0) {
const invalidDefinitions: DefinitionNode[] = [];
Expand Down
14 changes: 14 additions & 0 deletions packages/load/src/load-typedefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ export type LoadTypedefsOptions<ExtraConfig = { [key: string]: any }> = SingleFi

export type UnnormalizedTypeDefPointer = { [key: string]: any } | string;

/**
* Asynchronously loads any GraphQL documents (i.e. executable documents like
* operations and fragments as well as type system definitions) from the
* provided pointers.
* @param pointerOrPointers Pointers to the sources to load the documents from
* @param options Additional options
*/
export async function loadTypedefs<AdditionalConfig = Record<string, unknown>>(
pointerOrPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
options: LoadTypedefsOptions<Partial<AdditionalConfig>>
Expand Down Expand Up @@ -56,6 +63,13 @@ export async function loadTypedefs<AdditionalConfig = Record<string, unknown>>(
return prepareResult({ options, pointerOptionMap, validSources });
}

/**
* Synchronously loads any GraphQL documents (i.e. executable documents like
* operations and fragments as well as type system definitions) from the
* provided pointers.
* @param pointerOrPointers Pointers to the sources to load the documents from
* @param options Additional options
*/
export function loadTypedefsSync<AdditionalConfig = Record<string, unknown>>(
pointerOrPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
options: LoadTypedefsOptions<Partial<AdditionalConfig>>
Expand Down
10 changes: 10 additions & 0 deletions packages/load/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export type LoadSchemaOptions = BuildSchemaOptions &
includeSources?: boolean;
};

/**
* Asynchronously loads a schema from the provided pointers.
* @param schemaPointers Pointers to the sources to load the schema from
* @param options Additional options
*/
export async function loadSchema(
schemaPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
options: LoadSchemaOptions
Expand All @@ -40,6 +45,11 @@ export async function loadSchema(
return schema;
}

/**
* Synchronously loads a schema from the provided pointers.
* @param schemaPointers Pointers to the sources to load the schema from
* @param options Additional options
*/
export function loadSchemaSync(
schemaPointers: UnnormalizedTypeDefPointer | UnnormalizedTypeDefPointer[],
options: LoadSchemaOptions
Expand Down
9 changes: 9 additions & 0 deletions packages/loaders/apollo-engine/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { SchemaLoader, Source, SingleFileOptions } from '@graphql-tools/utils';
import { fetch } from 'cross-fetch';
import { buildClientSchema } from 'graphql';

/**
* Additional options for loading from Apollo Engine
*/
export interface ApolloEngineOptions extends SingleFileOptions {
engine: {
endpoint?: string;
Expand All @@ -14,6 +17,9 @@ export interface ApolloEngineOptions extends SingleFileOptions {

const DEFAULT_APOLLO_ENDPOINT = 'https://engine-graphql.apollographql.com/api/graphql';

/**
* This loader loads a schema from Apollo Engine
*/
export class ApolloEngineLoader implements SchemaLoader<ApolloEngineOptions> {
loaderId() {
return 'apollo-engine';
Expand Down Expand Up @@ -65,6 +71,9 @@ export class ApolloEngineLoader implements SchemaLoader<ApolloEngineOptions> {
}
}

/**
* @internal
*/
export const SCHEMA_QUERY = /* GraphQL */ `
query GetSchemaByTag($tag: String!, $id: ID!) {
service(id: $id) {
Expand Down
6 changes: 6 additions & 0 deletions packages/loaders/code-file/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ const identifiersToLookFor = ['default', 'schema', 'typeDefs', 'data'];

// Pick exports

/**
* @internal
*/
export function pickExportFromModule({ module, filepath }: { module: any; filepath: string }) {
ensureModule({ module, filepath });

return resolveModule(ensureExports({ module, filepath }));
}

/**
* @internal
*/
export function pickExportFromModuleSync({ module, filepath }: { module: any; filepath: string }) {
ensureModule({ module, filepath });

Expand Down
15 changes: 15 additions & 0 deletions packages/loaders/code-file/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { DocumentNode, IntrospectionQuery } from 'graphql';

/**
* @internal
*/
export function pick<T>(obj: any, keys: string[]): T {
for (const key of keys) {
if (obj[key]) {
Expand All @@ -12,22 +15,34 @@ export function pick<T>(obj: any, keys: string[]): T {

// checkers

/**
* @internal
*/
export function isSchemaText(obj: any): obj is string {
return typeof obj === 'string';
}

/**
* @internal
*/
export function isWrappedSchemaJson(obj: any): obj is { data: IntrospectionQuery } {
const json = obj as { data: IntrospectionQuery };

return json.data !== undefined && json.data.__schema !== undefined;
}

/**
* @internal
*/
export function isSchemaJson(obj: any): obj is IntrospectionQuery {
const json = obj as IntrospectionQuery;

return json !== undefined && json.__schema !== undefined;
}

/**
* @internal
*/
export function isSchemaAst(obj: any): obj is DocumentNode {
return (obj as DocumentNode).kind !== undefined;
}

0 comments on commit df52bf8

Please sign in to comment.