Giter Club home page Giter Club logo

apollo-tooling's Introduction

Apollo CLI

GitHub license npm Get on Slack


[2023-03-29] Note - all apollo service:* commands will reach end-of-life on April 28th, 2023. Refer to this blog post for more details.


[2022-07-07] Are you here for codegen? We highly recommend using graphql-code-generator instead. Codegen in this repo is no longer supported and will be removed completely in a future version. For additional migration details, please see this fantastic writeup by @dotansimha: #2053


[2022-01-21] Note - Upcoming Deprecation Plans: We (Apollo) are working towards fully deprecating this repository and its related projects. Most of the functionality in this repository has been replaced by newer projects and the rest will be soon. We'll share detailed migration documentation when everything here is ready to be officially deprecated, but just a heads up in case you're planning on adopting anything here for a new project (which you still can of course if the tooling here works for you - support for this tooling will be minimal however).


[2021-07-23] Note - Housekeeping: Apollo's GraphQL VSCode extension is no longer housed in this repository. It is now maintained separately in this repo.


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.

Usage

Disclaimer: The following API documentation is only for the latest version released on NPM, and may not be accurate for previous or future versions.

$ npm install -g apollo
$ apollo COMMAND
running command...
$ apollo (-v|--version|version)
apollo/2.33.11 darwin-arm64 node-v16.14.2
$ apollo --help [COMMAND]
USAGE
  $ apollo COMMAND
...

Commands

apollo client:check

Check a client project against a pushed service

USAGE
  $ apollo client:check

OPTIONS
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID for the graph in Apollo to operate client commands with.
      Overrides config file if set.

  -v, --variant=variant
      The variant of the graph in Apollo to associate this client to

  --clientName=clientName
      Name of the client that the queries will be attached to

  --clientReferenceId=clientReferenceId
      Reference id for the client which will match ids from client traces,
      will use clientName if not provided

  --clientVersion=clientVersion
      The version of the client that the queries will be attached to

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --excludes=excludes
      Glob of files to exclude for GraphQL operations. Caveat: this doesn't
      currently work in watch mode

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --includes=includes
      Glob of files to search for GraphQL operations. This should be used to
      find queries *and* any client schema extensions

  --key=key
      The API key to use for authentication to Apollo

  --queries=queries
      Deprecated in favor of the includes flag

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

See code: src/commands/client/check.ts

apollo client:codegen [OUTPUT]

Generate static types for GraphQL queries. Can use the published schema in the Apollo registry or a downloaded schema.

USAGE
  $ apollo client:codegen [OUTPUT]

ARGUMENTS
  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
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID for the graph in Apollo to operate client commands with.
      Overrides config file if set.

  -v, --variant=variant
      The variant of the graph in Apollo to associate this client to

  --[no-]addTypename
      [default: true] Automatically add __typename to your queries, can be
      unset with --no-addTypename

  --clientName=clientName
      Name of the client that the queries will be attached to

  --clientReferenceId=clientReferenceId
      Reference id for the client which will match ids from client traces,
      will use clientName if not provided

  --clientVersion=clientVersion
      The version of the client that the queries will be attached to

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

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --excludes=excludes
      Glob of files to exclude for GraphQL operations. Caveat: this doesn't
      currently work in watch mode

  --globalTypesFile=globalTypesFile
      By default, TypeScript will put a file named "globalTypes.ts" inside
      the "output" directory. Set "globalTypesFile" to specify a different
      path. Alternatively, set "tsFileExtension" to modify the extension of
      the file, for example "d.ts" will output "globalTypes.d.ts"

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --includes=includes
      Glob of files to search for GraphQL operations. This should be used to
      find queries *and* any client schema extensions

  --key=key
      The API key to use for authentication to Apollo

  --localSchemaFile=localSchemaFile
      Path to one or more local GraphQL schema file(s), as introspection
      result or SDL. Supports comma-separated list of paths (ex.
      `--localSchemaFile=schema.graphql,extensions.graphql`)

  --mergeInFieldsFromFragmentSpreads
      Merge fragment fields onto its enclosing type

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

  --omitDeprecatedEnumCases
      Omit deprecated enum cases from generated code [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]

  --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

  --queries=queries
      Deprecated in favor of the includes flag

  --suppressSwiftMultilineStringLiterals
      Prevents operations from being rendered as multiline strings [Swift
      only]

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

  --target=target
      (required) Type of code generator to use (swift | typescript | flow |
      scala | json | json-modern (exposes raw json types))

  --tsFileExtension=tsFileExtension
      By default, TypeScript will output "ts" files. Set "tsFileExtension"
      to specify a different file extension, for example "d.ts"

  --useFlowExactObjects
      Use Flow exact objects for generated types [flow only]

  --useFlowReadOnlyTypes
      Use read only types for generated types [flow only]. **Deprecated in
      favor of `useReadOnlyTypes`.**

  --useReadOnlyTypes
      Use read only types for generated types [flow | typescript]

  --watch
      Watch for file changes and reload codegen

ALIASES
  $ apollo codegen:generate

See code: src/commands/client/codegen.ts

apollo client:download-schema OUTPUT

Download a schema from Apollo or a GraphQL endpoint in JSON or SDL format

USAGE
  $ apollo client:download-schema OUTPUT

ARGUMENTS
  OUTPUT  [default: schema.json] Path to write the introspection result
          to. Can be `.graphql`, `.gql`, `.graphqls`, or `.json`

OPTIONS
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID for the graph in Apollo to operate client commands with.
      Overrides config file if set.

  -v, --variant=variant
      The variant of the graph in Apollo to associate this client to

  --clientName=clientName
      Name of the client that the queries will be attached to

  --clientReferenceId=clientReferenceId
      Reference id for the client which will match ids from client traces,
      will use clientName if not provided

  --clientVersion=clientVersion
      The version of the client that the queries will be attached to

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --excludes=excludes
      Glob of files to exclude for GraphQL operations. Caveat: this doesn't
      currently work in watch mode

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --includes=includes
      Glob of files to search for GraphQL operations. This should be used to
      find queries *and* any client schema extensions

  --key=key
      The API key to use for authentication to Apollo

  --queries=queries
      Deprecated in favor of the includes flag

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

See code: src/commands/client/download-schema.ts

apollo client:extract OUTPUT

Extract queries from a client

USAGE
  $ apollo client:extract OUTPUT

ARGUMENTS
  OUTPUT  [default: manifest.json] Path to write the extracted queries to

OPTIONS
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID for the graph in Apollo to operate client commands with.
      Overrides config file if set.

  -v, --variant=variant
      The variant of the graph in Apollo to associate this client to

  --clientName=clientName
      Name of the client that the queries will be attached to

  --clientReferenceId=clientReferenceId
      Reference id for the client which will match ids from client traces,
      will use clientName if not provided

  --clientVersion=clientVersion
      The version of the client that the queries will be attached to

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --excludes=excludes
      Glob of files to exclude for GraphQL operations. Caveat: this doesn't
      currently work in watch mode

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --includes=includes
      Glob of files to search for GraphQL operations. This should be used to
      find queries *and* any client schema extensions

  --key=key
      The API key to use for authentication to Apollo

  --preserveStringAndNumericLiterals
      Disable redaction of string and numerical literals.  Without this
      flag, these values will be replaced with empty strings (`''`) and
      zeroes (`0`) respectively.  This redaction is intended to avoid
      inadvertently outputting potentially personally identifiable
      information (e.g. embedded passwords  or API keys) into operation
      manifests

  --queries=queries
      Deprecated in favor of the includes flag

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

See code: src/commands/client/extract.ts

apollo client:push

Register operations with Apollo, adding them to the safelist

USAGE
  $ apollo client:push

OPTIONS
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID for the graph in Apollo to operate client commands with.
      Overrides config file if set.

  -v, --variant=variant
      The variant of the graph in Apollo to associate this client to

  --clientName=clientName
      Name of the client that the queries will be attached to

  --clientReferenceId=clientReferenceId
      Reference id for the client which will match ids from client traces,
      will use clientName if not provided

  --clientVersion=clientVersion
      The version of the client that the queries will be attached to

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --excludes=excludes
      Glob of files to exclude for GraphQL operations. Caveat: this doesn't
      currently work in watch mode

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --includes=includes
      Glob of files to search for GraphQL operations. This should be used to
      find queries *and* any client schema extensions

  --key=key
      The API key to use for authentication to Apollo

  --queries=queries
      Deprecated in favor of the includes flag

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

See code: src/commands/client/push.ts

apollo help [COMMAND]

display help for apollo

