Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore ability to put generated files in a directory relative to source #470

Merged
merged 4 commits into from
Jul 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 120 additions & 49 deletions packages/apollo-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
Apollo CLI brings together your GraphQL clients and servers with tools for validating your schema, linting your operations for compatibility with your server, and generating static types for improved client-side type safety.

<!-- toc -->
* [Apollo CLI](#apollo-cli)
* [Usage](#usage)
* [Commands](#commands)
* [Code Generation](#code-generation)
* [Contributing](#contributing)
<!-- tocstop -->

- [Apollo CLI](#apollo-cli)
- [Usage](#usage)
- [Commands](#commands)
- [Code Generation](#code-generation)
- [Contributing](#contributing)
<!-- tocstop -->

# Usage

<!-- usage -->

```sh-session
$ npm install -g apollo
$ apollo COMMAND
Expand All @@ -25,15 +28,19 @@ USAGE
$ apollo COMMAND
...
```

<!-- usagestop -->

# Commands

<!-- commands -->
* [`apollo codegen:generate [OUTPUT]`](#apollo-codegengenerate-output)
* [`apollo help [COMMAND]`](#apollo-help-command)
* [`apollo schema:check`](#apollo-schemacheck)
* [`apollo schema:checkQueries`](#apollo-schemacheck-queries)
* [`apollo schema:download OUTPUT`](#apollo-schemadownload-output)
* [`apollo schema:publish`](#apollo-schemapublish)

- [`apollo codegen:generate [OUTPUT]`](#apollo-codegengenerate-output)
- [`apollo help [COMMAND]`](#apollo-help-command)
- [`apollo schema:check`](#apollo-schemacheck)
- [`apollo schema:checkQueries`](#apollo-schemacheck-queries)
- [`apollo schema:download OUTPUT`](#apollo-schemadownload-output)
- [`apollo schema:publish`](#apollo-schemapublish)

## `apollo codegen:generate [OUTPUT]`

Expand All @@ -44,40 +51,80 @@ USAGE
$ apollo codegen:generate [OUTPUT]

ARGUMENTS
OUTPUT Path to write the generated code to. Can be a directory to generate split files (TypeScript/Flow only). Leave
empty to generate types next to sources (TypeScript/Flow only)
OUTPUT
Directory to which generated files will be written.
- For TypeScript/Flow generators, this specifies a directory relative
to each source file by default.
- For TypeScript/Flow generators with the "outputFlat" flag
is set, and for the Swift generator, this specifies a file or
directory (absolute or relative to the current working directory) to
which:
- a file will be written for each query (if "output" is a
directory)
- all generated types will be written
- For all other types, this defines a file (absolute or relative to
the current working directory) to which all generated types are
written.

OPTIONS
-h, --help Show command help
--addTypename Automatically add __typename to your queries
--customScalarsPrefix=customScalarsPrefix Include a prefix when using provided types for custom scalars
--key=key The API key for the Apollo Engine service
--mergeInFieldsFromFragmentSpreads Merge fragment fields onto its enclosing type
--namespace=namespace The namespace to emit generated code into.
-h, --help
Show command help

--addTypename
Automatically add __typename to your queries

--customScalarsPrefix=customScalarsPrefix
Include a prefix when using provided types for custom scalars

--key=key
The API key for the Apollo Engine service

--mergeInFieldsFromFragmentSpreads
Merge fragment fields onto its enclosing type

--namespace=namespace
The namespace to emit generated code into.

--only=only
Parse all input files, but only output generated code for the
specified file [Swift only]

--only=only Parse all input files, but only output generated code for the specified
file [Swift only]
--operationIdsPath=operationIdsPath
Path to an operation id JSON map file. If specified, also stores the
operation ids (hashes) as properties on operation types [currently
Swift-only]

--operationIdsPath=operationIdsPath Path to an operation id JSON map file. If specified, also stores the
operation ids (hashes) as properties on operation types [currently
Swift-only]
--outputFlat
By default, TypeScript/Flow will put each generated file in a
directory next to its source file using the value of the "output" as
the directory name. Set "outputFlat" to put all generated
files in the directory relative to the current working directory
defined by "output".

--passthroughCustomScalars Use your own types for custom scalars
--passthroughCustomScalars
Use your own types for custom scalars

--queries=queries [default: **/*.graphql] Path to your GraphQL queries, can include search
tokens like **
--queries=queries
[default: **/*.graphql] Path to your GraphQL queries, can include
search tokens like **

--schema=schema Path to your GraphQL schema introspection result
--schema=schema
Path to your GraphQL schema introspection result

--tagName=tagName [default: gql] Name of the template literal tag used to identify template
literals containing GraphQL queries in Javascript/Typescript code
--tagName=tagName
[default: gql] Name of the template literal tag used to identify
template literals containing GraphQL queries in Javascript/Typescript
code

--target=target Type of code generator to use (swift | typescript | flow | scala), inferred
from output
--target=target
Type of code generator to use (swift | typescript | flow | scala),
inferred from output

--useFlowExactObjects Use Flow read only types for generated types [flow only]
--useFlowExactObjects
Use Flow read only types for generated types [flow only]

--useFlowReadOnlyTypes Use Flow read only types for generated types [flow only]
--useFlowReadOnlyTypes
Use Flow read only types for generated types [flow only]
```

_See code: [src/commands/codegen/generate.ts](https://github.com/apollographql/apollo-cli/blob/v1.1.1/src/commands/codegen/generate.ts)_
Expand Down Expand Up @@ -174,13 +221,17 @@ OPTIONS
```

_See code: [src/commands/schema/publish.ts](https://github.com/apollographql/apollo-cli/blob/v1.1.1/src/commands/schema/publish.ts)_

<!-- commandsstop -->

# Code Generation

## Accompanying Libraries

See [Apollo iOS](https://github.com/apollographql/apollo-ios) for details on the mapping from GraphQL results to Swift types, as well as runtime support for executing queries and mutations. For Scala, see [React Apollo Scala.js](https://github.com/apollographql/react-apollo-scalajs) for details on how to use generated Scala code in a Scala.js app with Apollo Client.

## `gql` template support

If the source file for generation is a JavaScript or TypeScript file, the codegen will try to extrapolate the queries inside the [gql tag](https://github.com/apollographql/graphql-tag) templates.

The tag name is configurable using the CLI `--tagName` option.
Expand All @@ -191,11 +242,13 @@ When using the codegen command with Typescript or Flow, make sure to add the `__

If you're using a client like `apollo-client` that does this automatically for your GraphQL operations, pass in the `--addTypename` option to `apollo codegen:generate` to make sure the generated Typescript and Flow types have the `__typename` field as well. This is required to ensure proper type generation support for `GraphQLUnionType` and `GraphQLInterfaceType` fields.

## Why is the __typename field required?
## Why is the \_\_typename field required?

Using the type information from the GraphQL schema, we can infer the possible types for fields. However, in the case of a `GraphQLUnionType` or `GraphQLInterfaceType`, there are multiple types that are possible for that field. This is best modeled using a disjoint union with the `__typename`
as the discriminant.

For example, given a schema:

```graphql
...

Expand Down Expand Up @@ -239,34 +292,48 @@ Apollo Codegen will generate a union type for Character.

```javascript
export type CharactersQuery = {
characters: Array<{
__typename: 'Human',
name: string,
homePlanet: ?string
} | {
__typename: 'Droid',
name: string,
primaryFunction: ?string
}>
}
characters: Array<
| {
__typename: "Human",
name: string,
homePlanet: ?string
}
| {
__typename: "Droid",
name: string,
primaryFunction: ?string
}
>
};
```

This type can then be used as follows to ensure that all possible types are handled:

```javascript
function CharacterFigures({ characters }: CharactersQuery) {
return characters.map(character => {
switch(character.__typename) {
switch (character.__typename) {
case "Human":
return <HumanFigure homePlanet={character.homePlanet} name={character.name} />
return (
<HumanFigure
homePlanet={character.homePlanet}
name={character.name}
/>
);
case "Droid":
return <DroidFigure primaryFunction={character.primaryFunction} name={character.name} />
return (
<DroidFigure
primaryFunction={character.primaryFunction}
name={character.name}
/>
);
}
});
}
```

# Contributing

[![Build status](https://travis-ci.org/apollographql/apollo-cli.svg?branch=master)](https://travis-ci.org/apollographql/apollo-cli)

This repo is composed of multiple packages managed by Lerna. The `apollo-cli` contains the core CLI commands. The `apollo-codegen-core` package contains all the compiler APIs needed to implement code generation support for new languages. The other `apollo-codegen-*` packages implement code generation support for individual languages.
Expand All @@ -279,3 +346,7 @@ npm test
```

You can also run `npm` commands within package folders after you have bootstrapped the repository (part of `npm install`).

```

```
2 changes: 1 addition & 1 deletion packages/apollo-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"memfs": "^2.9.1",
"fs-monkey": "^0.3.3"
},
"precommit": "pretty-quick --staged",
"engines": {
"node": ">=8.0.0"
},
Expand Down Expand Up @@ -119,6 +118,7 @@
"postpack": "rm -f oclif.manifest.json",
"posttest": "tsc -p . --noEmit",
"prepack": "rm -rf lib && tsc && oclif-dev manifest && oclif-dev readme",
"precommit": "pretty-quick --staged",
"test": "jest",
"version": "oclif-dev readme && git add README.md"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export interface SimpleQuery {
//=============================================================="
`;

exports[`successful codegen writes Flow types next to sources when no output is set 1`] = `
exports[`successful codegen writes Flow types into a __generated__ directory next to sources when no output is set 1`] = `
"

/* @flow */
Expand Down Expand Up @@ -176,7 +176,115 @@ export type SimpleQuery = {
//=============================================================="
`;

exports[`successful codegen writes TypeScript types next to sources when no output is set 1`] = `
exports[`successful codegen writes Flow types next to sources when output is set to empty string 1`] = `
"

/* @flow */
/* eslint-disable */
// This file was automatically generated and should not be edited.

// ====================================================
// GraphQL query operation: SimpleQuery
// ====================================================

export type SimpleQuery = {
hello: string
};

/* @flow */
/* eslint-disable */
// This file was automatically generated and should not be edited.

//==============================================================
// START Enums and Input Objects
//==============================================================

//==============================================================
// END Enums and Input Objects
//=============================================================="
`;

exports[`successful codegen writes Flow types to a custom directory next to sources when output is set 1`] = `
"

/* @flow */
/* eslint-disable */
// This file was automatically generated and should not be edited.

// ====================================================
// GraphQL query operation: SimpleQuery
// ====================================================

export type SimpleQuery = {
hello: string
};

/* @flow */
/* eslint-disable */
// This file was automatically generated and should not be edited.

//==============================================================
// START Enums and Input Objects
//==============================================================

//==============================================================
// END Enums and Input Objects
//=============================================================="
`;

exports[`successful codegen writes TypeScript types into a __generated__ directory next to sources when no output is set 1`] = `
"

/* tslint:disable */
// This file was automatically generated and should not be edited.

// ====================================================
// GraphQL query operation: SimpleQuery
// ====================================================

export interface SimpleQuery {
hello: string;
}

/* tslint:disable */
// This file was automatically generated and should not be edited.

//==============================================================
// START Enums and Input Objects
//==============================================================

//==============================================================
// END Enums and Input Objects
//=============================================================="
`;

exports[`successful codegen writes TypeScript types next to sources when output is set to empty string 1`] = `
"

/* tslint:disable */
// This file was automatically generated and should not be edited.

// ====================================================
// GraphQL query operation: SimpleQuery
// ====================================================

export interface SimpleQuery {
hello: string;
}

/* tslint:disable */
// This file was automatically generated and should not be edited.

//==============================================================
// START Enums and Input Objects
//==============================================================

//==============================================================
// END Enums and Input Objects
//=============================================================="
`;

exports[`successful codegen writes TypeScript types to a custom directory next to sources when output is set 1`] = `
"

/* tslint:disable */
Expand Down
Loading