284 lines
7.4 KiB
Plaintext
284 lines
7.4 KiB
Plaintext
/**
|
||||
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|||
|
|
*
|
|||
|
|
* This source code is licensed under the MIT license found in the
|
|||
|
|
* LICENSE file in the root directory of this source tree.
|
|||
|
|
*
|
|||
|
|
* @flow strict-local
|
|||
|
|
* @format
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
// flowlint ambiguous-object-type:error
|
|||
|
|
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
const {RelayConcreteNode} = require('relay-runtime');
|
|||
|
|
|
|||
|
|
import type {
|
|||
|
|
IsGeneratedFileFn,
|
|||
|
|
KeepExtraFileFn,
|
|||
|
|
} from '../codegen/CodegenRunner';
|
|||
|
|
import type {IRTransform} from '../core/CompilerContext';
|
|||
|
|
import type {GeneratedDefinition, Root, Fragment} from '../core/IR';
|
|||
|
|
import type {GetFileFilter} from '../core/RelaySourceModuleParser';
|
|||
|
|
import type {Schema} from '../core/Schema';
|
|||
|
|
import type {ScalarTypeMapping} from './javascript/RelayFlowTypeTransformers';
|
|||
|
|
import type {GeneratedNode} from 'relay-runtime';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* A language plugin allows relay-compiler to both read and write files for any
|
|||
|
|
* language.
|
|||
|
|
*
|
|||
|
|
* When reading, the plugin is expected to parse and return GraphQL tags; and
|
|||
|
|
* when writing the plugin is responsible for generating type information about
|
|||
|
|
* the GraphQL selections made as well as generating the contents of the
|
|||
|
|
* artifact file.
|
|||
|
|
*
|
|||
|
|
* This interface describes the details relay-compiler requires to be able to
|
|||
|
|
* use the plugin and is expected to be returned by a {PluginInitializer}.
|
|||
|
|
*/
|
|||
|
|
export type PluginInterface = {
|
|||
|
|
inputExtensions: string[],
|
|||
|
|
outputExtension: string,
|
|||
|
|
findGraphQLTags: GraphQLTagFinder,
|
|||
|
|
formatModule: FormatModule,
|
|||
|
|
typeGenerator: TypeGenerator,
|
|||
|
|
isGeneratedFile?: IsGeneratedFileFn,
|
|||
|
|
keepExtraFile?: KeepExtraFileFn,
|
|||
|
|
schemaExtensions?: $ReadOnlyArray<string>,
|
|||
|
|
getModuleName?: (operationName: string) => string,
|
|||
|
|
getFileFilter?: GetFileFilter,
|
|||
|
|
...
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The plugin is expected to have as its main default export a function that
|
|||
|
|
* returns an object conforming to the plugin interface.
|
|||
|
|
*
|
|||
|
|
* For now a plugin doesn’t take any arguments, but may do so in the future.
|
|||
|
|
*/
|
|||
|
|
export type PluginInitializer = () => PluginInterface;
|
|||
|
|
|
|||
|
|
export type GraphQLTag = {
|
|||
|
|
/**
|
|||
|
|
* Should hold the string content of the `graphql` tagged template literal,
|
|||
|
|
* which is either an operation or fragment.
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
*
|
|||
|
|
* grapqhl`query MyQuery { … }`
|
|||
|
|
* grapqhl`fragment MyFragment on MyType { … }`
|
|||
|
|
*/
|
|||
|
|
template: string,
|
|||
|
|
/**
|
|||
|
|
* In the case this tag was part of a fragment container and it used a node
|
|||
|
|
* map as fragment spec, rather than a single tagged node, this should hold
|
|||
|
|
* the prop key to which the node is assigned.
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
*
|
|||
|
|
* createFragmentContainer(
|
|||
|
|
* MyComponent,
|
|||
|
|
* {
|
|||
|
|
* keyName: graphql`fragment MyComponent_keyName { … }`
|
|||
|
|
* }
|
|||
|
|
* )
|
|||
|
|
*
|
|||
|
|
*/
|
|||
|
|
keyName: ?string,
|
|||
|
|
/**
|
|||
|
|
* The location in the source file that the tag is placed at.
|
|||
|
|
*/
|
|||
|
|
sourceLocationOffset: {|
|
|||
|
|
/**
|
|||
|
|
* The line in the source file that the tag is placed on.
|
|||
|
|
*
|
|||
|
|
* Lines use 1-based indexing.
|
|||
|
|
*/
|
|||
|
|
line: number,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The column in the source file that the tag starts on.
|
|||
|
|
*
|
|||
|
|
* Columns use 1-based indexing.
|
|||
|
|
*/
|
|||
|
|
column: number,
|
|||
|
|
|},
|
|||
|
|
...
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* This function is responsible for extracting `GraphQLTag` objects from source
|
|||
|
|
* files.
|
|||
|
|
*
|
|||
|
|
* @param {string} text The source file contents.
|
|||
|
|
* @param {string} filePath The path to the source file on disk.
|
|||
|
|
* @return {Array<GraphQLTag>} All extracted `GraphQLTag` objects.
|
|||
|
|
*
|
|||
|
|
* @see {@link javascript/FindGraphQLTags.js}
|
|||
|
|
*/
|
|||
|
|
export type GraphQLTagFinder = (
|
|||
|
|
text: string,
|
|||
|
|
filePath: string,
|
|||
|
|
) => $ReadOnlyArray<GraphQLTag>;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The function that is responsible for generating the contents of the artifact
|
|||
|
|
* file.
|
|||
|
|
*
|
|||
|
|
* @see {@link javascript/formatGeneratedModule.js}
|
|||
|
|
*/
|
|||
|
|
export type FormatModule = ({|
|
|||
|
|
/**
|
|||
|
|
* The filename of the module.
|
|||
|
|
*/
|
|||
|
|
moduleName: string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The type of artifact that this module represents.
|
|||
|
|
*
|
|||
|
|
* @todo Document when this can be `empty`.
|
|||
|
|
*/
|
|||
|
|
documentType:
|
|||
|
|
| typeof RelayConcreteNode.FRAGMENT
|
|||
|
|
| typeof RelayConcreteNode.REQUEST
|
|||
|
|
| null,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The actual document that this module represents.
|
|||
|
|
*/
|
|||
|
|
docText: ?string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The IR for the document that this module represents.
|
|||
|
|
*/
|
|||
|
|
concreteText: string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The type information generated for the GraphQL selections made.
|
|||
|
|
*/
|
|||
|
|
typeText: string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* A hash of the concrete node including the query text.
|
|||
|
|
*
|
|||
|
|
* @todo Document how this is different from `sourceHash`.
|
|||
|
|
*/
|
|||
|
|
hash: ?string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The 'kind' of the generated node.
|
|||
|
|
*/
|
|||
|
|
kind: string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The IR node from which the generated node is derived.
|
|||
|
|
*/
|
|||
|
|
definition: GeneratedDefinition,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* A hash of the document, which is used by relay-compiler to know if it needs
|
|||
|
|
* to write a new version of the artifact.
|
|||
|
|
*
|
|||
|
|
* @todo Is this correct? And document how this is different from `hash`.
|
|||
|
|
*/
|
|||
|
|
sourceHash: string,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The generated node being written.
|
|||
|
|
*/
|
|||
|
|
node: GeneratedNode,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* GraphQL Schema Interface
|
|||
|
|
*/
|
|||
|
|
schema: Schema,
|
|||
|
|
|}) => string;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* The options that will be passed to the `generate` function of your plugin’s
|
|||
|
|
* type generator.
|
|||
|
|
*/
|
|||
|
|
export type TypeGeneratorOptions = {|
|
|||
|
|
/**
|
|||
|
|
* A map of custom scalars to scalars that the plugin knows about and emits
|
|||
|
|
* type information for.
|
|||
|
|
*
|
|||
|
|
* @example
|
|||
|
|
*
|
|||
|
|
* // The URL custom scalar is essentially a string and should be treated as
|
|||
|
|
* // such by the language’s type system.
|
|||
|
|
* { URL: 'String' }
|
|||
|
|
*/
|
|||
|
|
+customScalars: ScalarTypeMapping,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Whether or not relay-compiler will store artifacts next to the module that
|
|||
|
|
* they originate from or all together in a single directory.
|
|||
|
|
*
|
|||
|
|
* Storing all artifacts in a single directory makes it easy to import and
|
|||
|
|
* reference fragments defined in other artifacts without needing to use the
|
|||
|
|
* Haste module system.
|
|||
|
|
*
|
|||
|
|
* This defaults to `false`.
|
|||
|
|
*/
|
|||
|
|
+useSingleArtifactDirectory: boolean,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* This option controls whether or not a catch-all entry is added to enum type
|
|||
|
|
* definitions for values that may be added in the future. Enabling this means
|
|||
|
|
* you will have to update your application whenever the GraphQL server schema
|
|||
|
|
* adds new enum values to prevent it from breaking.
|
|||
|
|
*
|
|||
|
|
* This defaults to `false`.
|
|||
|
|
*/
|
|||
|
|
+noFutureProofEnums: boolean,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @todo Document this.
|
|||
|
|
*/
|
|||
|
|
+optionalInputFields: $ReadOnlyArray<string>,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Whether or not the Haste module system is being used. This will currently
|
|||
|
|
* always be `false` for OSS users.
|
|||
|
|
*/
|
|||
|
|
+useHaste: boolean,
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Import flow types from the Haste-style global module name or per-enum
|
|||
|
|
* global module name given by the function variant.
|
|||
|
|
*/
|
|||
|
|
+enumsHasteModule?: string | ((enumName: string) => string),
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Optional normalization IR for generating raw response
|
|||
|
|
*/
|
|||
|
|
+normalizationIR?: Root,
|
|||
|
|
|};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* This object should hold the implementation required to generate types for the
|
|||
|
|
* GraphQL selections made.
|
|||
|
|
*
|
|||
|
|
* @see {@link javascript/RelayFlowGenerator.js}
|
|||
|
|
*/
|
|||
|
|
export type TypeGenerator = {
|
|||
|
|
/**
|
|||
|
|
* Transforms that should be applied to the intermediate representation of the
|
|||
|
|
* GraphQL document before passing to the `generate` function.
|
|||
|
|
*/
|
|||
|
|
transforms: $ReadOnlyArray<IRTransform>,
|
|||
|
|
/**
|
|||
|
|
* Given GraphQL document IR, this function should generate type information
|
|||
|
|
* for e.g. the selections made. It can, however, also generate any other
|
|||
|
|
* content such as importing other files, including other artifacts.
|
|||
|
|
*/
|
|||
|
|
generate: (
|
|||
|
|
schema: Schema,
|
|||
|
|
node: Root | Fragment,
|
|||
|
|
options: TypeGeneratorOptions,
|
|||
|
|
) => string,
|
|||
|
|
...
|
|||
|
|
};
|