USAGE
  $ apollo help [COMMAND]

ARGUMENTS
  COMMAND  command to show help for

OPTIONS
  --all  see all commands in CLI

See code: @oclif/plugin-help

apollo plugins

List installed plugins.

USAGE
  $ apollo plugins

OPTIONS
  --core  Show core plugins.

EXAMPLE
  $ apollo plugins

See code: @oclif/plugin-plugins

apollo plugins:inspect PLUGIN...

Displays installation properties of a plugin.

USAGE
  $ apollo plugins:inspect PLUGIN...

ARGUMENTS
  PLUGIN  [default: .] Plugin to inspect.

OPTIONS
  -h, --help     Show CLI help.
  -v, --verbose

EXAMPLE
  $ apollo plugins:inspect myplugin

See code: @oclif/plugin-plugins

apollo plugins:install PLUGIN...

Installs a plugin into the CLI.

USAGE
  $ apollo plugins:install PLUGIN...

ARGUMENTS
  PLUGIN  Plugin to install.

OPTIONS
  -f, --force    Run yarn install with force flag.
  -h, --help     Show CLI help.
  -v, --verbose

DESCRIPTION
  Can be installed from npm or a git url.

  Installation of a user-installed plugin will override a core plugin.

  e.g. If you have a core plugin that has a 'hello' command, installing a
  user-installed plugin with a 'hello' command will override the core
  plugin implementation. This is useful if a user needs to update core
  plugin functionality in the CLI without the need to patch and update the
   whole CLI.

ALIASES
  $ apollo plugins:add

EXAMPLES
  $ apollo plugins:install myplugin
  $ apollo plugins:install https://github.com/someuser/someplugin
  $ apollo plugins:install someuser/someplugin

See code: @oclif/plugin-plugins

apollo plugins:link PLUGIN

Links a plugin into the CLI for development.

USAGE
  $ apollo plugins:link PLUGIN

ARGUMENTS
  PATH  [default: .] path to plugin

OPTIONS
  -h, --help     Show CLI help.
  -v, --verbose

DESCRIPTION
  Installation of a linked plugin will override a user-installed or core
  plugin.

  e.g. If you have a user-installed or core plugin that has a 'hello'
  command, installing a linked plugin with a 'hello' command will override
   the user-installed or core plugin implementation. This is useful for
  development work.

EXAMPLE
  $ apollo plugins:link myplugin

See code: @oclif/plugin-plugins

apollo plugins:uninstall PLUGIN...

Removes a plugin from the CLI.

USAGE
  $ apollo plugins:uninstall PLUGIN...

ARGUMENTS
  PLUGIN  plugin to uninstall

OPTIONS
  -h, --help     Show CLI help.
  -v, --verbose

ALIASES
  $ apollo plugins:unlink
  $ apollo plugins:remove

See code: @oclif/plugin-plugins

apollo plugins:update

Update installed plugins.

USAGE
  $ apollo plugins:update

OPTIONS
  -h, --help     Show CLI help.
  -v, --verbose

See code: @oclif/plugin-plugins

apollo service:check

[DEPRECATED] Check a service against known operation workloads to find breaking changes

USAGE
  $ apollo service:check

OPTIONS
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID of the graph in Apollo to check your proposed schema changes
      against. Overrides config file if set.

  -v, --variant=variant
      The variant to check the proposed schema against

  --author=author
      The author to associate with this proposed schema

  --branch=branch
      The branch name to associate with this check

  --commitId=commitId
      The SHA-1 hash of the commit to associate with this check

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --ignoreFailures
      Exit with status 0 when the check completes, even if errors are found

  --json
      Output result in json, which can then be parsed by CLI tools such as
      jq.

  --key=key
      The API key to use for authentication to Apollo

  --localSchemaFile=localSchemaFile
      Path to one or more local GraphQL schema file(s), as introspection
      result or SDL. Supports comma-separated list of paths (ex.
      `--localSchemaFile=schema.graphql,extensions.graphql`)

  --markdown
      Output result in markdown.

  --queryCountThreshold=queryCountThreshold
      Minimum number of requests within the requested time window for a
      query to be considered.

  --queryCountThresholdPercentage=queryCountThresholdPercentage
      Number of requests within the requested time window for a query to be
      considered, relative to total request count. Expected values are
      between 0 and 0.05 (minimum 5% of total request volume)

  --serviceName=serviceName
      Provides the name of the implementing service for a federated graph.
      This flag will indicate that the schema is a partial schema from a
      federated service

  --validationPeriod=validationPeriod
      The size of the time window with which to validate the schema against.
      You may provide a number (in seconds), or an ISO8601 format duration
      for more granularity (see:
      https://en.wikipedia.org/wiki/ISO_8601#Durations)

DESCRIPTION
  -----------------------------------------------------------------
  DEPRECATED: This command will be removed from the `apollo` CLI in
  its next major version. Replacement functionality is available in
  the new Apollo Rover CLI: https://go.apollo.dev/t/migration
  -----------------------------------------------------------------

ALIASES
  $ apollo schema:check

See code: src/commands/service/check.ts

apollo service:delete

[DEPRECATED] Delete a federated service from Apollo and recompose remaining services

USAGE
  $ apollo service:delete

OPTIONS
  -c, --config=config        Path to your Apollo config file

  -g, --graph=graph          The ID of the graph in Apollo for which to
                             delete an implementing service. Overrides
                             config file if set.

  -v, --variant=variant      The variant to delete the implementing
                             service from

  -y, --yes                  Bypass confirmation when deleting a service

  --endpoint=endpoint        The URL for the CLI use to introspect your
                             service

  --header=header            Additional header to send during
                             introspection. May be used multiple times to
                             add multiple headers. NOTE: The `--endpoint`
                             flag is REQUIRED if using the `--header`
                             flag.

  --key=key                  The API key to use for authentication to
                             Apollo

  --serviceName=serviceName  (required) Provides the name of the
                             implementing service for a federated graph

DESCRIPTION
  -----------------------------------------------------------------
  DEPRECATED: This command will be removed from the `apollo` CLI in
  its next major version. Replacement functionality is available in
  the new Apollo Rover CLI: https://go.apollo.dev/t/migration
  -----------------------------------------------------------------

See code: src/commands/service/delete.ts

apollo service:download OUTPUT

[DEPRECATED] Download the schema from your GraphQL endpoint.

USAGE
  $ apollo service:download OUTPUT

ARGUMENTS
  OUTPUT  [default: schema.json] Path to write the introspection result
          to. Supports .json output only.

OPTIONS
  -c, --config=config      Path to your Apollo config file

  -g, --graph=graph        The ID of the graph in the Apollo registry for
                           which to download the schema for. Overrides
                           config file if provided.

  -k, --skipSSLValidation  Allow connections to an SSL site without certs

  -v, --variant=variant    The variant to download the schema of

  --endpoint=endpoint      The URL for the CLI use to introspect your
                           service

  --header=header          Additional header to send during introspection.
                           May be used multiple times to add multiple
                           headers. NOTE: The `--endpoint` flag is
                           REQUIRED if using the `--header` flag.

  --key=key                The API key to use for authentication to Apollo

DESCRIPTION
  -----------------------------------------------------------------
  DEPRECATED: This command will be removed from the `apollo` CLI in
  its next major version. Replacement functionality is available in
  the new Apollo Rover CLI: https://go.apollo.dev/t/migration
  -----------------------------------------------------------------

ALIASES
  $ apollo schema:download

See code: src/commands/service/download.ts

apollo service:list

[DEPRECATED] List the services in a graph

USAGE
  $ apollo service:list

OPTIONS
  -c, --config=config    Path to your Apollo config file

  -g, --graph=graph      The ID of the graph in the Apollo registry for
                         which to list implementing services. Overrides
                         config file if set.

  -v, --variant=variant  The variant to list implementing services for

  --endpoint=endpoint    The URL for the CLI use to introspect your
                         service

  --header=header        Additional header to send during introspection.
                         May be used multiple times to add multiple
                         headers. NOTE: The `--endpoint` flag is REQUIRED
                         if using the `--header` flag.

  --key=key              The API key to use for authentication to Apollo

DESCRIPTION
  -----------------------------------------------------------------
  DEPRECATED: This command will be removed from the `apollo` CLI in
  its next major version. Replacement functionality is available in
  the new Apollo Rover CLI: https://go.apollo.dev/t/migration
  -----------------------------------------------------------------

See code: src/commands/service/list.ts

apollo service:push

[DEPRECATED] Push a service definition to Apollo

USAGE
  $ apollo service:push

OPTIONS
  -c, --config=config
      Path to your Apollo config file

  -g, --graph=graph
      The ID of the graph in Apollo to publish your service to. Overrides
      config file if set.

  -v, --variant=variant
      The variant to publish your service to in Apollo

  --author=author
      The author to associate with this publication

  --branch=branch
      The branch name to associate with this publication

  --commitId=commitId
      The SHA-1 hash of the commit to associate with this publication

  --endpoint=endpoint
      The URL for the CLI use to introspect your service

  --header=header
      Additional header to send during introspection. May be used multiple
      times to add multiple headers. NOTE: The `--endpoint` flag is REQUIRED
      if using the `--header` flag.

  --key=key
      The API key to use for authentication to Apollo

  --localSchemaFile=localSchemaFile
      Path to one or more local GraphQL schema file(s), as introspection
      result or SDL. Supports comma-separated list of paths (ex.
      `--localSchemaFile=schema.graphql,extensions.graphql`)

  --serviceName=serviceName
      Provides the name of the implementing service for a federated graph

  --serviceRevision=serviceRevision
      Provides a unique revision identifier for a change to an implementing
      service on a federated service push. The default of this is a git sha

  --serviceURL=serviceURL
      Provides the url to the location of the implementing service for a
      federated graph

DESCRIPTION
  -----------------------------------------------------------------
  DEPRECATED: This command will be removed from the `apollo` CLI in
  its next major version. Replacement functionality is available in
  the new Apollo Rover CLI: https://go.apollo.dev/t/migration
  -----------------------------------------------------------------

ALIASES
  $ apollo schema:publish

See code: src/commands/service/push.ts

Configuration

The Apollo CLI and VS Code extension can be configured with an Apollo config file. Apollo configuration is stored as a plain object in an apollo.config.js file which exports the configuration. For more information about configuring an Apollo project, see: https://www.apollographql.com/docs/devtools/apollo-config/.

Note: the use of the apollo key in the project's package.json file for configuration is deprecated, and will no longer be supported in Apollo v3

You'll need to set up your Apollo configuration for all the features of the Apollo CLI and VS Code extension to work correctly. For full details on how to do that, visit our docs. A basic configuration (apollo.config.js style) looks something like this:

module.exports = {
  client: {
    name: "My Client Project",
    service: "my-service-name"
  }
};

Code Generation

Accompanying Libraries

See 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 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 templates.

The tag name is configurable using the CLI --tagName option.

Typescript and Flow

When using the codegen command with Typescript or Flow, make sure to add the __typename introspection field to every selection set within your graphql operations.

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?

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:

...

interface Character {
  name: String!
}

type Human implements Character {
  homePlanet: String
}

type Droid implements Character {
  primaryFunction: String
}

...

Whenever a field of type Character is encountered, it could be either a Human or Droid. Human and Droid objects will have a different set of fields. Within your application code, when interacting with a Character you'll want to make sure to handle both of these cases.

Given this query:

query Characters {
  characters(episode: NEW_HOPE) {
    name

    ... on Human {
      homePlanet
    }

    ... on Droid {
      primaryFunction
    }
  }
}

Apollo Codegen will generate a union type for Character.

export type CharactersQuery = {
  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:

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

Contributing

Build Status

This repo is composed of multiple packages. 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.

Running tests locally:

npm install
npm test

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

Note: if you have issues, try npm run clean && npm i to get a fresh install of the packages. Occasionally problems arise when removed dependencies stay around

Nock tests

To display the debugging messages for nock, run the following command:

DEBUG=nock.* npm test

It can also be helpful to print standard out during testing. To enable logging, add the following configuration to the stdout function call during test creation:

.stdout({ print: true })

Active Development / Debugging

To simplify the development process, you may want to step through and debug commands whose behavior you're modifying. To do this, run the executable with node in debug mode like so, where <command> is a valid CLI command like client:check or service:push:

node --inspect-brk=9002 packages/apollo/bin/run <command>

If you're using VS Code, you can run the included "Attach to CLI Debugger" launch task and debug right from VS Code! Otherwise, you may use the Chrome inspector or other Node debugger of your choice.

Regenerating Mocked Network Data

Some integration tests rely on mocked server data (service:check for example). Mock data is generated by making real network requests and recording those requests with nock's recording feature. Stop mocking network calls and add nock.recorder.rec() before network calls are made. For service:check, change apiKey to a real Apollo API key. Then run the tests and nock will output code to mock requests to the console. You can (and probably should) pare down the request to be less brittle (by only checking for an operation name, for example). See src/commands/service/__tests__/check.test.ts for an example of how a mocked network request will look.

Publishing

  1. Make sure the CHANGELOG.md is updated with all changes committed since the last release. Make sure the versions for each package to update are correct.
  2. Run npm run release:version-bump -- <bumpish>
    • Can use major, minor, patch, prepatch, etc for the bump type. If not used, the command will prompt and ask for the bump type.
    • This command updates git tags locally and on GitHub
  3. Run npm run release:start-ci-publish locally
    • IMPORTANT: If publishing a prerelease (like alpha/beta/rc), set the tag that NPM will use to publish with the APOLLO_DIST_TAG environment variable. By default, if this isn't set, NPM will publish the prerelease to the latest tag (which isn't what we'd want).
    • Pushes a publish/XXXXXXXXXX tag to GitHub to trigger circle CI build
  4. Circle will notify the appropriate Apollo team slack channel when ready to release
    • Slack channel member will confirm through the Apollo Deploy Bot
    • Circle will release to all channels (npm, cli binary to s3, vscode marketplace)
    • Another slack bot notification will confirm success of release.

Maintainers

apollo-tooling's People

Contributors

abernix avatar caydie-tran avatar cheapsteak avatar cltnschlosser avatar danilobuerger avatar davidwu226 avatar designatednerd avatar glasser avatar greenkeeper[bot] avatar greenkeeperio-bot avatar hwillson avatar jakedawkins avatar justinanastos avatar kevinmbeaulieu avatar kompfner avatar leethree avatar ligaz avatar lilyball avatar martijnwalraven avatar mayakoneval avatar mike-marcacci avatar pcarrier avatar renovate-bot avatar renovate[bot] avatar rricard avatar shadaj avatar tgriesser avatar tladd avatar trevor-scheer avatar zionts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apollo-tooling's Issues

WIP/RFC - Objective-c target

Hey guys, been playing around with an obj-c target on my fork of this repo (https://github.com/kieranlafferty/apollo-codegen)

Still not full working yet but thought it may be of interest to some people who are also interested in contributing to getting the codegen to work for objc.

Interested to get some early feedback. Thanks again for making such an awesome project!

apollo-codegen generate produces different schema.ts files on different platforms

Bug:
The schema.ts changes depending on which env it was last generated on. Without any code change.

Steps:
apollo-codegen generate $PATH/**/*.gql --schema $PATH/doc.json --target typescript --output $PATH/schema.ts

  1. Run the above command on macOS Sierra (node v6.9.5), and save the schema.ts and submit it to your repository.

  2. Check out your code on Ubuntu (node v6.9.5) and run the above command again.

  3. Diff the schema.ts

You'd see that the schema.ts has changed. Nothing is removed and nothing is added. Just the order of some interfaces has changed.

Cause:
It is possible that $PATH/**/*.gql produces a different sorted list on OSX and Linux as sort may be different going from one OS to another.

Side effect
This doesn't break anything and everything works fine. However, in a group development environment, every time the codegen is executed in different env, it will produce a change which may require an unnecessary repo submission.

Incorrect code gen of field name with multiple caps in a row

Currently in our JSON schema we have an input_obect that contains the following field

{
                            "name": "deviceID",
                            "description": null,
                            "type": {
                                "kind": "SCALAR",
                                "name": "String",
                                "ofType": null
                            },
                            "defaultValue": null
}

In the generated swift code, however, this is becoming deviceId and this same capitalization is being used in the endpoint request, causing it to fail as an unrecognized field.

Generated swift looks like:

public struct addUserInput: GraphQLMapConvertible {
  public var graphQLMap: GraphQLMap

  public init(firstName: String, lastName: String, identifier: String, identifierType: String, deviceId: String? = nil, clientMutationId: String? = nil) {
    graphQLMap = ["firstName": firstName, "lastName": lastName, "identifier": identifier, "identifierType": identifierType, "deviceId": deviceId, "clientMutationId": clientMutationId]
  }
}

Duplicate fields are generated into Fragment interface

I'm using version 0.10.9 and ran into the problem that some properties are generated more than one time into a Fragment interface.

I've assembled a very trivial example for this.
Schema:
zoo.graphql

interface Feedable {
    _id: ID!,
    kind: String!
    feedWith: String!
}


interface Reptile {
    scaleSkin: String!
}

type Crocodile implements Feedable, Reptile {
    _id: ID!,
    kind: String!
    feedWith: String!
    scaleSkin: String!

    victims: Int!
}

type Iguana implements Feedable, Reptile {
    _id: ID!,
    kind: String!
    feedWith: String!
    scaleSkin: String!

    age: Int!
}

root.graphql

type Query {
    getZoo: [Feedable!]!
}

schema {
    query: Query
}

And now I setup a very simple query with some fragments:
zooQuery.graphql

query getZoo {
    getZoo {
        ...FeedableFragment
    }
}

FeedableFragment

fragment FeedableFragment on Feedable {
    _id
    kind,
    feedWith

    ... on Reptile {
        scaleSkin
    }

    ... on Crocodile {
        victims
    }

    ... on Iguana {
        age
    }
}

And now I check the generated interfaces and I have this:

export interface FeedableFragment {
  _id: string;
  kind: string;
  feedWith: string;
  _id: string;
  kind: string;
  feedWith: string;
  scaleSkin: string;
  victims: number;
  _id: string;
  kind: string;
  feedWith: string;
  scaleSkin: string;
  age: number;
}

As you can see, the _id, kind, feedWith fields are repeated three times, instead of one.
What's more, I think that the scaleSkin and age properties should be optional properties.

Flow generation incorrectly PascalCases all type names

The following line
https://github.com/apollographql/apollo-codegen/blob/master/src/flow/codeGeneration.js#L81
optimistically PascalCases all type names even if they might in fact not be.

I agree PascalCase is conventional for naming GraphQL types but I can't find that it's required.

I was trying to generate flow annotations against a schema that contained types with camelCase names. This caused fields referencing the type to remain in camelCase whereas the definition of the type was in PascalCase

No code generated for interface inline fragments

I can use objects as inline fragments, but for interface fragments no code is generated. Shouldn't this be possible?

{
... on ClosedEvent {
        # object, works
    }  
... on IssueEvent {
        # interface, no code is generated
    }
}

(Using Swift, but saw similar results with the other targets.)

Custom scalar types should be listed in typesUsed

Android GraphQL requires custom scalar types to be listed in typesUsed array in IR.json file.
Custom scalar type should be defined in the same way as enum types. This definitions will be later used by android code generator and response adapters

For example:

"typesUsed": [
    {
      "kind": "???",
      "name": "Date",
      "description": "DateTime value"
    },
    {
      "kind": "EnumType",
      "name": "Episode",
      "description": "The episodes in the Star Wars trilogy",
      "values": [
        {
          "name": "NEWHOPE",
          "description": "Star Wars Episode IV: A New Hope, released in 1977."
        },
        {
          "name": "EMPIRE",
          "description": "Star Wars Episode V: The Empire Strikes Back, released in 1980."
        },
        {
          "name": "JEDI",
          "description": "Star Wars Episode VI: Return of the Jedi, released in 1983."
        }
      ]
    }

Crash due to GraphQLEnumType variable types not serialized correctly

Currently String Enum types are not being converted to its rawValue before being used as a parameter. This causes a crash as Swift Enum types are not allowed in JSON serialization and the following error is thrown:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (_SwiftValue)'

Here is some relevant code demonstrating the issue:

API.swift

public enum Size: String {
  case small = "small" /// A Small Size
  case large = "large" /// A Large Size
}

public final class UpdateSizeMutation: GraphQLMutation {
   ...
  public var variables: GraphQLMap? {
    return ["size": size]
  }
}

GraphQLNetworkTransport

    func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (GraphQLResponse<Operation>?, Error?) -> Void) -> Cancellable {
        let params: [String: Any] = ["query": type(of: operation).queryDocument as Any, "variables": operation.variables as Any]
        let request = manager.request(baseURLString, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers)
        ...
        return request
    }

The Swift Enum is therefore included inside of the params variable when sending the request and causes an error when encoding to JSON.

A potential fix is to use .rawValue for string enum types inside of variables during code generation.

Potential Fix

  public var variables: GraphQLMap? {
    return ["size": size.rawValue]
  }

This is a problem that can also be addressed within apollo-ios.

Error running apollo-codegen after installing 0.10.4

Ive installed apollo-codegen globally, which is at version .10.4:

/usr/local/lib
└─┬ [email protected]

When running the iOS sample apps, I get the following error:

/usr/local/lib/node_modules/apollo-codegen/lib/cli.js:33
_process2.default.on('unhandledRejection', error => {
                                                 ^^
SyntaxError: Unexpected token =>
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:448:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:471:10)
    at startup (node.js:117:18)
    at node.js:953:3
error: The version of Apollo.framework in your project requires the use of version 0.9 of apollo-codegen, but an unknown older version seems to be installed.
  • It seems to work from command line:
    apollo-codegen download-schema http://localhost:8080/graphql --output schema.json
  • So it may be how its executed from Xcode.
  • Seems to work fine on 0.10.0

[TS] Spreading named fragments in list selection sets doesn't work

If we try to spread a fragment on a list type, the generated ts type won't be a list.

@dotansimha this feels very similar to the issue you raised about inline fragments and for which you created a PR (#17). Care to take a look? Don't worry, if you don't have time, I'll do it, but I'm interested in bringing contributors like you to this!

Duplicate __typename in generated query string if included in query used for codegen

When I generate Swift-code from a query that include __typename there is duplication in the Query class.

query Foo($id: ID!) {
    bar {
        __typename
        ... on bazType {
            ..
        }
    }
}

Generate code like:

public static let operationDefinition =
"query Foo($id: ID!) {" +
"  bar {" +
"    __typename" +
"    __typename" +
"    ... on bazType {" +
"      .." +
"    }" +
"  }" +
"}"

While it is easy to avoid including it in the query, it seem reasonable to handle this.

Errors should include filename

apollo-codegen takes all of a project's GraphQL files at once to produce a schema, in the form **/*.graphql (or similar).

Whilst validation isn't this tool's primary job (I assume), when it displays errors, it currently doesn't display from which files those errors are sourced.

Whether embedded in something else or used directly, it seems like the resulting validation errors would be more useful if they displayed the file in which they occurred?

Cannot find module 'process' & version issues

I see 0.8.0 is installed, but it still gives me errors

npm install -g apollo-codegen
/usr/local/bin/apollo-codegen -> /usr/local/lib/node_modules/apollo-codegen/lib/cli.js
[email protected] /usr/local/lib/node_modules/apollo-codegen

In Xcode:

Error: Cannot find module 'process'
    at Function.Module._resolveFilename (module.js:336:15)
    at Function.Module._load (module.js:278:25)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/usr/local/lib/node_modules/apollo-codegen/lib/cli.js:20:16)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
error: The version of Apollo.framework in your project requires the use of version 0.8 of apollo-codegen, but an unknown older version seems to be installed.

Many variants of apollo-codegen -version fail with the same error as above.
Please advise.

Cheers

Empty init() being generated for a MutationInput struct

Hi there,

apollo-codegen seems to generate an empty init() on a mutation struct in API.swift, my server implementation for the mutation is pretty straightforward with one input object (UserInput) and one return type (UserType)

Xcode won't compile with an empty init because the graphQLMap property is not being initialised. The workaround currently is modifying API.swift and initialising graphQLMap inside the empty init before running the project, like:

public init() {
  graphQLMap = [:]
}

Steps to reproduce:

  1. Define a Mutation on the server that takes an input object
  2. Use apollo-codegen to download the schema and copy it to your target
  3. Build your project
  4. The generated API.swift has an empty public init()

Can anyone else reproduce this?

This is my API.swift for reference: API.swift

Thanks for the wonderful set of tools, otherwise. :)

Typescript output for non-nullable list is incorrect

Assume schema/type:

type Query {
  episodes: [Episode]! //non-null list
}

Typescript output for query:

query LoadEpisodes {
  episodes {
     ...EpisodeInfo
  }
}

fragment EpisodeInfo on Episode {
  name
}

Results in the following output:

export interface LoadEpisodesQuery {
  episodes: EpisodeInfoFragment;
}

Expected:

export interface LoadEpisodesQuery {
  episodes: Array<EpisodeInfoFragment>;
}

generate appears to be broken

Am I doing something wrong or are these errors able to be recreated by anyone else?

Environment

  • nvm 0.32.1
  • node 7.4.0
  • yarn 0.18.1
  • Darwin Kernel Version 16.3.0: Thu Nov 17 20:23:58 PST 2016; root:xnu-3789.31.2~1/RELEASE_X86_64 x86_64

Steps To Reproduce

  • Install apollo-codegen via yarn global add apollo-codegen
  • Run apollo-codegen download-schema ...
  • Run apollo-codegen generate **/*.graphql ...

I was originally trying to generate flow types and wanted to verify undesired behavior so I attempted the same command so i tried with --target typescript instead of --target flow. The inputs and outputs of both commands are below.

Errors

Flow Scenario

Command:

apollo-codegen generate **/*.graphql --schema schema.graphql.json --target flow --output schema.flow.js`

Response:

Invalid values:
  Argument: target, Given: "flow", Choices: "swift", "json", "ts", "typescript"

TypeScript Scenario

Command:

apollo-codegen generate **/*.graphql --schema schema.graphql.json --target typescript --output schema.graphql.ts

Response:

Error: ENOENT: no such file or directory, open '/Users/Gabe/Sites/foresight-client/**/*.graphql'
    at Object.fs.openSync (fs.js:558:18)
    at Object.fs.readFileSync (fs.js:468:33)
    at /Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/src/loading.js:28:21
    at Array.map (native)
    at loadAndMergeQueryDocuments (/Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/src/loading.js:27:30)
    at generate (/Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/src/generate.js:14:20)
    at Object.handler (/Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/src/cli.js:91:9)
    at Object.self.runCommand (/Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/node_modules/yargs/lib/command.js:170:22)
    at parseArgs (/Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/node_modules/yargs/yargs.js:920:28)
    at Object.get [as argv] (/Users/Gabe/.nvm/versions/node/v7.4.0/lib/node_modules/apollo-codegen/node_modules/yargs/yargs.js:860:16)

Flow codegen

We could generate Flow types for the GraphQL queries in the project in parallel of something like graphql-document-collector to get the query docs globally.

I'll work on this in a folder parallel to the swift/ folder.

TypeScript error on GitHunt-React

I've been messing around and converting the GitHunt-React repo to use TypeScript along with codegen from this module. Really cool stuff, and it almost worked except for one error in the generated Typescript file.

I got an error on FeedEntryFragment due to incorrect extension of RepoInfoFragment.

export interface FeedEntryFragment extends VoteButtonsFragment, RepoInfoFragment {
  id: number;
  commentCount: number;
  repository: {
    fullName: string,
    htmlUrl: string,
    owner: {
      avatarUrl: string,
    } | null,
  };
}

export interface RepoInfoFragment {
  createdAt: number;
  repository: {
    description: string | null,
    stargazersCount: number,
    openIssuesCount: number | null,
  };
  postedBy: {
    htmlUrl: string,
    login: string,
  };
}

export interface VoteButtonsFragment {
  score: number;
  vote: {
    voteValue: number,
  };
}

Unfortunately typescript can't merge nested interface properties. What seems to be needed is to extract the nested type information into their own interfaces which could then be either merged or extended. I can't think of an exact example right now, but I'll try to put something together

Optional arrays in the scheme become non optional

In my scheme there is a non optional array called genres.
genres: [String!]

In the API.swift file it is not optional
public let genres: [String]

Error:

▿ Optional<Error>
  ▿ some : GraphQLResultError
    ▿ path : 7 elements
      - 0 : "viewer"
      - 1 : "market"
      - 2 : "channels"
      - 3 : "edges"
      - 4 : "0"
      - 5 : "node"
      - 6 : "genres"
    - underlying : Apollo.JSONDecodingError.nullValue

Non-nullable types in TypeScript

Looking through the tests for TypeScript codegen, the only non-nullable fields are scalars. Is this a limitation of the codegen or of GraphQL?

export interface HeroAndFriendsNamesQuery {
  hero: {
    name: string,
    friends: Array< {
      name: string,
    } > | null,
  } | null;
}

GraphQLResultReader variables member missing

I bumped to version 0.10.9 and get an error I didn't get with version 0.9.4 for the same query.

The GraphQLResultReader doesn't have a variables member.

API.swift with my query and the xCode error:
skarmavbild 2017-03-08 kl 11 22 26

0.10.7 doesn't work

I get the following error:


> @ generate-types /Users/clayne/workspace/casalova-web
> apollo-codegen generate **/*.graphql --schema graphql-schema.json --target typescript --output ./packages/casalova-web-client/src/universal/graphql-schema.d.ts

Apollo iOS does not support anonymous operations
This anonymous operation must be the only defined operation.
Cannot query field "hero" on type "Query".
Cannot query field "hero" on type "Query".
Apollo iOS inserts __typename automatically when needed, please do not include it explicitly
Unknown type "Episode".
Cannot query field "hero" on type "Query".
Unknown type "Character".
Unknown type "Droid".
Unknown type "Human".
Unknown type "Episode".
Cannot query field "hero" on type "Query".
Cannot query field "hero" on type "Query".
There can only be one operation named "HeroName".
There can only be one operation named "HeroName".
Cannot query field "hero" on type "Query".
Cannot query field "hero" on type "Query".
Cannot query field "hero" on type "Query".
There can only be one operation named "HeroName".
There can only be one operation named "HeroName".
Cannot query field "hero" on type "Query".
Apollo iOS needs to be able to insert __typename when needed, please do not use it as an alias
Validation of GraphQL query document failed

[Swift] Generate is producing errors.

I'm generating swift using the default startwars scheme.json. Its failing to produce output.
scheme.json is attached.

apollo-codegen generate **/*.graphql --schema schema.json --output API.swift

produces the error:

Apollo iOS does not support anonymous operations
This anonymous operation must be the only defined operation.
Apollo iOS inserts __typename automatically when needed, please do not include it explicitly
Cannot query field "height" on type "Human".
There can only be one operation named "HeroName".
There can only be one operation named "HeroName".
There can only be one operation named "HeroName".
There can only be one operation named "HeroName".
Apollo iOS needs to be able to insert __typename when needed, please do not use it as an alias
Validation of GraphQL query document failed

schema.json.txt

Generating flow definitions for queries vs schema

The current flow type generation only generates specific flow types for queries/mutations detected.

I'm curious about if there are any benefits to this approach compared to just generating the flow equivalent of the entire schema. It should be a pretty simple mapping, but maybe I'm missing something.

E.g. if I have a couple of mutations that all resolve to SomeResponseInterface and a specific mutation resolves to SomeImplementationOfSomeResponseInterface I can find use for both the generic and specific types in my code (shared error handling code can be annotate with interface and code dealing with the special fields can be annotated with the other type etc.).

This should also enable any traversals of returned data automatically being type checked even when a query is changed, independent of regenerating flow types (as long as schema stays the same).

The obvious drawback with not-query-specific-annotations is that the flow type-checking doesn't guarantee that I've actually queried for a specific field (but this is currently a little sketchy depending on how diligent(/automated) you are in regenerating the flow annotations since that need to happen for every change in a query).

Maybe the current style of annotations should be accompanied by a complete set of type declarations for the entire schema too?

TypeScript codegen

We could generate TS types for the GraphQL queries in the project in parallel of something like graphql-document-collector to get the query docs globally.

I'll work on this in a folder parallel to the swift/ folder.

Swift Codegen, fragments

Question/Feature request regarding the output of the generated code for swift when fragments are used.

We have a fragment called "FormattedText" to encapsulate complex text fields that have nested bold/italic/link content.
And example quest would be

...
...
  headingText {
        ...formattedText
      }
...

The returned data is as follows

"headingText": {
            "spans": [
              {
                "text": "Credit card utilization"
              }
            ]
          },

The issue arrises with the gerenated code:

...
public let headingText: HeadingText?
...


  public struct HeadingText: GraphQLMappable {
                    public let __typename = "FormattedText"

                    public let fragments: Fragments

                    public init(reader: GraphQLResultReader) throws {
                        let formattedText = try FormattedText(reader: reader)
                        fragments = Fragments(formattedText: formattedText)
                    }

                    public struct Fragments {
                        public let formattedText: FormattedText
                    }
                }
...
...
//and finally Fragmented Text

public struct FormattedText: GraphQLNamedFragment {
    public static let fragmentDefinition =
        "fragment formattedText on FormattedText {" +
        "  spans {" +
        "    text" +
        "  }" +
        "}"

    public static let possibleTypes = ["FormattedText"]

    public let __typename = "FormattedText"
    public let spans: [Span?]?

    public init(reader: GraphQLResultReader) throws {
        spans = try reader.optionalList(for: Field(responseName: "spans"))
    }

    public struct Span: GraphQLMappable {
        public let __typename = "FormattedSpan"
        public let text: String?

        public init(reader: GraphQLResultReader) throws {
            text = try reader.optionalValue(for: Field(responseName: "text"))
        }
    }
}

In order to access this object you would write:

data.headingText?.fragments.formattedText

The feedback is the fragments contatiner necessary? Should the HeadingText class itself not be a FormattedText or more closely implement the FormattedText fragment. This indirection strikes me as unnecessary.

Even the headingText?.__typename == "FormattedText" so this type has been fully specified.

eg:

headingText	CKGraphQL.TestCreditFactorsQuery.Data.CreditFactor.HeadingText?	some
	__typename	String	"FormattedText"			
	fragments	CKGraphQL.TestCreditFactorsQuery.Data.CreditFactor.HeadingText.Fragments	
		formattedText	CKGraphQL.FormattedText	
			__typename	String	"FormattedText"	
			spans	[CKGraphQL.FormattedText.Span?]?	1 value	some
				[0]	CKGraphQL.FormattedText.Span?	some
					__typename	String	"FormattedSpan"	
					text	String?	"Credit card utilization"	some

So my suggestion is, can we make HeadingText more directly inherit from FormattedText?

 public struct HeadingText: FormattedText {

What are the conditions under which this fragment structure becomes more useful?

Multi line fields description isn't supported.

Version: 0.11.0

Part of my schema.json looks as follows:

"fields": null,
          "enumValues": null,
          "description": "This is the first line of the comment.\n\nThis is the second line.\n"

Intended outcome of generated code

// This is the first line of the comment.
//
// This is the second line.
//

public struct ResponseInput: GraphQLMapConvertible {
  public var graphQLMap: GraphQLMap
...

Actual outcome

// This is the first line of the comment.

This is the second line. 

public struct ResponseInput: GraphQLMapConvertible {
  public var graphQLMap: GraphQLMap
...

Because This is the second line. is not in comment-block, it's treated as part of the swift code. This obviously leads to compiler error.

[IR] Operations need to include the file path to each input file

This has been discussed on apollographql/apollo-kotlin#83
On Android, the generated classes need to be organized by package, so that requires us to be able to determine the original file path for each of the .graphql files so we can use that to determine which package name to use. Organizing classes in packages is a very standard practice on Android and this solution is inspired by how Sqldelight handles .sq files.

@martijnwalraven

Windows: apollo-codegen generate does not work.

I've tested on Mac, Windows, and Bash on Ubuntu on Windows. It works great on Mac and Windows Bash, but when I run in a command prompt or powershell:

apollo-codegen generate src/**/*.graphql --schema graphql.schema.json --target typescript --output src/schema.d.ts

I get errors like the following:

Error: ENOENT: no such file or directory, open 'C:\Projects\src\**\*.graphql'

It's interpreting the wildcard path as a string

Response error: Apollo.JSONDecodingError.missingValue

Using version 0.4.3, performing a mutation that returns the following content:

{
  "errors": [
    {
      "message":"In field \"updatePassword\": Invalid password",
      "locations":[{"line":1,"column":0}]
    }
  ],
  "data":{}
}

the completionHandler returns no error (GraphQLResultError), but the result contains errors (result.errors: [GraphQLError]?).

Now using 0.5.1, the resultHandler returns an error (GraphQLResultError) with the following message:

GraphQLResultError(path: ["updatePassword"], underlying: Apollo.JSONDecodingError.missingValue)

For information, here is the client definition for that mutation (apollo-cogen 0.10):

public final class UpdatePasswordMutation: GraphQLMutation {
  public static let operationDefinition =
    "mutation UpdatePassword($oldPassword: String!, $newPassword: String!) {" +
    "  updatePassword(oldPassword: $oldPassword, newPassword: $newPassword) {" +
    "    email" +
    "    timezone" +
    "  }" +
    "}"

  public let oldPassword: String
  public let newPassword: String

  public init(oldPassword: String, newPassword: String) {
    self.oldPassword = oldPassword
    self.newPassword = newPassword
  }

  public var variables: GraphQLMap? {
    return ["oldPassword": oldPassword, "newPassword": newPassword]
  }

  public struct Data: GraphQLMappable {
    public let updatePassword: UpdatePassword?

    public init(reader: GraphQLResultReader) throws {
      updatePassword = try reader.optionalValue(for: Field(responseName: "updatePassword", arguments: ["oldPassword": reader.variables["oldPassword"], "newPassword": reader.variables["newPassword"]]))
    }

    public struct UpdatePassword: GraphQLMappable {
      public let __typename = "Account"
      public let email: String?
      public let timezone: String?

      public init(reader: GraphQLResultReader) throws {
        email = try reader.optionalValue(for: Field(responseName: "email"))
        timezone = try reader.optionalValue(for: Field(responseName: "timezone"))
      }
    }
  }
}

and how it was with apollo-codegen 0.9:

public final class UpdatePasswordMutation: GraphQLMutation {
  public static let operationDefinition =
    "mutation UpdatePassword($oldPassword: String!, $newPassword: String!) {" +
    "  updatePassword(oldPassword: $oldPassword, newPassword: $newPassword) {" +
    "    email" +
    "    timezone" +
    "  }" +
    "}"

  public let oldPassword: String
  public let newPassword: String

  public init(oldPassword: String, newPassword: String) {
    self.oldPassword = oldPassword
    self.newPassword = newPassword
  }

  public var variables: GraphQLMap? {
    return ["oldPassword": oldPassword, "newPassword": newPassword]
  }

  public struct Data: GraphQLMappable {
    public let updatePassword: UpdatePassword?

    public init(reader: GraphQLResultReader) throws {
      updatePassword = try reader.optionalValue(for: Field(responseName: "updatePassword"))
    }

    public struct UpdatePassword: GraphQLMappable {
      public let __typename = "Account"
      public let email: String?
      public let timezone: String?

      public init(reader: GraphQLResultReader) throws {
        email = try reader.optionalValue(for: Field(responseName: "email"))
        timezone = try reader.optionalValue(for: Field(responseName: "timezone"))
      }
    }
  }
}

It looks like something's wrong.. Can you help me there?

Nested inputs with variables have undefined as value in arguments

Hi, I have been using this library for the past 2 months and it is fantastic (app for an animal shelter), but I added a package to Carthage this evening and upgraded, now the generated API file is not being generated correctly. I have a rather large query which fetches the bulk of the data and I have structured my GraphQL schema with nested inputs I have not changed the schema and it was previously working.

Here is the query (I have left out the fragments):

query AllData($facilityId:ID, $squareImageWidth:Float!, $aspectImageWidth:Float!, $cityId:ID) { viewer { allAnimals(order:NAME filters: { facilityId: $facilityId, cityId: $cityId }) { list { ...AnimalFragment } count } allFacilities(order: NAME, filters: { cityId: $cityId }) { list { ...FacilityFragment } count } allLocations(order: NAME, filters: { locationType:[ADOPTION_LOCATION], cityId: $cityId }) { list { ...LocationFragment } count } allCountries(order: NAME) { list { ...CountryFragment } count } allCities(order: NAME) { list { ...CityFragment } count } } }

but I now get undefined for all those variables in the generated code:

`
public struct Viewer: GraphQLMappable {
public let __typename: String
public let allAnimals: AllAnimal?
public let allFacilities: AllFacility
public let allLocations: AllLocation
public let allCountries: AllCountry
public let allCities: AllCity

  public init(reader: GraphQLResultReader) throws {
    __typename = try reader.value(for: Field(responseName: "__typename"))
    allAnimals = try reader.optionalValue(for: Field(responseName: "allAnimals", arguments: ["order": "NAME", "filters": ["facilityId": undefined, "cityId": undefined]]))
    allFacilities = try reader.value(for: Field(responseName: "allFacilities", arguments: ["order": "NAME", "filters": ["cityId": undefined]]))
    allLocations = try reader.value(for: Field(responseName: "allLocations", arguments: ["order": "NAME", "filters": ["locationType": ["ADOPTION_LOCATION"], "cityId": undefined]]))
    allCountries = try reader.value(for: Field(responseName: "allCountries", arguments: ["order": "NAME"]))
    allCities = try reader.value(for: Field(responseName: "allCities", arguments: ["order": "NAME"]))
  }

etc...

`

the shelter I am developing this for is hosting a huge event in a few weeks and I need to get this complete, please any help would be much appreciated.

Thanks.

Generating unnecessary types

Hi,

It seems that the apollo-codegen is generating an unnecessary objects off the typeName.

I think the typeName should define the type and not the instance name.

For example:

        public struct PointsLastYear: GraphQLMappable {
          public let __typename = "point"
          public let time: String?
          public let value: Double?

          public init(reader: GraphQLResultReader) throws {
            time = try reader.optionalValue(for: Field(responseName: "time"))
            value = try reader.optionalValue(for: Field(responseName: "value"))
          }
        }

        public struct Point: GraphQLMappable {
          public let __typename = "point"
          public let time: String?
          public let value: Double?

          public init(reader: GraphQLResultReader) throws {
            time = try reader.optionalValue(for: Field(responseName: "time"))
            value = try reader.optionalValue(for: Field(responseName: "value"))
          }
        }
      }

The typeName for PointsLastYear and Point is the same i.e point.

Based on the schema below, it does seem like we are defining the typeName as point, but the generator ends up creating an additional object of the same instance type, which deems unnecessary.

    {
              "type": {
                "ofType": {
                  "ofType": null,
                  "name": "point",
                  "kind": "OBJECT"
                },
                "name": null,
                "kind": "LIST"
              },
              "name": "points",
              "isDeprecated": false,
              "description": null,
              "deprecationReason": null,
              "args": []
            },
            {
              "type": {
                "ofType": {
                  "ofType": null,
                  "name": "point",
                  "kind": "OBJECT"
                },
                "name": null,
                "kind": "LIST"
              },
              "name": "pointsLastYear",
              "isDeprecated": false,
              "description": null,
              "deprecationReason": null,
              "args": []
            },

This is causing unnecessary abstractions and objects which are really not needed as they are of the same type.

Is this the kind of expected behavior and by design ?

Please advice.

No public init in generated Swift classes

Hi,

When a query does not have any variables, the generated GraphQLQuery class does not contain a public init.
This prevents initialising an instance outside of the module.
You can see this in the StarWars Playground when using HeroNameQuery():

Playground execution failed: error: StarWarsAPI.playground:4:21: error: 'HeroNameQuery' initializer is inaccessible due to 'internal' protection level
client.fetch(query: HeroNameQuery()) { (result, error) in

The ParseQueryResponseTests however don’t catch this issue since there, the StarWars API is local, inside the ApolloTests module.
Is this by design, or should the queries be available outside of the module as well?

Possible fix is emitting an empty init for operations without variables :

diff --git a/src/swift/codeGeneration.js b/src/swift/codeGeneration.js
index cc415fd..ea0b2a9 100644
--- a/src/swift/codeGeneration.js
+++ b/src/swift/codeGeneration.js
@@ -126,6 +126,8 @@ export function classDeclarationForOperation(
           `]`
         ));
       });
+    } else {
+      initializerDeclarationForProperties(generator, []);
     }

     structDeclarationForSelectionSet(

Fragment name uppercase-lowecase problem for the generated TS interfaces

I'm using version 0.10.9 , and if I declare a fragment like this:

fragment ICQMessageFragment on RandomTest {
    _id
}

the name of the generated ts interface will be:

export interface IcqMessageFragment  

Notice that ICQ turned into Icq

however when I use this fragment on a query, like:

getMessages {
  ...ICQMessageFragment 
} 

The generated ts interface inside the query will use the original form of the fragment, like this:

 Array<ICQMessageFragment>

And Typescript immediately throws an error that it doesn't find: ICQMessageFragment because it is case-sensitive.

Allow for disabling of the NoUnusedFragments rule

If you want to reuse fragments and import them with the

#import "../common-fragments.graphql

syntax, then validation will fall as the common-fragments.graphql file will fail with these errors:

Fragment "Foo" is never used.
Validation of GraphQL query document failed

This can be "hacked" by changing line 16 of validations.js from:

  const rules = [NoAnonymousQueries, NoExplicitTypename, NoTypenameAlias].concat(_graphql.specifiedRules)

to

  const rules = [NoAnonymousQueries, NoExplicitTypename, NoTypenameAlias].concat(_graphql.specifiedRules).filter((rule) => rule.name !== "NoUnusedFragments")

However, the default should probably remain as is but this be set via CLI option.

If this would be an acceptable feature, I'll add a PR.

installation issues with apollo-codegen

[email protected] prepublish /Users/moniquehaas/apollo-codegen
rm -rf lib && npm run compile

[email protected] compile /Users/moniquehaas/apollo-codegen
babel src --out-dir lib --source-maps

ReferenceError: Unknown plugin "transform-runtime" specified in "/Users/moniquehaas/apollo-codegen/.babelrc" at 0, attempted to resolve relative to "/Users/moniquehaas/apollo-codegen"
at /usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/options/option-manager.js:193:17
at Array.map (native)
at Function.normalisePlugins (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/options/option-manager.js:173:20)
at OptionManager.mergeOptions (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/options/option-manager.js:271:36)
at OptionManager.addConfig (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/options/option-manager.js:221:10)
at OptionManager.findConfigs (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/options/option-manager.js:364:16)
at OptionManager.init (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/options/option-manager.js:412:12)
at File.initOptions (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/index.js:191:75)
at new File (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/file/index.js:122:22)
at Pipeline.transform (/usr/local/lib/node_modules/babel-cli/node_modules/babel-core/lib/transformation/pipeline.js:42:16)

npm ERR! Darwin 16.5.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "compile"
npm ERR! node v6.10.2
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] compile: babel src --out-dir lib --source-maps
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] compile script 'babel src --out-dir lib --source-maps'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the apollo-codegen package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! babel src --out-dir lib --source-maps
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs apollo-codegen
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls apollo-codegen
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/moniquehaas/apollo-codegen/npm-debug.log

npm ERR! addLocal Could not install /Users/moniquehaas/apollo-codegen
npm ERR! Darwin 16.5.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "-g" "apollo-codegen"
npm ERR! node v6.10.2
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! [email protected] prepublish: rm -rf lib && npm run compile
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] prepublish script 'rm -rf lib && npm run compile'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the apollo-codegen package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! rm -rf lib && npm run compile
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs apollo-codegen
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls apollo-codegen
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR! /Users/moniquehaas/npm-debug.log

External updates to Swift models

Is there currently a mechanism by which the Swift model structs can be mutated?

My two use cases are as follows:

  1. Optimistic updates -- aka the user submits a change, and we want to update the UI before receiving the response from the server
  2. A source other than the GraphQL API indicates that data returned from the GraphQL API has changed -- for example, we have unreadCount as a property of a GraphQL model struct A, but push notifications also contain an unreadCount and when we receive a push notification, we want to mutate the A struct to update it's unreadCount.

Currently, it appears that structs are generated with properties as constants (let), and the simple solution would be to change these to var. Would this be something that would be considered to add to the apollo-codegen CLI as an option?

Keep top-level data field when storing the schema.json

Most (if not all) of the schema.json files provided online (such as Relay for example) have the data field as the top-level field.

When downloading a schema through an introspection query using apollo-codegen, it only stores the __schema object in the json file.

IMO, keeping the data field should provide more flexibility for users, particularly in cases when someone doesn't go through the download-schema process.

This would also require minor modification to the checks in loading.js to support both cases.

I can push a fix if that's of interest.

GraphQL custom Scalar types are now all 'String' in Swift

We were relying on the GraphQL type names coming in as described in GraphQL, so we could add our own typealiases and conversion code in Swift. For example we had:

public extension OurGeneratedQueryType {
    public typealias ID = String
    public typealias ResourceURL = URL
}

What's more, we have certain types notated as Doubles in our Schema, which used to arrive in Swift as Doubles. Since the change these are all Strings. Using GraphQL's built-in Float type is not a good compromise here, since we want to keep the precision of the Double type (from what I've read, Javascript / MongoDB floating point numbers have double precision).

By changing everything to a String at the codegen stage we're losing valuable type information – type information which in my opinion is the whole point of using Apollo-iOS / codegen.

If the aim of this change was to simplify the developer experience for beginners, maybe it'd be a good compromise to generate a block that the user can then override themselves if needed? Like this:

public extension GeneratedQueryType {
    public typealias ID = String
    public typealias CustomScalarType = String
    etc...
}

That way users can create their own conversion code for specific Scalars without coupling the conversion code to specific queries.

IR doesn't provide possible types required for fragments that extends interface

Original issue described here apollographql/apollo-kotlin#222

Query:

query getAllTrips {
  allTrips {
    ...commonFields
  }
}

fragment commonFields on Plan {
  id
  title
}

Where Plan extends Trip, response:

{
  "data": {
    "allTrips": [
      {
        "__typename": "Trip",
        "id": "2c494055-78bc-430c-9ab7-19817f3fc060",
        "title": "Vacation!"
      }
    ]
  }
}

Codegen generates IR with only one typeCondition =Plan.

"fragments": [
		{
			"fragmentName": "commonFields",
			"source": "fragment commonFields on Plan {\n  __typename\n  id\n  title\n}",
			"typeCondition": "Plan",
			"fields": [
				{
					"responseName": "id",
					"fieldName": "id",
					"type": "ID!"
				},
				{
					"responseName": "title",
					"fieldName": "title",
					"type": "String!"
				}
			],
		}
	],

So to be able correctly parse response on Android, we need to get access to all possibleTypes = ["Tree", "Plan"]

Add flag to include warning in generated files

Many generators or config editors will include a commented warning at the top of generated files to indicate that the file should be edited directly since it was generated.

Perhaps it would be a good idea to either add a flag to insert a standard warning or an argument to specify the warning text.

Syntax Error when generating Swift file where model contains reserved word

If you have a query like:

query GetSimpleQuery {
    member {
        profile {
            private
        }
    }
}

This'll generate

public final class GetSimpleQueryQuery: GraphQLQuery {
  public static let operationDefinition =
    "query GetSimpleQuery {" +
    "  member {" +
    "    profile {" +
    "      private" +
    "    }" +
    "  }" +
    "}"
  public init() {
  }

  public struct Data: GraphQLMappable {
    public let member: Member?

    public init(reader: GraphQLResultReader) throws {
      member = try reader.optionalValue(for: Field(responseName: "member"))
    }

    public struct Member: GraphQLMappable {
      public let __typename = "Member"
      public let profile: Profile

      public init(reader: GraphQLResultReader) throws {
        profile = try reader.value(for: Field(responseName: "profile"))
      }

      public struct Profile: GraphQLMappable {
        public let __typename = "MemberProfile"
        public let private: Bool?

        public init(reader: GraphQLResultReader) throws {
          private = try reader.optionalValue(for: Field(responseName: "private"))
        }
      }
    }
  }
}

Which produces the error:

Keyword private cannot be used as an identifier here

When generating .swift files can we escape these?

Split out targets?

Just a suggestion, but would it make sense to split out different targets ala plugins rather than having them all exist in the same repo?

react-apollo additional properties

When we use react-apollo like this :

let Component = ({data:GetSomethingQuery}) => {
  ...
}
export let ComponentWithApollo = graphql(getSomethingQuery)(Component)

with GetSomethingQuery as the result of the apollo-codegen generate, react-apollo add to data additional properties like loading, refetch or subscribeToMore.

How could we add those fields to the type definition ?

Make nullable arguments optional in their typescript interface

The graphql spec at http://facebook.github.io/graphql/#sec-Required-Non-Null-Arguments says

If it is not non‐null, the argument is optional.

And I have been happily omitting them in my JavaScript/react-apollo projects for weeks. But in transitioning to TypeScript I want to avoid explicitly supplying each nullable argument, with a null value.

So the following is just a hacky excursion to make such nullable arguments optional in their typescript interface declarations:

For example:

export interface AddPassengerMutationVariables {
  bookingId: number;
  name: string;
  email: string | null;
  mobile: string | null;
  phone: string | null;
}

becomes

export interface AddPassengerMutationVariables {
  bookingId: number;
  name: string;
  email?: string | null;
  mobile?: string | null;
  phone?: string | null;
}

Frankly I just started with typescript yesterday so this might not even be a sound idea but I just wanted to leave this here for any discussion...

diff --git a/src/typescript/codeGeneration.js b/src/typescript/codeGeneration.js
index fb5dfad..d5b5b89 100644
--- a/src/typescript/codeGeneration.js
+++ b/src/typescript/codeGeneration.js
@@ -126,7 +126,7 @@ export function interfaceVariablesDeclarationForOperation(
   interfaceDeclaration(generator, {
     interfaceName,
   }, () => {
-    const properties = propertiesFromFields(generator.context, variables);
+    const properties = propertiesFromFields(generator.context, variables, false, true);
     propertyDeclarations(generator, properties, true);
   });
 }
@@ -179,17 +179,17 @@ export function interfaceDeclarationForFragment(
   });
 }
 
-export function propertiesFromFields(context, fields, forceNullable) {
-  return fields.map(field => propertyFromField(context, field, forceNullable));
+export function propertiesFromFields(context, fields, forceNullable, isVariable) {
+  return fields.map(field => propertyFromField(context, field, forceNullable, isVariable));
 }
 
-export function propertyFromField(context, field, forceNullable) {
+export function propertyFromField(context, field, forceNullable, isVariable) {
   let { name: fieldName, type: fieldType, description, fragmentSpreads, inlineFragments } = field;
   fieldName = fieldName || field.responseName;
 
   const propertyName = fieldName;
 
-  let property = { fieldName, fieldType, propertyName, description };
+  let property = { fieldName, fieldType, propertyName, description, isVariable };
 
   const namedType = getNamedType(fieldType);
 
@@ -212,8 +212,9 @@ export function propertyFromField(context, field, forceNullable) {
       isArray, isNullable,
     };
   } else {
+    const isNullable = !(fieldType instanceof GraphQLNonNull)
     const typeName = typeNameFromGraphQLType(context, fieldType);
-    return { ...property, typeName, isComposite: false, fieldType };
+    return { ...property, typeName, isNullable, isComposite: false, fieldType };
   }
 }
 
diff --git a/src/typescript/language.js b/src/typescript/language.js
index 0ab5440..53e3a61 100644
--- a/src/typescript/language.js
+++ b/src/typescript/language.js
@@ -15,10 +15,11 @@ export function interfaceDeclaration(generator, { interfaceName, extendTypes },
   generator.popScope();
 }
 
-export function propertyDeclaration(generator, { propertyName, typeName, description, isArray, isNullable, inInterface, fragmentSpreads }, closure) {
+export function propertyDeclaration(generator, { propertyName, typeName, description, isArray, isNullable, isVariable, inInterface, fragmentSpreads }, closure) {
   generator.printOnNewline(description && `// ${description}`);
+  const optional = isVariable && isNullable ? '?' : ''
   if (closure) {
-    generator.printOnNewline(`${propertyName}:`);
+    generator.printOnNewline(`${propertyName}${optional}:`);
     if (isArray) {
       generator.print(' Array<');
     }
@@ -37,7 +38,7 @@ export function propertyDeclaration(generator, { propertyName, typeName, descrip
   } else if (fragmentSpreads && fragmentSpreads.length > 0) {
     generator.printOnNewline(`${propertyName}: ${isArray ? 'Array<' : ''}${fragmentSpreads.map(n => `${n}Fragment`).join(' & ')}${isArray ? '>' : ''}`);
   } else {
-    generator.printOnNewline(`${propertyName}: ${typeName}`);
+    generator.printOnNewline(`${propertyName}${optional}: ${typeName}`);
   }
   generator.print(inInterface ? ';' : ',');
 }

RangeError: Maximum call stack size exceeded on 0.9.6

I just update my apollo-ios from 0.3.1 to 0.4.2 and apollo-codegen to 0.9.6.

I have 19 *.graphql files with approximate 3k lines. It's quite good on old version, but they have some issue so I have to update.

Then now, I get this error:

apollo-codegen generate **/*.graphql --schema schema.json --output API.swift
RangeError: Maximum call stack size exceeded
at _loop (/usr/local/lib/node_modules/apollo-codegen/src/swift/codeGeneration.js:443:22)
at /usr/local/lib/node_modules/apollo-codegen/src/swift/codeGeneration.js:442:40
at CodeGenerator.withIndent (/usr/local/lib/node_modules/apollo-codegen/src/utilities/CodeGenerator.js:63:5)
at CodeGenerator.withinBlock (/usr/local/lib/node_modules/apollo-codegen/src/utilities/CodeGenerator.js:69:10)
at structDeclaration (/usr/local/lib/node_modules/apollo-codegen/src/swift/language.js:23:13)
at structDeclarationForInputObjectType (/usr/local/lib/node_modules/apollo-codegen/src/swift/codeGeneration.js:437:3)
at typeDeclarationForGraphQLType (/usr/local/lib/node_modules/apollo-codegen/src/swift/codeGeneration.js:412:5)
at /usr/local/lib/node_modules/apollo-codegen/src/swift/codeGeneration.js:48:5
at Array.forEach (native)
at generateSource (/usr/local/lib/node_modules/apollo-codegen/src/swift/codeGeneration.js:47:21)

Did anyone get this isssue and solved it ?

P/s: I'm not english speaking, so sorry for my bad english

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.