diff --git a/CHANGELOG.md b/CHANGELOG.md index f5464be81cb..dc9d3aaf505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,376 +1 @@ -## Note: >0.9.2 Releases CHANGELOG moved to GitHub releases - - - -## [0.9.1](https://github.com/dotansimha/graphql-codegen/compare/0.9.0...0.9.1) (2018-05-08) - -- TypeScript template: added missing `readonly` for `__typename` field when generating immutable types -- TypeScript template: added missing imports for ts-multiple templates when generating fragments - - - -## [0.9.0](https://github.com/dotansimha/graphql-codegen/compare/0.8.21...0.9.0) (2018-05-07) - -- Update all dependencies -- Fix bugs with document finder ([#233](https://github.com/dotansimha/graphql-code-generator/issues/233), [#216](https://github.com/dotansimha/graphql-code-generator/pull/216)) -- Respect `--out` when generating a project ([#210](https://github.com/dotansimha/graphql-code-generator/pull/210), Thanks @micimize) -- Automatically registerPartial custom templates without breaking normal partial registration ([#210](https://github.com/dotansimha/graphql-code-generator/pull/210), Thanks @micimize) -- Make `ts.{ schema, documents }.handlebars` work without a prefix (e.g. `ts.schema.handlebars` => `schema.ts`) ([#210](https://github.com/dotansimha/graphql-code-generator/pull/210), Thanks @micimize) -- Mark template comments as safe to avoid url escaping ([#210](https://github.com/dotansimha/graphql-code-generator/pull/210), Thanks @micimize) -- Fixed some links in the docs and add relevant docs for the included changes ([#210](https://github.com/dotansimha/graphql-code-generator/pull/210), Thanks @micimize) -- Fix export CLI short alias ([#255](https://github.com/dotansimha/graphql-code-generator/pull/255), Thanks @eritikass) -- Deprecate `--export`, `--file`, `--url` in favor of `--schema` ([#208](https://github.com/dotansimha/graphql-code-generator/pull/208)) -- Added support for a `Promise` as export value ([#208](https://github.com/dotansimha/graphql-code-generator/pull/208)) -- New template! TypeScript typings with MongoDB models! -- Added support for custom output processor ([#263](https://github.com/dotansimha/graphql-code-generator/issues/263)) -- Better detection of `GraphQLSchema` objects -- Added programmatic usage ([#288](https://github.com/dotansimha/graphql-code-generator/pull/288)) -- TypeScript generated comments are now `docstring` valid! -- Added `isNullableArray` and `raw` type name to `ResolvedType` interface. -- Fixed TypeScript template output: handle nullables correctly (See [#260](https://github.com/dotansimha/graphql-code-generator/issues/260)) -- You can now pass generator-specific config using environment variables with the prefix `CODEGEN_` (See [#260](https://github.com/dotansimha/graphql-code-generator/issues/260)) -- Added `avoidOptionals` option to TypeScript generators (See [#260](https://github.com/dotansimha/graphql-code-generator/issues/260)) -- Added `enumsAsTypes` option to TypeScript generators (See [#260](https://github.com/dotansimha/graphql-code-generator/issues/260)) -- Added `immutableTypes` option to TypeScript generators (See [#260](https://github.com/dotansimha/graphql-code-generator/issues/260)) - -### BREAKING CHANGES - -- `--no-schema` changed to `--skip-schema` -- `--no-documents` changed to `--skip-documents` -- **Templates are no longer part of the core package, and they needed to be installed separately (see README installation notes)** - - - -## [0.8.21](https://github.com/dotansimha/graphql-codegen/compare/0.8.20...0.8.21) (2018-03-17) - -- Use default `.ts` extension for TypeScript generatos (instead of `.d.ts`) to avoid errors with enums (Thanks @guilhermehubner) -- Update some dependencies to the latest version. - - - -## [0.8.20](https://github.com/dotansimha/graphql-codegen/compare/0.8.19...0.8.20) (2018-03-14) - -- Fixed a bug with `gql` detection on TSX files - - - -## [0.8.19](https://github.com/dotansimha/graphql-codegen/compare/0.8.18...0.8.19) (2018-03-13) - -- Ignore commented code in document files -- Better detection for GraphQL documents usage with `gql` tag. -- Added prettier support (see README) - - - -## [0.8.18](https://github.com/dotansimha/graphql-codegen/compare/0.8.16...0.8.18) (2018-03-13) - -- Added `__typename` to TypeScript templates, with support for inline fragments. -- Added `stringify` Handlebars helpers for easy debugging. -- Codegen compiler: trim templates before using it. -- Refactor parts of the TypeScript templates -- Change inline fragments behavior in generated TypeScript code to use `|` instead of `&`. -- Added `--no-overwrite` flag to skip overwriting existing files -- Generator will not throw an error if a glob expression does not match any GraphQL document files -- Generator will not write a file to file system if the content is empty - - - -## [0.8.16](https://github.com/dotansimha/graphql-codegen/compare/0.8.15...0.8.16) (2018-03-13) - -- Handle lists and non-null properly (Thanks @FredyC) - - - -## [0.8.15](https://github.com/dotansimha/graphql-codegen/compare/0.8.14...0.8.15) (2018-03-13) - -- Added support for generator-specific config in `gql-gen.json` file. -- Generated config is now exposed in the template under the name `config` in the root context. -- Added `currentTime` to the context. -- Added support for GraphQL 0.13 -- Updated all dependencies -- Added support for using custom `require` using `--require` flag (Thanks Jonas Kello) -- Update TypeScript enum template (Thanks @darthtrevino) - -### Breaking Changes - -- Changed CLI option that points to `gql-gen.json` file from `--project-config` to `--config`. - - - -## [0.8.14](https://github.com/dotansimha/graphql-codegen/compare/0.8.12...0.8.14) (2017-10-29) - -- (Compiler) Fixed execution context for `ifDirective` and `unlessDirective` (now the parent is also available, no need for `../`) -- (TypeScript) Fix for nullable types [Fixes #155](https://github.com/dotansimha/graphql-code-generator/issues/155) - - - -## [0.8.12](https://github.com/dotansimha/graphql-codegen/compare/0.8.11...0.8.12) (2017-09-21) - -- Fix for custom templates in an external project that use `.` in result file name (for example: `my-file.d.ts.schema.handlebars`) - - - -## [0.8.11](https://github.com/dotansimha/graphql-codegen/compare/0.8.10...0.8.11) (2017-09-20) - -- Export all available interfaces from the compiler package (Fixes [#144](https://github.com/dotansimha/graphql-code-generator/issues/144) -- Fixed incorrect typings path (Fixes [#143](https://github.com/dotansimha/graphql-code-generator/issues/143)) -- Simplify fragment emitting for selection sets (Fixes [#139](https://github.com/dotansimha/graphql-code-generator/issues/139)) -- Change TypeScript optional to use `?` instead of `| null` ([#142](https://github.com/dotansimha/graphql-code-generator/pull/142)) -- Allow insecure HTTP requests (Fixes [#137](https://github.com/dotansimha/graphql-code-generator/issues/137)) - - - -## [0.8.10](https://github.com/dotansimha/graphql-codegen/compare/0.8.9...0.8.10) (2017-07-24) - -- Fixed bug with relative path for export JS - - - -## [0.8.9](https://github.com/dotansimha/graphql-codegen/compare/0.8.8...0.8.9) (2017-07-24) - -- Fixed bug with relative path for file schema - - - -## [0.8.8](https://github.com/dotansimha/graphql-codegen/compare/0.8.7...0.8.8) (2017-07-24) - -- Added support for custom helpers when generating custom templates -- Added more Handlebars helpers -- Some fixed for `ifDirective` helper -- Updated docs - - - -## [0.8.7](https://github.com/dotansimha/graphql-codegen/compare/0.8.6...0.8.7) (2017-07-23) - -- Fixed issue with remote GraphQL endpoint and custom headers - - - -## [0.8.6](https://github.com/dotansimha/graphql-codegen/compare/0.8.5...0.8.6) (2017-07-20) - -- Fixed issue with loading GraphQLSchema export from JS file -- Changed `graphql` to be peer dependency to avoid multiple instance of GraphQL -- Fixed issue with custom templates without prefix name - - - -## [0.8.5](https://github.com/dotansimha/graphql-codegen/compare/0.8.4...0.8.5) (2017-07-19) - -- Fixed issue with missing indicators for variables and selection set node -- Better imports optimization and detection -- Removed default file extension for imports builder - - - -## [0.8.4](https://github.com/dotansimha/graphql-codegen/compare/0.8.3...0.8.4) (2017-07-19) - -- Fixed issue with generated result missing Fragment spread -- Fixed issue with wrong output for GraphQL primitives -- Fixed issue with default output file overrides the `out` cli parameter - - - -## [0.8.3](https://github.com/dotansimha/graphql-codegen/compare/0.8.2...0.8.3) (2017-07-19) - -- Fixed issue with \_\_typename in selectionSet - - - -## [0.8.2](https://github.com/dotansimha/graphql-codegen/compare/0.8.1...0.8.2) (2017-07-18) - -- Fixed issue with NPM installation - - - -## [0.8.1](https://github.com/dotansimha/graphql-codegen/compare/0.8.0...0.8.1) (2017-07-18) - -- Fixed issue with NPM installation - - - -## [0.8.0](https://github.com/dotansimha/graphql-codegen/compare/0.5.5...0.8.0) (2017-07-17) - -- Refactor everything :) - - - -## [0.5.5](https://github.com/dotansimha/graphql-codegen/compare/0.5.4...0.5.5) (2017-07-13) - -- fixed peer dependencies issue -- fixed error with template resolution [PR #110](https://github.com/dotansimha/graphql-code-generator/pull/110) -- update depndencies -- Prevent primitives from being output like other models [PR #116](https://github.com/dotansimha/graphql-code-generator/pull/116) - - - -## [0.5.4](https://github.com/dotansimha/graphql-codegen/compare/0.5.2...0.5.4) (2017-06-24) - -- updated all dependencies - - - -## [0.5.2](https://github.com/dotansimha/graphql-codegen/compare/0.5.1...v0.5.2) (2017-05-03) - -## Bug fixes - -- Added support for Anonymous operations (closes [#82](https://github.com/dotansimha/graphql-code-generator/issues/82)) -- Fixed a bug with missing root types (closes [#83](https://github.com/dotansimha/graphql-code-generator/issues/83)) -- Fixed a bug with multiple extends for TypeScript generator [#81](https://github.com/dotansimha/graphql-code-generator/pull/81) - Thanks @Anthonyzou -- Fixed a issue with generated TypeScript file and TSLint warnings [#81](https://github.com/dotansimha/graphql-code-generator/pull/81) - Thanks @Anthonyzou - -### Other - -- Updated all dependencies to their latest version. -- **package:** update graphql to version 0.9.1 ([2782925](https://github.com/dotansimha/graphql-codegen/commit/2782925)) - - - -## [0.5.1](https://github.com/dotansimha/graphql-codegen/compare/0.5.0...v0.5.1) (2017-01-03) - -- updated dependecies - - - -# [0.5.0](https://github.com/dotansimha/graphql-codegen/compare/0.3.0...v0.5.0) (2016-12-29) - -### Features - -- **core:** add support for loading GraphQL schema from js export file ([1587ef7](https://github.com/dotansimha/graphql-codegen/commit/1587ef7)) - - - -# [0.4.0](https://github.com/dotansimha/graphql-codegen/compare/0.3.0...v0.4.0) (2016-12-28) - -### Bug Fixes - -- **package:** update [@types](https://github.com/types)/request to version 0.0.37 ([4fcdc32](https://github.com/dotansimha/graphql-codegen/commit/4fcdc32)) - -### Features - -- **libify:** added lib exports ([7175e11](https://github.com/dotansimha/graphql-codegen/commit/7175e11)) -- **core:** added support for server side schema arguments - - - -# [0.3.0](https://github.com/dotansimha/graphql-codegen/compare/0.2.5...v0.3.0) (2016-12-26) - -### Bug Fixes - -- **generators:** fixes for ts generators ([2f72d44](https://github.com/dotansimha/graphql-codegen/commit/2f72d44)) - -### Features - -- **generators:** generated ts/swift result examples ([e43f289](https://github.com/dotansimha/graphql-codegen/commit/e43f289)) -- **generators:** swift with Apollo iOS generator ([cee08c8](https://github.com/dotansimha/graphql-codegen/commit/cee08c8)) -- **generators:** add support for fragments spread for swift generator ([f95fa72](https://github.com/dotansimha/graphql-codegen/commit/f95fa72)) -- **generators:** More fixes for swift generator ([487a249](https://github.com/dotansimha/graphql-codegen/commit/487a249)) - - - -## [0.2.5](https://github.com/dotansimha/graphql-codegen/compare/0.2.4...v0.2.5) (2016-12-24) - -### Bug Fixes - -- **generators:** fixed a small bug with typescript generator after code modifications ([33a4b83](https://github.com/dotansimha/graphql-codegen/commit/33a4b83)) - -### Features - -- **generators:** WIP: added swift generator support for inline fragments ([3c087b4](https://github.com/dotansimha/graphql-codegen/commit/3c087b4)) -- **generators:** WIP: some more fixes and template code for swift generator ([3b0d0f9](https://github.com/dotansimha/graphql-codegen/commit/3b0d0f9)) -- **generators:** WIP: swift generator and some bug fixes ([f5b0b92](https://github.com/dotansimha/graphql-codegen/commit/f5b0b92)) - - - -## [0.2.4](https://github.com/dotansimha/graphql-codegen/compare/0.2.3...v0.2.4) (2016-12-24) - -### Features - -- **cli:** add support for --no-documents and --no-schema flags ([1a6a692](https://github.com/dotansimha/graphql-codegen/commit/1a6a692)) - - - -## [0.2.3](https://github.com/dotansimha/graphql-codegen/compare/0.2.2...v0.2.3) (2016-12-24) - -### Features - -- **documents-finder:** add support for finding GraphQL documents inside code files ([1d11980](https://github.com/dotansimha/graphql-codegen/commit/1d11980)) - - - -## [0.2.2](https://github.com/dotansimha/graphql-codegen/compare/0.2.1...v0.2.2) (2016-12-23) - -### Bug Fixes - -- **fragments:** added rootType to fragments ([af9b932](https://github.com/dotansimha/graphql-codegen/commit/af9b932)) - - - -## [0.2.1](https://github.com/dotansimha/graphql-codegen/compare/0.2.0...v0.2.1) (2016-12-23) - -### Features - -- **flatten, partials:** add support for non-flatten innerTypes ([1f6d001](https://github.com/dotansimha/graphql-codegen/commit/1f6d001)) - - - -# [0.2.0](https://github.com/dotansimha/graphql-codegen/compare/0.1.9...v0.2.0) (2016-12-14) - -### Features - -- **core:** added custom headers for remote GraphQL endpoint ([d3b2cf9](https://github.com/dotansimha/graphql-codegen/commit/d3b2cf9)) - - - -## [0.1.9](https://github.com/dotansimha/graphql-codegen/compare/0.1.8...v0.1.9) (2016-12-14) - -### Features - -- **cli:** added package version to cli ([df698d8](https://github.com/dotansimha/graphql-codegen/commit/df698d8)) -- **core:** added support for custom scalar types ([6ce7aa9](https://github.com/dotansimha/graphql-codegen/commit/6ce7aa9)) - - - -## 0.1.8 (2016-12-14) - -### Bug Fixes - -- **core:** fixes for cli and template path resolve ([b7a3540](https://github.com/dotansimha/graphql-codegen/commit/b7a3540)) -- **typescript:** fixed enum template ([c05acd6](https://github.com/dotansimha/graphql-codegen/commit/c05acd6)) - -### Features - -- **cli:** added basic cli support ([12b4458](https://github.com/dotansimha/graphql-codegen/commit/12b4458)) -- **cli:** added support for introspection from URL, and updated README ([cc15899](https://github.com/dotansimha/graphql-codegen/commit/cc15899)) -- **core:** added document content, added basic Swift generated content ([2d144ff](https://github.com/dotansimha/graphql-codegen/commit/2d144ff)) -- **core:** added generated root result object to the generated innertypes ([086d019](https://github.com/dotansimha/graphql-codegen/commit/086d019)) -- **core:** added handlebars helpers and added more swift support ([657c9f6](https://github.com/dotansimha/graphql-codegen/commit/657c9f6)) -- **core:** added inner types resolution and basic typescript template ([c173fc3](https://github.com/dotansimha/graphql-codegen/commit/c173fc3)) -- **core:** added more template helpers and added variables generation ([6da0d88](https://github.com/dotansimha/graphql-codegen/commit/6da0d88)) -- **core:** added primitives map, fixes for typescript generators ([ebc117b](https://github.com/dotansimha/graphql-codegen/commit/ebc117b)) -- **core:** added support for generated fragments and it's use inside documents ([fbd268c](https://github.com/dotansimha/graphql-codegen/commit/fbd268c)) -- **core:** added support for generated type as array based on server-side schema ([a37c849](https://github.com/dotansimha/graphql-codegen/commit/a37c849)) -- **core:** added support for index file for multiple-files generators ([7519de0](https://github.com/dotansimha/graphql-codegen/commit/7519de0)) -- **core:** added support for inline fragments ([f432ecd](https://github.com/dotansimha/graphql-codegen/commit/f432ecd)) -- **core:** added support for multiple-files generation, added typescript-multiple generator, added ([0af3cd0](https://github.com/dotansimha/graphql-codegen/commit/0af3cd0)) -- **core:** added support for operations variables generation ([a9bf28f](https://github.com/dotansimha/graphql-codegen/commit/a9bf28f)) -- **core:** added support for schema interfaces, and update typescript generator ([22d3ad0](https://github.com/dotansimha/graphql-codegen/commit/22d3ad0)) -- **core:** added support for server side types generation only ([2bec16f](https://github.com/dotansimha/graphql-codegen/commit/2bec16f)) -- **core:** added support for spread fragment when used in client side query ([8e9b093](https://github.com/dotansimha/graphql-codegen/commit/8e9b093)) -- **core:** added support for union types, updated typescript templates ([0172461](https://github.com/dotansimha/graphql-codegen/commit/0172461)) -- **core:** fixes for generated array types ([e2fb340](https://github.com/dotansimha/graphql-codegen/commit/e2fb340)) -- **core:** handle multiple inner types with the same name ([614ea3a](https://github.com/dotansimha/graphql-codegen/commit/614ea3a)) -- **core:** minor fixes and some changes in swift generator ([8d30bad](https://github.com/dotansimha/graphql-codegen/commit/8d30bad)) -- **core:** minor name fix ([5509b1d](https://github.com/dotansimha/graphql-codegen/commit/5509b1d)) -- **core:** remove swift ([85f1956](https://github.com/dotansimha/graphql-codegen/commit/85f1956)) -- **core:** some fixes ([60d4494](https://github.com/dotansimha/graphql-codegen/commit/60d4494)) -- **core, cli:** added cli and more core features ([b858693](https://github.com/dotansimha/graphql-codegen/commit/b858693)) -- **flow:** add flow generator template ([af72bbb](https://github.com/dotansimha/graphql-codegen/commit/af72bbb)) -- **generator:** added code generator for scheme basic types ([f04b3a0](https://github.com/dotansimha/graphql-codegen/commit/f04b3a0)) -- **generator:** added typescript basic template ([00739db](https://github.com/dotansimha/graphql-codegen/commit/00739db)) -- **generator:** fixes for type handling and added support for lists and nullable types ([8c4c498](https://github.com/dotansimha/graphql-codegen/commit/8c4c498)) -- **generator:** minor fixes for code generation for schema ([f69f375](https://github.com/dotansimha/graphql-codegen/commit/f69f375)) -- **generator:** refactor some code of the generator, added stub for operation handler ([156d710](https://github.com/dotansimha/graphql-codegen/commit/156d710)) -- **loader:** added basic schema loader and validator from JSON introspection file ([13b3dec](https://github.com/dotansimha/graphql-codegen/commit/13b3dec)) -- **parser:** added basic parser for documents and added some basic interfaces ([8ecaf4e](https://github.com/dotansimha/graphql-codegen/commit/8ecaf4e)) -- **typescript:** fixed issue with fragment name ([e3799da](https://github.com/dotansimha/graphql-codegen/commit/e3799da)) +## CHANGELOG moved to [GitHub releases](https://github.com/dotansimha/graphql-code-generator/releases) diff --git a/README.md b/README.md index c432e97a9b4..61df42532c7 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ If you don't want to use the wizard, create a basic `codegen.yml` configuration schema: http://localhost:3000/graphql generates: src/types.ts: - - typescript-common + - typescript - typescript-server ``` diff --git a/dev-test/codegen-watch.yml b/dev-test/codegen-watch.yml deleted file mode 100644 index bcd69456f1a..00000000000 --- a/dev-test/codegen-watch.yml +++ /dev/null @@ -1,9 +0,0 @@ -overwrite: true -watch: true -generates: - ./dev-test/githunt/types.ts: - schema: ./dev-test/githunt/schema.json - documents: ./dev-test/githunt/**/*.graphql - plugins: - - typescript-common - - typescript-client diff --git a/dev-test/codegen.yml b/dev-test/codegen.yml index 47adb027574..ae6daea2c2d 100644 --- a/dev-test/codegen.yml +++ b/dev-test/codegen.yml @@ -4,8 +4,7 @@ generates: schema: ./dev-test/test-schema/schema-text.js plugins: - add: // tslint:disable - - typescript-common - - typescript-server + - typescript - typescript-resolvers ./dev-test/test-schema/flow-types.flow.js: schema: ./dev-test/test-schema/schema.json @@ -16,30 +15,26 @@ generates: schema: ./dev-test/test-schema/schema-with-root.graphql plugins: - add: // tslint:disable - - typescript-common - - typescript-server + - typescript - typescript-resolvers ./dev-test/test-schema/typings.ts: schema: ./dev-test/test-schema/schema.json plugins: - add: // tslint:disable - - typescript-common - - typescript-server + - typescript - typescript-resolvers ./dev-test/test-schema/typings.avoidOptionals.ts: schema: ./dev-test/test-schema/schema.json config: avoidOptionals: true plugins: - - typescript-common - - typescript-server + - typescript ./dev-test/test-schema/typings.immutableTypes.ts: schema: ./dev-test/test-schema/schema.json config: imutableTypes: true plugins: - - typescript-common - - typescript-server + - typescript ./dev-test/githunt/graphql-declared-modules.d.ts: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql @@ -51,153 +46,114 @@ generates: documents: ./dev-test/githunt/**/*.graphql plugins: - flow - - flow-documents + - flow-operations ./dev-test/githunt/types.ts: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/githunt/types.enumsAsTypes.ts: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql config: enumsAsTypes: true plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/githunt/types.d.ts: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql config: enumsAsTypes: true plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/githunt/types.avoidOptionals.ts: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql config: avoidOptionals: true plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/githunt/types.immutableTypes.ts: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql config: immutableTypes: true plugins: - - typescript-common - - typescript-client - ./dev-test/githunt/types.noNamespaces.ts: + - typescript + - typescript-operations + ./dev-test/githunt/types.reactApollo.tsx: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql - config: - noNamespaces: true plugins: - - typescript-common - - typescript-client - ./dev-test/githunt/types.reactApollo.tsx: + - add: // tslint:disable + - typescript + - typescript-operations + - typescript-react-apollo + ./dev-test/githunt/types.reactApollo.hooks.tsx: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql plugins: - add: // tslint:disable - - typescript-common - - typescript-client + - typescript + - typescript-operations - typescript-react-apollo - ./dev-test/githunt/types.reactApollo.noNamespaces.tsx: + config: + withHooks: true + ./dev-test/githunt/types.stencilApollo.tsx: schema: ./dev-test/githunt/schema.json documents: ./dev-test/githunt/**/*.graphql - config: - noNamespaces: true plugins: - add: // tslint:disable - - typescript-common - - typescript-client - - typescript-react-apollo + - typescript + - typescript-operations + - typescript-stencil-apollo + ./dev-test/githunt/types.stencilApollo.class.tsx: + schema: ./dev-test/githunt/schema.json + documents: ./dev-test/githunt/**/*.graphql + plugins: + - add: // tslint:disable + - typescript + - typescript-operations + - typescript-stencil-apollo + config: + componentType: class ./dev-test/star-wars/types.ts: schema: ./dev-test/star-wars/schema.json documents: ./dev-test/star-wars/**/*.graphql plugins: - - typescript-common - - typescript-client - ./dev-test/star-wars/types.uppercase-enums.ts: - schema: ./dev-test/star-wars/schema.json - plugins: - - add: // tslint:disable - - typescript-common - - typescript-server - config: - namingConvention: - default: change-case#pascalCase - enumValues: change-case#upperCase + - typescript + - typescript-operations ./dev-test/star-wars/types.d.ts: schema: ./dev-test/star-wars/schema.json documents: ./dev-test/star-wars/**/*.graphql config: enumsAsTypes: true plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/star-wars/types.avoidOptionals.ts: schema: ./dev-test/star-wars/schema.json documents: ./dev-test/star-wars/**/*.graphql config: avoidOptionals: true plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/star-wars/types.immutableTypes.ts: schema: ./dev-test/star-wars/schema.json documents: ./dev-test/star-wars/**/*.graphql config: immutableTypes: true plugins: - - typescript-common - - typescript-client - ./dev-test/star-wars/types.noNamespaces.ts: - schema: ./dev-test/star-wars/schema.json - documents: ./dev-test/star-wars/**/*.graphql - config: - immutableTypes: true - plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ./dev-test/star-wars/types.skipSchema.ts: schema: ./dev-test/star-wars/schema.json documents: ./dev-test/star-wars/**/*.graphql plugins: - - typescript-common - - typescript-client - ./dev-test/test-message/types.reactApollo.noNamespaces.tsx: - schema: ./dev-test/test-message/schema.graphql - documents: ./dev-test/test-message/documents.ts - config: - noNamespaces: true - plugins: - - add: // tslint:disable - - typescript-common - - typescript-client - - typescript-react-apollo - ./dev-test/test-message/types.stencilApollo.noNamespaces.tsx: - schema: ./dev-test/test-message/schema.graphql - documents: ./dev-test/test-message/documents.ts - config: - noNamespaces: true - plugins: - - add: // tslint:disable - - typescript-common - - typescript-client - - typescript-stencil-apollo - ./dev-test/test-mongodb/types.ts: - schema: ./dev-test/test-mongodb/schema.graphql - config: - scalars: - Date: Date - plugins: - - add: // tslint:disable - - typescript-common - - typescript-server - - typescript-mongodb - - typescript-resolvers + - typescript + - typescript-operations diff --git a/dev-test/generate-all.sh b/dev-test/generate-all.sh index 45cdf7287b7..6006ff085f7 100755 --- a/dev-test/generate-all.sh +++ b/dev-test/generate-all.sh @@ -1,3 +1,3 @@ #/bin/sh -node packages/graphql-codegen-cli/dist/cli.js --config ./dev-test/codegen.yml +node packages/graphql-codegen-cli/dist/commonjs/cli.js --config ./dev-test/codegen.yml diff --git a/dev-test/generate-watch.sh b/dev-test/generate-watch.sh index c6f0095bec9..2b385d1a813 100755 --- a/dev-test/generate-watch.sh +++ b/dev-test/generate-watch.sh @@ -1,3 +1,3 @@ #/bin/sh -node packages/graphql-codegen-cli/dist/cli.js --config ./dev-test/codegen-watch.yml \ No newline at end of file +node packages/graphql-codegen-cli/dist/commonjs/cli.js --config ./dev-test/codegen.yml -w diff --git a/dev-test/githunt/graphql-declared-modules.d.ts b/dev-test/githunt/graphql-declared-modules.d.ts index a45f2ad576d..30f44516ebf 100644 --- a/dev-test/githunt/graphql-declared-modules.d.ts +++ b/dev-test/githunt/graphql-declared-modules.d.ts @@ -1,133 +1,100 @@ // tslint:disable + declare module '*/comment-added.subscription.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const onCommentAdded: DocumentNode; - - export { - onCommentAdded, - }; + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const onCommentAdded: DocumentNode; - export default defaultDocument; + export default defaultDocument; } + declare module '*/comment.query.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const Comment: DocumentNode; + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const Comment: DocumentNode; + + export default defaultDocument; +} - export { - Comment, - }; - export default defaultDocument; +declare module '*/comments-page-comment.fragment.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const CommentsPageComment: DocumentNode; + + export default defaultDocument; } + declare module '*/current-user.query.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const CurrentUserForProfile: DocumentNode; + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const CurrentUserForProfile: DocumentNode; + + export default defaultDocument; +} - export { - CurrentUserForProfile, - }; - export default defaultDocument; +declare module '*/feed-entry.fragment.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const FeedEntry: DocumentNode; + + export default defaultDocument; } + declare module '*/feed.query.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const Feed: DocumentNode; - - export { - Feed, - }; + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const Feed: DocumentNode; - export default defaultDocument; + export default defaultDocument; } + declare module '*/new-entry.mutation.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const submitRepository: DocumentNode; - - export { - submitRepository, - }; + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const submitRepository: DocumentNode; - export default defaultDocument; + export default defaultDocument; } - -declare module '*/submit-comment.mutation.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const submitComment: DocumentNode; - export { - submitComment, - }; - - export default defaultDocument; -} -declare module '*/vote.mutation.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - const vote: DocumentNode; - - export { - vote, - }; +declare module '*/repo-info.fragment.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const RepoInfo: DocumentNode; - export default defaultDocument; + export default defaultDocument; } - -declare module '*/comments-page-comment.fragment.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - - export { - - }; - - export default defaultDocument; -} -declare module '*/feed-entry.fragment.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - - - export { - - }; +declare module '*/submit-comment.mutation.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const submitComment: DocumentNode; - export default defaultDocument; + export default defaultDocument; } - -declare module '*/repo-info.fragment.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - - export { - - }; - - export default defaultDocument; -} declare module '*/vote-buttons.fragment.graphql' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - - - export { - - }; + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const VoteButtons: DocumentNode; - export default defaultDocument; + export default defaultDocument; } + +declare module '*/vote.mutation.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const vote: DocumentNode; + + export default defaultDocument; +} + \ No newline at end of file diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 5aae0f25a6b..7930dfc05e5 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -1,323 +1,168 @@ -export type Maybe = T | null; - -/** A list of options for the sort order of the feed */ - export enum FeedType { - Hot = 'HOT', - New = 'NEW', - Top = 'TOP', - } -/** The type of vote to record, when submitting a vote */ - export enum VoteType { - Up = 'UP', - Down = 'DOWN', - Cancel = 'CANCEL', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace OnCommentAdded { - export type Variables = { - repoFullName: string; - }; - - export type Subscription = { - __typename?: 'Subscription'; - - commentAdded: Maybe; - }; - - export type CommentAdded = { - __typename?: 'Comment'; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - }; - - export type PostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit: Maybe, + offset: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' } -export namespace Comment { - export type Variables = { - repoFullName: string; - limit: Maybe; - offset: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - currentUser: Maybe; - - entry: Maybe; - }; +export type Mutation = { + submitRepository: Maybe, + vote: Maybe, + submitComment: Maybe, +}; - export type CurrentUser = { - __typename?: 'User'; - login: string; +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; - html_url: string; - }; - export type Entry = { - __typename?: 'Entry'; +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; - id: number; - postedBy: PostedBy; +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; - createdAt: number; +export type Query = { + feed: Maybe>>, + entry: Maybe, + currentUser: Maybe, +}; - comments: (Maybe)[]; - commentCount: number; +export type QueryFeedArgs = { + type: FeedType, + offset: Maybe, + limit: Maybe +}; - repository: Repository; - }; - export type PostedBy = { - __typename?: 'User'; +export type QueryEntryArgs = { + repoFullName: string +}; - login: string; +export type Repository = { + name: string, + full_name: string, + description: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count: Maybe, + owner: Maybe, +}; - html_url: string; - }; +export type Subscription = { + commentAdded: Maybe, +}; - export type Comments = CommentsPageComment.Fragment; - export type Repository = { - __typename?: RepositoryInlineFragment['__typename']; +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; - full_name: string; +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; - html_url: string; - } & RepositoryInlineFragment; +export type Vote = { + vote_value: number, +}; - export type RepositoryInlineFragment = { - __typename?: 'Repository'; - - description: Maybe; - - open_issues_count: Maybe; - - stargazers_count: number; - }; -} - -export namespace CurrentUserForProfile { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - currentUser: Maybe; - }; - - export type CurrentUser = { - __typename?: 'User'; - - login: string; - - avatar_url: string; - }; +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' } +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; -export namespace Feed { - export type Variables = { - type: FeedType; - offset: Maybe; - limit: Maybe; - }; - export type Query = { - __typename?: 'Query'; +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); - currentUser: Maybe; +export type CommentQueryVariables = { + repoFullName: string, + limit: Maybe, + offset: Maybe +}; - feed: Maybe<(Maybe)[]>; - }; - export type CurrentUser = { - __typename?: 'User'; +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); - login: string; - }; +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); - export type Feed = FeedEntry.Fragment; -} +export type CurrentUserForProfileQueryVariables = {}; -export namespace SubmitRepository { - export type Variables = { - repoFullName: string; - }; - export type Mutation = { - __typename?: 'Mutation'; +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); - submitRepository: Maybe; - }; +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); - export type SubmitRepository = { - __typename?: 'Entry'; +export type FeedQueryVariables = { + type: FeedType, + offset: Maybe, + limit: Maybe +}; - createdAt: number; - }; -} -export namespace SubmitComment { - export type Variables = { - repoFullName: string; - commentContent: string; - }; +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); - export type Mutation = { - __typename?: 'Mutation'; +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; - submitComment: Maybe; - }; - - export type SubmitComment = CommentsPageComment.Fragment; -} -export namespace Vote { - export type Variables = { - repoFullName: string; - type: VoteType; - }; +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); - export type Mutation = { - __typename?: 'Mutation'; +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); - vote: Maybe; - }; +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; - export type Vote = { - __typename?: 'Entry'; - score: number; +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); - id: number; - - vote: _Vote; - }; - - export type _Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); -export namespace CommentsPageComment { - export type Fragment = { - __typename?: 'Comment'; +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - }; - - export type PostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; -} - -export namespace FeedEntry { - export type Fragment = { - __typename?: 'Entry'; - - id: number; - - commentCount: number; - - repository: Repository; - } & (VoteButtons.Fragment & RepoInfo.Fragment); - - export type Repository = { - __typename?: 'Repository'; - - full_name: string; - - html_url: string; - - owner: Maybe; - }; - - export type Owner = { - __typename?: 'User'; - - avatar_url: string; - }; -} - -export namespace RepoInfo { - export type Fragment = { - __typename?: 'Entry'; - - createdAt: number; - - repository: Repository; - - postedBy: PostedBy; - }; - - export type Repository = { - __typename?: 'Repository'; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - }; - - export type PostedBy = { - __typename?: 'User'; - - html_url: string; - - login: string; - }; -} - -export namespace VoteButtons { - export type Fragment = { - __typename?: 'Entry'; - - score: number; - - vote: Vote; - }; - - export type Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 27ff1ecbcde..90abe027980 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -1,315 +1,160 @@ -export type Maybe = T | null; +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; -/** A list of options for the sort order of the feed */ - export type FeedType = 'HOT' | 'NEW' | 'TOP'; -/** The type of vote to record, when submitting a vote */ - export type VoteType = 'UP' | 'DOWN' | 'CANCEL'; +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; -// ==================================================== -// Documents -// ==================================================== +export type FeedType = 'HOT' | 'NEW' | 'TOP'; +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; -export namespace OnCommentAdded { - export type Variables = { - repoFullName: string; - }; +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; - export type Subscription = { - __typename?: 'Subscription'; - commentAdded: Maybe; - }; +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; - export type CommentAdded = { - __typename?: 'Comment'; - id: number; +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; - postedBy: PostedBy; +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; - createdAt: number; - content: string; - }; +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - export type PostedBy = { - __typename?: 'User'; - login: string; +export type QueryEntryArgs = { + repoFullName: string +}; - html_url: string; - }; -} +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; -export namespace Comment { - export type Variables = { - repoFullName: string; - limit?: Maybe; - offset?: Maybe; - }; +export type Subscription = { + commentAdded?: Maybe, +}; - export type Query = { - __typename?: 'Query'; - currentUser: Maybe; +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; - entry: Maybe; - }; +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; - export type CurrentUser = { - __typename?: 'User'; +export type Vote = { + vote_value: number, +}; - login: string; +export type VoteType = 'UP' | 'DOWN' | 'CANCEL'; +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; - html_url: string; - }; - export type Entry = { - __typename?: 'Entry'; +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); - id: number; +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; - postedBy: PostedBy; - createdAt: number; +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); - comments: (Maybe)[]; +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); - commentCount: number; +export type CurrentUserForProfileQueryVariables = {}; - repository: Repository; - }; - export type PostedBy = { - __typename?: 'User'; +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); - login: string; +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); - html_url: string; - }; +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - export type Comments = CommentsPageComment.Fragment; - export type Repository = { - __typename?: RepositoryInlineFragment['__typename']; +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); - full_name: string; +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; - html_url: string; - } & RepositoryInlineFragment; - export type RepositoryInlineFragment = { - __typename?: 'Repository'; +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); - description: Maybe; +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); - open_issues_count: Maybe; +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; - stargazers_count: number; - }; -} -export namespace CurrentUserForProfile { - export type Variables = { - }; +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); - export type Query = { - __typename?: 'Query'; +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); - currentUser: Maybe; - }; +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; - export type CurrentUser = { - __typename?: 'User'; - - login: string; - - avatar_url: string; - }; -} - -export namespace Feed { - export type Variables = { - type: FeedType; - offset?: Maybe; - limit?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - currentUser: Maybe; - - feed: Maybe<(Maybe)[]>; - }; - - export type CurrentUser = { - __typename?: 'User'; - - login: string; - }; - - export type Feed = FeedEntry.Fragment; -} - -export namespace SubmitRepository { - export type Variables = { - repoFullName: string; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - submitRepository: Maybe; - }; - - export type SubmitRepository = { - __typename?: 'Entry'; - - createdAt: number; - }; -} - -export namespace SubmitComment { - export type Variables = { - repoFullName: string; - commentContent: string; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - submitComment: Maybe; - }; - - export type SubmitComment = CommentsPageComment.Fragment; -} - -export namespace Vote { - export type Variables = { - repoFullName: string; - type: VoteType; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - vote: Maybe; - }; - - export type Vote = { - __typename?: 'Entry'; - - score: number; - - id: number; - - vote: _Vote; - }; - - export type _Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} - -export namespace CommentsPageComment { - export type Fragment = { - __typename?: 'Comment'; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - }; - - export type PostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; -} - -export namespace FeedEntry { - export type Fragment = { - __typename?: 'Entry'; - - id: number; - - commentCount: number; - - repository: Repository; - } & (VoteButtons.Fragment & RepoInfo.Fragment); - - export type Repository = { - __typename?: 'Repository'; - - full_name: string; - - html_url: string; - - owner: Maybe; - }; - - export type Owner = { - __typename?: 'User'; - - avatar_url: string; - }; -} - -export namespace RepoInfo { - export type Fragment = { - __typename?: 'Entry'; - - createdAt: number; - - repository: Repository; - - postedBy: PostedBy; - }; - - export type Repository = { - __typename?: 'Repository'; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - }; - - export type PostedBy = { - __typename?: 'User'; - - html_url: string; - - login: string; - }; -} - -export namespace VoteButtons { - export type Fragment = { - __typename?: 'Entry'; - - score: number; - - vote: Vote; - }; - - export type Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 27ff1ecbcde..90abe027980 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -1,315 +1,160 @@ -export type Maybe = T | null; +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; -/** A list of options for the sort order of the feed */ - export type FeedType = 'HOT' | 'NEW' | 'TOP'; -/** The type of vote to record, when submitting a vote */ - export type VoteType = 'UP' | 'DOWN' | 'CANCEL'; +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; -// ==================================================== -// Documents -// ==================================================== +export type FeedType = 'HOT' | 'NEW' | 'TOP'; +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; -export namespace OnCommentAdded { - export type Variables = { - repoFullName: string; - }; +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; - export type Subscription = { - __typename?: 'Subscription'; - commentAdded: Maybe; - }; +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; - export type CommentAdded = { - __typename?: 'Comment'; - id: number; +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; - postedBy: PostedBy; +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; - createdAt: number; - content: string; - }; +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - export type PostedBy = { - __typename?: 'User'; - login: string; +export type QueryEntryArgs = { + repoFullName: string +}; - html_url: string; - }; -} +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; -export namespace Comment { - export type Variables = { - repoFullName: string; - limit?: Maybe; - offset?: Maybe; - }; +export type Subscription = { + commentAdded?: Maybe, +}; - export type Query = { - __typename?: 'Query'; - currentUser: Maybe; +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; - entry: Maybe; - }; +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; - export type CurrentUser = { - __typename?: 'User'; +export type Vote = { + vote_value: number, +}; - login: string; +export type VoteType = 'UP' | 'DOWN' | 'CANCEL'; +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; - html_url: string; - }; - export type Entry = { - __typename?: 'Entry'; +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); - id: number; +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; - postedBy: PostedBy; - createdAt: number; +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); - comments: (Maybe)[]; +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); - commentCount: number; +export type CurrentUserForProfileQueryVariables = {}; - repository: Repository; - }; - export type PostedBy = { - __typename?: 'User'; +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); - login: string; +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); - html_url: string; - }; +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - export type Comments = CommentsPageComment.Fragment; - export type Repository = { - __typename?: RepositoryInlineFragment['__typename']; +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); - full_name: string; +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; - html_url: string; - } & RepositoryInlineFragment; - export type RepositoryInlineFragment = { - __typename?: 'Repository'; +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); - description: Maybe; +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); - open_issues_count: Maybe; +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; - stargazers_count: number; - }; -} -export namespace CurrentUserForProfile { - export type Variables = { - }; +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); - export type Query = { - __typename?: 'Query'; +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); - currentUser: Maybe; - }; +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; - export type CurrentUser = { - __typename?: 'User'; - - login: string; - - avatar_url: string; - }; -} - -export namespace Feed { - export type Variables = { - type: FeedType; - offset?: Maybe; - limit?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - currentUser: Maybe; - - feed: Maybe<(Maybe)[]>; - }; - - export type CurrentUser = { - __typename?: 'User'; - - login: string; - }; - - export type Feed = FeedEntry.Fragment; -} - -export namespace SubmitRepository { - export type Variables = { - repoFullName: string; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - submitRepository: Maybe; - }; - - export type SubmitRepository = { - __typename?: 'Entry'; - - createdAt: number; - }; -} - -export namespace SubmitComment { - export type Variables = { - repoFullName: string; - commentContent: string; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - submitComment: Maybe; - }; - - export type SubmitComment = CommentsPageComment.Fragment; -} - -export namespace Vote { - export type Variables = { - repoFullName: string; - type: VoteType; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - vote: Maybe; - }; - - export type Vote = { - __typename?: 'Entry'; - - score: number; - - id: number; - - vote: _Vote; - }; - - export type _Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} - -export namespace CommentsPageComment { - export type Fragment = { - __typename?: 'Comment'; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - }; - - export type PostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; -} - -export namespace FeedEntry { - export type Fragment = { - __typename?: 'Entry'; - - id: number; - - commentCount: number; - - repository: Repository; - } & (VoteButtons.Fragment & RepoInfo.Fragment); - - export type Repository = { - __typename?: 'Repository'; - - full_name: string; - - html_url: string; - - owner: Maybe; - }; - - export type Owner = { - __typename?: 'User'; - - avatar_url: string; - }; -} - -export namespace RepoInfo { - export type Fragment = { - __typename?: 'Entry'; - - createdAt: number; - - repository: Repository; - - postedBy: PostedBy; - }; - - export type Repository = { - __typename?: 'Repository'; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - }; - - export type PostedBy = { - __typename?: 'User'; - - html_url: string; - - login: string; - }; -} - -export namespace VoteButtons { - export type Fragment = { - __typename?: 'Entry'; - - score: number; - - vote: Vote; - }; - - export type Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 8e02e202a19..84453cd6bb6 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -1,323 +1,168 @@ -export type Maybe = T | null; - -/** A list of options for the sort order of the feed */ - export enum FeedType { - Hot = 'HOT', - New = 'NEW', - Top = 'TOP', - } -/** The type of vote to record, when submitting a vote */ - export enum VoteType { - Up = 'UP', - Down = 'DOWN', - Cancel = 'CANCEL', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace OnCommentAdded { - export type Variables = { - readonly repoFullName: string; - }; - - export type Subscription = { - readonly __typename?: 'Subscription'; - - readonly commentAdded: Maybe; - }; - - export type CommentAdded = { - readonly __typename?: 'Comment'; - - readonly id: number; - - readonly postedBy: PostedBy; - - readonly createdAt: number; - - readonly content: string; - }; - - export type PostedBy = { - readonly __typename?: 'User'; - - readonly login: string; - - readonly html_url: string; - }; +type Maybe = T | null; +export type Comment = { + readonly id: number, + readonly postedBy: User, + readonly createdAt: number, + readonly content: string, + readonly repoName: string, +}; + +export type Entry = { + readonly repository: Repository, + readonly postedBy: User, + readonly createdAt: number, + readonly score: number, + readonly hotScore: number, + readonly comments: ReadonlyArray>, + readonly commentCount: number, + readonly id: number, + readonly vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' } -export namespace Comment { - export type Variables = { - readonly repoFullName: string; - readonly limit?: Maybe; - readonly offset?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly currentUser: Maybe; - - readonly entry: Maybe; - }; +export type Mutation = { + readonly submitRepository?: Maybe, + readonly vote?: Maybe, + readonly submitComment?: Maybe, +}; - export type CurrentUser = { - readonly __typename?: 'User'; - readonly login: string; +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; - readonly html_url: string; - }; - export type Entry = { - readonly __typename?: 'Entry'; +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; - readonly id: number; - readonly postedBy: PostedBy; +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; - readonly createdAt: number; +export type Query = { + readonly feed?: Maybe>>, + readonly entry?: Maybe, + readonly currentUser?: Maybe, +}; - readonly comments: ReadonlyArray>; - readonly commentCount: number; +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - readonly repository: Repository; - }; - export type PostedBy = { - readonly __typename?: 'User'; +export type QueryEntryArgs = { + repoFullName: string +}; - readonly login: string; +export type Repository = { + readonly name: string, + readonly full_name: string, + readonly description?: Maybe, + readonly html_url: string, + readonly stargazers_count: number, + readonly open_issues_count?: Maybe, + readonly owner?: Maybe, +}; - readonly html_url: string; - }; +export type Subscription = { + readonly commentAdded?: Maybe, +}; - export type Comments = CommentsPageComment.Fragment; - export type Repository = { - readonly __typename?: RepositoryInlineFragment['__typename']; +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; - readonly full_name: string; +export type User = { + readonly login: string, + readonly avatar_url: string, + readonly html_url: string, +}; - readonly html_url: string; - } & RepositoryInlineFragment; +export type Vote = { + readonly vote_value: number, +}; - export type RepositoryInlineFragment = { - readonly __typename?: 'Repository'; - - readonly description: Maybe; - - readonly open_issues_count: Maybe; - - readonly stargazers_count: number; - }; -} - -export namespace CurrentUserForProfile { - export type Variables = { - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly currentUser: Maybe; - }; - - export type CurrentUser = { - readonly __typename?: 'User'; - - readonly login: string; - - readonly avatar_url: string; - }; +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' } +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; -export namespace Feed { - export type Variables = { - readonly type: FeedType; - readonly offset?: Maybe; - readonly limit?: Maybe; - }; - export type Query = { - readonly __typename?: 'Query'; +export type OnCommentAddedSubscription = ({ readonly __typename?: 'Subscription' } & { readonly commentAdded: Maybe<({ readonly __typename?: 'Comment' } & Pick & { readonly postedBy: ({ readonly __typename?: 'User' } & Pick) })> }); - readonly currentUser: Maybe; +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; - readonly feed: Maybe>>; - }; - export type CurrentUser = { - readonly __typename?: 'User'; +export type CommentQuery = ({ readonly __typename?: 'Query' } & { readonly currentUser: Maybe<({ readonly __typename?: 'User' } & Pick)>, readonly entry: Maybe<({ readonly __typename?: 'Entry' } & Pick & { readonly postedBy: ({ readonly __typename?: 'User' } & Pick), readonly comments: ReadonlyArray>, readonly repository: ({ readonly __typename?: 'Repository' } & Pick & (({ readonly __typename?: 'Repository' } & Pick))) })> }); - readonly login: string; - }; +export type CommentsPageCommentFragment = ({ readonly __typename?: 'Comment' } & Pick & { readonly postedBy: ({ readonly __typename?: 'User' } & Pick) }); - export type Feed = FeedEntry.Fragment; -} +export type CurrentUserForProfileQueryVariables = {}; -export namespace SubmitRepository { - export type Variables = { - readonly repoFullName: string; - }; - export type Mutation = { - readonly __typename?: 'Mutation'; +export type CurrentUserForProfileQuery = ({ readonly __typename?: 'Query' } & { readonly currentUser: Maybe<({ readonly __typename?: 'User' } & Pick)> }); - readonly submitRepository: Maybe; - }; +export type FeedEntryFragment = ({ readonly __typename?: 'Entry' } & Pick & { readonly repository: ({ readonly __typename?: 'Repository' } & Pick & { readonly owner: Maybe<({ readonly __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); - export type SubmitRepository = { - readonly __typename?: 'Entry'; +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - readonly createdAt: number; - }; -} -export namespace SubmitComment { - export type Variables = { - readonly repoFullName: string; - readonly commentContent: string; - }; +export type FeedQuery = ({ readonly __typename?: 'Query' } & { readonly currentUser: Maybe<({ readonly __typename?: 'User' } & Pick)>, readonly feed: Maybe>> }); - export type Mutation = { - readonly __typename?: 'Mutation'; +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; - readonly submitComment: Maybe; - }; - - export type SubmitComment = CommentsPageComment.Fragment; -} -export namespace Vote { - export type Variables = { - readonly repoFullName: string; - readonly type: VoteType; - }; +export type SubmitRepositoryMutation = ({ readonly __typename?: 'Mutation' } & { readonly submitRepository: Maybe<({ readonly __typename?: 'Entry' } & Pick)> }); - export type Mutation = { - readonly __typename?: 'Mutation'; +export type RepoInfoFragment = ({ readonly __typename?: 'Entry' } & Pick & { readonly repository: ({ readonly __typename?: 'Repository' } & Pick), readonly postedBy: ({ readonly __typename?: 'User' } & Pick) }); - readonly vote: Maybe; - }; +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; - export type Vote = { - readonly __typename?: 'Entry'; - readonly score: number; +export type SubmitCommentMutation = ({ readonly __typename?: 'Mutation' } & { readonly submitComment: Maybe<({ readonly __typename?: 'Comment' } & CommentsPageCommentFragment)> }); - readonly id: number; - - readonly vote: _Vote; - }; - - export type _Vote = { - readonly __typename?: 'Vote'; - - readonly vote_value: number; - }; -} +export type VoteButtonsFragment = ({ readonly __typename?: 'Entry' } & Pick & { readonly vote: ({ readonly __typename?: 'Vote' } & Pick) }); -export namespace CommentsPageComment { - export type Fragment = { - readonly __typename?: 'Comment'; +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; - readonly id: number; - - readonly postedBy: PostedBy; - - readonly createdAt: number; - - readonly content: string; - }; - - export type PostedBy = { - readonly __typename?: 'User'; - - readonly login: string; - - readonly html_url: string; - }; -} - -export namespace FeedEntry { - export type Fragment = { - readonly __typename?: 'Entry'; - - readonly id: number; - - readonly commentCount: number; - - readonly repository: Repository; - } & (VoteButtons.Fragment & RepoInfo.Fragment); - - export type Repository = { - readonly __typename?: 'Repository'; - - readonly full_name: string; - - readonly html_url: string; - - readonly owner: Maybe; - }; - - export type Owner = { - readonly __typename?: 'User'; - - readonly avatar_url: string; - }; -} - -export namespace RepoInfo { - export type Fragment = { - readonly __typename?: 'Entry'; - - readonly createdAt: number; - - readonly repository: Repository; - - readonly postedBy: PostedBy; - }; - - export type Repository = { - readonly __typename?: 'Repository'; - - readonly description: Maybe; - - readonly stargazers_count: number; - - readonly open_issues_count: Maybe; - }; - - export type PostedBy = { - readonly __typename?: 'User'; - - readonly html_url: string; - - readonly login: string; - }; -} - -export namespace VoteButtons { - export type Fragment = { - readonly __typename?: 'Entry'; - - readonly score: number; - - readonly vote: Vote; - }; - - export type Vote = { - readonly __typename?: 'Vote'; - - readonly vote_value: number; - }; -} +export type VoteMutation = ({ readonly __typename?: 'Mutation' } & { readonly vote: Maybe<({ readonly __typename?: 'Entry' } & Pick & { readonly vote: ({ readonly __typename?: 'Vote' } & Pick) })> }); diff --git a/dev-test/githunt/types.noNamespaces.ts b/dev-test/githunt/types.noNamespaces.ts deleted file mode 100644 index 40b5849d11c..00000000000 --- a/dev-test/githunt/types.noNamespaces.ts +++ /dev/null @@ -1,301 +0,0 @@ -export type Maybe = T | null; - -/** A list of options for the sort order of the feed */ - export enum FeedType { - Hot = 'HOT', - New = 'NEW', - Top = 'TOP', - } -/** The type of vote to record, when submitting a vote */ - export enum VoteType { - Up = 'UP', - Down = 'DOWN', - Cancel = 'CANCEL', - } - - -// ==================================================== -// Documents -// ==================================================== - - - - export type OnCommentAddedVariables = { - repoFullName: string; - }; - - export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; - - commentAdded: Maybe; - }; - - export type OnCommentAddedCommentAdded = { - __typename?: 'Comment'; - - id: number; - - postedBy: OnCommentAddedPostedBy; - - createdAt: number; - - content: string; - }; - - export type OnCommentAddedPostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; - - export type CommentVariables = { - repoFullName: string; - limit?: Maybe; - offset?: Maybe; - }; - - export type CommentQuery = { - __typename?: 'Query'; - - currentUser: Maybe; - - entry: Maybe; - }; - - export type CommentCurrentUser = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; - - export type CommentEntry = { - __typename?: 'Entry'; - - id: number; - - postedBy: CommentPostedBy; - - createdAt: number; - - comments: (Maybe)[]; - - commentCount: number; - - repository: CommentRepository; - }; - - export type CommentPostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; - - export type CommentComments = CommentsPageCommentFragment; - - export type CommentRepository = { - __typename?: CommentRepositoryInlineFragment['__typename']; - - full_name: string; - - html_url: string; - } & CommentRepositoryInlineFragment; - - export type CommentRepositoryInlineFragment = { - __typename?: 'Repository'; - - description: Maybe; - - open_issues_count: Maybe; - - stargazers_count: number; - }; - - export type CurrentUserForProfileVariables = { - }; - - export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - - currentUser: Maybe; - }; - - export type CurrentUserForProfileCurrentUser = { - __typename?: 'User'; - - login: string; - - avatar_url: string; - }; - - export type FeedVariables = { - type: FeedType; - offset?: Maybe; - limit?: Maybe; - }; - - export type FeedQuery = { - __typename?: 'Query'; - - currentUser: Maybe; - - feed: Maybe<(Maybe)[]>; - }; - - export type FeedCurrentUser = { - __typename?: 'User'; - - login: string; - }; - - export type FeedFeed = FeedEntryFragment; - - export type SubmitRepositoryVariables = { - repoFullName: string; - }; - - export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - - submitRepository: Maybe; - }; - - export type SubmitRepositorySubmitRepository = { - __typename?: 'Entry'; - - createdAt: number; - }; - - export type SubmitCommentVariables = { - repoFullName: string; - commentContent: string; - }; - - export type SubmitCommentMutation = { - __typename?: 'Mutation'; - - submitComment: Maybe; - }; - - export type SubmitCommentSubmitComment = CommentsPageCommentFragment; - - export type VoteVariables = { - repoFullName: string; - type: VoteType; - }; - - export type VoteMutation = { - __typename?: 'Mutation'; - - vote: Maybe; - }; - - export type VoteVote = { - __typename?: 'Entry'; - - score: number; - - id: number; - - vote: Vote_Vote; - }; - - export type Vote_Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; - - export type CommentsPageCommentFragment = { - __typename?: 'Comment'; - - id: number; - - postedBy: CommentsPageCommentPostedBy; - - createdAt: number; - - content: string; - }; - - export type CommentsPageCommentPostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; - - export type FeedEntryFragment = { - __typename?: 'Entry'; - - id: number; - - commentCount: number; - - repository: FeedEntryRepository; - } & (VoteButtonsFragment & RepoInfoFragment); - - export type FeedEntryRepository = { - __typename?: 'Repository'; - - full_name: string; - - html_url: string; - - owner: Maybe; - }; - - export type FeedEntryOwner = { - __typename?: 'User'; - - avatar_url: string; - }; - - export type RepoInfoFragment = { - __typename?: 'Entry'; - - createdAt: number; - - repository: RepoInfoRepository; - - postedBy: RepoInfoPostedBy; - }; - - export type RepoInfoRepository = { - __typename?: 'Repository'; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - }; - - export type RepoInfoPostedBy = { - __typename?: 'User'; - - html_url: string; - - login: string; - }; - - export type VoteButtonsFragment = { - __typename?: 'Entry'; - - score: number; - - vote: VoteButtonsVote; - }; - - export type VoteButtonsVote = { - __typename?: 'Vote'; - - vote_value: number; - }; - diff --git a/dev-test/githunt/types.reactApollo.hooks.tsx b/dev-test/githunt/types.reactApollo.hooks.tsx new file mode 100644 index 00000000000..1142e88775b --- /dev/null +++ b/dev-test/githunt/types.reactApollo.hooks.tsx @@ -0,0 +1,451 @@ +// tslint:disable +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' +} + +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; + + +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; + + +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; + + +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; + +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; + + +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; + + +export type QueryEntryArgs = { + repoFullName: string +}; + +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; + +export type Subscription = { + commentAdded?: Maybe, +}; + + +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; + +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; + +export type Vote = { + vote_value: number, +}; + +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' +} +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; + + +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); + +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; + + +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); + +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); + +export type CurrentUserForProfileQueryVariables = {}; + + +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); + +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); + +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; + + +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); + +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; + + +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); + +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); + +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; + + +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); + +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); + +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; + + +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); + +import gql from 'graphql-tag'; +import * as React from 'react'; +import * as ReactApollo from 'react-apollo'; +import * as ReactApolloHooks from 'react-apollo-hooks'; +export const CommentsPageCommentFragmentDoc = gql` + fragment CommentsPageComment on Comment { + id + postedBy { + login + html_url + } + createdAt + content +} + `; +export const VoteButtonsFragmentDoc = gql` + fragment VoteButtons on Entry { + score + vote { + vote_value + } +} + `; +export const RepoInfoFragmentDoc = gql` + fragment RepoInfo on Entry { + createdAt + repository { + description + stargazers_count + open_issues_count + } + postedBy { + html_url + login + } +} + `; +export const FeedEntryFragmentDoc = gql` + fragment FeedEntry on Entry { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } + } + ...VoteButtons + ...RepoInfo +} + ${VoteButtonsFragmentDoc} +${RepoInfoFragmentDoc}`; +export const OnCommentAddedDocument = gql` + subscription onCommentAdded($repoFullName: String!) { + commentAdded(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + content + } +} + `; + +export class OnCommentAddedComponent extends React.Component>> { + render() { + return ( + subscription={OnCommentAddedDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type OnCommentAddedProps = Partial> & TChildProps; +export function OnCommentAddedHOC(operationOptions: ReactApollo.OperationOption< + TProps, + OnCommentAddedSubscription, + OnCommentAddedSubscriptionVariables, + OnCommentAddedProps> | undefined) { + return ReactApollo.graphql>(OnCommentAddedDocument, operationOptions); +}; + +export function useOnCommentAddedSubscription(baseOptions?: ReactApolloHooks.SubscriptionHookOptions) { + return ReactApolloHooks.useSubscription(OnCommentAddedDocument, baseOptions); +}; +export const CommentDocument = gql` + query Comment($repoFullName: String!, $limit: Int, $offset: Int) { + currentUser { + login + html_url + } + entry(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + comments(limit: $limit, offset: $offset) { + ...CommentsPageComment + } + commentCount + repository { + full_name + html_url + ... on Repository { + description + open_issues_count + stargazers_count + } + } + } +} + ${CommentsPageCommentFragmentDoc}`; + +export class CommentComponent extends React.Component>> { + render() { + return ( + query={CommentDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type CommentProps = Partial> & TChildProps; +export function CommentHOC(operationOptions: ReactApollo.OperationOption< + TProps, + CommentQuery, + CommentQueryVariables, + CommentProps> | undefined) { + return ReactApollo.graphql>(CommentDocument, operationOptions); +}; + +export function useCommentQuery(baseOptions?: ReactApolloHooks.QueryHookOptions) { + return ReactApolloHooks.useQuery(CommentDocument, baseOptions); +}; +export const CurrentUserForProfileDocument = gql` + query CurrentUserForProfile { + currentUser { + login + avatar_url + } +} + `; + +export class CurrentUserForProfileComponent extends React.Component>> { + render() { + return ( + query={CurrentUserForProfileDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type CurrentUserForProfileProps = Partial> & TChildProps; +export function CurrentUserForProfileHOC(operationOptions: ReactApollo.OperationOption< + TProps, + CurrentUserForProfileQuery, + CurrentUserForProfileQueryVariables, + CurrentUserForProfileProps> | undefined) { + return ReactApollo.graphql>(CurrentUserForProfileDocument, operationOptions); +}; + +export function useCurrentUserForProfileQuery(baseOptions?: ReactApolloHooks.QueryHookOptions) { + return ReactApolloHooks.useQuery(CurrentUserForProfileDocument, baseOptions); +}; +export const FeedDocument = gql` + query Feed($type: FeedType!, $offset: Int, $limit: Int) { + currentUser { + login + } + feed(type: $type, offset: $offset, limit: $limit) { + ...FeedEntry + } +} + ${FeedEntryFragmentDoc}`; + +export class FeedComponent extends React.Component>> { + render() { + return ( + query={FeedDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type FeedProps = Partial> & TChildProps; +export function FeedHOC(operationOptions: ReactApollo.OperationOption< + TProps, + FeedQuery, + FeedQueryVariables, + FeedProps> | undefined) { + return ReactApollo.graphql>(FeedDocument, operationOptions); +}; + +export function useFeedQuery(baseOptions?: ReactApolloHooks.QueryHookOptions) { + return ReactApolloHooks.useQuery(FeedDocument, baseOptions); +}; +export const SubmitRepositoryDocument = gql` + mutation submitRepository($repoFullName: String!) { + submitRepository(repoFullName: $repoFullName) { + createdAt + } +} + `; + +export class SubmitRepositoryComponent extends React.Component>> { + render() { + return ( + mutation={SubmitRepositoryDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type SubmitRepositoryProps = Partial> & TChildProps; +export type SubmitRepositoryMutationFn = ReactApollo.MutationFn; +export function SubmitRepositoryHOC(operationOptions: ReactApollo.OperationOption< + TProps, + SubmitRepositoryMutation, + SubmitRepositoryMutationVariables, + SubmitRepositoryProps> | undefined) { + return ReactApollo.graphql>(SubmitRepositoryDocument, operationOptions); +}; + +export function useSubmitRepositoryMutation(baseOptions?: ReactApolloHooks.MutationHookOptions) { + return ReactApolloHooks.useMutation(SubmitRepositoryDocument, baseOptions); +}; +export const SubmitCommentDocument = gql` + mutation submitComment($repoFullName: String!, $commentContent: String!) { + submitComment(repoFullName: $repoFullName, commentContent: $commentContent) { + ...CommentsPageComment + } +} + ${CommentsPageCommentFragmentDoc}`; + +export class SubmitCommentComponent extends React.Component>> { + render() { + return ( + mutation={SubmitCommentDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type SubmitCommentProps = Partial> & TChildProps; +export type SubmitCommentMutationFn = ReactApollo.MutationFn; +export function SubmitCommentHOC(operationOptions: ReactApollo.OperationOption< + TProps, + SubmitCommentMutation, + SubmitCommentMutationVariables, + SubmitCommentProps> | undefined) { + return ReactApollo.graphql>(SubmitCommentDocument, operationOptions); +}; + +export function useSubmitCommentMutation(baseOptions?: ReactApolloHooks.MutationHookOptions) { + return ReactApolloHooks.useMutation(SubmitCommentDocument, baseOptions); +}; +export const VoteDocument = gql` + mutation vote($repoFullName: String!, $type: VoteType!) { + vote(repoFullName: $repoFullName, type: $type) { + score + id + vote { + vote_value + } + } +} + `; + +export class VoteComponent extends React.Component>> { + render() { + return ( + mutation={VoteDocument} {...(this as any)['props'] as any} /> + ); + } +} +export type VoteProps = Partial> & TChildProps; +export type VoteMutationFn = ReactApollo.MutationFn; +export function VoteHOC(operationOptions: ReactApollo.OperationOption< + TProps, + VoteMutation, + VoteMutationVariables, + VoteProps> | undefined) { + return ReactApollo.graphql>(VoteDocument, operationOptions); +}; + +export function useVoteMutation(baseOptions?: ReactApolloHooks.MutationHookOptions) { + return ReactApolloHooks.useMutation(VoteDocument, baseOptions); +}; \ No newline at end of file diff --git a/dev-test/githunt/types.reactApollo.noNamespaces.tsx b/dev-test/githunt/types.reactApollo.noNamespaces.tsx deleted file mode 100644 index 40be3600bf2..00000000000 --- a/dev-test/githunt/types.reactApollo.noNamespaces.tsx +++ /dev/null @@ -1,711 +0,0 @@ -// tslint:disable -export type Maybe = T | null; - -/** A list of options for the sort order of the feed */ - export enum FeedType { - Hot = "HOT", - New = "NEW", - Top = "TOP", - } -/** The type of vote to record, when submitting a vote */ - export enum VoteType { - Up = "UP", - Down = "DOWN", - Cancel = "CANCEL", - } - - -// ==================================================== -// Documents -// ==================================================== - - - - export type OnCommentAddedVariables = { - repoFullName: string; - } - - export type OnCommentAddedSubscription = { - __typename?: "Subscription"; - - commentAdded: Maybe; - } - - export type OnCommentAddedCommentAdded = { - __typename?: "Comment"; - - id: number; - - postedBy: OnCommentAddedPostedBy; - - createdAt: number; - - content: string; - } - - export type OnCommentAddedPostedBy = { - __typename?: "User"; - - login: string; - - html_url: string; - } - - export type CommentVariables = { - repoFullName: string; - limit?: Maybe; - offset?: Maybe; - } - - export type CommentQuery = { - __typename?: "Query"; - - currentUser: Maybe; - - entry: Maybe; - } - - export type CommentCurrentUser = { - __typename?: "User"; - - login: string; - - html_url: string; - } - - export type CommentEntry = { - __typename?: "Entry"; - - id: number; - - postedBy: CommentPostedBy; - - createdAt: number; - - comments: (Maybe)[]; - - commentCount: number; - - repository: CommentRepository; - } - - export type CommentPostedBy = { - __typename?: "User"; - - login: string; - - html_url: string; - } - - export type CommentComments = CommentsPageCommentFragment - - export type CommentRepository = { - __typename?: CommentRepositoryInlineFragment["__typename"]; - - full_name: string; - - html_url: string; - } & CommentRepositoryInlineFragment - - export type CommentRepositoryInlineFragment = { - __typename?: "Repository"; - - description: Maybe; - - open_issues_count: Maybe; - - stargazers_count: number; - } - - export type CurrentUserForProfileVariables = { - } - - export type CurrentUserForProfileQuery = { - __typename?: "Query"; - - currentUser: Maybe; - } - - export type CurrentUserForProfileCurrentUser = { - __typename?: "User"; - - login: string; - - avatar_url: string; - } - - export type FeedVariables = { - type: FeedType; - offset?: Maybe; - limit?: Maybe; - } - - export type FeedQuery = { - __typename?: "Query"; - - currentUser: Maybe; - - feed: Maybe<(Maybe)[]>; - } - - export type FeedCurrentUser = { - __typename?: "User"; - - login: string; - } - - export type FeedFeed = FeedEntryFragment - - export type SubmitRepositoryVariables = { - repoFullName: string; - } - - export type SubmitRepositoryMutation = { - __typename?: "Mutation"; - - submitRepository: Maybe; - } - - export type SubmitRepositorySubmitRepository = { - __typename?: "Entry"; - - createdAt: number; - } - - export type SubmitCommentVariables = { - repoFullName: string; - commentContent: string; - } - - export type SubmitCommentMutation = { - __typename?: "Mutation"; - - submitComment: Maybe; - } - - export type SubmitCommentSubmitComment = CommentsPageCommentFragment - - export type VoteVariables = { - repoFullName: string; - type: VoteType; - } - - export type VoteMutation = { - __typename?: "Mutation"; - - vote: Maybe; - } - - export type VoteVote = { - __typename?: "Entry"; - - score: number; - - id: number; - - vote: Vote_Vote; - } - - export type Vote_Vote = { - __typename?: "Vote"; - - vote_value: number; - } - - export type CommentsPageCommentFragment = { - __typename?: "Comment"; - - id: number; - - postedBy: CommentsPageCommentPostedBy; - - createdAt: number; - - content: string; - } - - export type CommentsPageCommentPostedBy = { - __typename?: "User"; - - login: string; - - html_url: string; - } - - export type FeedEntryFragment = { - __typename?: "Entry"; - - id: number; - - commentCount: number; - - repository: FeedEntryRepository; - } & (VoteButtonsFragment & RepoInfoFragment) - - export type FeedEntryRepository = { - __typename?: "Repository"; - - full_name: string; - - html_url: string; - - owner: Maybe; - } - - export type FeedEntryOwner = { - __typename?: "User"; - - avatar_url: string; - } - - export type RepoInfoFragment = { - __typename?: "Entry"; - - createdAt: number; - - repository: RepoInfoRepository; - - postedBy: RepoInfoPostedBy; - } - - export type RepoInfoRepository = { - __typename?: "Repository"; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - } - - export type RepoInfoPostedBy = { - __typename?: "User"; - - html_url: string; - - login: string; - } - - export type VoteButtonsFragment = { - __typename?: "Entry"; - - score: number; - - vote: VoteButtonsVote; - } - - export type VoteButtonsVote = { - __typename?: "Vote"; - - vote_value: number; - } - - - import gql from 'graphql-tag'; - import * as React from 'react'; -import * as ReactApollo from 'react-apollo'; - - - - -// ==================================================== -// Fragments -// ==================================================== - - - - export const CommentsPageCommentFragmentDoc = gql` - fragment CommentsPageComment on Comment { - id - postedBy { - login - html_url - } - createdAt - content -} - - - - `; - - - export const VoteButtonsFragmentDoc = gql` - fragment VoteButtons on Entry { - score - vote { - vote_value - } -} - - - - `; - - - export const RepoInfoFragmentDoc = gql` - fragment RepoInfo on Entry { - createdAt - repository { - description - stargazers_count - open_issues_count - } - postedBy { - html_url - login - } -} - - - - `; - - - export const FeedEntryFragmentDoc = gql` - fragment FeedEntry on Entry { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - ...VoteButtons - ...RepoInfo -} - - ${VoteButtonsFragmentDoc} -${RepoInfoFragmentDoc} - - `; - - - - -// ==================================================== -// Components -// ==================================================== - - - export const OnCommentAddedDocument = gql` - subscription onCommentAdded($repoFullName: String!) { - commentAdded(repoFullName: $repoFullName) { - id - postedBy { - login - html_url - } - createdAt - content - } -} - - - - `; - export class OnCommentAddedComponent extends React.Component>> { - render(){ - return ( - - subscription={ OnCommentAddedDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type OnCommentAddedProps = - Partial< - ReactApollo.DataProps< - OnCommentAddedSubscription, - OnCommentAddedVariables - > - > - & TChildProps; - export function OnCommentAddedHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - OnCommentAddedSubscription, - OnCommentAddedVariables, - OnCommentAddedProps - > | undefined){ - return ReactApollo.graphql>( - OnCommentAddedDocument, - operationOptions - ); - }; - export const CommentDocument = gql` - query Comment($repoFullName: String!, $limit: Int, $offset: Int) { - currentUser { - login - html_url - } - entry(repoFullName: $repoFullName) { - id - postedBy { - login - html_url - } - createdAt - comments(limit: $limit, offset: $offset) { - ...CommentsPageComment - } - commentCount - repository { - full_name - html_url - ... on Repository { - description - open_issues_count - stargazers_count - } - } - } -} - - ${CommentsPageCommentFragmentDoc} - - `; - export class CommentComponent extends React.Component>> { - render(){ - return ( - - query={ CommentDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type CommentProps = - Partial< - ReactApollo.DataProps< - CommentQuery, - CommentVariables - > - > - & TChildProps; - export function CommentHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - CommentQuery, - CommentVariables, - CommentProps - > | undefined){ - return ReactApollo.graphql>( - CommentDocument, - operationOptions - ); - }; - export const CurrentUserForProfileDocument = gql` - query CurrentUserForProfile { - currentUser { - login - avatar_url - } -} - - - - `; - export class CurrentUserForProfileComponent extends React.Component>> { - render(){ - return ( - - query={ CurrentUserForProfileDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type CurrentUserForProfileProps = - Partial< - ReactApollo.DataProps< - CurrentUserForProfileQuery, - CurrentUserForProfileVariables - > - > - & TChildProps; - export function CurrentUserForProfileHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - CurrentUserForProfileQuery, - CurrentUserForProfileVariables, - CurrentUserForProfileProps - > | undefined){ - return ReactApollo.graphql>( - CurrentUserForProfileDocument, - operationOptions - ); - }; - export const FeedDocument = gql` - query Feed($type: FeedType!, $offset: Int, $limit: Int) { - currentUser { - login - } - feed(type: $type, offset: $offset, limit: $limit) { - ...FeedEntry - } -} - - ${FeedEntryFragmentDoc} - - `; - export class FeedComponent extends React.Component>> { - render(){ - return ( - - query={ FeedDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type FeedProps = - Partial< - ReactApollo.DataProps< - FeedQuery, - FeedVariables - > - > - & TChildProps; - export function FeedHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - FeedQuery, - FeedVariables, - FeedProps - > | undefined){ - return ReactApollo.graphql>( - FeedDocument, - operationOptions - ); - }; - export const SubmitRepositoryDocument = gql` - mutation submitRepository($repoFullName: String!) { - submitRepository(repoFullName: $repoFullName) { - createdAt - } -} - - - - `; - export class SubmitRepositoryComponent extends React.Component>> { - render(){ - return ( - - mutation={ SubmitRepositoryDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type SubmitRepositoryProps = - Partial< - ReactApollo.MutateProps< - SubmitRepositoryMutation, - SubmitRepositoryVariables - > - > - & TChildProps; - export type SubmitRepositoryMutationFn = ReactApollo.MutationFn; - export function SubmitRepositoryHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - SubmitRepositoryMutation, - SubmitRepositoryVariables, - SubmitRepositoryProps - > | undefined){ - return ReactApollo.graphql>( - SubmitRepositoryDocument, - operationOptions - ); - }; - export const SubmitCommentDocument = gql` - mutation submitComment($repoFullName: String!, $commentContent: String!) { - submitComment(repoFullName: $repoFullName, commentContent: $commentContent) { - ...CommentsPageComment - } -} - - ${CommentsPageCommentFragmentDoc} - - `; - export class SubmitCommentComponent extends React.Component>> { - render(){ - return ( - - mutation={ SubmitCommentDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type SubmitCommentProps = - Partial< - ReactApollo.MutateProps< - SubmitCommentMutation, - SubmitCommentVariables - > - > - & TChildProps; - export type SubmitCommentMutationFn = ReactApollo.MutationFn; - export function SubmitCommentHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - SubmitCommentMutation, - SubmitCommentVariables, - SubmitCommentProps - > | undefined){ - return ReactApollo.graphql>( - SubmitCommentDocument, - operationOptions - ); - }; - export const VoteDocument = gql` - mutation vote($repoFullName: String!, $type: VoteType!) { - vote(repoFullName: $repoFullName, type: $type) { - score - id - vote { - vote_value - } - } -} - - - - `; - export class VoteComponent extends React.Component>> { - render(){ - return ( - - mutation={ VoteDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type VoteProps = - Partial< - ReactApollo.MutateProps< - VoteMutation, - VoteVariables - > - > - & TChildProps; - export type VoteMutationFn = ReactApollo.MutationFn; - export function VoteHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - VoteMutation, - VoteVariables, - VoteProps - > | undefined){ - return ReactApollo.graphql>( - VoteDocument, - operationOptions - ); - }; diff --git a/dev-test/githunt/types.reactApollo.tsx b/dev-test/githunt/types.reactApollo.tsx index da532423a64..a1df32d9782 100644 --- a/dev-test/githunt/types.reactApollo.tsx +++ b/dev-test/githunt/types.reactApollo.tsx @@ -1,343 +1,177 @@ // tslint:disable -export type Maybe = T | null; +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' +} -/** A list of options for the sort order of the feed */ - export enum FeedType { - Hot = "HOT", - New = "NEW", - Top = "TOP", - } -/** The type of vote to record, when submitting a vote */ - export enum VoteType { - Up = "UP", - Down = "DOWN", - Cancel = "CANCEL", - } +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; -// ==================================================== -// Documents -// ==================================================== +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; -export namespace OnCommentAdded { - export type Variables = { - repoFullName: string; - } - export type Subscription = { - __typename?: "Subscription"; - - commentAdded: Maybe; - } +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; - export type CommentAdded = { - __typename?: "Comment"; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - } - - export type PostedBy = { - __typename?: "User"; - - login: string; - - html_url: string; - } -} +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; -export namespace Comment { - export type Variables = { - repoFullName: string; - limit?: Maybe; - offset?: Maybe; - } - export type Query = { - __typename?: "Query"; - - currentUser: Maybe; - - entry: Maybe; - } +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - export type CurrentUser = { - __typename?: "User"; - - login: string; - - html_url: string; - } - - export type Entry = { - __typename?: "Entry"; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - comments: (Maybe)[]; - - commentCount: number; - - repository: Repository; - } - - export type PostedBy = { - __typename?: "User"; - - login: string; - - html_url: string; - } - - export type Comments = CommentsPageComment.Fragment - - export type Repository = { - __typename?: RepositoryInlineFragment["__typename"]; - - full_name: string; - - html_url: string; - } & RepositoryInlineFragment - - export type RepositoryInlineFragment = { - __typename?: "Repository"; - - description: Maybe; - - open_issues_count: Maybe; - - stargazers_count: number; - } -} -export namespace CurrentUserForProfile { - export type Variables = { - } - - export type Query = { - __typename?: "Query"; - - currentUser: Maybe; - } - - export type CurrentUser = { - __typename?: "User"; - - login: string; - - avatar_url: string; - } -} +export type QueryEntryArgs = { + repoFullName: string +}; -export namespace Feed { - export type Variables = { - type: FeedType; - offset?: Maybe; - limit?: Maybe; - } +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; - export type Query = { - __typename?: "Query"; - - currentUser: Maybe; - - feed: Maybe<(Maybe)[]>; - } +export type Subscription = { + commentAdded?: Maybe, +}; - export type CurrentUser = { - __typename?: "User"; - - login: string; - } - export type Feed = FeedEntry.Fragment -} +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; -export namespace SubmitRepository { - export type Variables = { - repoFullName: string; - } +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; - export type Mutation = { - __typename?: "Mutation"; - - submitRepository: Maybe; - } +export type Vote = { + vote_value: number, +}; - export type SubmitRepository = { - __typename?: "Entry"; - - createdAt: number; - } +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' } +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; -export namespace SubmitComment { - export type Variables = { - repoFullName: string; - commentContent: string; - } - export type Mutation = { - __typename?: "Mutation"; - - submitComment: Maybe; - } +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); - export type SubmitComment = CommentsPageComment.Fragment -} +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; -export namespace Vote { - export type Variables = { - repoFullName: string; - type: VoteType; - } - export type Mutation = { - __typename?: "Mutation"; - - vote: Maybe; - } +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); - export type Vote = { - __typename?: "Entry"; - - score: number; - - id: number; - - vote: _Vote; - } - - export type _Vote = { - __typename?: "Vote"; - - vote_value: number; - } -} +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); -export namespace CommentsPageComment { - export type Fragment = { - __typename?: "Comment"; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - } +export type CurrentUserForProfileQueryVariables = {}; - export type PostedBy = { - __typename?: "User"; - - login: string; - - html_url: string; - } -} -export namespace FeedEntry { - export type Fragment = { - __typename?: "Entry"; - - id: number; - - commentCount: number; - - repository: Repository; - } & (VoteButtons.Fragment & RepoInfo.Fragment) - - export type Repository = { - __typename?: "Repository"; - - full_name: string; - - html_url: string; - - owner: Maybe; - } +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); - export type Owner = { - __typename?: "User"; - - avatar_url: string; - } -} +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); -export namespace RepoInfo { - export type Fragment = { - __typename?: "Entry"; - - createdAt: number; - - repository: Repository; - - postedBy: PostedBy; - } +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - export type Repository = { - __typename?: "Repository"; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - } - export type PostedBy = { - __typename?: "User"; - - html_url: string; - - login: string; - } -} +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); -export namespace VoteButtons { - export type Fragment = { - __typename?: "Entry"; - - score: number; - - vote: Vote; - } +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; - export type Vote = { - __typename?: "Vote"; - - vote_value: number; - } -} +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); - import gql from 'graphql-tag'; - import * as React from 'react'; -import * as ReactApollo from 'react-apollo'; +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); -// ==================================================== -// Fragments -// ==================================================== +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; - export namespace CommentsPageComment { - export const FragmentDoc = gql` +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); + +import gql from 'graphql-tag'; +import * as React from 'react'; +import * as ReactApollo from 'react-apollo'; +export const CommentsPageCommentFragmentDoc = gql` fragment CommentsPageComment on Comment { id postedBy { @@ -347,30 +181,16 @@ import * as ReactApollo from 'react-apollo'; createdAt content } - - - - `; - } - - - export namespace VoteButtons { - export const FragmentDoc = gql` + `; +export const VoteButtonsFragmentDoc = gql` fragment VoteButtons on Entry { score vote { vote_value } } - - - - `; - } - - - export namespace RepoInfo { - export const FragmentDoc = gql` + `; +export const RepoInfoFragmentDoc = gql` fragment RepoInfo on Entry { createdAt repository { @@ -383,15 +203,8 @@ import * as ReactApollo from 'react-apollo'; login } } - - - - `; - } - - - export namespace FeedEntry { - export const FragmentDoc = gql` + `; +export const FeedEntryFragmentDoc = gql` fragment FeedEntry on Entry { id commentCount @@ -405,23 +218,9 @@ import * as ReactApollo from 'react-apollo'; ...VoteButtons ...RepoInfo } - - ${VoteButtons.FragmentDoc} -${RepoInfo.FragmentDoc} - - `; - } - - - - -// ==================================================== -// Components -// ==================================================== - - -export namespace OnCommentAdded { - export const Document = gql` + ${VoteButtonsFragmentDoc} +${RepoInfoFragmentDoc}`; +export const OnCommentAddedDocument = gql` subscription onCommentAdded($repoFullName: String!) { commentAdded(repoFullName: $repoFullName) { id @@ -433,43 +232,24 @@ export namespace OnCommentAdded { content } } - - - - `; - export class Component extends React.Component>> { - render(){ - return ( - - subscription={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.DataProps< - Subscription, - Variables - > - > - & TChildProps; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Subscription, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + `; + +export class OnCommentAddedComponent extends React.Component>> { + render() { + return ( + subscription={OnCommentAddedDocument} {...(this as any)['props'] as any} /> + ); + } } -export namespace Comment { - export const Document = gql` +export type OnCommentAddedProps = Partial> & TChildProps; +export function OnCommentAddedHOC(operationOptions: ReactApollo.OperationOption< + TProps, + OnCommentAddedSubscription, + OnCommentAddedSubscriptionVariables, + OnCommentAddedProps> | undefined) { + return ReactApollo.graphql>(OnCommentAddedDocument, operationOptions); +}; +export const CommentDocument = gql` query Comment($repoFullName: String!, $limit: Int, $offset: Int) { currentUser { login @@ -497,86 +277,48 @@ export namespace Comment { } } } - - ${CommentsPageComment.FragmentDoc} - - `; - export class Component extends React.Component>> { - render(){ - return ( - - query={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.DataProps< - Query, - Variables - > - > - & TChildProps; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Query, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + ${CommentsPageCommentFragmentDoc}`; + +export class CommentComponent extends React.Component>> { + render() { + return ( + query={CommentDocument} {...(this as any)['props'] as any} /> + ); + } } -export namespace CurrentUserForProfile { - export const Document = gql` +export type CommentProps = Partial> & TChildProps; +export function CommentHOC(operationOptions: ReactApollo.OperationOption< + TProps, + CommentQuery, + CommentQueryVariables, + CommentProps> | undefined) { + return ReactApollo.graphql>(CommentDocument, operationOptions); +}; +export const CurrentUserForProfileDocument = gql` query CurrentUserForProfile { currentUser { login avatar_url } } - - - - `; - export class Component extends React.Component>> { - render(){ - return ( - - query={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.DataProps< - Query, - Variables - > - > - & TChildProps; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Query, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + `; + +export class CurrentUserForProfileComponent extends React.Component>> { + render() { + return ( + query={CurrentUserForProfileDocument} {...(this as any)['props'] as any} /> + ); + } } -export namespace Feed { - export const Document = gql` +export type CurrentUserForProfileProps = Partial> & TChildProps; +export function CurrentUserForProfileHOC(operationOptions: ReactApollo.OperationOption< + TProps, + CurrentUserForProfileQuery, + CurrentUserForProfileQueryVariables, + CurrentUserForProfileProps> | undefined) { + return ReactApollo.graphql>(CurrentUserForProfileDocument, operationOptions); +}; +export const FeedDocument = gql` query Feed($type: FeedType!, $offset: Int, $limit: Int) { currentUser { login @@ -585,129 +327,72 @@ export namespace Feed { ...FeedEntry } } - - ${FeedEntry.FragmentDoc} - - `; - export class Component extends React.Component>> { - render(){ - return ( - - query={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.DataProps< - Query, - Variables - > - > - & TChildProps; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Query, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + ${FeedEntryFragmentDoc}`; + +export class FeedComponent extends React.Component>> { + render() { + return ( + query={FeedDocument} {...(this as any)['props'] as any} /> + ); + } } -export namespace SubmitRepository { - export const Document = gql` +export type FeedProps = Partial> & TChildProps; +export function FeedHOC(operationOptions: ReactApollo.OperationOption< + TProps, + FeedQuery, + FeedQueryVariables, + FeedProps> | undefined) { + return ReactApollo.graphql>(FeedDocument, operationOptions); +}; +export const SubmitRepositoryDocument = gql` mutation submitRepository($repoFullName: String!) { submitRepository(repoFullName: $repoFullName) { createdAt } } - - - - `; - export class Component extends React.Component>> { - render(){ - return ( - - mutation={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.MutateProps< - Mutation, - Variables - > - > - & TChildProps; - export type MutationFn = ReactApollo.MutationFn; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Mutation, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + `; + +export class SubmitRepositoryComponent extends React.Component>> { + render() { + return ( + mutation={SubmitRepositoryDocument} {...(this as any)['props'] as any} /> + ); + } } -export namespace SubmitComment { - export const Document = gql` +export type SubmitRepositoryProps = Partial> & TChildProps; +export type SubmitRepositoryMutationFn = ReactApollo.MutationFn; +export function SubmitRepositoryHOC(operationOptions: ReactApollo.OperationOption< + TProps, + SubmitRepositoryMutation, + SubmitRepositoryMutationVariables, + SubmitRepositoryProps> | undefined) { + return ReactApollo.graphql>(SubmitRepositoryDocument, operationOptions); +}; +export const SubmitCommentDocument = gql` mutation submitComment($repoFullName: String!, $commentContent: String!) { submitComment(repoFullName: $repoFullName, commentContent: $commentContent) { ...CommentsPageComment } } - - ${CommentsPageComment.FragmentDoc} - - `; - export class Component extends React.Component>> { - render(){ - return ( - - mutation={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.MutateProps< - Mutation, - Variables - > - > - & TChildProps; - export type MutationFn = ReactApollo.MutationFn; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Mutation, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + ${CommentsPageCommentFragmentDoc}`; + +export class SubmitCommentComponent extends React.Component>> { + render() { + return ( + mutation={SubmitCommentDocument} {...(this as any)['props'] as any} /> + ); + } } -export namespace Vote { - export const Document = gql` +export type SubmitCommentProps = Partial> & TChildProps; +export type SubmitCommentMutationFn = ReactApollo.MutationFn; +export function SubmitCommentHOC(operationOptions: ReactApollo.OperationOption< + TProps, + SubmitCommentMutation, + SubmitCommentMutationVariables, + SubmitCommentProps> | undefined) { + return ReactApollo.graphql>(SubmitCommentDocument, operationOptions); +}; +export const VoteDocument = gql` mutation vote($repoFullName: String!, $type: VoteType!) { vote(repoFullName: $repoFullName, type: $type) { score @@ -717,39 +402,21 @@ export namespace Vote { } } } - - - - `; - export class Component extends React.Component>> { - render(){ - return ( - - mutation={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - export type Props = - Partial< - ReactApollo.MutateProps< - Mutation, - Variables - > - > - & TChildProps; - export type MutationFn = ReactApollo.MutationFn; - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Mutation, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; + `; + +export class VoteComponent extends React.Component>> { + render() { + return ( + mutation={VoteDocument} {...(this as any)['props'] as any} /> + ); + } } +export type VoteProps = Partial> & TChildProps; +export type VoteMutationFn = ReactApollo.MutationFn; +export function VoteHOC(operationOptions: ReactApollo.OperationOption< + TProps, + VoteMutation, + VoteMutationVariables, + VoteProps> | undefined) { + return ReactApollo.graphql>(VoteDocument, operationOptions); +}; \ No newline at end of file diff --git a/dev-test/githunt/types.stencilApollo.class.tsx b/dev-test/githunt/types.stencilApollo.class.tsx new file mode 100644 index 00000000000..008b4c1ba24 --- /dev/null +++ b/dev-test/githunt/types.stencilApollo.class.tsx @@ -0,0 +1,383 @@ +// tslint:disable +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' +} + +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; + + +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; + + +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; + + +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; + +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; + + +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; + + +export type QueryEntryArgs = { + repoFullName: string +}; + +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; + +export type Subscription = { + commentAdded?: Maybe, +}; + + +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; + +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; + +export type Vote = { + vote_value: number, +}; + +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' +} +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; + + +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); + +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; + + +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); + +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); + +export type CurrentUserForProfileQueryVariables = {}; + + +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); + +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); + +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; + + +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); + +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; + + +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); + +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); + +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; + + +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); + +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); + +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; + + +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); + +import gql from 'graphql-tag'; +import { Component } from '@stencil/core'; +export const CommentsPageCommentFragmentDoc = gql` + fragment CommentsPageComment on Comment { + id + postedBy { + login + html_url + } + createdAt + content +} + `; +export const VoteButtonsFragmentDoc = gql` + fragment VoteButtons on Entry { + score + vote { + vote_value + } +} + `; +export const RepoInfoFragmentDoc = gql` + fragment RepoInfo on Entry { + createdAt + repository { + description + stargazers_count + open_issues_count + } + postedBy { + html_url + login + } +} + `; +export const FeedEntryFragmentDoc = gql` + fragment FeedEntry on Entry { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } + } + ...VoteButtons + ...RepoInfo +} + ${VoteButtonsFragmentDoc} +${RepoInfoFragmentDoc}`; +export const OnCommentAddedDocument = gql` + subscription onCommentAdded($repoFullName: String!) { + commentAdded(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + content + } +} + `; + + @Component({ + tag: 'apollo-on-comment-added' + }) + export class OnCommentAddedComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-subscription/types').OnSubscriptionReadyFn; + render() { + return ; + } + } + +export const CommentDocument = gql` + query Comment($repoFullName: String!, $limit: Int, $offset: Int) { + currentUser { + login + html_url + } + entry(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + comments(limit: $limit, offset: $offset) { + ...CommentsPageComment + } + commentCount + repository { + full_name + html_url + ... on Repository { + description + open_issues_count + stargazers_count + } + } + } +} + ${CommentsPageCommentFragmentDoc}`; + + @Component({ + tag: 'apollo-comment' + }) + export class CommentComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + render() { + return ; + } + } + +export const CurrentUserForProfileDocument = gql` + query CurrentUserForProfile { + currentUser { + login + avatar_url + } +} + `; + + @Component({ + tag: 'apollo-current-user-for-profile' + }) + export class CurrentUserForProfileComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + render() { + return ; + } + } + +export const FeedDocument = gql` + query Feed($type: FeedType!, $offset: Int, $limit: Int) { + currentUser { + login + } + feed(type: $type, offset: $offset, limit: $limit) { + ...FeedEntry + } +} + ${FeedEntryFragmentDoc}`; + + @Component({ + tag: 'apollo-feed' + }) + export class FeedComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + render() { + return ; + } + } + +export const SubmitRepositoryDocument = gql` + mutation submitRepository($repoFullName: String!) { + submitRepository(repoFullName: $repoFullName) { + createdAt + } +} + `; + + @Component({ + tag: 'apollo-submit-repository' + }) + export class SubmitRepositoryComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; + render() { + return ; + } + } + +export const SubmitCommentDocument = gql` + mutation submitComment($repoFullName: String!, $commentContent: String!) { + submitComment(repoFullName: $repoFullName, commentContent: $commentContent) { + ...CommentsPageComment + } +} + ${CommentsPageCommentFragmentDoc}`; + + @Component({ + tag: 'apollo-submit-comment' + }) + export class SubmitCommentComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; + render() { + return ; + } + } + +export const VoteDocument = gql` + mutation vote($repoFullName: String!, $type: VoteType!) { + vote(repoFullName: $repoFullName, type: $type) { + score + id + vote { + vote_value + } + } +} + `; + + @Component({ + tag: 'apollo-vote' + }) + export class VoteComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; + render() { + return ; + } + } + \ No newline at end of file diff --git a/dev-test/githunt/types.stencilApollo.tsx b/dev-test/githunt/types.stencilApollo.tsx new file mode 100644 index 00000000000..e72e92f32ec --- /dev/null +++ b/dev-test/githunt/types.stencilApollo.tsx @@ -0,0 +1,368 @@ +// tslint:disable +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' +} + +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; + + +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; + + +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; + + +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; + +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; + + +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; + + +export type QueryEntryArgs = { + repoFullName: string +}; + +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; + +export type Subscription = { + commentAdded?: Maybe, +}; + + +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; + +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; + +export type Vote = { + vote_value: number, +}; + +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' +} +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; + + +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); + +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; + + +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); + +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); + +export type CurrentUserForProfileQueryVariables = {}; + + +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); + +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); + +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; + + +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); + +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; + + +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); + +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); + +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; + + +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); + +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); + +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; + + +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); + +import gql from 'graphql-tag'; +export const CommentsPageCommentFragmentDoc = gql` + fragment CommentsPageComment on Comment { + id + postedBy { + login + html_url + } + createdAt + content +} + `; +export const VoteButtonsFragmentDoc = gql` + fragment VoteButtons on Entry { + score + vote { + vote_value + } +} + `; +export const RepoInfoFragmentDoc = gql` + fragment RepoInfo on Entry { + createdAt + repository { + description + stargazers_count + open_issues_count + } + postedBy { + html_url + login + } +} + `; +export const FeedEntryFragmentDoc = gql` + fragment FeedEntry on Entry { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } + } + ...VoteButtons + ...RepoInfo +} + ${VoteButtonsFragmentDoc} +${RepoInfoFragmentDoc}`; +export const OnCommentAddedDocument = gql` + subscription onCommentAdded($repoFullName: String!) { + commentAdded(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + content + } +} + `; + + export type OnCommentAddedProps = { + variables ?: OnCommentAddedSubscriptionVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-subscription/types').OnSubscriptionReadyFn; + }; + + + export const OnCommentAddedComponent = (props: OnCommentAddedProps) => ; + +export const CommentDocument = gql` + query Comment($repoFullName: String!, $limit: Int, $offset: Int) { + currentUser { + login + html_url + } + entry(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + comments(limit: $limit, offset: $offset) { + ...CommentsPageComment + } + commentCount + repository { + full_name + html_url + ... on Repository { + description + open_issues_count + stargazers_count + } + } + } +} + ${CommentsPageCommentFragmentDoc}`; + + export type CommentProps = { + variables ?: CommentQueryVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + }; + + + export const CommentComponent = (props: CommentProps) => ; + +export const CurrentUserForProfileDocument = gql` + query CurrentUserForProfile { + currentUser { + login + avatar_url + } +} + `; + + export type CurrentUserForProfileProps = { + variables ?: CurrentUserForProfileQueryVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + }; + + + export const CurrentUserForProfileComponent = (props: CurrentUserForProfileProps) => ; + +export const FeedDocument = gql` + query Feed($type: FeedType!, $offset: Int, $limit: Int) { + currentUser { + login + } + feed(type: $type, offset: $offset, limit: $limit) { + ...FeedEntry + } +} + ${FeedEntryFragmentDoc}`; + + export type FeedProps = { + variables ?: FeedQueryVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + }; + + + export const FeedComponent = (props: FeedProps) => ; + +export const SubmitRepositoryDocument = gql` + mutation submitRepository($repoFullName: String!) { + submitRepository(repoFullName: $repoFullName) { + createdAt + } +} + `; + + export type SubmitRepositoryProps = { + variables ?: SubmitRepositoryMutationVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; + }; + + + export const SubmitRepositoryComponent = (props: SubmitRepositoryProps) => ; + +export const SubmitCommentDocument = gql` + mutation submitComment($repoFullName: String!, $commentContent: String!) { + submitComment(repoFullName: $repoFullName, commentContent: $commentContent) { + ...CommentsPageComment + } +} + ${CommentsPageCommentFragmentDoc}`; + + export type SubmitCommentProps = { + variables ?: SubmitCommentMutationVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; + }; + + + export const SubmitCommentComponent = (props: SubmitCommentProps) => ; + +export const VoteDocument = gql` + mutation vote($repoFullName: String!, $type: VoteType!) { + vote(repoFullName: $repoFullName, type: $type) { + score + id + vote { + vote_value + } + } +} + `; + + export type VoteProps = { + variables ?: VoteMutationVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; + }; + + + export const VoteComponent = (props: VoteProps) => ; + \ No newline at end of file diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 0333cc9c95b..bf4c2b75b50 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -1,323 +1,168 @@ -export type Maybe = T | null; - -/** A list of options for the sort order of the feed */ - export enum FeedType { - Hot = 'HOT', - New = 'NEW', - Top = 'TOP', - } -/** The type of vote to record, when submitting a vote */ - export enum VoteType { - Up = 'UP', - Down = 'DOWN', - Cancel = 'CANCEL', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace OnCommentAdded { - export type Variables = { - repoFullName: string; - }; - - export type Subscription = { - __typename?: 'Subscription'; - - commentAdded: Maybe; - }; - - export type CommentAdded = { - __typename?: 'Comment'; - - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - }; - - export type PostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; +type Maybe = T | null; +export type Comment = { + id: number, + postedBy: User, + createdAt: number, + content: string, + repoName: string, +}; + +export type Entry = { + repository: Repository, + postedBy: User, + createdAt: number, + score: number, + hotScore: number, + comments: Array>, + commentCount: number, + id: number, + vote: Vote, +}; + + +export type EntryCommentsArgs = { + limit?: Maybe, + offset?: Maybe +}; + +export enum FeedType { + Hot = 'HOT', + New = 'NEW', + Top = 'TOP' } -export namespace Comment { - export type Variables = { - repoFullName: string; - limit?: Maybe; - offset?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - currentUser: Maybe; - - entry: Maybe; - }; +export type Mutation = { + submitRepository?: Maybe, + vote?: Maybe, + submitComment?: Maybe, +}; - export type CurrentUser = { - __typename?: 'User'; - login: string; +export type MutationSubmitRepositoryArgs = { + repoFullName: string +}; - html_url: string; - }; - export type Entry = { - __typename?: 'Entry'; +export type MutationVoteArgs = { + repoFullName: string, + type: VoteType +}; - id: number; - postedBy: PostedBy; +export type MutationSubmitCommentArgs = { + repoFullName: string, + commentContent: string +}; - createdAt: number; +export type Query = { + feed?: Maybe>>, + entry?: Maybe, + currentUser?: Maybe, +}; - comments: (Maybe)[]; - commentCount: number; +export type QueryFeedArgs = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - repository: Repository; - }; - export type PostedBy = { - __typename?: 'User'; +export type QueryEntryArgs = { + repoFullName: string +}; - login: string; +export type Repository = { + name: string, + full_name: string, + description?: Maybe, + html_url: string, + stargazers_count: number, + open_issues_count?: Maybe, + owner?: Maybe, +}; - html_url: string; - }; +export type Subscription = { + commentAdded?: Maybe, +}; - export type Comments = CommentsPageComment.Fragment; - export type Repository = { - __typename?: RepositoryInlineFragment['__typename']; +export type SubscriptionCommentAddedArgs = { + repoFullName: string +}; - full_name: string; +export type User = { + login: string, + avatar_url: string, + html_url: string, +}; - html_url: string; - } & RepositoryInlineFragment; +export type Vote = { + vote_value: number, +}; - export type RepositoryInlineFragment = { - __typename?: 'Repository'; - - description: Maybe; - - open_issues_count: Maybe; - - stargazers_count: number; - }; -} - -export namespace CurrentUserForProfile { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - currentUser: Maybe; - }; - - export type CurrentUser = { - __typename?: 'User'; - - login: string; - - avatar_url: string; - }; +export enum VoteType { + Up = 'UP', + Down = 'DOWN', + Cancel = 'CANCEL' } +export type OnCommentAddedSubscriptionVariables = { + repoFullName: string +}; -export namespace Feed { - export type Variables = { - type: FeedType; - offset?: Maybe; - limit?: Maybe; - }; - export type Query = { - __typename?: 'Query'; +export type OnCommentAddedSubscription = ({ __typename?: 'Subscription' } & { commentAdded: Maybe<({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) })> }); - currentUser: Maybe; +export type CommentQueryVariables = { + repoFullName: string, + limit?: Maybe, + offset?: Maybe +}; - feed: Maybe<(Maybe)[]>; - }; - export type CurrentUser = { - __typename?: 'User'; +export type CommentQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, entry: Maybe<({ __typename?: 'Entry' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick), comments: Array>, repository: ({ __typename?: 'Repository' } & Pick & (({ __typename?: 'Repository' } & Pick))) })> }); - login: string; - }; +export type CommentsPageCommentFragment = ({ __typename?: 'Comment' } & Pick & { postedBy: ({ __typename?: 'User' } & Pick) }); - export type Feed = FeedEntry.Fragment; -} +export type CurrentUserForProfileQueryVariables = {}; -export namespace SubmitRepository { - export type Variables = { - repoFullName: string; - }; - export type Mutation = { - __typename?: 'Mutation'; +export type CurrentUserForProfileQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)> }); - submitRepository: Maybe; - }; +export type FeedEntryFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick & { owner: Maybe<({ __typename?: 'User' } & Pick)> }) } & (VoteButtonsFragment & RepoInfoFragment)); - export type SubmitRepository = { - __typename?: 'Entry'; +export type FeedQueryVariables = { + type: FeedType, + offset?: Maybe, + limit?: Maybe +}; - createdAt: number; - }; -} -export namespace SubmitComment { - export type Variables = { - repoFullName: string; - commentContent: string; - }; +export type FeedQuery = ({ __typename?: 'Query' } & { currentUser: Maybe<({ __typename?: 'User' } & Pick)>, feed: Maybe>> }); - export type Mutation = { - __typename?: 'Mutation'; +export type SubmitRepositoryMutationVariables = { + repoFullName: string +}; - submitComment: Maybe; - }; - - export type SubmitComment = CommentsPageComment.Fragment; -} -export namespace Vote { - export type Variables = { - repoFullName: string; - type: VoteType; - }; +export type SubmitRepositoryMutation = ({ __typename?: 'Mutation' } & { submitRepository: Maybe<({ __typename?: 'Entry' } & Pick)> }); - export type Mutation = { - __typename?: 'Mutation'; +export type RepoInfoFragment = ({ __typename?: 'Entry' } & Pick & { repository: ({ __typename?: 'Repository' } & Pick), postedBy: ({ __typename?: 'User' } & Pick) }); - vote: Maybe; - }; +export type SubmitCommentMutationVariables = { + repoFullName: string, + commentContent: string +}; - export type Vote = { - __typename?: 'Entry'; - score: number; +export type SubmitCommentMutation = ({ __typename?: 'Mutation' } & { submitComment: Maybe<({ __typename?: 'Comment' } & CommentsPageCommentFragment)> }); - id: number; - - vote: _Vote; - }; - - export type _Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} +export type VoteButtonsFragment = ({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) }); -export namespace CommentsPageComment { - export type Fragment = { - __typename?: 'Comment'; +export type VoteMutationVariables = { + repoFullName: string, + type: VoteType +}; - id: number; - - postedBy: PostedBy; - - createdAt: number; - - content: string; - }; - - export type PostedBy = { - __typename?: 'User'; - - login: string; - - html_url: string; - }; -} - -export namespace FeedEntry { - export type Fragment = { - __typename?: 'Entry'; - - id: number; - - commentCount: number; - - repository: Repository; - } & (VoteButtons.Fragment & RepoInfo.Fragment); - - export type Repository = { - __typename?: 'Repository'; - - full_name: string; - - html_url: string; - - owner: Maybe; - }; - - export type Owner = { - __typename?: 'User'; - - avatar_url: string; - }; -} - -export namespace RepoInfo { - export type Fragment = { - __typename?: 'Entry'; - - createdAt: number; - - repository: Repository; - - postedBy: PostedBy; - }; - - export type Repository = { - __typename?: 'Repository'; - - description: Maybe; - - stargazers_count: number; - - open_issues_count: Maybe; - }; - - export type PostedBy = { - __typename?: 'User'; - - html_url: string; - - login: string; - }; -} - -export namespace VoteButtons { - export type Fragment = { - __typename?: 'Entry'; - - score: number; - - vote: Vote; - }; - - export type Vote = { - __typename?: 'Vote'; - - vote_value: number; - }; -} +export type VoteMutation = ({ __typename?: 'Mutation' } & { vote: Maybe<({ __typename?: 'Entry' } & Pick & { vote: ({ __typename?: 'Vote' } & Pick) })> }); diff --git a/dev-test/init.sh b/dev-test/init.sh index ee64082f4da..d32c1b3502c 100755 --- a/dev-test/init.sh +++ b/dev-test/init.sh @@ -1,3 +1,3 @@ #/bin/sh -node packages/graphql-codegen-cli/dist/cli.js init +node packages/graphql-codegen-cli/dist/commonjs/cli.js init diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 47f2a1b910e..e2e374f11bc 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -1,349 +1,242 @@ -export type Maybe = T | null; - -/** The input object sent when someone is creating a new review */ -export interface ReviewInput { - /** 0-5 stars */ - stars: number; - /** Comment about the movie, optional */ - commentary: Maybe; - /** Favorite color, optional */ - favoriteColor: Maybe; +type Maybe = T | null; +export type Character = { + id: string, + name: string, + friends: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, +}; + +export type ColorInput = { + red: number, + green: number, + blue: number, +}; + +export type Droid = Character & { + id: string, + name: string, + friends: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + primaryFunction: Maybe, +}; + + +export type DroidFriendsConnectionArgs = { + first: Maybe, + after: Maybe +}; + +export enum Episode { + Newhope = 'NEWHOPE', + Empire = 'EMPIRE', + Jedi = 'JEDI' } -/** The input object sent when passing a color */ -export interface ColorInput { - red: number; - - green: number; - - blue: number; -} -/** The episodes in the Star Wars trilogy */ - export enum Episode { - Newhope = 'NEWHOPE', - Empire = 'EMPIRE', - Jedi = 'JEDI', - } -/** Units of height */ - export enum LengthUnit { - Meter = 'METER', - Foot = 'FOOT', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace CreateReviewForEpisode { - export type Variables = { - episode: Episode; - review: ReviewInput; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - createReview: Maybe; - }; - - export type CreateReview = { - __typename?: 'Review'; - - stars: number; - - commentary: Maybe; - }; -} - -export namespace HeroAndFriendsNames { - export type Variables = { - episode: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: 'Character'; - - name: string; - - friends: Maybe<(Maybe)[]>; - }; - - export type Friends = { - __typename?: 'Character'; - - name: string; - }; -} - -export namespace HeroAppearsIn { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: 'Character'; - - name: string; - - appearsIn: (Maybe)[]; - }; -} - -export namespace HeroDetails { - export type Variables = { - episode: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - __typename?: 'Human'; - - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; +export type FriendsConnection = { + totalCount: Maybe, + edges: Maybe>>, + friends: Maybe>>, + pageInfo: PageInfo, +}; + +export type FriendsEdge = { + cursor: string, + node: Maybe, +}; + +export type Human = Character & { + id: string, + name: string, + homePlanet: Maybe, + height: Maybe, + mass: Maybe, + friends: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + starships: Maybe>>, +}; + + +export type HumanHeightArgs = { + unit: LengthUnit +}; + + +export type HumanFriendsConnectionArgs = { + first: Maybe, + after: Maybe +}; + +export enum LengthUnit { + Meter = 'METER', + Foot = 'FOOT' } -export namespace HeroDetailsWithFragment { - export type Variables = { - episode: Maybe; - }; +export type Mutation = { + createReview: Maybe, +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type MutationCreateReviewArgs = { + episode: Maybe, + review: ReviewInput +}; - export type Hero = HeroDetails.Fragment; -} +export type PageInfo = { + startCursor: Maybe, + endCursor: Maybe, + hasNextPage: boolean, +}; -export namespace HeroName { - export type Variables = { - episode: Maybe; - }; +export type Query = { + hero: Maybe, + reviews: Maybe>>, + search: Maybe>>, + character: Maybe, + droid: Maybe, + human: Maybe, + starship: Maybe, +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHeroArgs = { + episode: Maybe +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type QueryReviewsArgs = { + episode: Episode +}; -export namespace HeroNameConditionalInclusion { - export type Variables = { - episode: Maybe; - includeName: boolean; - }; - export type Query = { - __typename?: 'Query'; +export type QuerySearchArgs = { + text: Maybe +}; - hero: Maybe; - }; - export type Hero = { - __typename?: 'Character'; +export type QueryCharacterArgs = { + id: string +}; - name: string; - }; -} -export namespace HeroNameConditionalExclusion { - export type Variables = { - episode: Maybe; - skipName: boolean; - }; +export type QueryDroidArgs = { + id: string +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHumanArgs = { + id: string +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type QueryStarshipArgs = { + id: string +}; -export namespace HeroParentTypeDependentField { - export type Variables = { - episode: Maybe; - }; +export type Review = { + stars: number, + commentary: Maybe, +}; - export type Query = { - __typename?: 'Query'; +export type ReviewInput = { + stars: number, + commentary: Maybe, + favoriteColor: Maybe, +}; - hero: Maybe; - }; +export type SearchResult = Human | Droid | Starship; - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; +export type Starship = { + id: string, + name: string, + length: Maybe, +}; - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type StarshipLengthArgs = { + unit: LengthUnit +}; +export type CreateReviewForEpisodeMutationVariables = { + episode: Episode, + review: ReviewInput +}; - friends: Maybe<(Maybe)[]>; - }; - export type Friends = { - __typename?: _HumanInlineFragment['__typename']; +export type CreateReviewForEpisodeMutation = ({ __typename?: 'Mutation' } & { createReview: Maybe<({ __typename?: 'Review' } & Pick)> }); - name: string; - } & _HumanInlineFragment; +export type HeroAndFriendsNamesQueryVariables = { + episode: Maybe +}; - export type _HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; +export type HeroAndFriendsNamesQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & { friends: Maybe>>> })> }); - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroAppearsInQueryVariables = {}; - friends: Maybe<(Maybe<_Friends>)[]>; - }; - export type _Friends = { - __typename?: __HumanInlineFragment['__typename']; +export type HeroAppearsInQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - name: string; - } & __HumanInlineFragment; +export type HeroDetailsQueryVariables = { + episode: Maybe +}; - export type __HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; -} +export type HeroDetailsQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick)))> }); -export namespace HeroTypeDependentAliasedField { - export type Variables = { - episode: Maybe; - }; +export type HeroDetailsWithFragmentQueryVariables = { + episode: Maybe +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type HeroDetailsWithFragmentQuery = ({ __typename?: 'Query' } & { hero: Maybe }); - export type Hero = (HumanInlineFragment | DroidInlineFragment); +export type HeroDetailsFragment = (Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick))); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type HeroNameQueryVariables = { + episode: Maybe +}; - property: Maybe; - }; - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroNameQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - property: Maybe; - }; -} +export type HeroNameConditionalInclusionQueryVariables = { + episode: Maybe, + includeName: boolean +}; -export namespace HumanWithNullHeight { - export type Variables = { - }; - export type Query = { - __typename?: 'Query'; +export type HeroNameConditionalInclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - human: Maybe; - }; +export type HeroNameConditionalExclusionQueryVariables = { + episode: Maybe, + skipName: boolean +}; - export type Human = { - __typename?: 'Human'; - name: string; +export type HeroNameConditionalExclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - mass: Maybe; - }; -} +export type HeroParentTypeDependentFieldQueryVariables = { + episode: Maybe +}; -export namespace TwoHeroes { - export type Variables = { - }; - export type Query = { - __typename?: 'Query'; +export type HeroParentTypeDependentFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> }) | ({ __typename?: 'Droid' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> })))> }); - r2: Maybe; +export type HeroTypeDependentAliasedFieldQueryVariables = { + episode: Maybe +}; - luke: Maybe; - }; - export type R2 = { - __typename?: 'Character'; +export type HeroTypeDependentAliasedFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(({ __typename?: 'Human' } & { property: Human['homePlanet'] }) | ({ __typename?: 'Droid' } & { property: Droid['primaryFunction'] }))> }); - name: string; - }; +export type HumanWithNullHeightQueryVariables = {}; - export type Luke = { - __typename?: 'Character'; - name: string; - }; -} - -export namespace HeroDetails { - export type Fragment = { - __typename?: 'Character'; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); +export type HumanWithNullHeightQuery = ({ __typename?: 'Query' } & { human: Maybe<({ __typename?: 'Human' } & Pick)> }); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type TwoHeroesQueryVariables = {}; - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; -} +export type TwoHeroesQuery = ({ __typename?: 'Query' } & { r2: Maybe>, luke: Maybe> }); diff --git a/dev-test/star-wars/types.d.ts b/dev-test/star-wars/types.d.ts index aaa1efd1ce6..765089cc8ec 100644 --- a/dev-test/star-wars/types.d.ts +++ b/dev-test/star-wars/types.d.ts @@ -1,342 +1,235 @@ -export type Maybe = T | null; +type Maybe = T | null; +export type Character = { + id: string, + name: string, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, +}; + +export type ColorInput = { + red: number, + green: number, + blue: number, +}; + +export type Droid = Character & { + id: string, + name: string, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + primaryFunction?: Maybe, +}; + -/** The input object sent when someone is creating a new review */ -export interface ReviewInput { - /** 0-5 stars */ - stars: number; - /** Comment about the movie, optional */ - commentary?: Maybe; - /** Favorite color, optional */ - favoriteColor?: Maybe; -} -/** The input object sent when passing a color */ -export interface ColorInput { +export type DroidFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; - red: number; +export type Episode = 'NEWHOPE' | 'EMPIRE' | 'JEDI'; - green: number; +export type FriendsConnection = { + totalCount?: Maybe, + edges?: Maybe>>, + friends?: Maybe>>, + pageInfo: PageInfo, +}; - blue: number; -} -/** The episodes in the Star Wars trilogy */ - export type Episode = 'NEWHOPE' | 'EMPIRE' | 'JEDI'; -/** Units of height */ - export type LengthUnit = 'METER' | 'FOOT'; +export type FriendsEdge = { + cursor: string, + node?: Maybe, +}; +export type Human = Character & { + id: string, + name: string, + homePlanet?: Maybe, + height?: Maybe, + mass?: Maybe, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + starships?: Maybe>>, +}; + + +export type HumanHeightArgs = { + unit: LengthUnit +}; -// ==================================================== -// Documents -// ==================================================== +export type HumanFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; +export type LengthUnit = 'METER' | 'FOOT'; -export namespace CreateReviewForEpisode { - export type Variables = { - episode: Episode; - review: ReviewInput; - }; +export type Mutation = { + createReview?: Maybe, +}; - export type Mutation = { - __typename?: 'Mutation'; - createReview: Maybe; - }; +export type MutationCreateReviewArgs = { + episode?: Maybe, + review: ReviewInput +}; - export type CreateReview = { - __typename?: 'Review'; +export type PageInfo = { + startCursor?: Maybe, + endCursor?: Maybe, + hasNextPage: boolean, +}; - stars: number; +export type Query = { + hero?: Maybe, + reviews?: Maybe>>, + search?: Maybe>>, + character?: Maybe, + droid?: Maybe, + human?: Maybe, + starship?: Maybe, +}; - commentary: Maybe; - }; -} -export namespace HeroAndFriendsNames { - export type Variables = { - episode?: Maybe; - }; +export type QueryHeroArgs = { + episode?: Maybe +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryReviewsArgs = { + episode: Episode +}; - export type Hero = { - __typename?: 'Character'; - name: string; +export type QuerySearchArgs = { + text?: Maybe +}; - friends: Maybe<(Maybe)[]>; - }; - export type Friends = { - __typename?: 'Character'; +export type QueryCharacterArgs = { + id: string +}; - name: string; - }; -} -export namespace HeroAppearsIn { - export type Variables = { - }; +export type QueryDroidArgs = { + id: string +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHumanArgs = { + id: string +}; - export type Hero = { - __typename?: 'Character'; - name: string; +export type QueryStarshipArgs = { + id: string +}; - appearsIn: (Maybe)[]; - }; -} +export type Review = { + stars: number, + commentary?: Maybe, +}; -export namespace HeroDetails { - export type Variables = { - episode?: Maybe; - }; +export type ReviewInput = { + stars: number, + commentary: Maybe, + favoriteColor: Maybe, +}; - export type Query = { - __typename?: 'Query'; +export type SearchResult = Human | Droid | Starship; - hero: Maybe; - }; +export type Starship = { + id: string, + name: string, + length?: Maybe, +}; - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - name: string; - } & (HumanInlineFragment | DroidInlineFragment); +export type StarshipLengthArgs = { + unit: LengthUnit +}; +export type CreateReviewForEpisodeMutationVariables = { + episode: Episode, + review: ReviewInput +}; - export type HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; +export type CreateReviewForEpisodeMutation = ({ __typename?: 'Mutation' } & { createReview: Maybe<({ __typename?: 'Review' } & Pick)> }); - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroAndFriendsNamesQueryVariables = { + episode?: Maybe +}; - primaryFunction: Maybe; - }; -} -export namespace HeroDetailsWithFragment { - export type Variables = { - episode?: Maybe; - }; +export type HeroAndFriendsNamesQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & { friends: Maybe>>> })> }); - export type Query = { - __typename?: 'Query'; +export type HeroAppearsInQueryVariables = {}; - hero: Maybe; - }; - export type Hero = HeroDetails.Fragment; -} +export type HeroAppearsInQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); -export namespace HeroName { - export type Variables = { - episode?: Maybe; - }; +export type HeroDetailsQueryVariables = { + episode?: Maybe +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type HeroDetailsQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick)))> }); - export type Hero = { - __typename?: 'Character'; +export type HeroDetailsWithFragmentQueryVariables = { + episode?: Maybe +}; - name: string; - }; -} -export namespace HeroNameConditionalInclusion { - export type Variables = { - episode?: Maybe; - includeName: boolean; - }; +export type HeroDetailsWithFragmentQuery = ({ __typename?: 'Query' } & { hero: Maybe }); - export type Query = { - __typename?: 'Query'; +export type HeroDetailsFragment = (Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick))); - hero: Maybe; - }; +export type HeroNameQueryVariables = { + episode?: Maybe +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type HeroNameQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); -export namespace HeroNameConditionalExclusion { - export type Variables = { - episode?: Maybe; - skipName: boolean; - }; +export type HeroNameConditionalInclusionQueryVariables = { + episode?: Maybe, + includeName: boolean +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type HeroNameConditionalInclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - export type Hero = { - __typename?: 'Character'; +export type HeroNameConditionalExclusionQueryVariables = { + episode?: Maybe, + skipName: boolean +}; - name: string; - }; -} -export namespace HeroParentTypeDependentField { - export type Variables = { - episode?: Maybe; - }; +export type HeroNameConditionalExclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - export type Query = { - __typename?: 'Query'; +export type HeroParentTypeDependentFieldQueryVariables = { + episode?: Maybe +}; - hero: Maybe; - }; - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; +export type HeroParentTypeDependentFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> }) | ({ __typename?: 'Droid' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> })))> }); - name: string; - } & (HumanInlineFragment | DroidInlineFragment); +export type HeroTypeDependentAliasedFieldQueryVariables = { + episode?: Maybe +}; - export type HumanInlineFragment = { - __typename?: 'Human'; - friends: Maybe<(Maybe)[]>; - }; +export type HeroTypeDependentAliasedFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(({ __typename?: 'Human' } & { property: Human['homePlanet'] }) | ({ __typename?: 'Droid' } & { property: Droid['primaryFunction'] }))> }); - export type Friends = { - __typename?: _HumanInlineFragment['__typename']; +export type HumanWithNullHeightQueryVariables = {}; - name: string; - } & _HumanInlineFragment; - export type _HumanInlineFragment = { - __typename?: 'Human'; +export type HumanWithNullHeightQuery = ({ __typename?: 'Query' } & { human: Maybe<({ __typename?: 'Human' } & Pick)> }); - height: Maybe; - }; +export type TwoHeroesQueryVariables = {}; - export type DroidInlineFragment = { - __typename?: 'Droid'; - - friends: Maybe<(Maybe<_Friends>)[]>; - }; - - export type _Friends = { - __typename?: __HumanInlineFragment['__typename']; - - name: string; - } & __HumanInlineFragment; - - export type __HumanInlineFragment = { - __typename?: 'Human'; - - height: Maybe; - }; -} - -export namespace HeroTypeDependentAliasedField { - export type Variables = { - episode?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - __typename?: 'Human'; - - property: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - property: Maybe; - }; -} - -export namespace HumanWithNullHeight { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - human: Maybe; - }; - - export type Human = { - __typename?: 'Human'; - - name: string; - - mass: Maybe; - }; -} - -export namespace TwoHeroes { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - r2: Maybe; - - luke: Maybe; - }; - - export type R2 = { - __typename?: 'Character'; - - name: string; - }; - - export type Luke = { - __typename?: 'Character'; - - name: string; - }; -} - -export namespace HeroDetails { - export type Fragment = { - __typename?: 'Character'; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - __typename?: 'Human'; - - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; -} +export type TwoHeroesQuery = ({ __typename?: 'Query' } & { r2: Maybe>, luke: Maybe> }); diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index 86f19b57cb5..65e04886f40 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -1,349 +1,242 @@ -export type Maybe = T | null; - -/** The input object sent when someone is creating a new review */ -export interface ReviewInput { - /** 0-5 stars */ - readonly stars: number; - /** Comment about the movie, optional */ - readonly commentary?: Maybe; - /** Favorite color, optional */ - readonly favoriteColor?: Maybe; +type Maybe = T | null; +export type Character = { + readonly id: string, + readonly name: string, + readonly friends?: Maybe>>, + readonly friendsConnection: FriendsConnection, + readonly appearsIn: ReadonlyArray>, +}; + +export type ColorInput = { + red: number, + green: number, + blue: number, +}; + +export type Droid = Character & { + readonly id: string, + readonly name: string, + readonly friends?: Maybe>>, + readonly friendsConnection: FriendsConnection, + readonly appearsIn: ReadonlyArray>, + readonly primaryFunction?: Maybe, +}; + + +export type DroidFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; + +export enum Episode { + Newhope = 'NEWHOPE', + Empire = 'EMPIRE', + Jedi = 'JEDI' } -/** The input object sent when passing a color */ -export interface ColorInput { - readonly red: number; - - readonly green: number; - - readonly blue: number; -} -/** The episodes in the Star Wars trilogy */ - export enum Episode { - Newhope = 'NEWHOPE', - Empire = 'EMPIRE', - Jedi = 'JEDI', - } -/** Units of height */ - export enum LengthUnit { - Meter = 'METER', - Foot = 'FOOT', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace CreateReviewForEpisode { - export type Variables = { - readonly episode: Episode; - readonly review: ReviewInput; - }; - - export type Mutation = { - readonly __typename?: 'Mutation'; - - readonly createReview: Maybe; - }; - - export type CreateReview = { - readonly __typename?: 'Review'; - - readonly stars: number; - - readonly commentary: Maybe; - }; -} - -export namespace HeroAndFriendsNames { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - - readonly friends: Maybe>>; - }; - - export type Friends = { - readonly __typename?: 'Character'; - - readonly name: string; - }; -} - -export namespace HeroAppearsIn { - export type Variables = { - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - - readonly appearsIn: ReadonlyArray>; - }; -} - -export namespace HeroDetails { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - - readonly name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly height: Maybe; - }; - - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; - - readonly primaryFunction: Maybe; - }; +export type FriendsConnection = { + readonly totalCount?: Maybe, + readonly edges?: Maybe>>, + readonly friends?: Maybe>>, + readonly pageInfo: PageInfo, +}; + +export type FriendsEdge = { + readonly cursor: string, + readonly node?: Maybe, +}; + +export type Human = Character & { + readonly id: string, + readonly name: string, + readonly homePlanet?: Maybe, + readonly height?: Maybe, + readonly mass?: Maybe, + readonly friends?: Maybe>>, + readonly friendsConnection: FriendsConnection, + readonly appearsIn: ReadonlyArray>, + readonly starships?: Maybe>>, +}; + + +export type HumanHeightArgs = { + unit: LengthUnit +}; + + +export type HumanFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; + +export enum LengthUnit { + Meter = 'METER', + Foot = 'FOOT' } -export namespace HeroDetailsWithFragment { - export type Variables = { - readonly episode?: Maybe; - }; +export type Mutation = { + readonly createReview?: Maybe, +}; - export type Query = { - readonly __typename?: 'Query'; - readonly hero: Maybe; - }; +export type MutationCreateReviewArgs = { + episode?: Maybe, + review: ReviewInput +}; - export type Hero = HeroDetails.Fragment; -} +export type PageInfo = { + readonly startCursor?: Maybe, + readonly endCursor?: Maybe, + readonly hasNextPage: boolean, +}; -export namespace HeroName { - export type Variables = { - readonly episode?: Maybe; - }; +export type Query = { + readonly hero?: Maybe, + readonly reviews?: Maybe>>, + readonly search?: Maybe>>, + readonly character?: Maybe, + readonly droid?: Maybe, + readonly human?: Maybe, + readonly starship?: Maybe, +}; - export type Query = { - readonly __typename?: 'Query'; - readonly hero: Maybe; - }; +export type QueryHeroArgs = { + episode?: Maybe +}; - export type Hero = { - readonly __typename?: 'Character'; - readonly name: string; - }; -} +export type QueryReviewsArgs = { + episode: Episode +}; -export namespace HeroNameConditionalInclusion { - export type Variables = { - readonly episode?: Maybe; - readonly includeName: boolean; - }; - export type Query = { - readonly __typename?: 'Query'; +export type QuerySearchArgs = { + text?: Maybe +}; - readonly hero: Maybe; - }; - export type Hero = { - readonly __typename?: 'Character'; +export type QueryCharacterArgs = { + id: string +}; - readonly name: string; - }; -} -export namespace HeroNameConditionalExclusion { - export type Variables = { - readonly episode?: Maybe; - readonly skipName: boolean; - }; +export type QueryDroidArgs = { + id: string +}; - export type Query = { - readonly __typename?: 'Query'; - readonly hero: Maybe; - }; +export type QueryHumanArgs = { + id: string +}; - export type Hero = { - readonly __typename?: 'Character'; - readonly name: string; - }; -} +export type QueryStarshipArgs = { + id: string +}; -export namespace HeroParentTypeDependentField { - export type Variables = { - readonly episode?: Maybe; - }; +export type Review = { + readonly stars: number, + readonly commentary?: Maybe, +}; - export type Query = { - readonly __typename?: 'Query'; +export type ReviewInput = { + stars: number, + commentary: Maybe, + favoriteColor: Maybe, +}; - readonly hero: Maybe; - }; +export type SearchResult = Human | Droid | Starship; - export type Hero = { - readonly __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; +export type Starship = { + readonly id: string, + readonly name: string, + readonly length?: Maybe, +}; - readonly name: string; - } & (HumanInlineFragment | DroidInlineFragment); - export type HumanInlineFragment = { - readonly __typename?: 'Human'; +export type StarshipLengthArgs = { + unit: LengthUnit +}; +export type CreateReviewForEpisodeMutationVariables = { + episode: Episode, + review: ReviewInput +}; - readonly friends: Maybe>>; - }; - export type Friends = { - readonly __typename?: _HumanInlineFragment['__typename']; +export type CreateReviewForEpisodeMutation = ({ readonly __typename?: 'Mutation' } & { readonly createReview: Maybe<({ readonly __typename?: 'Review' } & Pick)> }); - readonly name: string; - } & _HumanInlineFragment; +export type HeroAndFriendsNamesQueryVariables = { + episode?: Maybe +}; - export type _HumanInlineFragment = { - readonly __typename?: 'Human'; - readonly height: Maybe; - }; +export type HeroAndFriendsNamesQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe<(Pick & { readonly friends: Maybe>>> })> }); - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; +export type HeroAppearsInQueryVariables = {}; - readonly friends: Maybe>>; - }; - export type _Friends = { - readonly __typename?: __HumanInlineFragment['__typename']; +export type HeroAppearsInQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe> }); - readonly name: string; - } & __HumanInlineFragment; +export type HeroDetailsQueryVariables = { + episode?: Maybe +}; - export type __HumanInlineFragment = { - readonly __typename?: 'Human'; - readonly height: Maybe; - }; -} +export type HeroDetailsQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe<(Pick & (({ readonly __typename?: 'Human' } & Pick) | ({ readonly __typename?: 'Droid' } & Pick)))> }); -export namespace HeroTypeDependentAliasedField { - export type Variables = { - readonly episode?: Maybe; - }; +export type HeroDetailsWithFragmentQueryVariables = { + episode?: Maybe +}; - export type Query = { - readonly __typename?: 'Query'; - readonly hero: Maybe; - }; +export type HeroDetailsWithFragmentQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe }); - export type Hero = (HumanInlineFragment | DroidInlineFragment); +export type HeroDetailsFragment = (Pick & (({ readonly __typename?: 'Human' } & Pick) | ({ readonly __typename?: 'Droid' } & Pick))); - export type HumanInlineFragment = { - readonly __typename?: 'Human'; +export type HeroNameQueryVariables = { + episode?: Maybe +}; - readonly property: Maybe; - }; - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; +export type HeroNameQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe> }); - readonly property: Maybe; - }; -} +export type HeroNameConditionalInclusionQueryVariables = { + episode?: Maybe, + includeName: boolean +}; -export namespace HumanWithNullHeight { - export type Variables = { - }; - export type Query = { - readonly __typename?: 'Query'; +export type HeroNameConditionalInclusionQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe> }); - readonly human: Maybe; - }; +export type HeroNameConditionalExclusionQueryVariables = { + episode?: Maybe, + skipName: boolean +}; - export type Human = { - readonly __typename?: 'Human'; - readonly name: string; +export type HeroNameConditionalExclusionQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe> }); - readonly mass: Maybe; - }; -} +export type HeroParentTypeDependentFieldQueryVariables = { + episode?: Maybe +}; -export namespace TwoHeroes { - export type Variables = { - }; - export type Query = { - readonly __typename?: 'Query'; +export type HeroParentTypeDependentFieldQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe<(Pick & (({ readonly __typename?: 'Human' } & { readonly friends: Maybe & (({ readonly __typename?: 'Human' } & Pick)))>>> }) | ({ readonly __typename?: 'Droid' } & { readonly friends: Maybe & (({ readonly __typename?: 'Human' } & Pick)))>>> })))> }); - readonly r2: Maybe; +export type HeroTypeDependentAliasedFieldQueryVariables = { + episode?: Maybe +}; - readonly luke: Maybe; - }; - export type R2 = { - readonly __typename?: 'Character'; +export type HeroTypeDependentAliasedFieldQuery = ({ readonly __typename?: 'Query' } & { readonly hero: Maybe<(({ readonly __typename?: 'Human' } & { readonly property: Human['homePlanet'] }) | ({ readonly __typename?: 'Droid' } & { readonly property: Droid['primaryFunction'] }))> }); - readonly name: string; - }; +export type HumanWithNullHeightQueryVariables = {}; - export type Luke = { - readonly __typename?: 'Character'; - readonly name: string; - }; -} - -export namespace HeroDetails { - export type Fragment = { - readonly __typename?: 'Character'; - - readonly name: string; - } & (HumanInlineFragment | DroidInlineFragment); +export type HumanWithNullHeightQuery = ({ readonly __typename?: 'Query' } & { readonly human: Maybe<({ readonly __typename?: 'Human' } & Pick)> }); - export type HumanInlineFragment = { - readonly __typename?: 'Human'; +export type TwoHeroesQueryVariables = {}; - readonly height: Maybe; - }; - - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; - - readonly primaryFunction: Maybe; - }; -} +export type TwoHeroesQuery = ({ readonly __typename?: 'Query' } & { readonly r2: Maybe>, readonly luke: Maybe> }); diff --git a/dev-test/star-wars/types.noNamespaces.ts b/dev-test/star-wars/types.noNamespaces.ts deleted file mode 100644 index 86f19b57cb5..00000000000 --- a/dev-test/star-wars/types.noNamespaces.ts +++ /dev/null @@ -1,349 +0,0 @@ -export type Maybe = T | null; - -/** The input object sent when someone is creating a new review */ -export interface ReviewInput { - /** 0-5 stars */ - readonly stars: number; - /** Comment about the movie, optional */ - readonly commentary?: Maybe; - /** Favorite color, optional */ - readonly favoriteColor?: Maybe; -} -/** The input object sent when passing a color */ -export interface ColorInput { - - readonly red: number; - - readonly green: number; - - readonly blue: number; -} -/** The episodes in the Star Wars trilogy */ - export enum Episode { - Newhope = 'NEWHOPE', - Empire = 'EMPIRE', - Jedi = 'JEDI', - } -/** Units of height */ - export enum LengthUnit { - Meter = 'METER', - Foot = 'FOOT', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace CreateReviewForEpisode { - export type Variables = { - readonly episode: Episode; - readonly review: ReviewInput; - }; - - export type Mutation = { - readonly __typename?: 'Mutation'; - - readonly createReview: Maybe; - }; - - export type CreateReview = { - readonly __typename?: 'Review'; - - readonly stars: number; - - readonly commentary: Maybe; - }; -} - -export namespace HeroAndFriendsNames { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - - readonly friends: Maybe>>; - }; - - export type Friends = { - readonly __typename?: 'Character'; - - readonly name: string; - }; -} - -export namespace HeroAppearsIn { - export type Variables = { - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - - readonly appearsIn: ReadonlyArray>; - }; -} - -export namespace HeroDetails { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - - readonly name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly height: Maybe; - }; - - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; - - readonly primaryFunction: Maybe; - }; -} - -export namespace HeroDetailsWithFragment { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = HeroDetails.Fragment; -} - -export namespace HeroName { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - }; -} - -export namespace HeroNameConditionalInclusion { - export type Variables = { - readonly episode?: Maybe; - readonly includeName: boolean; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - }; -} - -export namespace HeroNameConditionalExclusion { - export type Variables = { - readonly episode?: Maybe; - readonly skipName: boolean; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: 'Character'; - - readonly name: string; - }; -} - -export namespace HeroParentTypeDependentField { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = { - readonly __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - - readonly name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly friends: Maybe>>; - }; - - export type Friends = { - readonly __typename?: _HumanInlineFragment['__typename']; - - readonly name: string; - } & _HumanInlineFragment; - - export type _HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly height: Maybe; - }; - - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; - - readonly friends: Maybe>>; - }; - - export type _Friends = { - readonly __typename?: __HumanInlineFragment['__typename']; - - readonly name: string; - } & __HumanInlineFragment; - - export type __HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly height: Maybe; - }; -} - -export namespace HeroTypeDependentAliasedField { - export type Variables = { - readonly episode?: Maybe; - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly hero: Maybe; - }; - - export type Hero = (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly property: Maybe; - }; - - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; - - readonly property: Maybe; - }; -} - -export namespace HumanWithNullHeight { - export type Variables = { - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly human: Maybe; - }; - - export type Human = { - readonly __typename?: 'Human'; - - readonly name: string; - - readonly mass: Maybe; - }; -} - -export namespace TwoHeroes { - export type Variables = { - }; - - export type Query = { - readonly __typename?: 'Query'; - - readonly r2: Maybe; - - readonly luke: Maybe; - }; - - export type R2 = { - readonly __typename?: 'Character'; - - readonly name: string; - }; - - export type Luke = { - readonly __typename?: 'Character'; - - readonly name: string; - }; -} - -export namespace HeroDetails { - export type Fragment = { - readonly __typename?: 'Character'; - - readonly name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - readonly __typename?: 'Human'; - - readonly height: Maybe; - }; - - export type DroidInlineFragment = { - readonly __typename?: 'Droid'; - - readonly primaryFunction: Maybe; - }; -} - diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index e469b39337e..839602dfd11 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -1,349 +1,242 @@ -export type Maybe = T | null; - -/** The input object sent when someone is creating a new review */ -export interface ReviewInput { - /** 0-5 stars */ - stars: number; - /** Comment about the movie, optional */ - commentary?: Maybe; - /** Favorite color, optional */ - favoriteColor?: Maybe; +type Maybe = T | null; +export type Character = { + id: string, + name: string, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, +}; + +export type ColorInput = { + red: number, + green: number, + blue: number, +}; + +export type Droid = Character & { + id: string, + name: string, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + primaryFunction?: Maybe, +}; + + +export type DroidFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; + +export enum Episode { + Newhope = 'NEWHOPE', + Empire = 'EMPIRE', + Jedi = 'JEDI' } -/** The input object sent when passing a color */ -export interface ColorInput { - red: number; - - green: number; - - blue: number; -} -/** The episodes in the Star Wars trilogy */ - export enum Episode { - Newhope = 'NEWHOPE', - Empire = 'EMPIRE', - Jedi = 'JEDI', - } -/** Units of height */ - export enum LengthUnit { - Meter = 'METER', - Foot = 'FOOT', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace CreateReviewForEpisode { - export type Variables = { - episode: Episode; - review: ReviewInput; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - createReview: Maybe; - }; - - export type CreateReview = { - __typename?: 'Review'; - - stars: number; - - commentary: Maybe; - }; -} - -export namespace HeroAndFriendsNames { - export type Variables = { - episode?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: 'Character'; - - name: string; - - friends: Maybe<(Maybe)[]>; - }; - - export type Friends = { - __typename?: 'Character'; - - name: string; - }; -} - -export namespace HeroAppearsIn { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: 'Character'; - - name: string; - - appearsIn: (Maybe)[]; - }; -} - -export namespace HeroDetails { - export type Variables = { - episode?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - __typename?: 'Human'; - - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; +export type FriendsConnection = { + totalCount?: Maybe, + edges?: Maybe>>, + friends?: Maybe>>, + pageInfo: PageInfo, +}; + +export type FriendsEdge = { + cursor: string, + node?: Maybe, +}; + +export type Human = Character & { + id: string, + name: string, + homePlanet?: Maybe, + height?: Maybe, + mass?: Maybe, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + starships?: Maybe>>, +}; + + +export type HumanHeightArgs = { + unit: LengthUnit +}; + + +export type HumanFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; + +export enum LengthUnit { + Meter = 'METER', + Foot = 'FOOT' } -export namespace HeroDetailsWithFragment { - export type Variables = { - episode?: Maybe; - }; +export type Mutation = { + createReview?: Maybe, +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type MutationCreateReviewArgs = { + episode?: Maybe, + review: ReviewInput +}; - export type Hero = HeroDetails.Fragment; -} +export type PageInfo = { + startCursor?: Maybe, + endCursor?: Maybe, + hasNextPage: boolean, +}; -export namespace HeroName { - export type Variables = { - episode?: Maybe; - }; +export type Query = { + hero?: Maybe, + reviews?: Maybe>>, + search?: Maybe>>, + character?: Maybe, + droid?: Maybe, + human?: Maybe, + starship?: Maybe, +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHeroArgs = { + episode?: Maybe +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type QueryReviewsArgs = { + episode: Episode +}; -export namespace HeroNameConditionalInclusion { - export type Variables = { - episode?: Maybe; - includeName: boolean; - }; - export type Query = { - __typename?: 'Query'; +export type QuerySearchArgs = { + text?: Maybe +}; - hero: Maybe; - }; - export type Hero = { - __typename?: 'Character'; +export type QueryCharacterArgs = { + id: string +}; - name: string; - }; -} -export namespace HeroNameConditionalExclusion { - export type Variables = { - episode?: Maybe; - skipName: boolean; - }; +export type QueryDroidArgs = { + id: string +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHumanArgs = { + id: string +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type QueryStarshipArgs = { + id: string +}; -export namespace HeroParentTypeDependentField { - export type Variables = { - episode?: Maybe; - }; +export type Review = { + stars: number, + commentary?: Maybe, +}; - export type Query = { - __typename?: 'Query'; +export type ReviewInput = { + stars: number, + commentary: Maybe, + favoriteColor: Maybe, +}; - hero: Maybe; - }; +export type SearchResult = Human | Droid | Starship; - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; +export type Starship = { + id: string, + name: string, + length?: Maybe, +}; - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type StarshipLengthArgs = { + unit: LengthUnit +}; +export type CreateReviewForEpisodeMutationVariables = { + episode: Episode, + review: ReviewInput +}; - friends: Maybe<(Maybe)[]>; - }; - export type Friends = { - __typename?: _HumanInlineFragment['__typename']; +export type CreateReviewForEpisodeMutation = ({ __typename?: 'Mutation' } & { createReview: Maybe<({ __typename?: 'Review' } & Pick)> }); - name: string; - } & _HumanInlineFragment; +export type HeroAndFriendsNamesQueryVariables = { + episode?: Maybe +}; - export type _HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; +export type HeroAndFriendsNamesQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & { friends: Maybe>>> })> }); - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroAppearsInQueryVariables = {}; - friends: Maybe<(Maybe<_Friends>)[]>; - }; - export type _Friends = { - __typename?: __HumanInlineFragment['__typename']; +export type HeroAppearsInQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - name: string; - } & __HumanInlineFragment; +export type HeroDetailsQueryVariables = { + episode?: Maybe +}; - export type __HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; -} +export type HeroDetailsQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick)))> }); -export namespace HeroTypeDependentAliasedField { - export type Variables = { - episode?: Maybe; - }; +export type HeroDetailsWithFragmentQueryVariables = { + episode?: Maybe +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type HeroDetailsWithFragmentQuery = ({ __typename?: 'Query' } & { hero: Maybe }); - export type Hero = (HumanInlineFragment | DroidInlineFragment); +export type HeroDetailsFragment = (Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick))); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type HeroNameQueryVariables = { + episode?: Maybe +}; - property: Maybe; - }; - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroNameQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - property: Maybe; - }; -} +export type HeroNameConditionalInclusionQueryVariables = { + episode?: Maybe, + includeName: boolean +}; -export namespace HumanWithNullHeight { - export type Variables = { - }; - export type Query = { - __typename?: 'Query'; +export type HeroNameConditionalInclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - human: Maybe; - }; +export type HeroNameConditionalExclusionQueryVariables = { + episode?: Maybe, + skipName: boolean +}; - export type Human = { - __typename?: 'Human'; - name: string; +export type HeroNameConditionalExclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - mass: Maybe; - }; -} +export type HeroParentTypeDependentFieldQueryVariables = { + episode?: Maybe +}; -export namespace TwoHeroes { - export type Variables = { - }; - export type Query = { - __typename?: 'Query'; +export type HeroParentTypeDependentFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> }) | ({ __typename?: 'Droid' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> })))> }); - r2: Maybe; +export type HeroTypeDependentAliasedFieldQueryVariables = { + episode?: Maybe +}; - luke: Maybe; - }; - export type R2 = { - __typename?: 'Character'; +export type HeroTypeDependentAliasedFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(({ __typename?: 'Human' } & { property: Human['homePlanet'] }) | ({ __typename?: 'Droid' } & { property: Droid['primaryFunction'] }))> }); - name: string; - }; +export type HumanWithNullHeightQueryVariables = {}; - export type Luke = { - __typename?: 'Character'; - name: string; - }; -} - -export namespace HeroDetails { - export type Fragment = { - __typename?: 'Character'; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); +export type HumanWithNullHeightQuery = ({ __typename?: 'Query' } & { human: Maybe<({ __typename?: 'Human' } & Pick)> }); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type TwoHeroesQueryVariables = {}; - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; -} +export type TwoHeroesQuery = ({ __typename?: 'Query' } & { r2: Maybe>, luke: Maybe> }); diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index e469b39337e..839602dfd11 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -1,349 +1,242 @@ -export type Maybe = T | null; - -/** The input object sent when someone is creating a new review */ -export interface ReviewInput { - /** 0-5 stars */ - stars: number; - /** Comment about the movie, optional */ - commentary?: Maybe; - /** Favorite color, optional */ - favoriteColor?: Maybe; +type Maybe = T | null; +export type Character = { + id: string, + name: string, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, +}; + +export type ColorInput = { + red: number, + green: number, + blue: number, +}; + +export type Droid = Character & { + id: string, + name: string, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + primaryFunction?: Maybe, +}; + + +export type DroidFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; + +export enum Episode { + Newhope = 'NEWHOPE', + Empire = 'EMPIRE', + Jedi = 'JEDI' } -/** The input object sent when passing a color */ -export interface ColorInput { - red: number; - - green: number; - - blue: number; -} -/** The episodes in the Star Wars trilogy */ - export enum Episode { - Newhope = 'NEWHOPE', - Empire = 'EMPIRE', - Jedi = 'JEDI', - } -/** Units of height */ - export enum LengthUnit { - Meter = 'METER', - Foot = 'FOOT', - } - - -// ==================================================== -// Documents -// ==================================================== - - - -export namespace CreateReviewForEpisode { - export type Variables = { - episode: Episode; - review: ReviewInput; - }; - - export type Mutation = { - __typename?: 'Mutation'; - - createReview: Maybe; - }; - - export type CreateReview = { - __typename?: 'Review'; - - stars: number; - - commentary: Maybe; - }; -} - -export namespace HeroAndFriendsNames { - export type Variables = { - episode?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: 'Character'; - - name: string; - - friends: Maybe<(Maybe)[]>; - }; - - export type Friends = { - __typename?: 'Character'; - - name: string; - }; -} - -export namespace HeroAppearsIn { - export type Variables = { - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: 'Character'; - - name: string; - - appearsIn: (Maybe)[]; - }; -} - -export namespace HeroDetails { - export type Variables = { - episode?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - - hero: Maybe; - }; - - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - - export type HumanInlineFragment = { - __typename?: 'Human'; - - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; +export type FriendsConnection = { + totalCount?: Maybe, + edges?: Maybe>>, + friends?: Maybe>>, + pageInfo: PageInfo, +}; + +export type FriendsEdge = { + cursor: string, + node?: Maybe, +}; + +export type Human = Character & { + id: string, + name: string, + homePlanet?: Maybe, + height?: Maybe, + mass?: Maybe, + friends?: Maybe>>, + friendsConnection: FriendsConnection, + appearsIn: Array>, + starships?: Maybe>>, +}; + + +export type HumanHeightArgs = { + unit: LengthUnit +}; + + +export type HumanFriendsConnectionArgs = { + first?: Maybe, + after?: Maybe +}; + +export enum LengthUnit { + Meter = 'METER', + Foot = 'FOOT' } -export namespace HeroDetailsWithFragment { - export type Variables = { - episode?: Maybe; - }; +export type Mutation = { + createReview?: Maybe, +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type MutationCreateReviewArgs = { + episode?: Maybe, + review: ReviewInput +}; - export type Hero = HeroDetails.Fragment; -} +export type PageInfo = { + startCursor?: Maybe, + endCursor?: Maybe, + hasNextPage: boolean, +}; -export namespace HeroName { - export type Variables = { - episode?: Maybe; - }; +export type Query = { + hero?: Maybe, + reviews?: Maybe>>, + search?: Maybe>>, + character?: Maybe, + droid?: Maybe, + human?: Maybe, + starship?: Maybe, +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHeroArgs = { + episode?: Maybe +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type QueryReviewsArgs = { + episode: Episode +}; -export namespace HeroNameConditionalInclusion { - export type Variables = { - episode?: Maybe; - includeName: boolean; - }; - export type Query = { - __typename?: 'Query'; +export type QuerySearchArgs = { + text?: Maybe +}; - hero: Maybe; - }; - export type Hero = { - __typename?: 'Character'; +export type QueryCharacterArgs = { + id: string +}; - name: string; - }; -} -export namespace HeroNameConditionalExclusion { - export type Variables = { - episode?: Maybe; - skipName: boolean; - }; +export type QueryDroidArgs = { + id: string +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type QueryHumanArgs = { + id: string +}; - export type Hero = { - __typename?: 'Character'; - name: string; - }; -} +export type QueryStarshipArgs = { + id: string +}; -export namespace HeroParentTypeDependentField { - export type Variables = { - episode?: Maybe; - }; +export type Review = { + stars: number, + commentary?: Maybe, +}; - export type Query = { - __typename?: 'Query'; +export type ReviewInput = { + stars: number, + commentary: Maybe, + favoriteColor: Maybe, +}; - hero: Maybe; - }; +export type SearchResult = Human | Droid | Starship; - export type Hero = { - __typename?: HumanInlineFragment['__typename'] | DroidInlineFragment['__typename']; +export type Starship = { + id: string, + name: string, + length?: Maybe, +}; - name: string; - } & (HumanInlineFragment | DroidInlineFragment); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type StarshipLengthArgs = { + unit: LengthUnit +}; +export type CreateReviewForEpisodeMutationVariables = { + episode: Episode, + review: ReviewInput +}; - friends: Maybe<(Maybe)[]>; - }; - export type Friends = { - __typename?: _HumanInlineFragment['__typename']; +export type CreateReviewForEpisodeMutation = ({ __typename?: 'Mutation' } & { createReview: Maybe<({ __typename?: 'Review' } & Pick)> }); - name: string; - } & _HumanInlineFragment; +export type HeroAndFriendsNamesQueryVariables = { + episode?: Maybe +}; - export type _HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; +export type HeroAndFriendsNamesQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & { friends: Maybe>>> })> }); - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroAppearsInQueryVariables = {}; - friends: Maybe<(Maybe<_Friends>)[]>; - }; - export type _Friends = { - __typename?: __HumanInlineFragment['__typename']; +export type HeroAppearsInQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - name: string; - } & __HumanInlineFragment; +export type HeroDetailsQueryVariables = { + episode?: Maybe +}; - export type __HumanInlineFragment = { - __typename?: 'Human'; - height: Maybe; - }; -} +export type HeroDetailsQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick)))> }); -export namespace HeroTypeDependentAliasedField { - export type Variables = { - episode?: Maybe; - }; +export type HeroDetailsWithFragmentQueryVariables = { + episode?: Maybe +}; - export type Query = { - __typename?: 'Query'; - hero: Maybe; - }; +export type HeroDetailsWithFragmentQuery = ({ __typename?: 'Query' } & { hero: Maybe }); - export type Hero = (HumanInlineFragment | DroidInlineFragment); +export type HeroDetailsFragment = (Pick & (({ __typename?: 'Human' } & Pick) | ({ __typename?: 'Droid' } & Pick))); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type HeroNameQueryVariables = { + episode?: Maybe +}; - property: Maybe; - }; - export type DroidInlineFragment = { - __typename?: 'Droid'; +export type HeroNameQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - property: Maybe; - }; -} +export type HeroNameConditionalInclusionQueryVariables = { + episode?: Maybe, + includeName: boolean +}; -export namespace HumanWithNullHeight { - export type Variables = { - }; - export type Query = { - __typename?: 'Query'; +export type HeroNameConditionalInclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - human: Maybe; - }; +export type HeroNameConditionalExclusionQueryVariables = { + episode?: Maybe, + skipName: boolean +}; - export type Human = { - __typename?: 'Human'; - name: string; +export type HeroNameConditionalExclusionQuery = ({ __typename?: 'Query' } & { hero: Maybe> }); - mass: Maybe; - }; -} +export type HeroParentTypeDependentFieldQueryVariables = { + episode?: Maybe +}; -export namespace TwoHeroes { - export type Variables = { - }; - export type Query = { - __typename?: 'Query'; +export type HeroParentTypeDependentFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(Pick & (({ __typename?: 'Human' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> }) | ({ __typename?: 'Droid' } & { friends: Maybe & (({ __typename?: 'Human' } & Pick)))>>> })))> }); - r2: Maybe; +export type HeroTypeDependentAliasedFieldQueryVariables = { + episode?: Maybe +}; - luke: Maybe; - }; - export type R2 = { - __typename?: 'Character'; +export type HeroTypeDependentAliasedFieldQuery = ({ __typename?: 'Query' } & { hero: Maybe<(({ __typename?: 'Human' } & { property: Human['homePlanet'] }) | ({ __typename?: 'Droid' } & { property: Droid['primaryFunction'] }))> }); - name: string; - }; +export type HumanWithNullHeightQueryVariables = {}; - export type Luke = { - __typename?: 'Character'; - name: string; - }; -} - -export namespace HeroDetails { - export type Fragment = { - __typename?: 'Character'; - - name: string; - } & (HumanInlineFragment | DroidInlineFragment); +export type HumanWithNullHeightQuery = ({ __typename?: 'Query' } & { human: Maybe<({ __typename?: 'Human' } & Pick)> }); - export type HumanInlineFragment = { - __typename?: 'Human'; +export type TwoHeroesQueryVariables = {}; - height: Maybe; - }; - - export type DroidInlineFragment = { - __typename?: 'Droid'; - - primaryFunction: Maybe; - }; -} +export type TwoHeroesQuery = ({ __typename?: 'Query' } & { r2: Maybe>, luke: Maybe> }); diff --git a/dev-test/test-message/package-lock.json b/dev-test/test-message/package-lock.json deleted file mode 100644 index 9a7bc786321..00000000000 --- a/dev-test/test-message/package-lock.json +++ /dev/null @@ -1,384 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@types/prop-types": { - "version": "15.5.6", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.6.tgz", - "integrity": "sha512-ZBFR7TROLVzCkswA3Fmqq+IIJt62/T7aY/Dmz+QkU7CaW2QFqAitCE8Ups7IzmGhcN1YWMBT4Qcoc07jU9hOJQ==" - }, - "@types/react": { - "version": "16.4.18", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.18.tgz", - "integrity": "sha512-eFzJKEg6pdeaukVLVZ8Xb79CTl/ysX+ExmOfAAqcFlCCK5TgFDD9kWR0S18sglQ3EmM8U+80enjUqbfnUyqpdA==", - "requires": { - "@types/prop-types": "*", - "csstype": "^2.2.0" - } - }, - "csstype": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.5.7.tgz", - "integrity": "sha512-Nt5VDyOTIIV4/nRFswoCKps1R5CD1hkiyjBE9/thNaNZILLEviVw9yWQw15+O+CpNjQKB/uvdcxFFOrSflY3Yw==" - }, - "fbjs": { - "version": "0.8.17", - "requires": { - "core-js": "^1.0.0", - "isomorphic-fetch": "^2.1.1", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - }, - "dependencies": { - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "core-js": { - "version": "1.2.7", - "resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "ua-parser-js": { - "version": "0.7.19", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz", - "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ==" - }, - "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" - } - } - }, - "fbjs-css-vars": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.1.tgz", - "integrity": "sha512-IM+v/C40MNZWqsLErc32e0TyIk/NhkkQZL0QmjBh6zi1eXv0/GeVKmKmueQX7nn9SXQBQbTUcB8zuexIF3/88w==" - }, - "hoist-non-react-statics": { - "version": "2.5.5" - }, - "lodash": { - "version": "4.17.10" - }, - "lodash.flowright": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/lodash.flowright/-/lodash.flowright-3.5.0.tgz", - "integrity": "sha1-K1//OZcW1+fcVyT+k0n2cGUYTWc=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "react": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.6.0.tgz", - "integrity": "sha512-zJPnx/jKtuOEXCbQ9BKaxDMxR0001/hzxXwYxG8septeyYGfsgAei6NgfbVgOhbY1WOP2o3VPs/E9HaN+9hV3Q==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.10.0" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - } - } - }, - "react-apollo": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-2.2.4.tgz", - "integrity": "sha512-haS5R30Qvteb65ZLfWomUZQh47VU4ld4Kof3zlqdbLOrYPt3/DdVZC8ZFPZSxd5zPeIJtZqpUfAxD1WHVoMPIA==", - "requires": { - "fbjs": "^1.0.0", - "hoist-non-react-statics": "^3.0.0", - "invariant": "^2.2.2", - "lodash.flowright": "^3.5.0", - "lodash.isequal": "^4.5.0", - "prop-types": "^15.6.0" - }, - "dependencies": { - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "fbjs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz", - "integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==", - "requires": { - "core-js": "^2.4.1", - "fbjs-css-vars": "^1.0.0", - "isomorphic-fetch": "^2.1.1", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - } - }, - "hoist-non-react-statics": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.1.0.tgz", - "integrity": "sha512-MYcYuROh7SBM69xHGqXEwQqDux34s9tz+sCnxJmN18kgWh6JFdTw/5YdZtqsOdZJXddE/wUpCzfEdDrJj8p0Iw==", - "requires": { - "react-is": "^16.3.2" - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, - "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "ua-parser-js": { - "version": "0.7.18", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", - "integrity": "sha512-LtzwHlVHwFGTptfNSgezHp7WUlwiqb0gA9AALRbKaERfxwJoiX0A73QbTToxteIAuIaFshhgIZfqK8s7clqgnA==" - }, - "whatwg-fetch": { - "version": "2.0.4", - "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" - } - } - }, - "react-is": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.6.0.tgz", - "integrity": "sha512-q8U7k0Fi7oxF1HvQgyBjPwDXeMplEsArnKt2iYhuIF86+GBbgLHdAmokL3XUFjTd7Q363OSNG55FOGUdONVn1g==" - }, - "scheduler": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.10.0.tgz", - "integrity": "sha512-+TSTVTCBAA3h8Anei3haDc1IRwMeDmtI/y/o3iBe3Mjl2vwYF9DtPDt929HyRmV/e7au7CLu8sc4C4W0VOs29w==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - }, - "dependencies": { - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - } - } - }, - "stencil-apollo": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/stencil-apollo/-/stencil-apollo-0.0.1.tgz", - "integrity": "sha512-2ZzvJ/ptA7/fhJ06BoJ073GjhVgaKivXOWoYpvboPCFnZ9dcvO4hX9XUfqiOXfn9Q1778bni9KUU45CNy9xm5w==" - } - } -} diff --git a/dev-test/test-message/types.reactApollo.noNamespaces.tsx b/dev-test/test-message/types.reactApollo.noNamespaces.tsx deleted file mode 100644 index 2a5187d26fe..00000000000 --- a/dev-test/test-message/types.reactApollo.noNamespaces.tsx +++ /dev/null @@ -1,317 +0,0 @@ -// tslint:disable -export type Maybe = T | null; - - -export interface CreateMessageInput { - - description: string; -} - - -// ==================================================== -// Documents -// ==================================================== - - - - export type GetMessagesVariables = { - tab: string; - } - - export type GetMessagesQuery = { - __typename?: "Query"; - - messages: Maybe<(Maybe)[]>; - } - - export type GetMessagesMessages = { - __typename?: "Message"; - - id: string; - } - - export type CreateMessageVariables = { - args: CreateMessageInput; - } - - export type CreateMessageMutation = { - __typename?: "Mutation"; - - createMessage: Maybe; - } - - export type CreateMessageCreateMessage = { - __typename?: "Message"; - - id: string; - } - - export type DeclineVariables = { - id: string; - reason: string; - } - - export type DeclineMutation = { - __typename?: "Mutation"; - - decline: Maybe; - } - - export type DeclineDecline = { - __typename?: "Message"; - - id: string; - } - - export type ApproveVariables = { - id: string; - } - - export type ApproveMutation = { - __typename?: "Mutation"; - - approve: Maybe; - } - - export type ApproveApprove = { - __typename?: "Message"; - - id: string; - } - - export type EscalateVariables = { - id: string; - } - - export type EscalateMutation = { - __typename?: "Mutation"; - - escalate: Maybe; - } - - export type EscalateEscalate = { - __typename?: "Message"; - - id: string; - } - - - import gql from 'graphql-tag'; - import * as React from 'react'; -import * as ReactApollo from 'react-apollo'; - - - - - - - -// ==================================================== -// Components -// ==================================================== - - - export const GetMessagesDocument = gql` - query GetMessages($tab: String!) { - messages(tab: $tab) { - id - } -} - - - - `; - export class GetMessagesComponent extends React.Component>> { - render(){ - return ( - - query={ GetMessagesDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type GetMessagesProps = - Partial< - ReactApollo.DataProps< - GetMessagesQuery, - GetMessagesVariables - > - > - & TChildProps; - export function GetMessagesHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - GetMessagesQuery, - GetMessagesVariables, - GetMessagesProps - > | undefined){ - return ReactApollo.graphql>( - GetMessagesDocument, - operationOptions - ); - }; - export const CreateMessageDocument = gql` - mutation CreateMessage($args: CreateMessageInput!) { - createMessage(args: $args) { - id - } -} - - - - `; - export class CreateMessageComponent extends React.Component>> { - render(){ - return ( - - mutation={ CreateMessageDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type CreateMessageProps = - Partial< - ReactApollo.MutateProps< - CreateMessageMutation, - CreateMessageVariables - > - > - & TChildProps; - export type CreateMessageMutationFn = ReactApollo.MutationFn; - export function CreateMessageHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - CreateMessageMutation, - CreateMessageVariables, - CreateMessageProps - > | undefined){ - return ReactApollo.graphql>( - CreateMessageDocument, - operationOptions - ); - }; - export const DeclineDocument = gql` - mutation Decline($id: ID!, $reason: String!) { - decline(id: $id, reason: $reason) { - id - } -} - - - - `; - export class DeclineComponent extends React.Component>> { - render(){ - return ( - - mutation={ DeclineDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type DeclineProps = - Partial< - ReactApollo.MutateProps< - DeclineMutation, - DeclineVariables - > - > - & TChildProps; - export type DeclineMutationFn = ReactApollo.MutationFn; - export function DeclineHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - DeclineMutation, - DeclineVariables, - DeclineProps - > | undefined){ - return ReactApollo.graphql>( - DeclineDocument, - operationOptions - ); - }; - export const ApproveDocument = gql` - mutation Approve($id: ID!) { - approve(id: $id) { - id - } -} - - - - `; - export class ApproveComponent extends React.Component>> { - render(){ - return ( - - mutation={ ApproveDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type ApproveProps = - Partial< - ReactApollo.MutateProps< - ApproveMutation, - ApproveVariables - > - > - & TChildProps; - export type ApproveMutationFn = ReactApollo.MutationFn; - export function ApproveHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - ApproveMutation, - ApproveVariables, - ApproveProps - > | undefined){ - return ReactApollo.graphql>( - ApproveDocument, - operationOptions - ); - }; - export const EscalateDocument = gql` - mutation Escalate($id: ID!) { - escalate(id: $id) { - id - } -} - - - - `; - export class EscalateComponent extends React.Component>> { - render(){ - return ( - - mutation={ EscalateDocument } - {...(this as any)['props'] as any} - /> - ); - } - } - export type EscalateProps = - Partial< - ReactApollo.MutateProps< - EscalateMutation, - EscalateVariables - > - > - & TChildProps; - export type EscalateMutationFn = ReactApollo.MutationFn; - export function EscalateHOC(operationOptions: - ReactApollo.OperationOption< - TProps, - EscalateMutation, - EscalateVariables, - EscalateProps - > | undefined){ - return ReactApollo.graphql>( - EscalateDocument, - operationOptions - ); - }; diff --git a/dev-test/test-message/types.stencilApollo.noNamespaces.tsx b/dev-test/test-message/types.stencilApollo.noNamespaces.tsx deleted file mode 100644 index bdf0c208169..00000000000 --- a/dev-test/test-message/types.stencilApollo.noNamespaces.tsx +++ /dev/null @@ -1,185 +0,0 @@ -// tslint:disable -export type Maybe = T | null; - - -export interface CreateMessageInput { - - description: string; -} - - -// ==================================================== -// Documents -// ==================================================== - - - - export type GetMessagesVariables = { - tab: string; - } - - export type GetMessagesQuery = { - __typename?: "Query"; - - messages: Maybe<(Maybe)[]>; - } - - export type GetMessagesMessages = { - __typename?: "Message"; - - id: string; - } - - export type CreateMessageVariables = { - args: CreateMessageInput; - } - - export type CreateMessageMutation = { - __typename?: "Mutation"; - - createMessage: Maybe; - } - - export type CreateMessageCreateMessage = { - __typename?: "Message"; - - id: string; - } - - export type DeclineVariables = { - id: string; - reason: string; - } - - export type DeclineMutation = { - __typename?: "Mutation"; - - decline: Maybe; - } - - export type DeclineDecline = { - __typename?: "Message"; - - id: string; - } - - export type ApproveVariables = { - id: string; - } - - export type ApproveMutation = { - __typename?: "Mutation"; - - approve: Maybe; - } - - export type ApproveApprove = { - __typename?: "Message"; - - id: string; - } - - export type EscalateVariables = { - id: string; - } - - export type EscalateMutation = { - __typename?: "Mutation"; - - escalate: Maybe; - } - - export type EscalateEscalate = { - __typename?: "Message"; - - id: string; - } - - -import gql from 'graphql-tag'; - - - - - - -// ==================================================== -// Components -// ==================================================== - - - export const GetMessagesDocument = gql` - query GetMessages($tab: String!) { - messages(tab: $tab) { - id - } -} - - - - `; - export interface GetMessagesComponentProps { - variables ?: GetMessagesVariables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; - } - export const GetMessagesComponent = (props: GetMessagesComponentProps) => ; - export const CreateMessageDocument = gql` - mutation CreateMessage($args: CreateMessageInput!) { - createMessage(args: $args) { - id - } -} - - - - `; - export interface CreateMessageComponentProps { - variables ?: CreateMessageVariables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; - } - export const CreateMessageComponent = (props: CreateMessageComponentProps) => ; - export const DeclineDocument = gql` - mutation Decline($id: ID!, $reason: String!) { - decline(id: $id, reason: $reason) { - id - } -} - - - - `; - export interface DeclineComponentProps { - variables ?: DeclineVariables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; - } - export const DeclineComponent = (props: DeclineComponentProps) => ; - export const ApproveDocument = gql` - mutation Approve($id: ID!) { - approve(id: $id) { - id - } -} - - - - `; - export interface ApproveComponentProps { - variables ?: ApproveVariables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; - } - export const ApproveComponent = (props: ApproveComponentProps) => ; - export const EscalateDocument = gql` - mutation Escalate($id: ID!) { - escalate(id: $id) { - id - } -} - - - - `; - export interface EscalateComponentProps { - variables ?: EscalateVariables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-mutation/types').OnMutationReadyFn; - } - export const EscalateComponent = (props: EscalateComponentProps) => ; diff --git a/dev-test/test-mongodb/schema.graphql b/dev-test/test-mongodb/schema.graphql index 85abd12da0c..a173399dd5f 100644 --- a/dev-test/test-mongodb/schema.graphql +++ b/dev-test/test-mongodb/schema.graphql @@ -1,17 +1,3 @@ -directive @union(discriminatorField: String) on UNION -directive @abstractEntity(discriminatorField: String!) on INTERFACE -directive @entity(embedded: Boolean, additionalFields: [AdditionalEntityFields]) on OBJECT -directive @column(name: String, overrideType: String, overrideIsArray: Boolean) on FIELD_DEFINITION -directive @id on FIELD_DEFINITION -directive @link on FIELD_DEFINITION -directive @embedded on FIELD_DEFINITION -directive @map(path: String!) on FIELD_DEFINITION -# Inputs -input AdditionalEntityFields { - path: String - type: String -} - enum Role { ADMIN WRITER diff --git a/dev-test/test-schema/flow-types.flow.js b/dev-test/test-schema/flow-types.flow.js index bf488c79ee8..13a2c7a6e5a 100644 --- a/dev-test/test-schema/flow-types.flow.js +++ b/dev-test/test-schema/flow-types.flow.js @@ -56,13 +56,13 @@ export type TypeResolveFn = ( export type NextResolverFn = () => Promise; -export type DirectiveResolverFn = ( - next?: NextResolverFn, - source?: any, - args?: TArgs, - context?: TContext, +export type DirectiveResolverFn = ( + next?: NextResolverFn, + parent?: Parent, + args?: Args, + context?: Context, info?: GraphQLResolveInfo -) => TResult | Promise; +) => Result | Promise; export interface QueryResolvers { allUsers?: Resolver, ParentType, Context>, @@ -75,7 +75,9 @@ export interface UserResolvers { email?: Resolver, } -export interface ResolversRoot { - Query?: QueryResolvers<>, - User?: UserResolvers<>, -} +export type IResolvers = { + Query?: QueryResolvers<>, + User?: UserResolvers<>, +}; + +export type IDirectiveResolvers = {}; diff --git a/dev-test/test-schema/resolvers-root.ts b/dev-test/test-schema/resolvers-root.ts index 9fc5b3d082a..4d266c520a7 100644 --- a/dev-test/test-schema/resolvers-root.ts +++ b/dev-test/test-schema/resolvers-root.ts @@ -1,184 +1,103 @@ // tslint:disable -export type Maybe = T | null; +type Maybe = T | null; +export type QueryRoot = { + allUsers: Array>, + userById?: Maybe, + answer: Array, +}; +export type QueryRootUserByIdArgs = { + id: number +}; +export type SubscriptionRoot = { + newUser?: Maybe, +}; - - - - -// ==================================================== -// Types -// ==================================================== - - - -export interface QueryRoot { - - allUsers: (Maybe)[]; - - userById?: Maybe; - /** Generates a new answer for the guessing game */ - answer: number[]; -} - - -export interface User { - - id: number; - - name: string; - - email: string; -} - - -export interface SubscriptionRoot { - - newUser?: Maybe; -} - - - -// ==================================================== -// Arguments -// ==================================================== - -export interface UserByIdQueryRootArgs { - - id: number; -} - +export type User = { + id: number, + name: string, + email: string, +}; import { GraphQLResolveInfo } from 'graphql'; +export type ResolverFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => Promise | TResult; + +export type StitchingResolver = { + fragment: string; + resolve: ResolverFn; +}; + +export type Resolver = + | ResolverFn + | StitchingResolver; + +export type SubscriptionSubscribeFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => AsyncIterator | Promise>; + +export type SubscriptionResolveFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => TResult | Promise; - - - -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -export interface ISubscriptionResolverObject { - subscribe( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): AsyncIterator | Promise>; - resolve?( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): R | Result | Promise; +export interface ISubscriptionResolverObject { + subscribe: SubscriptionSubscribeFn; + resolve?: SubscriptionResolveFn; } -export type SubscriptionResolver = - | ((...args: any[]) => ISubscriptionResolverObject) - | ISubscriptionResolverObject; +export type SubscriptionResolver = + | ((...args: any[]) => ISubscriptionResolverObject) + | ISubscriptionResolverObject; -export type TypeResolveFn = ( - parent: Parent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe; +export type TypeResolveFn = ( + parent?: TParent, + context?: TContext, + info?: GraphQLResolveInfo +) => Maybe; export type NextResolverFn = () => Promise; -export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, +export type DirectiveResolverFn = ( + next?: NextResolverFn, + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo ) => TResult | Promise; - -export namespace QueryRootResolvers { - export interface Resolvers { - - allUsers?: AllUsersResolver<(Maybe)[], TypeParent, TContext>; - - userById?: UserByIdResolver, TypeParent, TContext>; - /** Generates a new answer for the guessing game */ - answer?: AnswerResolver; - } - - - export type AllUsersResolver)[], Parent = {}, TContext = {}> = Resolver; - export type UserByIdResolver, Parent = {}, TContext = {}> = Resolver; - export interface UserByIdArgs { - - id: number; - } - - - export type AnswerResolver = Resolver; -} - -export namespace UserResolvers { - export interface Resolvers { - - id?: IdResolver; - - name?: NameResolver; - - email?: EmailResolver; - } - - - export type IdResolver = Resolver; - export type NameResolver = Resolver; - export type EmailResolver = Resolver; -} - -export namespace SubscriptionRootResolvers { - export interface Resolvers { - - newUser?: NewUserResolver, TypeParent, TContext>; - } - - - export type NewUserResolver, Parent = {}, TContext = {}> = SubscriptionResolver; +export interface QueryRootResolvers { + allUsers?: Resolver>, ParentType, Context>, + userById?: Resolver, ParentType, Context, QueryRootUserByIdArgs>, + answer?: Resolver, ParentType, Context>, } - - -/** Directs the executor to skip this field or fragment when the `if` argument is true. */ -export type SkipDirectiveResolver = DirectiveResolverFn; -export interface SkipDirectiveArgs { - /** Skipped when true. */ - if: boolean; +export interface SubscriptionRootResolvers { + newUser?: SubscriptionResolver, ParentType, Context>, } -/** Directs the executor to include this field or fragment only when the `if` argument is true. */ -export type IncludeDirectiveResolver = DirectiveResolverFn; -export interface IncludeDirectiveArgs { - /** Included when true. */ - if: boolean; +export interface UserResolvers { + id?: Resolver, + name?: Resolver, + email?: Resolver, } -/** Marks an element of a GraphQL schema as no longer supported. */ -export type DeprecatedDirectiveResolver = DirectiveResolverFn; -export interface DeprecatedDirectiveArgs { - /** Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax (as specified by [CommonMark](https://commonmark.org/). */ - reason?: string; -} +export type IResolvers = { + QueryRoot?: QueryRootResolvers, + SubscriptionRoot?: SubscriptionRootResolvers, + User?: UserResolvers, +} & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; -export type IResolvers = { - QueryRoot?: QueryRootResolvers.Resolvers; - User?: UserResolvers.Resolvers; - SubscriptionRoot?: SubscriptionRootResolvers.Resolvers; -} & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; - -export type IDirectiveResolvers = { - skip?: SkipDirectiveResolver; - include?: IncludeDirectiveResolver; - deprecated?: DeprecatedDirectiveResolver; -} & { [directiveName: string] : never }; +export type IDirectiveResolvers = {} & { [directiveName: string]: DirectiveResolverFn }; diff --git a/dev-test/test-schema/resolvers-types.ts b/dev-test/test-schema/resolvers-types.ts index 513f347a991..8b9c044cc80 100644 --- a/dev-test/test-schema/resolvers-types.ts +++ b/dev-test/test-schema/resolvers-types.ts @@ -1,169 +1,94 @@ // tslint:disable -export type Maybe = T | null; +type Maybe = T | null; +export type Query = { + allUsers: Array>, + userById?: Maybe, + answer: Array, +}; +export type QueryUserByIdArgs = { + id: number +}; - - - - - -// ==================================================== -// Types -// ==================================================== - - - -export interface Query { - - allUsers: (Maybe)[]; - - userById?: Maybe; - - answer: number[]; -} - - -export interface User { - - id: number; - - name: string; - - email: string; -} - - - -// ==================================================== -// Arguments -// ==================================================== - -export interface UserByIdQueryArgs { - - id: number; -} - +export type User = { + id: number, + name: string, + email: string, +}; import { GraphQLResolveInfo } from 'graphql'; +export type ResolverFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => Promise | TResult; + +export type StitchingResolver = { + fragment: string; + resolve: ResolverFn; +}; + +export type Resolver = + | ResolverFn + | StitchingResolver; + +export type SubscriptionSubscribeFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => AsyncIterator | Promise>; + +export type SubscriptionResolveFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => TResult | Promise; - - - -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -export interface ISubscriptionResolverObject { - subscribe( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): AsyncIterator | Promise>; - resolve?( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): R | Result | Promise; +export interface ISubscriptionResolverObject { + subscribe: SubscriptionSubscribeFn; + resolve?: SubscriptionResolveFn; } -export type SubscriptionResolver = - | ((...args: any[]) => ISubscriptionResolverObject) - | ISubscriptionResolverObject; +export type SubscriptionResolver = + | ((...args: any[]) => ISubscriptionResolverObject) + | ISubscriptionResolverObject; -export type TypeResolveFn = ( - parent: Parent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe; +export type TypeResolveFn = ( + parent?: TParent, + context?: TContext, + info?: GraphQLResolveInfo +) => Maybe; export type NextResolverFn = () => Promise; -export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, +export type DirectiveResolverFn = ( + next?: NextResolverFn, + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo ) => TResult | Promise; - -export namespace QueryResolvers { - export interface Resolvers { - - allUsers?: AllUsersResolver<(Maybe)[], TypeParent, TContext>; - - userById?: UserByIdResolver, TypeParent, TContext>; - - answer?: AnswerResolver; - } - - - export type AllUsersResolver)[], Parent = {}, TContext = {}> = Resolver; - export type UserByIdResolver, Parent = {}, TContext = {}> = Resolver; - export interface UserByIdArgs { - - id: number; - } - - - export type AnswerResolver = Resolver; -} - -export namespace UserResolvers { - export interface Resolvers { - - id?: IdResolver; - - name?: NameResolver; - - email?: EmailResolver; - } - - - export type IdResolver = Resolver; - export type NameResolver = Resolver; - export type EmailResolver = Resolver; -} - - - -/** Directs the executor to skip this field or fragment when the `if` argument is true. */ -export type SkipDirectiveResolver = DirectiveResolverFn; -export interface SkipDirectiveArgs { - /** Skipped when true. */ - if: boolean; -} - -/** Directs the executor to include this field or fragment only when the `if` argument is true. */ -export type IncludeDirectiveResolver = DirectiveResolverFn; -export interface IncludeDirectiveArgs { - /** Included when true. */ - if: boolean; +export interface QueryResolvers { + allUsers?: Resolver>, ParentType, Context>, + userById?: Resolver, ParentType, Context, QueryUserByIdArgs>, + answer?: Resolver, ParentType, Context>, } -/** Marks an element of a GraphQL schema as no longer supported. */ -export type DeprecatedDirectiveResolver = DirectiveResolverFn; -export interface DeprecatedDirectiveArgs { - /** Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax (as specified by [CommonMark](https://commonmark.org/). */ - reason?: string; +export interface UserResolvers { + id?: Resolver, + name?: Resolver, + email?: Resolver, } +export type IResolvers = { + Query?: QueryResolvers, + User?: UserResolvers, +} & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; - -export type IResolvers = { - Query?: QueryResolvers.Resolvers; - User?: UserResolvers.Resolvers; -} & { [typeName: string] : never }; - -export type IDirectiveResolvers = { - skip?: SkipDirectiveResolver; - include?: IncludeDirectiveResolver; - deprecated?: DeprecatedDirectiveResolver; -} & { [directiveName: string] : never }; +export type IDirectiveResolvers = {} & { [directiveName: string]: DirectiveResolverFn }; diff --git a/dev-test/test-schema/typings.avoidOptionals.ts b/dev-test/test-schema/typings.avoidOptionals.ts index bc89dc8afad..9283e98aaab 100644 --- a/dev-test/test-schema/typings.avoidOptionals.ts +++ b/dev-test/test-schema/typings.avoidOptionals.ts @@ -1,44 +1,16 @@ -export type Maybe = T | null; - - - - - - - - -// ==================================================== -// Types -// ==================================================== - - - -export interface Query { - - allUsers: (Maybe)[]; - - userById: Maybe; -} - - -export interface User { - - id: number; - - name: string; - - email: string; -} - - - -// ==================================================== -// Arguments -// ==================================================== - -export interface UserByIdQueryArgs { - - id: number; -} - - +type Maybe = T | null; +export type Query = { + allUsers: Array>, + userById: Maybe, +}; + + +export type QueryUserByIdArgs = { + id: number +}; + +export type User = { + id: number, + name: string, + email: string, +}; diff --git a/dev-test/test-schema/typings.immutableTypes.ts b/dev-test/test-schema/typings.immutableTypes.ts index 65f97847589..07ac48318b0 100644 --- a/dev-test/test-schema/typings.immutableTypes.ts +++ b/dev-test/test-schema/typings.immutableTypes.ts @@ -1,44 +1,16 @@ -export type Maybe = T | null; - - - - - - - - -// ==================================================== -// Types -// ==================================================== - - - -export interface Query { - - allUsers: (Maybe)[]; - - userById?: Maybe; -} - - -export interface User { - - id: number; - - name: string; - - email: string; -} - - - -// ==================================================== -// Arguments -// ==================================================== - -export interface UserByIdQueryArgs { - - id: number; -} - - +type Maybe = T | null; +export type Query = { + allUsers: Array>, + userById?: Maybe, +}; + + +export type QueryUserByIdArgs = { + id: number +}; + +export type User = { + id: number, + name: string, + email: string, +}; diff --git a/dev-test/test-schema/typings.ts b/dev-test/test-schema/typings.ts index 444611508a0..baf5120a9c4 100644 --- a/dev-test/test-schema/typings.ts +++ b/dev-test/test-schema/typings.ts @@ -1,164 +1,92 @@ // tslint:disable -export type Maybe = T | null; +type Maybe = T | null; +export type Query = { + allUsers: Array>, + userById?: Maybe, +}; +export type QueryUserByIdArgs = { + id: number +}; - - - - - -// ==================================================== -// Types -// ==================================================== - - - -export interface Query { - - allUsers: (Maybe)[]; - - userById?: Maybe; -} - - -export interface User { - - id: number; - - name: string; - - email: string; -} - - - -// ==================================================== -// Arguments -// ==================================================== - -export interface UserByIdQueryArgs { - - id: number; -} - +export type User = { + id: number, + name: string, + email: string, +}; import { GraphQLResolveInfo } from 'graphql'; +export type ResolverFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => Promise | TResult; + +export type StitchingResolver = { + fragment: string; + resolve: ResolverFn; +}; + +export type Resolver = + | ResolverFn + | StitchingResolver; + +export type SubscriptionSubscribeFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => AsyncIterator | Promise>; + +export type SubscriptionResolveFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => TResult | Promise; - - - -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -export interface ISubscriptionResolverObject { - subscribe( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): AsyncIterator | Promise>; - resolve?( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): R | Result | Promise; +export interface ISubscriptionResolverObject { + subscribe: SubscriptionSubscribeFn; + resolve?: SubscriptionResolveFn; } -export type SubscriptionResolver = - | ((...args: any[]) => ISubscriptionResolverObject) - | ISubscriptionResolverObject; +export type SubscriptionResolver = + | ((...args: any[]) => ISubscriptionResolverObject) + | ISubscriptionResolverObject; -export type TypeResolveFn = ( - parent: Parent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe; +export type TypeResolveFn = ( + parent?: TParent, + context?: TContext, + info?: GraphQLResolveInfo +) => Maybe; export type NextResolverFn = () => Promise; -export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, +export type DirectiveResolverFn = ( + next?: NextResolverFn, + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo ) => TResult | Promise; - -export namespace QueryResolvers { - export interface Resolvers { - - allUsers?: AllUsersResolver<(Maybe)[], TypeParent, TContext>; - - userById?: UserByIdResolver, TypeParent, TContext>; - } - - - export type AllUsersResolver)[], Parent = {}, TContext = {}> = Resolver; - export type UserByIdResolver, Parent = {}, TContext = {}> = Resolver; - export interface UserByIdArgs { - - id: number; - } - - -} - -export namespace UserResolvers { - export interface Resolvers { - - id?: IdResolver; - - name?: NameResolver; - - email?: EmailResolver; - } - - - export type IdResolver = Resolver; - export type NameResolver = Resolver; - export type EmailResolver = Resolver; -} - - - -/** Directs the executor to skip this field or fragment when the `if` argument is true. */ -export type SkipDirectiveResolver = DirectiveResolverFn; -export interface SkipDirectiveArgs { - /** Skipped when true. */ - if: boolean; -} - -/** Directs the executor to include this field or fragment only when the `if` argument is true. */ -export type IncludeDirectiveResolver = DirectiveResolverFn; -export interface IncludeDirectiveArgs { - /** Included when true. */ - if: boolean; +export interface QueryResolvers { + allUsers?: Resolver>, ParentType, Context>, + userById?: Resolver, ParentType, Context, QueryUserByIdArgs>, } -/** Marks an element of a GraphQL schema as no longer supported. */ -export type DeprecatedDirectiveResolver = DirectiveResolverFn; -export interface DeprecatedDirectiveArgs { - /** Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax (as specified by [CommonMark](https://commonmark.org/). */ - reason?: string; +export interface UserResolvers { + id?: Resolver, + name?: Resolver, + email?: Resolver, } +export type IResolvers = { + Query?: QueryResolvers, + User?: UserResolvers, +} & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; - -export type IResolvers = { - Query?: QueryResolvers.Resolvers; - User?: UserResolvers.Resolvers; -} & { [typeName: string] : never }; - -export type IDirectiveResolvers = { - skip?: SkipDirectiveResolver; - include?: IncludeDirectiveResolver; - deprecated?: DeprecatedDirectiveResolver; -} & { [directiveName: string] : never }; +export type IDirectiveResolvers = {} & { [directiveName: string]: DirectiveResolverFn }; diff --git a/docs/custom-codegen/extend-schema.md b/docs/custom-codegen/extend-schema.md index 082d8c3e609..ffaa4e09680 100644 --- a/docs/custom-codegen/extend-schema.md +++ b/docs/custom-codegen/extend-schema.md @@ -26,7 +26,7 @@ For example, let's add a custom `@directive` that tells the codegen to ignore a ```js module.exports = { - plugin: (schema, documents, config) => { + plugin: (schema, documents, config, info) => { const typesMap = schema.getTypeMap(); return Object.keys(typesMap) diff --git a/docs/custom-codegen/using-handlebars.md b/docs/custom-codegen/using-handlebars.md deleted file mode 100644 index 8a4f55bbaa8..00000000000 --- a/docs/custom-codegen/using-handlebars.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: using-handlebars -title: Using Handlebars ---- - -Most of the plugins we maintain are built with [Handlebars](https://handlebarsjs.com/), because it's easy to use and we can leverage it's helpers and partial features, and reuse parts of the plugins code. - -If you wish to use Handlebars, we recommend to use one of the GraphQL Code-Generators internal function, and transform your `GraphQLSchema` and GraphQL documents to Handlebars-ready objects. - -You can do it like that: - -```js -const { schemaToTemplateContext } = require('graphql-codegen-core'); -const { compile } = require('handlebars'); - -module.exports = { - plugin: (schema, documents, config) => { - const templateContext = schemaToTemplateContext(schema); - - return compile(`{{#each types}} {{ name }} {{/each}}`)(templateContext); - } -}; -``` - -The `schemaToTemplateContext` method [returns an object, in this structure](https://github.com/dotansimha/graphql-code-generator/blob/master/packages/graphql-codegen-core/src/types.ts#L98-L114). - -You can also do the same for your documents, by doing: - -```js -const { schemaToTemplateContext, transformDocumentsFiles } = require('graphql-codegen-core'); -const { compile } = require('handlebars'); - -module.exports = { - plugin: (schema, documents, config) => { - const transformedDocuments = transformDocumentsFiles(schema, documents); - - return compile(`{{#each operations}} {{ name }} {{/each}}`)(transformedDocuments); - } -}; -``` - -The `transformDocumentsFiles` method [returns an object, in this structure](https://github.com/dotansimha/graphql-code-generator/blob/master/packages/graphql-codegen-core/src/types.ts#L223-L228). diff --git a/docs/custom-codegen/using-visitor.md b/docs/custom-codegen/using-visitor.md new file mode 100644 index 00000000000..3e799ffc889 --- /dev/null +++ b/docs/custom-codegen/using-visitor.md @@ -0,0 +1,122 @@ +--- +id: using-visitor +title: Visitor Pattern +--- + +Most of the codegen's plugins are written with a design-pattern called [Visitor](https://en.wikipedia.org/wiki/Visitor_pattern). GraphQL has an internal mechanism for "visiting" a GraphQLSchema and GraphQL operations, and you can use it to transform your GraphQL definitions into a custom output. + +With visitor pattern you can call a custom function on each AST node, and transform it into something else. + +You can use [ASTExplorer](https://astexplorer.net/) and see how does GraphQL represents it's definitions in a JSON structure, and you can also use this to understand which function will be called each time. + +In [graphql.org](https://graphql.org/graphql-js/language/#visit) you can find the exact API documentation we are going to use in this section. + +## Basic Visitor + +In this example, we will transform a basic type definition into a list of types and fields: + +From: + +```graphql +type MyType { + myField: String! +} + +type MyOtherType { + myOtherField: Int! +} +``` + +To + +``` +MyType.myField +MyOtherType.myOtherField +``` + +To get started with a basic visitor, start by extracting the `astNode` of your `GraphQLSchema`: + +```javascript +const { printSchema, parse } = require('graphql'); + +module.exports = { + plugin: (schema, documents, config) => { + const printedSchema = printSchema(schema); // Returns a string representation of the schema + const astNode = parse(printedSchema); // Transforms the string into ASTNode + } +}; +``` + +> Note: if you wish to have GraphQL directives when you print your schema, use `printSchemaWithDirectives` from `graphql-toolkit` package. + +Then, create your initial visitor, in our case, we would like to transform a `FieldDefinition` and `ObjectTypeDefinition`, so let's create an object with a stub definitions, an use `visit` to run it: + +```javascript +const { printSchema, parse, visit } = require('graphql'); + +module.exports = { + plugin: (schema, documents, config) => { + const printedSchema = printSchema(schema); // Returns a string representation of the schema + const astNode = parse(printedSchema); // Transforms the string into ASTNode + const visitor = { + FieldDefinition: node => { + // This function triggered per each field + }, + ObjectTypeDefinition: node => { + // This function triggered per each type + } + }; + + const result = visit(astNode, { leave: visitor }); + + return result.definitions.join('\n'); + } +}; +``` + +Now, let's implement `ObjectTypeDefinition` and `FieldDefinition`: + +```javascript +const { printSchema, parse, visit } = require('graphql'); + +module.exports = { + plugin: (schema, documents, config) => { + const printedSchema = printSchema(schema); // Returns a string representation of the schema + const astNode = parse(printedSchema); // Transforms the string into ASTNode + const visitor = { + FieldDefinition: node => { + // Transform the field AST node into a string, containing only the name of the field + return node.name.value; + }, + ObjectTypeDefinition: node => { + // "node.fields" is an array of strings, because we transformed it using "FieldDefinition". + return node.fields.map(field => `${node.name.value}.${field}`).join('\n'); + } + }; + + const result = visit(astNode, { leave: visitor }); + + return result.definitions.join('\n'); + } +}; +``` + +## Codegen and Visitors + +This repository also contains a set of utils that might help you to write plugins faster using visitor pattern. + +All those utils are part of `graphql-codegen-visitor-plugin-common` package. + +It includes set of Visitor classes that you can use and extend, to implement your plugin easily: + +- `BaseVisitor` is a class that contains a very basic implementation and utils for plugin configuration, and let you easily implement plugins that compatiable with `namingConvention` and `scalars` configuration. [Here you can find an example for using it](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/typescript-mongodb/src/visitor.ts#L56). + +- `BaseTypesVisitor` is a class that contains implementation for converting types, interfaces, unions, enums and fields. It's the base implementation for [`flow`](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/flow/src/visitor.ts#L26) and [`typescript`](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/typescript/src/visitor.ts#L23) plugins. + +- `BaseResolversVisitor` is a class that contains implementation for generating a resolvers signature, it's the base implementation for [`flow-resolvers`](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/flow-resolvers/src/visitor.ts#L13) and [`typescript-resolvers`](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/typescript-resolvers/src/visitor.ts#L13) + +- `BaseDocumentsVisitor` is class that contains implementation for transforming GraphQL operations (query/mutation/subscription/fragment) with a resursive handler for selection-sets. It's the base implementation for [`flow-operations`](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/flow-operations/src/visitor.ts) and [`typescript-operations`](https://github.com/dotansimha/graphql-code-generator/blob/6f2999993315815e4625941b7a1a7d2fe035beb0/packages/plugins/typescript-operations/src/visitor.ts) + +- `ClientSideBaseVisitor` is a class that contains implementation for creating client-side code for consuming GraphQL operations, it's in use by `typescript-apollo-angular`, `typescript-react-apollo` and `typescript-apollo-stencil` plugins. + +You can use the above classes as base, and extend it as you wish, to create a custom plugin. diff --git a/docs/custom-codegen/validate-configuration.md b/docs/custom-codegen/validate-configuration.md index 35d62977a6b..bee355f3b4a 100644 --- a/docs/custom-codegen/validate-configuration.md +++ b/docs/custom-codegen/validate-configuration.md @@ -11,7 +11,7 @@ To add your plugin validation method, export a function called `validate` from y ```js module.exports = { - plugin: (schema, documents, config) => { + plugin: (schema, documents, config, info) => { const typesMap = schema.getTypeMap(); return Object.keys(typesMap).join('\n'); @@ -28,7 +28,7 @@ You can now check the schema, documents, configuration, output file and sibling ```js module.exports = { - plugin: (schema, documents, config) => { + plugin: (schema, documents, config, info) => { const typesMap = schema.getTypeMap(); return Object.keys(typesMap).join('\n'); diff --git a/docs/custom-codegen/write-your-plugin.md b/docs/custom-codegen/write-your-plugin.md index 3767c18d0e8..4be890a996a 100644 --- a/docs/custom-codegen/write-your-plugin.md +++ b/docs/custom-codegen/write-your-plugin.md @@ -39,7 +39,7 @@ So let's use a very basic method from `GraphQLSchema`, and return a list of all ```js module.exports = { - plugin: (schema, documents, config) => { + plugin: (schema, documents, config, info) => { const typesMap = schema.getTypeMap(); return Object.keys(typesMap).join('\n'); @@ -59,7 +59,7 @@ Let's print a list of all documents files, and the name of operations in this fi ```js module.exports = { - plugin: (schema, documents, config) => { + plugin: (schema, documents, config, info) => { return documents .map(doc => { const docsNames = doc.definitions.map(def => def.name.value); @@ -92,7 +92,11 @@ And then, you can use in your plugin: ```js module.exports = { - plugin: (schema, documents, config) => { + plugin: (schema, documents, config, info) => { + if (extname(info.outputFile) === '.graphql') { + return 'baz'; + } + if (config.myConfig === 'some-value') { return 'foo'; } else { diff --git a/docs/getting-started/codegen-config.md b/docs/getting-started/codegen-config.md index cfc6d6b17b3..89a46067606 100644 --- a/docs/getting-started/codegen-config.md +++ b/docs/getting-started/codegen-config.md @@ -18,8 +18,8 @@ overwrite: true generates: ./src/types.ts: plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ``` A more robust config file can be seen [here](https://github.com/dotansimha/graphql-code-generator/blob/70003040cfc3bf01a3d8eea9d4b2b5adec4ef77a/dev-test/codegen.yml). diff --git a/docs/getting-started/development-workflow.md b/docs/getting-started/development-workflow.md index ea1d9d2b409..093979fc46e 100644 --- a/docs/getting-started/development-workflow.md +++ b/docs/getting-started/development-workflow.md @@ -53,10 +53,9 @@ schema: 'server/src/**/*.graphql' documents: 'client/src/**/*.graphql' generates: client/src/models.ts: - - typescript-common - - typescript-client + - typescript + - typescript-operations server/src/models.ts: - - typescript-common - - typescript-server + - typescript - typescript-resolvers ``` diff --git a/docs/getting-started/documents-field.md b/docs/getting-started/documents-field.md index 727da2cd670..0acaf450403 100644 --- a/docs/getting-started/documents-field.md +++ b/docs/getting-started/documents-field.md @@ -21,8 +21,8 @@ documents: src/**/*.graphql generates: ./src/types.ts: plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ``` ### Output-file level @@ -35,8 +35,8 @@ generates: ./src/types1.ts: documents: src/**/*.graphql plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ``` ### Document Scanner diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index f240c7880bb..97b08f403f2 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -81,9 +81,9 @@ If you don't want to use the wizard, we've got you covered, just continue readin ## Setup -GraphQL Code Generator's behavior is bound into plugins, thus we will need to install few: +GraphQL Code Generator's behavior is bound into plugins, thus we will need to install one of them: - $ npm install -D graphql-codegen-typescript-common graphql-codegen-typescript-server + $ npm install -D graphql-codegen-typescript Although can be used directly, it's recommended to add the code generation task as an `npm` script in `package.json`. This way we won't have to install GraphQL Code Generator globally: @@ -103,8 +103,7 @@ overwrite: true generates: ./src/types.d.ts: plugins: - - typescript-common - - typescript-server + - typescript ``` By running the following command the GraphQL schema will be fetched from the route endpoint and the typescript definitions would be generated in the specified destination: @@ -130,7 +129,7 @@ async function doSomething() { documents: './src/**/*.graphql', generates: { [process.cwd() + '/models/']: { - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }, diff --git a/docs/getting-started/programmatic-usage.md b/docs/getting-started/programmatic-usage.md index 4e0b2f349a3..c311e52b76b 100644 --- a/docs/getting-started/programmatic-usage.md +++ b/docs/getting-started/programmatic-usage.md @@ -21,7 +21,7 @@ const config = { schema: ['schema.graphql'], generates: { 'output.ts': { - plugins: ['typescript-common'] + plugins: ['typescript'] } } }; @@ -50,7 +50,7 @@ If you are using a different environment that doesn't able to use `require` (suc ```ts const config = { pluginLoader: pluginName => { - if (pluginName === 'typescript-common') { + if (pluginName === 'typescript') { return { plugin: () => { // overwrite plugin here @@ -61,7 +61,7 @@ const config = { schema: ['schema.graphql'], generates: { 'output.ts': { - plugins: ['typescript-common'] + plugins: ['typescript'] } } }; diff --git a/docs/getting-started/schema-field.md b/docs/getting-started/schema-field.md index 5f1a07956ff..ce29da4df36 100644 --- a/docs/getting-started/schema-field.md +++ b/docs/getting-started/schema-field.md @@ -18,8 +18,7 @@ schema: http://localhost:3000/graphql generates: ./src/types.ts: plugins: - - typescript-common - - typescript-server + - typescript ``` ### Output-file level @@ -31,11 +30,11 @@ generates: ./src/types1.ts: schema: http://server1.com/graphql plugins: - - typescript-common + - typescript ./src/types2.ts: schema: http://server2.com/graphql plugins: - - typescript-common + - typescript ``` ### Multiple schemas and client-side schema @@ -49,8 +48,8 @@ generates: ./src/types.ts: schema: ./schema.graphql plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations ``` > It's also useful if you have a remote schema coming from a server, and a client-side schema that available in your client-side. @@ -111,21 +110,17 @@ schema: schema.js ``` ```javascript -import { makeExecutableSchema } from 'graphql-tools'; +const { buildSchema } = require('graphql'); -const schema = makeExecutableSchema({ - typeDefs: ` - type MyType { - foo: String! - } +module.exports = buildSchema(/* GraphQL */ ` + type MyType { + foo: String! + } - type Query { - myType: MyType! - } - ` -}); - -export default schema; + type Query { + myType: MyType! + } +`); ``` > You can also import from TypeScript files, but don't forget to specify [require field](./require-field). @@ -153,10 +148,10 @@ schema: Your custom loader should export a default function, and return `GraphQLSchema` object. For example: ```js -const { makeExecutableSchema } = require('graphql-tools'); +const { buildSchema } = require('graphql'); const { readFileSync } = require('fs'); module.exports = function(schemaString, config) { - return makeExecutableSchema({ typeDefs: readFileSync(schemaString, { encoding: 'utf-8' }) }); + return buildSchema(readFileSync(schemaString, { encoding: 'utf-8' })); }; ``` diff --git a/docs/integrations/create-react-app.md b/docs/integrations/create-react-app.md index fc59e0315c5..46b408b5d9b 100644 --- a/docs/integrations/create-react-app.md +++ b/docs/integrations/create-react-app.md @@ -5,19 +5,13 @@ title: Create-React-App Since v2 of [Create-React-App](https://github.com/facebook/create-react-app), you can use TypeScript without the need to eject from the basic scripts packages. -It uses `[babel-preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript)` for transpiling TypeScript files, which does not support `namespace` keyword. - -Some of the built-in plugins (such as `typescript-client`, `typescript-apollo-angular` and `typescript-react-apollo`) are using `namespace`. In order to use those templates with Create-React-App applications (or, any other app that using `babel-preset-typescript` instead of `tsc`), you can configure it with `noNamepsaces` field, to avoid generating output with `namespace`s. - ```yml schema: http://my-server/graphql documents: 'src/**/*.graphql' generates: components.tsx: - config: - noNamespaces: true plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations - typescript-react-apollo ``` diff --git a/docs/migration/from-0-13.md b/docs/migration/from-0-13.md index 16cdca932e0..83af515515b 100644 --- a/docs/migration/from-0-13.md +++ b/docs/migration/from-0-13.md @@ -36,6 +36,6 @@ Next, update your NPM scripts to run `gql-gen` only, without any cli-flags: Now, replace your deprecated `templates` packages with the new `plugins` packages. -For example, if you were using `graphql-codegen-typescript-template`, you should replace it with: `graphql-codegen-typescript-client`, `graphql-codegen-typescript-common` and `graphql-codegen-typescript-server`. +For example, if you were using `graphql-codegen-typescript-template`, you should replace it with: `graphql-codegen-typescript`, and `graphql-codegen-typescript-operations`. Note sure which new packages you need to use now? [You can take a look here](https://github.com/dotansimha/graphql-code-generator/tree/master/packages/old-templates). Under each directory you'll find a `package.json` pointing to the new packages names. diff --git a/docs/plugins/add.md b/docs/plugins/add.md index 693cfd11a32..2ee7fa93c2a 100644 --- a/docs/plugins/add.md +++ b/docs/plugins/add.md @@ -21,5 +21,5 @@ generates: path/to/file.ts: plugins: - add: '// THIS IS A GENERATED FILE' - - typescript-common + - typescript ``` diff --git a/docs/plugins/flow-documents.md b/docs/plugins/flow-operations.md similarity index 85% rename from docs/plugins/flow-documents.md rename to docs/plugins/flow-operations.md index ead6b329fa1..85fe8ca6c93 100644 --- a/docs/plugins/flow-documents.md +++ b/docs/plugins/flow-operations.md @@ -1,9 +1,9 @@ --- -id: flow-documents -title: Flow Documents +id: flow-operations +title: Flow Operations --- -The `graphql-codegen-flow-documents` plugin generates Flow types based on your `GraphQLSchema` and your GraphQL documents. +The `graphql-codegen-flow-operations` plugin generates Flow types based on your `GraphQLSchema` and your GraphQL operations and fragments. It generates types for your GraphQL documents: Query, Mutation, Subscription and Fragment. @@ -13,7 +13,7 @@ This plugin requires you to use `graphql-codegen-flow` as well, because it depen Install using `npm` (or `yarn`): - $ npm install graphql-codegen-flow-documents + $ npm install graphql-codegen-flow-operations ### Examples @@ -46,7 +46,6 @@ generates: config: scalars: Date: Date -] ``` > You can also override built-in scalars, such as `String`. diff --git a/docs/plugins/index.md b/docs/plugins/index.md index b23a0b1510c..b7fbf25c92c 100644 --- a/docs/plugins/index.md +++ b/docs/plugins/index.md @@ -9,24 +9,23 @@ The general purpose of GraphQL Code Generator is to parse GraphQL syntax, transf Below is a table that lists all available plugins which can be installed via NPM, along with a short description. If you're looking for anything specific, we might already have the solution: -| Format | Purpose | Package Name & Docs | -| ---------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| `typescript-common` | Generate enums, scalars and input types - those are usually relevant for both client side and server side code | [`graphql-codegen-typescript-common`](./typescript-common.md) | -| `typescript-client` | Generate client specific TypeScript types (query, mutation, subscription, fragment) | [`graphql-codegen-typescript-client`](./typescript-client.md) | -| `typescript-server` | Generate server specific TypeScript types (types, directives, interfaces, unions) | [`graphql-codegen-typescript-server`](./typescript-server.md) | -| `typescript-resolvers` | Generate TypeScript signature for server-side resolvers | [`graphql-codegen-typescript-resolvers`](./typescript-resolvers.md) | -| `typescript-apollo-angular` | Generate TypeScript types, and Apollo-Angular Services | [`graphql-codegen-typescript-apollo-angular`](./typescript-apollo-angular.md) | -| `typescript-react-apollo` | Generate TypeScript types, and React-Apollo Components | [`graphql-codegen-typescript-react-apollo`](./typescript-react-apollo.md) | -| `typescript-mongodb` | Generate Generate server-side TypeScript types, with MongoDB models | [`graphql-codegen-typescript-mongodb`](./typescript-mongodb.md) | -| `typescript-graphql-files-modules` | Generate `declare module` for `.graphql` files | [`graphql-codegen-typescript-graphql-files-modules`](./typescript-graphql-files-modules.md) | -| `add` | Add any string that you wish to the output file | [`graphql-codegen-add`](./add.md) | -| `schema-ast` | Prints the merged schemas as AST | [`graphql-codegen-schema-ast`](./schema-ast.md) | -| `fragment-matcher` | Generates an introspection result with only Unions and Interfaces | [`graphql-codegen-fragment-matcher`](./fragment-matcher.md) | -| `time` | Add the generation time to the output file | [`graphql-codegen-time`](./time.md) | -| `flow` | Generate types for Flow type based on your GraphQL schema | [`graphql-codegen-flow`](./flow.md) | -| `flow-resolvers` | Generate resolvers signature for Flow | [`graphql-codegen-flow-resolvers`](./flow-resolvers.md) | -| `flow-documents` | Generate types for Flow type based on your GraphQL documents | [`graphql-codegen-flow-documents`](./flow-documents.md) | -| `reason-client` | Generate ReasonML types based on your GraphQL schema for use in a client application | [`graphql-codegen-reason-client`](./reason-client.md) | +| Format | Purpose | Package Name & Docs | +| ---------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `typescript` | Generate types for TypeScript - those are usually relevant for both client side and server side code | [`graphql-codegen-typescript`](./typescript.md) | +| `typescript-operations` | Generate client specific TypeScript types (query, mutation, subscription, fragment) | [`graphql-codegen-typescript-operations`](./typescript-operations.md) | +| `typescript-resolvers` | Generate TypeScript signature for server-side resolvers | [`graphql-codegen-typescript-resolvers`](./typescript-resolvers.md) | +| `typescript-apollo-angular` | Generate TypeScript types, and Apollo-Angular Services | [`graphql-codegen-typescript-apollo-angular`](./typescript-apollo-angular.md) | +| `typescript-react-apollo` | Generate TypeScript types, and React-Apollo Components | [`graphql-codegen-typescript-react-apollo`](./typescript-react-apollo.md) | +| `typescript-mongodb` | Generate Generate server-side TypeScript types, with MongoDB models | [`graphql-codegen-typescript-mongodb`](./typescript-mongodb.md) | +| `typescript-graphql-files-modules` | Generate `declare module` for `.graphql` files | [`graphql-codegen-typescript-graphql-files-modules`](./typescript-graphql-files-modules.md) | +| `add` | Add any string that you wish to the output file | [`graphql-codegen-add`](./add.md) | +| `schema-ast` | Prints the merged schemas as AST | [`graphql-codegen-schema-ast`](./schema-ast.md) | +| `fragment-matcher` | Generates an introspection result with only Unions and Interfaces | [`graphql-codegen-fragment-matcher`](./fragment-matcher.md) | +| `time` | Add the generation time to the output file | [`graphql-codegen-time`](./time.md) | +| `flow` | Generate types for Flow type based on your GraphQL schema | [`graphql-codegen-flow`](./flow.md) | +| `flow-resolvers` | Generate resolvers signature for Flow | [`graphql-codegen-flow-resolvers`](./flow-resolvers.md) | +| `flow-operations` | Generate types for Flow type based on your GraphQL operations | [`graphql-codegen-flow-operations`](./flow-operations.md) | +| `reason-client` | Generate ReasonML types based on your GraphQL schema for use in a client application | [`graphql-codegen-reason-client`](./reason-client.md) | In addition, you can build your own code generating plugins based on your specific needs. For more information, check [this doc page](../custom-codegen/index). diff --git a/docs/plugins/time.md b/docs/plugins/time.md index f9095ab9e21..efcd72a4ad7 100644 --- a/docs/plugins/time.md +++ b/docs/plugins/time.md @@ -19,5 +19,5 @@ generates: path/to/file.ts: plugins: - time - - typescript-common + - typescript ``` diff --git a/docs/plugins/typescript-apollo-angular.md b/docs/plugins/typescript-apollo-angular.md index e2bb7b78525..b964e201cf3 100644 --- a/docs/plugins/typescript-apollo-angular.md +++ b/docs/plugins/typescript-apollo-angular.md @@ -55,6 +55,10 @@ export class FeedComponent { The output of this template can be controlled using a specified config file which consists of the fields below. Each config field is followed by its matching environment variable, which can be used as an alternative method to control the template's behavior: +#### `gqlImport` (default value: `import gql from 'graphql-tag'`) + +Customize from which module will `gql` be imported from. This is useful if you want to use modules other than `graphql-tag`, e.g. `graphql.macro`. You can also control the imported GraphQL-parse function identifier e.g. `gatsby#graphql`, which will result in `import { graphql as gql } from 'gatsby'`. + #### `noGraphqlTag` (default value: `false`) This will cause the codegen to output parsed documents and not use a literal tag of the `graphql-tag` package. @@ -69,3 +73,33 @@ generates: - typescript-apollo-angular # ... ``` + +#### `@NgModule` directive + +All generated services are defined with `@Injectable({ providedIn: 'root' })` and in most cases you don't need to overwrite it, because providing a service to the root injector is highly recommended. To customize that behavior you can use `@NgModule` directive, anywhere in an operation, to let the codegen know which injector should it use to create a service. + +> You can't use multiple `@NgModule` directives in the same operation + +```graphql +query feed { + feed @NgModule(module: "./feed/feed.module#FeedModule") { + id + title + } +} +``` + +#### `@namedClient` directive + +Sometimes you end up with multiple Apollo clients, which means part of operations can't use the defauls. In order to customize that behavior you simply attach the `@namedClient` directive and the `typescript-apollo-angular` plugin takes care of the rest. + +> You can't use multiple `@namedClient` directives in the same operation + +```graphql +query feed { + feed @namedClient(name: "custom") { + id + title + } +} +``` diff --git a/docs/plugins/typescript-client.md b/docs/plugins/typescript-client.md deleted file mode 100644 index 555212cf748..00000000000 --- a/docs/plugins/typescript-client.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: typescript-client -title: Typescript Client ---- - -A plugin that should be loaded if generating typescript code that should be relevant for client. Must be loaded with [`typescript-common`](./typescript-common). - -### Installation - -Install using `npm` (or `yarn`): - - $ npm install graphql-codegen-typescript-client - -### Examples - -- [Star Wars Schema](https://github.com/dotansimha/graphql-code-generator/blob/master/dev-test/star-wars/types.d.ts#L27) - -## Configuration - -#### `noNamespaces` (default value: `false`) - -This will cause the codegen not to use `namespace` in typings. - -This configuration field is useful if you are using [babel-typescript](https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/) or [Create-React-App](https://github.com/facebook/create-react-app), because Babel 7 TypeScript preset does not support `namespace`s. diff --git a/docs/plugins/typescript-mongodb.md b/docs/plugins/typescript-mongodb.md index eebe61518f9..52cd9054236 100644 --- a/docs/plugins/typescript-mongodb.md +++ b/docs/plugins/typescript-mongodb.md @@ -69,7 +69,7 @@ At this point, you can add the directives to your GraphQL definitions, and gener ## Directives -#### `@entity(embedded: Boolean, additionalFields: [AdditionalEntityFields])` (on `OBJECT`) +#### `@entity(additionalFields: [AdditionalEntityFields])` (on `OBJECT`) Use this directive to specify which GraphQL type should have generated MongoDB models. @@ -85,13 +85,11 @@ type User @entity(additionalFields: [ } ``` -#### `@column(name: string, overrideType: String, overrideIsArray: Boolean)` (on `FIELD_DEFINITION`) +#### `@column(overrideType: String)` (on `FIELD_DEFINITION`) Use this directive to declare a specific GraphQL field as part of your generated MongoDB type. - `overrideType: String` - use this to override the type of the field; for example, if you store dates as `Date` but expose them as `String`. -- `overrideIsArray: Boolean` - if true, override generated result and force generate it as an array type. -- `name: String` - a projection field name that would appear in the DB. This can be either a consistent string or a path (`a.b.c`). This is a shortcut for the `@map` directive. > âš  If target property is an embedded entity, you should use `@embedded` instead. diff --git a/docs/plugins/typescript-operations.md b/docs/plugins/typescript-operations.md new file mode 100644 index 00000000000..62242ea203c --- /dev/null +++ b/docs/plugins/typescript-operations.md @@ -0,0 +1,20 @@ +--- +id: typescript-operations +title: Typescript Operations +--- + +The `graphql-codegen-typescript-operations` plugin generates TypeScript types based on your `GraphQLSchema` and your GraphQL operations and fragments. + +It generates types for your GraphQL documents: Query, Mutation, Subscription and Fragment. + +This plugin requires you to use `graphql-codegen-typescript` as well, because it depends on it's types. + +### Installation + +Install using `npm` (or `yarn`): + + $ npm install graphql-codegen-typescript-operations + +### Examples + +- [Star Wars Schema](https://github.com/dotansimha/graphql-code-generator/blob/master/dev-test/star-wars/types.d.ts#L27) diff --git a/docs/plugins/typescript-react-apollo.md b/docs/plugins/typescript-react-apollo.md index 0dc38a69564..3f98ebad700 100644 --- a/docs/plugins/typescript-react-apollo.md +++ b/docs/plugins/typescript-react-apollo.md @@ -3,7 +3,7 @@ id: typescript-react-apollo title: TypeScript React Apollo --- -This plugin generates React Apollo components and HOC with TypeScript typings. It extends the basic TypeScript template [`graphql-codegen-typescript-common`](typescript-typings) and thus shares a similar configuration. +This plugin generates React Apollo components and HOC with TypeScript typings. It extends the basic TypeScript template [`graphql-codegen-typescript`](typescript-typings) and thus shares a similar configuration. ## Installation @@ -51,6 +51,21 @@ Or if you prefer: Customize from which module will `gql` be imported from. This is useful if you want to use modules other than `graphql-tag`, e.g. `graphql.macro`. You can also control the imported GraphQL-parse function identifier e.g. `gatsby#graphql`, which will result in `import { graphql as gql } from 'gatsby'`. +#### `noGraphqlTag` (default value: `false`) + +This will cause the codegen to output parsed documents and not use a literal tag of the `graphql-tag` package. + +```yaml +# ... +generates: + path/to/output: + config: + noGraphqlTag: true + plugins: + - typescript-react-apollo + # ... +``` + #### `noHOC` (default value: `false`) This will disable the higher order components generation.sable the higher order components generation by setting this option to `false`. @@ -65,12 +80,6 @@ This will cause the codegen to add React **Hooks** implementations, to be used i You can use the generated hook in your Functional Component like this: -```tsx - const { data, loading, error } = Test.use(...); -``` - -Or if you are using `noNamespaces` option: - ```tsx const { data, loading, error } = useTest(...); ``` diff --git a/docs/plugins/typescript-resolvers.md b/docs/plugins/typescript-resolvers.md index e55a6b611bd..57777555fd9 100644 --- a/docs/plugins/typescript-resolvers.md +++ b/docs/plugins/typescript-resolvers.md @@ -25,7 +25,7 @@ overwrite: true generates: ./src/resolvers-types.ts: plugins: - - typescript-common + - typescript - typescript-resolvers ``` @@ -34,7 +34,7 @@ Import the types from the generated file and use in the resolver: ```typescript import { QueryResolvers } from './resolvers-types'; -export const resolvers: QueryResolvers.Resolvers = { +export const resolvers: QueryResolvers = { myQuery: (root, args, context) => {} }; ``` @@ -91,29 +91,16 @@ type User { Given the schema above, the output should be the following: ```typescript -export namespace QueryResolvers { - export interface Resolvers { - allUsers?: AllUsersResolver<(User | null)[], TypeParent, Context>; - userById?: UserByIdResolver; - } - - export type AllUsersResolver = Resolver; - export type UserByIdResolver = Resolver; - export interface UserByIdArgs { - id: number; - } +export interface QueryResolvers { + allUsers?: Resolver>, ParentType, Context>; + userById?: Resolver, ParentType, Context, QueryUserByIdArgs>; + answer?: Resolver, ParentType, Context>; } -export namespace UserResolvers { - export interface Resolvers { - id?: IdResolver; - name?: NameResolver; - email?: EmailResolver; - } - - export type IdResolver = Resolver; - export type NameResolver = Resolver; - export type EmailResolver = Resolver; +export interface UserResolvers { + id?: Resolver; + name?: Resolver; + email?: Resolver; } ``` @@ -228,31 +215,23 @@ generates: - typescript-resolvers ``` +```typescript +export interface MyContext { + authToken: string; +} +``` + The config above will make every resolver to have `MyContext` as a context type. ```typescript import { QueryResolvers } from './resolvers-types'; -export const resolvers: QueryResolvers.Resolvers = { - myQuery: (root, args, context) => {} +export const resolvers: QueryResolvers = { + myQuery: (root, args, context) => { + const { authToken } = context; + // ... + } }; ``` Field resolvers will be modfied as well. - -## Field Resolver Name Prefix - -When using `noNamespace` option, you can add a prefix to field resolver name, in order to avoid conflicts in the generated typescript declarations. - -```yaml -# ... -generates: - path/to/file.ts: - config: - noNamespace: true - fieldResolverNamePrefix: Field - plugins: - - typescript-resolvers -``` - -And it will generate Field Resolver like `PostFieldIdResolver` instead of `PostIdResolver` diff --git a/docs/plugins/typescript-server.md b/docs/plugins/typescript-server.md deleted file mode 100644 index 1a2f1f21249..00000000000 --- a/docs/plugins/typescript-server.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -id: typescript-server -title: TypeScript Server ---- - -A plugin that should be loaded if generating typescript code that should be relevant for server. Must be loaded with [`typescript-common`](./typescript-common). - -### Installation - -Install using `npm` (or `yarn`): - - $ npm install graphql-codegen-typescript-server - -### Configuration - -#### `schemaNamespace` - -Specify this configuration field to wrap your entire types with a specific TypeScript `namespace`. diff --git a/docs/plugins/typescript-common.md b/docs/plugins/typescript.md similarity index 85% rename from docs/plugins/typescript-common.md rename to docs/plugins/typescript.md index aaf00ce9ffd..1b7e1033ed4 100644 --- a/docs/plugins/typescript-common.md +++ b/docs/plugins/typescript.md @@ -1,17 +1,17 @@ --- -id: typescript-common -title: TypeScript Common +id: typescript +title: TypeScript --- -This is the most basic TypeScript plugin and it can generate typings which can be used both in client and server, given a GraphQL schema. +This is the most basic TypeScript plugin and it can generate typings based on `GraphQLSchema`, which can be used by any other typescript related plugin. -It generated types for enums, scalars and input types - because those are relevant for both client-side and server-side. +It generates types for your entire schema: types, input types, enums, interfaces, scalars and unions. ## Installation Install using `npm` (or `yarn`): - $ npm install graphql-codegen-typescript-common + $ npm install graphql-codegen-typescript ### Examples @@ -34,26 +34,26 @@ You can either specify a string pointing to a method in a module (or a file) in generates: path/to/file.ts: plugins: - - typescript-common + - typescript config: namingConvention: change-case#lowerCase ``` -Or, an object with a method per output type (the allowed values are `default`, `enumValues` and `typeNames`): +Or, an object with a method per output type (the allowed values are `enumValues` and `typeNames`): ```yaml # ... generates: path/to/file.ts: plugins: - - typescript-common + - typescript config: namingConvention: - default: change-case#pascalCase + typeNames: change-case#pascalCase enumValues: change-case#upperCase ``` -> The example above will use `pascalCase` as default, and `upperCase` for the enum values. +> The example above will use `pascalCase` for most cases, and `upperCase` for the enum values. #### `scalars` @@ -64,7 +64,7 @@ Will map scalars to the predefined types. generates: path/to/file.ts: plugins: - - typescript-common + - typescript config: scalars: Date: Date @@ -91,7 +91,7 @@ Use this feature to set custom values for your GraphQL enums, reuse an existing generates: path/to/file.ts: plugins: - - typescript-common + - typescript config: enums: MyEnum: @@ -105,7 +105,7 @@ generates: generates: path/to/file.ts: plugins: - - typescript-common + - typescript config: enums: MyEnum: ./path/to/enum#MyEnum @@ -124,7 +124,7 @@ Note: generates: path/to/file.ts: plugins: - - typescript-common + - typescript config: enums: MyEnum: # empty @@ -139,7 +139,7 @@ Note: This will cause the codegen to output `readonly` properties and `ReadonlyArray`. -#### `interfacePrefix` (default value: '') +#### `typesPrefix` (default value: '') This will cause the codegen to prefix graphql type interfaces with the given value (if `I` is defined as prefix, type `Foo` will be generated as an interface named `IFoo`). Use this flag if you would like to run the codegen on multiple schemas. Note that even though we run this command on multiple schemas, the output types will be merged and not separated. For more information regards declaration merging, see [reference](https://www.typescriptlang.org/docs/handbook/declaration-merging.html). diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000000..6104c456eb7 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + rootDir: process.cwd(), + globals: { + 'ts-jest': { + diagnostics: false + } + } +}; diff --git a/package.json b/package.json index a823cc4edf9..cade1a8163d 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,7 @@ "packages/*", "packages/utils/*", "packages/plugins/*", - "website/live-demo", - "packages/old-templates/*" + "website/live-demo" ], "dependencies": { "lerna": "2.11.0" @@ -48,11 +47,7 @@ "ts-jest": "24.0.0", "graphql-tools": "4.0.4", "apollo-link": "1.2.11", - "awesome-typescript-loader": "5.2.1", - "raw-loader": "1.0.0", - "webpack": "4.29.6", - "webpack-cli": "3.2.3", - "webpack-node-externals": "1.7.2" + "microbundle": "0.11.0" }, "lint-staged": { "*.{ts,tsx}": [ diff --git a/packages/.DS_Store b/packages/.DS_Store new file mode 100644 index 00000000000..d114e53e948 Binary files /dev/null and b/packages/.DS_Store differ diff --git a/packages/graphql-codegen-cli/declarations.d.ts b/packages/graphql-codegen-cli/declarations.d.ts deleted file mode 100644 index 41b3582d8e5..00000000000 --- a/packages/graphql-codegen-cli/declarations.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare function isValidPath(path: string): boolean; - -declare module 'is-valid-path' { - export = isValidPath; -} - -declare module 'listr-update-renderer'; -declare module 'indent-string'; -declare module 'json-to-pretty-yaml'; diff --git a/packages/graphql-codegen-cli/jest.config.js b/packages/graphql-codegen-cli/jest.config.js deleted file mode 100644 index eef6b07c6be..00000000000 --- a/packages/graphql-codegen-cli/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node' -}; diff --git a/packages/graphql-codegen-cli/package.json b/packages/graphql-codegen-cli/package.json index ef197c9d81e..dc0599a53af 100644 --- a/packages/graphql-codegen-cli/package.json +++ b/packages/graphql-codegen-cli/package.json @@ -3,7 +3,7 @@ "version": "0.18.0", "license": "MIT", "bin": { - "gql-gen": "dist/cli.js" + "gql-gen": "dist/commonjs/cli.js" }, "repository": { "type": "git", @@ -12,12 +12,9 @@ "scripts": { "clean": "rimraf ./dist", "lint": "tslint src/**/*.ts", - "prebuild": "yarn clean && yarn lint", - "build": "tsc", - "prestart": "yarn build", - "start": "cd dist && node index.js", - "debug": "cd dist && node --inspect --debug-brk index.js", - "test": "jest --no-cache --verbose --runInBand" + "prebuild": "yarn clean", + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../jest.config.js" }, "keywords": [ "gql", @@ -59,6 +56,7 @@ "detect-indent": "5.0.0", "glob": "7.1.3", "graphql-codegen-core": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0", "graphql-config": "2.2.1", "graphql-import": "0.7.1", "graphql-tag-pluck": "0.7.0", @@ -77,6 +75,7 @@ "mkdirp": "0.5.1", "prettier": "1.16.4", "request": "2.88.0", + "tslib": "1.9.3", "valid-url": "1.0.9" }, "devDependencies": { @@ -86,16 +85,13 @@ "@types/js-yaml": "3.12.0", "@types/listr": "0.13.0", "@types/log-symbols": "2.0.0", - "graphql-codegen-add": "0.18.0", - "graphql-codegen-time": "0.18.0", - "graphql-codegen-typescript-client": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0", - "graphql-codegen-typescript-server": "0.18.0", + "bdd-stdin": "0.2.0", "ts-jest": "24.0.0" }, - "main": "./dist/index.js", - "typings": "./dist/index.d.ts", + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "./dist/index.d.ts" + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/graphql-codegen-cli/src/codegen.ts b/packages/graphql-codegen-cli/src/codegen.ts index 21b883184ff..526ce55b709 100644 --- a/packages/graphql-codegen-cli/src/codegen.ts +++ b/packages/graphql-codegen-cli/src/codegen.ts @@ -1,22 +1,15 @@ -import { FileOutput, DocumentFile, Types, debugLog } from 'graphql-codegen-core'; +import { FileOutput, DocumentFile, Types, debugLog, CodegenPlugin } from 'graphql-codegen-plugin-helpers'; +import { codegen, mergeSchemas } from 'graphql-codegen-core'; import * as Listr from 'listr'; import { normalizeOutputParam, normalizeInstanceOrArray, normalizeConfig } from './helpers'; import { prettify } from './utils/prettier'; import { Renderer } from './utils/listr-renderer'; import { DetailedError } from './errors'; import { loadSchema, loadDocuments } from './load'; -import { mergeSchemas } from './merge-schemas'; -import { GraphQLError, DocumentNode, visit } from 'graphql'; -import { executePlugin, getPluginByName } from './execute-plugin'; +import { GraphQLError, DocumentNode } from 'graphql'; +import { getPluginByName } from './plugins'; -export interface GenerateOutputOptions { - filename: string; - plugins: Types.ConfiguredPlugin[]; - schema: DocumentNode; - documents: DocumentFile[]; - pluginLoader: Types.PluginLoaderFn; - inheritedConfig: { [key: string]: any }; -} +export const defaultPluginLoader = (mod: string) => import(mod); export async function executeCodegen(config: Types.Config): Promise { function wrapTask(task: () => void | Promise, source?: string) { @@ -66,10 +59,12 @@ export async function executeCodegen(config: Types.Config): Promise(config.require); - requireExtensions.forEach(mod => require(mod)); + for (const mod of requireExtensions) { + await import(mod); + } /* Root templates-config */ rootConfig = config.config || {}; @@ -200,18 +195,34 @@ export async function executeCodegen(config: Types.Config): Promise { debugLog(`[CLI] Generating output`); const normalizedPluginsArray = normalizeConfig(outputConfig.plugins); - const output = await generateOutput({ + const pluginLoader = config.pluginLoader || defaultPluginLoader; + const pluginPackages = await Promise.all( + normalizedPluginsArray.map(plugin => getPluginByName(Object.keys(plugin)[0], pluginLoader)) + ); + const pluginMap: { [name: string]: CodegenPlugin } = {}; + + pluginPackages.forEach((pluginPackage, i) => { + const plugin = normalizedPluginsArray[i]; + const name = Object.keys(plugin)[0]; + + pluginMap[name] = pluginPackage; + }); + + const output = await codegen({ filename, plugins: normalizedPluginsArray, schema: outputSchema, documents: outputDocuments, - inheritedConfig: { + config: { ...rootConfig, ...outputFileTemplateConfig }, - pluginLoader: config.pluginLoader || require + pluginMap + }); + result.push({ + filename, + content: await prettify(filename, output) }); - result.push(output); }, filename) } ], @@ -236,105 +247,3 @@ export async function executeCodegen(config: Types.Config): Promise { - visit(file.content, { - OperationDefinition(node) { - if (typeof node.name !== 'undefined') { - if (!operationMap[node.name.value]) { - operationMap[node.name.value] = []; - } - - operationMap[node.name.value].push(file.filePath); - } - } - }); - }); - - const names = Object.keys(operationMap); - - if (names.length) { - const duplicated = names.filter(name => operationMap[name].length > 1); - - if (!duplicated.length) { - return; - } - - const list = duplicated - .map(name => - ` - * ${name} found in: - ${operationMap[name] - .map(filepath => { - return ` - - ${filepath} - `.trimRight(); - }) - .join('')} - `.trimRight() - ) - .join(''); - throw new DetailedError( - `Not all operations have an unique name: ${duplicated.join(', ')}`, - ` - Not all operations have an unique name - - ${list} - ` - ); - } -} - -export async function generateOutput(options: GenerateOutputOptions): Promise { - let output = ''; - - validateDocuments(options.schema, options.documents); - - const pluginsPackages = await Promise.all( - options.plugins.map(plugin => getPluginByName(Object.keys(plugin)[0], options.pluginLoader)) - ); - - // merged schema with parts added by plugins - const schema = pluginsPackages.reduce((schema, plugin) => { - return !plugin.addToSchema ? schema : mergeSchemas([schema, plugin.addToSchema]); - }, options.schema); - - for (let i = 0; i < options.plugins.length; i++) { - const plugin = options.plugins[i]; - const pluginPackage = pluginsPackages[i]; - const name = Object.keys(plugin)[0]; - const pluginConfig = plugin[name]; - - debugLog(`[CLI] Running plugin: ${name}`); - - const result = await executePlugin( - { - name, - config: - typeof pluginConfig !== 'object' - ? pluginConfig - : { - ...options.inheritedConfig, - ...(pluginConfig as object) - }, - schema, - documents: options.documents, - outputFilename: options.filename, - allPlugins: options.plugins - }, - pluginPackage - ); - - debugLog(`[CLI] Completed executing plugin: ${name}`); - - output += result; - } - - return { filename: options.filename, content: await prettify(options.filename, output) }; -} diff --git a/packages/graphql-codegen-cli/src/config.ts b/packages/graphql-codegen-cli/src/config.ts index b6365ed3b8c..bb3d2155339 100644 --- a/packages/graphql-codegen-cli/src/config.ts +++ b/packages/graphql-codegen-cli/src/config.ts @@ -1,7 +1,6 @@ -import { initCLI, createConfigFromOldCli, CLIOptions } from './old-cli-config'; import { existsSync, readFileSync } from 'fs'; import { join, resolve } from 'path'; -import { Types } from 'graphql-codegen-core'; +import { Types } from 'graphql-codegen-plugin-helpers'; import { DetailedError } from './errors'; import { parseConfigFile } from './yml'; import { Command } from 'commander'; @@ -9,7 +8,8 @@ import { Command } from 'commander'; export type YamlCliFlags = { config: string; watch: boolean; -} & Partial; + overwrite: boolean; +}; function getCustomConfigPath(cliFlags: YamlCliFlags): string | null | never { const configFile = cliFlags.config; @@ -67,43 +67,33 @@ export function createConfig(argv = process.argv): Types.Config | never { .option('-o, --overwrite', 'Overwrites existing files') .parse(argv) as any) as Command & YamlCliFlags; - const isUsingOldApi = - cliFlags.rawArgs.includes('--template') || - cliFlags.rawArgs.includes('-t') || - cliFlags.rawArgs.includes('--schema') || - cliFlags.rawArgs.includes('--s'); + const customConfigPath = getCustomConfigPath(cliFlags); + const locations: string[] = [join(process.cwd(), './codegen.yml'), join(process.cwd(), './codegen.json')]; - if (isUsingOldApi) { - return createConfigFromOldCli(initCLI(argv)); - } else { - const customConfigPath = getCustomConfigPath(cliFlags); - const locations: string[] = [join(process.cwd(), './codegen.yml'), join(process.cwd(), './codegen.json')]; - - if (customConfigPath) { - locations.unshift(customConfigPath); - } + if (customConfigPath) { + locations.unshift(customConfigPath); + } - const filepath = locations.find(existsSync); + const filepath = locations.find(existsSync); - if (!filepath) { - throw new DetailedError( - `Unable to find Codegen config file!`, - ` + if (!filepath) { + throw new DetailedError( + `Unable to find Codegen config file!`, + ` Please make sure that you have a configuration file under the current directory! ` - ); - } - - const parsedConfigFile = loadAndParseConfig(filepath); + ); + } - if (cliFlags.watch === true) { - parsedConfigFile.watch = cliFlags.watch; - } + const parsedConfigFile = loadAndParseConfig(filepath); - if (cliFlags.overwrite === true) { - parsedConfigFile.overwrite = cliFlags.overwrite; - } + if (cliFlags.watch === true) { + parsedConfigFile.watch = cliFlags.watch; + } - return parsedConfigFile; + if (cliFlags.overwrite === true) { + parsedConfigFile.overwrite = cliFlags.overwrite; } + + return parsedConfigFile; } diff --git a/packages/graphql-codegen-cli/src/declarations.d.ts b/packages/graphql-codegen-cli/src/declarations.d.ts new file mode 100644 index 00000000000..8ac4c500354 --- /dev/null +++ b/packages/graphql-codegen-cli/src/declarations.d.ts @@ -0,0 +1,5 @@ +declare module 'is-valid-path'; +declare module 'listr-update-renderer'; +declare module 'indent-string'; +declare module 'json-to-pretty-yaml'; +declare module 'bdd-stdin'; diff --git a/packages/graphql-codegen-cli/src/execute-plugin.ts b/packages/graphql-codegen-cli/src/execute-plugin.ts deleted file mode 100644 index 35057ee31c0..00000000000 --- a/packages/graphql-codegen-cli/src/execute-plugin.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Types, DocumentFile, CodegenPlugin } from 'graphql-codegen-core'; -import { DocumentNode, GraphQLSchema } from 'graphql'; -import { resolve } from 'path'; -import { DetailedError } from './errors'; -import { buildSchema } from './merge-schemas'; -import { validateGraphQlDocuments, checkValidationErrors } from 'graphql-toolkit'; - -export interface ExecutePluginOptions { - name: string; - config: Types.PluginConfig; - schema: DocumentNode; - documents: DocumentFile[]; - outputFilename: string; - allPlugins: Types.ConfiguredPlugin[]; -} - -export async function getPluginByName(name: string, pluginLoader: Types.PluginLoaderFn): Promise { - const possibleNames = [ - `graphql-codegen-${name}`, - `graphql-codegen-${name}-template`, - `codegen-${name}`, - `codegen-${name}-template`, - name - ]; - const possibleModules = possibleNames.concat(resolve(process.cwd(), name)); - - for (const moduleName of possibleModules) { - try { - return pluginLoader(moduleName) as CodegenPlugin; - } catch (err) { - if (err.message.indexOf(`Cannot find module '${moduleName}'`) === -1) { - throw new DetailedError( - `Unable to load template plugin matching ${name}`, - ` - Unable to load template plugin matching '${name}'. - Reason: - ${err.message} - ` - ); - } - } - } - - const possibleNamesMsg = possibleNames - .map(name => - ` - - ${name} - `.trimRight() - ) - .join(''); - - throw new DetailedError( - `Unable to find template plugin matching ${name}`, - ` - Unable to find template plugin matching '${name}' - Install one of the following packages: - - ${possibleNamesMsg} - ` - ); -} - -export async function executePlugin(options: ExecutePluginOptions, pluginPackage: CodegenPlugin): Promise { - if (!pluginPackage || !pluginPackage.plugin || typeof pluginPackage.plugin !== 'function') { - throw new DetailedError( - `Invalid Custom Plugin "${options.name}"`, - ` - Plugin ${options.name} does not export a valid JS object with "plugin" function. - - Make sure your custom plugin is written in the following form: - - module.exports = { - plugin: (schema, documents, config) => { - return 'my-custom-plugin-content'; - }, - }; - ` - ); - } - - const outputSchema: GraphQLSchema = buildSchema(options.schema); - - if (outputSchema && options.documents.length > 0) { - const errors = validateGraphQlDocuments(outputSchema, options.documents); - checkValidationErrors(errors); - } - - if (pluginPackage.validate && typeof pluginPackage.validate === 'function') { - try { - await pluginPackage.validate( - outputSchema, - options.documents, - options.config, - options.outputFilename, - options.allPlugins - ); - } catch (e) { - throw new DetailedError( - `Plugin "${options.name}" validation failed:`, - ` - ${e.message} - ` - ); - } - } - - return pluginPackage.plugin(outputSchema, options.documents, options.config, { - outputFile: options.outputFilename - }); -} diff --git a/packages/graphql-codegen-cli/src/generate-and-save.ts b/packages/graphql-codegen-cli/src/generate-and-save.ts index 9ddbada4803..2db98963960 100644 --- a/packages/graphql-codegen-cli/src/generate-and-save.ts +++ b/packages/graphql-codegen-cli/src/generate-and-save.ts @@ -1,7 +1,7 @@ -import { FileOutput, Types, debugLog } from 'graphql-codegen-core'; +import { FileOutput, Types, debugLog } from 'graphql-codegen-plugin-helpers'; import { executeCodegen } from './codegen'; import { createWatcher } from './utils/watcher'; -import fs from './utils/file-system'; +import { fileExists, writeSync } from './utils/file-system'; process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; @@ -13,7 +13,7 @@ export async function generate(config: Types.Config, saveToFile = true): Promise await Promise.all( generationResult.map(async (result: FileOutput) => { - if (!shouldOverwrite(config, result.filename) && fs.fileExists(result.filename)) { + if (!shouldOverwrite(config, result.filename) && fileExists(result.filename)) { return; } @@ -23,7 +23,7 @@ export async function generate(config: Types.Config, saveToFile = true): Promise return; } - fs.writeSync(result.filename, result.content); + writeSync(result.filename, result.content); }) ); diff --git a/packages/graphql-codegen-cli/src/helpers.ts b/packages/graphql-codegen-cli/src/helpers.ts index 60431ec97d5..54cc4063c26 100644 --- a/packages/graphql-codegen-cli/src/helpers.ts +++ b/packages/graphql-codegen-cli/src/helpers.ts @@ -1,4 +1,4 @@ -import { Types } from 'graphql-codegen-core'; +import { Types } from 'graphql-codegen-plugin-helpers'; export function isOutputConfigArray(type: any): type is Types.OutputConfig[] { return Array.isArray(type); diff --git a/packages/graphql-codegen-cli/src/index.ts b/packages/graphql-codegen-cli/src/index.ts index 135fdfdd4ef..c341edbabd3 100644 --- a/packages/graphql-codegen-cli/src/index.ts +++ b/packages/graphql-codegen-cli/src/index.ts @@ -1,3 +1,2 @@ export { executeCodegen } from './codegen'; export { generate } from './generate-and-save'; -export { CLIOptions, createConfigFromOldCli } from './old-cli-config'; diff --git a/packages/graphql-codegen-cli/src/init.ts b/packages/graphql-codegen-cli/src/init.ts deleted file mode 100644 index 77a8c27416f..00000000000 --- a/packages/graphql-codegen-cli/src/init.ts +++ /dev/null @@ -1,348 +0,0 @@ -import * as inquirer from 'inquirer'; -import chalk from 'chalk'; -import { Types } from 'graphql-codegen-core'; -import { resolve, relative } from 'path'; -import { writeFileSync, readFileSync } from 'fs'; -import * as YAML from 'json-to-pretty-yaml'; -import * as detectIndent from 'detect-indent'; - -interface PluginOption { - name: string; - package: string; - value: string; - available(tags: Tags[]): boolean; -} - -enum Tags { - client = 'Client', - server = 'Server', - typescript = 'TypeScript', - angular = 'Angular', - react = 'React' -} - -function log(...msgs: string[]) { - // tslint:disable-next-line - console.log(...msgs); -} - -const plugins: Array = [ - { - name: `TypeScript Common ${chalk.italic('(required by client and server plugins)')}`, - package: 'graphql-codegen-typescript-common', - value: 'typescript-common', - available: () => true - }, - { - name: `TypeScript Client ${chalk.italic('(operations and fragments)')}`, - package: 'graphql-codegen-typescript-client', - value: 'typescript-client', - available: tags => tags.some(tag => [Tags.client].includes(tag)) - }, - { - name: `TypeScript Server ${chalk.italic('(GraphQL Schema)')}`, - package: 'graphql-codegen-typescript-server', - value: 'typescript-server', - available: tags => tags.some(tag => [Tags.client, Tags.server].includes(tag)) - }, - { - name: `TypeScript Resolvers ${chalk.italic('(strongly typed resolve functions)')}`, - package: 'graphql-codegen-typescript-resolvers', - value: 'typescript-resolvers', - available: tags => tags.some(tag => [Tags.server].includes(tag)) - }, - { - name: `TypeScript Apollo Angular ${chalk.italic('(GQL services)')}`, - package: 'graphql-codegen-typescript-apollo-angular', - value: 'typescript-apollo-angular', - available: tags => { - const hasAngular = tags.includes(Tags.angular); - const noReact = !tags.includes(Tags.react); - - return hasAngular && noReact; - } - }, - { - name: `TypeScript React Apollo ${chalk.italic('(typed components and HOCs)')}`, - package: 'graphql-codegen-typescript-react-apollo', - value: 'typescript-react-apollo', - available: tags => { - const hasReact = tags.includes(Tags.react); - const noAngular = !tags.includes(Tags.angular); - - return hasReact && noAngular; - } - }, - { - name: `TypeScript MongoDB ${chalk.italic('(typed MongoDB objects)')}`, - package: 'graphql-codegen-typescript-mongodb', - value: 'typescript-mongodb', - available: tags => tags.includes(Tags.server) - }, - { - name: `TypeScript GraphQL files modules ${chalk.italic('(declarations for .graphql files)')}`, - package: 'graphql-codegen-typescript-graphql-files-modules', - value: 'typescript-graphql-files-modules', - available: tags => tags.includes(Tags.client) - }, - { - name: `Introspection Fragment Matcher ${chalk.italic('(for Apollo Client)')}`, - package: 'graphql-codegen-fragment-matcher', - value: 'fragment-matcher', - available: tags => tags.includes(Tags.client) - } -]; - -interface Answers { - targets: Tags[]; - config: string; - plugins: PluginOption[]; - schema: string; - documents?: string; - output: string; - script: string; - introspection: boolean; -} - -export async function init() { - log(` - Welcome to ${chalk.bold('GraphQL Code Generator')}! - Answer few questions and we will setup everything for you. - `); - - const possibleTargets = await guessTargets(); - - function normalizeTargets(targets: Tags[] | Tags[][]): Tags[] { - return [].concat(...targets); - } - - const answers = await inquirer.prompt([ - { - type: 'checkbox', - name: 'targets', - message: `What type of application are you building?`, - choices: [ - { - name: 'Backend - API or server', - key: 'backend', - value: [Tags.server], - checked: possibleTargets.Server - }, - { - name: 'Application built with Angular', - key: 'angular', - value: [Tags.angular, Tags.client], - checked: possibleTargets.Angular - }, - { - name: 'Application built with React', - key: 'react', - value: [Tags.react, Tags.client], - checked: possibleTargets.React - }, - { - name: 'Application built with other framework or vanilla JS', - key: 'client', - value: [Tags.client], - checked: false - } - ] - }, - { - type: 'input', - name: 'schema', - message: 'Where is your schema?:', - suffix: chalk.grey(' (path or url)'), - default: 'https://localhost:4000', // matches Apollo Server's default - validate: (str: string) => str.length > 0 - }, - { - type: 'input', - name: 'documents', - message: 'Where are your operations and fragments?:', - when: answers => { - // flatten targets - // I can't find an API in Inquirer that would do that - answers.targets = normalizeTargets(answers.targets); - - return answers.targets.includes(Tags.client); - }, - default: '**/*.graphql', - validate: (str: string) => str.length > 0 - }, - { - type: 'checkbox', - name: 'plugins', - message: 'Pick plugins:', - choices: answers => { - return plugins - .filter(p => p.available(answers.targets)) - .map(p => { - return { - name: p.name, - value: p, - checked: p.value === 'typescript-common' - }; - }); - }, - validate: (plugins: any[]) => plugins.length > 0 - }, - { - type: 'input', - name: 'output', - message: 'Where to write the output:', - default: 'src/generated/graphql.ts', - validate: (str: string) => str.length > 0 - }, - { - type: 'confirm', - name: 'introspection', - message: 'Do you want to generate an introspection file?' - }, - { - type: 'input', - name: 'config', - message: 'How to name the config file?', - default: 'codegen.yml', - validate: (str: string) => { - const isNotEmpty = str.length > 0; - const hasCorrectExtension = ['json', 'yml', 'yaml'].some(ext => str.toLocaleLowerCase().endsWith(`.${ext}`)); - - return isNotEmpty && hasCorrectExtension; - } - }, - { - type: 'input', - name: 'script', - message: 'What script in package.json should run the codegen?', - validate: (str: string) => str.length > 0 - } - ]); - - // define config - const config: Types.Config = { - overwrite: true, - schema: answers.schema, - documents: answers.targets.includes(Tags.client) ? answers.documents : null, - generates: { - [answers.output]: { - plugins: answers.plugins.map(p => p.value) - } - } - }; - - // introspection - if (answers.introspection) { - addIntrospection(config); - } - - // config file - const { relativePath } = writeConfig(answers, config); - - // write package.json - writePackage(answers, relativePath); - - // Emit status to the terminal - log(` - Config file generated at ${chalk.bold(relativePath)} - - ${chalk.bold('$ npm install')} - - To install the plugins. - - ${chalk.bold(`$ npm run ${answers.script}`)} - - To run GraphQL Code Generator. - `); -} - -// adds an introspection to `generates` -function addIntrospection(config: Types.Config) { - config.generates['./graphql.schema.json'] = { - plugins: ['introspection'] - }; -} - -// Parses config and writes it to a file -function writeConfig(answers: Answers, config: Types.Config) { - const ext = answers.config.toLocaleLowerCase().endsWith('.json') ? 'json' : 'yml'; - const content = ext === 'json' ? JSON.stringify(config) : YAML.stringify(config); - const fullPath = resolve(process.cwd(), answers.config); - const relativePath = relative(process.cwd(), answers.config); - - writeFileSync(fullPath, content, { - encoding: 'utf-8' - }); - - return { - relativePath, - fullPath - }; -} - -// Updates package.json (script and plugins as dependencies) -function writePackage(answers: Answers, configLocation: string) { - // script - const pkgPath = resolve(process.cwd(), 'package.json'); - const pkgContent = readFileSync(pkgPath, { - encoding: 'utf-8' - }); - const pkg = JSON.parse(pkgContent); - const { indent } = detectIndent(pkgContent); - - if (!pkg.scripts) { - pkg.scripts = {}; - } - - pkg.scripts[answers.script] = `gql-gen --config ${configLocation}`; - - // plugin - if (!pkg.devDependencies) { - pkg.devDependencies = {}; - } - - // read codegen's version - const { version } = JSON.parse( - readFileSync(resolve(__dirname, '../package.json'), { - encoding: 'utf-8' - }) - ); - - answers.plugins.forEach(plugin => { - pkg.devDependencies[plugin.package] = version; - }); - - writeFileSync(pkgPath, JSON.stringify(pkg, null, indent)); -} - -async function guessTargets(): Promise> { - const pkg = JSON.parse( - readFileSync(resolve(process.cwd(), 'package.json'), { - encoding: 'utf-8' - }) - ); - const dependencies = Object.keys({ - ...pkg.dependencies, - ...pkg.devDependencies - }); - - return { - [Tags.angular]: isAngular(dependencies), - [Tags.react]: isReact(dependencies), - [Tags.client]: false, - [Tags.server]: false, - [Tags.typescript]: isTypescript(dependencies) - }; -} - -function isAngular(dependencies: string[]): boolean { - return dependencies.includes('@angular/core'); -} - -function isReact(dependencies: string[]): boolean { - return dependencies.includes('react'); -} - -function isTypescript(dependencies: string[]): boolean { - return dependencies.includes('typescript'); -} diff --git a/packages/graphql-codegen-cli/src/init/helpers.ts b/packages/graphql-codegen-cli/src/init/helpers.ts new file mode 100644 index 00000000000..54369487252 --- /dev/null +++ b/packages/graphql-codegen-cli/src/init/helpers.ts @@ -0,0 +1,71 @@ +import chalk from 'chalk'; +import { resolve, relative } from 'path'; +import { writeFileSync, readFileSync } from 'fs'; +import { Types } from 'graphql-codegen-plugin-helpers'; +import * as YAML from 'json-to-pretty-yaml'; +import * as detectIndent from 'detect-indent'; +import { Answers } from './types'; + +// Parses config and writes it to a file +export function writeConfig(answers: Answers, config: Types.Config) { + const ext = answers.config.toLocaleLowerCase().endsWith('.json') ? 'json' : 'yml'; + const content = ext === 'json' ? JSON.stringify(config) : YAML.stringify(config); + const fullPath = resolve(process.cwd(), answers.config); + const relativePath = relative(process.cwd(), answers.config); + + writeFileSync(fullPath, content, { + encoding: 'utf-8' + }); + + return { + relativePath, + fullPath + }; +} + +// Updates package.json (script and plugins as dependencies) +export function writePackage(answers: Answers, configLocation: string) { + // script + const pkgPath = resolve(process.cwd(), 'package.json'); + const pkgContent = readFileSync(pkgPath, { + encoding: 'utf-8' + }); + const pkg = JSON.parse(pkgContent); + const { indent } = detectIndent(pkgContent); + + if (!pkg.scripts) { + pkg.scripts = {}; + } + + pkg.scripts[answers.script] = `gql-gen --config ${configLocation}`; + + // plugin + if (!pkg.devDependencies) { + pkg.devDependencies = {}; + } + + // read codegen's version + const { version } = JSON.parse( + readFileSync(resolve(__dirname, '../../package.json'), { + encoding: 'utf-8' + }) + ); + + answers.plugins.forEach(plugin => { + pkg.devDependencies[plugin.package] = version; + }); + + writeFileSync(pkgPath, JSON.stringify(pkg, null, indent)); +} + +export function bold(str: string) { + return chalk.bold(str); +} + +export function grey(str: string) { + return chalk.grey(str); +} + +export function italic(str: string) { + return chalk.italic(str); +} diff --git a/packages/graphql-codegen-cli/src/init/index.ts b/packages/graphql-codegen-cli/src/init/index.ts new file mode 100644 index 00000000000..de32091aedc --- /dev/null +++ b/packages/graphql-codegen-cli/src/init/index.ts @@ -0,0 +1,65 @@ +import * as inquirer from 'inquirer'; +import { Types } from 'graphql-codegen-plugin-helpers'; +import { getQuestions } from './questions'; +import { guessTargets } from './targets'; +import { Answers, Tags } from './types'; +import { writeConfig, writePackage, bold } from './helpers'; + +function log(...msgs: string[]) { + // tslint:disable-next-line + console.log(...msgs); +} + +export async function init() { + log(` + Welcome to ${bold('GraphQL Code Generator')}! + Answer few questions and we will setup everything for you. + `); + + const possibleTargets = await guessTargets(); + + const answers = await inquirer.prompt(getQuestions(possibleTargets)); + + // define config + const config: Types.Config = { + overwrite: true, + schema: answers.schema, + documents: answers.targets.includes(Tags.browser) ? answers.documents : null, + generates: { + [answers.output]: { + plugins: answers.plugins.map(p => p.value) + } + } + }; + + // introspection + if (answers.introspection) { + addIntrospection(config); + } + + // config file + const { relativePath } = writeConfig(answers, config); + + // write package.json + writePackage(answers, relativePath); + + // Emit status to the terminal + log(` + Config file generated at ${bold(relativePath)} + + ${bold('$ npm install')} + + To install the plugins. + + ${bold(`$ npm run ${answers.script}`)} + + To run GraphQL Code Generator. + `); +} + +// adds an introspection to `generates` +function addIntrospection(config: Types.Config) { + config.generates['./graphql.schema.json'] = { + plugins: ['introspection'] + }; +} diff --git a/packages/graphql-codegen-cli/src/init/plugins.ts b/packages/graphql-codegen-cli/src/init/plugins.ts new file mode 100644 index 00000000000..e2f1d6f6c2e --- /dev/null +++ b/packages/graphql-codegen-cli/src/init/plugins.ts @@ -0,0 +1,106 @@ +import { italic } from './helpers'; +import { PluginOption, Tags } from './types'; + +export const plugins: Array = [ + { + name: `TypeScript ${italic('(required by other typescript plugins)')}`, + package: 'graphql-codegen-typescript', + value: 'typescript', + available: hasTag(Tags.typescript), + shouldBeSelected: tags => + oneOf(tags, Tags.angular, Tags.stencil) || allOf(tags, Tags.typescript, Tags.react) || noneOf(tags, Tags.flow) + }, + { + name: `TypeScript Operations ${italic('(operations and fragments)')}`, + package: 'graphql-codegen-typescript-operations', + value: 'typescript-operations', + available: tags => allOf(tags, Tags.browser, Tags.typescript), + shouldBeSelected: tags => oneOf(tags, Tags.angular, Tags.stencil) || allOf(tags, Tags.typescript, Tags.react) + }, + { + name: `TypeScript Resolvers ${italic('(strongly typed resolve functions)')}`, + package: 'graphql-codegen-typescript-resolvers', + value: 'typescript-resolvers', + available: tags => allOf(tags, Tags.node, Tags.typescript), + shouldBeSelected: tags => noneOf(tags, Tags.flow) + }, + { + name: `Flow ${italic('(required by other flow plugins)')}`, + package: 'graphql-codegen-flow', + value: 'flow', + available: hasTag(Tags.flow), + shouldBeSelected: tags => noneOf(tags, Tags.typescript) + }, + { + name: `Flow Operations ${italic('(operations and fragments)')}`, + package: 'graphql-codegen-flow-operations', + value: 'flow-operations', + available: tags => allOf(tags, Tags.browser, Tags.flow), + shouldBeSelected: tags => noneOf(tags, Tags.typescript) + }, + { + name: `Flow Resolvers ${italic('(strongly typed resolve functions)')}`, + package: 'graphql-codegen-flow-resolvers', + value: 'flow-resolvers', + available: tags => allOf(tags, Tags.node, Tags.flow), + shouldBeSelected: tags => noneOf(tags, Tags.typescript) + }, + { + name: `TypeScript Apollo Angular ${italic('(typed GQL services)')}`, + package: 'graphql-codegen-typescript-apollo-angular', + value: 'typescript-apollo-angular', + available: hasTag(Tags.angular), + shouldBeSelected: () => true + }, + { + name: `TypeScript React Apollo ${italic('(typed components and HOCs)')}`, + package: 'graphql-codegen-typescript-react-apollo', + value: 'typescript-react-apollo', + available: tags => allOf(tags, Tags.react, Tags.typescript), + shouldBeSelected: () => true + }, + { + name: `TypeScript Stencil Apollo ${italic('(typed components)')}`, + package: 'graphql-codegen-typescript-stencil-apollo', + value: 'typescript-stencil-apollo', + available: hasTag(Tags.stencil), + shouldBeSelected: () => true + }, + { + name: `TypeScript MongoDB ${italic('(typed MongoDB objects)')}`, + package: 'graphql-codegen-typescript-mongodb', + value: 'typescript-mongodb', + available: tags => allOf(tags, Tags.node, Tags.typescript), + shouldBeSelected: () => false + }, + { + name: `TypeScript GraphQL files modules ${italic('(declarations for .graphql files)')}`, + package: 'graphql-codegen-typescript-graphql-files-modules', + value: 'typescript-graphql-files-modules', + available: tags => allOf(tags, Tags.browser, Tags.typescript), + shouldBeSelected: () => false + }, + { + name: `Introspection Fragment Matcher ${italic('(for Apollo Client)')}`, + package: 'graphql-codegen-fragment-matcher', + value: 'fragment-matcher', + available: hasTag(Tags.browser), + shouldBeSelected: () => false + } +]; + +function hasTag(tag: Tags) { + return (tags: Tags[]) => tags.includes(tag); +} + +function oneOf(list: T[], ...items: T[]): boolean { + return list.some(i => items.includes(i)); +} + +function noneOf(list: T[], ...items: T[]): boolean { + return !list.some(i => items.includes(i)); +} + +function allOf(list: T[], ...items: T[]): boolean { + return items.every(i => list.includes(i)); +} diff --git a/packages/graphql-codegen-cli/src/init/questions.ts b/packages/graphql-codegen-cli/src/init/questions.ts new file mode 100644 index 00000000000..68b6261784e --- /dev/null +++ b/packages/graphql-codegen-cli/src/init/questions.ts @@ -0,0 +1,137 @@ +import * as inquirer from 'inquirer'; +import { grey } from './helpers'; +import { Tags, Answers } from './types'; +import { plugins } from './plugins'; + +export function getQuestions(possibleTargets: Record): inquirer.Question[] { + return [ + { + type: 'checkbox', + name: 'targets', + message: `What type of application are you building?`, + choices: getApplicationTypeChoices(possibleTargets) + }, + { + type: 'input', + name: 'schema', + message: 'Where is your schema?:', + suffix: grey(' (path or url)'), + default: 'http://localhost:4000', // matches Apollo Server's default + validate: (str: string) => str.length > 0 + }, + { + type: 'input', + name: 'documents', + message: 'Where are your operations and fragments?:', + when: answers => { + // flatten targets + // I can't find an API in Inquirer that would do that + answers.targets = normalizeTargets(answers.targets); + + return answers.targets.includes(Tags.browser); + }, + default: '**/*.graphql', + validate: (str: string) => str.length > 0 + }, + { + type: 'checkbox', + name: 'plugins', + message: 'Pick plugins:', + choices: getPluginChoices, + validate: (plugins: any[]) => plugins.length > 0 + }, + { + type: 'input', + name: 'output', + message: 'Where to write the output:', + default: 'src/generated/graphql.ts', + validate: (str: string) => str.length > 0 + }, + { + type: 'confirm', + name: 'introspection', + message: 'Do you want to generate an introspection file?' + }, + { + type: 'input', + name: 'config', + message: 'How to name the config file?', + default: 'codegen.yml', + validate: (str: string) => { + const isNotEmpty = str.length > 0; + const hasCorrectExtension = ['json', 'yml', 'yaml'].some(ext => str.toLocaleLowerCase().endsWith(`.${ext}`)); + + return isNotEmpty && hasCorrectExtension; + } + }, + { + type: 'input', + name: 'script', + message: 'What script in package.json should run the codegen?', + validate: (str: string) => str.length > 0 + } + ]; +} + +export function getApplicationTypeChoices(possibleTargets: Record) { + function withFlowOrTypescript(tags: Tags[]) { + if (possibleTargets.TypeScript) { + tags.push(Tags.typescript); + } else if (possibleTargets.Flow) { + tags.push(Tags.flow); + } else { + tags.push(Tags.flow, Tags.typescript); + } + + return tags; + } + + return [ + { + name: 'Backend - API or server', + key: 'backend', + value: withFlowOrTypescript([Tags.node]), + checked: possibleTargets.Node + }, + { + name: 'Application built with Angular', + key: 'angular', + value: [Tags.angular, Tags.browser, Tags.typescript], + checked: possibleTargets.Angular + }, + { + name: 'Application built with React', + key: 'react', + value: withFlowOrTypescript([Tags.react, Tags.browser]), + checked: possibleTargets.React + }, + { + name: 'Application built with Stencil', + key: 'stencil', + value: [Tags.stencil, Tags.browser, Tags.typescript], + checked: possibleTargets.Stencil + }, + { + name: 'Application built with other framework or vanilla JS', + key: 'client', + value: [Tags.browser, Tags.typescript, Tags.flow], + checked: possibleTargets.Browser && !possibleTargets.Angular && !possibleTargets.React && !possibleTargets.Stencil + } + ]; +} + +export function getPluginChoices(answers: Answers) { + return plugins + .filter(p => p.available(answers.targets)) + .map(p => { + return { + name: p.name, + value: p, + checked: p.shouldBeSelected(answers.targets) + }; + }); +} + +function normalizeTargets(targets: Tags[] | Tags[][]): Tags[] { + return [].concat(...targets); +} diff --git a/packages/graphql-codegen-cli/src/init/targets.ts b/packages/graphql-codegen-cli/src/init/targets.ts new file mode 100644 index 00000000000..87b165ea96b --- /dev/null +++ b/packages/graphql-codegen-cli/src/init/targets.ts @@ -0,0 +1,45 @@ +import { resolve } from 'path'; +import { readFileSync } from 'fs'; +import { Tags } from './types'; + +export async function guessTargets(): Promise> { + const pkg = JSON.parse( + readFileSync(resolve(process.cwd(), 'package.json'), { + encoding: 'utf-8' + }) + ); + const dependencies = Object.keys({ + ...pkg.dependencies, + ...pkg.devDependencies + }); + + return { + [Tags.angular]: isAngular(dependencies), + [Tags.react]: isReact(dependencies), + [Tags.stencil]: isStencil(dependencies), + [Tags.browser]: false, + [Tags.node]: false, + [Tags.typescript]: isTypescript(dependencies), + [Tags.flow]: isFlow(dependencies) + }; +} + +function isAngular(dependencies: string[]): boolean { + return dependencies.includes('@angular/core'); +} + +function isReact(dependencies: string[]): boolean { + return dependencies.includes('react'); +} + +function isStencil(dependencies: string[]): boolean { + return dependencies.includes('@stencil/core'); +} + +function isTypescript(dependencies: string[]): boolean { + return dependencies.includes('typescript'); +} + +function isFlow(dependencies: string[]): boolean { + return dependencies.includes('flow'); +} diff --git a/packages/graphql-codegen-cli/src/init/types.ts b/packages/graphql-codegen-cli/src/init/types.ts new file mode 100644 index 00000000000..5bf83209e5a --- /dev/null +++ b/packages/graphql-codegen-cli/src/init/types.ts @@ -0,0 +1,28 @@ +export interface PluginOption { + name: string; + package: string; + value: string; + available(tags: Tags[]): boolean; + shouldBeSelected(tags: Tags[]): boolean; +} + +export interface Answers { + targets: Tags[]; + config: string; + plugins: PluginOption[]; + schema: string; + documents?: string; + output: string; + script: string; + introspection: boolean; +} + +export enum Tags { + browser = 'Browser', + node = 'Node', + typescript = 'TypeScript', + flow = 'Flow', + angular = 'Angular', + stencil = 'Stencil', + react = 'React' +} diff --git a/packages/graphql-codegen-cli/src/load.ts b/packages/graphql-codegen-cli/src/load.ts index 2ac8e70c485..484d8939785 100644 --- a/packages/graphql-codegen-cli/src/load.ts +++ b/packages/graphql-codegen-cli/src/load.ts @@ -1,10 +1,10 @@ import { loadSchema as loadSchemaToolkit, loadDocuments as loadDocumentsToolkit } from 'graphql-toolkit'; -import { Types, DocumentFile } from 'graphql-codegen-core'; +import { Types, DocumentFile } from 'graphql-codegen-plugin-helpers'; import { GraphQLSchema, DocumentNode } from 'graphql'; import { DetailedError } from './errors'; -function getCustomLoaderByPath(path: string): any { - const requiredModule = require(path); +async function getCustomLoaderByPath(path: string): Promise { + const requiredModule = await import(path); if (requiredModule && requiredModule.default && typeof requiredModule.default === 'function') { return requiredModule.default; @@ -32,7 +32,7 @@ export const loadSchema = async ( const loaderString = defObject.loader; try { - const customSchemaLoader = getCustomLoaderByPath(loaderString); + const customSchemaLoader = await getCustomLoaderByPath(loaderString); if (customSchemaLoader) { const returnedSchema = await customSchemaLoader(pointToSchema, config, defObject); @@ -110,7 +110,7 @@ export const loadDocuments = async ( const loaderString = defObject.loader; try { - const customDocumentLoader = getCustomLoaderByPath(loaderString); + const customDocumentLoader = await getCustomLoaderByPath(loaderString); if (customDocumentLoader) { const returned = await customDocumentLoader(pointToDoc, config); diff --git a/packages/graphql-codegen-cli/src/merge-schemas.ts b/packages/graphql-codegen-cli/src/merge-schemas.ts deleted file mode 100644 index be301d08bbf..00000000000 --- a/packages/graphql-codegen-cli/src/merge-schemas.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { GraphQLSchema, DocumentNode } from 'graphql'; -import { mergeTypeDefs } from 'graphql-toolkit'; -import { makeExecutableSchema } from 'graphql-tools'; - -export function mergeSchemas(schemas: Array): DocumentNode { - const compactSchemas = schemas.filter(s => s); - - if (compactSchemas.length === 0) { - return null; - } else { - return mergeTypeDefs(compactSchemas); - } -} - -export function buildSchema(node: DocumentNode): GraphQLSchema { - return makeExecutableSchema({ - typeDefs: node, - allowUndefinedInResolve: true, - resolverValidationOptions: { - requireResolversForResolveType: false, - requireResolversForAllFields: false, - requireResolversForNonScalar: false, - requireResolversForArgs: false - } - }); -} diff --git a/packages/graphql-codegen-cli/src/old-cli-config.ts b/packages/graphql-codegen-cli/src/old-cli-config.ts deleted file mode 100644 index 3197ece4635..00000000000 --- a/packages/graphql-codegen-cli/src/old-cli-config.ts +++ /dev/null @@ -1,262 +0,0 @@ -import { Command } from 'commander'; -import { Types } from 'graphql-codegen-core'; -import { existsSync, readFileSync } from 'fs'; -import { join } from 'path'; -import { cliError } from './utils/cli-error'; -import * as YAML from 'json-to-pretty-yaml'; -import { isNode } from './utils/is-browser'; - -export interface CLIOptions { - schema?: string; - clientSchema?: string; - args?: string[]; - template?: string; - project?: string; - out?: string; - header?: string[]; - skipSchema?: any; - skipDocuments?: any; - config?: string; - require?: string[]; - overwrite?: boolean; - watch?: boolean; - silent?: boolean; - mergeSchema?: string; - exitOnError?: boolean; - templateConfig?: { [key: string]: any }; -} - -function collect(val: T, memo: T[]) { - memo.push(val); - - return memo; -} - -export const initCLI = (args: any): CLIOptions => { - const command = new Command() - .usage('gql-gen [options]') - .option( - '-s, --schema ', - 'Path to GraphQL schema: local JSON file, GraphQL endpoint, local file that exports GraphQLSchema/AST/JSON' - ) - .option( - '-cs, --clientSchema ', - 'Path to GraphQL client schema: local JSON file, local file that exports GraphQLSchema/AST/JSON' - ) - .option( - '-h, --header [header]', - 'Header to add to the introspection HTTP request when using --url/--schema with url', - collect, - [] - ) - .option( - '-t, --template ', - 'Language/platform name templates, or a name of NPM modules that `export default` GqlGenConfig object' - ) - .option('-p, --project ', 'Project path(s) to scan for custom template files') - .option('--config ', 'Codegen configuration file, defaults to: ./gql-gen.json') - .option('-m, --skip-schema', 'Generates only client side documents, without server side schema types') - .option('-c, --skip-documents', 'Generates only server side schema types, without client side documents') - .option('-o, --out ', 'Output file(s) path', String, './') - .option('-r, --require [require]', 'module to preload (option can be repeated)', collect, []) - .option('-ow, --no-overwrite', 'Skip file writing if the output file(s) already exists in path') - .option('-w, --watch', 'Watch for changes and execute generation automatically') - .option('--silent', 'Does not print anything to the console') - .option('-ms, --merge-schema ', 'Merge schemas with custom logic') - .arguments(' [documents...]') - .parse(args); - - return (command as any) as CLIOptions; -}; - -export const validateCliOptions = (options: CLIOptions) => { - const schema = options.schema; - const template = options.template; - const project = options.project; - - if (!schema && isNode) { - const { getGraphQLProjectConfig, ConfigNotFoundError } = require('graphql-config'); - - try { - const graphqlProjectConfig = getGraphQLProjectConfig(project); - options.schema = graphqlProjectConfig.schemaPath; - } catch (e) { - if (e instanceof ConfigNotFoundError) { - cliError('Flag --schema is missing!'); - } - } - } - - if (!template && !project) { - cliError('Please specify language/platform, using --template flag!'); - } -}; - -function transformTemplatesToPlugins( - options: CLIOptions, - templateSpecificConfig: { [key: string]: any } = {} -): Types.ConfiguredOutput { - if ( - options.template === 'ts' || - options.template === 'typescript' || - options.template === 'graphql-codegen-typescript-template' - ) { - return { - config: templateSpecificConfig, - plugins: [ - templateSpecificConfig.printTime ? 'time' : null, - 'typescript-common', - options.skipDocuments ? null : 'typescript-client', - options.skipSchema ? null : 'typescript-server' - ].filter(s => s) - }; - } else if ( - options.template === 'typescript-resolvers' || - options.template === 'graphql-codegen-typescript-resolvers-template' - ) { - return { - config: templateSpecificConfig, - plugins: [templateSpecificConfig.printTime ? 'time' : null, 'typescript-common', 'typescript-resolvers'].filter( - s => s - ) - }; - } else if ( - options.template === 'typescript-mongodb' || - options.template === 'graphql-codegen-typescript-mongodb-template' - ) { - return { - config: templateSpecificConfig, - plugins: [ - templateSpecificConfig.printTime ? 'time' : null, - 'typescript-common', - 'typescript-server', - 'typescript-mongodb' - ].filter(s => s) - }; - } else if (options.template === 'apollo-angular' || options.template === 'graphql-codegen-apollo-angular-template') { - return { - config: templateSpecificConfig, - plugins: [ - templateSpecificConfig.printTime ? 'time' : null, - 'typescript-common', - 'typescript-client', - 'typescript-apollo-angular' - ].filter(s => s) - }; - } else if ( - options.template === 'react-apollo' || - options.template === 'graphql-codegen-typescript-react-apollo-template' - ) { - return { - config: templateSpecificConfig, - plugins: [ - templateSpecificConfig.printTime ? 'time' : null, - 'typescript-common', - 'typescript-client', - 'typescript-react-apollo' - ].filter(s => s) - }; - } else if (options.template === 'introspection' || options.template === 'graphql-codegen-introspection-template') { - return { - config: templateSpecificConfig, - plugins: ['introspection'].filter(s => s) - }; - } else if ( - options.template === 'graphql-files-typescript' || - options.template === 'graphql-codegen-graphql-files-typescript-modules' - ) { - return { - config: templateSpecificConfig, - plugins: ['typescript-graphql-files-modules'].filter(s => s) - }; - } - - return { plugins: [options.template].filter(a => a) }; -} - -function getConfigFromEnvVars() { - return Object.keys(process.env) - .filter(name => name.startsWith('CODEGEN_')) - .reduce( - (prev, name) => { - const cleanName = name - .replace('CODEGEN_', '') - .toLowerCase() - .replace(/[-_]+/g, ' ') - .replace(/[^\w\s]/g, '') - .replace(/ (.)/g, res => res.toUpperCase()) - .replace(/ /g, ''); - let value: any = process.env[name]; - - if (value === 'true') { - value = true; - } else if (value === 'false') { - value = false; - } - - prev[cleanName] = value; - - return prev; - }, - {} as any - ); -} - -export function createConfigFromOldCli(options: CLIOptions): Types.Config { - validateCliOptions(options); - - let rootConfig: { [key: string]: any } = {}; - const configPath = options.config ? options.config : existsSync(join(process.cwd(), './gql-gen.json')); - - if (configPath && typeof configPath === 'string') { - const rawObj = JSON.parse(readFileSync(configPath, 'utf-8')); - rootConfig = (rawObj || {}).generatorConfig || {}; - } - - const envVarsConfig = getConfigFromEnvVars(); - rootConfig = { - ...rootConfig, - ...envVarsConfig - }; - - let schema: Types.Schema = options.schema; - - if (options.header && Array.isArray(options.header) && options.header.length > 0) { - schema = { - [options.schema]: { - headers: options.header.reduce((prev, h) => { - const splitted = h.split(':').map(p => p.trim()); - const name = splitted[0]; - const value = splitted[1]; - - return { ...prev, [name]: value }; - }, {}) - } - }; - } - - const configObject: Types.Config = { - schema: [schema, options.clientSchema].filter(s => s), - documents: options.args || [], - config: rootConfig, - generates: { - [options.out]: transformTemplatesToPlugins(options, { - ...rootConfig, - ...(options.templateConfig || {}) - }) - }, - silent: options.silent, - watch: options.watch, - require: options.require - }; - - console['warn'](` - Note: You are using the old API of graphql-code-generator. You can easily migrate by creating "codegen.yml" file in your project with the following content: - -${YAML.stringify(configObject)} - - Then, make sure that your script is executing just "gql-gen" (without any cli flags). - `); - - return configObject; -} diff --git a/packages/graphql-codegen-cli/src/plugins.ts b/packages/graphql-codegen-cli/src/plugins.ts new file mode 100644 index 00000000000..59a19ef6025 --- /dev/null +++ b/packages/graphql-codegen-cli/src/plugins.ts @@ -0,0 +1,49 @@ +import { Types, CodegenPlugin } from 'graphql-codegen-plugin-helpers'; +import { resolve } from 'path'; +import { DetailedError } from './errors'; + +export async function getPluginByName(name: string, pluginLoader: Types.PluginLoaderFn): Promise { + const possibleNames = [ + `graphql-codegen-${name}`, + `graphql-codegen-${name}-template`, + `codegen-${name}`, + `codegen-${name}-template`, + name + ]; + const possibleModules = possibleNames.concat(resolve(process.cwd(), name)); + + for (const moduleName of possibleModules) { + try { + return (await pluginLoader(moduleName)) as CodegenPlugin; + } catch (err) { + if (err.message.indexOf(`Cannot find module '${moduleName}'`) === -1) { + throw new DetailedError( + `Unable to load template plugin matching ${name}`, + ` + Unable to load template plugin matching '${name}'. + Reason: + ${err.message} + ` + ); + } + } + } + + const possibleNamesMsg = possibleNames + .map(name => + ` + - ${name} + `.trimRight() + ) + .join(''); + + throw new DetailedError( + `Unable to find template plugin matching ${name}`, + ` + Unable to find template plugin matching '${name}' + Install one of the following packages: + + ${possibleNamesMsg} + ` + ); +} diff --git a/packages/graphql-codegen-cli/src/utils/file-system.ts b/packages/graphql-codegen-cli/src/utils/file-system.ts index db4bdd58309..6fe0b985b90 100644 --- a/packages/graphql-codegen-cli/src/utils/file-system.ts +++ b/packages/graphql-codegen-cli/src/utils/file-system.ts @@ -1,9 +1,6 @@ -import * as fs from 'fs'; -import { fileExists } from './file-exists'; +import { writeFileSync } from 'fs'; +export { fileExists } from './file-exists'; -export default { - writeSync(filepath: string, content: string) { - fs.writeFileSync(filepath, content); - }, - fileExists -}; +export function writeSync(filepath: string, content: string) { + writeFileSync(filepath, content); +} diff --git a/packages/graphql-codegen-cli/src/utils/listr-renderer.ts b/packages/graphql-codegen-cli/src/utils/listr-renderer.ts index 36d7e223145..9f3ca91e952 100644 --- a/packages/graphql-codegen-cli/src/utils/listr-renderer.ts +++ b/packages/graphql-codegen-cli/src/utils/listr-renderer.ts @@ -1,13 +1,13 @@ import chalk from 'chalk'; import logUpdate from 'log-update'; -import * as indentString from 'indent-string'; +import indentString from 'indent-string'; import * as logSymbol from 'log-symbols'; import * as UpdateRenderer from 'listr-update-renderer'; import { stripIndent } from 'common-tags'; import { ListrTask } from 'listr'; import { DetailedError, isDetailedError } from '../errors'; import { Source } from 'graphql'; -import { debugLog, printLogs } from 'graphql-codegen-core'; +import { debugLog, printLogs } from 'graphql-codegen-plugin-helpers'; export class Renderer { private updateRenderer: any; diff --git a/packages/graphql-codegen-cli/src/utils/prettier.ts b/packages/graphql-codegen-cli/src/utils/prettier.ts index d3c28dd96f0..4a568791134 100644 --- a/packages/graphql-codegen-cli/src/utils/prettier.ts +++ b/packages/graphql-codegen-cli/src/utils/prettier.ts @@ -24,7 +24,7 @@ export async function prettify(filePath: string, content: string): Promise { - const chokidar = require('chokidar'); + const chokidar = await import('chokidar'); emitWatching(); watcher = chokidar.watch(files, { diff --git a/packages/graphql-codegen-cli/src/yml.ts b/packages/graphql-codegen-cli/src/yml.ts index 4399cb725a1..a0ce917d204 100644 --- a/packages/graphql-codegen-cli/src/yml.ts +++ b/packages/graphql-codegen-cli/src/yml.ts @@ -1,11 +1,11 @@ -import { Types, debugLog } from 'graphql-codegen-core'; +import { Types } from 'graphql-codegen-plugin-helpers'; import { safeLoad } from 'js-yaml'; export function parseConfigFile(ymlString: string): Types.Config { if (typeof process !== 'undefined' && 'env' in process) { - debugLog(`[CLI] Interpolation of Environmental Variables`); + // debugLog(`[CLI] Interpolation of Environmental Variables`); ymlString = ymlString.replace(/\$\{(.*)\}/g, (str, variable, index) => process.env[variable]); } - debugLog(`[CLI] Parsing YAML file`); + // debugLog(`[CLI] Parsing YAML file`); return safeLoad(ymlString) as Types.Config; } diff --git a/packages/graphql-codegen-cli/tests/cli-flags.spec.ts b/packages/graphql-codegen-cli/tests/cli-flags.spec.ts index b74b5b37f65..0214fed5391 100644 --- a/packages/graphql-codegen-cli/tests/cli-flags.spec.ts +++ b/packages/graphql-codegen-cli/tests/cli-flags.spec.ts @@ -25,50 +25,6 @@ describe.only('CLI Flags', () => { resetFs(); }); - it('Should detect old cli flags and convert them correctly', () => { - const args = createArgv('--template my-template --schema a.graphql --out out.ts'); - const config = createConfig(args); - - expect(config).toEqual({ - config: {}, - require: [], - documents: [], - schema: ['a.graphql'], - generates: { - 'out.ts': { - plugins: ['my-template'] - } - } - }); - }); - - it('Should detect old cli flags and convert them correctly using header field', () => { - const args = createArgv( - '--template my-template --schema http://localhost:3000/graphql --header "Foo: bar" --out out.ts' - ); - const config = createConfig(args); - - expect(config).toEqual({ - config: {}, - require: [], - documents: [], - schema: [ - { - 'http://localhost:3000/graphql': { - headers: { - Foo: 'bar' - } - } - } - ], - generates: { - 'out.ts': { - plugins: ['my-template'] - } - } - }); - }); - it('Should create basic config using new yml API', () => { mockConfig(` schema: schema.graphql diff --git a/packages/graphql-codegen-cli/tests/cli.spec.ts b/packages/graphql-codegen-cli/tests/cli.spec.ts deleted file mode 100644 index a9f06101d98..00000000000 --- a/packages/graphql-codegen-cli/tests/cli.spec.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { executeCodegen } from '../src/codegen'; -import { createConfigFromOldCli } from '../src/old-cli-config'; - -declare let global: any; - -describe('executeWithOptions', () => { - describe('Functional testing (old cli flags)', () => { - it('execute the correct results when using schema with json file', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/githunt/schema.json', - template: 'typescript', - out: 'temp.ts' - }) - ); - - expect(result.length).toBe(1); - }); - - it('execute the throw an error when a document is not valid', async () => { - try { - await executeCodegen( - createConfigFromOldCli({ - silent: false, - schema: './tests/test-documents/schema.graphql', - template: 'graphql-codegen-typescript-template', - args: ['./tests/test-documents/invalid-fields.graphql'] - }) - ); - - throw new Error('Should not be here'); - } catch (error) { - expect(error.message).not.toMatch('Should not be here'); - } - }); - - it('execute the correct results when using schema with js file', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-object.js', - template: 'graphql-codegen-typescript-template' - }) - ); - - expect(result.length).toBe(1); - }); - - it('should accept and pass templateConfig correctly', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-object.js', - template: 'ts', - templateConfig: { - immutableTypes: true - } - }) - ); - - expect(result[0].content).toContain('readonly id: number;'); - - const result2 = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-object.js', - template: 'ts', - templateConfig: { - immutableTypes: false - } - }) - ); - - expect(result2[0].content).toContain('id: number;'); - expect(result2[0].content).not.toContain('readonly id: number;'); - }); - - it('execute the correct results when using schema with graphql file', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema.graphql', - template: 'ts' - }) - ); - - expect(result.length).toBe(1); - }); - - it('execute the correct results when using schema with graphql file and imports', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-with-imports.graphql', - template: 'ts' - }) - ); - - expect(result.length).toBe(1); - }); - - it('execute the correct results when using schema with graphql file and schema object in it', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-with-root.graphql', - template: 'ts' - }) - ); - - expect(result.length).toBe(1); - }); - - it('execute the correct results when using custom config file', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/githunt/schema.json', - template: 'ts', - config: '../../dev-test/config/gql-gen.json' - }) - ); - - expect(result[0].content).toMatch('Generated in'); - }); - - it('execute the correct results when using schema export as object', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-object.js', - template: 'ts' - }) - ); - expect(result.length).toBe(1); - }); - - it('execute the correct results when using schema export as text', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-text.js', - template: 'ts' - }) - ); - expect(result.length).toBe(1); - }); - - describe('with local schema', () => { - it('execute the correct results when using schema export as object', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-object.js', - clientSchema: '../../dev-test/test-schema/local/schema-object.js', - template: 'ts' - }) - ); - expect(result.length).toBe(1); - }); - - it('execute the correct results when using schema export as text', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-text.js', - clientSchema: '../../dev-test/test-schema/local/schema-text.js', - template: 'ts' - }) - ); - - const content = result[0].content; - - expect(content).toMatch('export interface Post'); - expect(content).toMatch('allPosts: Maybe[];'); - expect(content).toMatch('allPosts: Maybe[];'); - - expect(result.length).toBe(1); - }); - }); - - it('execute the correct results when using skipSchema', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-text.js', - template: 'ts', - skipSchema: true - }) - ); - - expect(result[0].content.trim()).toBe('export type Maybe = T | null;'); - }); - - it('execute the correct results when using skipDocuments', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/star-wars/schema.json', - template: 'ts', - args: ['../../dev-test/star-wars/HeroDetails.graphql'], - skipDocuments: true, - skipSchema: true - }) - ); - - expect(result[0].content).not.toMatch('HeroDetails'); - }); - - it('execute the correct results when using schema export as ast', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-ast.js', - template: 'ts' - }) - ); - expect(result.length).toBe(1); - }); - - it('execute the correct results when using schema export as json', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/test-schema/schema-json.js', - template: 'ts' - }) - ); - expect(result.length).toBe(1); - }); - - it('execute the correct results when using export and require', async () => { - const result = await executeCodegen( - createConfigFromOldCli({ - schema: '../../dev-test/githunt/schema.js', - template: 'ts', - require: ['../tests/dummy-require.js'] - }) - ); - expect(result.length).toBe(1); - expect(global['dummyWasLoaded']).toBe(true); - }); - }); -}); diff --git a/packages/graphql-codegen-cli/tests/codegen.spec.ts b/packages/graphql-codegen-cli/tests/codegen.spec.ts index ee1b31cb5a8..9e8e1888f05 100644 --- a/packages/graphql-codegen-cli/tests/codegen.spec.ts +++ b/packages/graphql-codegen-cli/tests/codegen.spec.ts @@ -1,8 +1,6 @@ -import { makeExecutableSchema } from 'graphql-tools'; -import { executeCodegen } from '../src/codegen'; -import { mergeSchemas, buildSchema } from '../src/merge-schemas'; -import { GraphQLObjectType, parse, print } from 'graphql'; -import { FileOutput } from 'graphql-codegen-core'; +import { GraphQLObjectType, buildSchema, buildASTSchema, parse, print } from 'graphql'; +import { mergeSchemas } from 'graphql-codegen-core'; +import { executeCodegen } from '../src'; const SHOULD_NOT_THROW_STRING = 'SHOULD_NOT_THROW'; const SIMPLE_TEST_SCHEMA = `type MyType { f: String } type Query { f: String }`; @@ -13,8 +11,8 @@ describe('Codegen Executor', () => { const output = await executeCodegen({ schema: SIMPLE_TEST_SCHEMA, generates: { - 'out1.ts': ['typescript-common'], - 'out2.ts': ['typescript-common'] + 'out1.ts': ['typescript'], + 'out2.ts': ['typescript'] } }); @@ -29,7 +27,7 @@ describe('Codegen Executor', () => { schema: SIMPLE_TEST_SCHEMA, require: '../tests/dummy-require.js', generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -43,7 +41,7 @@ describe('Codegen Executor', () => { schema: SIMPLE_TEST_SCHEMA, require: 'tests/missing.js', generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -60,16 +58,14 @@ describe('Codegen Executor', () => { generates: { 'out1.ts': { plugins: { - 'typescript-client': {}, - 'typescript-server': {} + 'typescript-operations': {} } } } }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export namespace Root'); - expect(output[0].content).toContain('export interface Query'); + expect(output[0].content).toContain('export type RootQuery'); }); it('Should accept plugins as arrat of objects', async () => { @@ -78,14 +74,13 @@ describe('Codegen Executor', () => { documents: `query root { f }`, generates: { 'out1.ts': { - plugins: [{ 'typescript-client': {} }, { 'typescript-server': {} }] + plugins: [{ 'typescript-operations': {} }] } } }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export namespace Root'); - expect(output[0].content).toContain('export interface Query'); + expect(output[0].content).toContain('export type RootQuery'); }); it('Should throw when no output files has been specified', async () => { @@ -106,7 +101,7 @@ describe('Codegen Executor', () => { const output = await executeCodegen({ schema: SIMPLE_TEST_SCHEMA, generates: { - 'out.ts': ['typescript-common', 'typescript-server'] + 'out.ts': ['typescript'] } }); @@ -119,7 +114,7 @@ describe('Codegen Executor', () => { generates: { 'out.ts': { schema: SIMPLE_TEST_SCHEMA, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } } as any); @@ -135,7 +130,7 @@ describe('Codegen Executor', () => { try { await executeCodegen({ generates: { - 'out.ts': ['typescript-common', 'typescript-server'] + 'out.ts': ['typescript'] } } as any); @@ -165,7 +160,7 @@ describe('Codegen Executor', () => { const output = await executeCodegen({ schema: './tests/test-files/schema-dir/with-extend.js', generates: { - 'out.ts': ['typescript-common', 'typescript-server'] + 'out.ts': ['typescript'] } }); @@ -184,15 +179,15 @@ describe('Codegen Executor', () => { schema: ` type OtherType { a: String } `, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export interface Query'); - expect(output[0].content).toContain('export interface MyType'); - expect(output[0].content).toContain('export interface OtherType'); + expect(output[0].content).toContain('export type Query'); + expect(output[0].content).toContain('export type MyType'); + expect(output[0].content).toContain('export type OtherType'); }); it('Should allow to specify documents extension for specific output', async () => { @@ -201,13 +196,13 @@ describe('Codegen Executor', () => { generates: { 'out1.ts': { documents: `query q { f }`, - plugins: ['typescript-client'] + plugins: ['typescript', 'typescript-operations'] } } }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export namespace Q'); + expect(output[0].content).toContain('export type QQuery'); }); it('Should extend existing documents', async () => { @@ -217,36 +212,13 @@ describe('Codegen Executor', () => { generates: { 'out1.ts': { documents: `query q { f }`, - plugins: ['typescript-client'] + plugins: ['typescript', 'typescript-operations'] } } }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export namespace Q'); - expect(output[0].content).toContain('export namespace Root'); - }); - - it('Should be able to use root schema object (in apollo-angular)', async () => { - let output: FileOutput[]; - - try { - output = await executeCodegen({ - schema: ` - type RootQuery { f: String } - schema { query: RootQuery } - `, - documents: `query q { f }`, - generates: { - 'out1.ts': ['typescript-common', 'typescript-client', 'typescript-apollo-angular'] - } - }); - } catch (e) { - throw new Error(SHOULD_NOT_THROW_STRING); - } - - expect(output.length).toBe(1); - expect(output[0].filename).toBe('out1.ts'); + expect(output[0].content).toContain('export type QQuery'); }); it('Should throw on duplicated names', async () => { @@ -258,7 +230,7 @@ describe('Codegen Executor', () => { `, documents: [`query q { f }`, `query q { f }`], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); throw new Error(SHOULD_NOT_THROW_STRING); @@ -273,7 +245,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/my-fragment.ts', './tests/test-documents/query-with-my-fragment.ts'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); expect(result[0].content).toContain('MyQuery'); @@ -285,7 +257,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/my-fragment.ts', './tests/test-documents/query-with-my-fragment.ts'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); @@ -298,7 +270,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/js-query-with-my-fragment.js', './tests/test-documents/js-my-fragment.js'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); @@ -311,7 +283,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/ts-features-with-query.ts'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); @@ -325,7 +297,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/query-with-commented-fragment.ts'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); expect(result[0].content).toContain('MyQuery'); @@ -337,7 +309,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/gatsby-and-custom-parsers.ts'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); @@ -350,7 +322,7 @@ describe('Codegen Executor', () => { schema: ['./tests/test-documents/schema.graphql'], documents: ['./tests/test-documents/gatsby-and-custom-parsers.ts'], generates: { - 'out1.ts': ['typescript-common', 'typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] }, pluckConfig: { modules: [ @@ -365,11 +337,12 @@ describe('Codegen Executor', () => { expect(result[0].content).toContain('FragmentC'); // import { parser } from 'custom-graphql-parser'; }); - it('should handle graphql-tag and gatsby by default (schema)', async () => { + // Dotan: @kamil please check + it.skip('should handle graphql-tag and gatsby by default (schema)', async () => { const result = await executeCodegen({ schema: './tests/test-files/schema-dir/gatsby-and-custom-parsers/*.ts', generates: { - 'out1.ts': ['typescript-common', 'typescript-server'] + 'out1.ts': ['typescript'] } }); @@ -380,11 +353,12 @@ describe('Codegen Executor', () => { expect(content).not.toContain('Used custom parser'); }); - it('should handle custom graphql string parsers (schema)', async () => { + // Dotan: @kamil please check + it.skip('should handle custom graphql string parsers (schema)', async () => { const result = await executeCodegen({ schema: './tests/test-files/schema-dir/gatsby-and-custom-parsers/*.ts', generates: { - 'out1.ts': ['typescript-common', 'typescript-server'] + 'out1.ts': ['typescript'] }, pluckConfig: { modules: [ @@ -413,12 +387,13 @@ describe('Codegen Executor', () => { namingConvention: 'change-case#lowerCase' }, generates: { - 'out1.ts': ['typescript-client'] + 'out1.ts': ['typescript', 'typescript-operations'] } }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export namespace root'); + expect(output[0].content).toContain('export type rootquery'); + expect(output[0].content).toContain('export type root'); }); it('Should accept config in per-output', async () => { @@ -430,20 +405,20 @@ describe('Codegen Executor', () => { config: { namingConvention: 'change-case#lowerCase' }, - plugins: ['typescript-client'] + plugins: ['typescript', 'typescript-operations'] }, 'out2.ts': { config: { namingConvention: 'change-case#upperCase' }, - plugins: ['typescript-client'] + plugins: ['typescript', 'typescript-operations'] } } }); expect(output.length).toBe(2); - expect(output[0].content).toContain('export namespace root'); - expect(output[1].content).toContain('export namespace ROOT'); + expect(output[0].content).toContain('export type rootquery'); + expect(output[1].content).toContain('export type ROOTQUERY'); }); it('Should accept config in per-plugin', async () => { @@ -454,12 +429,9 @@ describe('Codegen Executor', () => { 'out1.ts': { plugins: [ { - 'typescript-client': { + 'typescript-operations': { namingConvention: 'change-case#lowerCase' } - }, - { - 'typescript-server': {} } ] } @@ -467,10 +439,8 @@ describe('Codegen Executor', () => { }); expect(output.length).toBe(1); - expect(output[0].content).toContain('export namespace root'); - expect(output[0].content).not.toContain('export namespace oot'); - expect(output[0].content).toContain('export interface Query'); - expect(output[0].content).not.toContain('export interface query'); + expect(output[0].content).toContain('export type root'); + expect(output[0].content).toContain('export type rootquery'); }); it('Should allow override of config in', async () => { @@ -484,7 +454,7 @@ describe('Codegen Executor', () => { 'out1.ts': { plugins: [ { - 'typescript-client': { + 'typescript-operations': { namingConvention: 'change-case#upperCase' } } @@ -493,7 +463,7 @@ describe('Codegen Executor', () => { 'out2.ts': { plugins: [ { - 'typescript-client': { + 'typescript-operations': { namingConvention: 'change-case#pascalCase' } } @@ -503,8 +473,8 @@ describe('Codegen Executor', () => { }); expect(output.length).toBe(2); - expect(output[0].content).toContain('export namespace ROOT'); - expect(output[1].content).toContain('export namespace Root'); + expect(output[0].content).toContain('export type ROOTQUERY'); + expect(output[1].content).toContain('export type RootQuery'); }); }); @@ -569,18 +539,16 @@ describe('Codegen Executor', () => { describe('Schema Merging', () => { it('should keep definitions of all directives', async () => { - const merged = buildSchema( + const merged = buildASTSchema( await mergeSchemas([ - makeExecutableSchema({ typeDefs: SIMPLE_TEST_SCHEMA }), - makeExecutableSchema({ - typeDefs: ` + buildSchema(SIMPLE_TEST_SCHEMA), + buildSchema(/* GraphQL */ ` directive @id on FIELD_DEFINITION type Post { id: String @id } - ` - }) + `) ]) ); @@ -588,11 +556,10 @@ describe('Codegen Executor', () => { }); it('should keep directives in types', async () => { - const merged = buildSchema( + const merged = buildASTSchema( await mergeSchemas([ - makeExecutableSchema({ typeDefs: SIMPLE_TEST_SCHEMA }), - makeExecutableSchema({ - typeDefs: ` + buildSchema(SIMPLE_TEST_SCHEMA), + buildSchema(/* GraphQL */ ` directive @id on FIELD_DEFINITION directive @test on OBJECT @@ -607,8 +574,7 @@ describe('Codegen Executor', () => { schema { query: Query } - ` - }) + `) ]) ); @@ -636,7 +602,7 @@ describe('Codegen Executor', () => { expect(print(merged)).toContain('scalar UniqueID'); expect(print(merged)).toContain('scalar NotUniqueID'); - const schema = buildSchema(merged); + const schema = buildASTSchema(merged); expect(schema.getType('UniqueID')).toBeDefined(); expect(schema.getType('NotUniqueID')).toBeDefined(); @@ -656,7 +622,7 @@ describe('Codegen Executor', () => { schema: [schemaA, schemaB], generates: { 'out1.ts': { - plugins: ['typescript-common'] + plugins: ['typescript'] } } }); @@ -677,7 +643,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -695,7 +661,7 @@ describe('Codegen Executor', () => { } } ], - plugins: ['typescript-common'] + plugins: ['typescript'] } } }); @@ -714,7 +680,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -737,7 +703,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -760,7 +726,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -787,7 +753,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -806,7 +772,7 @@ describe('Codegen Executor', () => { } } ], - plugins: ['typescript-common'] + plugins: ['typescript'] } } }); @@ -826,7 +792,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -850,7 +816,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); @@ -874,7 +840,7 @@ describe('Codegen Executor', () => { } ], generates: { - 'out1.ts': ['typescript-common'] + 'out1.ts': ['typescript'] } }); diff --git a/packages/graphql-codegen-cli/tests/custom-loaders/custom-schema-loader.js b/packages/graphql-codegen-cli/tests/custom-loaders/custom-schema-loader.js index 9476b466e03..77ce8b622b3 100644 --- a/packages/graphql-codegen-cli/tests/custom-loaders/custom-schema-loader.js +++ b/packages/graphql-codegen-cli/tests/custom-loaders/custom-schema-loader.js @@ -1,8 +1,8 @@ -const { makeExecutableSchema } = require('graphql-tools'); +const { buildSchema } = require('graphql'); const { readFileSync } = require('fs'); module.exports = function(schemaString, config) { global.CUSTOM_SCHEMA_LOADER_CALLED = true; - return makeExecutableSchema({ typeDefs: readFileSync(schemaString, { encoding: 'utf-8' }) }); + return buildSchema(readFileSync(schemaString, { encoding: 'utf-8' })); }; diff --git a/packages/graphql-codegen-cli/tests/dummy-require.js b/packages/graphql-codegen-cli/tests/dummy-require.js index da1e46f772a..96b8dc345e4 100644 --- a/packages/graphql-codegen-cli/tests/dummy-require.js +++ b/packages/graphql-codegen-cli/tests/dummy-require.js @@ -1,3 +1,2 @@ // Just set something in global so the test can verify that it got set and thereby know that this module was loaded - global.dummyWasLoaded = true; diff --git a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts index e892133e3db..837970b355a 100644 --- a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts +++ b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts @@ -1,5 +1,5 @@ import { generate } from '../src/generate-and-save'; -import fs from '../src/utils/file-system'; +import * as fs from '../src/utils/file-system'; const SIMPLE_TEST_SCHEMA = `type MyType { f: String } type Query { f: String }`; @@ -22,7 +22,7 @@ describe('generate-and-save', () => { schema: ` type OtherType { a: String } `, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }, @@ -51,7 +51,7 @@ describe('generate-and-save', () => { schema: ` type OtherType { a: String } `, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }, @@ -78,7 +78,7 @@ describe('generate-and-save', () => { schema: ` type OtherType { a: String } `, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }, @@ -106,7 +106,7 @@ describe('generate-and-save', () => { schema: ` type OtherType { a: String } `, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }, @@ -135,7 +135,7 @@ describe('generate-and-save', () => { schema: ` type OtherType { a: String } `, - plugins: ['typescript-common', 'typescript-server'] + plugins: ['typescript'] } } }, diff --git a/packages/graphql-codegen-cli/tests/issues/issue-1068.spec.ts b/packages/graphql-codegen-cli/tests/issues/issue-1068.spec.ts deleted file mode 100644 index aa4597241dd..00000000000 --- a/packages/graphql-codegen-cli/tests/issues/issue-1068.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { parseConfigFile } from '../../src/yml'; -import { generate } from '../../src'; - -it('Issues 1068 - Cannot read property "onType" of undefined', async () => { - const ymlConfig = parseConfigFile(` -schema: - - " - type AuthState { - authenticated: Boolean - token: String - } - - type Query { - getAuthState: AuthState - } - - type Mutation { - changeAuthState: AuthState - } -" -documents: " - mutation ChangeAuthState { - changeAuthState @client { - ...authFragments - } - } - - fragment authStateFragment on AuthState { - authenticated - token - } -" -overwrite: true -generates: - output.tsx: - plugins: - - time - - add: "// THIS IS A GENERATED FILE, DO NOT EDIT IT!" - - typescript-common: - interfacePrefix: "I" - - typescript-client - - typescript-react-apollo - `); - - try { - await generate(ymlConfig); - expect(true).toBeFalsy(); - } catch (e) { - expect(e.errors[0].message).toBe( - `A fragment spread you used "authFragments" could not found. Please make sure that it's loaded as a GraphQL document!` - ); - } -}); diff --git a/packages/graphql-codegen-cli/tests/test-files/schema-dir/with-extend.js b/packages/graphql-codegen-cli/tests/test-files/schema-dir/with-extend.js index 3759c7a155c..dd2e1644eeb 100644 --- a/packages/graphql-codegen-cli/tests/test-files/schema-dir/with-extend.js +++ b/packages/graphql-codegen-cli/tests/test-files/schema-dir/with-extend.js @@ -1,22 +1,19 @@ const { makeExecutableSchema } = require('graphql-tools'); const schema = makeExecutableSchema({ - typeDefs: [ - ` + typeDefs: /* GraphQL */ ` type User { a: String } - + type Query { user: User } - `, - ` + extend type Query { hello: String } ` - ] }); module.exports = schema; diff --git a/packages/graphql-codegen-cli/tsconfig.json b/packages/graphql-codegen-cli/tsconfig.json index 64c1f5aa940..c8e1f767b91 100644 --- a/packages/graphql-codegen-cli/tsconfig.json +++ b/packages/graphql-codegen-cli/tsconfig.json @@ -1,8 +1,10 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "allowSyntheticDefaultImports": true, + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015", "dom"], "moduleResolution": "node", "emitDecoratorMetadata": true, @@ -17,6 +19,6 @@ "noUnusedLocals": true, "noUnusedParameters": false }, - "files": ["src/index.ts", "src/cli.ts", "declarations.d.ts"], + "files": ["src/index.ts", "src/cli.ts", "src/declarations.d.ts"], "exclude": ["node_modules"] } diff --git a/packages/graphql-codegen-core/.gitignore b/packages/graphql-codegen-core/.gitignore index 911ea64d58a..48bc1ab0c29 100644 --- a/packages/graphql-codegen-core/.gitignore +++ b/packages/graphql-codegen-core/.gitignore @@ -2,4 +2,5 @@ node_modules npm-debug.log dist temp -yarn-error.log \ No newline at end of file +yarn-error.log +tests/coverage/ \ No newline at end of file diff --git a/packages/graphql-codegen-core/.npmignore b/packages/graphql-codegen-core/.npmignore index 9ee5e2fb4d5..0dd971dc996 100644 --- a/packages/graphql-codegen-core/.npmignore +++ b/packages/graphql-codegen-core/.npmignore @@ -1,5 +1,6 @@ -../graphql-codegen-generators/dev-test src node_modules tests !dist +jest.config.js +tsconfig.json diff --git a/packages/graphql-codegen-core/.npmrc b/packages/graphql-codegen-core/.npmrc deleted file mode 100644 index 1dab4ed4c30..00000000000 --- a/packages/graphql-codegen-core/.npmrc +++ /dev/null @@ -1 +0,0 @@ -save-exact = true diff --git a/packages/graphql-codegen-core/README.md b/packages/graphql-codegen-core/README.md index 3d77b89756d..d8f980ab489 100644 --- a/packages/graphql-codegen-core/README.md +++ b/packages/graphql-codegen-core/README.md @@ -1,30 +1,9 @@ -# `graphql-codegen-core` +# GraphQL Code Generator -This package is in charge of converting `GraphQLSchema` and GraphQL client-side operations (query/mutation/subscription/fragment) into a template consumable JSON structure. +

+ +

-The entry points of this package are: +Live demo and full documentation: [graphql-code-generator.com](https://graphql-code-generator.com) -* `schemaToTemplateContext` - transforms `GraphQLSchema` into [`SchemaTemplateContext`](./src/types.ts#L78-L94) object. -* `transformDocument` - transforms GraphQL `DocumentNode` (object that can contains multiple GraphQL operations and fragments) to [`Document`](./src/types.ts#L195-L200). - -The purpose of the transformation is to simplify the links and connections between the GraphQL entities, and to add template indicators (`has...`, `is...`, `uses...`) to the context. - -## Build process - -The build process of this package is based on TypeScript and compiled with `typescript` compiler. - -To build this package, start by installing the package dependencies: - -``` - $ npm install - // Or, with Yarn - $ yarn -``` - -Then, you can use the existing NPM scripts to build the package: - -``` - $ npm build - // Or, with Yarn - $ yarn build -``` +Project repository: [graphql-code-generator](https://github.com/dotansimha/graphql-code-generator) diff --git a/packages/graphql-codegen-core/package.json b/packages/graphql-codegen-core/package.json index f1e01298aea..28b0338e701 100644 --- a/packages/graphql-codegen-core/package.json +++ b/packages/graphql-codegen-core/package.json @@ -1,22 +1,18 @@ { "name": "graphql-codegen-core", "version": "0.18.0", - "description": "GraphQL types and code generator based on schema", - "main": "dist/index.js", - "scripts": { - "clean": "rimraf ./dist", - "lint": "tslint src/**/*.ts", - "prebuild": "yarn clean && yarn lint", - "build": "tsc", - "prestart": "yarn build", - "start": "cd dist && node gql-gen.js", - "debug": "cd dist && node --inspect --debug-brk gql-gen.js", - "test": "jest --no-cache --verbose --runInBand" - }, + "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/dotansimha/graphql-code-generator.git" }, + "scripts": { + "clean": "rimraf ./dist", + "lint": "tslint src/**/*.ts", + "prebuild": "yarn clean", + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../jest.config.js" + }, "keywords": [ "gql", "generator", @@ -35,45 +31,26 @@ "typings" ], "author": "Dotan Simha ", - "license": "MIT", "bugs": { "url": "https://github.com/dotansimha/graphql-codegen/issues" }, "homepage": "https://github.com/dotansimha/graphql-codegen#readme", - "config": { - "commitizen": { - "path": "./node_modules/cz-conventional-changelog" - } - }, - "jest": { - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" }, "dependencies": { - "chalk": "2.4.2", - "change-case": "3.1.0", - "common-tags": "1.8.0", - "graphql-tag": "2.10.1", + "graphql-codegen-plugin-helpers": "0.18.0", "graphql-toolkit": "0.2.6", - "graphql-tools": "4.0.4", - "ts-log": "2.1.4", - "winston": "3.2.1" + "tslib": "1.9.3" }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" + "devDependencies": { + "ts-jest": "24.0.0" }, - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/graphql-codegen-core/src/codegen.ts b/packages/graphql-codegen-core/src/codegen.ts new file mode 100644 index 00000000000..6d64ad84fcc --- /dev/null +++ b/packages/graphql-codegen-core/src/codegen.ts @@ -0,0 +1,114 @@ +import { CodegenPlugin, DocumentFile, Types, debugLog } from 'graphql-codegen-plugin-helpers'; +import { DocumentNode, visit } from 'graphql'; +import { mergeSchemas } from './merge-schemas'; +import { executePlugin } from './execute-plugin'; +import { DetailedError } from './errors'; + +export async function codegen(options: { + filename: string; + plugins: Types.ConfiguredPlugin[]; + schema: DocumentNode; + documents: DocumentFile[]; + config: { [key: string]: any }; + pluginMap: { + [name: string]: CodegenPlugin; + }; +}) { + let output = ''; + + validateDocuments(options.schema, options.documents); + + const plugins = Object.keys(options.pluginMap).map(key => options.pluginMap[key]); + + // merged schema with parts added by plugins + const schema = plugins.reduce((schema, plugin) => { + return !plugin.addToSchema ? schema : mergeSchemas([schema, plugin.addToSchema]); + }, options.schema); + + for (let i = 0; i < plugins.length; i++) { + const plugin = options.plugins[i]; + const name = Object.keys(plugin)[0]; + const pluginPackage = options.pluginMap[name]; + const pluginConfig = plugin[name]; + + debugLog(`[CLI] Running plugin: ${name}`); + + const result = await executePlugin( + { + name, + config: + typeof pluginConfig !== 'object' + ? pluginConfig + : { + ...options.config, + ...(pluginConfig as object) + }, + schema, + documents: options.documents, + outputFilename: options.filename, + allPlugins: options.plugins + }, + pluginPackage + ); + + debugLog(`[CLI] Completed executing plugin: ${name}`); + + output += result; + } + + return output; +} + +function validateDocuments(schema: DocumentNode, files: DocumentFile[]) { + // duplicated names + const operationMap: { + [name: string]: string[]; + } = {}; + + files.forEach(file => { + visit(file.content, { + OperationDefinition(node) { + if (typeof node.name !== 'undefined') { + if (!operationMap[node.name.value]) { + operationMap[node.name.value] = []; + } + + operationMap[node.name.value].push(file.filePath); + } + } + }); + }); + + const names = Object.keys(operationMap); + + if (names.length) { + const duplicated = names.filter(name => operationMap[name].length > 1); + + if (!duplicated.length) { + return; + } + + const list = duplicated + .map(name => + ` + * ${name} found in: + ${operationMap[name] + .map(filepath => { + return ` + - ${filepath} + `.trimRight(); + }) + .join('')} + `.trimRight() + ) + .join(''); + throw new DetailedError( + `Not all operations have an unique name: ${duplicated.join(', ')}`, + ` + Not all operations have an unique name + + ${list} + ` + ); + } +} diff --git a/packages/graphql-codegen-core/src/errors.ts b/packages/graphql-codegen-core/src/errors.ts new file mode 100644 index 00000000000..c052591e5c9 --- /dev/null +++ b/packages/graphql-codegen-core/src/errors.ts @@ -0,0 +1,11 @@ +export class DetailedError extends Error { + constructor(public message: string, public details: string, public source?: string) { + super(message); + Object.setPrototypeOf(this, DetailedError.prototype); + Error.captureStackTrace(this, DetailedError); + } +} + +export function isDetailedError(error: any): error is DetailedError { + return error.details; +} diff --git a/packages/graphql-codegen-core/src/execute-plugin.ts b/packages/graphql-codegen-core/src/execute-plugin.ts new file mode 100644 index 00000000000..1c856478903 --- /dev/null +++ b/packages/graphql-codegen-core/src/execute-plugin.ts @@ -0,0 +1,62 @@ +import { Types, DocumentFile, CodegenPlugin } from 'graphql-codegen-plugin-helpers'; +import { DocumentNode, GraphQLSchema, buildASTSchema } from 'graphql'; +import { DetailedError } from './errors'; +import { validateGraphQlDocuments, checkValidationErrors } from 'graphql-toolkit'; + +export interface ExecutePluginOptions { + name: string; + config: Types.PluginConfig; + schema: DocumentNode; + documents: DocumentFile[]; + outputFilename: string; + allPlugins: Types.ConfiguredPlugin[]; +} + +export async function executePlugin(options: ExecutePluginOptions, plugin: CodegenPlugin): Promise { + if (!plugin || !plugin.plugin || typeof plugin.plugin !== 'function') { + throw new DetailedError( + `Invalid Custom Plugin "${options.name}"`, + ` + Plugin ${options.name} does not export a valid JS object with "plugin" function. + + Make sure your custom plugin is written in the following form: + + module.exports = { + plugin: (schema, documents, config) => { + return 'my-custom-plugin-content'; + }, + }; + ` + ); + } + + const outputSchema: GraphQLSchema = buildASTSchema(options.schema); + + if (outputSchema && options.documents.length > 0) { + const errors = validateGraphQlDocuments(outputSchema, options.documents); + checkValidationErrors(errors); + } + + if (plugin.validate && typeof plugin.validate === 'function') { + try { + await plugin.validate( + outputSchema, + options.documents, + options.config, + options.outputFilename, + options.allPlugins + ); + } catch (e) { + throw new DetailedError( + `Plugin "${options.name}" validation failed:`, + ` + ${e.message} + ` + ); + } + } + + return plugin.plugin(outputSchema, options.documents, options.config, { + outputFile: options.outputFilename + }); +} diff --git a/packages/graphql-codegen-core/src/index.ts b/packages/graphql-codegen-core/src/index.ts index 8abca9d8773..a1ce4dfe07a 100644 --- a/packages/graphql-codegen-core/src/index.ts +++ b/packages/graphql-codegen-core/src/index.ts @@ -1,8 +1,4 @@ -export { schemaToTemplateContext } from './schema/schema-to-template-context'; -export { transformDocument, transformDocumentsFiles } from './operations/transform-document'; -export { parse } from './utils/parse'; -export { toPascalCase } from './utils/to-pascal-case'; -export * from './types'; -export * from './yml-config-types'; -export { debugLog, printLogs, resetLogs } from './debugging'; -export { getLogger, setLogger, setSilentLogger, useWinstonLogger } from './utils/logger'; +export * from './errors'; +export { codegen } from './codegen'; +export { executePlugin, ExecutePluginOptions } from './execute-plugin'; +export { mergeSchemas } from './merge-schemas'; diff --git a/packages/graphql-codegen-core/src/merge-schemas.ts b/packages/graphql-codegen-core/src/merge-schemas.ts new file mode 100644 index 00000000000..c904fe73b29 --- /dev/null +++ b/packages/graphql-codegen-core/src/merge-schemas.ts @@ -0,0 +1,12 @@ +import { GraphQLSchema, DocumentNode } from 'graphql'; +import { mergeTypeDefs } from 'graphql-toolkit'; + +export function mergeSchemas(schemas: Array): DocumentNode { + const compactSchemas = schemas.filter(s => s); + + if (compactSchemas.length === 0) { + return null; + } else { + return mergeTypeDefs(compactSchemas); + } +} diff --git a/packages/graphql-codegen-core/src/operations/build-selection-set.ts b/packages/graphql-codegen-core/src/operations/build-selection-set.ts deleted file mode 100644 index 3319a4a6cc8..00000000000 --- a/packages/graphql-codegen-core/src/operations/build-selection-set.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { - isFragmentSpreadNode, - SelectionSetFieldNode, - SelectionSetFragmentSpread, - SelectionSetInlineFragment, - SelectionSetItem, - isInlineFragmentNode, - isFieldNode -} from '../types'; -import { - Kind, - FieldNode, - FragmentSpreadNode, - getNamedType, - GraphQLSchema, - InlineFragmentNode, - SelectionNode, - SelectionSetNode, - typeFromAST, - isEqualType, - GraphQLNamedType, - GraphQLObjectType, - __Schema, - __Type, - SchemaMetaFieldDef, - TypeMetaFieldDef, - GraphQLField -} from 'graphql'; -import { getFieldDef } from '../utils/get-field-def'; -import { resolveType } from '../schema/resolve-type'; -import { debugLog } from '../debugging'; -import { resolveTypeIndicators } from '../schema/resolve-type-indicators'; - -function isMetadataFieldName(name: string) { - return ['__schema', '__type'].includes(name); -} - -function isRootType(type: GraphQLNamedType, schema: GraphQLSchema): type is GraphQLObjectType { - return ( - isEqualType(type, schema.getQueryType()) || - isEqualType(type, schema.getMutationType()) || - isEqualType(type, schema.getSubscriptionType()) - ); -} - -export function separateSelectionSet(selectionSet: SelectionSetItem[]): any { - const fields = selectionSet.filter(n => isFieldNode(n)); - const fragmentsSpread = selectionSet.filter(n => isFragmentSpreadNode(n)); - const inlineFragments = selectionSet.filter(n => isInlineFragmentNode(n)); - - return { - fragmentsSpread, - fields, - inlineFragments, - hasFragmentsSpread: fragmentsSpread.length > 0, - hasFields: fields.length > 0, - hasInlineFragments: inlineFragments.length > 0 - }; -} - -const metadataObjectMap: Record = { - __schema: __Schema, - __type: __Type -}; -const metadataFieldMap: Record> = { - __schema: SchemaMetaFieldDef, - __type: TypeMetaFieldDef -}; - -export function buildMetadata(schema: GraphQLSchema, fieldNode: FieldNode): SelectionSetItem { - const name = fieldNode.name.value; - const type = metadataObjectMap[name]; - const field = metadataFieldMap[name]; - - return resolveFieldNode( - schema, - fieldNode, - field, - fieldNode.alias && fieldNode.alias.value ? fieldNode.alias.value : fieldNode.name.value, - type - ); -} - -function resolveFieldNode( - schema: GraphQLSchema, - fieldNode: FieldNode, - field: GraphQLField, - name: string, - type: GraphQLNamedType -): SelectionSetItem { - const resolvedType = resolveType(field.type); - const childSelectionSet = buildSelectionSet(schema, type, fieldNode.selectionSet); - const namedType = type; - const indicators = resolveTypeIndicators(namedType); - - return { - isField: true, - isFragmentSpread: false, - isInlineFragment: false, - isLeaf: childSelectionSet.length === 0, - schemaFieldName: fieldNode.name.value, - name, - isAliased: fieldNode.alias && fieldNode.alias.value, - selectionSet: childSelectionSet, - ...separateSelectionSet(childSelectionSet), - type: resolvedType.name, - raw: resolvedType.raw, - isRequired: resolvedType.isRequired, - isNullableArray: resolvedType.isNullableArray, - isArray: resolvedType.isArray, - dimensionOfArray: resolvedType.dimensionOfArray, - hasTypename: hasTypename(fieldNode), - isEnum: indicators.isEnum, - isScalar: indicators.isScalar, - isInterface: indicators.isInterface, - isUnion: indicators.isUnion, - isInputType: indicators.isInputType, - isType: indicators.isType - } as SelectionSetFieldNode; -} - -export function buildSelectionSet( - schema: GraphQLSchema, - rootObject: GraphQLNamedType, - node: SelectionSetNode -): SelectionSetItem[] { - return ((node && node.selections ? node.selections : []) as SelectionNode[]) - .map( - (selectionNode: SelectionNode): SelectionSetItem => { - if (selectionNode.kind === Kind.FIELD) { - const fieldNode = selectionNode as FieldNode; - const name = fieldNode.alias && fieldNode.alias.value ? fieldNode.alias.value : fieldNode.name.value; - debugLog(`[buildSelectionSet] transforming FIELD with name ${name}`); - - // Kamil: `__query` and `__type` metadata fields are available only in root types. - // Or I'm wrong and maybe just in Query type? - // Or I'm completely wrong and even outside of root types? - // So many unanswered questions... - if (isRootType(rootObject, schema) && isMetadataFieldName(fieldNode.name.value)) { - return buildMetadata(schema, fieldNode); - } - - const field = getFieldDef(rootObject, fieldNode); - - if (!field) { - debugLog(`[buildSelectionSet] Ignoring field because of null result from getFieldDef...`); - - return null; - } - - return resolveFieldNode(schema, fieldNode, field, name, getNamedType(field.type)); - } else if (selectionNode.kind === Kind.FRAGMENT_SPREAD) { - const fieldNode = selectionNode as FragmentSpreadNode; - debugLog(`[buildSelectionSet] transforming FRAGMENT_SPREAD with name ${fieldNode.name.value}...`); - - return { - isField: false, - isFragmentSpread: true, - isInlineFragment: false, - isLeaf: true, - fragmentName: fieldNode.name.value - } as SelectionSetFragmentSpread; - } else if (selectionNode.kind === Kind.INLINE_FRAGMENT) { - debugLog(`[buildSelectionSet] transforming INLINE_FRAGMENT...`); - - const fieldNode = selectionNode as InlineFragmentNode; - const nextRoot = typeFromAST(schema, fieldNode.typeCondition); - const childSelectionSet = buildSelectionSet(schema, nextRoot, fieldNode.selectionSet); - - return { - isField: false, - isFragmentSpread: false, - isInlineFragment: true, - isLeaf: childSelectionSet.length === 0, - selectionSet: childSelectionSet, - ...separateSelectionSet(childSelectionSet), - onType: fieldNode.typeCondition.name.value, - hasTypename: hasTypename(fieldNode) - } as SelectionSetInlineFragment; - } else { - throw new Error(`Unexpected GraphQL type: ${(selectionNode as any).kind}!`); - } - } - ) - .filter(item => item); // filter to remove null types -} - -function hasTypename(fieldNode: FieldNode | InlineFragmentNode): boolean { - return ( - fieldNode.selectionSet && - fieldNode.selectionSet.selections.some(f => f.kind === 'Field' && f.name.value === '__typename') - ); -} diff --git a/packages/graphql-codegen-core/src/operations/transform-document.ts b/packages/graphql-codegen-core/src/operations/transform-document.ts deleted file mode 100644 index 761ba0a5447..00000000000 --- a/packages/graphql-codegen-core/src/operations/transform-document.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { - Kind, - DefinitionNode, - DocumentNode, - FragmentDefinitionNode, - GraphQLSchema, - OperationDefinitionNode, - print -} from 'graphql'; -import { Document, DocumentFile } from '../types'; -import { transformFragment } from './transform-fragment-document'; -import { transformOperation } from './transform-operation'; -import { debugLog } from '../debugging'; -import { getLogger } from '..'; - -let usedNames: { [key: string]: any } = {}; - -function nameGenerator(operationType: string, count = 1): any { - const idea = `Anonymous_${operationType}_${count}`; - - if (usedNames[idea]) { - return nameGenerator(operationType, count + 1); - } - - usedNames[idea] = true; - - return idea; -} - -function generateTempName(documentNode: FragmentDefinitionNode | OperationDefinitionNode): string { - let operationType: string; - - if (documentNode.kind === Kind.FRAGMENT_DEFINITION) { - operationType = 'fragment'; - } else if (documentNode.kind === Kind.OPERATION_DEFINITION) { - operationType = documentNode.operation; - } - - return nameGenerator(operationType); -} - -export function fixAnonymousDocument(documentNode: FragmentDefinitionNode | OperationDefinitionNode): string | null { - if (!documentNode.name) { - const newName = generateTempName(documentNode); - - getLogger().warn( - `The following document does not have a name. The codegen will use an anonymous name: ${newName}, please consider to name it.`, - print(documentNode) - ); - - return newName; - } - - return null; -} - -export function transformDocumentsFiles(schema: GraphQLSchema, documentFiles: DocumentFile[]): Document { - return documentFiles - .map(documentsFile => transformDocument(schema, documentsFile.content, documentsFile.filePath)) - .reduce( - (result, transformedDocument) => { - result.fragments = [...result.fragments, ...transformedDocument.fragments]; - result.operations = [...result.operations, ...transformedDocument.operations]; - result.hasFragments = result.fragments.length > 0; - result.hasOperations = result.operations.length > 0; - - return result; - }, - { - fragments: [], - operations: [], - hasFragments: false, - hasOperations: false - } as Document - ); -} - -export function transformDocument( - schema: GraphQLSchema, - documentNode: DocumentNode, - originalFilePath: string | null = null -): Document { - const result: Document = { - fragments: [], - operations: [], - hasFragments: false, - hasOperations: false - }; - - const definitions = documentNode.definitions || []; - - debugLog(`[transformDocument] transforming total of ${definitions.length} definitions...`); - - definitions.forEach((definitionNode: DefinitionNode) => { - if (definitionNode.kind === Kind.OPERATION_DEFINITION) { - const overrideName = fixAnonymousDocument(definitionNode as OperationDefinitionNode); - const operation = transformOperation(schema, definitionNode as OperationDefinitionNode, overrideName); - operation.originalFile = originalFilePath; - result.operations.push(operation); - } else if (definitionNode.kind === Kind.FRAGMENT_DEFINITION) { - const overrideName = fixAnonymousDocument(definitionNode as FragmentDefinitionNode); - const fragment = transformFragment(schema, definitionNode as FragmentDefinitionNode, overrideName); - fragment.originalFile = originalFilePath; - result.fragments.push(fragment); - } else { - getLogger().warn(`It seems like you provided an invalid GraphQL document of kind "${definitionNode.kind}".`); - } - }); - - result.hasFragments = result.fragments.length > 0; - result.hasOperations = result.operations.length > 0; - - return result; -} diff --git a/packages/graphql-codegen-core/src/operations/transform-fragment-document.ts b/packages/graphql-codegen-core/src/operations/transform-fragment-document.ts deleted file mode 100644 index 709de8df998..00000000000 --- a/packages/graphql-codegen-core/src/operations/transform-fragment-document.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { FragmentDefinitionNode, GraphQLSchema, typeFromAST } from 'graphql'; -import { Fragment } from '../types'; -import { buildSelectionSet, separateSelectionSet } from './build-selection-set'; -import { debugLog } from '../debugging'; -import { print } from 'graphql/language/printer'; -import { getDirectives } from 'graphql-toolkit'; - -export function transformFragment( - schema: GraphQLSchema, - fragment: FragmentDefinitionNode, - overrideName?: string | null -): Fragment { - debugLog( - `[transformFragment] transforming fragment ${fragment.name.value} on type ${fragment.typeCondition.name.value}` - ); - - const root = typeFromAST(schema, fragment.typeCondition); - const name = overrideName ? overrideName : fragment.name.value; - const onType = fragment.typeCondition.name.value; - const directives = getDirectives(schema, fragment); - const selectionSet = buildSelectionSet(schema, root, fragment.selectionSet); - - return { - name, - onType, - selectionSet, - document: print(fragment), - directives, - usesDirectives: Object.keys(directives).length > 0, - ...separateSelectionSet(selectionSet) - } as Fragment; -} diff --git a/packages/graphql-codegen-core/src/operations/transform-operation.ts b/packages/graphql-codegen-core/src/operations/transform-operation.ts deleted file mode 100644 index db9b22101e7..00000000000 --- a/packages/graphql-codegen-core/src/operations/transform-operation.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { GraphQLSchema, OperationDefinitionNode } from 'graphql'; -import { Operation } from '../types'; -import { getRoot } from '../utils/get-root'; -import { buildSelectionSet, separateSelectionSet } from './build-selection-set'; -import { transformVariables } from './transform-variables'; -import { debugLog } from '../debugging'; -import { print } from 'graphql/language/printer'; -import { getDirectives } from 'graphql-toolkit'; - -export function transformOperation( - schema: GraphQLSchema, - operationNode: OperationDefinitionNode, - overrideName?: string | null -): Operation { - const name = overrideName - ? overrideName - : operationNode.name && operationNode.name.value - ? operationNode.name.value - : ''; - debugLog(`[transformOperation] transforming operation ${name} of type ${operationNode.operation}`); - - const root = getRoot(schema, operationNode); - - if (!root) { - throw new Error(`Unable to find the schema root matching: ${operationNode.operation}`); - } - - const variables = transformVariables(schema, operationNode); - const directives = getDirectives(schema, operationNode); - const selectionSet = buildSelectionSet(schema, root, operationNode.selectionSet); - - return { - name, - selectionSet, - operationType: operationNode.operation, - variables: variables, - hasVariables: variables.length > 0, - isQuery: operationNode.operation === 'query', - isMutation: operationNode.operation === 'mutation', - isSubscription: operationNode.operation === 'subscription', - document: print(operationNode), - directives, - usesDirectives: Object.keys(directives).length > 0, - ...separateSelectionSet(selectionSet) - } as Operation; -} diff --git a/packages/graphql-codegen-core/src/operations/transform-variables.ts b/packages/graphql-codegen-core/src/operations/transform-variables.ts deleted file mode 100644 index db4dc11d990..00000000000 --- a/packages/graphql-codegen-core/src/operations/transform-variables.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { getNamedType, GraphQLSchema, OperationDefinitionNode, typeFromAST, VariableDefinitionNode } from 'graphql'; -import { Variable } from '../types'; -import { resolveType } from '../schema/resolve-type'; -import { debugLog } from '../debugging'; -import { resolveTypeIndicators } from '../schema/resolve-type-indicators'; -import { NonNullTypeNode } from 'graphql/language/ast'; - -export function transformVariables(schema: GraphQLSchema, definitionNode: OperationDefinitionNode): Variable[] { - return definitionNode.variableDefinitions.map( - (variableDefinition: VariableDefinitionNode): Variable => { - const typeFromSchema = typeFromAST(schema, variableDefinition.type as NonNullTypeNode); - const resolvedType = resolveType(typeFromSchema); - debugLog( - `[transformVariables] transforming variable ${variableDefinition.variable.name.value} of type ${ - resolvedType.name - }` - ); - const namedType = getNamedType(typeFromSchema); - const indicators = resolveTypeIndicators(namedType); - - return { - name: variableDefinition.variable.name.value, - type: resolvedType.name, - raw: resolvedType.raw, - isNullableArray: resolvedType.isNullableArray, - isArray: resolvedType.isArray, - dimensionOfArray: resolvedType.dimensionOfArray, - isRequired: resolvedType.isRequired, - isEnum: indicators.isEnum, - isScalar: indicators.isScalar, - isInterface: indicators.isInterface, - isUnion: indicators.isUnion, - isInputType: indicators.isInputType, - isType: indicators.isType - }; - } - ); -} diff --git a/packages/graphql-codegen-core/src/schema/resolve-arguments.ts b/packages/graphql-codegen-core/src/schema/resolve-arguments.ts deleted file mode 100644 index 1f106bc4804..00000000000 --- a/packages/graphql-codegen-core/src/schema/resolve-arguments.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { getNamedType, GraphQLArgument, GraphQLSchema } from 'graphql'; -import { Argument } from '../types'; -import { resolveType } from './resolve-type'; -import { resolveTypeIndicators } from './resolve-type-indicators'; -import { debugLog } from '../debugging'; -import { getDirectives } from 'graphql-toolkit'; - -export function resolveArguments(schema: GraphQLSchema, args: GraphQLArgument[]): Argument[] { - return args.map( - (arg: GraphQLArgument): Argument => { - const type = resolveType(arg.type); - const namedType = getNamedType(arg.type); - const indicators = resolveTypeIndicators(namedType); - const directives = getDirectives(schema, arg); - const defaultValue = arg.defaultValue; - const hasDefaultValue = defaultValue != null; - - debugLog(`[resolveArguments] resolving argument ${arg.name} of type ${type.name}...`); - - return { - name: arg.name, - description: arg.description || '', - type: type.name, - isRequired: type.isRequired, - raw: type.raw, - isNullableArray: type.isNullableArray, - isArray: type.isArray, - dimensionOfArray: type.dimensionOfArray, - isEnum: indicators.isEnum, - isScalar: indicators.isScalar, - isInterface: indicators.isInterface, - isUnion: indicators.isUnion, - isInputType: indicators.isInputType, - isType: indicators.isType, - directives, - usesDirectives: Object.keys(directives).length > 0, - hasDefaultValue, - defaultValue - }; - } - ); -} diff --git a/packages/graphql-codegen-core/src/schema/resolve-type-indicators.ts b/packages/graphql-codegen-core/src/schema/resolve-type-indicators.ts deleted file mode 100644 index 9ed7f42e6a6..00000000000 --- a/packages/graphql-codegen-core/src/schema/resolve-type-indicators.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - GraphQLEnumType, - GraphQLInputObjectType, - GraphQLInterfaceType, - GraphQLNamedType, - GraphQLObjectType, - GraphQLScalarType, - GraphQLUnionType -} from 'graphql'; - -export interface NamedTypeIndicators { - isType: boolean; - isScalar: boolean; - isInterface: boolean; - isUnion: boolean; - isInputType: boolean; - isEnum: boolean; -} - -export function resolveTypeIndicators(namedType: GraphQLNamedType): NamedTypeIndicators { - return { - isType: namedType instanceof GraphQLObjectType, - isScalar: namedType instanceof GraphQLScalarType, - isInterface: namedType instanceof GraphQLInterfaceType, - isUnion: namedType instanceof GraphQLUnionType, - isInputType: namedType instanceof GraphQLInputObjectType, - isEnum: namedType instanceof GraphQLEnumType - }; -} diff --git a/packages/graphql-codegen-core/src/schema/resolve-type.ts b/packages/graphql-codegen-core/src/schema/resolve-type.ts deleted file mode 100644 index 4ed100b0d31..00000000000 --- a/packages/graphql-codegen-core/src/schema/resolve-type.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { getNamedType, GraphQLInputType, GraphQLOutputType, GraphQLType } from 'graphql'; -import { debugLog } from '../debugging'; - -export interface ResolvedType { - raw: string; - name: string; - isRequired: boolean; - isArray: boolean; - isNullableArray: boolean; - dimensionOfArray: number; -} - -export function isRequired(type: GraphQLOutputType | GraphQLInputType): boolean { - const stringType = String(type); - - return stringType.lastIndexOf('!') === stringType.length - 1; -} - -export function isNullable(type: GraphQLOutputType | GraphQLInputType): boolean { - const stringType = String(type); - - return isArray(type) && !stringType.includes('!]'); -} - -export function isArray(type: GraphQLOutputType | GraphQLInputType): boolean { - return String(type).indexOf('[') > -1; -} - -export function dimensionOfArray(type: GraphQLOutputType | GraphQLInputType): number { - if (isArray(type)) { - let dimension = 0; - const characters = Array.from(String(type)); - for (const char of characters) { - if (char !== '[') { - return dimension; - } else { - dimension++; - } - } - } - return -1; -} - -export function resolveType(type: GraphQLType): ResolvedType { - const name = getNamedType(type).name; - debugLog(`[resolveType] resolving type ${name}`); - - return { - name, - raw: String(type), - isRequired: isRequired(type), - isArray: isArray(type), - isNullableArray: isNullable(type), - dimensionOfArray: dimensionOfArray(type) - }; -} diff --git a/packages/graphql-codegen-core/src/schema/schema-to-template-context.ts b/packages/graphql-codegen-core/src/schema/schema-to-template-context.ts deleted file mode 100644 index 7558800fac9..00000000000 --- a/packages/graphql-codegen-core/src/schema/schema-to-template-context.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { - GraphQLEnumType, - GraphQLInputObjectType, - GraphQLInterfaceType, - GraphQLNamedType, - GraphQLObjectType, - GraphQLScalarType, - GraphQLSchema, - GraphQLUnionType, - visitWithTypeInfo, - TypeInfo, - visit, - getNamedType, - isIntrospectionType, - isEnumType -} from 'graphql'; -import { SchemaTemplateContext, DocumentFile } from '../types'; -import { objectMapToArray } from '../utils/object-map-to-array'; -import { transformGraphQLObject } from './transform-object'; -import { transformGraphQLEnum } from './transform-enum'; -import { transformUnion } from './transform-union'; -import { transformInterface } from './transform-interface'; -import { transformScalar } from './transform-scalar'; -import { debugLog } from '../debugging'; -import { transformDirectives } from './transform-directives'; -import { getDirectives } from 'graphql-toolkit'; - -const GRAPHQL_PRIMITIVES = ['String', 'Int', 'Boolean', 'ID', 'Float']; -type GraphQLTypesMap = { [typeName: string]: GraphQLNamedType }; - -const clearTypes = (typesMap: GraphQLTypesMap, forcedTypes: string[]): GraphQLTypesMap => - Object.keys(typesMap) - .filter(key => forcedTypes.includes(key) || (!GRAPHQL_PRIMITIVES.includes(key) && !key.startsWith('__'))) - .reduce((obj, key) => { - obj[key] = typesMap[key]; - return obj; - }, {}); - -export function schemaToTemplateContext(schema: GraphQLSchema, documents?: DocumentFile[]): SchemaTemplateContext { - debugLog('[schemaToTemplateContext] started...'); - - const introspectionTypesToInclude = includeIntrospectionTypes(schema, documents); - - const directives = getDirectives(schema, schema); - const result: SchemaTemplateContext = { - types: [], - inputTypes: [], - enums: [], - unions: [], - scalars: [], - interfaces: [], - definedDirectives: [], - // Indicators - hasTypes: false, - hasInputTypes: false, - hasEnums: false, - hasUnions: false, - hasScalars: false, - hasInterfaces: false, - hasDefinedDirectives: false, - rawSchema: schema, - directives, - usesDirectives: Object.keys(directives).length > 0 - }; - - const rawTypesMap = schema.getTypeMap(); - const typesMap = clearTypes(rawTypesMap, introspectionTypesToInclude.map(t => t.name)); - const typesArray = objectMapToArray(typesMap); - - debugLog(`[schemaToTemplateContext] Got total of ${typesArray.length} types in the GraphQL schema`); - - typesArray.map((graphQlType: { key: string; value: GraphQLNamedType }) => { - const actualTypeDef = graphQlType.value; - - if (actualTypeDef instanceof GraphQLObjectType) { - result.types.push(transformGraphQLObject(schema, actualTypeDef)); - } else if (actualTypeDef instanceof GraphQLInputObjectType) { - result.inputTypes.push(transformGraphQLObject(schema, actualTypeDef)); - } else if (actualTypeDef instanceof GraphQLEnumType) { - result.enums.push(transformGraphQLEnum(schema, actualTypeDef)); - } else if (actualTypeDef instanceof GraphQLUnionType) { - result.unions.push(transformUnion(schema, actualTypeDef)); - } else if (actualTypeDef instanceof GraphQLInterfaceType) { - result.interfaces.push(transformInterface(schema, actualTypeDef)); - } else if (actualTypeDef instanceof GraphQLScalarType) { - result.scalars.push(transformScalar(schema, actualTypeDef)); - } else { - throw new Error( - `Unexpected GraphQL type definition: ${graphQlType.key} (As string: ${String(actualTypeDef)}).` + - `Please check that you are importing only one instance of the 'graphql' package.` - ); - } - }); - - result.definedDirectives = transformDirectives(schema, schema.getDirectives() || []); - - result.hasTypes = result.types.length > 0; - result.hasInputTypes = result.inputTypes.length > 0; - result.hasEnums = result.enums.length > 0; - result.hasUnions = result.unions.length > 0; - result.hasScalars = result.scalars.length > 0; - result.hasInterfaces = result.interfaces.length > 0; - result.hasDefinedDirectives = result.definedDirectives.length > 0; - - debugLog(`[schemaToTemplateContext] done, results is: `, result); - - return result; -} - -function includeIntrospectionTypes(schema: GraphQLSchema, documents?: DocumentFile[]): GraphQLNamedType[] { - let typesToInclude: GraphQLNamedType[] = []; - - if (documents) { - const typeInfo = new TypeInfo(schema); - const visitor = visitWithTypeInfo(typeInfo, { - Field() { - const type = getNamedType(typeInfo.getType()); - - if (isIntrospectionType(type) && isEnumType(type) && !typesToInclude.includes(type)) { - typesToInclude.push(type); - } - } - }); - - documents.forEach(doc => visit(doc.content, visitor)); - } - - return typesToInclude; -} diff --git a/packages/graphql-codegen-core/src/schema/transform-directives.ts b/packages/graphql-codegen-core/src/schema/transform-directives.ts deleted file mode 100644 index c9d2e5eb00a..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-directives.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { GraphQLDirective, DirectiveLocation, GraphQLSchema } from 'graphql'; -import { Directive } from '../types'; -import { resolveArguments } from './resolve-arguments'; - -export function transformDirectives(schema: GraphQLSchema, directives: ReadonlyArray): Directive[] { - return directives.map((directive: GraphQLDirective): Directive => { - const args = resolveArguments(schema, directive.args); - const locations = directive.locations || []; - - return { - name: directive.name, - description: directive.description || '', - hasArguments: args.length > 0, - arguments: args, - locations, - - onFragmentSpread: locations.includes(DirectiveLocation.FRAGMENT_SPREAD), - onInlineFragment: locations.includes(DirectiveLocation.INLINE_FRAGMENT), - onQuery: locations.includes(DirectiveLocation.QUERY), - onMutation: locations.includes(DirectiveLocation.MUTATION), - onSubscription: locations.includes(DirectiveLocation.SUBSCRIPTION), - onFragment: locations.includes(DirectiveLocation.FRAGMENT_SPREAD), - onField: locations.includes(DirectiveLocation.FIELD), - - onSchema: locations.includes(DirectiveLocation.SCHEMA), - onScalar: locations.includes(DirectiveLocation.SCALAR), - onFieldDefinition: locations.includes(DirectiveLocation.FIELD_DEFINITION), - onEnum: locations.includes(DirectiveLocation.ENUM), - onEnumValue: locations.includes(DirectiveLocation.ENUM_VALUE), - onObject: locations.includes(DirectiveLocation.OBJECT), - onInputObject: locations.includes(DirectiveLocation.INPUT_OBJECT), - onInputField: locations.includes(DirectiveLocation.INPUT_FIELD_DEFINITION), - onArgument: locations.includes(DirectiveLocation.ARGUMENT_DEFINITION), - onInterface: locations.includes(DirectiveLocation.INTERFACE), - onUnion: locations.includes(DirectiveLocation.UNION) - }; - }); -} diff --git a/packages/graphql-codegen-core/src/schema/transform-enum.ts b/packages/graphql-codegen-core/src/schema/transform-enum.ts deleted file mode 100644 index 0e8972a5157..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-enum.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GraphQLEnumType, GraphQLEnumValue, GraphQLSchema } from 'graphql'; -import { Enum, EnumValue } from '../types'; -import { debugLog } from '../debugging'; -import { getDirectives } from 'graphql-toolkit'; - -export function transformGraphQLEnum(schema: GraphQLSchema, graphqlEnum: GraphQLEnumType): Enum { - debugLog(`[transformGraphQLEnum] transformed enum ${graphqlEnum.name}`); - const directives = getDirectives(schema, graphqlEnum); - - const enumValues = graphqlEnum.getValues().map((enumItem: GraphQLEnumValue) => { - const valueDirectives = getDirectives(schema, enumItem); - - return { - name: enumItem.name, - description: enumItem.description || '', - value: enumItem.value, - directives: valueDirectives, - usesDirectives: Object.keys(valueDirectives).length > 0 - }; - }); - - return { - name: graphqlEnum.name, - description: graphqlEnum.description || '', - values: enumValues, - directives, - usesDirectives: Object.keys(directives).length > 0 - }; -} diff --git a/packages/graphql-codegen-core/src/schema/transform-fields.ts b/packages/graphql-codegen-core/src/schema/transform-fields.ts deleted file mode 100644 index ff3ac857481..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-fields.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { - getNamedType, - GraphQLField, - GraphQLFieldMap, - GraphQLSchema, - GraphQLInterfaceType, - GraphQLObjectType, - GraphQLInputObjectType, - GraphQLNamedType, - GraphQLScalarType, - GraphQLUnionType, - GraphQLEnumType, - GraphQLInputFieldMap, - GraphQLInputField, - isInputType -} from 'graphql'; -import { objectMapToArray } from '../utils/object-map-to-array'; -import { Field, FieldType } from '../types'; -import { resolveType } from './resolve-type'; -import { resolveArguments } from './resolve-arguments'; -import { resolveTypeIndicators } from './resolve-type-indicators'; -import { debugLog } from '../debugging'; -import { getDirectives } from 'graphql-toolkit'; - -export function resolveFields( - schema: GraphQLSchema, - rawFields: GraphQLFieldMap | GraphQLInputFieldMap, - _parent: GraphQLObjectType | GraphQLInterfaceType | GraphQLInputObjectType -): Field[] { - const fieldsArray = objectMapToArray | GraphQLInputField>(rawFields); - - return fieldsArray.map( - (item: { key: string; value: GraphQLField }): Field => { - const type = resolveType(item.value.type); - const resolvedArguments = resolveArguments(schema, item.value.args || []); - const namedType = getNamedType(item.value.type); - const indicators = resolveTypeIndicators(namedType); - const directives = getDirectives(schema, item.value); - - let defaultValue = null; - - let hasDefaultValue = false; - - if (isInputField(item.value)) { - defaultValue = item.value.defaultValue; - hasDefaultValue = defaultValue != null && typeof defaultValue !== 'undefined'; - } - - debugLog(`[resolveFields] transformed field ${item.value.name} of type ${type}, resolved type is: `, type); - - return { - name: item.value.name, - description: item.value.description || '', - arguments: resolvedArguments, - type: type.name, - fieldType: toFieldType(schema, namedType), - raw: type.raw, - isNullableArray: type.isNullableArray, - isArray: type.isArray, - dimensionOfArray: type.dimensionOfArray, - isRequired: type.isRequired, - hasArguments: resolvedArguments.length > 0, - isEnum: indicators.isEnum, - isScalar: indicators.isScalar, - isInterface: indicators.isInterface, - isUnion: indicators.isUnion, - isInputType: indicators.isInputType, - isType: indicators.isType, - hasDefaultValue, - defaultValue, - directives, - usesDirectives: Object.keys(directives).length > 0 - }; - } - ); -} - -function toFieldType(schema: GraphQLSchema, type: GraphQLNamedType): FieldType { - const typeMap = { - Type: () => type instanceof GraphQLObjectType, - Scalar: () => type instanceof GraphQLScalarType, - Interface: () => type instanceof GraphQLInterfaceType, - Union: () => type instanceof GraphQLUnionType, - InputType: () => type instanceof GraphQLInputObjectType, - Enum: () => type instanceof GraphQLEnumType, - Query: () => schema.getQueryType() && (schema.getQueryType() as GraphQLObjectType).name === type.name, - Mutation: () => schema.getMutationType() && (schema.getMutationType() as GraphQLObjectType).name === type.name, - Subscription: () => - schema.getSubscriptionType() && (schema.getSubscriptionType() as GraphQLObjectType).name === type.name - }; - - return Object.keys(typeMap).find(fieldType => typeMap[fieldType]()) as FieldType; -} - -function isInputField(field: any): field is GraphQLInputField { - return isInputType(field.type); -} diff --git a/packages/graphql-codegen-core/src/schema/transform-interface.ts b/packages/graphql-codegen-core/src/schema/transform-interface.ts deleted file mode 100644 index aba81b6b025..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-interface.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { GraphQLInterfaceType, GraphQLSchema } from 'graphql'; -import { Interface } from '../types'; -import { resolveFields } from './transform-fields'; -import { debugLog } from '../debugging'; -import { getDirectives, getImplementingTypes } from 'graphql-toolkit'; - -export function transformInterface(schema: GraphQLSchema, gqlInterface: GraphQLInterfaceType): Interface { - debugLog(`[transformInterface] transformed interface ${gqlInterface.name}`); - - const resolvedFields = resolveFields(schema, gqlInterface.getFields(), gqlInterface); - const directives = getDirectives(schema, gqlInterface); - const implementingTypes = getImplementingTypes(gqlInterface.name, schema); - - return { - name: gqlInterface.name, - description: gqlInterface.description || '', - fields: resolvedFields, - hasFields: resolvedFields.length > 0, - directives, - usesDirectives: Object.keys(directives).length > 0, - implementingTypes, - hasImplementingTypes: implementingTypes.length > 0 - }; -} diff --git a/packages/graphql-codegen-core/src/schema/transform-object.ts b/packages/graphql-codegen-core/src/schema/transform-object.ts deleted file mode 100644 index 60f048caf4e..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-object.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { GraphQLInputObjectType, GraphQLObjectType, GraphQLSchema } from 'graphql'; -import { resolveFields } from './transform-fields'; -import { Type } from '../types'; -import { debugLog } from '../debugging'; -import { getDirectives } from 'graphql-toolkit'; - -export function transformGraphQLObject( - schema: GraphQLSchema, - object: GraphQLObjectType | GraphQLInputObjectType -): Type { - debugLog(`[transformGraphQLObject] transforming type ${object.name}`); - const resolvedFields = resolveFields(schema, (object as any).getFields(), object); - const resolvedInterfaces = object instanceof GraphQLObjectType ? object.getInterfaces().map(inf => inf.name) : []; - const directives = getDirectives(schema, object); - - return { - name: object.name, - description: object.description || '', - fields: resolvedFields, - interfaces: resolvedInterfaces, - isInputType: object instanceof GraphQLInputObjectType, - hasFields: resolvedFields.length > 0, - hasInterfaces: resolvedInterfaces.length > 0, - directives, - usesDirectives: Object.keys(directives).length > 0 - }; -} diff --git a/packages/graphql-codegen-core/src/schema/transform-scalar.ts b/packages/graphql-codegen-core/src/schema/transform-scalar.ts deleted file mode 100644 index 6f8c146c3a4..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-scalar.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { GraphQLScalarType, GraphQLSchema } from 'graphql'; -import { Scalar } from '../types'; -import { debugLog } from '../debugging'; -import { getDirectives } from 'graphql-toolkit'; - -export function transformScalar(schema: GraphQLSchema, scalar: GraphQLScalarType): Scalar { - debugLog(`[transformInterface] transformed custom scalar ${scalar.name}`); - const directives = getDirectives(schema, scalar); - - return { - name: scalar.name, - description: scalar.description || '', - directives, - usesDirectives: Object.keys(directives).length > 0 - }; -} diff --git a/packages/graphql-codegen-core/src/schema/transform-union.ts b/packages/graphql-codegen-core/src/schema/transform-union.ts deleted file mode 100644 index 92fbcc7e535..00000000000 --- a/packages/graphql-codegen-core/src/schema/transform-union.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { GraphQLSchema, GraphQLUnionType } from 'graphql'; -import { Union } from '../types'; -import { debugLog } from '../debugging'; -import { getDirectives } from 'graphql-toolkit'; - -export function transformUnion(schema: GraphQLSchema, union: GraphQLUnionType): Union { - debugLog(`[transformUnion] transformed union ${union.name}`); - const directives = getDirectives(schema, union); - - return { - name: union.name, - description: union.description || '', - possibleTypes: union.getTypes().map(type => type.name), - directives, - usesDirectives: Object.keys(directives).length > 0 - }; -} diff --git a/packages/graphql-codegen-core/src/utils/get-field-def.ts b/packages/graphql-codegen-core/src/utils/get-field-def.ts deleted file mode 100644 index 7276f54f88e..00000000000 --- a/packages/graphql-codegen-core/src/utils/get-field-def.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GraphQLField, GraphQLType, FieldNode, isObjectType, isInterfaceType } from 'graphql'; - -export function getFieldDef(parentType: GraphQLType, fieldAST: FieldNode): GraphQLField { - const name = fieldAST.name.value; - - if (name === '__typename') { - return null; - } - - if (isObjectType(parentType) || isInterfaceType(parentType)) { - return parentType.getFields()[name]; - } - - return null; -} diff --git a/packages/graphql-codegen-core/src/utils/get-root.ts b/packages/graphql-codegen-core/src/utils/get-root.ts deleted file mode 100644 index ac04e869971..00000000000 --- a/packages/graphql-codegen-core/src/utils/get-root.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { GraphQLObjectType, GraphQLSchema, OperationDefinitionNode } from 'graphql'; - -export const getRoot = (schema: GraphQLSchema, operation: OperationDefinitionNode): GraphQLObjectType | void => { - switch (operation.operation) { - case 'query': - return schema.getQueryType(); - case 'mutation': - return schema.getMutationType(); - case 'subscription': - return schema.getSubscriptionType(); - default: - return null; - } -}; diff --git a/packages/graphql-codegen-core/src/utils/object-map-to-array.ts b/packages/graphql-codegen-core/src/utils/object-map-to-array.ts deleted file mode 100644 index d398aad1419..00000000000 --- a/packages/graphql-codegen-core/src/utils/object-map-to-array.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function objectMapToArray(objectMap: { [key: string]: T }): { key: string; value: T }[] { - return Object.keys(objectMap).map(key => ({ key, value: objectMap[key] })); -} diff --git a/packages/graphql-codegen-core/src/utils/parse.ts b/packages/graphql-codegen-core/src/utils/parse.ts deleted file mode 100644 index 19e82b7df03..00000000000 --- a/packages/graphql-codegen-core/src/utils/parse.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { parse as coreParse, Source } from 'graphql'; - -export function parse(source: Source | string) { - try { - return coreParse(source); - } catch (e) { - let error: Error; - - if (typeof source === 'string') { - error = new Error(`Parsing '${source.trim().substr(0, 25)}...' failed with: ${e.message}`); - } else { - error = new Error(`Parsing a document in '${source.name}' failed with: ${e.message}`); - } - - throw error; - } -} diff --git a/packages/graphql-codegen-core/tests/.gitignore b/packages/graphql-codegen-core/tests/.gitignore deleted file mode 100644 index ed9f9cc1285..00000000000 --- a/packages/graphql-codegen-core/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -coverage \ No newline at end of file diff --git a/packages/graphql-codegen-cli/tests/execute-plugin.spec.ts b/packages/graphql-codegen-core/tests/execute-plugin.spec.ts similarity index 92% rename from packages/graphql-codegen-cli/tests/execute-plugin.spec.ts rename to packages/graphql-codegen-core/tests/execute-plugin.spec.ts index bf08a0de679..21cd538e8ec 100644 --- a/packages/graphql-codegen-cli/tests/execute-plugin.spec.ts +++ b/packages/graphql-codegen-core/tests/execute-plugin.spec.ts @@ -1,20 +1,17 @@ import { parse } from 'graphql'; -import * as typescriptClientPlugin from 'graphql-codegen-typescript-client'; import { executePlugin } from '../src/execute-plugin'; +import * as typescriptClientPlugin from 'graphql-codegen-typescript-operations'; describe('executePlugin', () => { it('Should throw a detailed error message with source file and position for an invalid GraphQL document', () => { const options = { allPlugins: [ { - 'typescript-common': {} - }, - { - 'typescript-client': {} + typescript: {} } ], config: {}, - schema: parse(` + schema: parse(/* GraphQL */ ` type Character { id: ID! name: String! @@ -46,7 +43,7 @@ describe('executePlugin', () => { `) } ], - name: 'typescript-client', + name: 'typescript', outputFilename: 'a/random/path/output.ts' }; diff --git a/packages/graphql-codegen-core/tests/get-field-def.spec.ts b/packages/graphql-codegen-core/tests/get-field-def.spec.ts deleted file mode 100644 index 3dfe25f8795..00000000000 --- a/packages/graphql-codegen-core/tests/get-field-def.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { DocumentNode, GraphQLEnumType, GraphQLObjectType, GraphQLString, OperationDefinitionNode } from 'graphql'; -import gql from 'graphql-tag'; -import { getFieldDef } from '../src/utils/get-field-def'; - -describe('getFieldDef', () => { - it('should return the correct field when using GraphQLObjectType', () => { - const type = new GraphQLObjectType({ - name: 'myType', - fields: { - f1: { - type: GraphQLString, - name: 'f1' - } - } - }); - - const parsedDocuments = gql` - query { - f1 - } - `; - - const fieldNode = ((parsedDocuments as DocumentNode).definitions[0] as OperationDefinitionNode).selectionSet - .selections[0]; - const fieldDef = getFieldDef(type, fieldNode as any); - - expect(fieldDef.type).toBe(GraphQLString); - expect(fieldDef.name).toBe('f1'); - }); - - it('should return null when incorrect GraphQL object type provided', () => { - const type = new GraphQLEnumType({ - name: 'myType', - values: { - A: {}, - B: {} - } - }); - - const parsedDocuments = gql` - query { - f1 - } - `; - - const fieldNode = ((parsedDocuments as DocumentNode).definitions[0] as OperationDefinitionNode).selectionSet - .selections[0]; - const fieldDef = getFieldDef(type, fieldNode as any); - - expect(fieldDef).toBe(null); - }); -}); diff --git a/packages/graphql-codegen-core/tests/get-root.spec.ts b/packages/graphql-codegen-core/tests/get-root.spec.ts deleted file mode 100644 index b164a0214c1..00000000000 --- a/packages/graphql-codegen-core/tests/get-root.spec.ts +++ /dev/null @@ -1,66 +0,0 @@ -import gql from 'graphql-tag'; -import { GraphQLSchema, buildClientSchema } from 'graphql'; -import * as fs from 'fs'; -import { getRoot } from '../src/utils/get-root'; - -describe('getRoot', () => { - let schema: GraphQLSchema; - - beforeAll(() => { - schema = buildClientSchema(JSON.parse(fs.readFileSync('../../dev-test/githunt/schema.json').toString())); - }); - - it('should return root Query type', () => { - const query = gql` - query MyQuery { - currentUser { - login - avatar_url - } - } - `; - - const root = getRoot(schema, query.definitions[0]); - expect(String(root)).toBe('Query'); - }); - - it('should return root Mutation type', () => { - const query = gql` - mutation { - currentUser { - login - avatar_url - } - } - `; - - const root = getRoot(schema, query.definitions[0]); - expect(String(root)).toBe('Mutation'); - }); - - it('should return root Query type', () => { - const query = gql` - subscription { - currentUser { - login - avatar_url - } - } - `; - - const root = getRoot(schema, query.definitions[0]); - expect(String(root)).toBe('Subscription'); - }); - - it('should return null when invalid operation provided', () => { - const query = gql` - fragment f on User { - login - avatar_url - } - `; - - const root = getRoot(schema, query.definitions[0]); - expect(root).toBe(null); - }); -}); diff --git a/packages/graphql-codegen-core/tests/parse.spec.ts b/packages/graphql-codegen-core/tests/parse.spec.ts deleted file mode 100644 index a24a7c73e49..00000000000 --- a/packages/graphql-codegen-core/tests/parse.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Source } from 'graphql'; -import { parse } from '../src/utils/parse'; - -describe('parse', () => { - test('include file path', () => { - const query = ` - query Feed { - feed($type) { - id - } - } - `; - const filepath = '../path/to/file'; - const source = new Source(query, filepath); - - expect(() => { - parse(source); - }).toThrowError(new RegExp(filepath)); - }); - - test('include subset of a document', () => { - const query = ` - query Feed { - feed($type) { - id - } - } - `; - - expect(() => { - parse(query); - }).toThrow(/query Feed \{/); - }); -}); diff --git a/packages/graphql-codegen-core/tests/resolve-type-indicators.spec.ts b/packages/graphql-codegen-core/tests/resolve-type-indicators.spec.ts deleted file mode 100644 index efb78e6c097..00000000000 --- a/packages/graphql-codegen-core/tests/resolve-type-indicators.spec.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { buildASTSchema, parse } from 'graphql'; -import { resolveTypeIndicators } from '../src/schema/resolve-type-indicators'; - -describe('resolveTypeIndicators', () => { - function parseAndBuildSchema(str: string, typeName: string): T { - const schema = buildASTSchema( - parse(` - type Query { - test: Int - } - - ${str} - `) - ); - - return (schema.getTypeMap()[typeName] as unknown) as T; - } - - it('should return the correct indicators when using interface', () => { - const type = parseAndBuildSchema( - ` - interface A { - f: String - }`, - 'A' - ) as any; - - const indicators = resolveTypeIndicators(type); - - expect(indicators.isEnum).toBeFalsy(); - expect(indicators.isType).toBeFalsy(); - expect(indicators.isUnion).toBeFalsy(); - expect(indicators.isScalar).toBeFalsy(); - expect(indicators.isInputType).toBeFalsy(); - expect(indicators.isInterface).toBeTruthy(); - }); - - it('should return the correct indicators when using scalar', () => { - const type = parseAndBuildSchema( - ` - scalar A - `, - 'A' - ) as any; - - const indicators = resolveTypeIndicators(type); - - expect(indicators.isEnum).toBeFalsy(); - expect(indicators.isType).toBeFalsy(); - expect(indicators.isUnion).toBeFalsy(); - expect(indicators.isInputType).toBeFalsy(); - expect(indicators.isInterface).toBeFalsy(); - - expect(indicators.isScalar).toBeTruthy(); - }); - - it('should return the correct indicators when using enum', () => { - const type = parseAndBuildSchema( - ` - enum A { - V1, - V2 - } - `, - 'A' - ) as any; - - const indicators = resolveTypeIndicators(type); - - expect(indicators.isScalar).toBeFalsy(); - expect(indicators.isType).toBeFalsy(); - expect(indicators.isUnion).toBeFalsy(); - expect(indicators.isInputType).toBeFalsy(); - expect(indicators.isInterface).toBeFalsy(); - - expect(indicators.isEnum).toBeTruthy(); - }); - - it('should return the correct indicators when using input', () => { - const type = parseAndBuildSchema( - ` - input A { - f: String - } - `, - 'A' - ) as any; - - const indicators = resolveTypeIndicators(type); - - expect(indicators.isScalar).toBeFalsy(); - expect(indicators.isType).toBeFalsy(); - expect(indicators.isUnion).toBeFalsy(); - expect(indicators.isEnum).toBeFalsy(); - expect(indicators.isInterface).toBeFalsy(); - - expect(indicators.isInputType).toBeTruthy(); - }); - - it('should return the correct indicators when using type', () => { - const type = parseAndBuildSchema( - ` - type A { - f: String - } - `, - 'A' - ) as any; - - const indicators = resolveTypeIndicators(type); - - expect(indicators.isScalar).toBeFalsy(); - expect(indicators.isInputType).toBeFalsy(); - expect(indicators.isUnion).toBeFalsy(); - expect(indicators.isEnum).toBeFalsy(); - expect(indicators.isInterface).toBeFalsy(); - - expect(indicators.isType).toBeTruthy(); - }); - - it('should return the correct indicators when using union', () => { - const type = parseAndBuildSchema( - ` - type B { - f: String - } - - type C { - f: String - } - - union A = B | C - `, - 'A' - ) as any; - - const indicators = resolveTypeIndicators(type); - - expect(indicators.isScalar).toBeFalsy(); - expect(indicators.isInputType).toBeFalsy(); - expect(indicators.isType).toBeFalsy(); - expect(indicators.isEnum).toBeFalsy(); - expect(indicators.isInterface).toBeFalsy(); - - expect(indicators.isUnion).toBeTruthy(); - }); -}); diff --git a/packages/graphql-codegen-core/tests/resolve-type.spec.ts b/packages/graphql-codegen-core/tests/resolve-type.spec.ts deleted file mode 100644 index cdf6de6ca4a..00000000000 --- a/packages/graphql-codegen-core/tests/resolve-type.spec.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { buildASTSchema, parse } from 'graphql'; -import { resolveType } from '../src/schema/resolve-type'; - -describe('Resolve Type', function() { - function parseAndBuildSchema(str: string, typeName: string): T { - const schema = buildASTSchema( - parse(` - type Query { - test: Int - } - - ${str} - `) - ); - - return (schema.getTypeMap()[typeName] as any) as T; - } - - it('should return the correct booleans when the type is optional', () => { - const type = parseAndBuildSchema( - ` - type A { - f: String - }`, - 'A' - ); - - const field = type.getFields()['f'].type; - const result = resolveType(field); - - expect(result.raw).toBe('String'); - expect(result.isArray).toBeFalsy(); - expect(result.isRequired).toBeFalsy(); - expect(result.isNullableArray).toBeFalsy(); - }); - - it('should return the correct type name', () => { - const type = parseAndBuildSchema( - ` - type A { - f: String - }`, - 'A' - ); - - const field = type.getFields()['f'].type; - const result = resolveType(field); - - expect(result.raw).toBe('String'); - expect(result.name).toBe('String'); - }); - - it('should return the correct booleans when the type is required', () => { - const type = parseAndBuildSchema( - ` - type A { - f: String! - }`, - 'A' - ); - - const field = type.getFields()['f'].type; - const result = resolveType(field); - - expect(result.raw).toBe('String!'); - expect(result.isArray).toBeFalsy(); - expect(result.isRequired).toBeTruthy(); - expect(result.isNullableArray).toBeFalsy(); - }); - - it('should return the correct booleans when the type is required and array', () => { - const type = parseAndBuildSchema( - ` - type A { - f: [String]! - }`, - 'A' - ); - - const field = type.getFields()['f'].type; - const result = resolveType(field); - - expect(result.raw).toBe('[String]!'); - expect(result.isArray).toBeTruthy(); - expect(result.isRequired).toBeTruthy(); - expect(result.isNullableArray).toBeTruthy(); - }); - - it('should return the correct booleans when the type is not required and array', () => { - const type = parseAndBuildSchema( - ` - type A { - f: [String] - }`, - 'A' - ); - - const field = type.getFields()['f'].type; - const result = resolveType(field); - - expect(result.raw).toBe('[String]'); - expect(result.isArray).toBeTruthy(); - expect(result.isRequired).toBeFalsy(); - expect(result.isNullableArray).toBeTruthy(); - }); - - it('should return the correct booleans when the type is required and array with no nullables', () => { - const type = parseAndBuildSchema( - ` - type A { - f: [String!]! - }`, - 'A' - ); - - const field = type.getFields()['f'].type; - const result = resolveType(field); - - expect(result.raw).toBe('[String!]!'); - expect(result.isArray).toBeTruthy(); - expect(result.isRequired).toBeTruthy(); - expect(result.isNullableArray).toBeFalsy(); - }); -}); diff --git a/packages/graphql-codegen-core/tests/schema-to-template-context.spec.ts b/packages/graphql-codegen-core/tests/schema-to-template-context.spec.ts deleted file mode 100644 index fa655ffc4af..00000000000 --- a/packages/graphql-codegen-core/tests/schema-to-template-context.spec.ts +++ /dev/null @@ -1,286 +0,0 @@ -import { makeExecutableSchema } from 'graphql-tools'; -import { schemaToTemplateContext } from '../src/schema/schema-to-template-context'; -import { GraphQLSchema } from 'graphql'; - -describe('schemaToTemplateContext', () => { - it('should return the correct result when schema got directive', () => { - const typeDefs = ` - type Query { - test: String - } - - schema @app { - query: Query, - } - - directive @app on SCHEMA - `; - - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.directives).toEqual({ app: {} }); - }); - - it('should return the correct result when only Query defined', () => { - const typeDefs = ` - type Query { - test: String - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(1); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should pass GraphQL error when schema is not valid', () => { - const typeDefs = ` - type Query { - test: C - } - `; - - expect(() => { - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - schemaToTemplateContext(schema); - }).toThrow(); - }); - - it('should return the correct result when Query and Mutation defined', () => { - const typeDefs = ` - type Query { - test: String - } - - type Mutation { - test: String - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(2); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should return the correct result when custom type is defined', () => { - const typeDefs = ` - type Query { - test: CustomType - } - - type CustomType { - fieldA: String - fieldB: Int - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(2); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should return the correct result when using interface', () => { - const typeDefs = ` - type Query { - test: CustomType - } - - interface Base { - fieldA: String - } - - type CustomType implements Base { - fieldA: String - fieldB: Int - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(2); - expect(context.interfaces.length).toBe(1); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeTruthy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should return the correct result when using unions', () => { - const typeDefs = ` - type Query { - test: U - } - - type A { - test: String - } - - type B { - test: String - } - - union U = A | B - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(3); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(1); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeTruthy(); - }); - - it('should return the correct result when using enum', () => { - const typeDefs = ` - type Query { - test: E - } - - enum E { - A - B - C - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(1); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(1); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeTruthy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should return the correct result when using scalar', () => { - const typeDefs = ` - type Query { - test: Date - } - - scalar Date - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(1); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(0); - expect(context.scalars.length).toBe(1); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeFalsy(); - expect(context.hasScalars).toBeTruthy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should return the correct result when using input type', () => { - const typeDefs = ` - type Query { - test(argument: Input!): [Int] - } - - input Input { - f: String - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const context = schemaToTemplateContext(schema); - - expect(context.types.length).toBe(1); - expect(context.interfaces.length).toBe(0); - expect(context.enums.length).toBe(0); - expect(context.inputTypes.length).toBe(1); - expect(context.scalars.length).toBe(0); - expect(context.unions.length).toBe(0); - - expect(context.hasTypes).toBeTruthy(); - expect(context.hasInterfaces).toBeFalsy(); - expect(context.hasEnums).toBeFalsy(); - expect(context.hasInputTypes).toBeTruthy(); - expect(context.hasScalars).toBeFalsy(); - expect(context.hasUnions).toBeFalsy(); - }); - - it('should throw when invalid type is in schema', () => { - const typeDefs = ` - type Query { - test: String - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - - Object.assign(schema, { - _typeMap: { - C: {} - } - }); - - expect(() => schemaToTemplateContext(schema)).toThrow(); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-arguments.spec.ts b/packages/graphql-codegen-core/tests/transform-arguments.spec.ts deleted file mode 100644 index ebe099d268c..00000000000 --- a/packages/graphql-codegen-core/tests/transform-arguments.spec.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { buildASTSchema, GraphQLObjectType, parse } from 'graphql'; -import { resolveArguments } from '../src/schema/resolve-arguments'; - -describe('resolveArguments', () => { - function parseAndBuildSchema(str: string, typeName: string): T { - return (buildASTSchema( - parse(` - type Query { - test: Int - } - - ${str} - `) - ).getTypeMap()[typeName] as unknown) as T; - } - - it('should resolve correctly when there is one arguments', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: String): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(1); - }); - - it('should resolve correctly when there are more then one arguments', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: String, arg2: Int): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(2); - }); - - it('should resolve correctly when there are no arguments', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(0); - }); - - it('should resolve correctly when using argument of primitive scalar', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: String): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('arg'); - expect(result[0].type).toBe('String'); - expect(result[0].description).toBe(''); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should resolve correctly when using argument of array primitive scalar', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: [String]): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('arg'); - expect(result[0].type).toBe('String'); - expect(result[0].description).toBe(''); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should resolve correctly when using argument of required primitive scalar', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: String!): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('arg'); - expect(result[0].type).toBe('String'); - expect(result[0].description).toBe(''); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeTruthy(); - }); - - it('should resolve correctly when using argument of required array primitive scalar', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: [String]!): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('arg'); - expect(result[0].type).toBe('String'); - expect(result[0].description).toBe(''); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeTruthy(); - }); - - it('should resolve correctly when using argument of input type', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(arg: T): String - } - - input T { - t1: String - t2: String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('arg'); - expect(result[0].type).toBe('T'); - expect(result[0].description).toBe(''); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should resolve correctly when using arguments with default values', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(offset: Int = 0, limit: Int = 50): String - } - `, - 'A' - ); - - const args = parsed.getFields()['f1'].args; - const result = resolveArguments({} as any, args); - - expect(result.length).toBe(2); - - expect(result[0].name).toBe('offset'); - expect(result[0].type).toBe('Int'); - expect(result[0].hasDefaultValue).toBe(true); - expect(result[0].defaultValue).toBe(0); - - expect(result[1].name).toBe('limit'); - expect(result[1].type).toBe('Int'); - expect(result[1].hasDefaultValue).toBe(true); - expect(result[1].defaultValue).toBe(50); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-directives.spec.ts b/packages/graphql-codegen-core/tests/transform-directives.spec.ts deleted file mode 100644 index 7a9e16e22e7..00000000000 --- a/packages/graphql-codegen-core/tests/transform-directives.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { GraphQLSchema } from 'graphql'; -import { makeExecutableSchema } from 'graphql-tools'; -import { transformDirectives } from '../src/schema/transform-directives'; - -describe('transformDirectives', () => { - it('should return the correct transformation for default GraphQL directives', () => { - const typeDefs = ` - type Query { - test: String - } - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const directives = transformDirectives(schema, schema.getDirectives()); - - expect(directives.length).toBe(3); - expect(directives[0].name).toBe('skip'); - expect(directives[1].name).toBe('include'); - expect(directives[2].name).toBe('deprecated'); - }); - - it('should return the correct transformation with custom directive', () => { - const typeDefs = ` - type Query { - test: String - } - - directive @mydir on FIELD_DEFINITION - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const directives = transformDirectives(schema, schema.getDirectives()); - - expect(directives.length).toBe(4); - expect(directives[0].name).toBe('mydir'); - expect(directives[0].arguments.length).toBe(0); - expect(directives[0].description).toBe(''); - expect(directives[0].locations.length).toBe(1); - expect(directives[0].onFieldDefinition).toBe(true); - expect(directives[1].name).toBe('skip'); - expect(directives[2].name).toBe('include'); - expect(directives[3].name).toBe('deprecated'); - }); - it('should return the correct transformation with custom directive with args', () => { - const typeDefs = ` - type Query { - test: String - } - - directive @mydir(t: Int!) on FIELD_DEFINITION - `; - const schema = makeExecutableSchema({ typeDefs, resolvers: {}, allowUndefinedInResolve: true }) as GraphQLSchema; - const directives = transformDirectives(schema, schema.getDirectives()); - - expect(directives.length).toBe(4); - expect(directives[0].name).toBe('mydir'); - expect(directives[0].arguments.length).toBe(1); - expect(directives[0].arguments[0].name).toBe('t'); - expect(directives[0].arguments[0].type).toBe('Int'); - expect(directives[0].arguments[0].isArray).toBeFalsy(); - expect(directives[0].arguments[0].isRequired).toBeTruthy(); - expect(directives[0].description).toBe(''); - expect(directives[0].locations.length).toBe(1); - expect(directives[0].onFieldDefinition).toBe(true); - expect(directives[1].name).toBe('skip'); - expect(directives[2].name).toBe('include'); - expect(directives[3].name).toBe('deprecated'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-document.spec.ts b/packages/graphql-codegen-core/tests/transform-document.spec.ts deleted file mode 100644 index 3078c6891bd..00000000000 --- a/packages/graphql-codegen-core/tests/transform-document.spec.ts +++ /dev/null @@ -1,323 +0,0 @@ -import * as fs from 'fs'; -import gql from 'graphql-tag'; -import { GraphQLSchema, buildClientSchema } from 'graphql'; -import { transformDocument, transformDocumentsFiles } from '../src/operations/transform-document'; -import { SelectionSetFieldNode, SelectionSetFragmentSpread, SelectionSetInlineFragment } from '../src/types'; - -describe('transformDocument', () => { - let schema: GraphQLSchema; - - beforeAll(() => { - schema = buildClientSchema(JSON.parse(fs.readFileSync('../../dev-test/githunt/schema.json').toString())); - }); - - it('should handle multiple files correctly', () => { - const fragment = { - filePath: './a.fragment.graphql', - content: gql` - fragment MyFragment on User { - login - avatar_url - } - ` - }; - const document = { - filePath: './my.query.graphql', - content: gql` - query MyQuery { - currentUser { - login - avatar_url - } - } - ` - }; - - const result = transformDocumentsFiles(schema, [fragment, document]); - expect(result.operations[0].originalFile).toBe(document.filePath); - expect(result.fragments[0].originalFile).toBe(fragment.filePath); - }); - - it('should add the correct file path', () => { - const fakePath = './a.graphql'; - const doc = gql` - fragment MyFragment on User { - login - avatar_url - } - - query MyQuery { - currentUser { - login - avatar_url - } - } - `; - - const document = transformDocument(schema, doc, fakePath); - expect(document.operations[0].originalFile).toBe(fakePath); - expect(document.fragments[0].originalFile).toBe(fakePath); - }); - - it('should return correct result when using simple fragment', () => { - const fragment = gql` - fragment MyFragment on User { - login - avatar_url - } - `; - - const document = transformDocument(schema, fragment); - - expect(document.operations.length).toBe(0); - expect(document.fragments.length).toBe(1); - expect(document.fragments[0].name).toBe('MyFragment'); - expect(document.fragments[0].onType).toBe('User'); - expect(document.fragments[0].selectionSet.length).toBe(2); - const first = document.fragments[0].selectionSet[0] as SelectionSetFieldNode; - const second = document.fragments[0].selectionSet[1] as SelectionSetFieldNode; - expect(first.name).toBe('login'); - expect(second.name).toBe('avatar_url'); - expect(first.type).toBe('String'); - expect(second.type).toBe('String'); - expect(first.isRequired).toBeTruthy(); - expect(second.isRequired).toBeTruthy(); - expect(first.isArray).toBeFalsy(); - expect(second.isArray).toBeFalsy(); - expect(first.selectionSet.length).toBe(0); - expect(second.selectionSet.length).toBe(0); - }); - - it('should return correct result when using 2 levels fragment', () => { - const fragment = gql` - fragment RepoInfo on Entry { - createdAt - repository { - description - stargazers_count - open_issues_count - } - postedBy { - html_url - login - } - } - `; - - const document = transformDocument(schema, fragment); - - expect(document.operations.length).toBe(0); - expect(document.fragments.length).toBe(1); - expect(document.fragments[0].name).toBe('RepoInfo'); - expect(document.fragments[0].onType).toBe('Entry'); - expect(document.fragments[0].selectionSet.length).toBe(3); - expect((document.fragments[0].selectionSet[0] as SelectionSetFieldNode).selectionSet.length).toBe(0); - expect((document.fragments[0].selectionSet[1] as SelectionSetFieldNode).selectionSet.length).toBe(3); - expect((document.fragments[0].selectionSet[2] as SelectionSetFieldNode).selectionSet.length).toBe(2); - }); - - it('should return correct result when using __typename in selectionSet', () => { - const fragment = gql` - fragment RepoInfo on Entry { - createdAt - __typename - } - `; - - const document = transformDocument(schema, fragment); - - expect(document.operations.length).toBe(0); - expect(document.fragments.length).toBe(1); - expect(document.fragments[0].name).toBe('RepoInfo'); - expect(document.fragments[0].onType).toBe('Entry'); - expect(document.fragments[0].selectionSet.length).toBe(1); - }); - - it('should return correct result when using fragment with inline fragment', () => { - const fragment = gql` - fragment MyFragment on Entry { - createdAt - repository { - ... on Repository { - description - stargazers_count - open_issues_count - } - } - } - `; - - const document = transformDocument(schema, fragment); - - expect(document.operations.length).toBe(0); - expect(document.fragments.length).toBe(1); - expect(document.fragments[0].name).toBe('MyFragment'); - expect(document.fragments[0].onType).toBe('Entry'); - expect(document.fragments[0].selectionSet.length).toBe(2); - expect((document.fragments[0].selectionSet[1] as SelectionSetFieldNode).selectionSet.length).toBe(1); - expect( - ((document.fragments[0].selectionSet[1] as SelectionSetFieldNode).selectionSet[0] as SelectionSetInlineFragment) - .selectionSet.length - ).toBe(3); - expect( - ((document.fragments[0].selectionSet[1] as SelectionSetFieldNode).selectionSet[0] as SelectionSetInlineFragment) - .onType - ).toBe('Repository'); - }); - - it('should return correct result when using 2 fragments with fragment spread', () => { - const fragment = gql` - fragment MyFragment on Entry { - createdAt - repository { - ...RepoFragment - } - } - - fragment RepoFragment on Repository { - description - stargazers_count - open_issues_count - } - `; - - const document = transformDocument(schema, fragment); - - expect(document.operations.length).toBe(0); - expect(document.fragments.length).toBe(2); - expect(document.fragments[0].name).toBe('MyFragment'); - expect(document.fragments[0].onType).toBe('Entry'); - expect(document.fragments[1].name).toBe('RepoFragment'); - expect(document.fragments[1].onType).toBe('Repository'); - expect(document.fragments[0].selectionSet.length).toBe(2); - expect((document.fragments[0].selectionSet[1] as SelectionSetFieldNode).selectionSet.length).toBe(1); - expect( - ((document.fragments[0].selectionSet[1] as SelectionSetFieldNode).selectionSet[0] as SelectionSetFragmentSpread) - .fragmentName - ).toBe('RepoFragment'); - }); - - it('should return correct result when using simple query', () => { - const query = gql` - query MyQuery { - currentUser { - login - avatar_url - } - } - `; - - const document = transformDocument(schema, query); - - expect(document.operations.length).toBe(1); - expect(document.fragments.length).toBe(0); - expect(document.operations[0].hasVariables).toBeFalsy(); - expect(document.operations[0].name).toBe('MyQuery'); - expect(document.operations[0].variables.length).toBe(0); - expect(document.operations[0].operationType).toBe('query'); - expect(document.operations[0].selectionSet.length).toBe(1); - }); - - it('should return correct result when using anonymous query', () => { - const query = gql` - query { - currentUser { - login - avatar_url - } - } - `; - - const document = transformDocument(schema, query); - - expect(document.operations.length).toBe(1); - expect(document.fragments.length).toBe(0); - expect(document.operations[0].hasVariables).toBeFalsy(); - expect(document.operations[0].name).toBe('Anonymous_query_1'); - expect(document.operations[0].variables.length).toBe(0); - expect(document.operations[0].operationType).toBe('query'); - expect(document.operations[0].selectionSet.length).toBe(1); - }); - - it('should return correct result when using simple query with 2 levels', () => { - const query = gql` - query MyQuery { - entry { - id - postedBy { - login - html_url - } - createdAt - } - } - `; - - const document = transformDocument(schema, query); - - expect(document.operations.length).toBe(1); - expect(document.fragments.length).toBe(0); - expect(document.operations[0].hasVariables).toBeFalsy(); - expect(document.operations[0].name).toBe('MyQuery'); - expect(document.operations[0].variables.length).toBe(0); - expect(document.operations[0].operationType).toBe('query'); - expect(document.operations[0].selectionSet.length).toBe(1); - - const operation = document.operations[0].selectionSet[0] as SelectionSetFieldNode; - expect(operation.selectionSet.length).toBe(3); - const innerField0 = operation.selectionSet[0] as SelectionSetFieldNode; - const innerField1 = operation.selectionSet[1] as SelectionSetFieldNode; - const innerField2 = operation.selectionSet[2] as SelectionSetFieldNode; - expect(innerField0.name).toBe('id'); - expect(innerField1.name).toBe('postedBy'); - expect(innerField2.name).toBe('createdAt'); - }); - - it('should handle anonymous document correctly', () => { - const query = gql` - query { - entry { - id - postedBy { - login - html_url - } - createdAt - } - } - `; - - const document = transformDocument(schema, query); - - expect(document.operations[0].name).toBe('Anonymous_query_2'); - }); - - it('should handle anonymous document correctly when already used', () => { - const query = gql` - query { - entry { - id - postedBy { - login - html_url - } - createdAt - } - } - `; - - const query2 = gql` - query { - entry { - id - } - } - `; - - const document = transformDocument(schema, query); - const document2 = transformDocument(schema, query2); - - expect(document.operations[0].name).toBe('Anonymous_query_3'); - expect(document2.operations[0].name).toBe('Anonymous_query_4'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-enum.spec.ts b/packages/graphql-codegen-core/tests/transform-enum.spec.ts deleted file mode 100644 index 92b72cbf4f3..00000000000 --- a/packages/graphql-codegen-core/tests/transform-enum.spec.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { GraphQLEnumType } from 'graphql'; -import { transformGraphQLEnum } from '../src/schema/transform-enum'; -import { makeExecutableSchema } from 'graphql-tools'; - -describe('transformGraphQLEnum', () => { - it('should use the correct value of name', () => { - const gqlEnum = new GraphQLEnumType({ - name: 'name', - values: { - A: {} - } - }); - - const result = transformGraphQLEnum({} as any, gqlEnum); - - expect(result.name).toBe('name'); - expect(result.description).toBe(''); - }); - - it('should use the correct value of description', () => { - const gqlEnum = new GraphQLEnumType({ - name: 'name', - description: 'my enum', - values: { - A: {} - } - }); - - const result = transformGraphQLEnum({} as any, gqlEnum); - - expect(result.description).toBe('my enum'); - }); - - it('should use the correct value of value mapping', () => { - const gqlEnum = new GraphQLEnumType({ - name: 'name', - description: 'my enum', - values: { - A: {} - } - }); - - const result = transformGraphQLEnum({} as any, gqlEnum); - - expect(result.values instanceof Array).toBeTruthy(); - expect(result.values.length).toBe(1); - expect(result.values[0].description).toBe(''); - expect(result.values[0].name).toBe('A'); - expect(result.values[0].value).toBe('A'); - }); - - it('should use the correct value of value mapping with multiple values', () => { - const gqlEnum = new GraphQLEnumType({ - name: 'name', - description: 'my enum', - values: { - A: {}, - B: {}, - C: {} - } - }); - - const result = transformGraphQLEnum({} as any, gqlEnum); - - expect(result.values instanceof Array).toBeTruthy(); - expect(result.values.length).toBe(3); - }); - - it('should expose the correct directives and indicators for enum and enum values', () => { - const schema = makeExecutableSchema({ - typeDefs: ` - directive @lookup on ENUM - directive @lookupItem(id:Int! ,name: String!) on ENUM_VALUE - - enum Color @lookup { - RED @lookupItem(id:1 ,name: "Red") - GREEN @lookupItem(id:2 ,name: "Green") - } - - type Query { - dummy: String - } - `, - allowUndefinedInResolve: true - }); - - const enumType = schema.getType('Color') as GraphQLEnumType; - const result = transformGraphQLEnum(schema, enumType); - - expect(result.values instanceof Array).toBeTruthy(); - expect(result.values.length).toBe(2); - - // Enum - expect(result.directives).toBeDefined(); - expect(result.usesDirectives).toBeTruthy(); - expect(result.directives['lookup']).toBeDefined(); - - // values - expect(result.values[0].usesDirectives).toBeTruthy(); - expect(result.values[1].usesDirectives).toBeTruthy(); - - expect(result.values[0].directives['lookupItem']).toBeDefined(); - expect(result.values[1].directives['lookupItem']).toBeDefined(); - - expect(result.values[0].directives['lookupItem'].id).toBe(1); - expect(result.values[1].directives['lookupItem'].id).toBe(2); - - expect(result.values[0].directives['lookupItem'].name).toBe('Red'); - expect(result.values[1].directives['lookupItem'].name).toBe('Green'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-fields.spec.ts b/packages/graphql-codegen-core/tests/transform-fields.spec.ts deleted file mode 100644 index 215e38452d2..00000000000 --- a/packages/graphql-codegen-core/tests/transform-fields.spec.ts +++ /dev/null @@ -1,338 +0,0 @@ -import { buildASTSchema, GraphQLObjectType, parse } from 'graphql'; -import { resolveFields } from '../src/schema/transform-fields'; - -describe('resolveFields', () => { - function parseAndBuildSchema(str: string, typeName: string): T { - return (buildASTSchema( - parse(` - type Query { - test: Int - } - - ${str} - `) - ).getTypeMap()[typeName] as unknown) as T; - } - - it('should build the correct fields map when using type with single primitive scalar', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].description).toBe(''); - expect(result[0].isRequired).toBeFalsy(); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].arguments.length).toBe(0); - expect(result[0].hasArguments).toBeFalsy(); - }); - - it('should build the correct fields map when using type with single primitive scalar and args', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1(t: String): String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].description).toBe(''); - expect(result[0].isRequired).toBeFalsy(); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].arguments.length).toBe(1); - expect(result[0].hasArguments).toBeTruthy(); - }); - - it('should identify the correct number of fields', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: String - f2: Int - f3: Float - f4: ID - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(4); - expect(result[0].name).toBe('f1'); - expect(result[1].name).toBe('f2'); - expect(result[2].name).toBe('f3'); - expect(result[3].name).toBe('f4'); - }); - - it('should identify Array type', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: [String] - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('String'); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should identify required Array type', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: [String]! - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('String'); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeTruthy(); - }); - - it('should identify required Array type with inner required', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: [String!]! - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('String'); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeTruthy(); - }); - - it('should identify required Array type with inner required only', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: [String!] - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('String'); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should identify other custom types', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: B - } - - type B { - f: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should identify other custom types with required', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: B! - } - - type B { - f: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeTruthy(); - }); - - it('should identify other custom types with array', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: [B] - } - - type B { - f: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should identify other custom types with interfaces', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: B - } - - interface T { - f: String - } - - type B implements T { - f: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeFalsy(); - }); - - it('should identify other custom types with union', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: B - } - - union B = C | D - - type C { - t: String - } - - type D { - t: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeFalsy(); - }); - it('should identify other custom types with required union', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: B! - } - - union B = C | D - - type C { - t: String - } - - type D { - t: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeFalsy(); - expect(result[0].isRequired).toBeTruthy(); - }); - - it('should identify other custom types with union array', () => { - const parsed = parseAndBuildSchema( - ` - type A { - f1: [B] - } - - union B = C | D - - type C { - t: String - } - - type D { - t: String - } - `, - 'A' - ); - - const result = resolveFields({} as any, parsed.getFields(), null); - - expect(result.length).toBe(1); - expect(result[0].name).toBe('f1'); - expect(result[0].type).toBe('B'); - expect(result[0].isArray).toBeTruthy(); - expect(result[0].isRequired).toBeFalsy(); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-interface.spec.ts b/packages/graphql-codegen-core/tests/transform-interface.spec.ts deleted file mode 100644 index de925359bd4..00000000000 --- a/packages/graphql-codegen-core/tests/transform-interface.spec.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { GraphQLInterfaceType, GraphQLString } from 'graphql'; -import { transformInterface } from '../src/schema/transform-interface'; -import { makeExecutableSchema } from 'graphql-tools'; - -describe('transformInterface', () => { - const schema = makeExecutableSchema({ - typeDefs: [ - `interface A { - f: String - }`, - `type B implements A { - f: String - }` - ], - resolverValidationOptions: { - requireResolversForResolveType: false - } - }); - - it('should use the correct value of name', () => { - const gqlInterface = new GraphQLInterfaceType({ - name: 'name', - fields: { - test: { - type: GraphQLString - } - } - }); - - const result = transformInterface(schema, gqlInterface); - - expect(result.name).toBe('name'); - expect(result.description).toBe(''); - }); - - it('should use the correct value of description', () => { - const gqlInterface = new GraphQLInterfaceType({ - name: 'name', - description: 'Test', - fields: { - test: { - type: GraphQLString - } - } - }); - - const result = transformInterface(schema, gqlInterface); - - expect(result.description).toBe('Test'); - }); - - it('should use the correct value of fields', () => { - const gqlInterface = new GraphQLInterfaceType({ - name: 'name', - fields: { - test: { - description: 'Test', - type: GraphQLString - } - } - }); - - const result = transformInterface(schema, gqlInterface); - - expect(result.fields.length).toBe(1); - expect(result.fields[0].name).toBe('test'); - expect(result.fields[0].description).toBe('Test'); - expect(result.fields[0].type).toBe('String'); - expect(result.fields[0].isArray).toBeFalsy(); - expect(result.fields[0].isRequired).toBeFalsy(); - }); - - it('should use the correct value when implementing types', () => { - const result = transformInterface(schema, schema.getTypeMap()['A'] as GraphQLInterfaceType); - - expect(result.hasImplementingTypes).toBeTruthy(); - expect(result.implementingTypes.length).toBe(1); - expect(result.implementingTypes[0]).toBe('B'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-object.spec.ts b/packages/graphql-codegen-core/tests/transform-object.spec.ts deleted file mode 100644 index 0c8c04e8358..00000000000 --- a/packages/graphql-codegen-core/tests/transform-object.spec.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { GraphQLInputObjectType, GraphQLInterfaceType, GraphQLObjectType, GraphQLString } from 'graphql'; -import { transformGraphQLObject } from '../src/schema/transform-object'; - -describe('transformObject', () => { - it('should use the correct value of name', () => { - const gqlObj = new GraphQLObjectType({ - name: 'name', - fields: { - test: { - type: GraphQLString - } - } - }); - - const result = transformGraphQLObject({} as any, gqlObj); - - expect(result.name).toBe('name'); - expect(result.description).toBe(''); - }); - - it('should identify correctly type of Input', () => { - const gqlObj = new GraphQLInputObjectType({ - name: 'name', - fields: { - test: { - type: GraphQLString - } - } - }); - - const result = transformGraphQLObject({} as any, gqlObj); - expect(result.isInputType).toBeTruthy(); - }); - - it('should identify correctly type of regular Type', () => { - const gqlObj = new GraphQLObjectType({ - name: 'name', - fields: { - test: { - type: GraphQLString - } - } - }); - - const result = transformGraphQLObject({} as any, gqlObj); - expect(result.isInputType).toBeFalsy(); - }); - - it('should use the correct value of description', () => { - const gqlObj = new GraphQLObjectType({ - name: 'name', - description: 'Test', - fields: { - test: { - type: GraphQLString - } - } - }); - - const result = transformGraphQLObject({} as any, gqlObj); - - expect(result.description).toBe('Test'); - }); - - it('should use the correct value of fields', () => { - const gqlInterface = new GraphQLObjectType({ - name: 'name', - fields: { - test: { - description: 'Test', - type: GraphQLString - } - } - }); - - const result = transformGraphQLObject({} as any, gqlInterface); - - expect(result.fields.length).toBe(1); - expect(result.fields[0].name).toBe('test'); - expect(result.fields[0].description).toBe('Test'); - expect(result.fields[0].type).toBe('String'); - expect(result.fields[0].isArray).toBeFalsy(); - expect(result.fields[0].isRequired).toBeFalsy(); - }); - - it('should use the correct value of interfaces', () => { - const bookType = new GraphQLObjectType({ - name: 'Book', - fields: { - author: { type: GraphQLString } - } - }); - - const interface1 = new GraphQLInterfaceType({ - name: 'MyInterface', - fields: { - test: { - description: 'Test', - type: bookType - } - }, - resolveType: () => bookType - }); - - const gqlInterface = new GraphQLObjectType({ - name: 'name', - fields: { - test: { - description: 'Test', - type: bookType - } - }, - interfaces: [interface1] - }); - - const result = transformGraphQLObject({} as any, gqlInterface); - - expect(result.fields.length).toBe(1); - expect(result.interfaces.length).toBe(1); - expect(result.interfaces[0]).toBe('MyInterface'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-scalar.spec.ts b/packages/graphql-codegen-core/tests/transform-scalar.spec.ts deleted file mode 100644 index a8b084e56bc..00000000000 --- a/packages/graphql-codegen-core/tests/transform-scalar.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GraphQLScalarType } from 'graphql'; -import { transformScalar } from '../src/schema/transform-scalar'; - -describe('transformScalar', () => { - it('should use the correct value of name', () => { - const gqlObj = new GraphQLScalarType({ - name: 'name', - serialize: () => '' - }); - - const result = transformScalar({} as any, gqlObj); - - expect(result.name).toBe('name'); - expect(result.description).toBe(''); - }); - - it('should use the correct value of description', () => { - const gqlObj = new GraphQLScalarType({ - name: 'name', - description: 'MyScalar', - serialize: () => '' - }); - - const result = transformScalar({} as any, gqlObj); - - expect(result.name).toBe('name'); - expect(result.description).toBe('MyScalar'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-union.spec.ts b/packages/graphql-codegen-core/tests/transform-union.spec.ts deleted file mode 100644 index 71c16428d20..00000000000 --- a/packages/graphql-codegen-core/tests/transform-union.spec.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { GraphQLObjectType, GraphQLString, GraphQLUnionType } from 'graphql'; -import { transformUnion } from '../src/schema/transform-union'; - -describe('transformUnion', () => { - it('should use the correct value of name', () => { - const bookType = new GraphQLObjectType({ - name: 'Book', - fields: { - author: { type: GraphQLString } - } - }); - const gqlObj = new GraphQLUnionType({ - name: 'MyUnion', - types: [bookType], - resolveType: () => null - }); - - const result = transformUnion({} as any, gqlObj); - - expect(result.name).toBe('MyUnion'); - expect(result.description).toBe(''); - }); - - it('should use the correct value of description', () => { - const bookType = new GraphQLObjectType({ - name: 'Book', - fields: { - author: { type: GraphQLString } - } - }); - const gqlObj = new GraphQLUnionType({ - name: 'MyUnion', - description: 'test', - types: [bookType], - resolveType: () => null - }); - - const result = transformUnion({} as any, gqlObj); - - expect(result.description).toBe('test'); - }); - - it('should identify the correct available types for the union', () => { - const bookType = new GraphQLObjectType({ - name: 'Book', - fields: { - author: { type: GraphQLString } - } - }); - const gqlObj = new GraphQLUnionType({ - name: 'MyUnion', - description: 'test', - types: [bookType], - resolveType: () => null - }); - - const result = transformUnion({} as any, gqlObj); - - expect(result.possibleTypes.length).toBe(1); - expect(result.possibleTypes[0]).toBe('Book'); - }); -}); diff --git a/packages/graphql-codegen-core/tests/transform-variables.spec.ts b/packages/graphql-codegen-core/tests/transform-variables.spec.ts deleted file mode 100644 index 69be2002fb1..00000000000 --- a/packages/graphql-codegen-core/tests/transform-variables.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import gql from 'graphql-tag'; -import { GraphQLSchema, buildClientSchema } from 'graphql'; -import * as fs from 'fs'; -import { transformVariables } from '../src/operations/transform-variables'; - -describe('transformVariables', () => { - let schema: GraphQLSchema; - - beforeAll(() => { - schema = buildClientSchema(JSON.parse(fs.readFileSync('../../dev-test/githunt/schema.json').toString())); - }); - - it('should return empty array when where are no variables', () => { - const query = gql` - query MyQuery { - currentUser { - login - avatar_url - } - } - `; - - const variables = transformVariables(schema, query.definitions[0]); - expect(variables.length).toBe(0); - }); - - it('should return correct results when using query with one simple variable', () => { - const query = gql` - query MyQuery($test: String) { - currentUser { - login - avatar_url - } - } - `; - - const variables = transformVariables(schema, query.definitions[0]); - expect(variables.length).toBe(1); - expect(variables[0].name).toBe('test'); - expect(variables[0].type).toBe('String'); - expect(variables[0].isRequired).toBeFalsy(); - expect(variables[0].isArray).toBeFalsy(); - }); - - it('should return correct results when using query with more than one simple variable', () => { - const query = gql` - query MyQuery($test: String, $t2: Int!, $t3: [String]!) { - currentUser { - login - avatar_url - } - } - `; - - const variables = transformVariables(schema, query.definitions[0]); - expect(variables.length).toBe(3); - expect(variables[0].name).toBe('test'); - expect(variables[0].type).toBe('String'); - expect(variables[0].isRequired).toBeFalsy(); - expect(variables[0].isArray).toBeFalsy(); - expect(variables[1].name).toBe('t2'); - expect(variables[1].type).toBe('Int'); - expect(variables[1].isRequired).toBeTruthy(); - expect(variables[1].isArray).toBeFalsy(); - expect(variables[2].name).toBe('t3'); - expect(variables[2].type).toBe('String'); - expect(variables[2].isRequired).toBeTruthy(); - expect(variables[2].isArray).toBeTruthy(); - }); -}); diff --git a/packages/graphql-codegen-core/tsconfig.json b/packages/graphql-codegen-core/tsconfig.json index 74a1e323584..2ee75144f79 100644 --- a/packages/graphql-codegen-core/tsconfig.json +++ b/packages/graphql-codegen-core/tsconfig.json @@ -1,24 +1,23 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", - "lib": ["es6", "esnext", "es2015"], - "suppressImplicitAnyIndexErrors": true, + "module": "esnext", + "target": "es2018", + "lib": ["es6", "esnext", "es2015", "dom"], "moduleResolution": "node", "emitDecoratorMetadata": true, "sourceMap": true, "declaration": true, - "outDir": "./dist/", - "rootDir": "./src/", + "outDir": "./dist", + "rootDir": "./src", "noImplicitAny": true, "noImplicitThis": true, "alwaysStrict": true, "noImplicitReturns": true, "noUnusedLocals": true, - "noUnusedParameters": true, - "resolveJsonModule": true + "noUnusedParameters": false }, - "files": ["src/index.ts", "src/testing/index.ts"], + "files": ["src/index.ts"], "exclude": ["node_modules"] } diff --git a/packages/old-templates/graphql-codegen-apollo-angular-template/README.md b/packages/old-templates/graphql-codegen-apollo-angular-template/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-apollo-angular-template/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-apollo-angular-template/package.json b/packages/old-templates/graphql-codegen-apollo-angular-template/package.json deleted file mode 100644 index 20e4ae98fd3..00000000000 --- a/packages/old-templates/graphql-codegen-apollo-angular-template/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "graphql-codegen-apollo-angular-template", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-typescript-apollo-angular": "0.18.0", - "graphql-codegen-typescript-client": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" - } -} diff --git a/packages/old-templates/graphql-codegen-graphql-files-typescript-modules/README.md b/packages/old-templates/graphql-codegen-graphql-files-typescript-modules/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-graphql-files-typescript-modules/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-graphql-files-typescript-modules/package.json b/packages/old-templates/graphql-codegen-graphql-files-typescript-modules/package.json deleted file mode 100644 index 61e74a7d0fe..00000000000 --- a/packages/old-templates/graphql-codegen-graphql-files-typescript-modules/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "graphql-codegen-graphql-files-typescript-modules", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-typescript-common": "0.18.0", - "graphql-codegen-typescript-graphql-files-modules": "0.18.0" - } -} diff --git a/packages/old-templates/graphql-codegen-introspection-template/README.md b/packages/old-templates/graphql-codegen-introspection-template/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-introspection-template/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-introspection-template/package.json b/packages/old-templates/graphql-codegen-introspection-template/package.json deleted file mode 100644 index 8a483393a96..00000000000 --- a/packages/old-templates/graphql-codegen-introspection-template/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "graphql-codegen-introspection-template", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-introspection": "0.18.0" - } -} diff --git a/packages/old-templates/graphql-codegen-typescript-mongodb-template/README.md b/packages/old-templates/graphql-codegen-typescript-mongodb-template/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-mongodb-template/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-typescript-mongodb-template/package.json b/packages/old-templates/graphql-codegen-typescript-mongodb-template/package.json deleted file mode 100644 index 635b8535d87..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-mongodb-template/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "graphql-codegen-typescript-mongodb-template", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-typescript-common": "0.18.0", - "graphql-codegen-typescript-mongodb": "0.18.0", - "graphql-codegen-typescript-server": "0.18.0" - } -} diff --git a/packages/old-templates/graphql-codegen-typescript-react-apollo-template/README.md b/packages/old-templates/graphql-codegen-typescript-react-apollo-template/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-react-apollo-template/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-typescript-react-apollo-template/package.json b/packages/old-templates/graphql-codegen-typescript-react-apollo-template/package.json deleted file mode 100644 index 0bfaa3c0dcd..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-react-apollo-template/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "graphql-codegen-typescript-react-apollo-template", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-typescript-client": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0", - "graphql-codegen-typescript-react-apollo": "0.18.0" - } -} diff --git a/packages/old-templates/graphql-codegen-typescript-resolvers-template/README.md b/packages/old-templates/graphql-codegen-typescript-resolvers-template/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-resolvers-template/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-typescript-resolvers-template/package.json b/packages/old-templates/graphql-codegen-typescript-resolvers-template/package.json deleted file mode 100644 index 29a2ee9ff9b..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-resolvers-template/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "graphql-codegen-typescript-resolvers-template", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-typescript-common": "0.18.0", - "graphql-codegen-typescript-resolvers": "0.18.0", - "graphql-codegen-typescript-server": "0.18.0" - } -} diff --git a/packages/old-templates/graphql-codegen-typescript-template/README.md b/packages/old-templates/graphql-codegen-typescript-template/README.md deleted file mode 100644 index ab79dde56c3..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-template/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# DEPRECATED! - -This GraphQL Code Generator is now deprecated. It's still installing all requried packages to make it work, but note that in the future it will no longer work. - -Please migrate your GraphQL-Code-Generator usage from <=0.13 API to the latest. - -You can find a migration guide here: - -[https://graphql-code-generator.com/docs/migration/from-0-13](https://graphql-code-generator.com/docs/migration/from-0-13) diff --git a/packages/old-templates/graphql-codegen-typescript-template/package.json b/packages/old-templates/graphql-codegen-typescript-template/package.json deleted file mode 100644 index 6080b235440..00000000000 --- a/packages/old-templates/graphql-codegen-typescript-template/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "graphql-codegen-typescript-template", - "version": "0.18.0", - "dependencies": { - "graphql-codegen-typescript-client": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0", - "graphql-codegen-typescript-server": "0.18.0" - } -} diff --git a/packages/plugins/add/package.json b/packages/plugins/add/package.json index 7e992f86186..f69e7feaa4e 100644 --- a/packages/plugins/add/package.json +++ b/packages/plugins/add/package.json @@ -5,39 +5,21 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs" }, "dependencies": { - "graphql-codegen-core": "0.18.0" + "tslib": "1.9.3", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1" + "graphql": "14.1.1", + "typescript": "3.3.3333" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/add/src/index.ts b/packages/plugins/add/src/index.ts index a490044fc4d..038462feaba 100644 --- a/packages/plugins/add/src/index.ts +++ b/packages/plugins/add/src/index.ts @@ -1,5 +1,5 @@ import { GraphQLSchema } from 'graphql'; -import { PluginFunction, DocumentFile } from 'graphql-codegen-core'; +import { PluginFunction, DocumentFile } from 'graphql-codegen-plugin-helpers'; export type AddPluginConfig = string | string[]; diff --git a/packages/plugins/add/tsconfig.json b/packages/plugins/add/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/add/tsconfig.json +++ b/packages/plugins/add/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/flow-documents/package.json b/packages/plugins/flow-documents/package.json deleted file mode 100644 index d0aa42add9d..00000000000 --- a/packages/plugins/flow-documents/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "graphql-codegen-flow-documents", - "version": "0.18.0", - "description": "GraphQL Code Generator plugin for generating Flow types for GraphQL docuemnts (query/mutation/subscription/fragment)", - "repository": "git@github.com:dotansimha/graphql-code-generator.git", - "license": "MIT", - "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build", - "test": "codegen-templates-scripts test" - }, - "dependencies": { - "graphql-codegen-core": "0.18.0", - "graphql-codegen-flow": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0" - }, - "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "flow-bin": "0.94.0", - "flow-parser": "0.94.0", - "graphql": "14.1.1" - }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] - } -} diff --git a/packages/plugins/flow-documents/src/selection-set-to-object.ts b/packages/plugins/flow-documents/src/selection-set-to-object.ts deleted file mode 100644 index 7fe4866dbc5..00000000000 --- a/packages/plugins/flow-documents/src/selection-set-to-object.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { - SelectionSetNode, - Kind, - FieldNode, - FragmentSpreadNode, - InlineFragmentNode, - GraphQLNamedType, - isObjectType, - isUnionType, - isInterfaceType, - isEnumType -} from 'graphql'; -import { getBaseType, quoteIfNeeded } from './utils'; -import { FlowDocumentsVisitor } from './visitor'; -import { wrapTypeWithModifiers } from 'graphql-codegen-flow'; - -export class SelectionSetToObject { - private _primitiveFields: string[] = []; - private _primitiveAliasedFields: { alias: string; fieldName: string }[] = []; - private _linksFields: { alias: string; name: string; type: string; selectionSet: string }[] = []; - private _fragmentSpreads: string[] = []; - private _inlineFragments: { [onType: string]: string[] } = {}; - private _queriedForTypename = false; - - constructor( - private _visitorInstance: FlowDocumentsVisitor, - private _parentSchemaType: GraphQLNamedType, - private _selectionSet: SelectionSetNode - ) {} - - _collectField(field: FieldNode) { - if (field.name.value === '__typename') { - this._queriedForTypename = true; - - return; - } - - if (isObjectType(this._parentSchemaType) || isInterfaceType(this._parentSchemaType)) { - const schemaField = this._parentSchemaType.getFields()[field.name.value]; - const rawType = schemaField.type as any; - const baseType = getBaseType(rawType); - const typeName = baseType.name; - - if (this._visitorInstance.scalars[typeName] || isEnumType(baseType)) { - if (field.alias && field.alias.value) { - this._primitiveAliasedFields.push({ - fieldName: field.name.value, - alias: field.alias.value - }); - } else { - this._primitiveFields.push(field.name.value); - } - } else { - const selectionSetToObject = new SelectionSetToObject(this._visitorInstance, baseType, field.selectionSet); - - this._linksFields.push({ - alias: field.alias ? field.alias.value : null, - name: field.name.value, - type: typeName, - selectionSet: wrapTypeWithModifiers(selectionSetToObject.string, rawType) - }); - } - } - } - - _collectFragmentSpread(node: FragmentSpreadNode) { - this._fragmentSpreads.push(node.name.value); - } - - _collectInlineFragment(node: InlineFragmentNode) { - const onType = node.typeCondition.name.value; - const schemaType = this._visitorInstance.schema.getType(onType); - const selectionSet = new SelectionSetToObject(this._visitorInstance, schemaType, node.selectionSet); - - if (!this._inlineFragments[onType]) { - this._inlineFragments[onType] = []; - } - - this._inlineFragments[onType].push(selectionSet.string); - } - - get inlineFragmentsString(): string | null { - const allPossibleTypes = Object.keys(this._inlineFragments).map(typeName => - this._inlineFragments[typeName].join(' & ') - ); - - return allPossibleTypes.length === 0 ? null : `(${allPossibleTypes.join(' | ')})`; - } - - private _buildTypeNameField(): string | null { - const possibleTypes = []; - - if (!isUnionType(this._parentSchemaType) && !isInterfaceType(this._parentSchemaType)) { - possibleTypes.push(this._parentSchemaType.name); - } - - if (possibleTypes.length === 0) { - return null; - } - - return `{ __typename${this._queriedForTypename ? '' : '?'}: ${possibleTypes.map(t => `'${t}'`).join(' | ')} }`; - } - - get string(): string { - if (!this._selectionSet || !this._selectionSet.selections || this._selectionSet.selections.length === 0) { - return ''; - } - - const { selections } = this._selectionSet; - const useFlowExactObject: boolean = this._visitorInstance.parsedConfig.useFlowExactObjects; - const useFlowReadOnlyTypes: boolean = this._visitorInstance.parsedConfig.useFlowReadOnlyTypes; - - for (const selection of selections) { - switch (selection.kind) { - case Kind.FIELD: - this._collectField(selection as FieldNode); - break; - case Kind.FRAGMENT_SPREAD: - this._collectFragmentSpread(selection as FragmentSpreadNode); - break; - case Kind.INLINE_FRAGMENT: - this._collectInlineFragment(selection as InlineFragmentNode); - break; - } - } - - const typeName = this._visitorInstance.addTypename || this._queriedForTypename ? this._buildTypeNameField() : null; - const baseFields = this._primitiveFields.length - ? `$Pick<${this._visitorInstance.convertName(this._parentSchemaType.name)}, {${ - useFlowExactObject ? '|' : '' - } ${this._primitiveFields.map(fieldName => `${useFlowReadOnlyTypes ? '+' : ''}${fieldName}: *`).join(', ')} ${ - useFlowExactObject ? '|' : '' - }}>` - : null; - const linksFields = this._linksFields.length - ? `{${useFlowExactObject ? '|' : ''} ${this._linksFields - .map(field => `${useFlowReadOnlyTypes ? '+' : ''}${field.alias || field.name}: ${field.selectionSet}`) - .join(', ')} ${useFlowExactObject ? '|' : ''}}` - : null; - const aliasBaseFields = this._primitiveAliasedFields.length - ? `{${useFlowExactObject ? '|' : ''} ${this._primitiveAliasedFields - .map( - aliasedField => - `${useFlowReadOnlyTypes ? '+' : ''}${ - aliasedField.alias - }: $ElementType<${this._visitorInstance.convertName(this._parentSchemaType.name)}, '${ - aliasedField.fieldName - }'>` - ) - .join(', ')} ${useFlowExactObject ? '|' : ''}}` - : null; - const inlineFragments = this.inlineFragmentsString; - const fragmentSpreads = quoteIfNeeded( - this._fragmentSpreads.map(fragmentName => this._visitorInstance.getFragmentName(fragmentName)), - ' & ' - ); - const fieldsSet = [typeName, baseFields, aliasBaseFields, linksFields, fragmentSpreads, inlineFragments].filter( - f => f && f !== '' - ); - - return quoteIfNeeded(fieldsSet, ' & '); - } -} diff --git a/packages/plugins/flow-documents/src/utils.ts b/packages/plugins/flow-documents/src/utils.ts deleted file mode 100644 index f0eaa15ea49..00000000000 --- a/packages/plugins/flow-documents/src/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { GraphQLOutputType, GraphQLNonNull, GraphQLList, isListType, isNonNullType, GraphQLNamedType } from 'graphql'; - -function isWrapperType(t: GraphQLOutputType): t is GraphQLNonNull | GraphQLList { - return isListType(t) || isNonNullType(t); -} - -export function getBaseType(type: GraphQLOutputType): GraphQLNamedType { - if (isWrapperType(type)) { - return getBaseType(type.ofType); - } else { - return type; - } -} - -export function quoteIfNeeded(array: string[], joinWith = ' & '): string { - if (array.length === 0) { - return ''; - } else if (array.length === 1) { - return array[0]; - } else { - return `(${array.join(joinWith)})`; - } -} diff --git a/packages/plugins/flow-documents/src/visitor.ts b/packages/plugins/flow-documents/src/visitor.ts deleted file mode 100644 index a2a5f5d4863..00000000000 --- a/packages/plugins/flow-documents/src/visitor.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { GraphQLSchema, GraphQLObjectType, FragmentDefinitionNode, VariableDefinitionNode } from 'graphql'; -import { - BasicFlowVisitor, - OperationVariablesToObject, - DeclarationBlock, - DEFAULT_SCALARS, - toPascalCase -} from 'graphql-codegen-flow'; -import { ScalarsMap, FlowDocumentsPluginConfig } from './index'; -import { OperationDefinitionNode } from 'graphql'; -import { pascalCase } from 'change-case'; -import { SelectionSetToObject } from './selection-set-to-object'; -import { resolveExternalModuleAndFn } from 'graphql-codegen-plugin-helpers'; - -export interface ParsedDocumentsConfig { - scalars: ScalarsMap; - addTypename: boolean; - convert: (str: string) => string; - typesPrefix: string; - useFlowExactObjects: boolean; - useFlowReadOnlyTypes: boolean; -} - -export class FlowDocumentsVisitor implements BasicFlowVisitor { - private _parsedConfig: ParsedDocumentsConfig; - private _unnamedCounter = 1; - - constructor(private _schema: GraphQLSchema, pluginConfig: FlowDocumentsPluginConfig) { - this._parsedConfig = { - addTypename: !pluginConfig.skipTypename, - scalars: { ...DEFAULT_SCALARS, ...(pluginConfig.scalars || {}) }, - convert: pluginConfig.namingConvention ? resolveExternalModuleAndFn(pluginConfig.namingConvention) : toPascalCase, - typesPrefix: pluginConfig.typesPrefix || '', - useFlowExactObjects: pluginConfig.useFlowExactObjects || false, - useFlowReadOnlyTypes: pluginConfig.useFlowReadOnlyTypes || false - }; - } - - public convertName(name: any, addPrefix = true): string { - return (addPrefix ? this._parsedConfig.typesPrefix : '') + this._parsedConfig.convert(name); - } - - public getFragmentName(nodeName: string): string { - return this.convertName(nodeName + 'Fragment'); - } - - public get parsedConfig(): ParsedDocumentsConfig { - return this._parsedConfig; - } - - public get schema(): GraphQLSchema { - return this._schema; - } - - public get scalars(): ScalarsMap { - return this._parsedConfig.scalars; - } - - public get addTypename(): boolean { - return this._parsedConfig.addTypename; - } - - private handleAnonymouseOperation(name: string | null): string { - if (name) { - return this.convertName(name); - } - - return this.convertName(`Unnamed_${this._unnamedCounter++}_`); - } - - FragmentDefinition = (node: FragmentDefinitionNode): string => { - const fragmentRootType = this._schema.getType(node.typeCondition.name.value) as GraphQLObjectType; - const selectionSet = new SelectionSetToObject(this, fragmentRootType, node.selectionSet); - - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.getFragmentName(node.name.value)) - .withContent(selectionSet.string).string; - }; - - OperationDefinition = (node: OperationDefinitionNode): string => { - const name = this.handleAnonymouseOperation(node.name && node.name.value ? node.name.value : null); - const operationRootType = this._schema.getType(pascalCase(node.operation)) as GraphQLObjectType; - const selectionSet = new SelectionSetToObject(this, operationRootType, node.selectionSet); - const visitedOperationVariables = new OperationVariablesToObject( - this, - node.variableDefinitions - ); - - const operationResult = new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(name + pascalCase(node.operation))) - .withContent(selectionSet.string).string; - - const operationVariables = !visitedOperationVariables - ? null - : new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(name + pascalCase(node.operation) + 'Variables')) - .withBlock(visitedOperationVariables.string).string; - - return [operationVariables, operationResult].filter(r => r).join('\n\n'); - }; -} diff --git a/packages/plugins/flow-documents/.gitignore b/packages/plugins/flow-operations/.gitignore similarity index 100% rename from packages/plugins/flow-documents/.gitignore rename to packages/plugins/flow-operations/.gitignore diff --git a/packages/plugins/flow-documents/.npmignore b/packages/plugins/flow-operations/.npmignore similarity index 100% rename from packages/plugins/flow-documents/.npmignore rename to packages/plugins/flow-operations/.npmignore diff --git a/packages/plugins/flow-operations/package.json b/packages/plugins/flow-operations/package.json new file mode 100644 index 00000000000..713ec46692e --- /dev/null +++ b/packages/plugins/flow-operations/package.json @@ -0,0 +1,33 @@ +{ + "name": "graphql-codegen-flow-operations", + "version": "0.18.0", + "description": "GraphQL Code Generator plugin for generating Flow types for GraphQL operations (query/mutation/subscription/fragment)", + "repository": "git@github.com:dotansimha/graphql-code-generator.git", + "license": "MIT", + "scripts": { + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" + }, + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-flow": "0.18.0", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" + }, + "devDependencies": { + "flow-bin": "0.94.0", + "flow-parser": "0.94.0", + "graphql": "14.1.1", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "graphql-codegen-testing": "0.18.0" + }, + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" + } +} diff --git a/packages/plugins/flow-operations/src/flow-selection-set-to-object.ts b/packages/plugins/flow-operations/src/flow-selection-set-to-object.ts new file mode 100644 index 00000000000..0f1d8fe9be6 --- /dev/null +++ b/packages/plugins/flow-operations/src/flow-selection-set-to-object.ts @@ -0,0 +1,112 @@ +import { + SelectionSetToObject, + PrimitiveField, + PrimitiveAliasedFields, + LinkField, + ConvertNameFn, + ScalarsMap +} from 'graphql-codegen-visitor-plugin-common'; +import { + GraphQLObjectType, + GraphQLNonNull, + GraphQLList, + isNonNullType, + isListType, + GraphQLSchema, + GraphQLNamedType, + SelectionSetNode +} from 'graphql'; +import { FlowDocumentsParsedConfig } from './visitor'; + +export class FlowSelectionSetToObject extends SelectionSetToObject { + constructor( + _scalars: ScalarsMap, + _schema: GraphQLSchema, + _convertName: ConvertNameFn, + _addTypename: boolean, + private _visitorConfig: FlowDocumentsParsedConfig, + _parentSchemaType?: GraphQLNamedType, + _selectionSet?: SelectionSetNode + ) { + super(_scalars, _schema, _convertName, _addTypename, _parentSchemaType, _selectionSet); + } + + public createNext(parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode): SelectionSetToObject { + return new FlowSelectionSetToObject( + this._scalars, + this._schema, + this._convertName, + this._addTypename, + this._visitorConfig, + parentSchemaType, + selectionSet + ); + } + + protected buildPrimitiveFields(parentName: string, fields: PrimitiveField[]): string | null { + if (fields.length === 0) { + return null; + } + + const useFlowExactObject = this._visitorConfig.useFlowExactObjects; + const useFlowReadOnlyTypes = this._visitorConfig.useFlowReadOnlyTypes; + + return `$Pick<${parentName}, {${useFlowExactObject ? '|' : ''} ${fields + .map(fieldName => `${useFlowReadOnlyTypes ? '+' : ''}${fieldName}: *`) + .join(', ')} ${useFlowExactObject ? '|' : ''}}>`; + } + + protected buildLinkFields(fields: LinkField[]): string | null { + if (fields.length === 0) { + return null; + } + + const useFlowExactObject = this._visitorConfig.useFlowExactObjects; + const useFlowReadOnlyTypes = this._visitorConfig.useFlowReadOnlyTypes; + + return `{${useFlowExactObject ? '|' : ''} ${fields + .map(field => `${useFlowReadOnlyTypes ? '+' : ''}${field.alias || field.name}: ${field.selectionSet}`) + .join(', ')} ${useFlowExactObject ? '|' : ''}}`; + } + + protected buildAliasedPrimitiveFields(parentName: string, fields: PrimitiveAliasedFields[]): string | null { + if (fields.length === 0) { + return null; + } + + const useFlowExactObject = this._visitorConfig.useFlowExactObjects; + const useFlowReadOnlyTypes = this._visitorConfig.useFlowReadOnlyTypes; + + return `{${useFlowExactObject ? '|' : ''} ${fields + .map( + aliasedField => + `${useFlowReadOnlyTypes ? '+' : ''}${aliasedField.alias}: $ElementType<${parentName}, '${ + aliasedField.fieldName + }'>` + ) + .join(', ')} ${useFlowExactObject ? '|' : ''}}`; + } + + protected clearOptional(str: string): string { + if (str.startsWith('?')) { + return str.substring(1); + } + + return str; + } + + protected wrapTypeWithModifiers( + baseType: string, + type: GraphQLObjectType | GraphQLNonNull | GraphQLList + ): string { + if (isNonNullType(type)) { + return this.clearOptional(this.wrapTypeWithModifiers(baseType, type.ofType)); + } else if (isListType(type)) { + const innerType = this.wrapTypeWithModifiers(baseType, type.ofType); + + return `?Array<${innerType}>`; + } else { + return `?${baseType}`; + } + } +} diff --git a/packages/plugins/flow-documents/src/index.ts b/packages/plugins/flow-operations/src/index.ts similarity index 73% rename from packages/plugins/flow-documents/src/index.ts rename to packages/plugins/flow-operations/src/index.ts index be378502d54..e57ec9872b0 100644 --- a/packages/plugins/flow-documents/src/index.ts +++ b/packages/plugins/flow-operations/src/index.ts @@ -1,18 +1,13 @@ -import { PluginFunction, DocumentFile } from 'graphql-codegen-core'; +import { PluginFunction, DocumentFile } from 'graphql-codegen-plugin-helpers'; import { visit, concatAST, GraphQLSchema } from 'graphql'; import { FlowDocumentsVisitor } from './visitor'; +import { RawDocumentsConfig } from 'graphql-codegen-visitor-plugin-common'; -export interface FlowDocumentsPluginConfig { - scalars?: ScalarsMap; - skipTypename?: boolean; - namingConvention?: string; - typesPrefix?: string; +export interface FlowDocumentsPluginConfig extends RawDocumentsConfig { useFlowExactObjects?: boolean; useFlowReadOnlyTypes?: boolean; } -export type ScalarsMap = { [name: string]: string }; - export const plugin: PluginFunction = ( schema: GraphQLSchema, documents: DocumentFile[], diff --git a/packages/plugins/flow-operations/src/visitor.ts b/packages/plugins/flow-operations/src/visitor.ts new file mode 100644 index 00000000000..b4c3dd8ac69 --- /dev/null +++ b/packages/plugins/flow-operations/src/visitor.ts @@ -0,0 +1,28 @@ +import { GraphQLSchema } from 'graphql'; +import { FlowDocumentsPluginConfig } from './index'; +import { ParsedDocumentsConfig, BaseDocumentsVisitor } from 'graphql-codegen-visitor-plugin-common'; +import { FlowSelectionSetToObject } from './flow-selection-set-to-object'; +import { FlowOperationVariablesToObject } from 'graphql-codegen-flow'; + +export interface FlowDocumentsParsedConfig extends ParsedDocumentsConfig { + useFlowExactObjects: boolean; + useFlowReadOnlyTypes: boolean; +} + +export class FlowDocumentsVisitor extends BaseDocumentsVisitor { + constructor(schema: GraphQLSchema, config: FlowDocumentsPluginConfig) { + super( + config, + { + useFlowExactObjects: config.useFlowExactObjects || false, + useFlowReadOnlyTypes: config.useFlowReadOnlyTypes || false + } as FlowDocumentsParsedConfig, + schema + ); + + this.setSelectionSetHandler( + new FlowSelectionSetToObject(this.scalars, this.schema, this.convertName, this.config.addTypename, this.config) + ); + this.setVariablesTransformer(new FlowOperationVariablesToObject(this.scalars, this.convertName)); + } +} diff --git a/packages/plugins/flow-documents/tests/flow-documents.spec.ts b/packages/plugins/flow-operations/tests/flow-documents.spec.ts similarity index 91% rename from packages/plugins/flow-documents/tests/flow-documents.spec.ts rename to packages/plugins/flow-operations/tests/flow-documents.spec.ts index 3c3fb3bb51a..76c765c982d 100644 --- a/packages/plugins/flow-documents/tests/flow-documents.spec.ts +++ b/packages/plugins/flow-operations/tests/flow-documents.spec.ts @@ -1,80 +1,77 @@ -import 'graphql-codegen-core/dist/testing'; -import { parse, visit, buildClientSchema } from 'graphql'; +import 'graphql-codegen-testing'; +import { parse, visit, buildClientSchema, buildSchema } from 'graphql'; import { FlowDocumentsVisitor } from '../src/visitor'; -import { makeExecutableSchema } from 'graphql-tools'; import { validateFlow } from './validate-flow'; import { readFileSync } from 'fs'; -describe('Flow Documents Plugin', () => { +describe('Flow Operations Plugin', () => { const gitHuntSchema = buildClientSchema(JSON.parse(readFileSync('../../../dev-test/githunt/schema.json', 'utf-8'))); - const schema = makeExecutableSchema({ - typeDefs: ` - type User { - id: ID! - username: String! - email: String! - profile: Profile - role: Role - } - - type Profile { - age: Int - firstName: String! - } - - type Mutation { - login(username: String!, password: String!): User - } - - type Subscription { - userCreated: User - } - - interface Notifiction { - id: ID! - } - - type TextNotification implements Notifiction { - id: ID! - text: String! - } - - type ImageNotification implements Notifiction { - id: ID! - imageUrl: String! - metadata: ImageMetadata! - } - - type ImageMetadata { - createdBy: String! - } - - enum Role { - USER - ADMIN - } - - union MyUnion = User | Profile - - type Query { - me: User - unionTest: MyUnion - notifications: [Notifiction!]! - dummy: String - dummyNonNull: String! - dummyArray: [String] - dummyNonNullArray: [String]! - dummyNonNullArrayWithValues: [String!]! - dummyWithType: Profile - } - - schema { - query: Query - mutation: Mutation - subscription: Subscription - } - ` - }); + const schema = buildSchema(/* GraphQL */ ` + type User { + id: ID! + username: String! + email: String! + profile: Profile + role: Role + } + + type Profile { + age: Int + firstName: String! + } + + type Mutation { + login(username: String!, password: String!): User + } + + type Subscription { + userCreated: User + } + + interface Notifiction { + id: ID! + } + + type TextNotification implements Notifiction { + id: ID! + text: String! + } + + type ImageNotification implements Notifiction { + id: ID! + imageUrl: String! + metadata: ImageMetadata! + } + + type ImageMetadata { + createdBy: String! + } + + enum Role { + USER + ADMIN + } + + union MyUnion = User | Profile + + type Query { + me: User + unionTest: MyUnion + notifications: [Notifiction!]! + dummy: String + dummyNonNull: String! + dummyArray: [String] + dummyNonNullArray: [String]! + dummyNonNullArrayWithValues: [String!]! + dummyWithType: Profile + } + + schema { + query: Query + mutation: Mutation + subscription: Subscription + } + `); describe('Naming Convention & Types Prefix', () => { it('Should allow custom naming and point to the correct type', () => { @@ -129,9 +126,9 @@ describe('Flow Documents Plugin', () => { leave: new FlowDocumentsVisitor(schema, { typesPrefix: 'i', namingConvention: 'change-case#lowerCase' }) }); - expect(result.definitions[0]).toBeSimilarStringTo(`export type iinotificationsqueryvariables = {};`); + expect(result.definitions[0]).toBeSimilarStringTo(`export type inotificationsqueryvariables = {};`); expect(result.definitions[0]).toBeSimilarStringTo( - `export type iinotificationsquery = ({ __typename?: 'Query' } & { notifications: Array<($Pick & (({ __typename?: 'TextNotification' } & $Pick) | ({ __typename?: 'ImageNotification' } & $Pick & { metadata: ({ __typename?: 'ImageMetadata' } & $Pick) })))> });` + `export type inotificationsquery = ({ __typename?: 'Query' } & { notifications: Array<($Pick & (({ __typename?: 'TextNotification' } & $Pick) | ({ __typename?: 'ImageNotification' } & $Pick & { metadata: ({ __typename?: 'ImageMetadata' } & $Pick) })))> });` ); validateFlow(result.definitions[0]); }); diff --git a/packages/plugins/flow-documents/tests/validate-flow.ts b/packages/plugins/flow-operations/tests/validate-flow.ts similarity index 100% rename from packages/plugins/flow-documents/tests/validate-flow.ts rename to packages/plugins/flow-operations/tests/validate-flow.ts diff --git a/packages/plugins/typescript-client/tsconfig.json b/packages/plugins/flow-operations/tsconfig.json similarity index 87% rename from packages/plugins/typescript-client/tsconfig.json rename to packages/plugins/flow-operations/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/typescript-client/tsconfig.json +++ b/packages/plugins/flow-operations/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/flow-resolvers/package.json b/packages/plugins/flow-resolvers/package.json index 19f2c7f5bc4..c3d1a2d212b 100644 --- a/packages/plugins/flow-resolvers/package.json +++ b/packages/plugins/flow-resolvers/package.json @@ -5,44 +5,29 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build", - "test": "codegen-templates-scripts test" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "dependencies": { - "graphql-codegen-core": "0.18.0", + "tslib": "1.9.3", "graphql-codegen-flow": "0.18.0", + "graphql-codegen-visitor-plugin-common": "0.18.0", "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", + "graphql-codegen-testing": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", "flow-bin": "0.94.0", "flow-parser": "0.94.0", "graphql": "14.1.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/flow-resolvers/src/index.ts b/packages/plugins/flow-resolvers/src/index.ts index 15c6ee6d892..edb2a5312eb 100644 --- a/packages/plugins/flow-resolvers/src/index.ts +++ b/packages/plugins/flow-resolvers/src/index.ts @@ -1,17 +1,9 @@ -import { ScalarsMap } from 'graphql-codegen-flow'; -import { DocumentFile, PluginFunction } from 'graphql-codegen-core'; +import { RawResolversConfig } from 'graphql-codegen-visitor-plugin-common'; +import { DocumentFile, PluginFunction } from 'graphql-codegen-plugin-helpers'; import { isScalarType, parse, printSchema, visit, GraphQLSchema } from 'graphql'; import { FlowResolversVisitor } from './visitor'; -export interface FlowResolversPluginConfig { - contextType?: string; - mapping?: { [typeName: string]: string }; - scalars?: ScalarsMap; - namingConvention?: string; - typesPrefix?: string; - useFlowExactObjects?: boolean; - useFlowReadOnlyTypes?: boolean; -} +export interface FlowResolversPluginConfig extends RawResolversConfig {} export const plugin: PluginFunction = ( schema: GraphQLSchema, @@ -27,7 +19,7 @@ export const plugin: PluginFunction = ( imports.push('type GraphQLScalarTypeConfig'); } - const result = ` + const header = ` import { ${imports.join(', ')} } from 'graphql'; export type Resolver = ( @@ -68,20 +60,26 @@ export type TypeResolveFn = ( export type NextResolverFn = () => Promise; -export type DirectiveResolverFn = ( - next?: NextResolverFn, - source?: any, - args?: TArgs, - context?: TContext, +export type DirectiveResolverFn = ( + next?: NextResolverFn, + parent?: Parent, + args?: Args, + context?: Context, info?: GraphQLResolveInfo -) => TResult | Promise; +) => Result | Promise; `; const printedSchema = printSchema(schema); const astNode = parse(printedSchema); const visitor = new FlowResolversVisitor(config, schema); const visitorResult = visit(astNode, { leave: visitor }); - const rootResolver = visitor.rootResolver; + const { getRootResolver, getAllDirectiveResolvers, mappersImports } = visitor; - return [result, ...visitorResult.definitions.filter(d => typeof d === 'string'), rootResolver].join('\n'); + return [ + ...mappersImports, + header, + ...visitorResult.definitions.filter(d => typeof d === 'string'), + getRootResolver(), + getAllDirectiveResolvers() + ].join('\n'); }; diff --git a/packages/plugins/flow-resolvers/src/visitor.ts b/packages/plugins/flow-resolvers/src/visitor.ts index b07038d3473..8655399817f 100644 --- a/packages/plugins/flow-resolvers/src/visitor.ts +++ b/packages/plugins/flow-resolvers/src/visitor.ts @@ -1,206 +1,42 @@ -import { resolveExternalModuleAndFn } from 'graphql-codegen-plugin-helpers'; -import { - DEFAULT_SCALARS, - indent, - toPascalCase, - DeclarationBlock, - BasicFlowVisitor, - ScalarsMap, - OperationVariablesToObject, - getBaseTypeNode, - wrapAstTypeWithModifiers -} from 'graphql-codegen-flow'; -import { - ObjectTypeDefinitionNode, - FieldDefinitionNode, - NameNode, - ListTypeNode, - NonNullTypeNode, - NamedTypeNode, - InterfaceTypeDefinitionNode, - UnionTypeDefinitionNode, - ScalarTypeDefinitionNode, - DirectiveDefinitionNode, - InputValueDefinitionNode -} from 'graphql/language/ast'; +import { ListTypeNode, NamedTypeNode, NonNullTypeNode } from 'graphql/language/ast'; import { FlowResolversPluginConfig } from './index'; -import { GraphQLSchema, GraphQLObjectType, isOutputType } from 'graphql'; - -export interface ParsedConfig { - scalars: ScalarsMap; - convert: (str: string) => string; - typesPrefix: string; - contextType: string; - mapping: { [typeName: string]: string }; - useFlowExactObjects: boolean; - useFlowReadOnlyTypes: boolean; -} - -export class FlowResolversVisitor implements BasicFlowVisitor { - private _parsedConfig: ParsedConfig; - private _collectedResolvers: { [key: string]: string } = {}; - - constructor(pluginConfig: FlowResolversPluginConfig, private _schema: GraphQLSchema) { - this._parsedConfig = { - contextType: pluginConfig.contextType || 'any', - mapping: pluginConfig.mapping || {}, - scalars: { ...DEFAULT_SCALARS, ...(pluginConfig.scalars || {}) }, - convert: pluginConfig.namingConvention ? resolveExternalModuleAndFn(pluginConfig.namingConvention) : toPascalCase, - typesPrefix: pluginConfig.typesPrefix || '', - useFlowExactObjects: pluginConfig.useFlowExactObjects || false, - useFlowReadOnlyTypes: pluginConfig.useFlowReadOnlyTypes || false - }; +import { GraphQLSchema } from 'graphql'; +import * as autoBind from 'auto-bind'; +import { ParsedResolversConfig, BaseResolversVisitor } from 'graphql-codegen-visitor-plugin-common'; +import { FlowOperationVariablesToObject } from 'graphql-codegen-flow'; + +export interface ParsedFlorResolversConfig extends ParsedResolversConfig {} + +export class FlowResolversVisitor extends BaseResolversVisitor { + constructor(pluginConfig: FlowResolversPluginConfig, schema: GraphQLSchema) { + super(pluginConfig, null, schema); + autoBind(this); + this.setVariablesTransformer(new FlowOperationVariablesToObject(this.config.scalars, this.convertName)); } - get scalars(): ScalarsMap { - return this._parsedConfig.scalars; + protected formatRootResolver(schemaTypeName: string, resolverType: string): string { + return `${schemaTypeName}?: ${resolverType}<>,`; } - public convertName(name: any, addPrefix = true): string { - return (addPrefix ? this._parsedConfig.typesPrefix : '') + this._parsedConfig.convert(name); + protected buildMapperImport(source: string, types: string[]): string { + return `import { ${types.map(t => `type ${t}`).join(', ')} } from '${source}';`; } - public get rootResolver(): string { - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('interface') - .withName(this.convertName('ResolversRoot')) - .withBlock( - Object.keys(this._collectedResolvers) - .map(schemaTypeName => { - const resolverType = this._collectedResolvers[schemaTypeName]; - - return indent(`${schemaTypeName}?: ${resolverType}<>,`); - }) - .join('\n') - ).string; + ListType(node: ListTypeNode): string { + return `?${super.ListType(node)}`; } - Name = (node: NameNode): string => { - return node.value; - }; - - ListType = (node: ListTypeNode): string => { - const asString = (node.type as any) as string; - - return `?Array<${asString}>`; - }; - - NamedType = (node: NamedTypeNode): string => { - const asString = (node.name as any) as string; - const type = this._parsedConfig.scalars[asString] || this.convertName(asString); - - return `?${type}`; - }; - - NonNullType = (node: NonNullTypeNode): string => { - const asString = (node.type as any) as string; - - if (asString.charAt(0) === '?') { - return asString.substr(1); - } - - return asString; - }; - - FieldDefinition = (node: FieldDefinitionNode, key, parent) => { - const hasArguments = node.arguments && node.arguments.length > 0; - - return parentName => { - const original = parent[key]; - const realType = getBaseTypeNode(original.type).name.value; - const mappedType = this._parsedConfig.mapping[realType] - ? wrapAstTypeWithModifiers(this._parsedConfig.mapping[realType], original.type) - : node.type; - const subscriptionType = this._schema.getSubscriptionType(); - const isSubscriptionType = subscriptionType && subscriptionType.name === parentName; - - return indent( - `${node.name}?: ${isSubscriptionType ? 'SubscriptionResolver' : 'Resolver'}<${mappedType}, ParentType, Context${ - hasArguments ? `, ${this.convertName(parentName, true) + this.convertName(node.name, false) + 'Args'}` : '' - }>,` - ); - }; - }; - - ObjectTypeDefinition = (node: ObjectTypeDefinitionNode) => { - const name = this.convertName(node.name + 'Resolvers'); - const type = - this._parsedConfig.mapping[node.name as any] || - this._parsedConfig.scalars[node.name as any] || - this.convertName(node.name); - const block = new DeclarationBlock(this._parsedConfig) - .export() - .asKind('interface') - .withName(name, ``) - .withBlock(node.fields.map((f: any) => f(node.name)).join('\n')); - - this._collectedResolvers[node.name as any] = name; - - return block.string; - }; - - UnionTypeDefinition = (node: UnionTypeDefinitionNode): string => { - const name = this.convertName(node.name + 'Resolvers'); - const possibleTypes = node.types - .map(name => ((name as any) as string).replace('?', '')) - .map(f => `'${f}'`) - .join(' | '); - - this._collectedResolvers[node.name as any] = name; - - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('interface') - .withName(name, ``) - .withBlock(indent(`__resolveType: TypeResolveFn<${possibleTypes}>`)).string; - }; - - ScalarTypeDefinition = (node: ScalarTypeDefinitionNode): string => { - const baseName = this.convertName(node.name); - - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('interface') - .withName(this.convertName(node.name + 'ScalarConfig'), ` extends GraphQLScalarTypeConfig<${baseName}, any>`) - .withBlock(indent(`name: '${node.name}'`)).string; - }; - - DirectiveDefinition = (node: DirectiveDefinitionNode): string => { - const directiveName = this.convertName(node.name + 'DirectiveResolver'); - const hasArguments = node.arguments && node.arguments.length > 0; - const directiveArgs = hasArguments - ? new OperationVariablesToObject(this, node.arguments).string - : ''; - - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(directiveName, '') - .withContent(`DirectiveResolverFn`).string; - }; - - InterfaceTypeDefinition = (node: InterfaceTypeDefinitionNode): string => { - const name = this.convertName(node.name + 'Resolvers'); - const allTypesMap = this._schema.getTypeMap(); - const implementingTypes: string[] = []; + NamedType(node: NamedTypeNode): string { + return `?${super.NamedType(node)}`; + } - this._collectedResolvers[node.name as any] = name; + NonNullType(node: NonNullTypeNode): string { + const baseValue = super.NonNullType(node); - for (const graphqlType of Object.values(allTypesMap)) { - if (graphqlType instanceof GraphQLObjectType) { - const allInterfaces = graphqlType.getInterfaces(); - if (allInterfaces.find(int => int.name === ((node.name as any) as string))) { - implementingTypes.push(graphqlType.name); - } - } + if (baseValue.charAt(0) === '?') { + return baseValue.substr(1); } - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('interface') - .withName(name, ``) - .withBlock(indent(`__resolveType: TypeResolveFn<${implementingTypes.map(name => `'${name}'`).join(' | ')}>`)) - .string; - }; + return baseValue; + } } diff --git a/packages/plugins/flow-resolvers/tests/flow-resolvers.spec.ts b/packages/plugins/flow-resolvers/tests/flow-resolvers.spec.ts index 0d269f4ccd5..2929927c1fb 100644 --- a/packages/plugins/flow-resolvers/tests/flow-resolvers.spec.ts +++ b/packages/plugins/flow-resolvers/tests/flow-resolvers.spec.ts @@ -1,50 +1,48 @@ -import 'graphql-codegen-core/dist/testing'; -import { makeExecutableSchema } from 'graphql-tools'; +import 'graphql-codegen-testing'; +import { buildSchema } from 'graphql'; import { plugin } from '../src'; describe('Flow Resolvers Plugin', () => { - const schema = makeExecutableSchema({ - typeDefs: ` - type MyType { - foo: String! - otherType: MyOtherType - withArgs(arg: String, arg2: String!): String - } + const schema = buildSchema(/* GraphQL */ ` + type MyType { + foo: String! + otherType: MyOtherType + withArgs(arg: String, arg2: String!): String + } - type MyOtherType { - bar: String! - } + type MyOtherType { + bar: String! + } - type Query { - something: MyType! - } + type Query { + something: MyType! + } - type Subscription { - somethingChanged: MyOtherType - } + type Subscription { + somethingChanged: MyOtherType + } - interface Node { - id: ID! - } + interface Node { + id: ID! + } - type SomeNode implements Node { - id: ID! - } + type SomeNode implements Node { + id: ID! + } - union MyUnion = MyType | MyOtherType + union MyUnion = MyType | MyOtherType - scalar MyScalar + scalar MyScalar - directive @myDirective(arg: Int!, arg2: String!, arg3: Boolean!) on FIELD - ` - }); + directive @myDirective(arg: Int!, arg2: String!, arg3: Boolean!) on FIELD + `); it('Should generate basic type resolvers', () => { const result = plugin(schema, [], {}, { outputFile: '' }); expect(result).toBeSimilarStringTo(` - export type MyDirectiveDirectiveResolver = DirectiveResolverFn; + export type MyDirectiveDirectiveResolver = DirectiveResolverFn; export interface MyOtherTypeResolvers { bar?: Resolver, @@ -83,7 +81,7 @@ describe('Flow Resolvers Plugin', () => { }); it('Should generate the correct imports when schema has scalars', () => { - const result = plugin(makeExecutableSchema({ typeDefs: `scalar MyScalar` }), [], {}, { outputFile: '' }); + const result = plugin(buildSchema(`scalar MyScalar`), [], {}, { outputFile: '' }); expect(result).toBeSimilarStringTo( `import { type GraphQLResolveInfo, type GraphQLScalarTypeConfig } from 'graphql';` @@ -91,7 +89,7 @@ describe('Flow Resolvers Plugin', () => { }); it('Should generate the correct imports when schema has no scalars', () => { - const result = plugin(makeExecutableSchema({ typeDefs: `type MyType { f: String }` }), [], {}, { outputFile: '' }); + const result = plugin(buildSchema(`type MyType { f: String }`), [], {}, { outputFile: '' }); expect(result).not.toBeSimilarStringTo( `import { type GraphQLResolveInfo, type GraphQLScalarTypeConfig } from 'graphql';` @@ -103,7 +101,7 @@ describe('Flow Resolvers Plugin', () => { schema, [], { - mapping: { + mappers: { MyOtherType: 'MyCustomOtherType' } }, @@ -111,8 +109,8 @@ describe('Flow Resolvers Plugin', () => { ); expect(result).toBeSimilarStringTo(` - export type MyDirectiveDirectiveResolver = DirectiveResolverFn; + export type MyDirectiveDirectiveResolver = DirectiveResolverFn; export interface MyOtherTypeResolvers { bar?: Resolver, @@ -150,9 +148,61 @@ describe('Flow Resolvers Plugin', () => { `); }); + it('Should generate basic type resolvers with external mapping', () => { + const result = plugin( + schema, + [], + { + mappers: { + MyOtherType: './some-file#MyCustomOtherType' + } + }, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(`import { type MyCustomOtherType } from './some-file';`); + expect(result).toBeSimilarStringTo(` + export type MyDirectiveDirectiveResolver = DirectiveResolverFn; + + export interface MyOtherTypeResolvers { + bar?: Resolver, + } + + export interface MyScalarScalarConfig extends GraphQLScalarTypeConfig { + name: 'MyScalar' + } + + export interface MyTypeResolvers { + foo?: Resolver, + otherType?: Resolver, + withArgs?: Resolver, + } + + export interface MyUnionResolvers { + __resolveType: TypeResolveFn<'MyType' | 'MyOtherType'> + } + + export interface NodeResolvers { + __resolveType: TypeResolveFn<'SomeNode'> + } + + export interface QueryResolvers { + something?: Resolver, + } + + export interface SomeNodeResolvers { + id?: Resolver, + } + + export interface SubscriptionResolvers { + somethingChanged?: SubscriptionResolver, + } + `); + }); it('Should generate the correct resolver args type names when typesPrefix is specified', () => { const result = plugin( - makeExecutableSchema({ typeDefs: `type MyType { f(a: String): String }` }), + buildSchema(`type MyType { f(a: String): String }`), [], { typesPrefix: 'T' }, { outputFile: '' } diff --git a/packages/plugins/flow-resolvers/tsconfig.json b/packages/plugins/flow-resolvers/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/flow-resolvers/tsconfig.json +++ b/packages/plugins/flow-resolvers/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/flow/package.json b/packages/plugins/flow/package.json index f8cc140626d..1f3f1d2b419 100644 --- a/packages/plugins/flow/package.json +++ b/packages/plugins/flow/package.json @@ -5,43 +5,28 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build", - "test": "codegen-templates-scripts test" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "dependencies": { - "graphql-codegen-core": "0.18.0", + "tslib": "1.9.3", + "graphql-codegen-visitor-plugin-common": "0.18.0", "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", + "graphql-codegen-testing": "0.18.0", "flow-bin": "0.94.0", "flow-parser": "0.94.0", - "graphql": "14.1.1" + "graphql": "14.1.1", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/flow/src/flow-variables-to-object.ts b/packages/plugins/flow/src/flow-variables-to-object.ts new file mode 100644 index 00000000000..a56f9473668 --- /dev/null +++ b/packages/plugins/flow/src/flow-variables-to-object.ts @@ -0,0 +1,42 @@ +import { OperationVariablesToObject } from 'graphql-codegen-visitor-plugin-common'; +import { TypeNode, Kind } from 'graphql'; + +export class FlowOperationVariablesToObject extends OperationVariablesToObject { + private clearOptional(str: string): string { + if (str.startsWith('?')) { + return str.replace(/^\?(.*?)$/i, '$1'); + } + + return str; + } + + public wrapAstTypeWithModifiers(baseType: string, typeNode: TypeNode): string { + if (typeNode.kind === Kind.NON_NULL_TYPE) { + const type = this.wrapAstTypeWithModifiers(baseType, typeNode.type); + + return this.clearOptional(type); + } else if (typeNode.kind === Kind.LIST_TYPE) { + const innerType = this.wrapAstTypeWithModifiers(baseType, typeNode.type); + + return `?Array<${innerType}>`; + } else { + return `?${baseType}`; + } + } + + protected formatFieldString(fieldName: string, isNonNullType: boolean, hasDefaultValue: boolean): string { + if (hasDefaultValue || isNonNullType) { + return fieldName; + } else { + return `${fieldName}?`; + } + } + + protected formatTypeString(fieldType: string, isNonNullType: boolean, hasDefaultValue: boolean): string { + if (hasDefaultValue && !isNonNullType) { + return this.clearOptional(fieldType); + } + + return fieldType; + } +} diff --git a/packages/plugins/flow/src/index.ts b/packages/plugins/flow/src/index.ts index df6b29357ab..06ad4195b0a 100644 --- a/packages/plugins/flow/src/index.ts +++ b/packages/plugins/flow/src/index.ts @@ -1,20 +1,12 @@ -import { DocumentFile, PluginFunction } from 'graphql-codegen-core'; +import { DocumentFile, PluginFunction } from 'graphql-codegen-plugin-helpers'; import { parse, printSchema, visit, GraphQLSchema } from 'graphql'; import { FlowVisitor } from './visitor'; +import { RawTypesConfig } from 'graphql-codegen-visitor-plugin-common'; -export { DEFAULT_SCALARS } from './visitor'; -export * from './utils'; -export * from './variables-to-object'; export * from './visitor'; +export * from './flow-variables-to-object'; -export type ScalarsMap = { [name: string]: string }; -export type EnumValuesMap = { [key: string]: string }; - -export interface FlowPluginConfig { - scalars?: ScalarsMap; - enumValues?: EnumValuesMap; - namingConvention?: string; - typesPrefix?: string; +export interface FlowPluginConfig extends RawTypesConfig { useFlowExactObjects?: boolean; useFlowReadOnlyTypes?: boolean; } diff --git a/packages/plugins/flow/src/variables-to-object.ts b/packages/plugins/flow/src/variables-to-object.ts deleted file mode 100644 index f68832ce447..00000000000 --- a/packages/plugins/flow/src/variables-to-object.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Kind, TypeNode, VariableNode, NameNode, ValueNode } from 'graphql'; -import { indent, getBaseTypeNode, wrapAstTypeWithModifiers } from './utils'; -import { BasicFlowVisitor } from './visitor'; - -export class OperationVariablesToObject< - Visitor extends BasicFlowVisitor, - DefinitionType extends { - name?: NameNode; - variable?: VariableNode; - type: TypeNode; - defaultValue?: ValueNode; - } -> { - constructor(private _visitorInstance: Visitor, private _variablesNode: ReadonlyArray) {} - - getName(node: DefinitionType): string { - if (node.name) { - if (typeof node.name === 'string') { - return node.name; - } - - return node.name.value; - } else if (node.variable) { - return node.variable.name.value; - } - - return null; - } - - get string(): string { - if (!this._variablesNode || this._variablesNode.length === 0) { - return null; - } - - return this._variablesNode - .map(variable => { - const baseType = typeof variable.type === 'string' ? variable.type : getBaseTypeNode(variable.type); - const typeName = typeof baseType === 'string' ? baseType : baseType.name.value; - const typeValue = this._visitorInstance.scalars[typeName] - ? this._visitorInstance.scalars[typeName] - : this._visitorInstance.convertName(typeName, true); - - const fieldName = this.getName(variable); - const fieldType = wrapAstTypeWithModifiers(typeValue, variable.type); - - const hasDefaultValue = variable.defaultValue != null && typeof variable.defaultValue !== 'undefined'; - const isNonNullType = variable.type.kind === Kind.NON_NULL_TYPE; - - const formattedFieldString = hasDefaultValue || isNonNullType ? fieldName : `${fieldName}?`; - const formattedTypeString = hasDefaultValue && !isNonNullType ? fieldType.substring(1) : fieldType; - - return indent(`${formattedFieldString}: ${formattedTypeString}`); - }) - .join(',\n'); - - return ''; - } -} diff --git a/packages/plugins/flow/src/visitor.ts b/packages/plugins/flow/src/visitor.ts index 26ad7622b4d..06f012bac58 100644 --- a/packages/plugins/flow/src/visitor.ts +++ b/packages/plugins/flow/src/visitor.ts @@ -1,191 +1,104 @@ -import { resolveExternalModuleAndFn } from 'graphql-codegen-plugin-helpers'; -import { - EnumTypeDefinitionNode, - ScalarTypeDefinitionNode, - InputObjectTypeDefinitionNode, - InputValueDefinitionNode, - NamedTypeNode, - NameNode -} from 'graphql'; -import { DeclarationBlock, wrapWithSingleQuotes, indent, toPascalCase } from './utils'; -import { ScalarsMap, EnumValuesMap, FlowPluginConfig } from './index'; -import { OperationVariablesToObject } from './variables-to-object'; import { NonNullTypeNode, ListTypeNode, ObjectTypeDefinitionNode, FieldDefinitionNode, - InterfaceTypeDefinitionNode, - UnionTypeDefinitionNode, - DirectiveDefinitionNode -} from 'graphql/language/ast'; - -export const DEFAULT_SCALARS = { - ID: 'string', - String: 'string', - Boolean: 'boolean', - Int: 'number', - Float: 'number', - string: 'string', - number: 'number', - boolean: 'boolean' -}; -export interface ParsedConfig { - scalars: ScalarsMap; - enumValues: EnumValuesMap; - convert: (str: string) => string; - typesPrefix: string; + EnumTypeDefinitionNode, + ScalarTypeDefinitionNode, + NamedTypeNode +} from 'graphql'; +import { + BaseTypesVisitor, + DeclarationBlock, + wrapWithSingleQuotes, + indent, + ParsedTypesConfig +} from 'graphql-codegen-visitor-plugin-common'; +import * as autoBind from 'auto-bind'; +import { FlowPluginConfig } from './index'; +import { FlowOperationVariablesToObject } from './flow-variables-to-object'; + +export interface FlowPluginParsedConfig extends ParsedTypesConfig { useFlowExactObjects: boolean; useFlowReadOnlyTypes: boolean; } -export interface BasicFlowVisitor { - scalars: ScalarsMap; - convertName: (name: any, addPrefix: boolean) => string; -} - -export class FlowVisitor implements BasicFlowVisitor { - private _parsedConfig: ParsedConfig; - +export class FlowVisitor extends BaseTypesVisitor { constructor(pluginConfig: FlowPluginConfig) { - this._parsedConfig = { - scalars: { ...DEFAULT_SCALARS, ...(pluginConfig.scalars || {}) }, - enumValues: pluginConfig.enumValues || {}, - convert: pluginConfig.namingConvention ? resolveExternalModuleAndFn(pluginConfig.namingConvention) : toPascalCase, - typesPrefix: pluginConfig.typesPrefix || '', + super(pluginConfig, { useFlowExactObjects: pluginConfig.useFlowExactObjects || false, useFlowReadOnlyTypes: pluginConfig.useFlowReadOnlyTypes || false - }; - } - - convertName(name: any, addPrefix = true): string { - return (addPrefix ? this._parsedConfig.typesPrefix : '') + this._parsedConfig.convert(name); - } + } as FlowPluginParsedConfig); + autoBind(this); - get scalars(): ScalarsMap { - return this._parsedConfig.scalars; + this.setArgumentsTransformer(new FlowOperationVariablesToObject(this.config.scalars, this.convertName)); + this.setDeclarationBlockConfig({ + blockWrapper: this.config.useFlowExactObjects ? '|' : '' + }); } - ScalarTypeDefinition = (node: ScalarTypeDefinitionNode): string => { - return new DeclarationBlock(this._parsedConfig) + public ScalarTypeDefinition = (node: ScalarTypeDefinitionNode): string => { + return new DeclarationBlock(this._declarationBlockConfig) .export() .asKind('type') - .withName(this.convertName(node.name)) - .withContent(this._parsedConfig.scalars[(node.name as any) as string] || 'any').string; - }; - - DirectiveDefinition = (node: DirectiveDefinitionNode): string => { - return ''; - }; - - NamedType = (node: NamedTypeNode): string => { - const asString = (node.name as any) as string; - const type = this._parsedConfig.scalars[asString] || this.convertName(asString); - - return `?${type}`; + .withName(this.convertName(node)) + .withContent(this.scalars[(node.name as any) as string] || 'any').string; }; - ListType = (node: ListTypeNode): string => { - const asString = (node.type as any) as string; + NamedType(node: NamedTypeNode): string { + return `?${super.NamedType(node)}`; + } - return `?Array<${asString}>`; - }; + ListType(node: ListTypeNode): string { + return `?${super.ListType(node)}`; + } - NonNullType = (node: NonNullTypeNode): string => { - const asString = (node.type as any) as string; + NonNullType(node: NonNullTypeNode): string { + const baseValue = super.NonNullType(node); - if (asString.charAt(0) === '?') { - return asString.substr(1); + if (baseValue.charAt(0) === '?') { + return baseValue.substr(1); } - return asString; - }; - - Name = (node: NameNode): string => { - return node.value; - }; - - InputObjectTypeDefinition = (node: InputObjectTypeDefinitionNode): string => { - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(node.name)) - .withBlock(node.fields.join('\n')).string; - }; - - InputValueDefinition = (node: InputValueDefinitionNode): string => { - return indent(`${node.name}: ${node.type},`); - }; + return baseValue; + } - FieldDefinition = (node: FieldDefinitionNode): string => { + FieldDefinition(node: FieldDefinitionNode): string { const typeString = (node.type as any) as string; const namePostfix = typeString.charAt(0) === '?' ? '?' : ''; - return indent(`${node.name}${namePostfix}: ${typeString},`); - }; - - UnionTypeDefinition = (node: UnionTypeDefinitionNode): string => { - const possibleTypes = node.types.map(name => ((name as any) as string).replace('?', '')).join(' | '); - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(node.name)) - .withContent(possibleTypes).string; - }; + return indent(`${this.config.useFlowReadOnlyTypes ? '+' : ''}${node.name}${namePostfix}: ${typeString},`); + } - ObjectTypeDefinition = (node: ObjectTypeDefinitionNode, key, parent): string => { - const interfaces = - node.interfaces && node.interfaces.length > 0 - ? node.interfaces.map(name => ((name as any) as string).replace('?', '')).join(' & ') + ' & ' - : ''; + ObjectTypeDefinition(node: ObjectTypeDefinitionNode, key: number | string, parent: any): string { + return super.ObjectTypeDefinition( + { + ...node, + interfaces: + node.interfaces && node.interfaces.length > 0 + ? node.interfaces.map(name => ((name as any) as string).replace('?', '')) + : ([] as any) + }, + key, + parent + ); + } - const typeDefinition = new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(node.name)) - .withContent(interfaces) - .withBlock(node.fields.join('\n')).string; - - const original = parent[key]; - const fieldsWithArguments = original.fields.filter(field => field.arguments && field.arguments.length > 0); - const fieldsArguments = fieldsWithArguments.map(field => { - const name = original.name.value + this.convertName(field.name.value, false) + 'Args'; - const transformedArguments = new OperationVariablesToObject( - this, - field.arguments - ); - - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(name)) - .withBlock(transformedArguments.string).string; + EnumTypeDefinition(node: EnumTypeDefinitionNode): string { + const enumValuesName = this.convertName(node, { + suffix: 'Values' }); - return [typeDefinition, ...fieldsArguments].filter(f => f).join('\n\n'); - }; - - InterfaceTypeDefinition = (node: InterfaceTypeDefinitionNode): string => { - return new DeclarationBlock(this._parsedConfig) - .export() - .asKind('type') - .withName(this.convertName(node.name)) - .withBlock(node.fields.join('\n')).string; - }; - - EnumTypeDefinition = (node: EnumTypeDefinitionNode): string => { - const enumValuesName = `${node.name}Values`; - - const enumValues = new DeclarationBlock(this._parsedConfig) + const enumValues = new DeclarationBlock(this._declarationBlockConfig) .export() .asKind('const') - .withName(this.convertName(enumValuesName)) + .withName(enumValuesName) .withMethodCall('Object.freeze') .withBlock( node.values .map(enumOption => indent( - `${this.convertName(enumOption.name)}: ${wrapWithSingleQuotes( + `${this.convertName(enumOption)}: ${wrapWithSingleQuotes( this._parsedConfig.enumValues[(enumOption.name as any) as string] || enumOption.name )}` ) @@ -193,12 +106,12 @@ export class FlowVisitor implements BasicFlowVisitor { .join(', \n') ).string; - const enumType = new DeclarationBlock(this._parsedConfig) + const enumType = new DeclarationBlock(this._declarationBlockConfig) .export() .asKind('type') - .withName(this.convertName(node.name)) - .withContent(`$Values`).string; + .withName(this.convertName(node)) + .withContent(`$Values`).string; return [enumValues, enumType].join('\n\n'); - }; + } } diff --git a/packages/plugins/flow/tests/flow.spec.ts b/packages/plugins/flow/tests/flow.spec.ts index ff7535ecd73..750de5bfa64 100644 --- a/packages/plugins/flow/tests/flow.spec.ts +++ b/packages/plugins/flow/tests/flow.spec.ts @@ -1,11 +1,72 @@ -import 'graphql-codegen-core/dist/testing'; +import 'graphql-codegen-testing'; import { parse, visit } from 'graphql'; import { FlowVisitor } from '../src/visitor'; -import { validateFlow } from '../../flow-documents/tests/validate-flow'; +import { validateFlow } from '../../flow-operations/tests/validate-flow'; describe('Flow Plugin', () => { const SCALARS = {}; + describe('Output options', () => { + it('Should respect flow option useFlowExactObjects', () => { + const ast = parse(` + interface MyInterface { + foo: String + bar: String! + }`); + const result = visit(ast, { + leave: new FlowVisitor({ + useFlowExactObjects: true + }) + }); + + expect(result.definitions[0]).toBeSimilarStringTo(` + export type MyInterface = {| + foo?: ?string, + bar: string, + |}; + `); + validateFlow(result.definitions[0]); + }); + + it('Should respect flow option useFlowReadOnlyTypes', () => { + const ast = parse(/* GraphQL */ ` + interface MyInterface { + foo: String + bar: String! + } + + enum MyEnum { + A + B + C + } + `); + const result = visit(ast, { + leave: new FlowVisitor({ + useFlowReadOnlyTypes: true + }) + }); + + expect(result.definitions[0]).toBeSimilarStringTo(` + export type MyInterface = { + +foo?: ?string, + +bar: string, + }; + `); + expect(result.definitions[1]).toBeSimilarStringTo(` + export const MyEnumValues = Object.freeze({ + A: 'A', + B: 'B', + C: 'C' + }); + export type MyEnum = $Values; + `); + + validateFlow(result.definitions[0]); + validateFlow(result.definitions[1]); + }); + }); + describe('Naming Convention & Types Prefix', () => { it('Should use custom namingConvention for type name and args typename', () => { const ast = parse(`type MyType { foo(a: String!, b: String, c: [String], d: [Int!]!): String }`); diff --git a/packages/plugins/flow/tsconfig.json b/packages/plugins/flow/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/flow/tsconfig.json +++ b/packages/plugins/flow/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/fragment-matcher/package.json b/packages/plugins/fragment-matcher/package.json index b655b5cde5f..2e0e08582f4 100644 --- a/packages/plugins/fragment-matcher/package.json +++ b/packages/plugins/fragment-matcher/package.json @@ -5,42 +5,27 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "test": "codegen-templates-scripts test", - "build": "codegen-templates-scripts build", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" + "dependencies": { + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", + "tslib": "1.9.3", "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", "graphql-tag": "2.10.1" }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" + }, + "sideEffects": false, "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/fragment-matcher/src/index.ts b/packages/plugins/fragment-matcher/src/index.ts index 0c341bb52aa..83f411292c0 100644 --- a/packages/plugins/fragment-matcher/src/index.ts +++ b/packages/plugins/fragment-matcher/src/index.ts @@ -1,5 +1,5 @@ import { GraphQLSchema, parse, execute } from 'graphql'; -import { PluginFunction, PluginValidateFn, DocumentFile } from 'graphql-codegen-core'; +import { PluginFunction, PluginValidateFn, DocumentFile } from 'graphql-codegen-plugin-helpers'; import { extname } from 'path'; interface IntrospectionResultData { diff --git a/packages/plugins/fragment-matcher/tests/plugin.spec.ts b/packages/plugins/fragment-matcher/tests/plugin.spec.ts index 1165fa384e7..e725b1bcca2 100644 --- a/packages/plugins/fragment-matcher/tests/plugin.spec.ts +++ b/packages/plugins/fragment-matcher/tests/plugin.spec.ts @@ -1,7 +1,7 @@ -import 'graphql-codegen-core/dist/testing'; +import 'graphql-codegen-testing'; import { buildASTSchema } from 'graphql'; import gql from 'graphql-tag'; -import { plugin, validate } from '../dist'; +import { plugin, validate } from '../src'; const schema = buildASTSchema(gql` type Character { diff --git a/packages/plugins/fragment-matcher/tsconfig.json b/packages/plugins/fragment-matcher/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/fragment-matcher/tsconfig.json +++ b/packages/plugins/fragment-matcher/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/introspection/package.json b/packages/plugins/introspection/package.json index 1e1d8c774b6..e684b27709f 100644 --- a/packages/plugins/introspection/package.json +++ b/packages/plugins/introspection/package.json @@ -5,41 +5,28 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "test": "codegen-templates-scripts test", - "build": "codegen-templates-scripts build", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0" + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "graphql-tag": "2.10.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/introspection/src/index.ts b/packages/plugins/introspection/src/index.ts index c5f4e0bad94..31dc77874c9 100644 --- a/packages/plugins/introspection/src/index.ts +++ b/packages/plugins/introspection/src/index.ts @@ -1,6 +1,5 @@ import { GraphQLSchema, introspectionFromSchema } from 'graphql'; -import { PluginFunction, PluginValidateFn } from 'graphql-codegen-core'; -import { DocumentFile } from '../../../graphql-codegen-core/src'; +import { PluginFunction, PluginValidateFn, DocumentFile } from 'graphql-codegen-plugin-helpers'; import { extname } from 'path'; export const plugin: PluginFunction = async (schema: GraphQLSchema): Promise => { diff --git a/packages/plugins/introspection/tests/introspection.spec.ts b/packages/plugins/introspection/tests/introspection.spec.ts index 88bfa7ada47..799c4147896 100644 --- a/packages/plugins/introspection/tests/introspection.spec.ts +++ b/packages/plugins/introspection/tests/introspection.spec.ts @@ -1,22 +1,19 @@ -import { makeExecutableSchema } from 'graphql-tools'; -import { introspectionFromSchema } from 'graphql'; -import { plugin } from '../dist'; +import { buildSchema, introspectionFromSchema } from 'graphql'; +import { plugin } from '../src'; describe('Introspection template', () => { it('should output a JSON file', async () => { - const schema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest: String - } - - schema { - query: Query - } - ` - }); + const schema = buildSchema(/* GraphQL */ ` + type Query { + fieldTest: String + } - const content = await plugin(schema); + schema { + query: Query + } + `); + + const content = await plugin(schema, [], {}, { outputFile: '' }); const introspection = JSON.stringify(introspectionFromSchema(schema, { descriptions: true })); expect(introspection).toEqual(content); }); diff --git a/packages/plugins/introspection/tsconfig.json b/packages/plugins/introspection/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/introspection/tsconfig.json +++ b/packages/plugins/introspection/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/schema-ast/package.json b/packages/plugins/schema-ast/package.json index 50bfb409b9b..69c7a4a0e24 100644 --- a/packages/plugins/schema-ast/package.json +++ b/packages/plugins/schema-ast/package.json @@ -5,41 +5,29 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", + "tslib": "1.9.3", "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0" + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "graphql-tag": "2.10.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/schema-ast/src/index.ts b/packages/plugins/schema-ast/src/index.ts index c661edc2cb6..012e23d8f03 100644 --- a/packages/plugins/schema-ast/src/index.ts +++ b/packages/plugins/schema-ast/src/index.ts @@ -1,5 +1,5 @@ import { GraphQLSchema, printSchema } from 'graphql'; -import { DocumentFile, PluginFunction, PluginValidateFn, Types } from 'graphql-codegen-core'; +import { DocumentFile, PluginFunction, PluginValidateFn, Types } from 'graphql-codegen-plugin-helpers'; import { extname } from 'path'; export const plugin: PluginFunction = async (schema: GraphQLSchema): Promise => { diff --git a/packages/plugins/schema-ast/tests/schema-ast.spec.ts b/packages/plugins/schema-ast/tests/schema-ast.spec.ts index d0f9f883bd6..054327fe986 100644 --- a/packages/plugins/schema-ast/tests/schema-ast.spec.ts +++ b/packages/plugins/schema-ast/tests/schema-ast.spec.ts @@ -1,5 +1,5 @@ import { validate } from '../src/index'; -import { Types } from 'graphql-codegen-core'; +import { Types } from 'graphql-codegen-plugin-helpers'; const SHOULD_THROW_ERROR = 'SHOULD_THROW_ERROR'; diff --git a/packages/plugins/schema-ast/tsconfig.json b/packages/plugins/schema-ast/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/schema-ast/tsconfig.json +++ b/packages/plugins/schema-ast/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/time/package.json b/packages/plugins/time/package.json index 5273599eb65..b57506c3f82 100644 --- a/packages/plugins/time/package.json +++ b/packages/plugins/time/package.json @@ -5,40 +5,25 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs" }, "dependencies": { + "graphql-codegen-plugin-helpers": "0.18.0", "moment": "2.24.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0" + "typescript": "3.3.3333", + "graphql-tag": "2.10.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/time/src/index.ts b/packages/plugins/time/src/index.ts index 7579a4cfe8a..fda59969569 100644 --- a/packages/plugins/time/src/index.ts +++ b/packages/plugins/time/src/index.ts @@ -1,6 +1,6 @@ import { GraphQLSchema } from 'graphql'; -import { PluginFunction, DocumentFile } from 'graphql-codegen-core'; -import * as moment from 'moment'; +import { PluginFunction, DocumentFile } from 'graphql-codegen-plugin-helpers'; +import moment from 'moment'; export type TimePluginConfig = string | { format: string; message: string }; diff --git a/packages/plugins/time/tsconfig.json b/packages/plugins/time/tsconfig.json index 782f215152c..349f9007cf7 100644 --- a/packages/plugins/time/tsconfig.json +++ b/packages/plugins/time/tsconfig.json @@ -1,8 +1,10 @@ { "compilerOptions": { + "importHelpers": true, + "allowSyntheticDefaultImports": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/typescript-apollo-angular/package.json b/packages/plugins/typescript-apollo-angular/package.json index ce116b48218..37cd37a0b4a 100644 --- a/packages/plugins/typescript-apollo-angular/package.json +++ b/packages/plugins/typescript-apollo-angular/package.json @@ -5,47 +5,31 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "peerDependencies": { "graphql-tag": "^2.0.0" }, "dependencies": { - "dependency-graph": "0.8.0", - "graphql-codegen-plugin-helpers": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" + "tslib": "1.9.3", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" + "graphql-codegen-testing": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "flow-bin": "0.94.0", + "flow-parser": "0.94.0", + "graphql": "14.1.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/directives.ts b/packages/plugins/typescript-apollo-angular/src/helpers/directives.ts deleted file mode 100644 index 909b2560c34..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/directives.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Operation } from 'graphql-codegen-core'; - -function R_DEF(directive: string) { - return new RegExp(`\\s+\\@${directive}\\([^)]+\\)`, 'gm'); -} - -// checks if operation has a directive -export function operationHasDirective(operation: Operation, directive: string) { - return operation.document.includes(`@${directive}`); -} - -// removes a directive from string -export function removeDirective(document: string, directive: string) { - if (operationHasDirective({ document } as Operation, directive)) { - return document.replace(R_DEF(directive), ''); - } - - return document; -} - -export function removeDirectives(document: string, directives: string[]) { - return directives.reduce((doc, directive) => removeDirective(doc, directive), document); -} - -// tries to find a directive and extract it's arguments -export function extractDirective(operation: Operation, directive: string) { - const doc: string = operation.document; - const directives = doc.match(R_DEF(directive)); - - if (directives.length > 1) { - throw new Error(`The ${directive} directive used multiple times in '${operation.name}' operation`); - } - - return directives[0]; -} diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/generate-fragments.ts b/packages/plugins/typescript-apollo-angular/src/helpers/generate-fragments.ts deleted file mode 100644 index b24f1d3e68f..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/generate-fragments.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { DepGraph } from 'dependency-graph'; -import { gql, extractFragments } from './gql'; -import { toFragmentName } from './to-fragment-name'; - -export const generateFragments = convert => (fragments: any[], options: any): string => { - const cachedFragments: Record = {}; - - if (!fragments) { - return ''; - } - - const graph = new DepGraph({ circular: true }); - - fragments.forEach(fragment => { - graph.addNode(fragment.name, fragment); - }); - - fragments.forEach(fragment => { - const depends = extractFragments(fragment.document); - - if (depends) { - depends.forEach(name => { - graph.addDependency(fragment.name, name); - }); - } - }); - - return graph - .overallOrder() - .map(name => generateFragment(graph.getNodeData(name), options)) - .join('\n'); - - function generateFragment(fragment: any, options: any): string | void { - const cached = cachedFragments[fragment.name]; - - if (!cached) { - cachedFragments[fragment.name] = fragment; - - return ` - export const ${toFragmentName(convert)(fragment.name)} = ${gql(convert)(fragment, fragments, options)}; - `; - } else { - if (fragment.document !== cached.document) { - throw new Error(`Duplicated fragment called '${fragment.name}'`); - } - } - } -}; diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/gql.ts b/packages/plugins/typescript-apollo-angular/src/helpers/gql.ts deleted file mode 100644 index 972cbda2cc2..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/gql.ts +++ /dev/null @@ -1,54 +0,0 @@ -import gqlTag from 'graphql-tag'; -import { toFragmentName } from './to-fragment-name'; -import { removeDirectives } from './directives'; -import { Operation } from 'graphql-codegen-core'; - -export const gql = convert => (operation: Operation, operations: Operation[], options: any): string => { - const config = options.data.root.config || {}; - const noGraphqlTag = config.noGraphqlTag; - const cleanDoc = removeDirectives(operation.document, ['NgModule', 'namedClient']); - - if (noGraphqlTag) { - const fragmentNames = extractFragments(operation.document); - const fragments = - operations - .filter(op => fragmentNames.includes(op.name) && !op.operationType) - .map(f => f.document) - .join(' ') || ''; - - return JSON.stringify( - gqlTag` - ${cleanDoc} - ${fragments} - ` - ); - } - - const doc = ` - ${cleanDoc} - ${includeFragments(transformFragments(convert)(operation.document))} - `; - - return 'gql`' + doc + '`'; -}; - -function includeFragments(fragments: string[]): string { - if (fragments) { - return ` - ${fragments - .filter((name, i, all) => all.indexOf(name) === i) - .map(name => '${' + name + '}') - .join('\n')} - `; - } - - return ''; -} - -export function extractFragments(document: string): string[] | undefined { - return (document.match(/\.\.\.[a-z0-9\_]+/gi) || []).map(name => name.replace('...', '')); -} - -const transformFragments = convert => (document: string): string[] | undefined => { - return extractFragments(document).map(toFragmentName(convert)); -}; diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/import-ng-modules.ts b/packages/plugins/typescript-apollo-angular/src/helpers/import-ng-modules.ts deleted file mode 100644 index 9f863514e19..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/import-ng-modules.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { extractNgModule } from './ngmodule-directive'; -import { operationHasDirective } from './directives'; - -export function importNgModules(operations: any[]) { - const defs: Record = {}; - - operations.filter(op => operationHasDirective(op, 'NgModule')).forEach(op => { - const def = extractNgModule(op); - - // by setting key as link we easily get rid of duplicated imports - // every path should be relative to the output file - defs[def.link] = { - path: def.path, - module: def.module - }; - }); - - return Object.keys(defs) - .map(key => { - const def = defs[key]; - // Every Angular Module that I've seen in my entire life use named exports - return `import { ${def.module} } from '${def.path}';`; - }) - .join('\n'); -} diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/named-client.ts b/packages/plugins/typescript-apollo-angular/src/helpers/named-client.ts deleted file mode 100644 index f25b91275b8..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/named-client.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { operationHasDirective, extractDirective } from './directives'; -import { Operation } from 'graphql-codegen-core'; - -const R_NAME = /name\:\s*"([^"]+)"/; // matches: name: "..." - -export function namedClient(operation: Operation): string { - if (!operationHasDirective(operation, 'namedClient')) { - return ''; - } - - const { name } = extractNamedClient(operation); - - return `client = '${name}';`; -} - -// tries to find namedClient directive and extract {name} -export function extractNamedClient(operation: Operation) { - const [, name] = extractDirective(operation, 'namedClient').match(R_NAME); - - return { - name - }; -} diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/ngmodule-directive.ts b/packages/plugins/typescript-apollo-angular/src/helpers/ngmodule-directive.ts deleted file mode 100644 index ba36fe3f57c..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/ngmodule-directive.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { extractDirective } from './directives'; -import { Operation } from 'graphql-codegen-core'; - -const R_MOD = /module\:\s*"([^"]+)"/; // matches: module: "..." - -// tries to find NgModule directive and extract {path, module} -export function extractNgModule(operation: Operation) { - const [, link] = extractDirective(operation, 'NgModule').match(R_MOD); - const [path, module] = link.split('#'); - - return { - path, - module, - link - }; -} diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/provided-in.ts b/packages/plugins/typescript-apollo-angular/src/helpers/provided-in.ts deleted file mode 100644 index 244e03383de..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/provided-in.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { extractNgModule } from './ngmodule-directive'; -import { operationHasDirective } from './directives'; -import { Operation } from 'graphql-codegen-core'; - -export function providedIn(operation: Operation) { - if (operationHasDirective(operation, 'NgModule')) { - const { module } = extractNgModule(operation); - - // it's a reference so just string, without any quotes - return module; - } - - return `'root'`; -} diff --git a/packages/plugins/typescript-apollo-angular/src/helpers/to-fragment-name.ts b/packages/plugins/typescript-apollo-angular/src/helpers/to-fragment-name.ts deleted file mode 100644 index a9e243c8335..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/helpers/to-fragment-name.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const toFragmentName = convert => (fragmentName: string): string => { - return convert(`${fragmentName}Fragment`, 'typeNames'); -}; diff --git a/packages/plugins/typescript-apollo-angular/src/index.ts b/packages/plugins/typescript-apollo-angular/src/index.ts index d58be45bdf0..f785057a57b 100644 --- a/packages/plugins/typescript-apollo-angular/src/index.ts +++ b/packages/plugins/typescript-apollo-angular/src/index.ts @@ -1,42 +1,35 @@ -import { initCommonTemplate, TypeScriptCommonConfig } from 'graphql-codegen-typescript-common'; -import { DocumentFile, PluginFunction, PluginValidateFn, transformDocumentsFiles } from 'graphql-codegen-core'; -import { flattenTypes } from 'graphql-codegen-plugin-helpers'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; -import { importNgModules } from './helpers/import-ng-modules'; -import { gql as gqlHelper } from './helpers/gql'; -import gql from 'graphql-tag'; -import { generateFragments } from './helpers/generate-fragments'; -import { providedIn } from './helpers/provided-in'; -import { namedClient } from './helpers/named-client'; +import { DocumentFile, PluginValidateFn, PluginFunction } from 'graphql-codegen-plugin-helpers'; +import { visit, GraphQLSchema, concatAST, Kind, FragmentDefinitionNode, OperationDefinitionNode } from 'graphql'; +import { RawClientSideBasePluginConfig } from 'graphql-codegen-visitor-plugin-common'; +import { ApolloAngularVisitor } from './visitor'; import { extname } from 'path'; +import gql from 'graphql-tag'; -export interface TypeScriptApolloAngularConfig extends TypeScriptCommonConfig { - noNamespaces?: boolean; - noGraphqlTag?: boolean; -} - -export const plugin: PluginFunction = async ( +export const plugin: PluginFunction = ( schema: GraphQLSchema, documents: DocumentFile[], - config: TypeScriptApolloAngularConfig -): Promise => { - const { templateContext, convert } = initCommonTemplate(Handlebars, schema, documents, config); - const transformedDocuments = transformDocumentsFiles(schema, documents); - const flattenDocuments = flattenTypes(transformedDocuments); - Handlebars.registerHelper('importNgModules', importNgModules); - Handlebars.registerHelper('gql', gqlHelper(convert)); - Handlebars.registerHelper('providedIn', providedIn); - Handlebars.registerHelper('namedClient', namedClient); - Handlebars.registerHelper('generateFragments', generateFragments(convert)); + config: RawClientSideBasePluginConfig +) => { + const allAst = concatAST( + documents.reduce((prev, v) => { + return [...prev, v.content]; + }, []) + ); + const operations = allAst.definitions.filter(d => d.kind === Kind.OPERATION_DEFINITION) as OperationDefinitionNode[]; + + if (operations.length === 0) { + return ''; + } - const hbsContext = { - ...templateContext, - ...flattenDocuments - }; + const allFragments = allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION) as FragmentDefinitionNode[]; + const visitor = new ApolloAngularVisitor(allFragments, operations, config) as any; + const visitorResult = visit(allAst, { leave: visitor }); - return Handlebars.compile(rootTemplate)(hbsContext); + return [ + visitor.getImports(), + visitor.fragments, + ...visitorResult.definitions.filter(t => typeof t === 'string') + ].join('\n'); }; export const addToSchema = gql` diff --git a/packages/plugins/typescript-apollo-angular/src/polyfills.d.ts b/packages/plugins/typescript-apollo-angular/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-apollo-angular/src/root.handlebars b/packages/plugins/typescript-apollo-angular/src/root.handlebars deleted file mode 100644 index 1ea37867e01..00000000000 --- a/packages/plugins/typescript-apollo-angular/src/root.handlebars +++ /dev/null @@ -1,30 +0,0 @@ -{{#ifCond operations.length '!==' 0}} -{{{ blockComment 'START: Apollo Angular template' }}} - -import { Injectable } from '@angular/core'; -import * as Apollo from 'apollo-angular'; - -{{#unless @root.config.noGraphqlTag}} -import gql from 'graphql-tag'; -{{/unless}} - -{{{ importNgModules operations }}} - -{{{ blockCommentIf 'GraphQL Fragments' fragments }}} - -{{{ generateFragments fragments }}} - -{{{ blockCommentIf 'Apollo Services' operations }}} - -{{#each operations}} - @Injectable({ - providedIn: {{{ providedIn this }}} - }) - export class {{ convert name 'typeNames' }}GQL extends Apollo.{{convert operationType 'typeNames'}}<{{ convert name 'typeNames' }}{{#unless @root.config.noNamespaces}}.{{/unless}}{{ convert operationType 'typeNames' }}, {{ convert name 'typeNames' }}{{#unless @root.config.noNamespaces}}.{{/unless}}Variables> { - document: any = {{{ gql this ../fragments }}}; - {{{ namedClient this }}} - } -{{/each}} - -{{{ blockComment 'END: Apollo Angular template' }}} -{{/ifCond}} diff --git a/packages/plugins/typescript-apollo-angular/src/visitor.ts b/packages/plugins/typescript-apollo-angular/src/visitor.ts new file mode 100644 index 00000000000..d6a5dc14ea5 --- /dev/null +++ b/packages/plugins/typescript-apollo-angular/src/visitor.ts @@ -0,0 +1,135 @@ +import { ClientSideBaseVisitor } from 'graphql-codegen-visitor-plugin-common'; +import * as autoBind from 'auto-bind'; +import { parse, FragmentDefinitionNode, OperationDefinitionNode, print, Kind } from 'graphql'; + +const R_MOD = /module\:\s*"([^"]+)"/; // matches: module: "..." +const R_NAME = /name\:\s*"([^"]+)"/; // matches: name: "..." + +function R_DEF(directive: string) { + return new RegExp(`\\s+\\@${directive}\\([^)]+\\)`, 'gm'); +} + +export class ApolloAngularVisitor extends ClientSideBaseVisitor { + constructor(fragments: FragmentDefinitionNode[], private _allOperations: OperationDefinitionNode[], rawConfig) { + super(fragments, rawConfig, {}); + + autoBind(this); + } + + public getImports(): string { + const baseImports = super.getImports(); + const imports = [`import { Injectable } from '@angular/core';`, `import Apollo from 'apollo-angular';`]; + + const defs: Record = {}; + + this._allOperations + .filter(op => this._operationHasDirective(op, 'NgModule')) + .forEach(op => { + const def = this._extractNgModule(op); + + // by setting key as link we easily get rid of duplicated imports + // every path should be relative to the output file + defs[def.link] = { + path: def.path, + module: def.module + }; + }); + + Object.keys(defs).forEach(key => { + const def = defs[key]; + // Every Angular Module that I've seen in my entire life use named exports + imports.push(`import { ${def.module} } from '${def.path}';`); + }); + + return [baseImports, ...imports].join('\n'); + } + + private _extractNgModule(operation: OperationDefinitionNode) { + const [, link] = print(operation).match(R_MOD); + const [path, module] = link.split('#'); + + return { + path, + module, + link + }; + } + + private _operationHasDirective(operation: OperationDefinitionNode, directive: string) { + return print(operation).includes(`@${directive}`); + } + + private _removeDirective(document: OperationDefinitionNode, directive: string): OperationDefinitionNode { + if (this._operationHasDirective(document, directive)) { + return parse(print(document).replace(R_DEF(directive), '')).definitions[0] as OperationDefinitionNode; + } + + return parse(print(document)).definitions[0] as OperationDefinitionNode; + } + + private _removeDirectives(document: OperationDefinitionNode, directives: string[]): OperationDefinitionNode { + return directives.reduce((doc, directive) => this._removeDirective(doc, directive), document); + } + + private _extractDirective(operation: OperationDefinitionNode, directive: string) { + const directives = print(operation).match(R_DEF(directive)); + + if (directives.length > 1) { + throw new Error(`The ${directive} directive used multiple times in '${operation.name}' operation`); + } + + return directives[0]; + } + + protected _prepareDocument(documentStr: string): string { + return print( + this._removeDirectives(parse(documentStr).definitions[0] as OperationDefinitionNode, ['NgModule', 'namedClient']) + ); + } + + private _namedClient(operation: OperationDefinitionNode): string { + if (!this._operationHasDirective(operation, 'namedClient')) { + return ''; + } + + const name = this._extractNamedClient(operation); + + return `client = '${name}';`; + } + + // tries to find namedClient directive and extract {name} + private _extractNamedClient(operation: OperationDefinitionNode): string { + const [, name] = this._extractDirective(operation, 'namedClient').match(R_NAME); + + return name; + } + + private _providedIn(operation: OperationDefinitionNode): string { + if (this._operationHasDirective(operation, 'NgModule')) { + return this._extractNgModule(operation).module; + } + + return `'root'`; + } + + protected buildOperation( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + const content = ` + @Injectable({ + providedIn: ${this._providedIn(node)} + }) + export class ${this.convertName( + node.name.value + )}GQL extends Apollo.${operationType}<${operationResultType}, ${operationVariablesTypes}> { + document = ${documentVariableName}; + ${this._namedClient(node)} + }`; + + return content; + } +} diff --git a/packages/plugins/typescript-apollo-angular/tests/apollo-angular.spec.ts b/packages/plugins/typescript-apollo-angular/tests/apollo-angular.spec.ts index c99468f5bac..07cade4c95a 100644 --- a/packages/plugins/typescript-apollo-angular/tests/apollo-angular.spec.ts +++ b/packages/plugins/typescript-apollo-angular/tests/apollo-angular.spec.ts @@ -1,584 +1,227 @@ -import 'graphql-codegen-core/dist/testing'; -import { plugin, addToSchema } from '../dist'; -import * as fs from 'fs'; -import { extendSchema, print, buildSchema, buildClientSchema } from 'graphql'; +import 'graphql-codegen-testing'; import gql from 'graphql-tag'; - -describe('Components', () => { - const schema = buildClientSchema(JSON.parse(fs.readFileSync('./tests/files/schema.json').toString())); - - it('should be able to use root schema object', async () => { - const rootSchema = buildSchema(` - type RootQuery { f: String } - schema { query: RootQuery } - `); - const query = gql` - query test { - f - } - `; - - const content = await plugin( - rootSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - @Injectable({ - providedIn: 'root' - }) - export class TestGQL extends Apollo.Query - `); - }); - - it('should generate Component with noGraphqlTag = true', async () => { - const query = gql` - query MyFeed { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - { noGraphqlTag: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import * as Apollo from 'apollo-angular'; - `); - expect(content).not.toBeSimilarStringTo(` - import gql from 'graphql-tag'; - `); - expect(content).toBeSimilarStringTo(` - import { Injectable } from '@angular/core'; - `); - expect(content).toBeSimilarStringTo(` - @Injectable({ - providedIn: 'root' - }) - export class MyFeedGQL extends Apollo.Query - `); - }); - - it('should generate Component with noGraphqlTag = true and fragments', async () => { - const query = gql` - query MyFeed { - feed { - id - commentCount - repository { - ...RepositoryInfo - } - } - } - `; - const fragment = gql` - fragment RepositoryInfo on Repository { - full_name - html_url - owner { - avatar_url - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: fragment }, { filePath: '', content: query }], - { - noGraphqlTag: true - }, - { - outputFile: 'graphql.ts' - } - ); - - const docR = /document: any = ([^;]+)/gm; - const doc = docR.exec(content)[1]; - - expect(print(JSON.parse(doc))).toBe( - print(gql` - ${query} - ${fragment} - `) - ); - }); - - it('should generate correct Component when noNamespaces enabled', async () => { - const query = gql` - query MyFeed { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - { - noNamespaces: true, - noGraphqlTag: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - @Injectable({ - providedIn: 'root' - }) - export class MyFeedGQL extends Apollo.Query { - `); - }); - - it('should generate correct Component when noNamespaces disabled', async () => { - const query = gql` - query MyFeed { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - @Injectable({ - providedIn: 'root' - }) - export class MyFeedGQL extends Apollo.Query { - `); - }); - - it('should use parsed document instead of graphql-tag', async () => { - const query = gql` - query MyFeed { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - // location might be different so let's skip it - delete query.loc; - const rawContent = await plugin( - schema, - [{ filePath: '', content: query }], - { - noNamespaces: true, - noGraphqlTag: true - }, - { - outputFile: 'graphql.ts' - } - ); - const content = rawContent.replace(/,"loc":{"start":\d+,"end":\d+}}\s+}/, '}'); - - expect(content).toBeSimilarStringTo(` - @Injectable({ - providedIn: 'root' - }) - export class MyFeedGQL extends Apollo.Query { - `); - - expect(content).toBeSimilarStringTo(` - document: any = ${JSON.stringify(query)}; - `); - }); - - it('should not escape html', async () => { - const query = gql` - query MyFeed { - feed(search: "phrase") { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - document: any = gql\` query MyFeed { - `); - - expect(content.includes('"')).toBe(false); - expect(content.includes('"phrase"')).toBe(true); - }); - - it('should handle fragments', async () => { - const repositoryWithOwner = gql` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - `; - const feedWithRepository = gql` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } - - ${repositoryWithOwner} - `; - const myFeed = gql` - query MyFeed { - feed { - ...FeedWithRepository - } - } - - ${feedWithRepository} - `; - - const documents = [repositoryWithOwner, feedWithRepository, myFeed]; - const files = documents.map(query => ({ filePath: '', content: query })); - const content = await plugin( - schema, - files, - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - document: any = gql\` query MyFeed { - feed { - ...FeedWithRepository - } - } - \${FeedWithRepositoryFragment} - \` - `); - - expect(content).toBeSimilarStringTo(` - const FeedWithRepositoryFragment = gql\` fragment FeedWithRepository on FeedType { +import { plugin, addToSchema } from '../src/index'; +import { parse, GraphQLSchema, buildClientSchema, buildSchema, extendSchema } from 'graphql'; +import { DocumentFile } from 'graphql-codegen-plugin-helpers'; +import { plugin as tsPlugin } from '../../typescript/src/index'; +import { plugin as tsDocumentsPlugin } from '../../typescript-operations/src/index'; +import { validateTs } from '../../typescript/tests/validate'; +import { readFileSync } from 'fs'; + +describe('Apollo Angular', () => { + const schema = buildClientSchema(JSON.parse(readFileSync('../../../dev-test/githunt/schema.json').toString())); + const basicDoc = parse(/* GraphQL */ ` + query test { + feed { id commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } - \${RepositoryWithOwnerFragment} - \`; - `); - - expect(content).toBeSimilarStringTo(` - const RepositoryWithOwnerFragment = gql\` fragment RepositoryWithOwner on Repository { + repository { full_name html_url owner { avatar_url } } - \`; - `); - }); - - it('should handle @client', async () => { - const myFeed = gql` - query MyFeed { - feed @client { - id - } } - `; + } + `); + const validateTypeScript = async ( + output: string, + testSchema: GraphQLSchema, + documents: DocumentFile[], + config: any + ) => { + const tsOutput = await tsPlugin(testSchema, documents, config, { outputFile: '' }); + const tsDocumentsOutput = await tsDocumentsPlugin(testSchema, documents, config, { outputFile: '' }); + const merged = [tsOutput, tsDocumentsOutput, output].join('\n'); + validateTs(merged, undefined, true); + }; + + it(`should skip if there's no operations`, async () => { const content = await plugin( schema, - [{ filePath: '', content: myFeed }], + [], {}, { outputFile: 'graphql.ts' } ); - expect(content).toBeSimilarStringTo(` - document: any = gql\` query MyFeed { - feed @client { - id - } - } - \` - `); + expect(content).toBe(''); + await validateTypeScript(content, schema, [], {}); }); - test('import NgModules and remove NgModule directive', async () => { - const modifiedSchema = extendSchema(schema, addToSchema); - expect(modifiedSchema.getDirective('NgModule').name).toBe('NgModule'); - const modulePath = '../my/lazy-module'; - const moduleName = 'LazyModule'; - - const myFeed = gql(` - query MyFeed { - feed @client @NgModule(module: "${modulePath}#${moduleName}") { - id + describe('Imports', () => { + it('should import DocumentNode when using noGraphQLTag', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { + noGraphQLTag: true + }, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toContain(`import { DocumentNode } from 'graphql';`); + expect(content).not.toBeSimilarStringTo(`import gql from 'graphql-tag';`); + await validateTypeScript(content, schema, docs, {}); + }); + + it(`should use gql import from gqlImport config option`, async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { gqlImport: 'graphql.macro#gql' }, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toContain(`import { gql } from 'graphql.macro';`); + await validateTypeScript(content, schema, docs, {}); + }); + + it(`should add the correct angular imports`, async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toBeSimilarStringTo(`import Apollo from 'apollo-angular';`); + expect(content).toBeSimilarStringTo(`import { Injectable } from '@angular/core';`); + await validateTypeScript(content, schema, docs, {}); + }); + + it('Should import NgModules and remove NgModule directive', async () => { + const modifiedSchema = extendSchema(schema, addToSchema); + expect(modifiedSchema.getDirective('NgModule').name).toBe('NgModule'); + const modulePath = '../my/lazy-module'; + const moduleName = 'LazyModule'; + + const myFeed = gql(` + query MyFeed { + feed @client @NgModule(module: "${modulePath}#${moduleName}") { + id + } } - } - `); - const content = await plugin( - modifiedSchema, - [{ filePath: '', content: myFeed }], - {}, - { - outputFile: 'graphql.ts' - } - ); - expect(content).toMatch(`import { ${moduleName} } from '${modulePath}'`); - - expect(content).toBeSimilarStringTo(` - @Injectable({ - providedIn: ${moduleName} - }) - export class MyFeedGQL - `); - - expect(content).toBeSimilarStringTo(` - document: any = gql\` query MyFeed { - feed @client { - id + `); + const docs = [{ filePath: '', content: myFeed }]; + const content = await plugin( + modifiedSchema, + docs, + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(content).toMatch(`import { ${moduleName} } from '${modulePath}'`); + expect(content).toBeSimilarStringTo(` + @Injectable({ + providedIn: ${moduleName} + }) + export class MyFeedGQL + `); + expect(content).toBeSimilarStringTo(`document = MyFeedDocument;`); + expect(content).not.toContain('@NgModule'); + expect(content).toContain('@client'); + validateTypeScript(content, modifiedSchema, docs, {}); + }); + + it('Should import namedClient and remove namedClient directive', async () => { + const modifiedSchema = extendSchema(schema, addToSchema); + expect(modifiedSchema.getDirective('namedClient').name).toBe('namedClient'); + + const myFeed = gql(` + query MyFeed { + feed @namedClient(name: "custom") { + id + } } - } - \` - `); - }); - - test('import namedClient and remove namedClient directive', async () => { - const modifiedSchema = extendSchema(schema, addToSchema); - expect(modifiedSchema.getDirective('namedClient').name).toBe('namedClient'); + `); - const myFeed = gql(` - query MyFeed { - feed @namedClient(name: "custom") { - id + const docs = [{ filePath: '', content: myFeed }]; + const content = await plugin( + modifiedSchema, + docs, + {}, + { + outputFile: 'graphql.ts' } - } - `); + ); - const content = await plugin( - modifiedSchema, - [{ filePath: '', content: myFeed }], - {}, - { - outputFile: 'graphql.ts' - } - ); + expect(content).toBeSimilarStringTo(`document = MyFeedDocument;`); - expect(content).toBeSimilarStringTo(` - document: any = gql\` query MyFeed { - feed { - id - } - } - \` - `); - - expect(content).toBeSimilarStringTo(` - client = 'custom'; - `); + expect(content).toBeSimilarStringTo(` + client = 'custom'; + `); + expect(content).not.toContain('@namedClient'); + validateTypeScript(content, modifiedSchema, docs, {}); + }); }); - it('no duplicated fragments', async () => { - const simpleFeed = gql` - fragment SimpleFeed on FeedType { - id - commentCount - } - `; - const myFeed = gql` - query MyFeed { - feed { - ...SimpleFeed - } - allFeeds { - ...SimpleFeed - } - } - `; - - const documents = [simpleFeed, myFeed]; - const content = await plugin( - schema, - documents.map(content => ({ content, filePath: '' })), - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - document: any = gql\` query MyFeed { - feed { - ...SimpleFeed - } - allFeeds { - ...SimpleFeed + describe('Component', () => { + it('Should be able to use root schema object', async () => { + const rootSchema = buildSchema(` + type RootQuery { f: String } + schema { query: RootQuery } + `); + const query = gql` + query test { + f + } + `; + const docs = [{ filePath: '', content: query }]; + const content = await plugin( + rootSchema, + docs, + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(content).toBeSimilarStringTo(` + @Injectable({ + providedIn: 'root' + }) + export class TestGQL extends Apollo.Query + `); + validateTypeScript(content, rootSchema, docs, {}); + }); + + it('Should handle @client', async () => { + const myFeed = gql` + query MyFeed { + feed @client { + id } } - \${SimpleFeedFragment} - \` - `); + `; - expect(content).toBeSimilarStringTo(` - const SimpleFeedFragment = gql\` fragment SimpleFeed on FeedType { - id - commentCount - } - \`; - `); - }); - - it('write fragments in proper order (when one depends on other)', async () => { - const myFeed = gql` - fragment FeedWithRepository on FeedType { - id - repository { - ...RepositoryWithOwner - } - } - fragment RepositoryWithOwner on Repository { - full_name - } - query MyFeed { - feed { - ...FeedWithRepository + const docs = [{ filePath: '', content: myFeed }]; + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.ts' } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: myFeed }], - {}, - { - outputFile: 'graphql.ts' - } - ); - const feedWithRepositoryPos = content.indexOf('fragment FeedWithRepository'); - const repositoryWithOwnerPos = content.indexOf('fragment RepositoryWithOwner'); + ); - expect(repositoryWithOwnerPos).toBeLessThan(feedWithRepositoryPos); - }); - - it('should add comments (non-graphql)', async () => { - const myFeed = gql` - fragment FeedWithRepository on FeedType { - id - repository { - ...RepositoryWithOwner - } - } - fragment RepositoryWithOwner on Repository { - full_name - } - query MyFeed { - feed { - ...FeedWithRepository - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: myFeed }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo('// START: Apollo Angular template'); - expect(content).toBeSimilarStringTo('// GraphQL Fragments'); - expect(content).toBeSimilarStringTo('// Apollo Services'); - expect(content).toBeSimilarStringTo('// END: Apollo Angular template'); - }); - - it(`should skip if there's no operations`, async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); + expect(content).toBeSimilarStringTo(`document = MyFeedDocument;`); - expect(content).not.toContain('// START: Apollo Angular template'); - expect(content).not.toContain('// END: Apollo Angular template'); - expect(content).not.toContain(`import * as Apollo from 'apollo-angular';`); - expect(content).not.toContain(`import gql from 'graphql-tag';`); - expect(content).not.toContain(`import { Injectable } from '@angular/core';`); + validateTypeScript(content, schema, docs, {}); + }); }); }); diff --git a/packages/plugins/typescript-apollo-angular/tests/files/schema.json b/packages/plugins/typescript-apollo-angular/tests/files/schema.json deleted file mode 100644 index e9ce20244e9..00000000000 --- a/packages/plugins/typescript-apollo-angular/tests/files/schema.json +++ /dev/null @@ -1,1739 +0,0 @@ -{ - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": { - "name": "Mutation" - }, - "subscriptionType": { - "name": "Subscription" - }, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": "", - "fields": [ - { - "name": "feed", - "description": "A feed of repository submissions", - "args": [ - { - "name": "type", - "description": "The sort order for the feed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "FeedType", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "The number of items to skip, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "limit", - "description": "The number of items to fetch starting from the offset, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "entry", - "description": "A single entry", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "currentUser", - "description": "Return the currently logged in user, or null if nobody is logged in", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FeedType", - "description": "A list of options for the sort order of the feed", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "HOT", - "description": "Sort by a combination of freshness and score, using Reddit's algorithm", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NEW", - "description": "Newest entries first", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TOP", - "description": "Highest score entries first", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Entry", - "description": "Information about a GitHub repository submitted to GitHunt", - "fields": [ - { - "name": "repository", - "description": "Information about the repository from GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Repository", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who submitted this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the entry was submitted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "score", - "description": "The score of this repository, upvotes - downvotes", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hotScore", - "description": "The hot score of this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "comments", - "description": "Comments posted about this repository", - "args": [ - { - "name": "limit", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commentCount", - "description": "The number of comments posted about this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "XXX to be changed", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Repository", - "description": "A repository object from the GitHub API. This uses the exact field names returned by the\nGitHub API for simplicity, even though the convention for GraphQL is usually to camel case.", - "fields": [ - { - "name": "name", - "description": "Just the name of the repository, e.g. GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full_name", - "description": "The full name of the repository with the username, e.g. apollostack/GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "The description of the repository", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The link to the repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "stargazers_count", - "description": "The number of people who have starred this repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "open_issues_count", - "description": "The number of open issues on this repository on GitHub", - "args": [], - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "owner", - "description": "The owner of this repository on GitHub, e.g. apollostack", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "User", - "description": "A user object from the GitHub API. This uses the exact field names returned from the GitHub API.", - "fields": [ - { - "name": "login", - "description": "The name of the user, e.g. apollostack", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "avatar_url", - "description": "The URL to a directly embeddable image for this user's avatar", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The URL of this user's GitHub page", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Float", - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Comment", - "description": "A comment about an entry, submitted by a user", - "fields": [ - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who posted the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the comment was posted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "content", - "description": "The text of the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "repoName", - "description": "The repository which this comment is about", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Vote", - "description": "XXX to be removed", - "fields": [ - { - "name": "vote_value", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Mutation", - "description": "", - "fields": [ - { - "name": "submitRepository", - "description": "Submit a new repository, returns the new submission", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "Vote on a repository submission, returns the submission that was voted on", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "type", - "description": "The type of vote - UP, DOWN, or CANCEL", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VoteType", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "submitComment", - "description": "Comment on a repository, returns the new comment", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "commentContent", - "description": "The text content for the new comment", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "VoteType", - "description": "The type of vote to record, when submitting a vote", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "UP", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "DOWN", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "CANCEL", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Subscription", - "description": "", - "fields": [ - { - "name": "commentAdded", - "description": "Subscription fires on every comment added", - "args": [ - { - "name": "repoFullName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "locations", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__DirectiveLocation", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "QUERY", - "description": "Location adjacent to a query operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MUTATION", - "description": "Location adjacent to a mutation operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SUBSCRIPTION", - "description": "Location adjacent to a subscription operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD", - "description": "Location adjacent to a field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_DEFINITION", - "description": "Location adjacent to a fragment definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_SPREAD", - "description": "Location adjacent to a fragment spread.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INLINE_FRAGMENT", - "description": "Location adjacent to an inline fragment.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCHEMA", - "description": "Location adjacent to a schema definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCALAR", - "description": "Location adjacent to a scalar definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Location adjacent to an object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD_DEFINITION", - "description": "Location adjacent to a field definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ARGUMENT_DEFINITION", - "description": "Location adjacent to an argument definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Location adjacent to an interface definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Location adjacent to a union definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Location adjacent to an enum definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM_VALUE", - "description": "Location adjacent to an enum value definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Location adjacent to an input object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_FIELD_DEFINITION", - "description": "Location adjacent to an input object field definition.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - } - ], - "directives": [ - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "deprecated", - "description": "Marks an element of a GraphQL schema as no longer supported.", - "locations": ["FIELD_DEFINITION", "ENUM_VALUE"], - "args": [ - { - "name": "reason", - "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": "\"No longer supported\"" - } - ] - } - ] - } -} diff --git a/packages/plugins/typescript-apollo-angular/tsconfig.json b/packages/plugins/typescript-apollo-angular/tsconfig.json index 782f215152c..e872bb81d5d 100644 --- a/packages/plugins/typescript-apollo-angular/tsconfig.json +++ b/packages/plugins/typescript-apollo-angular/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", @@ -17,5 +18,6 @@ "noUnusedLocals": false, "noUnusedParameters": false }, + "include": ["src/**/*.ts"], "exclude": ["node_modules", "tests", "dist"] } diff --git a/packages/plugins/typescript-client/package.json b/packages/plugins/typescript-client/package.json deleted file mode 100644 index 4f61e4387fd..00000000000 --- a/packages/plugins/typescript-client/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "graphql-codegen-typescript-client", - "version": "0.18.0", - "description": "graphql-codegen-cli template for TypeScript typings for both client side and server side", - "repository": "git@github.com:dotansimha/graphql-code-generator.git", - "license": "MIT", - "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" - }, - "dependencies": { - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" - }, - "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" - }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] - } -} diff --git a/packages/plugins/typescript-client/src/helpers.ts b/packages/plugins/typescript-client/src/helpers.ts deleted file mode 100644 index a9133711fa3..00000000000 --- a/packages/plugins/typescript-client/src/helpers.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { getFieldType } from 'graphql-codegen-typescript-common'; -import { SafeString } from 'handlebars'; -import { - Field, - Operation, - SelectionSetFragmentSpread, - SelectionSetInlineFragment, - Fragment -} from 'graphql-codegen-core'; - -// it's not a config.interfacePrefix, it's document related -export function shouldHavePrefix(field: Field, options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - const nonPrefixable = field.isEnum || field.isScalar; - - return config.noNamespaces === true && !isPrimitiveType(field, options) && !nonPrefixable; -} - -export function isPrimitiveType(type: Field, options: Handlebars.HelperOptions) { - return options.data.root.primitives[type.type]; -} - -function nameFragment( - convert: (str: string, kind: string) => string, - prefix: string, - fragment: SelectionSetFragmentSpread | SelectionSetInlineFragment, - noNamespaces: boolean -) { - if (isFragmentSpread(fragment)) { - return convert(fragment.fragmentName, 'typeNames') + (noNamespaces ? '' : '.') + 'Fragment'; - } - - return (noNamespaces ? convert(prefix, 'typeNames') : '') + fragment.name; -} - -function isFragmentSpread( - fragment: SelectionSetFragmentSpread | SelectionSetInlineFragment -): fragment is SelectionSetFragmentSpread { - return fragment.isFragmentSpread; -} - -export function fragments(convert: (str: string) => string) { - return (operation: Operation, prefix: string, fragments: Fragment[], options: Handlebars.HelperOptions): string => { - const config = options.data.root.config || {}; - const noNamespaces = config.noNamespaces === true; - const fragmentsByType: { - [type: string]: Array; - } = {}; - - operation.inlineFragments.forEach(fragment => { - const type = fragment.onType; - - if (!fragmentsByType[type]) { - fragmentsByType[type] = []; - } - fragmentsByType[type].push(nameFragment(convert, prefix, fragment, noNamespaces)); - }); - - operation.fragmentsSpread.forEach(fragment => { - const def = fragments.find(f => f.name === fragment.fragmentName); - - if (!def) { - throw new Error( - `A fragment spread you used "${ - fragment.fragmentName - }" could not found. Please make sure that it's loaded as a GraphQL document!` - ); - } - - if (!fragmentsByType[def.onType]) { - fragmentsByType[def.onType] = []; - } - fragmentsByType[def.onType].push(nameFragment(convert, prefix, fragment, noNamespaces)); - }); - - const mergedFragments = Object.values(fragmentsByType) - // (F1 & F1) - .map(names => { - const joined = names.join(' & '); - - return names.length > 1 ? `(${joined})` : joined; - }) - // (F1 & F2) | (F3 & F4) - .join(' | '); - - const output: string[] = []; - - if (mergedFragments && operation.hasFields) { - output.push(' & '); - } - - if (Object.keys(fragmentsByType).length > 1) { - output.push(`(${mergedFragments})`); - } else { - output.push(mergedFragments); - } - - return output.join(''); - }; -} - -export function convertedFieldType(convert) { - return (field: Field, prefix: string, options: Handlebars.HelperOptions) => { - const config = options.data.root.config || {}; - let realType = ''; - const primitiveType = isPrimitiveType(field, options); - - if (shouldHavePrefix(field, options)) { - realType = convert(prefix, 'typeNames'); - - if (config.noNamespaces) { - realType += field.type; - } - } else if (primitiveType) { - realType = primitiveType; - } else if (field.isEnum) { - realType = (config.interfacePrefix || '') + convert(field.type, 'typeNames'); - } else { - realType = convert(field.type, 'typeNames'); - } - - return new SafeString(getFieldType(field, realType, options)); - }; -} diff --git a/packages/plugins/typescript-client/src/index.ts b/packages/plugins/typescript-client/src/index.ts deleted file mode 100644 index d4fee3dcb1c..00000000000 --- a/packages/plugins/typescript-client/src/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { TypeScriptCommonConfig, initCommonTemplate } from 'graphql-codegen-typescript-common'; -import { PluginFunction, DocumentFile, transformDocumentsFiles } from 'graphql-codegen-core'; -import { flattenTypes } from 'graphql-codegen-plugin-helpers'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; -import * as selectionSet from './selection-set.handlebars'; -import { shouldHavePrefix, fragments, convertedFieldType } from './helpers'; - -export interface TypeScriptClientConfig extends TypeScriptCommonConfig { - noNamespaces?: boolean; -} - -export const plugin: PluginFunction = async ( - schema: GraphQLSchema, - documents: DocumentFile[], - config: TypeScriptClientConfig -): Promise => { - const { templateContext, convert } = initCommonTemplate(Handlebars, schema, documents, config); - const transformedDocuments = transformDocumentsFiles(schema, documents); - const flattenDocuments = flattenTypes(transformedDocuments); - - Handlebars.registerPartial('selectionSet', selectionSet); - Handlebars.registerHelper('shouldHavePrefix', shouldHavePrefix); - Handlebars.registerHelper('fragments', fragments(convert)); - Handlebars.registerHelper('convertedFieldType', convertedFieldType(convert)); - - const hbsContext = { - ...templateContext, - ...flattenDocuments - }; - - return Handlebars.compile(rootTemplate)(hbsContext); -}; diff --git a/packages/plugins/typescript-client/src/polyfills.d.ts b/packages/plugins/typescript-client/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-client/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-client/src/root.handlebars b/packages/plugins/typescript-client/src/root.handlebars deleted file mode 100644 index 85c0d29ccf0..00000000000 --- a/packages/plugins/typescript-client/src/root.handlebars +++ /dev/null @@ -1,56 +0,0 @@ -{{{ blockCommentIf 'Documents' operations }}} -{{#each operations }} - -{{#unless @root.config.noNamespaces}} -export namespace {{ convert name 'typeNames' }} { -{{/unless}} - export type {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Variables = { - {{#each variables}} - {{#if @root.config.immutableTypes }}readonly {{/if}}{{ name }}{{ getOptionals this }}: {{ convertedType this }}; - {{/each}} - } - - export type {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}{{ convert operationType 'typeNames' }} ={{#if hasFields}} { - {{#if @root.config.immutableTypes }}readonly {{/if}}__typename?: "{{ convert operationType 'typeNames' }}"; - {{> selectionSet fields=fields prefix=name }} - }{{/if}}{{{ fragments this name ../fragments }}} - {{#each innerModels }} - - export type {{#if @root.config.noNamespaces}}{{ convert ../name 'typeNames' }}{{/if}}{{ convert modelType 'typeNames' }} ={{#ifCond hasFields '||' hasTypename}} { - {{#unless hasInlineFragments}} - {{#if @root.config.immutableTypes }}readonly {{/if}}__typename{{#unless hasTypename}}?{{/unless}}: "{{ schemaBaseType }}"; - {{else}} - {{#if @root.config.immutableTypes }}readonly {{/if}}__typename{{#unless hasTypename}}?{{/unless}}: {{#each inlineFragments}}{{#if @root.config.noNamespaces}}{{ convert ../../name 'typeNames' }}{{/if}}{{name}}["__typename"]{{#unless @last}} | {{/unless}}{{/each}}; - {{/unless}} - {{> selectionSet fields=fields prefix=../name }} - }{{/ifCond}} {{{ fragments this ../name ../../fragments }}} - {{/each}} -{{#unless @root.config.noNamespaces}} -} -{{/unless}} -{{/each}} -{{#each fragments }} - -{{#unless @root.config.noNamespaces}} -export namespace {{ convert name 'typeNames' }} { -{{/unless}} - export type {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Fragment ={{#if hasFields}} { - {{#if @root.config.immutableTypes }}readonly {{/if}}__typename?: "{{ onType }}"; - {{> selectionSet fields=fields prefix=name }} - }{{/if}}{{{ fragments this name ../fragments }}} - {{#each innerModels }} - - export type {{#if @root.config.noNamespaces}}{{ convert ../name 'typeNames' }}{{/if}}{{ convert modelType 'typeNames' }} ={{#if hasFields}} { - {{#unless hasInlineFragments}} - {{#if @root.config.immutableTypes }}readonly {{/if}}__typename{{#unless hasTypename}}?{{/unless}}: "{{ schemaBaseType }}"; - {{else}} - {{#if @root.config.immutableTypes }}readonly {{/if}}__typename{{#unless hasTypename}}?{{/unless}}: {{#each inlineFragments}}{{#if @root.config.noNamespaces}}{{ convert ../name 'typeNames' }}{{/if}}{{name}}["__typename"]{{#unless @last}} | {{/unless}}{{/each}}; - {{/unless}} - {{> selectionSet fields=fields prefix=../name }} - }{{/if}}{{{ fragments this ../name ../../fragments }}} - {{/each}} -{{#unless @root.config.noNamespaces}} -} -{{/unless}} -{{/each}} - diff --git a/packages/plugins/typescript-client/src/selection-set.handlebars b/packages/plugins/typescript-client/src/selection-set.handlebars deleted file mode 100644 index da71f5ec75a..00000000000 --- a/packages/plugins/typescript-client/src/selection-set.handlebars +++ /dev/null @@ -1,4 +0,0 @@ -{{#each fields}} -{{ toComment description }} -{{#if @root.config.immutableTypes }}readonly {{/if}}{{ name }}: {{ convertedFieldType this ../prefix }}; -{{/each}} diff --git a/packages/plugins/typescript-client/tests/files/schema.json b/packages/plugins/typescript-client/tests/files/schema.json deleted file mode 100644 index e9ce20244e9..00000000000 --- a/packages/plugins/typescript-client/tests/files/schema.json +++ /dev/null @@ -1,1739 +0,0 @@ -{ - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": { - "name": "Mutation" - }, - "subscriptionType": { - "name": "Subscription" - }, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": "", - "fields": [ - { - "name": "feed", - "description": "A feed of repository submissions", - "args": [ - { - "name": "type", - "description": "The sort order for the feed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "FeedType", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "The number of items to skip, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "limit", - "description": "The number of items to fetch starting from the offset, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "entry", - "description": "A single entry", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "currentUser", - "description": "Return the currently logged in user, or null if nobody is logged in", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FeedType", - "description": "A list of options for the sort order of the feed", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "HOT", - "description": "Sort by a combination of freshness and score, using Reddit's algorithm", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NEW", - "description": "Newest entries first", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TOP", - "description": "Highest score entries first", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Entry", - "description": "Information about a GitHub repository submitted to GitHunt", - "fields": [ - { - "name": "repository", - "description": "Information about the repository from GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Repository", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who submitted this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the entry was submitted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "score", - "description": "The score of this repository, upvotes - downvotes", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hotScore", - "description": "The hot score of this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "comments", - "description": "Comments posted about this repository", - "args": [ - { - "name": "limit", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commentCount", - "description": "The number of comments posted about this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "XXX to be changed", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Repository", - "description": "A repository object from the GitHub API. This uses the exact field names returned by the\nGitHub API for simplicity, even though the convention for GraphQL is usually to camel case.", - "fields": [ - { - "name": "name", - "description": "Just the name of the repository, e.g. GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full_name", - "description": "The full name of the repository with the username, e.g. apollostack/GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "The description of the repository", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The link to the repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "stargazers_count", - "description": "The number of people who have starred this repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "open_issues_count", - "description": "The number of open issues on this repository on GitHub", - "args": [], - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "owner", - "description": "The owner of this repository on GitHub, e.g. apollostack", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "User", - "description": "A user object from the GitHub API. This uses the exact field names returned from the GitHub API.", - "fields": [ - { - "name": "login", - "description": "The name of the user, e.g. apollostack", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "avatar_url", - "description": "The URL to a directly embeddable image for this user's avatar", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The URL of this user's GitHub page", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Float", - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Comment", - "description": "A comment about an entry, submitted by a user", - "fields": [ - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who posted the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the comment was posted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "content", - "description": "The text of the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "repoName", - "description": "The repository which this comment is about", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Vote", - "description": "XXX to be removed", - "fields": [ - { - "name": "vote_value", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Mutation", - "description": "", - "fields": [ - { - "name": "submitRepository", - "description": "Submit a new repository, returns the new submission", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "Vote on a repository submission, returns the submission that was voted on", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "type", - "description": "The type of vote - UP, DOWN, or CANCEL", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VoteType", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "submitComment", - "description": "Comment on a repository, returns the new comment", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "commentContent", - "description": "The text content for the new comment", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "VoteType", - "description": "The type of vote to record, when submitting a vote", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "UP", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "DOWN", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "CANCEL", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Subscription", - "description": "", - "fields": [ - { - "name": "commentAdded", - "description": "Subscription fires on every comment added", - "args": [ - { - "name": "repoFullName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "locations", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__DirectiveLocation", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "QUERY", - "description": "Location adjacent to a query operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MUTATION", - "description": "Location adjacent to a mutation operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SUBSCRIPTION", - "description": "Location adjacent to a subscription operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD", - "description": "Location adjacent to a field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_DEFINITION", - "description": "Location adjacent to a fragment definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_SPREAD", - "description": "Location adjacent to a fragment spread.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INLINE_FRAGMENT", - "description": "Location adjacent to an inline fragment.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCHEMA", - "description": "Location adjacent to a schema definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCALAR", - "description": "Location adjacent to a scalar definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Location adjacent to an object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD_DEFINITION", - "description": "Location adjacent to a field definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ARGUMENT_DEFINITION", - "description": "Location adjacent to an argument definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Location adjacent to an interface definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Location adjacent to a union definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Location adjacent to an enum definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM_VALUE", - "description": "Location adjacent to an enum value definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Location adjacent to an input object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_FIELD_DEFINITION", - "description": "Location adjacent to an input object field definition.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - } - ], - "directives": [ - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "deprecated", - "description": "Marks an element of a GraphQL schema as no longer supported.", - "locations": ["FIELD_DEFINITION", "ENUM_VALUE"], - "args": [ - { - "name": "reason", - "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": "\"No longer supported\"" - } - ] - } - ] - } -} diff --git a/packages/plugins/typescript-client/tests/typescript-client.spec.ts b/packages/plugins/typescript-client/tests/typescript-client.spec.ts deleted file mode 100644 index 1d2e701a530..00000000000 --- a/packages/plugins/typescript-client/tests/typescript-client.spec.ts +++ /dev/null @@ -1,1246 +0,0 @@ -import 'graphql-codegen-core/dist/testing'; -import { makeExecutableSchema } from 'graphql-tools'; -import { readFileSync } from 'fs'; -import { plugin } from '../dist'; -import gql from 'graphql-tag'; -import { buildClientSchema } from 'graphql'; - -describe('TypeScript Client', () => { - const schema = buildClientSchema(JSON.parse(readFileSync('./tests/files/schema.json', 'utf-8'))); - - it('Should generate simple Query correctly', async () => { - const query = gql` - query myFeed { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace MyFeed { - export type Variables = { - } - export type Query = { - __typename?: "Query"; - feed: Maybe<(Maybe)[]>; - } - export type Feed = { - __typename?: "Entry"; - id: number; - commentCount: number; - repository: Repository; - } - export type Repository = { - __typename?: "Repository"; - full_name: string; - html_url: string; - owner: Maybe; - } - export type Owner = { - __typename?: "User"; - avatar_url: string; - } - } - `); - }); - - it('Should generate and convert names correctly', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type User_Special { - id: String! - name: String! - } - type Query { - users: [User_Special] - vE2_User: [User_Special] - } - ` - }); - - const query = gql` - query Query1 { - users { - ...my_fragment - } - } - fragment my_fragment on User_Special { - id - name - } - query Query2 { - vE2_User { - id - name - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - expect(content).not.toContain('export namespace my_fragment {'); - expect(content).not.toContain('export type VE2User = {'); - expect(content).toContain('export namespace MyFragment {'); - expect(content).toContain('export type Ve2User = {'); - }); - - it('Should generate nested types', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type User { - profile: Profile - id: Int! - favFriend: User - } - type Profile { - name: String! - email: String! - } - - type Query { - me: User - } - ` - }); - - const query = gql` - query me { - me { - id - profile { - name - } - favFriend { - id - profile { - email - } - favFriend { - id - profile { - email - } - } - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace Me { - export type Variables = { - } - - export type Query = { - __typename?: "Query"; - me: Maybe; - } - - export type Me = { - __typename?: "User"; - id: number; - profile: Maybe; - favFriend: Maybe; - } - - export type Profile = { - __typename?: "Profile"; - name: string; - } - - export type FavFriend = { - __typename?: "User"; - id: number; - profile: Maybe<_Profile>; - favFriend: Maybe<_FavFriend>; - } - - export type _Profile = { - __typename?: "Profile"; - email: string; - } - - export type _FavFriend = { - __typename?: "User"; - id: number; - profile: Maybe<__Profile>; - } - - export type __Profile = { - __typename?: "Profile"; - email: string; - } - }`); - }); - - it('Should generate anonymous Query correctly', async () => { - const query = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace AnonymousQuery_1 { - export type Variables = { - } - export type Query = { - __typename?: "Query"; - feed: Maybe<(Maybe)[]>; - } - export type Feed = { - __typename?: "Entry"; - id: number; - commentCount: number; - repository: Repository; - } - export type Repository = { - __typename?: "Repository"; - full_name: string; - html_url: string; - owner: Maybe; - } - export type Owner = { - __typename?: "User"; - avatar_url: string; - } - }`); - }); - - it('Should generate simple Query with Fragment spread correctly', async () => { - const query = gql` - query myFeed { - feed { - id - commentCount - repository { - full_name - ...RepoFields - } - } - } - - fragment RepoFields on Repository { - html_url - owner { - avatar_url - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace MyFeed { - export type Variables = { - } - export type Query = { - __typename?: "Query"; - feed: Maybe<(Maybe)[]>; - } - export type Feed = { - __typename?: "Entry"; - id: number; - commentCount: number; - repository: Repository; - } - export type Repository = { - __typename?: "Repository"; - full_name: string; - } & RepoFields.Fragment - } - `); - expect(content).toBeSimilarStringTo(` - export namespace RepoFields { - export type Fragment = { - __typename?: "Repository"; - html_url: string; - owner: Maybe; - } - export type Owner = { - __typename?: "User"; - avatar_url: string; - } - } - `); - }); - - it('should preserve a prefix for Unions', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - schema { - query: Query - } - - type Query { - me: User - user(id: ID!): User - } - - type Pizza { - dough: String! - toppings: [String!] - } - - type Hamburger { - patty: String! - toppings: [String!] - } - - union FavoriteFood = Pizza | Hamburger - - type User { - id: ID! - favoriteFood: FavoriteFood! - } - ` - }); - - const query = gql` - query findUser($userId: ID!) { - user(id: $userId) { - id - favoriteFood { - ... on Pizza { - dough - toppings - } - ... on Hamburger { - patty - toppings - } - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - { noNamespaces: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type FindUserUser = { - __typename?: "User"; - id: string; - favoriteFood: FindUserFavoriteFood; - } - `); - - expect(content).toBeSimilarStringTo(` - export type FindUserFavoriteFood = - `); - }); - - it('Should generate correctly when using scalar and noNamespace', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - scalar JSON - - enum Access { - Read - Write - All - } - - type User { - id: Int! - data: JSON - access: Access - } - - type Query { - me: User - } - ` - }); - const query = gql` - query me { - me { - id - data - access - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - { noNamespaces: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type MeVariables = { - } - `); - - expect(content).toBeSimilarStringTo(` - export type MeQuery = { - __typename?: "Query"; - me: Maybe; - } - `); - - expect(content).toBeSimilarStringTo(` - export type MeMe = { - __typename?: "User"; - id: number; - data: Maybe; - access: Maybe; - } - `); - }); - - it('Should generate correctly when using enums and interfacePrefix', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - enum Access { - Read - Write - All - } - - type User { - access: Access - } - - input Filter { - match: String! - } - - type Query { - users(filter: Filter!): [User] - } - ` - }); - const query = gql` - query users($filter: Filter!) { - users(filter: $filter) { - access - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - { interfacePrefix: 'PREFIX_' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace Users { - export type Variables = { - filter: PREFIX_Filter; - } - - export type Query = { - __typename?: "Query"; - - users: Maybe<(Maybe)[]>; - } - - export type Users = { - __typename?: "User"; - - access: Maybe; - } - } - `); - }); - - it('Should generate simple Query with inline Fragment and handle noNamespaces', async () => { - const query = gql` - query myFeed { - feed { - id - commentCount - repository { - html_url - ... on Repository { - full_name - } - ... on Repository { - owner { - avatar_url - } - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - { noNamespaces: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type MyFeedVariables = { - } - - export type MyFeedQuery = { - __typename?: "Query"; - feed: Maybe<(Maybe)[]>; - } - - export type MyFeedFeed = { - __typename?: "Entry"; - id: number; - commentCount: number; - repository: MyFeedRepository; - } - - export type MyFeedRepository = { - __typename?: MyFeedRepositoryInlineFragment["__typename"] | MyFeed_RepositoryInlineFragment["__typename"]; - html_url: string; - } & (MyFeedRepositoryInlineFragment & MyFeed_RepositoryInlineFragment) - - export type MyFeedRepositoryInlineFragment = { - __typename?: "Repository"; - full_name: string; - } - - export type MyFeed_RepositoryInlineFragment = { - __typename?: "Repository"; - owner: Maybe; - } - - export type MyFeedOwner = { - __typename?: "User"; - avatar_url: string; - } -`); - }); - - it('Should generate simple Query with inline Fragment', async () => { - const query = gql` - query myFeed { - feed { - id - commentCount - repository { - html_url - ... on Repository { - full_name - } - ... on Repository { - owner { - avatar_url - } - } - } - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace MyFeed { - export type Variables = { - } - - export type Query = { - __typename?: "Query"; - feed: Maybe<(Maybe)[]>; - } - - export type Feed = { - __typename?: "Entry"; - id: number; - commentCount: number; - repository: Repository; - } - - export type Repository = { - __typename?: RepositoryInlineFragment["__typename"] | _RepositoryInlineFragment["__typename"]; - html_url: string; - } & (RepositoryInlineFragment & _RepositoryInlineFragment) - - export type RepositoryInlineFragment = { - __typename?: "Repository"; - full_name: string; - } - - export type _RepositoryInlineFragment = { - __typename?: "Repository"; - owner: Maybe; - } - - export type Owner = { - __typename?: "User"; - avatar_url: string; - } - } - `); - }); - - it('Should group fragments by type', async () => { - const testSchema = makeExecutableSchema({ - resolverValidationOptions: { - requireResolversForResolveType: false - }, - typeDefs: ` - type Photo { - height: Int! - width: Int! - } - - type Sport { - id: Int! - name: String! - teams: Int! - } - - union Extra = Photo | Sport - - type Person { - extra: Extra - } - - type Query { - person: Person - } - ` - }); - - const query = gql` - fragment PhotoFragment on Photo { - width - } - fragment SportFragment on Sport { - id - } - query search { - person { - extra { - ...PhotoFragment - ...SportFragment - ... on Sport { - name - } - ... on Photo { - height - } - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Extra = ((SportInlineFragment & SportFragment.Fragment) | (PhotoInlineFragment & PhotoFragment.Fragment)) - `); - }); - - it('Should generate simple Query with Fragment spread and handle noNamespaces', async () => { - const query = gql` - query myFeed { - feed { - id - commentCount - repository { - full_name - ...RepoFields - } - } - } - fragment RepoFields on Repository { - html_url - owner { - avatar_url - } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: query }], - { noNamespaces: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type MyFeedVariables = { - } - export type MyFeedQuery = { - __typename?: "Query"; - feed: Maybe<(Maybe)[]>; - } - export type MyFeedFeed = { - __typename?: "Entry"; - id: number; - commentCount: number; - repository: MyFeedRepository; - } - export type MyFeedRepository = { - __typename?: "Repository"; - full_name: string; - } & RepoFieldsFragment -`); - expect(content).toBeSimilarStringTo(` - export type RepoFieldsFragment = { - __typename?: "Repository"; - html_url: string; - owner: Maybe; - } - export type RepoFieldsOwner = { - __typename?: "User"; - avatar_url: string; - } -`); - }); - - it('should generate correctly when using immutableTypes and noNamespace', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Country { - id: Int! - code: String! - name: String! - } - - type CountriesPayload { - countries: [Country!] - } - - type Query { - countries: CountriesPayload! - } - ` - }); - const query = gql` - query Countries { - countries { - countries { - code - name - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - { - immutableTypes: true, - noNamespaces: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type CountriesCountries = { - readonly __typename?: "CountriesPayload"; - readonly countries: Maybe>; - } - `); - }); - - it('should generate correctly when using immutableTypes', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Country { - id: Int! - code: String! - name: String! - } - - type CountriesPayload { - countries: [Country!] - } - - type Query { - countries: CountriesPayload! - } - ` - }); - const query = gql` - query Countries { - countries { - countries { - code - name - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - { - immutableTypes: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Countries = { - readonly __typename?: "CountriesPayload"; - readonly countries: Maybe>; - } - `); - }); - - it('should generate correctly when using noNamespace', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Country { - id: Int! - code: String! - name: String! - } - - type CountriesPayload { - countries: [Country!] - } - - type Query { - countries: CountriesPayload! - } - ` - }); - const query = gql` - query Countries { - countries { - countries { - code - name - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - { - noNamespaces: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type CountriesCountries = { - __typename?: "CountriesPayload"; - countries: Maybe; - } - `); - }); - - it('should make __typename non optional when requested', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Post { - title: String - } - - type Query { - post: Post! - } - ` - }); - const query = gql` - query Post { - post { - __typename - title - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Query = { - __typename?: "Query"; - post: Post; - } - `); - - expect(content).toBeSimilarStringTo(` - export type Post = { - __typename: "Post"; - title: Maybe; - } - `); - }); - - it('should make __typename non optional when requested within an inline fragment', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Post { - title: String - } - - type Query { - post: Post! - } - ` - }); - const query = gql` - query Post { - post { - ... on Post { - __typename - title - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Query = { - __typename?: "Query"; - post: Post; - } - `); - - expect(content).toBeSimilarStringTo(` - export type PostInlineFragment = { - __typename: "Post"; - title: Maybe; - } - `); - }); - - it('should use __typename in fragments when requested', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Post { - title: String - } - - type Query { - post: Post! - } - ` - }); - const query = gql` - query Post { - post { - ... on Post { - __typename - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Query = { - __typename?: "Query"; - post: Post; - } - `); - - expect(content).toBeSimilarStringTo(` - export type PostInlineFragment = { - __typename: "Post"; - } - `); - }); - - it('should handle introspection types (__schema)', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Post { - title: String - } - - type Query { - post: Post! - } - ` - }); - const query = gql` - query Info { - __schema { - queryType { - fields { - name - } - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace Info { - export type Variables = { - } - - export type Query = { - __typename?: "Query"; - - __schema: Schema; - } - - export type Schema = { - __typename?: "__Schema"; - - queryType: QueryType; - } - - export type QueryType = { - __typename?: "__Type"; - - fields: Maybe; - } - - export type Fields = { - __typename?: "__Field"; - - name: string; - } - } - `); - }); - - it('should handle introspection types (__type)', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type Post { - title: String - } - - type Query { - post: Post! - } - ` - }); - const query = gql` - query Info { - __type(name: "Post") { - name - fields { - name - type { - name - kind - } - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace Info { - export type Variables = { - } - - export type Query = { - __typename?: "Query"; - __type: Maybe; - } - - export type Type = { - __typename?: "__Type"; - - name: Maybe; - fields: Maybe; - } - - export type Fields = { - __typename?: "__Field"; - name: string; - type: _Type; - } - - export type _Type = { - __typename?: "__Type"; - name: Maybe; - kind: __TypeKind; - } - } - `); - }); - - it('avoid duplicates - each type name should be unique', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: gql` - type DeleteMutation { - deleted: Boolean! - } - - type UpdateMutation { - updated: Boolean! - } - - union MessageMutationType = DeleteMutation | UpdateMutation - - type Query { - dummy: String - } - - type Mutation { - mutation(message: String!, type: String!): MessageMutationType! - } - ` - }); - const query = gql` - mutation SubmitMessage($message: String!) { - mutation(message: $message) { - ... on DeleteMutation { - deleted - } - ... on UpdateMutation { - updated - } - } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content.match(/type Mutation\b/g)).toHaveLength(1); - }); -}); diff --git a/packages/plugins/typescript-common/package.json b/packages/plugins/typescript-common/package.json deleted file mode 100644 index 2b1742692b1..00000000000 --- a/packages/plugins/typescript-common/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "graphql-codegen-typescript-common", - "version": "0.18.0", - "description": "graphql-codegen-cli template for TypeScript typings for both client side and server side", - "repository": "git@github.com:dotansimha/graphql-code-generator.git", - "license": "MIT", - "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build", - "test": "codegen-templates-scripts test" - }, - "dependencies": { - "change-case": "3.1.0", - "common-tags": "1.8.0", - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0" - }, - "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" - }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] - } -} diff --git a/packages/plugins/typescript-common/src/enum.handlebars b/packages/plugins/typescript-common/src/enum.handlebars deleted file mode 100644 index 1df6fbab712..00000000000 --- a/packages/plugins/typescript-common/src/enum.handlebars +++ /dev/null @@ -1,23 +0,0 @@ -{{{ toComment description }}} -{{#with (importEnum name) }} - {{#if file}} - import {{#if type}}{ {{type}}{{#ifCond type "!=" (concat @root.config.interfacePrefix (convert name 'typeNames'))}} as {{@root.config.interfacePrefix}}{{ convert name 'typeNames' }}{{/ifCond}} }{{else}}{{@root.config.interfacePrefix}}{{ convert name 'typeNames' }}{{/if}} from "{{file}}" - - export type {{@root.config.interfacePrefix}}{{ convert (concat name "ValueMap") 'typeNames'}} = { - {{#each ../values}} - {{{ value }}}: {{@root.config.interfacePrefix}}{{ convert ../name 'typeNames' }}, - {{/each}} - } - {{/if}} - -{{else}} - {{#if @root.config.enumsAsTypes }} - export type {{@root.config.interfacePrefix}}{{ convert name 'typeNames' }} = {{#each values }}{{{ getEnumValue ../name value }}}{{#unless @last}} | {{/unless}}{{/each}}; - {{else}} - export {{#if @root.config.constEnums }}const {{/if}}enum {{@root.config.interfacePrefix}}{{ convert name 'typeNames' }} { - {{#each values }} - {{ convert value 'enumValues' }} = {{{ getEnumValue ../name value }}}, - {{/each}} - } - {{/if}} -{{/with}} diff --git a/packages/plugins/typescript-common/src/helpers.ts b/packages/plugins/typescript-common/src/helpers.ts deleted file mode 100644 index 03bd7b8571f..00000000000 --- a/packages/plugins/typescript-common/src/helpers.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Field } from 'graphql-codegen-core'; -import { SafeString } from 'handlebars'; -import * as Handlebars from 'handlebars'; - -export function concat(...args: string[]) { - args.pop(); // HBS options passed as last argument - - return args.join(''); -} - -export function defineMaybe(options: Handlebars.HelperOptions): string { - const config = options.data.root.config || {}; - const optionalType = config.optionalType || 'null'; - - return `export type Maybe = T | ${optionalType};`; -} - -export function useMaybe(type: string): string { - return `Maybe<${type}>`; -} - -export function getScalarType(type: string, options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - if (config.scalars && type in config.scalars) { - return config.scalars[type as string]; - } else { - return 'any'; - } -} - -export function importEnum(name: string, options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - const definition = config.enums && config.enums[name]; - - if (typeof definition === 'string') { - // filename specified with optional type name - const [file, type] = config.enums[name].split('#'); - return { name, file, type }; - } - - if (typeof definition === 'object' && definition === null) { - // empty definition: don't generate anything - return {}; - } - - // fall through to normal or value-mapped generation - return undefined; -} - -export function getEnumValue(type: string, name: string, options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - if (config.enums && config.enums[type] != null && name in config.enums[type]) { - return config.enums[type][name]; - } else { - return `"${name}"`; - } -} - -export function getFieldType(field: Field, realType: string, options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - const useImmutable = !!config.immutableTypes; - - function extendType(type: string) { - return field.hasDefaultValue ? type : useMaybe(type); - } - - if (field.isArray) { - let result = realType; - - const dimension = field.dimensionOfArray + 1; - - if (field.isNullableArray) { - result = useImmutable ? useMaybe(realType) : `(${useMaybe(realType)})`; - } - - if (useImmutable) { - result = `${new Array(dimension).join('ReadonlyArray<')}${result}${new Array(dimension).join('>')}`; - } else { - result = `${result}${new Array(dimension).join('[]')}`; - } - - if (!field.isRequired) { - result = extendType(result); - } - - return result; - } else { - if (field.isRequired) { - return realType; - } else { - return extendType(realType); - } - } -} - -export function getOptionals(type: Field, options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - - if ( - config.avoidOptionals === '1' || - config.avoidOptionals === 'true' || - config.avoidOptionals === true || - config.avoidOptionals === 1 - ) { - return ''; - } - - if (!type.isRequired) { - return '?'; - } - - return ''; -} - -export const getType = (convert: Function) => (type: Field, options: Handlebars.HelperOptions) => { - if (!type) { - return ''; - } - - const result = convertedType(type, options, convert); - - return new SafeString(result); -}; - -export function convertedType(type: Field, options: Handlebars.HelperOptions, convert, skipConversion = false) { - const baseType = type.type; - const config = options.data.root.config || {}; - const realType = - options.data.root.primitives[baseType] || - `${type.isScalar ? '' : config.interfacePrefix || ''}${skipConversion ? baseType : convert(baseType, 'typeNames')}`; - - return getFieldType(type, realType, options); -} diff --git a/packages/plugins/typescript-common/src/index.ts b/packages/plugins/typescript-common/src/index.ts deleted file mode 100644 index ba059adacb0..00000000000 --- a/packages/plugins/typescript-common/src/index.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { PluginFunction, DocumentFile, schemaToTemplateContext } from 'graphql-codegen-core'; -import { GraphQLSchema } from 'graphql'; -import { helpers } from 'graphql-codegen-plugin-handlebars-helpers'; -import { resolveExternalModuleAndFn } from 'graphql-codegen-plugin-helpers'; -import * as enumTemplate from './enum.handlebars'; -import * as type from './type.handlebars'; -import * as rootTemplate from './root.handlebars'; -import * as Handlebars from 'handlebars'; -import { getOptionals, getType, getEnumValue, getScalarType, defineMaybe, importEnum, concat } from './helpers'; -import { pascalCase } from 'change-case'; - -export * from './helpers'; - -export interface TypeScriptNamingConventionMap { - default?: string | Function; - enumValues?: string | Function; - typeNames?: string | Function; -} - -export interface TypeScriptCommonConfig { - namingConvention?: string | TypeScriptNamingConventionMap; - avoidOptionals?: boolean; - optionalType?: string; - constEnums?: boolean; - enumsAsTypes?: boolean; - immutableTypes?: boolean; - interfacePrefix?: string; - enums?: { [enumName: string]: { [valueName: string]: string } | string | null }; - scalars?: { [scalarName: string]: string }; -} - -export const DEFAULT_SCALARS = { - String: 'string', - Int: 'number', - Float: 'number', - Boolean: 'boolean', - ID: 'string' -}; - -export function initCommonTemplate(hbs, schema, documents: DocumentFile[], config: TypeScriptCommonConfig) { - const scalars = { ...DEFAULT_SCALARS, ...(config.scalars || {}) }; - let namingConventionMap: TypeScriptNamingConventionMap; - if (typeof config.namingConvention === 'undefined') { - namingConventionMap = { - default: pascalCase, - enumValues: pascalCase, - typeNames: pascalCase - }; - } else if (typeof config.namingConvention === 'string') { - namingConventionMap = { - default: config.namingConvention, - enumValues: config.namingConvention, - typeNames: config.namingConvention - }; - } else { - namingConventionMap = { - default: config.namingConvention.default || pascalCase, - enumValues: config.namingConvention.enumValues || config.namingConvention.default || pascalCase, - typeNames: config.namingConvention.typeNames || config.namingConvention.default || pascalCase - }; - } - const convert = (str: string, kind: keyof TypeScriptNamingConventionMap = 'default'): string => { - // Workaround for use-case as `{{ convert something }}` without specifying. The "kind" arguemnt - // will contains the "options" value of Handlebars, in this case we need to override it to be "default". - - if (typeof kind === 'object') { - kind = 'default'; - } - - const baseConvertFn = - !namingConventionMap[kind] || namingConventionMap[kind] === 'keep' - ? (str: string) => str - : typeof namingConventionMap[kind] === 'string' - ? resolveExternalModuleAndFn(namingConventionMap[kind] as string) - : namingConventionMap[kind]; - - if (str.charAt(0) === '_') { - const after = str.replace( - /^(_*)(.*)/, - (_match, underscorePrefix, typeName) => `${underscorePrefix}${baseConvertFn(typeName || '')}` - ); - - return after; - } - - return baseConvertFn(str); - }; - hbs.registerPartial('enum', enumTemplate); - hbs.registerPartial('type', type); - hbs.registerHelper('concat', concat); - hbs.registerHelper('defineMaybe', defineMaybe); - hbs.registerHelper('blockComment', helpers.blockComment); - hbs.registerHelper('blockCommentIf', helpers.blockCommentIf); - hbs.registerHelper('toComment', helpers.toComment); - hbs.registerHelper('convert', convert); - hbs.registerHelper('getOptionals', getOptionals); - hbs.registerHelper('getEnumValue', getEnumValue); - hbs.registerHelper('importEnum', importEnum); - hbs.registerHelper('convertedType', getType(convert)); - hbs.registerHelper('toLowerCase', helpers.toLowerCase); - hbs.registerHelper('toUpperCase', helpers.toUpperCase); - hbs.registerHelper('times', helpers.times); - hbs.registerHelper('stringify', helpers.stringify); - hbs.registerHelper('ifDirective', helpers.ifDirective); - hbs.registerHelper('ifCond', helpers.ifCond); - hbs.registerHelper('getScalarType', getScalarType); - hbs.registerHelper('unlessDirective', helpers.unlessDirective); - hbs.registerHelper('toPrimitive', type => scalars[type] || type || ''); - - const templateContext = schemaToTemplateContext(schema, documents); - - return { - templateContext: { - ...templateContext, - config, - primitives: scalars - }, - convert, - scalars - }; -} - -export const plugin: PluginFunction = async ( - schema: GraphQLSchema, - documents: DocumentFile[], - config: TypeScriptCommonConfig -): Promise => { - const { templateContext } = initCommonTemplate(Handlebars, schema, documents, config); - - return Handlebars.compile(rootTemplate)(templateContext); -}; diff --git a/packages/plugins/typescript-common/src/polyfills.d.ts b/packages/plugins/typescript-common/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-common/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-common/src/root.handlebars b/packages/plugins/typescript-common/src/root.handlebars deleted file mode 100644 index 98b88e7630a..00000000000 --- a/packages/plugins/typescript-common/src/root.handlebars +++ /dev/null @@ -1,13 +0,0 @@ -{{{ defineMaybe }}} - -{{#each inputTypes}} - {{~> type }} -{{/each}} -{{#each enums}} - {{~> enum }} -{{/each}} -{{#each scalars}} - -{{ toComment description }} -{{#ifCond (convert name 'typeNames' ) "!==" (getScalarType name) }}export type {{ convert name 'typeNames' }} = {{ getScalarType name }};{{/ifCond}} -{{/each}} \ No newline at end of file diff --git a/packages/plugins/typescript-common/src/type.handlebars b/packages/plugins/typescript-common/src/type.handlebars deleted file mode 100644 index 63a076ba5ba..00000000000 --- a/packages/plugins/typescript-common/src/type.handlebars +++ /dev/null @@ -1,7 +0,0 @@ -{{ toComment description }} -export interface {{@root.config.interfacePrefix}}{{ convert name 'typeNames' }}{{#if hasInterfaces}} extends {{#each interfaces}}{{@root.config.interfacePrefix}}{{ convert this 'typeNames' }}{{#unless @last}},{{/unless}}{{/each}}{{/if}} { -{{#each fields}} - {{ toComment description }} - {{#if @root.config.immutableTypes }}readonly {{/if}}{{ name }}{{ getOptionals this }}: {{ convertedType this }}; -{{/each}} -} diff --git a/packages/plugins/typescript-common/tests/typescript-common.spec.ts b/packages/plugins/typescript-common/tests/typescript-common.spec.ts deleted file mode 100644 index afa8254572b..00000000000 --- a/packages/plugins/typescript-common/tests/typescript-common.spec.ts +++ /dev/null @@ -1,714 +0,0 @@ -import 'graphql-codegen-core/dist/testing'; -import { GraphQLSchema, parse } from 'graphql'; -import { makeExecutableSchema } from 'graphql-tools'; -import { plugin } from '../dist'; - -describe('TypeScript Common', () => { - function buildSchema(ast: string): GraphQLSchema { - return makeExecutableSchema({ - typeDefs: ast, - allowUndefinedInResolve: true - }); - } - - const schema = buildSchema(` - type Foo { - bar: Bar - } - - type Bar { - qux: String - } - - input myTypeNOnStandart { - f: String - } - - enum FOODEnum { - PIZZA, - BURGER, - } - - input T { - f1: String - f2: Int! - f3: [String] - f4: [String]! - f5: [String!]! - f6: [String!] - f7: Int = 42 - } - `); - - it('should have correct Maybe type', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - type Maybe = T | null; - `); - }); - - it('should have customizable Maybe type', async () => { - const content = await plugin( - schema, - [], - { - optionalType: 'undefined' - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - type Maybe = T | undefined; - `); - }); - - describe('namingConvention', () => { - it('Should use pascal case by default', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).not.toContain(`myTypeNOnStandart`); - expect(content).toContain(`MyTypeNOnStandart`); - }); - - it('Should generate enums in PascalCase by default', async () => { - const content = await plugin( - buildSchema(` - enum FOODEnum { - PIZZA, - BURGER, - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export enum FoodEnum { - Pizza = "PIZZA", - Burger = "BURGER", - } - `); - }); - - it('Should generate enums in PascalCase by default when enumsAsTypes is used', async () => { - const content = await plugin( - buildSchema(` - enum FOODEnum { - PIZZA, - BURGER, - } - `), - [], - { - enumsAsTypes: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type FoodEnum = "PIZZA" | "BURGER"; - `); - }); - - it('Should use different naming when overridden', async () => { - const content = await plugin( - schema, - [], - { namingConvention: 'change-case#lowerCase' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).not.toContain(`myTypeNOnStandart`); - expect(content).toContain(`mytypenonstandart`); - }); - - it('Should throw when module does not exists', async () => { - let thrown = false; - try { - await plugin( - schema, - [], - { namingConvention: 'oops#boop' }, - { - outputFile: 'graphql.ts' - } - ); - } catch (e) { - thrown = true; - expect(e.message).toContain(`Cannot find module`); - } - - expect(thrown).toBeTruthy(); - }); - - it('Should throw when method does not exists', async () => { - let thrown = false; - try { - await plugin( - schema, - [], - { namingConvention: 'change-case#boop' }, - { - outputFile: 'graphql.ts' - } - ); - } catch (e) { - thrown = true; - expect(e.message).toContain(`boop couldn't be found in module change-case!`); - } - - expect(thrown).toBeTruthy(); - }); - }); - - describe('Enums', () => { - it('Should generate enums as interface by default', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export enum FoodEnum { - Pizza = "PIZZA", - Burger = "BURGER", - } - `); - }); - - it('Should generate enums as types with enumsAsTypes', async () => { - const content = await plugin( - schema, - [], - { enumsAsTypes: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(`export type FoodEnum = "PIZZA" | "BURGER";`); - }); - - it('Should generate const enums as types with constEnums', async () => { - const content = await plugin( - schema, - [], - { constEnums: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export const enum FoodEnum { - Pizza = "PIZZA", - Burger = "BURGER", - }`); - }); - - it('Should generate correct enum names with interfacePrefix', async () => { - const content = await plugin( - schema, - [], - { interfacePrefix: 'Pref' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export enum PrefFoodEnum { - Pizza = "PIZZA", - Burger = "BURGER", - }`); - }); - - it('Should generate the correct output with custom enums value', async () => { - const content = await plugin( - schema, - [], - { - enums: { - FOODEnum: { - PIZZA: 'pizza', - BURGER: 'burger' - } - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export enum FoodEnum { - Pizza = pizza, - Burger = burger, - }`); - }); - - describe('When imported', () => { - it('Should import the default export', async () => { - const content = await plugin( - schema, - [], - { - enums: { - FOODEnum: 'some/path' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import FoodEnum from "some/path" - `); - }); - - it('Should import a named export', async () => { - const content = await plugin( - schema, - [], - { - enums: { - FOODEnum: 'some/path#A' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { A as FoodEnum } from "some/path" - `); - }); - - it('Should import an aliased named export', async () => { - const content = await plugin( - schema, - [], - { - enums: { - FOODEnum: 'some/path#MyCustomA' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { MyCustomA as FoodEnum } from "some/path" - `); - }); - - it('Should import the default export with interfacePrefix', async () => { - const content = await plugin( - schema, - [], - { - interfacePrefix: 'Pref', - enums: { - FOODEnum: 'some/path' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import PrefFoodEnum from "some/path" - `); - }); - - it('Should import a named export with interfacePrefix', async () => { - const content = await plugin( - schema, - [], - { - interfacePrefix: 'Pref', - enums: { - FOODEnum: 'some/path#A' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { A as PrefFoodEnum } from "some/path" - `); - }); - - it('Should import an aliased named export with interfacePrefix', async () => { - const content = await plugin( - schema, - [], - { - interfacePrefix: 'Pref', - enums: { - FOODEnum: 'some/path#MyCustomA' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { MyCustomA as PrefFoodEnum } from "some/path" - `); - }); - - it('Should generate the value map with interfacePrefix', async () => { - const content = await plugin( - schema, - [], - { - interfacePrefix: 'Pref', - enums: { - FOODEnum: 'some/path#MyCustomA' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type PrefFoodEnumValueMap = { - PIZZA: PrefFoodEnum, - BURGER: PrefFoodEnum, - } - `); - }); - - it('Should skip generation of an empty definition', async () => { - const content = await plugin( - schema, - [], - { - enums: { - FOODEnum: null - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).not.toBeSimilarStringTo(` - import FoodEnum from - `); - - expect(content).not.toBeSimilarStringTo(` - import { FoodEnum - `); - - expect(content).not.toBeSimilarStringTo(` - export enum FoodEnum {" - `); - - expect(content).not.toBeSimilarStringTo(` - export type FoodEnumValueMap {" - `); - }); - }); - - it('Should generate the correct description for enums', async () => { - const content = await plugin( - buildSchema(` - # MyEnumA - enum FoodEnum { - PIZZA, - BURGER, - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - /** MyEnumA */ - export enum FoodEnum { - Pizza = "PIZZA", - Burger = "BURGER", - }`); - }); - }); - - describe('Input Types', () => { - it('Should generate input type fields correctly', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface T { - f1?: Maybe; - f2: number; - f3?: Maybe<(Maybe)[]>; - f4: (Maybe)[]; - f5: string[]; - f6?: Maybe; - f7?: number; - } - `); - }); - it('Should generate input type fields correctly when noNamespaces is true', async () => { - const content = await plugin( - schema, - [], - { - noNamespaces: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface T { - f1?: Maybe; - f2: number; - f3?: Maybe<(Maybe)[]>; - f4: (Maybe)[]; - f5: string[]; - f6?: Maybe; - f7?: number; - } - `); - }); - - it('Should generate input type fields correctly when immutableTypes is set', async () => { - const content = await plugin( - schema, - [], - { immutableTypes: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface T { - readonly f1?: Maybe; - readonly f2: number; - readonly f3?: Maybe>>; - readonly f4: ReadonlyArray>; - readonly f5: ReadonlyArray; - readonly f6?: Maybe>; - readonly f7?: number; - } - `); - }); - - it('Should generate input type description', async () => { - const content = await plugin( - buildSchema(` - # inputTypeDesc - input T { - f: String! - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - /** inputTypeDesc */ - export interface T { - f: string; - } - `); - }); - - it('Should the correct prefix when interfacePrefix is set', async () => { - const content = await plugin( - schema, - [], - { interfacePrefix: 'Pre' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface PreT { - f1?: Maybe; - f2: number; - f3?: Maybe<(Maybe)[]>; - f4: (Maybe)[]; - f5: string[]; - f6?: Maybe; - f7?: number; - } - `); - }); - - it('Should the correct prefix when scalars is set', async () => { - const content = await plugin( - schema, - [], - { scalars: { String: 'boop' } }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface T { - f1?: Maybe; - f2: number; - f3?: Maybe<(Maybe)[]>; - f4: (Maybe)[]; - f5: boop[]; - f6?: Maybe; - f7?: number; - } - `); - }); - }); - - describe('Scalars', () => { - it('Should generate correctly scalars without definition of it', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: [Date] - } - - scalar Date - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Date = any; - `); - }); - - it('Should generate correctly scalars with custom scalar type', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: [Date] - } - - scalar Date - `), - [], - { - scalars: { - Date: 'MyCustomDate' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type Date = MyCustomDate; - `); - }); - }); - - it('should handle introspection types (__TypeKind)', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: /* GraphQL */ ` - type Post { - title: String - } - - type Query { - post: Post! - } - ` - }); - const query = parse(/* GraphQL */ ` - query Info { - __type(name: "Post") { - name - fields { - name - type { - name - kind - } - } - } - } - `); - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export enum __TypeKind { - Scalar = "SCALAR", - Object = "OBJECT", - Interface = "INTERFACE", - Union = "UNION", - Enum = "ENUM", - InputObject = "INPUT_OBJECT", - List = "LIST", - NonNull = "NON_NULL", - } - `); - }); -}); diff --git a/packages/plugins/typescript-graphql-files-modules/package.json b/packages/plugins/typescript-graphql-files-modules/package.json index c34fe343912..de8a0b058af 100644 --- a/packages/plugins/typescript-graphql-files-modules/package.json +++ b/packages/plugins/typescript-graphql-files-modules/package.json @@ -5,39 +5,25 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" + }, + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", + "graphql-codegen-testing": "0.18.0", "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0" + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/typescript-graphql-files-modules/src/index.ts b/packages/plugins/typescript-graphql-files-modules/src/index.ts index a2c1ef8870e..07d2cc7bb24 100644 --- a/packages/plugins/typescript-graphql-files-modules/src/index.ts +++ b/packages/plugins/typescript-graphql-files-modules/src/index.ts @@ -1,14 +1,46 @@ -import { DocumentFile, PluginFunction, PluginValidateFn, transformDocumentsFiles } from 'graphql-codegen-core'; -import { buildFilesArray } from 'graphql-codegen-plugin-helpers'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; +import { basename } from 'path'; +import { DocumentFile, PluginFunction, PluginValidateFn } from 'graphql-codegen-plugin-helpers'; +import { GraphQLSchema, OperationDefinitionNode } from 'graphql'; export const plugin: PluginFunction = async (schema: GraphQLSchema, documents: DocumentFile[]): Promise => { - const transformedDocuments = transformDocumentsFiles(schema, documents); - const files = buildFilesArray(transformedDocuments); + const mappedDocuments: { [fileName: string]: OperationDefinitionNode[] } = documents.reduce( + (prev, documentRecord) => { + const fileName = basename(documentRecord.filePath); - return Handlebars.compile(rootTemplate)({ files }); + if (!prev[fileName]) { + prev[fileName] = []; + } + + prev[fileName].push( + ...documentRecord.content.definitions.filter( + document => document.kind === 'OperationDefinition' || document.kind === 'FragmentDefinition' + ) + ); + + return prev; + }, + {} + ); + + return Object.keys(mappedDocuments) + .filter(fileName => mappedDocuments[fileName].length > 0) + .map(fileName => { + const operations = mappedDocuments[fileName]; + + return ` +declare module '*/${fileName}' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + ${operations + .filter(d => d.name && d.name.value) + .map(d => `export const ${d.name.value}: DocumentNode;`) + .join('\n')} + + export default defaultDocument; +} + `; + }) + .join('\n'); }; export const validate: PluginValidateFn = async ( diff --git a/packages/plugins/typescript-graphql-files-modules/src/polyfills.d.ts b/packages/plugins/typescript-graphql-files-modules/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-graphql-files-modules/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-graphql-files-modules/src/root.handlebars b/packages/plugins/typescript-graphql-files-modules/src/root.handlebars deleted file mode 100644 index b9f258cec2a..00000000000 --- a/packages/plugins/typescript-graphql-files-modules/src/root.handlebars +++ /dev/null @@ -1,14 +0,0 @@ -{{#each files}} -declare module '*/{{ filename }}' { - import { DocumentNode } from 'graphql'; - const defaultDocument: DocumentNode; - {{#each documents}}{{#if operationType}}const {{ name }}: DocumentNode;{{/if}}{{/each}} - - export { - {{#each documents}}{{#if operationType}}{{ name }},{{/if}}{{/each}} - }; - - export default defaultDocument; -} - -{{/each}} \ No newline at end of file diff --git a/packages/plugins/typescript-graphql-files-modules/tests/graphql-files-modules.spec.ts b/packages/plugins/typescript-graphql-files-modules/tests/graphql-files-modules.spec.ts new file mode 100644 index 00000000000..5b9a28e70ad --- /dev/null +++ b/packages/plugins/typescript-graphql-files-modules/tests/graphql-files-modules.spec.ts @@ -0,0 +1,180 @@ +import 'graphql-codegen-testing'; +import { plugin } from '../src/index'; +import { parse } from 'graphql'; +import { validateTs } from '../../typescript/tests/validate'; + +describe('graphql-codegen-typescript-graphql-files-modules', () => { + it('Should generate simple module with one file', async () => { + const result = await plugin( + null, + [ + { + filePath: 'some/file/my-query.graphql', + content: parse(/* GraphQL */ ` + query MyQuery { + field + } + `) + } + ], + {}, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + declare module '*/my-query.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const MyQuery: DocumentNode; + + export default defaultDocument; + } + `); + validateTs(result); + }); + + it('Should generate correctly for mutiple files', async () => { + const result = await plugin( + null, + [ + { + filePath: 'some/file/my-query.graphql', + content: parse(/* GraphQL */ ` + query MyQuery { + field + } + `) + }, + { + filePath: 'some/file/my-other-query.graphql', + content: parse(/* GraphQL */ ` + query OtherQuery { + field + } + `) + } + ], + {}, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + declare module '*/my-query.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const MyQuery: DocumentNode; + + export default defaultDocument; + } + + declare module '*/my-other-query.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const OtherQuery: DocumentNode; + + export default defaultDocument; + } + `); + validateTs(result); + }); + + it('Should ignore unnamed documents', async () => { + const result = await plugin( + null, + [ + { + filePath: 'some/file/my-query.graphql', + content: parse(/* GraphQL */ ` + query { + field + } + `) + } + ], + {}, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + declare module '*/my-query.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + + export default defaultDocument; + } + `); + validateTs(result); + }); + + it('Should generate simple module with two documents in one file', async () => { + const result = await plugin( + null, + [ + { + filePath: 'some/file/my-query.graphql', + content: parse(/* GraphQL */ ` + query MyQuery { + field + } + + query OtherQuery { + field + } + `) + } + ], + {}, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + declare module '*/my-query.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const MyQuery: DocumentNode; + export const OtherQuery: DocumentNode; + + export default defaultDocument; + } + `); + validateTs(result); + }); + + it('Should generate simple module with two documents in two files, with same name', async () => { + const result = await plugin( + null, + [ + { + filePath: 'some/file/my-query.graphql', + content: parse(/* GraphQL */ ` + query MyQuery { + field + } + `) + }, + { + filePath: 'some/file-other-path/my-query.graphql', + content: parse(/* GraphQL */ ` + query OtherQuery { + field + } + `) + } + ], + {}, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + declare module '*/my-query.graphql' { + import { DocumentNode } from 'graphql'; + const defaultDocument: DocumentNode; + export const MyQuery: DocumentNode; + export const OtherQuery: DocumentNode; + + export default defaultDocument; + } + `); + validateTs(result); + }); +}); diff --git a/packages/plugins/typescript-graphql-files-modules/tsconfig.json b/packages/plugins/typescript-graphql-files-modules/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/typescript-graphql-files-modules/tsconfig.json +++ b/packages/plugins/typescript-graphql-files-modules/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/typescript-mongodb/package.json b/packages/plugins/typescript-mongodb/package.json index 6a91ab32604..5b1b5585f1f 100644 --- a/packages/plugins/typescript-mongodb/package.json +++ b/packages/plugins/typescript-mongodb/package.json @@ -5,46 +5,33 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "peerDependencies": { "graphql-tag": "^2.0.0" }, "dependencies": { - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" + "tslib": "1.9.3", + "graphql-toolkit": "0.2.6", + "graphql-codegen-typescript": "0.18.0", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" + "graphql-codegen-testing": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "flow-bin": "0.94.0", + "flow-parser": "0.94.0", + "graphql": "14.1.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/typescript-mongodb/src/fields-tree.ts b/packages/plugins/typescript-mongodb/src/fields-tree.ts new file mode 100644 index 00000000000..eec05969e9b --- /dev/null +++ b/packages/plugins/typescript-mongodb/src/fields-tree.ts @@ -0,0 +1,34 @@ +import { set } from 'lodash'; +import { indent } from 'graphql-codegen-visitor-plugin-common'; + +type FieldsResult = { [name: string]: string | FieldsResult }; + +export class FieldsTree { + private _fields: FieldsResult = {}; + + addField(path: string, type: string): void { + set(this._fields, path, type); + } + + private _getInnerField(root: FieldsResult, level = 1): string { + if (typeof root === 'string') { + return root; + } + + const fields = Object.keys(root).map(fieldName => { + const fieldValue = root[fieldName]; + + return indent(`${fieldName}: ${this._getInnerField(fieldValue as FieldsResult, level + 1)},`, level); + }); + + return level === 1 + ? fields.join('\n') + : `{ +${fields.join('\n')} +${indent('}', level - 1)}`; + } + + get string(): string { + return this._getInnerField(this._fields); + } +} diff --git a/packages/plugins/typescript-mongodb/src/helpers/entity-fields.ts b/packages/plugins/typescript-mongodb/src/helpers/entity-fields.ts deleted file mode 100644 index d95c8d93b29..00000000000 --- a/packages/plugins/typescript-mongodb/src/helpers/entity-fields.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { Field, Interface, Type } from 'graphql-codegen-core'; -import { set } from 'lodash'; -import { convertedType } from 'graphql-codegen-typescript-common'; - -// Directives fields -const ID_DIRECTIVE = 'id'; -const ENTITY_DIRECTIVE = 'entity'; -const ABSTRACT_ENTITY_DIRECTIVE = 'abstractEntity'; -const LINK_DIRECTIVE = 'link'; -const COLUMN_DIRECTIVE = 'column'; -const EMBEDDED_DIRECTIVE = 'embedded'; -const MAP_DIRECTIVE = 'map'; - -// Mapping -const ID_FIELD_NAME = '_id'; -const ENUM_TYPE = 'string'; -const ID_TYPE = 'ObjectID'; - -const appendField = convert => ( - obj: object, - field: string, - value: string, - mapDirectiveValue: null | { path: string } = null -) => { - if (mapDirectiveValue) { - set(obj, mapDirectiveValue.path, value); - } else { - set(obj, field, value); - } -}; - -type FieldsResult = { [name: string]: string | FieldsResult }; - -const buildFieldDef = convert => (type: string, field: Field, options: Handlebars.HelperOptions): string => { - return convertedType( - { - ...field, - type - }, - options, - convert, - true - ); -}; - -function convertToInterfaceDefinition(type: Type | Interface, obj: FieldsResult, root = true): string { - if (typeof obj === 'string') { - return obj; - } - - const result = Object.keys(obj).map(fieldName => { - const fieldValue = obj[fieldName]; - - return `${fieldName}: ${convertToInterfaceDefinition(type, fieldValue as FieldsResult, false)}`; - }); - - let appendExtensions = ''; - - if (root && type['interfaces'] && type['interfaces'].length > 0) { - const interfaces = type['interfaces'] as string[]; - - appendExtensions = ` extends ${interfaces.map(n => `${n}DbInterface`).join(', ')} `; - } - - return `${appendExtensions}{\n${result.join('\n')}\n}`; -} - -export const entityFields = convert => ( - type: Type | Interface, - options: Handlebars.HelperOptions, - returnRaw = false -) => { - if (type && (type.directives[ENTITY_DIRECTIVE] || type.directives[ABSTRACT_ENTITY_DIRECTIVE])) { - const allFields = type.fields || []; - const finalResult: FieldsResult = {}; - - if (type.directives[ABSTRACT_ENTITY_DIRECTIVE] && type.directives[ABSTRACT_ENTITY_DIRECTIVE].discriminatorField) { - appendField(convert)(finalResult, type.directives[ABSTRACT_ENTITY_DIRECTIVE].discriminatorField, 'string'); - } - - for (const field of allFields) { - if (field.directives[ID_DIRECTIVE]) { - appendField(convert)( - finalResult, - ID_FIELD_NAME, - buildFieldDef(convert)(ID_TYPE, field, options), - field.directives[MAP_DIRECTIVE] - ); - } else if (field.directives[LINK_DIRECTIVE]) { - appendField(convert)( - finalResult, - field.name, - buildFieldDef(convert)(ID_TYPE, field, options), - field.directives[MAP_DIRECTIVE] - ); - } else if (field.directives[COLUMN_DIRECTIVE]) { - if (field.isEnum) { - appendField(convert)( - finalResult, - field.name, - buildFieldDef(convert)(ENUM_TYPE, field, options), - field.directives[MAP_DIRECTIVE] - ); - } else { - appendField(convert)( - finalResult, - field.directives[COLUMN_DIRECTIVE].name ? field.directives[COLUMN_DIRECTIVE].name : field.name, - buildFieldDef(convert)( - field.directives[COLUMN_DIRECTIVE].overrideType - ? field.directives[COLUMN_DIRECTIVE].overrideType - : field.type, - field.directives[COLUMN_DIRECTIVE].overrideIsArray !== undefined - ? { - ...field, - isArray: field.directives[COLUMN_DIRECTIVE].overrideIsArray, - dimensionOfArray: 1 - } - : field, - options - ), - field.directives[MAP_DIRECTIVE] - ); - } - } else if (field.directives[EMBEDDED_DIRECTIVE]) { - appendField(convert)( - finalResult, - field.name, - buildFieldDef(convert)(`${field.type}DbObject`, field, options), - field.directives[MAP_DIRECTIVE] - ); - } - } - - const additionalFields: [{ path: string; type: string }] = - (type.directives[ENTITY_DIRECTIVE] && type.directives[ENTITY_DIRECTIVE].additionalFields) || []; - - if (additionalFields.length > 0) { - for (const field of additionalFields) { - appendField(convert)(finalResult, field.path, field.type); - } - } - - if (returnRaw) { - return finalResult; - } - - return convertToInterfaceDefinition(type, finalResult); - } - - return ''; -}; diff --git a/packages/plugins/typescript-mongodb/src/helpers/filter-model-fields.ts b/packages/plugins/typescript-mongodb/src/helpers/filter-model-fields.ts deleted file mode 100755 index bfc0fdbde73..00000000000 --- a/packages/plugins/typescript-mongodb/src/helpers/filter-model-fields.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AstNode } from 'graphql-codegen-core'; - -function filterModelFields(fieldsArray: AstNode[], options: Handlebars.HelperOptions) { - let result = ''; - const validFields: AstNode[] = []; - - if (!fieldsArray) { - throw new Error(`Invalid context for filterModelFields: ${JSON.stringify(fieldsArray)}`); - } - - fieldsArray.forEach(gqlField => { - if ( - gqlField.directives.id || - gqlField.directives.link || - gqlField.directives.column || - gqlField.directives.embedded - ) { - validFields.push(gqlField); - } - }); - - validFields.forEach(field => { - result += options.fn(field); - }); - - return result; -} - -export default filterModelFields; diff --git a/packages/plugins/typescript-mongodb/src/helpers/if-not-root-type.ts b/packages/plugins/typescript-mongodb/src/helpers/if-not-root-type.ts deleted file mode 100644 index 1b197ef034f..00000000000 --- a/packages/plugins/typescript-mongodb/src/helpers/if-not-root-type.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Type } from 'graphql-codegen-core'; -import { GraphQLSchema, GraphQLObjectType } from 'graphql'; - -function getRootTypeNames(schema: GraphQLSchema): string[] { - const query = ((schema.getQueryType() || {}) as GraphQLObjectType).name; - const mutation = ((schema.getMutationType() || {}) as GraphQLObjectType).name; - const subscription = ((schema.getSubscriptionType() || {}) as GraphQLObjectType).name; - - return [query, mutation, subscription]; -} - -function ifNotRootType(this: any, type: Type, options: Handlebars.HelperOptions) { - const schema: GraphQLSchema = options.data.root.rawSchema; - - if (!getRootTypeNames(schema).includes(type.name)) { - return options.fn(this); - } else { - return options.inverse(this); - } -} - -export default ifNotRootType; diff --git a/packages/plugins/typescript-mongodb/src/helpers/is-array.ts b/packages/plugins/typescript-mongodb/src/helpers/is-array.ts deleted file mode 100755 index ccd906343b0..00000000000 --- a/packages/plugins/typescript-mongodb/src/helpers/is-array.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Field } from 'graphql-codegen-core'; - -function isArray(this: any, field: Field, options: Handlebars.HelperOptions) { - if (!field) { - return ''; - } - - if (field.isArray || (field.directives.column && field.directives.column.overrideIsArray)) { - return options.fn(this); - } else { - return options.inverse(this); - } -} - -export default isArray; diff --git a/packages/plugins/typescript-mongodb/src/helpers/is-primitive.ts b/packages/plugins/typescript-mongodb/src/helpers/is-primitive.ts deleted file mode 100755 index 3d7aff2efe8..00000000000 --- a/packages/plugins/typescript-mongodb/src/helpers/is-primitive.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Field } from 'graphql-codegen-core'; - -export const isPrimitive = map => - function(this: any, field: Field | keyof typeof map, options: Handlebars.HelperOptions) { - if (!field) { - return options.inverse(this); - } else { - if (map[field as keyof typeof map]) { - return options.fn(this); - } else { - return options.inverse(this); - } - } - }; diff --git a/packages/plugins/typescript-mongodb/src/index.ts b/packages/plugins/typescript-mongodb/src/index.ts index 19992c92ad4..43112a24e64 100644 --- a/packages/plugins/typescript-mongodb/src/index.ts +++ b/packages/plugins/typescript-mongodb/src/index.ts @@ -1,54 +1,56 @@ -import { TypeScriptCommonConfig, initCommonTemplate } from 'graphql-codegen-typescript-common'; -import { PluginValidateFn, PluginFunction, DocumentFile, toPascalCase } from 'graphql-codegen-core'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as index from './templates/index.handlebars'; -import * as interfaceTemplate from './templates/interface.handlebars'; -import * as type from './templates/type.handlebars'; -import * as union from './templates/union.handlebars'; -import * as schemaTemplate from './templates/schema.handlebars'; -import ifNotRootType from './helpers/if-not-root-type'; -import { isPrimitive } from './helpers/is-primitive'; -import isArray from './helpers/is-array'; -import filterModelFields from './helpers/filter-model-fields'; -import { entityFields } from './helpers/entity-fields'; -import gql from 'graphql-tag'; +import { RawConfig } from 'graphql-codegen-visitor-plugin-common'; +import { DocumentFile, PluginFunction, PluginValidateFn } from 'graphql-codegen-plugin-helpers'; +import { parse, visit, GraphQLSchema } from 'graphql'; +import { printSchemaWithDirectives } from 'graphql-toolkit'; import { extname } from 'path'; +import gql from 'graphql-tag'; +import { TsMongoVisitor } from './visitor'; -export interface TypeScriptMongoDbConfig extends TypeScriptCommonConfig {} +export interface TypeScriptMongoPluginConfig extends RawConfig { + dbTypeSuffix?: string; + dbInterfaceSuffix?: string; + objectIdType?: string; + idFieldName?: string; + enumsAsString?: boolean; + avoidOptionals?: boolean; +} -export const plugin: PluginFunction = async ( +export const plugin: PluginFunction = ( schema: GraphQLSchema, documents: DocumentFile[], - config: TypeScriptMongoDbConfig -): Promise => { - const { templateContext, scalars, convert } = initCommonTemplate(Handlebars, schema, documents, config); - // KAMIL: I think we don't need to generate enums, scalars, types, unions etc - // because it's a part of typescript-common - Handlebars.registerPartial('type', type); - Handlebars.registerPartial('union', union); - Handlebars.registerPartial('schema', schemaTemplate); - Handlebars.registerPartial('interface', interfaceTemplate); - - Handlebars.registerHelper('entityFields', entityFields(convert)); - Handlebars.registerHelper('filterModelFields', filterModelFields); - Handlebars.registerHelper('ifNotRootType', ifNotRootType); - Handlebars.registerHelper('isPrimitive', isPrimitive(scalars)); - Handlebars.registerHelper('isArray', isArray); - Handlebars.registerHelper('toPascalCase', toPascalCase); + config: TypeScriptMongoPluginConfig +) => { + const visitor = new TsMongoVisitor(schema, config); + const printedSchema = printSchemaWithDirectives(schema); + const astNode = parse(printedSchema); + const visitorResult = visit(astNode, { leave: visitor as any }); + const header = visitor.objectIdImport; - return Handlebars.compile(index)(templateContext); + return [header, ...visitorResult.definitions.filter(d => typeof d === 'string')].join('\n'); }; -const addToSchema = gql` - directive @union(discriminatorField: String) on UNION - directive @abstractEntity(discriminatorField: String!) on INTERFACE - directive @entity(embedded: Boolean, additionalFields: [AdditionalEntityFields]) on OBJECT - directive @column(name: String, overrideType: String, overrideIsArray: Boolean) on FIELD_DEFINITION - directive @id on FIELD_DEFINITION - directive @link on FIELD_DEFINITION - directive @embedded on FIELD_DEFINITION - directive @map(path: String!) on FIELD_DEFINITION +export enum Directives { + ID = 'id', + ENTITY = 'entity', + ABSTRACT_ENTITY = 'abstractEntity', + UNION = 'union', + LINK = 'link', + COLUMN = 'column', + EMBEDDED = 'embedded', + MAP = 'map' +} + +export const DIRECTIVES = gql` + directive @${Directives.UNION}(discriminatorField: String, additionalFields: [AdditionalEntityFields]) on UNION + directive @${ + Directives.ABSTRACT_ENTITY + }(discriminatorField: String!, additionalFields: [AdditionalEntityFields]) on INTERFACE + directive @${Directives.ENTITY}(embedded: Boolean, additionalFields: [AdditionalEntityFields]) on OBJECT + directive @${Directives.COLUMN}(overrideType: String) on FIELD_DEFINITION + directive @${Directives.ID} on FIELD_DEFINITION + directive @${Directives.LINK} on FIELD_DEFINITION + directive @${Directives.EMBEDDED} on FIELD_DEFINITION + directive @${Directives.MAP}(path: String!) on FIELD_DEFINITION # Inputs input AdditionalEntityFields { path: String @@ -56,8 +58,7 @@ const addToSchema = gql` } `; -export { addToSchema }; -export { addToSchema as DIRECTIVES }; +export const addToSchema = DIRECTIVES; export const validate: PluginValidateFn = async ( schema: GraphQLSchema, diff --git a/packages/plugins/typescript-mongodb/src/polyfills.d.ts b/packages/plugins/typescript-mongodb/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-mongodb/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-mongodb/src/templates/index.handlebars b/packages/plugins/typescript-mongodb/src/templates/index.handlebars deleted file mode 100644 index 03f3ec61d84..00000000000 --- a/packages/plugins/typescript-mongodb/src/templates/index.handlebars +++ /dev/null @@ -1,3 +0,0 @@ -import { ObjectID } from 'mongodb'; - -{{> schema }} diff --git a/packages/plugins/typescript-mongodb/src/templates/interface.handlebars b/packages/plugins/typescript-mongodb/src/templates/interface.handlebars deleted file mode 100755 index fb0ab388922..00000000000 --- a/packages/plugins/typescript-mongodb/src/templates/interface.handlebars +++ /dev/null @@ -1,4 +0,0 @@ -{{ toComment description }} -{{#ifDirective this "abstractEntity" }} -export interface {{ ../name }}DbInterface {{{ entityFields ../this }}} -{{/ifDirective}} diff --git a/packages/plugins/typescript-mongodb/src/templates/schema.handlebars b/packages/plugins/typescript-mongodb/src/templates/schema.handlebars deleted file mode 100644 index 06dc377ad49..00000000000 --- a/packages/plugins/typescript-mongodb/src/templates/schema.handlebars +++ /dev/null @@ -1,11 +0,0 @@ -{{#if @root.config.schemaNamespace ~}}export namespace {{@root.config.schemaNamespace}} { {{/if}} -{{#each interfaces}} -{{>interface }} -{{/each}} -{{#each types}} -{{>type }} -{{/each}} -{{#each unions}} -{{>union }} -{{/each}} -{{#if @root.config.schemaNamespace ~}} } {{~/if}} \ No newline at end of file diff --git a/packages/plugins/typescript-mongodb/src/templates/type.handlebars b/packages/plugins/typescript-mongodb/src/templates/type.handlebars deleted file mode 100755 index c8e35595254..00000000000 --- a/packages/plugins/typescript-mongodb/src/templates/type.handlebars +++ /dev/null @@ -1,6 +0,0 @@ -{{#ifNotRootType this }} -{{#ifDirective this "entity" }} - -export interface {{ ../name }}DbObject {{{ entityFields ../this }}} -{{/ifDirective}} -{{/ifNotRootType}} diff --git a/packages/plugins/typescript-mongodb/src/templates/union.handlebars b/packages/plugins/typescript-mongodb/src/templates/union.handlebars deleted file mode 100755 index 405e43f6412..00000000000 --- a/packages/plugins/typescript-mongodb/src/templates/union.handlebars +++ /dev/null @@ -1,7 +0,0 @@ -{{#ifDirective this "union" }} -{{ toComment description }} -export type {{ name }}DbObject = {{#if discriminatorField}}{ {{discriminatorField}}: string } & {{/if}}({{#each possibleTypes}}{{this}}DbObject{{#unless @last}} | {{/unless}}{{/each}}); - -{{/ifDirective}} -{{ toComment description }} -export type {{ name }} = {{#each possibleTypes}}{{this}}{{#unless @last}} | {{/unless}}{{/each}}; \ No newline at end of file diff --git a/packages/plugins/typescript-mongodb/src/visitor.ts b/packages/plugins/typescript-mongodb/src/visitor.ts new file mode 100644 index 00000000000..2945555dfa7 --- /dev/null +++ b/packages/plugins/typescript-mongodb/src/visitor.ts @@ -0,0 +1,335 @@ +import { UnionTypeDefinitionNode } from 'graphql/language/ast'; +import { FieldsTree } from './fields-tree'; +import { + getBaseTypeNode, + DeclarationBlock, + getConfigValue, + ParsedConfig, + BaseVisitor, + indent +} from 'graphql-codegen-visitor-plugin-common'; +import { TypeScriptOperationVariablesToObject } from 'graphql-codegen-typescript'; +import * as autoBind from 'auto-bind'; +import { Directives, TypeScriptMongoPluginConfig } from './index'; +import { + DirectiveNode, + GraphQLSchema, + ObjectTypeDefinitionNode, + NamedTypeNode, + FieldDefinitionNode, + Kind, + ValueNode, + isEnumType, + InterfaceTypeDefinitionNode +} from 'graphql'; + +type AdditionalField = { path: string; type: string }; +export interface TypeScriptMongoPluginParsedConfig extends ParsedConfig { + dbTypeSuffix: string; + dbInterfaceSuffix: string; + objectIdType: string; + objectIdImport: string; + idFieldName: string; + enumsAsString: boolean; + avoidOptionals: boolean; +} + +type Directivable = { directives?: ReadonlyArray }; + +function resolveObjectId(pointer: string | null | undefined): { identifier: string; module: string } { + if (!pointer) { + return { identifier: 'ObjectID', module: 'mongodb' }; + } + + if (pointer.includes('#')) { + const [path, module] = pointer.split('#'); + + return { identifier: path, module }; + } + + return { + identifier: pointer, + module: null + }; +} + +export class TsMongoVisitor extends BaseVisitor { + private _variablesTransformer: TypeScriptOperationVariablesToObject; + + constructor(private _schema: GraphQLSchema, pluginConfig: TypeScriptMongoPluginConfig) { + super(pluginConfig, ({ + dbTypeSuffix: pluginConfig.dbTypeSuffix || 'DbObject', + dbInterfaceSuffix: pluginConfig.dbInterfaceSuffix || 'DbInterface', + objectIdType: resolveObjectId(pluginConfig.objectIdType).identifier, + objectIdImport: resolveObjectId(pluginConfig.objectIdType).module, + idFieldName: pluginConfig.idFieldName || '_id', + enumsAsString: getConfigValue(pluginConfig.enumsAsString, true), + avoidOptionals: getConfigValue(pluginConfig.avoidOptionals, false) + } as Partial) as any); + autoBind(this); + this._variablesTransformer = new TypeScriptOperationVariablesToObject(this.scalars, this.convertName, false, false); + } + + public get objectIdImport(): string { + if (this.config.objectIdImport === null) { + return null; + } + + return `import { ${this.config.objectIdType} } from '${this.config.objectIdImport}';`; + } + + private _resolveDirectiveValue(valueNode: ValueNode): T | undefined | null { + switch (valueNode.kind) { + case Kind.INT: + case Kind.STRING: + case Kind.FLOAT: + case Kind.BOOLEAN: + case Kind.ENUM: + return (valueNode.value as any) as T; + case Kind.LIST: + return (valueNode.values.map(v => this._resolveDirectiveValue(v)) as any) as T; + case Kind.NULL: + return null; + case Kind.OBJECT: + return valueNode.fields.reduce( + (prev, f) => { + return { + ...prev, + [f.name.value]: this._resolveDirectiveValue(f.value) + }; + }, + {} as T + ); + default: + return undefined; + } + } + + private _getDirectiveArgValue(node: DirectiveNode, argName: string): T | null | undefined { + if (!node || !node.arguments || node.arguments.length === 0) { + return undefined; + } + + const foundArgument = node.arguments.find(a => a.name.value === argName); + + if (!foundArgument) { + return undefined; + } + + return this._resolveDirectiveValue(foundArgument.value); + } + + private _getDirectiveFromAstNode(node: Directivable, directiveName: Directives): DirectiveNode | null { + if (!node || !node.directives || node.directives.length === 0) { + return null; + } + + const foundDirective = node.directives.find( + d => (d.name as any) === directiveName || (d.name.value && d.name.value === directiveName) + ); + + if (!foundDirective) { + return null; + } + + return foundDirective; + } + + private _buildInterfaces(interfaces: ReadonlyArray): string[] { + return (interfaces || []) + .map(namedType => { + const schemaType = this._schema.getType(namedType.name.value); + const abstractEntityDirective = this._getDirectiveFromAstNode(schemaType.astNode, Directives.ABSTRACT_ENTITY); + + if (!abstractEntityDirective) { + return null; + } + + return this.convertName(namedType.name.value, { suffix: this.config.dbInterfaceSuffix }); + }) + .filter(a => a); + } + + private _handleIdField(fieldNode: FieldDefinitionNode, tree: FieldsTree, addOptionalSign: boolean): void { + tree.addField( + `${this.config.idFieldName}${addOptionalSign ? '?' : ''}`, + this._variablesTransformer.wrapAstTypeWithModifiers(this.config.objectIdType, fieldNode.type) + ); + } + + private _handleLinkField( + fieldNode: FieldDefinitionNode, + tree: FieldsTree, + mapPath: string | null, + addOptionalSign: boolean + ): void { + const coreType = getBaseTypeNode(fieldNode.type); + const type = this.convertName(coreType, { suffix: this.config.dbTypeSuffix }); + + tree.addField( + mapPath ? mapPath : `${fieldNode.name.value}${addOptionalSign ? '?' : ''}`, + this._variablesTransformer.wrapAstTypeWithModifiers(`${type}['${this.config.idFieldName}']`, fieldNode.type) + ); + } + + private _handleColumnField( + fieldNode: FieldDefinitionNode, + tree: FieldsTree, + columnDirective: DirectiveNode, + mapPath: string | null, + addOptionalSign: boolean + ): void { + const overrideType = this._getDirectiveArgValue(columnDirective, 'overrideType'); + const coreType = getBaseTypeNode(fieldNode.type); + let type: string = null; + + if (this.scalars[coreType.name.value]) { + type = this.scalars[coreType.name.value]; + } else { + const schemaType = this._schema.getType(coreType.name.value); + + if (isEnumType(schemaType) && this.config.enumsAsString) { + type = this.scalars.String; + } else { + type = coreType.name.value; + } + } + + tree.addField( + mapPath ? mapPath : `${fieldNode.name.value}${addOptionalSign ? '?' : ''}`, + overrideType ? overrideType : this._variablesTransformer.wrapAstTypeWithModifiers(type, fieldNode.type) + ); + } + + private _handleEmbeddedField( + fieldNode: FieldDefinitionNode, + tree: FieldsTree, + mapPath: string | null, + addOptionalSign: boolean + ): void { + const coreType = getBaseTypeNode(fieldNode.type); + const type = this.convertName(coreType, { suffix: this.config.dbTypeSuffix }); + + tree.addField( + mapPath ? mapPath : `${fieldNode.name.value}${addOptionalSign ? '?' : ''}`, + this._variablesTransformer.wrapAstTypeWithModifiers(type, fieldNode.type) + ); + } + + private _buildFieldsTree(fields: ReadonlyArray): FieldsTree { + const tree = new FieldsTree(); + + fields.forEach(field => { + const idDirective = this._getDirectiveFromAstNode(field, Directives.ID); + const linkDirective = this._getDirectiveFromAstNode(field, Directives.LINK); + const columnDirective = this._getDirectiveFromAstNode(field, Directives.COLUMN); + const embeddedDirective = this._getDirectiveFromAstNode(field, Directives.EMBEDDED); + const mapDirective = this._getDirectiveFromAstNode(field, Directives.MAP); + const mapPath: string | null = this._getDirectiveArgValue(mapDirective, 'path'); + const addOptionalSign = !this.config.avoidOptionals && field.type.kind !== Kind.NON_NULL_TYPE; + + if (idDirective) { + this._handleIdField(field, tree, addOptionalSign); + } else if (linkDirective) { + this._handleLinkField(field, tree, mapPath, addOptionalSign); + } else if (columnDirective) { + this._handleColumnField(field, tree, columnDirective, mapPath, addOptionalSign); + } else if (embeddedDirective) { + this._handleEmbeddedField(field, tree, mapPath, addOptionalSign); + } + }); + + return tree; + } + + private _addAdditionalFields(tree: FieldsTree, additioalFields: AdditionalField[] | null): void { + if (!additioalFields || additioalFields.length === 0) { + return; + } + + for (const field of additioalFields) { + tree.addField(field.path, field.type); + } + } + + InterfaceTypeDefinition(node: InterfaceTypeDefinitionNode): string { + const abstractEntityDirective = this._getDirectiveFromAstNode(node, Directives.ABSTRACT_ENTITY); + + if (abstractEntityDirective === null) { + return null; + } + + const discriminatorField = this._getDirectiveArgValue(abstractEntityDirective, 'discriminatorField'); + const additionalFields = this._getDirectiveArgValue(abstractEntityDirective, 'additionalFields'); + const fields = this._buildFieldsTree(node.fields); + fields.addField(discriminatorField, this.scalars.String); + this._addAdditionalFields(fields, additionalFields); + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node, { suffix: this.config.dbInterfaceSuffix })) + .withBlock(fields.string).string; + } + + UnionTypeDefinition(node: UnionTypeDefinitionNode): string { + const unionDirective = this._getDirectiveFromAstNode(node, Directives.UNION); + + if (unionDirective === null) { + return null; + } + + const discriminatorField = this._getDirectiveArgValue(unionDirective, 'discriminatorField'); + const possibleTypes = node.types + .map(namedType => { + const schemaType = this._schema.getType(namedType.name.value); + const entityDirective = this._getDirectiveFromAstNode(schemaType.astNode, Directives.ENTITY); + const abstractEntityDirective = this._getDirectiveFromAstNode(schemaType.astNode, Directives.ABSTRACT_ENTITY); + + if (entityDirective) { + return this.convertName(namedType, { suffix: this.config.dbTypeSuffix }); + } else if (abstractEntityDirective) { + return this.convertName(namedType, { suffix: this.config.dbInterfaceSuffix }); + } + + return null; + }) + .filter(a => a); + + if (possibleTypes.length === 0) { + return null; + } + + const additionalFields = this._getDirectiveArgValue(unionDirective, 'additionalFields'); + const fields = new FieldsTree(); + fields.addField(discriminatorField, this.scalars.String); + this._addAdditionalFields(fields, additionalFields); + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node, { suffix: this.config.dbTypeSuffix })) + .withContent(`(${possibleTypes.join(' | ')}) & `) + .withBlock(fields.string).string; + } + + ObjectTypeDefinition(node: ObjectTypeDefinitionNode): string { + const entityDirective = this._getDirectiveFromAstNode(node, Directives.ENTITY); + + if (entityDirective === null) { + return null; + } + + const implementingInterfaces = this._buildInterfaces(node.interfaces); + const fields = this._buildFieldsTree(node.fields); + const additionalFields = this._getDirectiveArgValue(entityDirective, 'additionalFields'); + this._addAdditionalFields(fields, additionalFields); + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node, { suffix: this.config.dbTypeSuffix })) + .withContent(implementingInterfaces.length ? implementingInterfaces.join(' & ') + ' & ' : '') + .withBlock(fields.string).string; + } +} diff --git a/packages/plugins/typescript-mongodb/tests/typescript-mongo.spec.ts b/packages/plugins/typescript-mongodb/tests/typescript-mongo.spec.ts index 2dfd963f9c4..6b74d661994 100644 --- a/packages/plugins/typescript-mongodb/tests/typescript-mongo.spec.ts +++ b/packages/plugins/typescript-mongodb/tests/typescript-mongo.spec.ts @@ -1,162 +1,209 @@ -import 'graphql-codegen-core/dist/testing'; -import { SchemaTemplateContext, schemaToTemplateContext } from 'graphql-codegen-core'; -import { entityFields } from '../src/helpers/entity-fields'; -import { addToSchema, plugin } from '../dist'; -import { pascalCase } from 'change-case'; -import { print, GraphQLSchema } from 'graphql'; -import { makeExecutableSchema } from 'graphql-tools'; - -describe('Types', () => { - const compileAndBuildContext = (typeDefs: string): { context: SchemaTemplateContext; schema: GraphQLSchema } => { - const schema = makeExecutableSchema({ - typeDefs: ` - ${print(addToSchema)} - - type Query { - dummy: String - } - - ${typeDefs} - ` - }) as GraphQLSchema; - - return { - schema, - context: schemaToTemplateContext(schema) - }; +import 'graphql-codegen-testing'; +import { plugin, addToSchema } from './../src/index'; +import { buildSchema, print, GraphQLSchema } from 'graphql'; +import { plugin as tsPlugin } from '../../typescript/src/index'; +import { validateTs } from '../../typescript/tests/validate'; + +describe('TypeScript Mongo', () => { + const validate = async (content: string, schema: GraphQLSchema, config: any) => { + const tsPluginOutput = await tsPlugin(schema, [], config, { outputFile: '' }); + const result = [tsPluginOutput, content].join('\n'); + await validateTs(result); }; - const hbsContext: any = { - data: { - root: { - primitives: { - String: 'string', - Int: 'number', - Float: 'number', - Boolean: 'boolean', - ID: 'string' - } - } + const schema = buildSchema(/* GraphQL */ ` + ${print(addToSchema)} + + type User @entity(additionalFields: [{ path: "nonSchemaField", type: "string" }]) { + id: ID @id + name: String @column + gender: Gender @column + someLink: LinkType @link + linkWithoutDirective: LinkType + multipleLinks: [LinkType] @link + fieldWithMap: String @column @map(path: "profile.inner.field") + columnWithOverride: String @column(overrideType: "number") + requiredField: String! + arrayColumn: [Int] @column + arrayColumnMap: [Int] @column @map(path: "myInnerArray") + basicEmbedded: EmbeddedType! @embedded + arrayEmbedded: [EmbeddedType!]! @embedded + nullableEmbedded: [EmbeddedType] @embedded + mappedEmbedded: EmbeddedType @embedded @map(path: "innerEmbedded.moreLevel") + changeName: String @column @map(path: "other_name") + } + + type EmbeddedType @entity { + eField: String @column + eField2: Int! @column + } + + type LinkType @entity { + id: ID @id + } + + enum Gender { + MALE + FEMALE + OTHER + } + + type Query { + me: User! + feed: [FeedItem!]! + search: [SearchResult!]! + } + + interface FeedItem @abstractEntity(discriminatorField: "kind") { + id: ID! @id + content: String! @column } - }; - it('should resolve type and fields correctly', async () => { - const { context } = compileAndBuildContext(` - type User @entity(additionalFields: [ - { path: "nonSchemaField", type: "string" } - ]) { - id: ID @id - name: String @column - gender: Gender @column - someLink: LinkType @link - multipleLinks: [LinkType] @link - fieldWithMap: String @column @map(path: "profile.inner.field") - columnWithOverride: String @column(overrideType: "number") - requiredField: String! - arrayColumn: [Int] @column - arrayColumnMap: [Int] @column @map(path: "myInnerArray") - basicEmbedded: EmbeddedType! @embedded - arrayEmbedded: [EmbeddedType!]! @embedded - nullableEmbedded: [EmbeddedType] @embedded - mappedEmbedded: EmbeddedType @embedded @map(path: "innerEmbedded.moreLevel") - overriddedArray: String @column(overrideIsArray: true) - changeName: String @column(name: "other_name") - } - - type EmbeddedType @entity(embedded: true) { - eField: String - eField2: Int! - } - - type LinkType @entity { - id: ID @id - } - - enum Gender { - MALE - FEMALE - OTHER - } - `); - - const type = context.types.find(t => t.name === 'User'); - const fieldsMapping = entityFields(pascalCase)(type, hbsContext, true); - - expect(fieldsMapping).toEqual({ - _id: 'Maybe', - name: 'Maybe', - gender: 'Maybe', - someLink: 'Maybe', - multipleLinks: 'Maybe<(Maybe)[]>', - profile: { inner: { field: 'Maybe' } }, - columnWithOverride: 'Maybe', - arrayColumn: 'Maybe<(Maybe)[]>', - myInnerArray: 'Maybe<(Maybe)[]>', - basicEmbedded: 'EmbeddedTypeDbObject', - arrayEmbedded: 'EmbeddedTypeDbObject[]', - nullableEmbedded: 'Maybe<(Maybe)[]>', - innerEmbedded: { moreLevel: 'Maybe' }, - overriddedArray: 'Maybe', - other_name: 'Maybe', - nonSchemaField: 'string' + type Post implements FeedItem @entity { + id: ID! @id + content: String! @column + author: User! @link + } + + union SearchResult @union(discriminatorField: "entityType") = Post | User + `); + + describe('Config', () => { + it('Should accept dbTypeSuffix', async () => { + const result = await plugin(schema, [], { dbTypeSuffix: 'Obj' }, { outputFile: '' }); + expect(result).toContain('export type UserObj = {'); + expect(result).toContain('export type EmbeddedTypeObj = {'); + expect(result).toContain('export type LinkTypeObj = {'); + await validate(result, schema, {}); }); - }); - it('should resolve type and fields correctly with interfaces', async () => { - const { context } = compileAndBuildContext(` - interface BaseEntity @abstractEntity(discriminatorField: "type") { - id: ID! @id - title: String! @column - } - - type Entity1 implements BaseEntity @entity { - id: ID! @id - title: String! @column - } - `); - - const gqlInterface = context.interfaces.find(t => t.name === 'BaseEntity'); - const type1 = context.types.find(t => t.name === 'Entity1'); - const fieldsMappingInterface = entityFields(pascalCase)(gqlInterface, hbsContext, true); - const fieldsMappingType = entityFields(pascalCase)(type1, hbsContext, true); - - expect(fieldsMappingInterface).toEqual({ - type: 'string', - _id: 'ObjectID', - title: 'string' - }); - - expect(fieldsMappingType).toEqual({ - _id: 'ObjectID', - title: 'string' - }); - - const fieldsMappingTypeString = entityFields(pascalCase)(type1, hbsContext, false); - expect(fieldsMappingTypeString).toContain('extends BaseEntityDbInterface'); + it('Should accept dbInterfaceSuffix', async () => { + const result = await plugin(schema, [], { dbInterfaceSuffix: 'InterfaceObj' }, { outputFile: '' }); + expect(result).toContain(`export type FeedItemInterfaceObj = {`); + expect(result).toContain(`export type PostDbObject = FeedItemInterfaceObj & {`); + await validate(result, schema, {}); + }); + + it('Should allow to customize objectIdType import with basic type', async () => { + const result = await plugin(schema, [], { objectIdType: 'string' }, { outputFile: '' }); + expect(result).toContain(`_id: string`); + expect(result).not.toContain(`ObjectID`); + await validate(result, schema, {}); + }); + + it('Should allow to customize objectIdType import with custom import', async () => { + const result = await plugin(schema, [], { objectIdType: 'ObjectId#bson' }, { outputFile: '' }); + expect(result).toContain(`_id: ObjectId`); + expect(result).not.toContain(`ObjectID`); + expect(result).toContain(`import { ObjectId } from 'bson';`); + await validate(result, schema, {}); + }); + + it('Should allow to customize idFieldName', async () => { + const result = await plugin(schema, [], { idFieldName: 'id' }, { outputFile: '' }); + expect(result).toContain(`id: ObjectID`); + expect(result).not.toContain(`_id`); + await validate(result, schema, {}); + }); + + it('Should allow to customize enumsAsString', async () => { + const result = await plugin(schema, [], { enumsAsString: false }, { outputFile: '' }); + expect(result).not.toContain('gender?: Maybe'); + expect(result).toContain('gender?: Maybe'); + await validate(result, schema, {}); + }); + + it('Should allow to customize avoidOptionals', async () => { + const result = await plugin(schema, [], { avoidOptionals: true }, { outputFile: '' }); + expect(result).not.toContain('?:'); + await validate(result, schema, {}); + }); + + it('Should allow to customize namingConvention', async () => { + const result = await plugin(schema, [], { namingConvention: 'change-case#lowerCase' }, { outputFile: '' }); + expect(result).toContain('export type userdbobject = {'); + expect(result).toContain(`export type feeditemdbinterface = {`); + await validate(result, schema, {}); + }); }); - it('should', async () => { - const { schema } = compileAndBuildContext(` - type Entity1 @entity { - id: ID! @id - title: String! @column - } - `); - - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Entity1DbObject { - _id: ObjectID - title: string - } - `); + describe('Output', () => { + it('Should compile TypeScript correctly', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + await validate(result, schema, {}); + }); + + it('Should include only the relevant types', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain('export type UserDbObject = {'); + expect(result).not.toContain('export type QueryDbObject = {'); + }); + + it('Should generate output for interfaces with discriminatorField', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain(`export type FeedItemDbInterface = {`); + expect(result).toContain(`kind: string,`); + }); + + it('Should include a valid type when implementing interfaces', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain(`export type FeedItemDbInterface = {`); + expect(result).toContain(`export type PostDbObject = FeedItemDbInterface & {`); + }); + + it('Should include a valid union with discriminatorField', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toBeSimilarStringTo(` + export type SearchResultDbObject = (PostDbObject | UserDbObject) & { + entityType: string, + };`); + }); + + it('Should output the correct values for @id directive', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain('_id?: Maybe'); // optional id + }); + + it('Should output the correct values for @column directive', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain('name?: Maybe'); // optional scalar + expect(result).toContain('gender?: Maybe'); // enum as string by default + expect(result).toContain(`arrayColumn?: Maybe>>`); // simple @column with array + expect(result).toContain(`columnWithOverride?: number`); // override type + }); + + it('Should output the correct values for @link directive', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain(`someLink?: Maybe`); // link to another entity + expect(result).toContain(`multipleLinks?: Maybe>>`); // links array + }); + + it('Should output the correct values for @map directive', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain(`myInnerArray: Maybe>>`); // simple @column with array and @map + expect(result).toContain(`other_name: Maybe`); // simple @map scalar + expect(result).toBeSimilarStringTo(` + profile: { + inner: { + field: Maybe, + }, + },`); // custom @map with inner fields + expect(result).toBeSimilarStringTo(` + innerEmbedded: { + moreLevel: Maybe, + },`); // embedded with @map + }); + + it('Should output the correct values for @embedded directive', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain(`basicEmbedded: EmbeddedTypeDbObject`); // embedded type + expect(result).toContain(`arrayEmbedded: Array`); // embedded array + expect(result).toContain(`nullableEmbedded?: Maybe>`); // optional array embedded + }); + + it('Should output the correct values with additionalFields', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + expect(result).toContain(`nonSchemaField: string`); // additional field + }); }); }); diff --git a/packages/plugins/typescript-mongodb/tsconfig.json b/packages/plugins/typescript-mongodb/tsconfig.json index 782f215152c..e872bb81d5d 100644 --- a/packages/plugins/typescript-mongodb/tsconfig.json +++ b/packages/plugins/typescript-mongodb/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", @@ -17,5 +18,6 @@ "noUnusedLocals": false, "noUnusedParameters": false }, + "include": ["src/**/*.ts"], "exclude": ["node_modules", "tests", "dist"] } diff --git a/packages/plugins/typescript-client/.gitignore b/packages/plugins/typescript-operations/.gitignore similarity index 100% rename from packages/plugins/typescript-client/.gitignore rename to packages/plugins/typescript-operations/.gitignore diff --git a/packages/plugins/typescript-client/.npmignore b/packages/plugins/typescript-operations/.npmignore similarity index 100% rename from packages/plugins/typescript-client/.npmignore rename to packages/plugins/typescript-operations/.npmignore diff --git a/packages/plugins/typescript-operations/package.json b/packages/plugins/typescript-operations/package.json new file mode 100644 index 00000000000..942d3989ded --- /dev/null +++ b/packages/plugins/typescript-operations/package.json @@ -0,0 +1,31 @@ +{ + "name": "graphql-codegen-typescript-operations", + "version": "0.18.0", + "description": "GraphQL Code Generator plugin for generating TypeScript types for GraphQL queries, mutations, subscriptions and fragments", + "repository": "git@github.com:dotansimha/graphql-code-generator.git", + "license": "MIT", + "scripts": { + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" + }, + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-typescript": "0.18.0", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" + }, + "devDependencies": { + "graphql-codegen-testing": "0.18.0", + "graphql": "14.1.1", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333" + }, + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" + } +} diff --git a/packages/plugins/typescript-operations/src/index.ts b/packages/plugins/typescript-operations/src/index.ts new file mode 100644 index 00000000000..d6dd8957831 --- /dev/null +++ b/packages/plugins/typescript-operations/src/index.ts @@ -0,0 +1,27 @@ +import { PluginFunction, DocumentFile } from 'graphql-codegen-plugin-helpers'; +import { visit, concatAST, GraphQLSchema } from 'graphql'; +import { TypeScriptDocumentsVisitor } from './visitor'; +import { RawDocumentsConfig } from 'graphql-codegen-visitor-plugin-common'; + +export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { + avoidOptionals?: boolean; + immutableTypes?: boolean; +} + +export const plugin: PluginFunction = ( + schema: GraphQLSchema, + documents: DocumentFile[], + config: TypeScriptDocumentsPluginConfig +) => { + const allAst = concatAST( + documents.reduce((prev, v) => { + return [...prev, v.content]; + }, []) + ); + + const visitorResult = visit(allAst, { + leave: new TypeScriptDocumentsVisitor(schema, config) + }); + + return visitorResult.definitions.join('\n'); +}; diff --git a/packages/plugins/typescript-operations/src/ts-selection-set-to-object.ts b/packages/plugins/typescript-operations/src/ts-selection-set-to-object.ts new file mode 100644 index 00000000000..99533b4eb07 --- /dev/null +++ b/packages/plugins/typescript-operations/src/ts-selection-set-to-object.ts @@ -0,0 +1,64 @@ +import { SelectionSetToObject, ConvertNameFn, ScalarsMap } from 'graphql-codegen-visitor-plugin-common'; +import { + GraphQLSchema, + GraphQLNamedType, + SelectionSetNode, + GraphQLObjectType, + GraphQLNonNull, + GraphQLList, + isNonNullType, + isListType +} from 'graphql'; + +export class TypeScriptSelectionSetToObject extends SelectionSetToObject { + constructor( + _scalars: ScalarsMap, + _schema: GraphQLSchema, + _convertName: ConvertNameFn, + _addTypename: boolean, + private _immutableTypes: boolean, + _parentSchemaType?: GraphQLNamedType, + _selectionSet?: SelectionSetNode + ) { + super(_scalars, _schema, _convertName, _addTypename, _parentSchemaType, _selectionSet); + } + + public createNext(parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode): SelectionSetToObject { + return new TypeScriptSelectionSetToObject( + this._scalars, + this._schema, + this._convertName, + this._addTypename, + this._immutableTypes, + parentSchemaType, + selectionSet + ); + } + + private clearOptional(str: string): string { + if (str.startsWith('Maybe')) { + return str.replace(/^Maybe<(.*?)>$/i, '$1'); + } + + return str; + } + + protected formatNamedField(name: string): string { + return this._immutableTypes ? `readonly ${name}` : name; + } + + protected wrapTypeWithModifiers( + baseType: string, + type: GraphQLObjectType | GraphQLNonNull | GraphQLList + ): string { + if (isNonNullType(type)) { + return this.clearOptional(this.wrapTypeWithModifiers(baseType, type.ofType)); + } else if (isListType(type)) { + const innerType = this.wrapTypeWithModifiers(baseType, type.ofType); + + return `Maybe<${this._immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>>`; + } else { + return `Maybe<${baseType}>`; + } + } +} diff --git a/packages/plugins/typescript-operations/src/visitor.ts b/packages/plugins/typescript-operations/src/visitor.ts new file mode 100644 index 00000000000..75541920e63 --- /dev/null +++ b/packages/plugins/typescript-operations/src/visitor.ts @@ -0,0 +1,44 @@ +import { GraphQLSchema } from 'graphql'; +import { ParsedDocumentsConfig, BaseDocumentsVisitor } from 'graphql-codegen-visitor-plugin-common'; +import { TypeScriptSelectionSetToObject } from './ts-selection-set-to-object'; +import { TypeScriptDocumentsPluginConfig } from './index'; +import { TypeScriptOperationVariablesToObject } from 'graphql-codegen-typescript'; + +export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { + avoidOptionals: boolean; + immutableTypes: boolean; +} + +export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< + TypeScriptDocumentsPluginConfig, + TypeScriptDocumentsParsedConfig +> { + constructor(schema: GraphQLSchema, config: TypeScriptDocumentsPluginConfig) { + super( + config, + { + avoidOptionals: config.avoidOptionals || false, + immutableTypes: config.immutableTypes || false + } as any, + schema + ); + + this.setSelectionSetHandler( + new TypeScriptSelectionSetToObject( + this.scalars, + this.schema, + this.convertName, + this.config.addTypename, + this.config.immutableTypes + ) + ); + this.setVariablesTransformer( + new TypeScriptOperationVariablesToObject( + this.scalars, + this.convertName, + this.config.avoidOptionals, + this.config.immutableTypes + ) + ); + } +} diff --git a/packages/plugins/typescript-operations/tests/ts-documents.spec.ts b/packages/plugins/typescript-operations/tests/ts-documents.spec.ts new file mode 100644 index 00000000000..15a5d44a791 --- /dev/null +++ b/packages/plugins/typescript-operations/tests/ts-documents.spec.ts @@ -0,0 +1,946 @@ +import 'graphql-codegen-testing'; +import { parse, buildClientSchema, buildSchema } from 'graphql'; +import { readFileSync } from 'fs'; +import { format } from 'prettier'; +import { plugin } from '../src/index'; +import { validateTs } from '../../typescript/tests/validate'; +import { plugin as tsPlugin } from '../../typescript/src/index'; + +describe('TypeScript Operations Plugin', () => { + const gitHuntSchema = buildClientSchema(JSON.parse(readFileSync('../../../dev-test/githunt/schema.json', 'utf-8'))); + + const schema = buildSchema(/* GraphQL */ ` + type User { + id: ID! + username: String! + email: String! + profile: Profile + role: Role + } + + type Profile { + age: Int + firstName: String! + } + + type Mutation { + login(username: String!, password: String!): User + } + + type Subscription { + userCreated: User + } + + interface Notifiction { + id: ID! + } + + type TextNotification implements Notifiction { + id: ID! + text: String! + } + + type ImageNotification implements Notifiction { + id: ID! + imageUrl: String! + metadata: ImageMetadata! + } + + type ImageMetadata { + createdBy: String! + } + + enum Role { + USER + ADMIN + } + + union MyUnion = User | Profile + + type Query { + me: User + unionTest: MyUnion + notifications: [Notifiction!]! + dummy: String + dummyNonNull: String! + dummyArray: [String] + dummyNonNullArray: [String]! + dummyNonNullArrayWithValues: [String!]! + dummyWithType: Profile + } + + schema { + query: Query + mutation: Mutation + subscription: Subscription + } + `); + + const validate = async (content: string, config: any = {}, pluginSchema = schema) => + validateTs((await tsPlugin(pluginSchema, [], config, { outputFile: '' })) + '\n' + content); + + describe('Config', () => { + it('Should generate the correct output when using immutableTypes config', async () => { + const ast = parse(` + query notifications { + notifications { + id + + ... on TextNotification { + text + } + + ... on ImageNotification { + imageUrl + metadata { + createdBy + } + } + } + } + `); + const config = { namingConvention: 'change-case#lowerCase', immutableTypes: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type notificationsquery = ({ readonly __typename?: 'Query' } & { readonly notifications: ReadonlyArray<(Pick & (({ readonly __typename?: 'TextNotification' } & Pick) | ({ readonly __typename?: 'ImageNotification' } & Pick & { readonly metadata: ({ readonly __typename?: 'ImageMetadata' } & Pick) })))> });` + ); + await validate(result, config); + }); + }); + + describe('Naming Convention & Types Prefix', () => { + it('Should allow custom naming and point to the correct type', async () => { + const ast = parse(` + query notifications { + notifications { + id + + ... on TextNotification { + text + } + + ... on ImageNotification { + imageUrl + metadata { + createdBy + } + } + } + } + `); + const config = { namingConvention: 'change-case#lowerCase' }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type notificationsquery = ({ __typename?: 'Query' } & { notifications: Array<(Pick & (({ __typename?: 'TextNotification' } & Pick) | ({ __typename?: 'ImageNotification' } & Pick & { metadata: ({ __typename?: 'ImageMetadata' } & Pick) })))> });` + ); + await validate(result, config); + }); + + it('Should allow custom naming and point to the correct type - with custom prefix', async () => { + const ast = parse(` + query notifications { + notifications { + id + + ... on TextNotification { + text + } + + ... on ImageNotification { + imageUrl + metadata { + createdBy + } + } + } + } + `); + + const config = { typesPrefix: 'i', namingConvention: 'change-case#lowerCase' }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`export type inotificationsqueryvariables = {};`); + expect(result).toBeSimilarStringTo( + `export type inotificationsquery = ({ __typename?: 'Query' } & { notifications: Array<(Pick & (({ __typename?: 'TextNotification' } & Pick) | ({ __typename?: 'ImageNotification' } & Pick & { metadata: ({ __typename?: 'ImageMetadata' } & Pick) })))> });` + ); + validate(result, config); + }); + }); + + describe('__typename', () => { + it('Should skip __typename when skipTypename is set to true', async () => { + const ast = parse(` + query { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).not.toContain(`__typename`); + validate(result, config); + }); + + it('Should add __typename as non-optional when explicitly specified', async () => { + const ast = parse(` + query { + __typename + dummy + } + `); + const config = {}; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo( + `export type Unnamed_1_Query = ({ __typename: 'Query' } & Pick);` + ); + validate(result, config); + }); + + it('Should add __typename as optional when its not specified', async () => { + const ast = parse(` + query { + dummy + } + `); + const config = {}; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo( + `export type Unnamed_1_Query = ({ __typename?: 'Query' } & Pick);` + ); + validate(result, config); + }); + + it('Should add __typename as non-optional when its explictly specified, even if skipTypename is true', async () => { + const ast = parse(` + query { + __typename + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type Unnamed_1_Query = ({ __typename: 'Query' } & Pick);` + ); + validate(result, config); + }); + + it('Should add __typename correctly when unions are in use', async () => { + const ast = parse(` + query unionTest { + unionTest { + ... on User { + id + } + + ... on Profile { + age + } + } + } + `); + const config = {}; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo( + `export type UnionTestQuery = ({ __typename?: 'Query' } & { unionTest: Maybe<(({ __typename?: 'User' } & Pick) | ({ __typename?: 'Profile' } & Pick))> });` + ); + validate(result, config); + }); + + it('Should add __typename correctly when interfaces are in use', async () => { + const ast = parse(` + query notifications { + notifications { + id + + ... on TextNotification { + text + } + + ... on ImageNotification { + imageUrl + metadata { + createdBy + } + } + } + } + `); + const config = {}; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo( + `export type NotificationsQuery = ({ __typename?: 'Query' } & { notifications: Array<(Pick & (({ __typename?: 'TextNotification' } & Pick) | ({ __typename?: 'ImageNotification' } & Pick & { metadata: ({ __typename?: 'ImageMetadata' } & Pick) })))> });` + ); + validate(result, config); + }); + }); + + describe('Unnamed Documents', () => { + it('Should handle unnamed documents correctly', async () => { + const ast = parse(` + query { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo(`export type Unnamed_1_Query = Pick;`); + expect(result).toBeSimilarStringTo(`export type Unnamed_1_QueryVariables = {};`); + validate(result, config); + }); + + it('Should handle unnamed documents correctly with multiple documents', async () => { + const ast = parse(` + query { + dummy + } + + query { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`export type Unnamed_1_Query = Pick;`); + expect(result).toBeSimilarStringTo(`export type Unnamed_1_QueryVariables = {};`); + expect(result).toBeSimilarStringTo(`export type Unnamed_2_Query = Pick;`); + expect(result).toBeSimilarStringTo(`export type Unnamed_2_QueryVariables = {};`); + validate(result, config); + }); + }); + + describe('Selection Set', () => { + it('Should support fragment spread correctly with simple type with no other fields', async () => { + const ast = parse(` + fragment UserFields on User { + id + username + profile { + age + } + role + } + + query me { + me { + ...UserFields + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo(`export type MeQuery = { me: Maybe };`); + validate(result, config); + }); + + it('Should support fragment spread correctly with simple type with other fields', async () => { + const ast = parse(` + fragment UserFields on User { + id + profile { + age + } + } + + query me { + me { + ...UserFields + username + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type MeQuery = { me: Maybe<(Pick & UserFieldsFragment)> };` + ); + validate(result, config); + }); + + it('Should support fragment spread correctly with multiple fragment spread', async () => { + const ast = parse(` + fragment UserFields on User { + id + } + + fragment UserProfile on User { + profile { + age + } + } + + query me { + me { + ...UserFields + ...UserProfile + username + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type MeQuery = { me: Maybe<(Pick & (UserFieldsFragment & UserProfileFragment))> };` + ); + validate(result, config); + }); + + it('Should support interfaces correctly when used with inline fragments', async () => { + const ast = parse(` + query notifications { + notifications { + id + + ... on TextNotification { + text + } + + ... on ImageNotification { + imageUrl + metadata { + createdBy + } + } + } + } + `); + + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo( + `export type NotificationsQuery = { notifications: Array<(Pick & (Pick | (Pick & { metadata: Pick })))> };` + ); + validate(result, config); + }); + + it('Should support union correctly when used with inline fragments', async () => { + const ast = parse(` + query unionTest { + unionTest { + ... on User { + id + } + + ... on Profile { + age + } + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type UnionTestQuery = { unionTest: Maybe<(Pick | Pick)> };` + ); + validate(result, config); + }); + + it('Should support inline fragments', async () => { + const ast = parse(` + query currentUser { + me { + id + ... on User { + username + profile { + age + } + } + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + expect(result).toBeSimilarStringTo( + `export type CurrentUserQuery = { me: Maybe<(Pick & ((Pick & { profile: Maybe> })))> };` + ); + validate(result, config); + }); + + it('Should build a basic selection set based on basic query on GitHub schema', async () => { + const ast = parse(` + query me($repoFullName: String!) { + currentUser { + login + html_url + } + entry(repoFullName: $repoFullName) { + id + postedBy { + login + html_url + } + createdAt + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(gitHuntSchema, [{ filePath: 'test-file.ts', content: ast }], config, { + outputFile: '' + }); + + expect(result).toBeSimilarStringTo( + `export type MeQueryVariables = { + repoFullName: string + };` + ); + expect(result).toBeSimilarStringTo( + `export type MeQuery = { currentUser: Maybe>, entry: Maybe<(Pick & { postedBy: Pick })> };` + ); + validate(result, config, gitHuntSchema); + }); + + it('Should build a basic selection set based on basic query', async () => { + const ast = parse(` + query dummy { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`export type DummyQuery = Pick;`); + validate(result, config); + }); + + it('Should build a basic selection set based on basic query with field aliasing for basic scalar', async () => { + const ast = parse(` + query dummy { + customName: dummy + customName2: dummyWithType { + age + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type DummyQuery = ({ customName: Query['dummy'] } & { customName2: Maybe> });` + ); + validate(result, config); + }); + + it('Should build a basic selection set based on a query with inner fields', async () => { + const ast = parse(` + query currentUser { + me { + id + username + role + profile { + age + } + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type CurrentUserQuery = { me: Maybe<(Pick & { profile: Maybe> })> };` + ); + validate(result, config); + }); + }); + + describe('Fragment Definition', () => { + it('Should build fragment definition correctly - with name and selection set', async () => { + const ast = parse(` + fragment UserFields on User { + id + username + profile { + age + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type UserFieldsFragment = (Pick & { profile: Maybe> });` + ); + validate(result, config); + }); + }); + + describe('Operation Definition', () => { + it('Should detect Mutation correctly', async () => { + const ast = parse(` + mutation login { + login(username: "1", password: "2") { + id + username + profile { + age + } + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type LoginMutation = { login: Maybe<(Pick & { profile: Maybe> })> };` + ); + validate(result, config); + }); + + it('Should detect Query correctly', async () => { + const ast = parse(` + query test { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`export type TestQuery = Pick;`); + validate(result, config); + }); + + it('Should detect Subscription correctly', async () => { + const ast = parse(` + subscription test { + userCreated { + id + } + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`export type TestSubscription = { userCreated: Maybe> };`); + validate(result, config); + }); + + it('Should handle operation variables correctly', async () => { + const ast = parse(` + query testQuery($username: String, $email: String, $password: String!, $input: InputType, $mandatoryInput: InputType!, $testArray: [String], $requireString: [String]!, $innerRequired: [String!]!) { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `export type TestQueryQueryVariables = { + username?: Maybe, + email?: Maybe, + password: string, + input?: Maybe, + mandatoryInput: InputType, + testArray?: Maybe>>, + requireString: Array>, + innerRequired: Array + };` + ); + validate(result, config); + }); + + it('Should create empty variables when there are no operation variables', async () => { + const ast = parse(` + query testQuery { + dummy + } + `); + const config = { skipTypename: true }; + const result = await plugin(schema, [{ filePath: 'test-file.ts', content: ast }], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`export type TestQueryQueryVariables = {};`); + validate(result, config); + }); + + it('avoid duplicates - each type name should be unique', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type DeleteMutation { + deleted: Boolean! + } + type UpdateMutation { + updated: Boolean! + } + union MessageMutationType = DeleteMutation | UpdateMutation + type Query { + dummy: String + } + type Mutation { + mutation(message: String!, type: String!): MessageMutationType! + } + `); + const query = parse(/* GraphQL */ ` + mutation SubmitMessage($message: String!) { + mutation(message: $message) { + ... on DeleteMutation { + deleted + } + ... on UpdateMutation { + updated + } + } + } + `); + + const content = await plugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(format(content)).toBeSimilarStringTo( + format(` + type SubmitMessageMutation = { __typename?: 'Mutation' } & { + mutation: + | ({ __typename?: 'DeleteMutation' } & Pick) + | ({ __typename?: 'UpdateMutation' } & Pick); + }; + `) + ); + }); + + it('should use __typename in fragments when requested', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Post { + title: String + } + type Query { + post: Post! + } + `); + const query = parse(/* GraphQL */ ` + query Post { + post { + ... on Post { + __typename + } + } + } + `); + + const content = await plugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(format(content)).toBeSimilarStringTo( + format(` + export type PostQuery = { __typename?: 'Query' } & { post: { __typename?: 'Post' } & ({ __typename: 'Post' }) }; + `) + ); + }); + + it('should handle introspection types (__schema)', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Post { + title: String + } + type Query { + post: Post! + } + `); + const query = parse(/* GraphQL */ ` + query Info { + __schema { + queryType { + fields { + name + } + } + } + } + `); + + const content = await plugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(format(content)).toBeSimilarStringTo( + format(` + export type InfoQuery = { __typename?: 'Query' } & { + __schema: { __typename?: '__Schema' } & { + queryType: { __typename?: '__Type' } & { fields: Maybe>> }; + }; + }; + `) + ); + }); + + it('should handle introspection types (__type)', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Post { + title: String + } + type Query { + post: Post! + } + `); + const query = parse(/* GraphQL */ ` + query Info { + __type(name: "Post") { + name + fields { + name + type { + name + kind + } + } + } + } + `); + + const content = await plugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(format(content)).toBeSimilarStringTo( + format(` + export type InfoQuery = { __typename?: 'Query' } & { + __type: Maybe< + { __typename?: '__Type' } & Pick<__Type, 'name'> & { + fields: Maybe< + Array< + { __typename?: '__Field' } & Pick<__Field, 'name'> & { + type: { __typename?: '__Type' } & Pick<__Type, 'name' | 'kind'>; + } + > + >; + } + >; + }; + `) + ); + }); + + it('should handle introspection types (like __TypeKind)', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Post { + title: String + } + type Query { + post: Post! + } + `); + const query = parse(/* GraphQL */ ` + query Info { + __type(name: "Post") { + name + fields { + name + type { + name + kind + } + } + } + } + `); + + const coreContent = await tsPlugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + const pluginContent = await plugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + const content = [coreContent, pluginContent].join('\n'); + + expect(content).toBeSimilarStringTo(` + export enum __TypeKind { + Scalar = 'SCALAR', + Object = 'OBJECT', + Interface = 'INTERFACE', + Union = 'UNION', + Enum = 'ENUM', + Input_Object = 'INPUT_OBJECT', + List = 'LIST', + Non_Null = 'NON_NULL' + } + `); + + validateTs(content); + }); + + it('Should generate correctly when using enums and typesPrefix', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + enum Access { + Read + Write + All + } + type User { + access: Access + } + input Filter { + match: String! + } + type Query { + users(filter: Filter!): [User] + } + `); + const query = parse(/* GraphQL */ ` + query users($filter: Filter!) { + users(filter: $filter) { + access + } + } + `); + + const content = await plugin( + testSchema, + [{ filePath: '', content: query }], + { typesPrefix: 'PREFIX_' }, + { + outputFile: 'graphql.ts' + } + ); + + expect(format(content)).toBeSimilarStringTo( + format(` + export type PREFIX_UsersQueryVariables = { + filter: PREFIX_Filter; + }; + + export type PREFIX_UsersQuery = { __typename?: 'Query' } & { + users: Maybe>>>; + }; + `) + ); + }); + }); +}); diff --git a/packages/plugins/flow-documents/tsconfig.json b/packages/plugins/typescript-operations/tsconfig.json similarity index 87% rename from packages/plugins/flow-documents/tsconfig.json rename to packages/plugins/typescript-operations/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/flow-documents/tsconfig.json +++ b/packages/plugins/typescript-operations/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/typescript-react-apollo/example/.env b/packages/plugins/typescript-react-apollo/example/.env deleted file mode 100644 index 6f809cc2540..00000000000 --- a/packages/plugins/typescript-react-apollo/example/.env +++ /dev/null @@ -1 +0,0 @@ -SKIP_PREFLIGHT_CHECK=true diff --git a/packages/plugins/typescript-react-apollo/example/.gitignore b/packages/plugins/typescript-react-apollo/example/.gitignore deleted file mode 100644 index d30f40ef442..00000000000 --- a/packages/plugins/typescript-react-apollo/example/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# See https://help.github.com/ignore-files/ for more about ignoring files. - -# dependencies -/node_modules - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/packages/plugins/typescript-react-apollo/example/README.md b/packages/plugins/typescript-react-apollo/example/README.md deleted file mode 100644 index 42e21994daf..00000000000 --- a/packages/plugins/typescript-react-apollo/example/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# React Apollo TypeScript Example Project - -This project shows an example usage of `graphql-code-generator` and `graphql-code-generator-typescript-react-apollo-template` with a remote endpoint. - -When you start the project by the `yarn start` or `npm start`, it scans the schema on the remote endpoint defined as an env variable in `generate-types` script on `package.json` file, and your definitions in `src`; and generates reusable Components and HOCs. - -If you don't know which one you should use, please check the following docs to learn more about HOCs; - - -## What's included - -- Generated models -> `src/generated-models.tsx` -- Example with HOC -- Example with Component diff --git a/packages/plugins/typescript-react-apollo/example/codegen.yml b/packages/plugins/typescript-react-apollo/example/codegen.yml deleted file mode 100644 index 71a5adda42c..00000000000 --- a/packages/plugins/typescript-react-apollo/example/codegen.yml +++ /dev/null @@ -1,12 +0,0 @@ -overwrite: true -watch: true -schema: https://0vw9j9w0l5.lp.gql.zone/graphql -documents: ./src/**/*.graphql -generates: - src/generated-models.tsx: - plugins: - - typescript-common - - typescript-client - - typescript-react-apollo - config: - noNamespaces: true \ No newline at end of file diff --git a/packages/plugins/typescript-react-apollo/example/images.d.ts b/packages/plugins/typescript-react-apollo/example/images.d.ts deleted file mode 100644 index ada0bb95f4b..00000000000 --- a/packages/plugins/typescript-react-apollo/example/images.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module '*.svg'; -declare module '*.png'; -declare module '*.jpg'; diff --git a/packages/plugins/typescript-react-apollo/example/package.json b/packages/plugins/typescript-react-apollo/example/package.json deleted file mode 100644 index b0aa2fa225a..00000000000 --- a/packages/plugins/typescript-react-apollo/example/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "graphql-codegen-typescript-react-apollo-example", - "version": "0.1.0", - "private": true, - "dependencies": { - "apollo-boost": "0.1.21", - "apollo-client": "2.4.6", - "graphql": "14.0.2", - "graphql-tag": "2.10.0", - "react": "16.6.3", - "react-apollo": "2.3.1", - "react-dom": "16.6.3", - "react-scripts": "2.1.1" - }, - "scripts": { - "start": "concurrently \"gql-gen\" \"react-scripts start\"", - "build": "react-scripts build", - "eject": "react-scripts eject" - }, - "devDependencies": { - "@types/graphql": "14.0.3", - "@types/node": "10.12.9", - "@types/react": "16.7.6", - "@types/react-dom": "16.0.9", - "concurrently": "4.1.0", - "graphql-code-generator": "0.14.1", - "graphql-codegen-typescript-react-apollo-template": "0.14.1", - "tslint-react": "3.6.0", - "typescript": "3.1.6" - }, - "browserslist": [ - ">0.2%", - "not dead", - "not ie <= 11", - "not op_mini all" - ] -} diff --git a/packages/plugins/typescript-react-apollo/example/public/favicon.ico b/packages/plugins/typescript-react-apollo/example/public/favicon.ico deleted file mode 100644 index a11777cc471..00000000000 Binary files a/packages/plugins/typescript-react-apollo/example/public/favicon.ico and /dev/null differ diff --git a/packages/plugins/typescript-react-apollo/example/public/index.html b/packages/plugins/typescript-react-apollo/example/public/index.html deleted file mode 100644 index ed0ebafa1b7..00000000000 --- a/packages/plugins/typescript-react-apollo/example/public/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - React App - - - -
- - - diff --git a/packages/plugins/typescript-react-apollo/example/public/manifest.json b/packages/plugins/typescript-react-apollo/example/public/manifest.json deleted file mode 100644 index ef19ec243e7..00000000000 --- a/packages/plugins/typescript-react-apollo/example/public/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - } - ], - "start_url": "./index.html", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/packages/plugins/typescript-react-apollo/example/src/components/App/App.css b/packages/plugins/typescript-react-apollo/example/src/components/App/App.css deleted file mode 100644 index 31be39dcc49..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/App/App.css +++ /dev/null @@ -1,32 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 80px; -} - -.App-header { - background-color: #222; - height: 150px; - padding: 20px; - color: white; -} - -.App-title { - font-size: 1.5em; -} - -.App-intro { - font-size: large; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/packages/plugins/typescript-react-apollo/example/src/components/App/App.tsx b/packages/plugins/typescript-react-apollo/example/src/components/App/App.tsx deleted file mode 100644 index 395e60f2251..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/App/App.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import './App.css'; - -import logo from './logo.svg'; -import { TestWithComponent } from '../TestWithComponent/TestWithComponent'; -import { TestWithHOC } from '../TestWithHOC/TestWithHOC.container'; -import { TestWithFragment } from '../TestWithFragment/TestWithFragment'; - -class App extends React.Component { - public render() { - return ( -
-
- logo -

Welcome to React

-
-

- To get started, edit src/App.tsx and save to reload. -

-
- Example With Generated Component - -
-
- Example With Generated HOC - -
-
- Example With Generated Fragment - -
-
- ); - } -} - -export default App; diff --git a/packages/plugins/typescript-react-apollo/example/src/components/App/logo.svg b/packages/plugins/typescript-react-apollo/example/src/components/App/logo.svg deleted file mode 100644 index 6b60c1042f5..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/App/logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/packages/plugins/typescript-react-apollo/example/src/components/TestWithComponent/TestWithComponent.tsx b/packages/plugins/typescript-react-apollo/example/src/components/TestWithComponent/TestWithComponent.tsx deleted file mode 100644 index cf29cedaf74..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/TestWithComponent/TestWithComponent.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import { AllPostsComponent, UpvotePostComponent } from '../../generated-models'; - -export class TestWithComponent extends React.Component { - render() { - return ( - - {({ data, error, loading }) => { - if (error || loading) return '...'; - - return ( -
    - {data && - data.posts && - data.posts.map( - post => - post && - post.author && ( -
  • - {post.title} by {post.author.firstName} {post.author.lastName} ({post.votes} votes){' '} - - {upvotePost => ( - - )} - -
  • - ) - )} -
- ); - }} -
- ); - } -} diff --git a/packages/plugins/typescript-react-apollo/example/src/components/TestWithFragment/TestWithFragment.tsx b/packages/plugins/typescript-react-apollo/example/src/components/TestWithFragment/TestWithFragment.tsx deleted file mode 100644 index a12ce1b9c74..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/TestWithFragment/TestWithFragment.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import * as React from 'react'; -import { AllPostsWithFragmentComponent, UpvotePostComponent } from '../../generated-models'; - -export class TestWithFragment extends React.Component { - render() { - return ( - - {({ loading, error, data }) => { - if (loading) { - return 'Loading...'; - } - if (error) { - return `Error! ${error.message}`; - } - return ( -
    - {data && - data.posts && - data.posts.map( - post => - post && - post.author && ( -
  • - {post.title} by {post.author.firstName} {post.author.lastName} ({post.votes} votes){' '} - - {upvotePost => ( - - )} - -
  • - ) - )} -
- ); - }} -
- ); - } -} diff --git a/packages/plugins/typescript-react-apollo/example/src/components/TestWithHOC/TestWithHOC.container.tsx b/packages/plugins/typescript-react-apollo/example/src/components/TestWithHOC/TestWithHOC.container.tsx deleted file mode 100644 index 9063dc860bf..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/TestWithHOC/TestWithHOC.container.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { TestWithHOCView } from './TestWithHOC.view'; -import { AllPostsHOC } from '../../generated-models'; - -const withUser = AllPostsHOC({ - options: { - variables: { - id: Date.now().toString() - } - } -}); - -export const TestWithHOC = withUser(TestWithHOCView); diff --git a/packages/plugins/typescript-react-apollo/example/src/components/TestWithHOC/TestWithHOC.view.tsx b/packages/plugins/typescript-react-apollo/example/src/components/TestWithHOC/TestWithHOC.view.tsx deleted file mode 100644 index 56041278226..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/components/TestWithHOC/TestWithHOC.view.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import * as React from 'react'; -import { DataProps } from 'react-apollo'; -import { AllPostsQuery, AllPostsVariables, UpvotePostComponent } from '../../generated-models'; - -export interface TestWithHOCViewProps extends DataProps {} - -export class TestWithHOCView extends React.Component { - render() { - if (this.props.data.loading) return 'Loading...'; - if (this.props.data.error) return `Error! ${this.props.data.error.message}`; - return ( -
    - {this.props && - this.props.data && - this.props.data.posts && - this.props.data.posts.map( - post => - post && - post.author && ( -
  • - {post.title} by {post.author.firstName} {post.author.lastName} ({post.votes} votes){' '} - - {upvotePost => ( - - )} - -
  • - ) - )} -
- ); - } -} diff --git a/packages/plugins/typescript-react-apollo/example/src/generated-models.tsx b/packages/plugins/typescript-react-apollo/example/src/generated-models.tsx deleted file mode 100644 index e98afec6445..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/generated-models.tsx +++ /dev/null @@ -1,235 +0,0 @@ -// ==================================================== -// Documents -// ==================================================== - -export type AllPostsVariables = {}; - -export type AllPostsQuery = { - __typename?: 'Query'; - - posts: AllPostsPosts[] | null; -}; - -export type AllPostsPosts = { - __typename?: 'Post'; - - id: number; - - title: string | null; - - votes: number | null; - - author: AllPostsAuthor | null; -}; - -export type AllPostsAuthor = { - __typename?: 'Author'; - - id: number; - - firstName: string | null; - - lastName: string | null; -}; - -export type AllPostsWithFragmentVariables = {}; - -export type AllPostsWithFragmentQuery = { - __typename?: 'Query'; - - posts: AllPostsWithFragmentPosts[] | null; -}; - -export type AllPostsWithFragmentPosts = PostFragmentFragment; - -export type UpvotePostVariables = { - postId: number; -}; - -export type UpvotePostMutation = { - __typename?: 'Mutation'; - - upvotePost: UpvotePostUpvotePost | null; -}; - -export type UpvotePostUpvotePost = { - __typename?: 'Post'; - - id: number; - - votes: number | null; -}; - -export type PostFragmentFragment = { - __typename?: 'Post'; - - id: number; - - title: string | null; - - votes: number | null; - - author: PostFragmentAuthor | null; -}; - -export type PostFragmentAuthor = AuthorFragmentFragment; - -export type AuthorFragmentFragment = { - __typename?: 'Author'; - - id: number; - - firstName: string | null; - - lastName: string | null; -}; - -import * as ReactApollo from 'react-apollo'; -import * as React from 'react'; - -import gql from 'graphql-tag'; - -// ==================================================== -// Fragments -// ==================================================== - -export const AuthorFragmentFragmentDoc = gql` - fragment AuthorFragment on Author { - id - firstName - lastName - } -`; - -export const PostFragmentFragmentDoc = gql` - fragment PostFragment on Post { - id - title - votes - author { - ...AuthorFragment - } - } - - ${AuthorFragmentFragmentDoc} -`; - -// ==================================================== -// Components -// ==================================================== - -export const AllPostsDocument = gql` - query allPosts { - posts { - id - title - votes - author { - id - firstName - lastName - } - } - } -`; -export class AllPostsComponent extends React.Component< - Partial> -> { - render() { - return ( - - query={AllPostsDocument} - {...(this as any)['props'] as any} - /> - ); - } -} -export type AllPostsProps = Partial> & - TChildProps; -export function AllPostsHOC( - operationOptions: - | ReactApollo.OperationOption> - | undefined -) { - return ReactApollo.graphql>( - AllPostsDocument, - operationOptions - ); -} -export const AllPostsWithFragmentDocument = gql` - query allPostsWithFragment { - posts { - ...PostFragment - } - } - - ${PostFragmentFragmentDoc} -`; -export class AllPostsWithFragmentComponent extends React.Component< - Partial> -> { - render() { - return ( - - query={AllPostsWithFragmentDocument} - {...(this as any)['props'] as any} - /> - ); - } -} -export type AllPostsWithFragmentProps = Partial< - ReactApollo.DataProps -> & - TChildProps; -export function AllPostsWithFragmentHOC( - operationOptions: - | ReactApollo.OperationOption< - TProps, - AllPostsWithFragmentQuery, - AllPostsWithFragmentVariables, - AllPostsWithFragmentProps - > - | undefined -) { - return ReactApollo.graphql< - TProps, - AllPostsWithFragmentQuery, - AllPostsWithFragmentVariables, - AllPostsWithFragmentProps - >(AllPostsWithFragmentDocument, operationOptions); -} -export const UpvotePostDocument = gql` - mutation upvotePost($postId: Int!) { - upvotePost(postId: $postId) { - id - votes - } - } -`; -export class UpvotePostComponent extends React.Component< - Partial> -> { - render() { - return ( - - mutation={UpvotePostDocument} - {...(this as any)['props'] as any} - /> - ); - } -} -export type UpvotePostProps = Partial< - ReactApollo.MutateProps -> & - TChildProps; -export type UpvotePostMutationFn = ReactApollo.MutationFn; -export function UpvotePostHOC( - operationOptions: - | ReactApollo.OperationOption> - | undefined -) { - return ReactApollo.graphql>( - UpvotePostDocument, - operationOptions - ); -} diff --git a/packages/plugins/typescript-react-apollo/example/src/index.css b/packages/plugins/typescript-react-apollo/example/src/index.css deleted file mode 100644 index b4cc7250b98..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/index.css +++ /dev/null @@ -1,5 +0,0 @@ -body { - margin: 0; - padding: 0; - font-family: sans-serif; -} diff --git a/packages/plugins/typescript-react-apollo/example/src/index.tsx b/packages/plugins/typescript-react-apollo/example/src/index.tsx deleted file mode 100644 index 409f3e14c6d..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import App from './components/App/App'; -import './index.css'; -import registerServiceWorker from './registerServiceWorker'; -import { ApolloProvider } from 'react-apollo'; -import ApolloClient from 'apollo-boost'; - -const client = new ApolloClient({ - uri: 'https://0vw9j9w0l5.lp.gql.zone/graphql' -}); - -ReactDOM.render( - - - , - document.getElementById('root') as HTMLElement -); -registerServiceWorker(); diff --git a/packages/plugins/typescript-react-apollo/example/src/react-app-env.d.ts b/packages/plugins/typescript-react-apollo/example/src/react-app-env.d.ts deleted file mode 100644 index 6431bc5fc6b..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/packages/plugins/typescript-react-apollo/example/src/registerServiceWorker.ts b/packages/plugins/typescript-react-apollo/example/src/registerServiceWorker.ts deleted file mode 100644 index e9fb3341db8..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/registerServiceWorker.ts +++ /dev/null @@ -1,113 +0,0 @@ -// tslint:disable:no-console -// In production, we register a service worker to serve assets from local cache. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on the 'N+1' visit to a page, since previously -// cached resources are updated in the background. - -// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. -// This link also includes instructions on opting out of this behavior. - -const isLocalhost = Boolean( - window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/) -); - -export default function register() { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL!, window.location.toString()); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 - return; - } - - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Lets check if a service worker still exists or not. - checkValidServiceWorker(swUrl); - - // Add some additional logging to localhost, pointing developers to the - // service worker/PWA documentation. - navigator.serviceWorker.ready.then(() => { - console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://goo.gl/SC7cgQ' - ); - }); - } else { - // Is not local host. Just register service worker - registerValidSW(swUrl); - } - }); - } -} - -function registerValidSW(swUrl: string) { - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - if (installingWorker) { - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a 'New content is - // available; please refresh.' message in your web app. - console.log('New content is available; please refresh.'); - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // 'Content is cached for offline use.' message. - console.log('Content is cached for offline use.'); - } - } - }; - } - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); -} - -function checkValidServiceWorker(swUrl: string) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl) - .then(response => { - // Ensure service worker exists, and that we really are getting a JS file. - if (response.status === 404 || response.headers.get('content-type')!.indexOf('javascript') === -1) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl); - } - }) - .catch(() => { - console.log('No internet connection found. App is running in offline mode.'); - }); -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { - registration.unregister(); - }); - } -} diff --git a/packages/plugins/typescript-react-apollo/example/src/schema/all-posts.query.graphql b/packages/plugins/typescript-react-apollo/example/src/schema/all-posts.query.graphql deleted file mode 100644 index 9e5ea783460..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/schema/all-posts.query.graphql +++ /dev/null @@ -1,18 +0,0 @@ -query allPosts { - posts { - id - title - votes - author { - id - firstName - lastName - } - } -} - -query allPostsWithFragment { - posts { - ...PostFragment - } -} diff --git a/packages/plugins/typescript-react-apollo/example/src/schema/post-fragment.graphql b/packages/plugins/typescript-react-apollo/example/src/schema/post-fragment.graphql deleted file mode 100644 index 727cb6c3826..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/schema/post-fragment.graphql +++ /dev/null @@ -1,14 +0,0 @@ -fragment PostFragment on Post { - id - title - votes - author { - ...AuthorFragment - } -} - -fragment AuthorFragment on Author { - id - firstName - lastName -} \ No newline at end of file diff --git a/packages/plugins/typescript-react-apollo/example/src/schema/upvote-post.mutation.graphql b/packages/plugins/typescript-react-apollo/example/src/schema/upvote-post.mutation.graphql deleted file mode 100644 index aa88f5af4c4..00000000000 --- a/packages/plugins/typescript-react-apollo/example/src/schema/upvote-post.mutation.graphql +++ /dev/null @@ -1,6 +0,0 @@ -mutation upvotePost($postId: Int!) { - upvotePost(postId: $postId) { - id - votes - } -} \ No newline at end of file diff --git a/packages/plugins/typescript-react-apollo/example/tsconfig.json b/packages/plugins/typescript-react-apollo/example/tsconfig.json deleted file mode 100644 index 47febc513e5..00000000000 --- a/packages/plugins/typescript-react-apollo/example/tsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "compilerOptions": { - "outDir": "build/dist", - "module": "esnext", - "target": "es5", - "lib": ["es6", "dom", "esnext.asynciterable"], - "sourceMap": true, - "allowJs": true, - "jsx": "preserve", - "moduleResolution": "node", - "rootDir": "src", - "forceConsistentCasingInFileNames": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "suppressImplicitAnyIndexErrors": true, - "noUnusedLocals": true, - "strict": true, - "noImplicitAny": true, - "alwaysStrict": true, - "noUnusedParameters": true, - "skipLibCheck": false, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - }, - "exclude": ["node_modules", "build", "scripts", "acceptance-tests", "webpack", "jest", "src/setupTests.ts"], - "include": ["src"] -} diff --git a/packages/plugins/typescript-react-apollo/example/tsconfig.prod.json b/packages/plugins/typescript-react-apollo/example/tsconfig.prod.json deleted file mode 100644 index fc8520e7376..00000000000 --- a/packages/plugins/typescript-react-apollo/example/tsconfig.prod.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "./tsconfig.json" -} diff --git a/packages/plugins/typescript-react-apollo/example/tslint.json b/packages/plugins/typescript-react-apollo/example/tslint.json deleted file mode 100644 index 7f20a52cd5a..00000000000 --- a/packages/plugins/typescript-react-apollo/example/tslint.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": ["tslint-react"], - "linterOptions": { - "exclude": ["config/**/*.js", "tools/**/*.js", "node_modules/**/*.ts"] - }, - "rules": { - "import-sources-order": false, - "named-imports-order": false, - "import-ordering": false, - "no-string-literal": false, - "object-literal-sort-keys": false, - "jsx-no-lambda": false - }, - "defaultSeverity": "warning" -} diff --git a/packages/plugins/typescript-react-apollo/package.json b/packages/plugins/typescript-react-apollo/package.json index e17c22c5d3d..8534a510eba 100644 --- a/packages/plugins/typescript-react-apollo/package.json +++ b/packages/plugins/typescript-react-apollo/package.json @@ -5,46 +5,31 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "peerDependencies": { "graphql-tag": "^2.0.0" }, "dependencies": { - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" + "tslib": "1.9.3", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" + "graphql-codegen-testing": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "flow-bin": "0.94.0", + "flow-parser": "0.94.0", + "graphql": "14.1.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/typescript-react-apollo/src/helpers.ts b/packages/plugins/typescript-react-apollo/src/helpers.ts deleted file mode 100644 index ba6b32578c3..00000000000 --- a/packages/plugins/typescript-react-apollo/src/helpers.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { DepGraph } from 'dependency-graph'; -import gqlTag from 'graphql-tag'; -import { Operation } from 'graphql-codegen-core'; -import { Fragment } from 'graphql-codegen-core'; - -export const propsType = convert => ({ name, operationType }: any, options: Handlebars.HelperOptions) => { - const { noNamespaces } = options.data.root.config || { noNamespaces: false }; - if (operationType === 'mutation') { - return ` - Partial< - ReactApollo.MutateProps< - ${noNamespaces ? convert(name, 'typeNames') : ''}Mutation, - ${noNamespaces ? convert(name, 'typeNames') : ''}Variables - > - > - `; - } else { - return ` - Partial< - ReactApollo.DataProps< - ${noNamespaces ? convert(name, 'typeNames') : ''}${convert(operationType)}, - ${noNamespaces ? convert(name, 'typeNames') : ''}Variables - > - > - `; - } -}; - -export const generateFragments = convert => (fragments: Fragment[], options: Handlebars.HelperOptions): string => { - const cachedFragments: Record = {}; - if (!fragments) { - return ''; - } - const graph = new DepGraph({ circular: true }); - fragments.forEach(fragment => { - graph.addNode(fragment.name, fragment); - }); - fragments.forEach(fragment => { - const depends = extractFragments(fragment.document); - if (depends) { - depends.forEach(name => { - graph.addDependency(fragment.name, name); - }); - } - }); - return graph - .overallOrder() - .map(name => generateFragment(graph.getNodeData(name), options)) - .join('\n'); - - function generateFragment(fragment: any, options: any): string | void { - const cached = cachedFragments[fragment.name]; - if (!cached) { - cachedFragments[fragment.name] = fragment; - const config = options.data.root.config || {}; - const pascalCasedFragmentName = convert(fragment.name, 'typeNames'); - // fooBar, FooBar and foo_bar may cause conflict due to the pascalCase. - // Because all of them will have same namespace FooBar - if (config.noNamespaces) { - return ` - export const ${pascalCasedFragmentName}FragmentDoc = ${gql(convert)(fragment, options)}; - `; - } else { - return ` - export namespace ${pascalCasedFragmentName} { - export const FragmentDoc = ${gql(convert)(fragment, options)}; - } - `; - } - } else { - if (fragment.document !== cached.document) { - throw new Error(`Duplicated fragment called '${fragment.name}'`); - } - } - } -}; - -export const gql = convert => (operation: Operation, options: Handlebars.HelperOptions): string => { - const config = options.data.root.config || {}; - - const doc = ` - ${operation.document} - ${includeFragments(transformFragments(convert)(operation.document, options))} - `; - - return config.gqlImport ? JSON.stringify(gqlTag(doc)) : 'gql`' + doc + '`'; -}; - -function includeFragments(fragments: string[]): string { - if (fragments) { - return ` - ${fragments - .filter((name, i, all) => all.indexOf(name) === i) - .map(name => '${' + name + '}') - .join('\n')} - `; - } - - return ''; -} - -export function extractFragments(document: string): string[] | undefined { - return (document.match(/\.\.\.[a-z0-9\_]+/gi) || []).map(name => name.replace('...', '')); -} - -const transformFragments = convert => (document: string, options: Handlebars.HelperOptions): string[] | undefined => { - return extractFragments(document).map(document => toFragmentName(convert)(document, options)); -}; - -export const toFragmentName = convert => (fragmentName: string, options: Handlebars.HelperOptions): string => { - const config = options.data.root.config || {}; - - if (config.noNamespaces) { - return convert(`${fragmentName}FragmentDoc`, 'typeNames'); - } else { - return convert(fragmentName, 'typeNames') + '.FragmentDoc'; - } -}; - -export const parseImport = (importStr: string) => { - const [moduleName, propName] = importStr.split('#'); - return { - moduleName, - propName - }; -}; - -export const hooksNamespace = (operationType: string): string => { - return operationType === 'subscription' ? 'SubscriptionHooks' : 'ReactApolloHooks'; -}; - -export const getImports = (operationType: string, options: Handlebars.HelperOptions) => { - const config = options.data.root.config || {}; - const gqlImport = parseImport(config.gqlImport || 'graphql-tag'); - let imports = ` - import ${ - gqlImport.propName ? `{ ${gqlImport.propName === 'gql' ? 'gql' : `${gqlImport.propName} as gql`} }` : 'gql' - } from '${gqlImport.moduleName}'; - `; - if (!config.noComponents) { - imports += `import * as React from 'react';\n`; - } - if (!config.noComponents || !config.noHOC) { - imports += `import * as ReactApollo from 'react-apollo';\n`; - } - if (config.withHooks) { - imports += `import * as ReactApolloHooks from '${ - typeof config.hooksImportFrom === 'string' ? config.hooksImportFrom : 'react-apollo-hooks' - }';\n`; - } - return imports; -}; diff --git a/packages/plugins/typescript-react-apollo/src/index.ts b/packages/plugins/typescript-react-apollo/src/index.ts index 70af72db250..0bdb3ba65f4 100644 --- a/packages/plugins/typescript-react-apollo/src/index.ts +++ b/packages/plugins/typescript-react-apollo/src/index.ts @@ -1,49 +1,52 @@ -import { initCommonTemplate, TypeScriptCommonConfig } from 'graphql-codegen-typescript-common'; -import { DocumentFile, PluginFunction, PluginValidateFn, transformDocumentsFiles } from 'graphql-codegen-core'; -import { flattenTypes } from 'graphql-codegen-plugin-helpers'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; -import { generateFragments, gql, propsType, getImports } from './helpers'; +import { DocumentFile, PluginValidateFn, PluginFunction } from 'graphql-codegen-plugin-helpers'; +import { visit, GraphQLSchema, concatAST, Kind, FragmentDefinitionNode } from 'graphql'; +import { RawClientSideBasePluginConfig } from 'graphql-codegen-visitor-plugin-common'; +import { ReactApolloVisitor } from './visitor'; import { extname } from 'path'; -export interface TypeScriptReactApolloConfig extends TypeScriptCommonConfig { - noNamespaces?: boolean; - noHOC?: boolean; - noComponents?: boolean; +export interface ReactApolloRawPluginConfig extends RawClientSideBasePluginConfig { + withHOC?: boolean; + withComponent?: boolean; withHooks?: boolean; hooksImportFrom?: string; gqlImport?: string; + noGraphQLTag?: boolean; } -export const plugin: PluginFunction = async ( +export const plugin: PluginFunction = ( schema: GraphQLSchema, documents: DocumentFile[], - config: TypeScriptReactApolloConfig = {} -): Promise => { - const { templateContext, convert } = initCommonTemplate(Handlebars, schema, documents, config); - const transformedDocuments = transformDocumentsFiles(schema, documents); - const flattenDocuments = flattenTypes(transformedDocuments); - Handlebars.registerHelper('generateFragments', generateFragments(convert)); - Handlebars.registerHelper('gql', gql(convert)); - Handlebars.registerHelper('propsType', propsType(convert)); - Handlebars.registerHelper('getImports', getImports); + config: ReactApolloRawPluginConfig +) => { + const allAst = concatAST( + documents.reduce((prev, v) => { + return [...prev, v.content]; + }, []) + ); + const operationsCount = allAst.definitions.filter(d => d.kind === Kind.OPERATION_DEFINITION); + + if (operationsCount.length === 0) { + return ''; + } - const hbsContext = { - ...templateContext, - ...flattenDocuments - }; + const allFragments = allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION) as FragmentDefinitionNode[]; + const visitor = new ReactApolloVisitor(allFragments, config) as any; + const visitorResult = visit(allAst, { leave: visitor }); - return Handlebars.compile(rootTemplate)(hbsContext); + return [ + visitor.getImports(), + visitor.fragments, + ...visitorResult.definitions.filter(t => typeof t === 'string') + ].join('\n'); }; export const validate: PluginValidateFn = async ( schema: GraphQLSchema, documents: DocumentFile[], - config: TypeScriptReactApolloConfig, + config: ReactApolloRawPluginConfig, outputFile: string ) => { - if (config.noComponents) { + if (config.withComponent === false) { if (extname(outputFile) !== '.ts' && extname(outputFile) !== '.tsx') { throw new Error(`Plugin "react-apollo" with "noComponents" requires extension to be ".ts" or ".tsx"!`); } diff --git a/packages/plugins/typescript-react-apollo/src/polyfills.d.ts b/packages/plugins/typescript-react-apollo/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-react-apollo/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-react-apollo/src/root.handlebars b/packages/plugins/typescript-react-apollo/src/root.handlebars deleted file mode 100644 index ba030230822..00000000000 --- a/packages/plugins/typescript-react-apollo/src/root.handlebars +++ /dev/null @@ -1,58 +0,0 @@ -{{#ifCond operations.length '!==' 0}} -{{{getImports this}}} - -{{ blockCommentIf 'Fragments' fragments }} -{{{generateFragments fragments}}} - -{{ blockCommentIf 'Components' operations }} -{{#each operations }} - {{#unless @root.config.noNamespaces}} -export namespace {{convert name 'typeNames' }} { - {{/unless}} - export const {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Document = {{{ gql this }}}; - {{#unless @root.config.noComponents}} - export class {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Component extends React.Component>> { - render(){ - return ( - - {{ toLowerCase operationType }}={ {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Document } - {...(this as any)['props'] as any} - /> - ); - } - } - {{/unless}} - {{#unless @root.config.noHOC}} - export type {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Props = {{{propsType this}}} & TChildProps; - {{#ifCond operationType '===' 'mutation'}} - export type {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}MutationFn = ReactApollo.MutationFn<{{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}{{convert operationType 'typeNames'}}, {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Variables>; - {{/ifCond}} - export function {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}{{convert operationType 'typeNames'}}, - {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Variables, - {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Props - > | undefined){ - return ReactApollo.graphql>( - {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Document, - operationOptions - ); - }; - {{/unless}} - {{#if @root.config.withHooks}} - export function use{{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}(baseOptions?: ReactApolloHooks.{{convert operationType 'typeNames'}}HookOptions< - {{#ifCond operationType '!==' 'query'}}{{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}{{convert operationType 'typeNames'}}, - {{/ifCond}}{{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Variables - >) { - return ReactApolloHooks.use{{convert operationType 'typeNames'}}< - {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}{{convert operationType 'typeNames'}}, - {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Variables - >({{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Document, baseOptions); - }; - {{/if}} - {{#unless @root.config.noNamespaces}} -} - {{/unless}} -{{/each}} -{{/ifCond}} diff --git a/packages/plugins/typescript-react-apollo/src/visitor.ts b/packages/plugins/typescript-react-apollo/src/visitor.ts new file mode 100644 index 00000000000..20ae4586a2e --- /dev/null +++ b/packages/plugins/typescript-react-apollo/src/visitor.ts @@ -0,0 +1,148 @@ +import { + ClientSideBaseVisitor, + ClientSideBasePluginConfig, + getConfigValue +} from 'graphql-codegen-visitor-plugin-common'; +import { ReactApolloRawPluginConfig } from './index'; +import * as autoBind from 'auto-bind'; +import { FragmentDefinitionNode, print, OperationDefinitionNode } from 'graphql'; +import { toPascalCase } from 'graphql-codegen-plugin-helpers'; + +export interface ReactApolloPluginConfig extends ClientSideBasePluginConfig { + withHOC: boolean; + withComponent: boolean; + withHooks: boolean; + hooksImportFrom: string; +} + +export class ReactApolloVisitor extends ClientSideBaseVisitor { + constructor(fragments: FragmentDefinitionNode[], rawConfig: ReactApolloRawPluginConfig) { + super(fragments, rawConfig, { + withHOC: getConfigValue(rawConfig.withHOC, true), + withComponent: getConfigValue(rawConfig.withComponent, true), + withHooks: getConfigValue(rawConfig.withHooks, false), + hooksImportFrom: getConfigValue(rawConfig.hooksImportFrom, 'react-apollo-hooks') + } as any); + + autoBind(this); + } + + public getImports(): string { + const baseImports = super.getImports(); + const imports = []; + + if (this.config.withComponent) { + imports.push(`import * as React from 'react';`); + } + + if (this.config.withComponent || this.config.withHOC) { + imports.push(`import * as ReactApollo from 'react-apollo';`); + } + + if (this.config.withHooks) { + imports.push( + `import * as ReactApolloHooks from '${ + typeof this.config.hooksImportFrom === 'string' ? this.config.hooksImportFrom : 'react-apollo-hooks' + }';` + ); + } + + return [baseImports, ...imports].join('\n'); + } + + private _buildHocProps(operationName: string, operationType: string): string { + const typeVariableName = this.convertName(operationName + toPascalCase(operationType)); + const variablesVarName = this.convertName(operationName + toPascalCase(operationType) + 'Variables'); + const argType = operationType === 'mutation' ? 'MutateProps' : 'DataProps'; + + return `Partial>`; + } + + private _buildOperationHoc( + node: OperationDefinitionNode, + documentVariableName: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + const operationName: string = this.convertName(node.name.value); + const propsTypeName: string = operationName + 'Props'; + + const propsVar = `export type ${propsTypeName} = ${this._buildHocProps( + node.name.value, + node.operation + )} & TChildProps;`; + + const mutationFn = + node.operation === 'mutation' + ? `export type ${this.convertName( + node.name.value + 'MutationFn' + )} = ReactApollo.MutationFn<${operationResultType}, ${operationVariablesTypes}>;` + : null; + + const hocString = `export function ${operationName}HOC(operationOptions: ReactApollo.OperationOption< + TProps, + ${operationResultType}, + ${operationVariablesTypes}, + ${propsTypeName}> | undefined) { + return ReactApollo.graphql>(${documentVariableName}, operationOptions); +};`; + + return [propsVar, mutationFn, hocString].filter(a => a).join('\n'); + } + + private _buildComponent( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + const componentName: string = this.convertName(node.name.value + 'Component'); + + return ` +export class ${componentName} extends React.Component>> { + render() { + return ( + ${ + node.operation + }={${documentVariableName}} {...(this as any)['props'] as any} /> + ); + } +}`; + } + + private _buildHooks( + node: OperationDefinitionNode, + operationType: string, + documentVariableName: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + return ` +export function use${operationResultType}(baseOptions?: ReactApolloHooks.${operationType}HookOptions<${ + node.operation !== 'query' ? `${operationResultType}, ` : '' + }${operationVariablesTypes}>) { + return ReactApolloHooks.use${operationType}<${operationResultType}, ${operationVariablesTypes}>(${documentVariableName}, baseOptions); +};`; + } + + protected buildOperation( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + const component = this.config.withComponent + ? this._buildComponent(node, documentVariableName, operationType, operationResultType, operationVariablesTypes) + : null; + const hoc = this.config.withHOC + ? this._buildOperationHoc(node, documentVariableName, operationResultType, operationVariablesTypes) + : null; + const hooks = this.config.withHooks + ? this._buildHooks(node, operationType, documentVariableName, operationResultType, operationVariablesTypes) + : null; + + return [component, hoc, hooks].filter(a => a).join('\n'); + } +} diff --git a/packages/plugins/typescript-react-apollo/tests/files/schema.json b/packages/plugins/typescript-react-apollo/tests/files/schema.json deleted file mode 100644 index e9ce20244e9..00000000000 --- a/packages/plugins/typescript-react-apollo/tests/files/schema.json +++ /dev/null @@ -1,1739 +0,0 @@ -{ - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": { - "name": "Mutation" - }, - "subscriptionType": { - "name": "Subscription" - }, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": "", - "fields": [ - { - "name": "feed", - "description": "A feed of repository submissions", - "args": [ - { - "name": "type", - "description": "The sort order for the feed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "FeedType", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "The number of items to skip, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "limit", - "description": "The number of items to fetch starting from the offset, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "entry", - "description": "A single entry", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "currentUser", - "description": "Return the currently logged in user, or null if nobody is logged in", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FeedType", - "description": "A list of options for the sort order of the feed", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "HOT", - "description": "Sort by a combination of freshness and score, using Reddit's algorithm", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NEW", - "description": "Newest entries first", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TOP", - "description": "Highest score entries first", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Entry", - "description": "Information about a GitHub repository submitted to GitHunt", - "fields": [ - { - "name": "repository", - "description": "Information about the repository from GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Repository", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who submitted this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the entry was submitted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "score", - "description": "The score of this repository, upvotes - downvotes", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hotScore", - "description": "The hot score of this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "comments", - "description": "Comments posted about this repository", - "args": [ - { - "name": "limit", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commentCount", - "description": "The number of comments posted about this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "XXX to be changed", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Repository", - "description": "A repository object from the GitHub API. This uses the exact field names returned by the\nGitHub API for simplicity, even though the convention for GraphQL is usually to camel case.", - "fields": [ - { - "name": "name", - "description": "Just the name of the repository, e.g. GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full_name", - "description": "The full name of the repository with the username, e.g. apollostack/GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "The description of the repository", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The link to the repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "stargazers_count", - "description": "The number of people who have starred this repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "open_issues_count", - "description": "The number of open issues on this repository on GitHub", - "args": [], - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "owner", - "description": "The owner of this repository on GitHub, e.g. apollostack", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "User", - "description": "A user object from the GitHub API. This uses the exact field names returned from the GitHub API.", - "fields": [ - { - "name": "login", - "description": "The name of the user, e.g. apollostack", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "avatar_url", - "description": "The URL to a directly embeddable image for this user's avatar", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The URL of this user's GitHub page", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Float", - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Comment", - "description": "A comment about an entry, submitted by a user", - "fields": [ - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who posted the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the comment was posted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "content", - "description": "The text of the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "repoName", - "description": "The repository which this comment is about", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Vote", - "description": "XXX to be removed", - "fields": [ - { - "name": "vote_value", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Mutation", - "description": "", - "fields": [ - { - "name": "submitRepository", - "description": "Submit a new repository, returns the new submission", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "Vote on a repository submission, returns the submission that was voted on", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "type", - "description": "The type of vote - UP, DOWN, or CANCEL", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VoteType", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "submitComment", - "description": "Comment on a repository, returns the new comment", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "commentContent", - "description": "The text content for the new comment", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "VoteType", - "description": "The type of vote to record, when submitting a vote", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "UP", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "DOWN", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "CANCEL", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Subscription", - "description": "", - "fields": [ - { - "name": "commentAdded", - "description": "Subscription fires on every comment added", - "args": [ - { - "name": "repoFullName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "locations", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__DirectiveLocation", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "QUERY", - "description": "Location adjacent to a query operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MUTATION", - "description": "Location adjacent to a mutation operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SUBSCRIPTION", - "description": "Location adjacent to a subscription operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD", - "description": "Location adjacent to a field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_DEFINITION", - "description": "Location adjacent to a fragment definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_SPREAD", - "description": "Location adjacent to a fragment spread.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INLINE_FRAGMENT", - "description": "Location adjacent to an inline fragment.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCHEMA", - "description": "Location adjacent to a schema definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCALAR", - "description": "Location adjacent to a scalar definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Location adjacent to an object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD_DEFINITION", - "description": "Location adjacent to a field definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ARGUMENT_DEFINITION", - "description": "Location adjacent to an argument definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Location adjacent to an interface definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Location adjacent to a union definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Location adjacent to an enum definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM_VALUE", - "description": "Location adjacent to an enum value definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Location adjacent to an input object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_FIELD_DEFINITION", - "description": "Location adjacent to an input object field definition.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - } - ], - "directives": [ - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "deprecated", - "description": "Marks an element of a GraphQL schema as no longer supported.", - "locations": ["FIELD_DEFINITION", "ENUM_VALUE"], - "args": [ - { - "name": "reason", - "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": "\"No longer supported\"" - } - ] - } - ] - } -} diff --git a/packages/plugins/typescript-react-apollo/tests/react-apollo.spec.ts b/packages/plugins/typescript-react-apollo/tests/react-apollo.spec.ts index d970fd5ffb1..027f2a25c8d 100644 --- a/packages/plugins/typescript-react-apollo/tests/react-apollo.spec.ts +++ b/packages/plugins/typescript-react-apollo/tests/react-apollo.spec.ts @@ -1,707 +1,564 @@ -import 'graphql-codegen-core/dist/testing'; -import { makeExecutableSchema } from 'graphql-tools'; -import { plugin } from '../dist'; -import * as fs from 'fs'; +import 'graphql-codegen-testing'; +import { plugin } from '../src/index'; +import { parse, GraphQLSchema, buildClientSchema } from 'graphql'; import gql from 'graphql-tag'; -import { buildClientSchema } from 'graphql'; - -describe('Components', () => { - const schema = buildClientSchema(JSON.parse(fs.readFileSync('./tests/files/schema.json').toString())); - - it('should import React and ReactApollo dependencies', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } +import { DocumentFile } from 'graphql-codegen-plugin-helpers'; +import { plugin as tsPlugin } from '../../typescript/src/index'; +import { plugin as tsDocumentsPlugin } from '../../typescript-operations/src/index'; +import { validateTs } from '../../typescript/tests/validate'; +import { readFileSync } from 'fs'; + +describe('React Apollo', () => { + const schema = buildClientSchema(JSON.parse(readFileSync('../../../dev-test/githunt/schema.json').toString())); + const basicDoc = parse(/* GraphQL */ ` + query test { + feed { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url } } } - `; + } + `); + + const validateTypeScript = async ( + output: string, + testSchema: GraphQLSchema, + documents: DocumentFile[], + config: any + ) => { + const tsOutput = await tsPlugin(testSchema, documents, config, { outputFile: '' }); + const tsDocumentsOutput = await tsDocumentsPlugin(testSchema, documents, config, { outputFile: '' }); + const merged = [tsOutput, tsDocumentsOutput, output].join('\n'); + validateTs(merged, undefined, true); + }; + it(`should skip if there's no operations`, async () => { const content = await plugin( schema, - [{ filePath: '', content: documents }], + [], {}, { outputFile: 'graphql.tsx' } ); - expect(content).toBeSimilarStringTo(` - import * as ReactApollo from 'react-apollo'; - `); - - expect(content).toBeSimilarStringTo(` - import * as React from 'react'; - `); - - expect(content).toBeSimilarStringTo(` - import gql from 'graphql-tag'; - `); + expect(content).not.toContain(`import * as ReactApollo from 'react-apollo';`); + expect(content).not.toContain(`import * as React from 'react';`); + expect(content).not.toContain(`import gql from 'graphql-tag';`); + await validateTypeScript(content, schema, [], {}); }); - it('should generate Document variable', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } + describe('Imports', () => { + it('should import React and ReactApollo dependencies', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' } - } - `; + ); - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - {}, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).toBeSimilarStringTo(` - export const Document = gql\` - { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - \`; - `); - }); + expect(content).toBeSimilarStringTo(`import * as ReactApollo from 'react-apollo';`); + expect(content).toBeSimilarStringTo(`import * as React from 'react';`); + expect(content).toBeSimilarStringTo(`import gql from 'graphql-tag';`); + await validateTypeScript(content, schema, docs, {}); + }); - it('should generate Component', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } + it('should import DocumentNode when using noGraphQLTag', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { + noGraphQLTag: true + }, + { + outputFile: 'graphql.tsx' } - } - `; + ); - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - {}, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).toBeSimilarStringTo(` - export class Component extends React.Component>> { - render(){ - return ( - - query={ Document } - {...(this as any)['props'] as any} - /> - ); - } - } - `); - }); + expect(content).toContain(`import { DocumentNode } from 'graphql';`); + expect(content).not.toBeSimilarStringTo(`import gql from 'graphql-tag';`); + await validateTypeScript(content, schema, docs, {}); + }); - it('should generate HOCs', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } + it(`should use gql import from gqlImport config option`, async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { gqlImport: 'graphql.macro#gql' }, + { + outputFile: 'graphql.tsx' } - } - `; + ); - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - {}, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).toBeSimilarStringTo(` - export function HOC(operationOptions: - ReactApollo.OperationOption< - TProps, - Query, - Variables, - Props - > | undefined){ - return ReactApollo.graphql>( - Document, - operationOptions - ); - }; - `); - }); - - it('should generate Document variables for inline fragments', async () => { - const repositoryWithOwner = gql` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - `; - const feedWithRepository = gql` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } + expect(content).toContain(`import { gql } from 'graphql.macro';`); + await validateTypeScript(content, schema, docs, {}); + }); - ${repositoryWithOwner} - `; - const myFeed = gql` - query MyFeed { - feed { - ...FeedWithRepository + it('should import ReactApolloHooks dependencies', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { withHooks: true }, + { + outputFile: 'graphql.tsx' } - } + ); - ${feedWithRepository} - `; + expect(content).toBeSimilarStringTo(`import * as ReactApolloHooks from 'react-apollo-hooks';`); + await validateTypeScript(content, schema, docs, {}); + }); - const content = await plugin( - schema, - [{ filePath: '', content: myFeed }], - {}, - { - outputFile: 'graphql.tsx' - } - ); + it('should import ReactApolloHooks from hooksImportFrom config option', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { withHooks: true, hooksImportFrom: 'custom-apollo-hooks' }, + { + outputFile: 'graphql.tsx' + } + ); - expect(content).toBeSimilarStringTo(` - export namespace FeedWithRepository { - export const FragmentDoc = gql\` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } + expect(content).toBeSimilarStringTo(`import * as ReactApolloHooks from 'custom-apollo-hooks';`); + await validateTypeScript(content, schema, docs, {}); + }); - \${RepositoryWithOwner.FragmentDoc} + it('should skip import React and ReactApollo if only hooks are used', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { + withHooks: true, + withHOC: false, + withComponent: false + }, + { + outputFile: 'graphql.tsx' + } + ); - \`; - } - `); - expect(content).toBeSimilarStringTo(` - export namespace RepositoryWithOwner { - export const FragmentDoc = gql\` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - \`; - } - `); + expect(content).not.toBeSimilarStringTo(`import * as ReactApollo from 'react-apollo';`); + expect(content).not.toBeSimilarStringTo(`import * as React from 'react';`); + await validateTypeScript(content, schema, docs, {}); + }); }); - it('should embed inline fragments inside query document', async () => { - const repositoryWithOwner = gql` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - `; - const feedWithRepository = gql` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } + describe('Fragments', () => { + it('Should generate basic fragments documents correctly', async () => { + const docs = [ + { + filePath: 'a.graphql', + content: parse(/* GraphQL */ ` + fragment MyFragment on Repository { + full_name + } - ${repositoryWithOwner} - `; - const myFeed = gql` - query MyFeed { - feed { - ...FeedWithRepository + query { + feed { + id + } + } + `) } - } + ]; + const result = await plugin(schema, docs, {}, { outputFile: '' }); - ${feedWithRepository} - `; - - const content = await plugin( - schema, - [{ filePath: '', content: myFeed }], - {}, - { - outputFile: 'graphql.tsx' + expect(result).toBeSimilarStringTo(` + export const MyFragmentFragmentDoc = gql\` + fragment MyFragment on Repository { + full_name } - ); + \`;`); + await validateTypeScript(result, schema, docs, {}); + }); - expect(content).toBeSimilarStringTo(` - export const Document = gql\` - query MyFeed { - feed { - ...FeedWithRepository - } + it('should generate Document variables for inline fragments', async () => { + const repositoryWithOwner = gql` + fragment RepositoryWithOwner on Repository { + full_name + html_url + owner { + avatar_url } - - \${FeedWithRepository.FragmentDoc} - \`; - `); - }); - it('no duplicated fragments', async () => { - const simpleFeed = gql` - fragment SimpleFeed on FeedType { - id - commentCount - } - `; - const myFeed = gql` - query MyFeed { - feed { - ...SimpleFeed } - allFeeds { - ...SimpleFeed + `; + const feedWithRepository = gql` + fragment FeedWithRepository on FeedType { + id + commentCount + repository(search: "phrase") { + ...RepositoryWithOwner + } } - } - `; - const documents = [simpleFeed, myFeed]; - const content = await plugin( - schema, - documents.map(content => ({ content, filePath: '' })), - {}, - { - outputFile: 'graphql.tsx' - } - ); - expect(content).toBeSimilarStringTo(` - const Document = gql\` query MyFeed { + ${repositoryWithOwner} + `; + const myFeed = gql` + query MyFeed { feed { - ...SimpleFeed - } - allFeeds { - ...SimpleFeed + ...FeedWithRepository } } - \${SimpleFeed.FragmentDoc} - \` - `); - expect(content).toBeSimilarStringTo(` - const FragmentDoc = gql\` fragment SimpleFeed on FeedType { - id - commentCount - } - \`; - `); - }); - - it('write fragments in proper order (when one depends on other)', async () => { - const myFeed = gql` - fragment FeedWithRepository on FeedType { - id - repository { - ...RepositoryWithOwner - } - } - fragment RepositoryWithOwner on Repository { - full_name - } - query MyFeed { - feed { - ...FeedWithRepository - } - } - `; - const documents = [myFeed]; - const content = await plugin( - schema, - documents.map(content => ({ content, filePath: '' })), - {}, - { - outputFile: 'graphql.tsx' - } - ); - - const feedWithRepositoryPos = content.indexOf('fragment FeedWithRepository'); - const repositoryWithOwnerPos = content.indexOf('fragment RepositoryWithOwner'); - expect(repositoryWithOwnerPos).toBeLessThan(feedWithRepositoryPos); - }); - it('Issue 702 - handle duplicated documents when fragment and query have the same name', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Event { - type: String! - name: String! - } + ${feedWithRepository} + `; - type Query { - events: [Event] - } + const docs = [{ filePath: '', content: myFeed }]; - schema { - query: Query + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' } - ` + ); + + expect(content).toBeSimilarStringTo(`export const FeedWithRepositoryFragmentDoc = gql\` +fragment FeedWithRepository on FeedType { + id + commentCount + repository(search: "phrase") { + ...RepositoryWithOwner + } +} +\${RepositoryWithOwnerFragmentDoc}\`;`); + expect(content).toBeSimilarStringTo(`export const RepositoryWithOwnerFragmentDoc = gql\` +fragment RepositoryWithOwner on Repository { + full_name + html_url + owner { + avatar_url + } +} +\`;`); + + expect(content).toBeSimilarStringTo(`export const MyFeedDocument = gql\` +query MyFeed { + feed { + ...FeedWithRepository + } +} +\${FeedWithRepositoryFragmentDoc}\`;`); + await validateTypeScript(content, schema, docs, {}); }); - const query = gql` - fragment event on Event { - name - } - - query event { - events { - ...event + it('should avoid generating duplicate fragments', async () => { + const simpleFeed = gql` + fragment Item on FeedType { + id } - } - `; - - const content = await plugin( - testSchema, - [{ filePath: '', content: query }], - {}, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace Event { - export const FragmentDoc = gql\` - fragment event on Event { - name + `; + const myFeed = gql` + query MyFeed { + feed { + ...Item } - \`; - } - `); - - expect(content).toBeSimilarStringTo(` - export namespace Event { - export const FragmentDoc = gql\` - fragment event on Event { - name + allFeeds: feed { + ...Item } - \`; - } - `); - - expect(content).toBeSimilarStringTo(` - export namespace Event { - export const Document = gql\` - query event { - events { - ...event + } + `; + const documents = [simpleFeed, myFeed]; + const docs = documents.map(content => ({ content, filePath: '' })); + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toBeSimilarStringTo(` + export const MyFeedDocument = gql\` + query MyFeed { + feed { + ...Item + } + allFeeds: feed { + ...Item } } - - \${Event.FragmentDoc} - \`; - `); - }); - - it(`should skip if there's no operations`, async () => { - const content = await plugin( - schema, - [], - { noNamespaces: true }, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).not.toContain(`import * as ReactApollo from 'react-apollo';`); - expect(content).not.toContain(`import * as React from 'react';`); - expect(content).not.toContain(`import gql from 'graphql-tag';`); - }); - - it(`should use gql import from gqlImport config option`, async () => { - const documents = gql` - query { - feed { + \${ItemFragmentDoc}\``); + expect(content).toBeSimilarStringTo(` + export const ItemFragmentDoc = gql\` + fragment Item on FeedType { id } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { gqlImport: 'graphql.macro#gql' }, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).toContain(`import { gql } from 'graphql.macro';`); - }); +\`;`); + await validateTypeScript(content, schema, docs, {}); + }); - it('should import ReactApolloHooks dependencies', async () => { - const documents = gql` - query { - feed { + it('Should generate fragments in proper order (when one depends on other)', async () => { + const myFeed = gql` + fragment FeedWithRepository on FeedType { id - commentCount repository { - full_name - html_url - owner { - avatar_url - } + ...RepositoryWithOwner } } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { withHooks: true }, - { - outputFile: 'graphql.tsx' - } - ); - - expect(content).toBeSimilarStringTo(` - import * as ReactApolloHooks from 'react-apollo-hooks'; - `); - }); - - it('should import ReactApolloHooks from hooksImportFrom config option', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } + fragment RepositoryWithOwner on Repository { + full_name + } + query MyFeed { + feed { + ...FeedWithRepository } } - } - `; - - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { withHooks: true, hooksImportFrom: 'custom-apollo-hooks' }, - { - outputFile: 'graphql.tsx' - } - ); + `; + const documents = [myFeed]; + const docs = documents.map(content => ({ content, filePath: '' })); + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' + } + ); - expect(content).toBeSimilarStringTo(` - import * as ReactApolloHooks from 'custom-apollo-hooks'; - `); + const feedWithRepositoryPos = content.indexOf('fragment FeedWithRepository'); + const repositoryWithOwnerPos = content.indexOf('fragment RepositoryWithOwner'); + expect(repositoryWithOwnerPos).toBeLessThan(feedWithRepositoryPos); + await validateTypeScript(content, schema, docs, {}); + }); }); - it('should generate Hooks', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url + describe('Component', () => { + it('should generate Document variable', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toBeSimilarStringTo(` + export const TestDocument = gql\` + query test { + feed { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } + } } } + \`; + `); + await validateTypeScript(content, schema, docs, {}); + }); + + it('should generate Document variable with noGraphQlTag', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { + noGraphQLTag: true + }, + { + outputFile: 'graphql.tsx' } - } + ); - mutation($name: String) { - submitRepository(repoFullName: $name) - } - `; + expect(content).toBeSimilarStringTo(`export const TestDocument: DocumentNode = {"kind":"Document","defin`); + await validateTypeScript(content, schema, docs, {}); + }); - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { withHooks: true }, - { - outputFile: 'graphql.tsx' - } - ); + it('should generate Component', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toBeSimilarStringTo(` + export class TestComponent extends React.Component>> { + render() { + return ( + query={TestDocument} {...(this as any)['props'] as any} /> + ); + } + }`); + await validateTypeScript(content, schema, docs, {}); + }); - expect(content).toBeSimilarStringTo(` - export function use(baseOptions?: ReactApolloHooks.QueryHookOptions< - Variables - >) { - return ReactApolloHooks.useQuery< - Query, - Variables - >(Document, baseOptions); - }; - `); - - expect(content).toBeSimilarStringTo(` - export function use(baseOptions?: ReactApolloHooks.MutationHookOptions< - Mutation, - Variables - >) { - return ReactApolloHooks.useMutation< - Mutation, - Variables - >(Document, baseOptions); - }; - `); + it('should not generate Component', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { withComponent: false }, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).not.toContain(`export class TestComponent`); + await validateTypeScript(content, schema, docs, {}); + }); }); - it('should generate Subscription Hooks', async () => { - const documents = gql` - subscription ListenToComments($name: String) { - commentAdded(repoFullName: $name) { - id + describe('HOC', () => { + it('should generate HOCs', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + {}, + { + outputFile: 'graphql.tsx' } - } - `; + ); + + expect(content).toBeSimilarStringTo( + `export type TestProps = Partial> & TChildProps;` + ); + + expect(content) + .toBeSimilarStringTo(`export function TestHOC(operationOptions: ReactApollo.OperationOption< + TProps, + TestQuery, + TestQueryVariables, + TestProps> | undefined) { + return ReactApollo.graphql>(TestDocument, operationOptions); +};`); + await validateTypeScript(content, schema, docs, {}); + }); - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { - noNamespaces: true, - withHooks: true - }, - { - outputFile: 'graphql.tsx' - } - ); + it('should not generate HOCs', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { withHOC: false }, + { + outputFile: 'graphql.tsx' + } + ); - expect(content).toBeSimilarStringTo(` - export function useListenToComments(baseOptions?: ReactApolloHooks.SubscriptionHookOptions< - ListenToCommentsSubscription, - ListenToCommentsVariables - >) { - return ReactApolloHooks.useSubscription< - ListenToCommentsSubscription, - ListenToCommentsVariables - >(ListenToCommentsDocument, baseOptions); - }; - `); + expect(content).not.toContain(`export type TestProps`); + expect(content).not.toContain(`export function TestHOC`); + await validateTypeScript(content, schema, docs, {}); + }); }); - it('should skip import React and ReactApollo if only hooks are used', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url + describe('Hooks', () => { + it('Should generate hooks for query and mutation', async () => { + const documents = parse(/* GraphQL */ ` + query feed { + feed { + id + commentCount + repository { + full_name + html_url + owner { + avatar_url + } } } } - } - `; - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { - withHooks: true, - noHOC: true, - noComponents: true - }, - { - outputFile: 'graphql.tsx' - } - ); + mutation submitRepository($name: String) { + submitRepository(repoFullName: $name) { + id + } + } + `); + const docs = [{ filePath: '', content: documents }]; + + const content = await plugin( + schema, + docs, + { withHooks: true, withComponent: false, withHOC: false }, + { + outputFile: 'graphql.tsx' + } + ); + + expect(content).toBeSimilarStringTo(` +export function useFeedQuery(baseOptions?: ReactApolloHooks.QueryHookOptions) { + return ReactApolloHooks.useQuery(FeedDocument, baseOptions); +};`); + + expect(content).toBeSimilarStringTo(` +export function useSubmitRepositoryMutation(baseOptions?: ReactApolloHooks.MutationHookOptions) { + return ReactApolloHooks.useMutation(SubmitRepositoryDocument, baseOptions); +};`); + await validateTypeScript(content, schema, docs, {}); + }); - expect(content).not.toBeSimilarStringTo(` - import * as ReactApollo from 'react-apollo'; - `); + it('Should not generate hooks for query and mutation', async () => { + const docs = [{ filePath: '', content: basicDoc }]; + const content = await plugin( + schema, + docs, + { withHooks: false }, + { + outputFile: 'graphql.tsx' + } + ); - expect(content).not.toBeSimilarStringTo(` - import * as React from 'react'; - `); - }); - it('should import ReactApolloHooks from hooksImportFrom config option', async () => { - const documents = gql` - query { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } + expect(content).not.toContain(`export function useTestQuery`); + await validateTypeScript(content, schema, docs, {}); + }); + + it('Should generate subscription hooks', async () => { + const documents = parse(/* GraphQL */ ` + subscription ListenToComments($name: String) { + commentAdded(repoFullName: $name) { + id } } - } - `; + `); - const content = await plugin( - schema, - [{ filePath: '', content: documents }], - { withHooks: true, hooksImportFrom: 'custom-apollo-hooks' }, - { - outputFile: 'graphql.tsx' - } - ); + const docs = [{ filePath: '', content: documents }]; + + const content = await plugin( + schema, + docs, + { + withHooks: true, + withComponent: false, + withHOC: false + }, + { + outputFile: 'graphql.tsx' + } + ); - expect(content).toBeSimilarStringTo(` - import * as ReactApolloHooks from 'custom-apollo-hooks'; - `); + expect(content).toBeSimilarStringTo(` +export function useListenToCommentsSubscription(baseOptions?: ReactApolloHooks.SubscriptionHookOptions) { + return ReactApolloHooks.useSubscription(ListenToCommentsDocument, baseOptions); +};`); + await validateTypeScript(content, schema, docs, {}); + }); }); }); diff --git a/packages/plugins/typescript-react-apollo/tsconfig.json b/packages/plugins/typescript-react-apollo/tsconfig.json index 77f658f5db3..42d8ecdd098 100644 --- a/packages/plugins/typescript-react-apollo/tsconfig.json +++ b/packages/plugins/typescript-react-apollo/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/typescript-resolvers/package.json b/packages/plugins/typescript-resolvers/package.json index ed33ef2f88b..7bac0224edc 100644 --- a/packages/plugins/typescript-resolvers/package.json +++ b/packages/plugins/typescript-resolvers/package.json @@ -1,47 +1,33 @@ { "name": "graphql-codegen-typescript-resolvers", "version": "0.18.0", - "description": "graphql-codegen-cli template for TypeScript typings for both client side and server side", + "description": "GraphQL Codegen pluginfor TypeScript typings for resolvers signature", "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "dependencies": { - "graphql-codegen-plugin-helpers": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" + "tslib": "1.9.3", + "graphql-codegen-typescript": "0.18.0", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" + "graphql-codegen-testing": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "flow-bin": "0.94.0", + "flow-parser": "0.94.0", + "graphql": "14.1.1" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/typescript-resolvers/src/context.ts b/packages/plugins/typescript-resolvers/src/context.ts deleted file mode 100644 index 2cd08259d93..00000000000 --- a/packages/plugins/typescript-resolvers/src/context.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { parseMapper } from './mappers'; - -export function importContext(options: Handlebars.HelperOptions): string { - const config = options.data.root.config || {}; - const contextType: string | undefined = config.contextType; - - if (typeof contextType === 'string') { - const mapper = parseMapper(contextType); - - if (mapper.isExternal) { - return `import { ${mapper.type} } from '${mapper.source}';`; - } - } - - return ''; -} - -export function getContext(options: Handlebars.HelperOptions): string { - const config = options.data.root.config || {}; - const contextType: string | undefined = config.contextType; - - if (typeof contextType !== 'string') { - return '{}'; - } - - const mapper = parseMapper(contextType); - - return mapper.type; -} diff --git a/packages/plugins/typescript-resolvers/src/directive.handlebars b/packages/plugins/typescript-resolvers/src/directive.handlebars deleted file mode 100644 index 3ebcb195f7b..00000000000 --- a/packages/plugins/typescript-resolvers/src/directive.handlebars +++ /dev/null @@ -1,13 +0,0 @@ -{{ toComment description }} -export type {{ convert name 'typeNames' }}DirectiveResolver = DirectiveResolverFn; - -{{~# if hasArguments }} - -export interface {{ convert name 'typeNames' }}DirectiveArgs { -{{#each arguments}} - {{ toComment description }} - {{ name }}{{ getOptionals this }}: {{ convertedType this }}; -{{/each}} -} - -{{/if}} \ No newline at end of file diff --git a/packages/plugins/typescript-resolvers/src/helpers.ts b/packages/plugins/typescript-resolvers/src/helpers.ts deleted file mode 100644 index 875cb943ed9..00000000000 --- a/packages/plugins/typescript-resolvers/src/helpers.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { SafeString } from 'handlebars'; -import { Field, Type, Interface, Union } from 'graphql-codegen-core'; -import { GraphQLSchema } from 'graphql'; -import { convertedType, getFieldType as fieldType } from 'graphql-codegen-typescript-common'; -import { pickMapper, useDefaultMapper } from './mappers'; - -export function importFromGraphQL(options: Handlebars.HelperOptions) { - const imports: string[] = ['GraphQLResolveInfo']; - - if (options.data.root.hasScalars) { - imports.push('GraphQLScalarType', 'GraphQLScalarTypeConfig'); - } - - return `import { ${imports.join(', ')} } from 'graphql';`; -} - -export const getFieldType = convert => (field: Field, options: Handlebars.HelperOptions) => { - const config = options.data.root.config || {}; - const mapper = pickMapper(field.type, config.mappers || {}, options); - const defaultMapper = useDefaultMapper(field, options); - - if (mapper) { - return fieldType(field, mapper.type, options); - } - - if (defaultMapper) { - return fieldType(field, defaultMapper.type, options); - } - - return convertedType(field, options, convert); -}; - -export const getFieldResolverName = (convert, config) => (name: string) => { - return `${config.fieldResolverNamePrefix || ''}${convert(name)}Resolver`; -}; - -export const getFieldResolver = convert => (field: Field, type: Type, options: Handlebars.HelperOptions) => { - if (!field) { - return ''; - } - - let resolver: string; - const config = options.data.root.config || {}; - const schema: GraphQLSchema = options.data.root.rawSchema; - const subscriptionType = schema.getSubscriptionType(); - const isSubscription = subscriptionType && subscriptionType.name === type.name; - - if (isSubscription) { - resolver = 'SubscriptionResolver'; - } else { - resolver = 'Resolver'; - } - - const generics: string[] = ['R', 'Parent', 'TContext']; - - if (field.hasArguments) { - const prefix = config.noNamespaces ? convert(type.name, 'typeNames') : ''; - generics.push(`${prefix}${convert(field.name)}Args`); - } - - return new SafeString(`${resolver}<${generics.join(', ')}>`); -}; - -export function getTypenames(entity: Interface | Union): string { - let types: string[] = []; - - if (isInterface(entity)) { - types = entity.implementingTypes; - } else { - types = entity.possibleTypes; - } - - return types.map(t => `'${t}'`).join(' | '); -} - -export function isInterface(entity: any): entity is Interface { - return typeof (entity as Interface).implementingTypes !== 'undefined'; -} diff --git a/packages/plugins/typescript-resolvers/src/import-mappers.ts b/packages/plugins/typescript-resolvers/src/import-mappers.ts deleted file mode 100644 index f7143dafa62..00000000000 --- a/packages/plugins/typescript-resolvers/src/import-mappers.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Type, Interface } from 'graphql-codegen-core'; -import { pickMapper, parseMapper } from './mappers'; - -interface Modules { - [path: string]: string[]; -} - -function extractVariable(type: string) { - const m = /^[^\[\.]+/.exec(type); - return m ? m[0] : type; -} - -export function importMappers(types: Type[], interfaces: Interface[], options: Handlebars.HelperOptions) { - const config = options.data.root.config || {}; - const mappers = config.mappers || {}; - const defaultMapper: string | undefined = config.defaultMapper; - const modules: Modules = {}; - const availableTypes = types.map(t => t.name); - const availableInterfaces = interfaces.map(iface => iface.name); - - if (defaultMapper) { - const mapper = parseMapper(defaultMapper); - - if (mapper.isExternal) { - modules[mapper.source] = [mapper.type]; - } - } - - for (const type in mappers) { - if (mappers.hasOwnProperty(type)) { - const mapper = pickMapper(type, mappers, options); - - // checks if mapper comes from a module - // and if is used - if (mapper && mapper.isExternal && (availableTypes.includes(type) || availableInterfaces.includes(type))) { - const path = mapper.source; - const variable = extractVariable(mapper.type); - - if (!modules[path]) { - modules[path] = []; - } - - // checks for duplicates - if (!modules[path].includes(variable)) { - modules[path].push(variable); - } - } - } - } - - const imports: string[] = Object.keys(modules).map( - path => ` - import { ${modules[path].join(', ')} } from '${path}'; - ` - ); - - return imports.join('\n'); -} diff --git a/packages/plugins/typescript-resolvers/src/index.ts b/packages/plugins/typescript-resolvers/src/index.ts index 5865b835843..1b89a37b791 100644 --- a/packages/plugins/typescript-resolvers/src/index.ts +++ b/packages/plugins/typescript-resolvers/src/index.ts @@ -1,46 +1,98 @@ -import { TypeScriptCommonConfig, initCommonTemplate } from 'graphql-codegen-typescript-common'; -import { PluginFunction, DocumentFile } from 'graphql-codegen-core'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; -import * as resolver from './resolver.handlebars'; -import * as resolveType from './resolve-type.handlebars'; -import * as directive from './directive.handlebars'; -import * as scalar from './scalar.handlebars'; -import { getFieldResolverName, getFieldResolver, getFieldType, getTypenames, importFromGraphQL } from './helpers'; -import { importMappers } from './import-mappers'; -import { importContext, getContext } from './context'; -import { getParentType, getParentTypes } from './parent-type'; - -export interface TypeScriptServerResolversConfig extends TypeScriptCommonConfig { - strict?: boolean; - noNamespaces?: boolean; - contextType?: string; - mappers?: { [name: string]: string }; - defaultMapper?: string; - fieldResolverNamePrefix?: string; +import { RawResolversConfig } from 'graphql-codegen-visitor-plugin-common'; +import { DocumentFile, PluginFunction } from 'graphql-codegen-plugin-helpers'; +import { isScalarType, parse, printSchema, visit, GraphQLSchema } from 'graphql'; +import { TypeScriptResolversVisitor } from './visitor'; + +export interface TypeScriptResolversPluginConfig extends RawResolversConfig { + avoidOptionals?: boolean; + immutableTypes?: boolean; } -export const plugin: PluginFunction = async ( +export const plugin: PluginFunction = ( schema: GraphQLSchema, documents: DocumentFile[], - config: TypeScriptServerResolversConfig -): Promise => { - const { templateContext, convert } = initCommonTemplate(Handlebars, schema, documents, config); - Handlebars.registerPartial('resolver', resolver); - Handlebars.registerPartial('resolveType', resolveType); - Handlebars.registerPartial('directive', directive); - Handlebars.registerPartial('scalar', scalar); - Handlebars.registerHelper('getFieldResolverName', getFieldResolverName(convert, config)); - Handlebars.registerHelper('getFieldResolver', getFieldResolver(convert)); - Handlebars.registerHelper('getTypenames', getTypenames); - Handlebars.registerHelper('getParentType', getParentType(convert)); - Handlebars.registerHelper('getParentTypes', getParentTypes(convert)); - Handlebars.registerHelper('getFieldType', getFieldType(convert)); - Handlebars.registerHelper('importMappers', importMappers); - Handlebars.registerHelper('importContext', importContext); - Handlebars.registerHelper('importFromGraphQL', importFromGraphQL); - Handlebars.registerHelper('getContext', getContext); - - return Handlebars.compile(rootTemplate)(templateContext); + config: TypeScriptResolversPluginConfig +) => { + const imports = ['GraphQLResolveInfo']; + const hasScalars = Object.values(schema.getTypeMap()) + .filter(t => t.astNode) + .some(isScalarType); + + if (hasScalars) { + imports.push('GraphQLScalarType', 'GraphQLScalarTypeConfig'); + } + + const visitor = new TypeScriptResolversVisitor(config, schema); + + const header = ` +import { ${imports.join(', ')} } from 'graphql'; + +export type ResolverFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => Promise | TResult; + +export type StitchingResolver = { + fragment: string; + resolve: ResolverFn; +}; + +export type Resolver = + | ResolverFn + | StitchingResolver; + +export type SubscriptionSubscribeFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => AsyncIterator | Promise>; + +export type SubscriptionResolveFn = ( + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => TResult | Promise; + +export interface ISubscriptionResolverObject { + subscribe: SubscriptionSubscribeFn; + resolve?: SubscriptionResolveFn; +} + +export type SubscriptionResolver = + | ((...args: any[]) => ISubscriptionResolverObject) + | ISubscriptionResolverObject; + +export type TypeResolveFn = ( + parent?: TParent, + context?: TContext, + info?: GraphQLResolveInfo +) => Maybe; + +export type NextResolverFn = () => Promise; + +export type DirectiveResolverFn = ( + next?: NextResolverFn, + parent?: TParent, + args?: TArgs, + context?: TContext, + info?: GraphQLResolveInfo +) => TResult | Promise; +`; + + const printedSchema = printSchema(schema); + const astNode = parse(printedSchema); + const visitorResult = visit(astNode, { leave: visitor }); + const { getRootResolver, getAllDirectiveResolvers, mappersImports } = visitor; + + return [ + ...mappersImports, + header, + ...visitorResult.definitions.filter(d => typeof d === 'string'), + getRootResolver(), + getAllDirectiveResolvers() + ].join('\n'); }; diff --git a/packages/plugins/typescript-resolvers/src/mappers.ts b/packages/plugins/typescript-resolvers/src/mappers.ts deleted file mode 100644 index 39a85623773..00000000000 --- a/packages/plugins/typescript-resolvers/src/mappers.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Field, Type } from 'graphql-codegen-core'; -import { GraphQLNamedType } from 'graphql'; - -export interface ParentsMap { - [key: string]: string; -} - -export interface Mapper { - isExternal: boolean; - type: string; - source?: string; -} - -function isExternal(value: string) { - return value.includes('#'); -} - -export function parseMapper(mapper: string): Mapper { - if (isExternal(mapper)) { - const [source, type] = mapper.split('#'); - return { - isExternal: true, - source, - type - }; - } - - return { - isExternal: false, - type: mapper - }; -} - -export function pickMapper(entity: string, map: ParentsMap, options: Handlebars.HelperOptions): Mapper | undefined { - const mapper = map[entity]; - - return mapper ? parseMapper(mapper) : undefined; -} - -export function useDefaultMapper( - entity: Field | Type | GraphQLNamedType, - options: Handlebars.HelperOptions -): Mapper | undefined { - const config = options.data.root.config || {}; - const defaultMapper: string | undefined = config.defaultMapper; - - return defaultMapper && canUseDefault(entity) ? parseMapper(defaultMapper) : undefined; -} - -function canUseDefault(entity: Field | Type | GraphQLNamedType): boolean { - if (isField(entity)) { - return entity.isUnion || entity.isType || entity.isInterface; - } - - return true; -} - -function isField(field: any): field is Field { - return typeof field.fieldType !== 'undefined'; -} diff --git a/packages/plugins/typescript-resolvers/src/parent-type.ts b/packages/plugins/typescript-resolvers/src/parent-type.ts deleted file mode 100644 index f7775f2858a..00000000000 --- a/packages/plugins/typescript-resolvers/src/parent-type.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Type, Interface, Union } from 'graphql-codegen-core'; -import { GraphQLSchema, GraphQLObjectType, GraphQLNamedType } from 'graphql'; -import { pickMapper, useDefaultMapper } from './mappers'; -import { isInterface } from './helpers'; - -const emptyParent = '{}'; - -function getRootTypeNames(schema: GraphQLSchema): string[] { - const query = ((schema.getQueryType() || {}) as GraphQLObjectType).name; - const mutation = ((schema.getMutationType() || {}) as GraphQLObjectType).name; - const subscription = ((schema.getSubscriptionType() || {}) as GraphQLObjectType).name; - - return [query, mutation, subscription]; -} - -function isRootType( - type: { - name: string; - }, - schema: GraphQLSchema -) { - return getRootTypeNames(schema).includes(type.name); -} - -export const getParentType = convert => (type: Type | GraphQLNamedType, options: Handlebars.HelperOptions) => { - const config = options.data.root.config || {}; - const schema: GraphQLSchema = options.data.root.rawSchema; - const mapper = pickMapper(type.name, config.mappers || {}, options); - const defaultMapper = useDefaultMapper(type, options); - let name: string; - - if (mapper) { - name = mapper.type; - } else if (defaultMapper) { - name = defaultMapper.type; - } else { - name = `${config.interfacePrefix || ''}${convert(type.name)}`; - } - - return isRootType(type, schema) ? emptyParent : name; -}; - -export function getParentTypes(convert) { - return (entity: Interface | Union, options: Handlebars.HelperOptions) => { - const schema: GraphQLSchema = options.data.root.rawSchema; - let types: string[] = []; - - if (isInterface(entity)) { - types = entity.implementingTypes; - } else { - types = entity.possibleTypes; - } - - const parentTypes = types - .map(name => schema.getType(name)) - .map(type => getParentType(convert)(type, options)) - .filter((parent, i, all) => all.indexOf(parent) === i); - - if (parentTypes.length) { - return parentTypes.join(' | '); - } - - return emptyParent; - }; -} diff --git a/packages/plugins/typescript-resolvers/src/polyfills.d.ts b/packages/plugins/typescript-resolvers/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-resolvers/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-resolvers/src/resolve-type.handlebars b/packages/plugins/typescript-resolvers/src/resolve-type.handlebars deleted file mode 100644 index 55eb409ff8c..00000000000 --- a/packages/plugins/typescript-resolvers/src/resolve-type.handlebars +++ /dev/null @@ -1,12 +0,0 @@ -{{ toComment description }} -{{#unless @root.config.noNamespaces}} -export namespace {{ convert name 'typeNames'}}Resolvers { -{{/unless}} - export interface {{#if @root.config.noNamespaces}}{{ convert name 'typeNames'}}{{/if}}Resolvers { - __resolveType: {{#if @root.config.noNamespaces}}{{ convert name 'typeNames'}}{{/if}}ResolveType; - } - export type {{#if @root.config.noNamespaces}}{{ convert name 'typeNames'}}{{/if}}ResolveType = TypeResolveFn; - -{{#unless @root.config.noNamespaces}} -} -{{/unless}} \ No newline at end of file diff --git a/packages/plugins/typescript-resolvers/src/resolver.handlebars b/packages/plugins/typescript-resolvers/src/resolver.handlebars deleted file mode 100644 index ace4d5ab87f..00000000000 --- a/packages/plugins/typescript-resolvers/src/resolver.handlebars +++ /dev/null @@ -1,30 +0,0 @@ -{{ toComment description }} -{{#unless @root.config.noNamespaces}} -export namespace {{ convert name 'typeNames'}}Resolvers { -{{/unless}} - export interface {{#if @root.config.noNamespaces}}{{ convert name 'typeNames'}}{{/if}}Resolvers { - {{#each fields}} - {{ toComment description }} - {{ name }}{{#unless @root.config.strict}}?{{/unless}}: {{#if @root.config.noNamespaces}}{{ convert ../name 'typeNames'}}{{/if}}{{ getFieldResolverName name }}<{{{ getFieldType this }}}, TypeParent, TContext>; - {{/each}} - } - - {{#each fields}} - - export type {{#if @root.config.noNamespaces}}{{ convert ../name 'typeNames'}}{{/if}}{{ getFieldResolverName name }} = {{ getFieldResolver this ../this }}; - - {{~# if hasArguments }} - - export interface {{#if @root.config.noNamespaces}}{{ convert ../name 'typeNames'}}{{/if}}{{ convert name 'typeNames'}}Args { - {{#each arguments}} - {{ toComment description }} - {{ name }}{{ getOptionals this }}: {{ convertedType this }}; - {{/each}} - } - - {{/if}} - {{/each}} - -{{#unless @root.config.noNamespaces}} -} -{{/unless}} \ No newline at end of file diff --git a/packages/plugins/typescript-resolvers/src/root.handlebars b/packages/plugins/typescript-resolvers/src/root.handlebars deleted file mode 100644 index 5d208631257..00000000000 --- a/packages/plugins/typescript-resolvers/src/root.handlebars +++ /dev/null @@ -1,88 +0,0 @@ -{{{ importFromGraphQL }}} - -{{{ importMappers types interfaces }}} - -{{{ importContext }}} - -export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo -) => Promise | Result; - -export interface ISubscriptionResolverObject { - subscribe( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): AsyncIterator | Promise>; - resolve?( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): R | Result | Promise; -} - -export type SubscriptionResolver = - | ((...args: any[]) => ISubscriptionResolverObject) - | ISubscriptionResolverObject; - -export type TypeResolveFn = ( - parent: Parent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe; - -export type NextResolverFn = () => Promise; - -export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, -) => TResult | Promise; - -{{#each types}} -{{~> resolver }} -{{/each}} - -{{#each interfaces}} -{{~> resolveType }} -{{/each}} - -{{#each unions}} -{{~> resolveType }} -{{/each}} - -{{#each definedDirectives}} -{{~> directive}} -{{/each}} - -{{#each scalars}} -{{~> scalar}} -{{/each}} - -export type IResolvers = { - {{#each types}} - {{ convert name 'typeNames'}}{{#unless @root.config.strict}}?{{/unless}}: {{ convert name 'typeNames'}}Resolvers{{#unless @root.config.noNamespaces}}.Resolvers{{/unless}}; - {{/each}} - {{#each interfaces}} - {{ convert name 'typeNames'}}{{#unless @root.config.strict}}?{{/unless}}: {{ convert name 'typeNames'}}Resolvers{{#unless @root.config.noNamespaces}}.Resolvers{{/unless}}; - {{/each}} - {{#each unions}} - {{ convert name 'typeNames'}}{{#unless @root.config.strict}}?{{/unless}}: {{ convert name 'typeNames'}}Resolvers{{#unless @root.config.noNamespaces}}.Resolvers{{/unless}}; - {{/each}} - {{#each scalars}} - {{ convert name 'typeNames'}}{{#unless @root.config.strict}}?{{/unless}}: GraphQLScalarType; - {{/each}} -} & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; - -export type IDirectiveResolvers = { - {{#each definedDirectives}} - {{ name }}{{#unless @root.config.strict}}?{{/unless}}: {{ convert name 'typeNames'}}DirectiveResolver; - {{/each}} -} & { [directiveName: string] : DirectiveResolverFn }; diff --git a/packages/plugins/typescript-resolvers/src/scalar.handlebars b/packages/plugins/typescript-resolvers/src/scalar.handlebars deleted file mode 100644 index af342413191..00000000000 --- a/packages/plugins/typescript-resolvers/src/scalar.handlebars +++ /dev/null @@ -1,3 +0,0 @@ -export interface {{name}}ScalarConfig extends GraphQLScalarTypeConfig<{{ convert name 'typeNames' }}, any> { - name: '{{name}}' -} diff --git a/packages/plugins/typescript-resolvers/src/visitor.ts b/packages/plugins/typescript-resolvers/src/visitor.ts new file mode 100644 index 00000000000..0251220e152 --- /dev/null +++ b/packages/plugins/typescript-resolvers/src/visitor.ts @@ -0,0 +1,81 @@ +import { ListTypeNode, NamedTypeNode, NonNullTypeNode } from 'graphql/language/ast'; +import { TypeScriptResolversPluginConfig } from './index'; +import { GraphQLSchema } from 'graphql'; +import * as autoBind from 'auto-bind'; +import { ParsedResolversConfig, BaseResolversVisitor } from 'graphql-codegen-visitor-plugin-common'; +import { TypeScriptOperationVariablesToObject } from 'graphql-codegen-typescript'; + +export interface ParsedTypeScriptResolversConfig extends ParsedResolversConfig { + avoidOptionals: boolean; + immutableTypes: boolean; +} + +export class TypeScriptResolversVisitor extends BaseResolversVisitor< + TypeScriptResolversPluginConfig, + ParsedTypeScriptResolversConfig +> { + constructor(pluginConfig: TypeScriptResolversPluginConfig, schema: GraphQLSchema) { + super( + pluginConfig, + { + avoidOptionals: pluginConfig.avoidOptionals || false, + immutableTypes: pluginConfig.immutableTypes || false + } as any, + schema + ); + autoBind(this); + this.setVariablesTransformer( + new TypeScriptOperationVariablesToObject( + this.config.scalars, + this.convertName, + this.config.avoidOptionals, + this.config.immutableTypes + ) + ); + } + + protected formatRootResolver(schemaTypeName: string, resolverType: string): string { + return `${schemaTypeName}?: ${resolverType},`; + } + + getRootResolver(): string { + return super + .getRootResolver() + .replace( + '};', + '} & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } };' + ); + } + + getAllDirectiveResolvers(): string { + return super + .getAllDirectiveResolvers() + .replace('};', '} & { [directiveName: string]: DirectiveResolverFn };'); + } + + private clearOptional(str: string): string { + if (str.startsWith('Maybe')) { + return str.replace(/Maybe<(.*?)>/, '$1'); + } + + return str; + } + + ListType(node: ListTypeNode): string { + return `Maybe<${super.ListType(node)}>`; + } + + protected wrapWithListType(str: string): string { + return `${this.config.immutableTypes ? 'ReadonlyArray' : 'Array'}<${str}>`; + } + + NamedType(node: NamedTypeNode): string { + return `Maybe<${super.NamedType(node)}>`; + } + + NonNullType(node: NonNullTypeNode): string { + const baseValue = super.NonNullType(node); + + return this.clearOptional(baseValue); + } +} diff --git a/packages/plugins/typescript-resolvers/tests/ts-resolvers.spec.ts b/packages/plugins/typescript-resolvers/tests/ts-resolvers.spec.ts new file mode 100644 index 00000000000..fb466132161 --- /dev/null +++ b/packages/plugins/typescript-resolvers/tests/ts-resolvers.spec.ts @@ -0,0 +1,276 @@ +import 'graphql-codegen-testing'; +import { buildSchema } from 'graphql'; +import { plugin } from '../src'; +import { plugin as tsPlugin } from '../../typescript/src/index'; +import { validateTs } from '../../typescript/tests/validate'; + +describe('TypeScript Resolvers Plugin', () => { + const schema = buildSchema(/* GraphQL */ ` + type MyType { + foo: String! + otherType: MyOtherType + withArgs(arg: String, arg2: String!): String + } + + type MyOtherType { + bar: String! + } + + type Query { + something: MyType! + } + + type Subscription { + somethingChanged: MyOtherType + } + + interface Node { + id: ID! + } + + type SomeNode implements Node { + id: ID! + } + + union MyUnion = MyType | MyOtherType + + scalar MyScalar + + directive @myDirective(arg: Int!, arg2: String!, arg3: Boolean!) on FIELD + `); + + const validate = async (content: string, config: any = {}, pluginSchema = schema) => { + const mergedContent = (await tsPlugin(pluginSchema, [], config, { outputFile: '' })) + '\n' + content; + + validateTs(mergedContent); + }; + + it('Should generate basic type resolvers', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyDirectiveDirectiveResolver, + arg2?: Maybe, arg3?: Maybe }> = DirectiveResolverFn; + + export interface MyOtherTypeResolvers { + bar?: Resolver, + } + + export interface MyScalarScalarConfig extends GraphQLScalarTypeConfig { + name: 'MyScalar' + } + + export interface MyTypeResolvers { + foo?: Resolver, + otherType?: Resolver, ParentType, Context>, + withArgs?: Resolver, ParentType, Context, MyTypeWithArgsArgs>, + } + + export interface MyUnionResolvers { + __resolveType: TypeResolveFn<'MyType' | 'MyOtherType'> + } + + export interface NodeResolvers { + __resolveType: TypeResolveFn<'SomeNode'> + } + + export interface QueryResolvers { + something?: Resolver, + } + + export interface SomeNodeResolvers { + id?: Resolver, + } + + export interface SubscriptionResolvers { + somethingChanged?: SubscriptionResolver, ParentType, Context>, + } + `); + + await validate(result); + }); + + it('Should generate the correct imports when schema has scalars', async () => { + const testSchema = buildSchema(`scalar MyScalar`); + const result = await plugin(testSchema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo( + `import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql';` + ); + await validate(result, {}, schema); + }); + + it('Should generate the correct imports when schema has no scalars', async () => { + const testSchema = buildSchema(`type MyType { f: String }`); + const result = await plugin(testSchema, [], {}, { outputFile: '' }); + + expect(result).not.toBeSimilarStringTo(`import { GraphQLResolveInfo, GraphQLScalarTypeConfig } from 'graphql';`); + await validate(result, {}, testSchema); + }); + + it('Should generate basic type resolvers with mapping', async () => { + const result = await plugin( + schema, + [], + { + mappers: { + MyOtherType: 'MyCustomOtherType' + } + }, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + export type MyDirectiveDirectiveResolver, + arg2?: Maybe, arg3?: Maybe }> = DirectiveResolverFn; + + export interface MyOtherTypeResolvers { + bar?: Resolver, + } + + export interface MyScalarScalarConfig extends GraphQLScalarTypeConfig { + name: 'MyScalar' + } + + export interface MyTypeResolvers { + foo?: Resolver, + otherType?: Resolver, ParentType, Context>, + withArgs?: Resolver, ParentType, Context, MyTypeWithArgsArgs>, + } + + export interface MyUnionResolvers { + __resolveType: TypeResolveFn<'MyType' | 'MyOtherType'> + } + + export interface NodeResolvers { + __resolveType: TypeResolveFn<'SomeNode'> + } + + export interface QueryResolvers { + something?: Resolver, + } + + export interface SomeNodeResolvers { + id?: Resolver, + } + + export interface SubscriptionResolvers { + somethingChanged?: SubscriptionResolver, ParentType, Context>, + } + `); + await validate(`type MyCustomOtherType = {}\n${result}`); + }); + + it('Should generate basic type resolvers with external mappers', async () => { + const result = await plugin( + schema, + [], + { + mappers: { + MyOtherType: './my-file#MyCustomOtherType' + } + }, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(`import { MyCustomOtherType } from './my-file';`); + expect(result).toBeSimilarStringTo(` + export type MyDirectiveDirectiveResolver, + arg2?: Maybe, arg3?: Maybe }> = DirectiveResolverFn; + + export interface MyOtherTypeResolvers { + bar?: Resolver, + } + + export interface MyScalarScalarConfig extends GraphQLScalarTypeConfig { + name: 'MyScalar' + } + + export interface MyTypeResolvers { + foo?: Resolver, + otherType?: Resolver, ParentType, Context>, + withArgs?: Resolver, ParentType, Context, MyTypeWithArgsArgs>, + } + + export interface MyUnionResolvers { + __resolveType: TypeResolveFn<'MyType' | 'MyOtherType'> + } + + export interface NodeResolvers { + __resolveType: TypeResolveFn<'SomeNode'> + } + + export interface QueryResolvers { + something?: Resolver, + } + + export interface SomeNodeResolvers { + id?: Resolver, + } + + export interface SubscriptionResolvers { + somethingChanged?: SubscriptionResolver, ParentType, Context>, + } + `); + await validate(result); + }); + + it('Should generate the correct resolver args type names when typesPrefix is specified', async () => { + const testSchema = buildSchema(`type MyType { f(a: String): String }`); + const config = { typesPrefix: 'T' }; + const result = await plugin(testSchema, [], config, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(`f?: Resolver, ParentType, Context, TMyTypeFArgs>,`); + await validate(result, config, testSchema); + }); + it('should generate Resolvers interface', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + directive @modify(limit: Int) on FIELD_DEFINITION + scalar Date + type Query { + post: Post + entity: PostOrUser + } + interface Node { + id: String + } + union PostOrUser = Post | User + type Post implements Node { + author: User + } + type User implements Node { + id: String + name: String + } + schema { + query: Query + } + `); + + const content = await plugin( + testSchema, + [], + { scalars: { Date: 'Date' } }, + { + outputFile: 'graphql.ts' + } + ); + + expect(content).toBeSimilarStringTo(` + export type IResolvers = { + Date?: GraphQLScalarType, + Node?: NodeResolvers, + Post?: PostResolvers, + PostOrUser?: PostOrUserResolvers, + Query?: QueryResolvers, + User?: UserResolvers, + } & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; + `); + + expect(content).toBeSimilarStringTo(` + export type IDirectiveResolvers = { + modify?: ModifyDirectiveResolver, + } & { [directiveName: string]: DirectiveResolverFn }; + `); + }); +}); diff --git a/packages/plugins/typescript-resolvers/tests/typescript-resolvers.spec.ts b/packages/plugins/typescript-resolvers/tests/typescript-resolvers.spec.ts deleted file mode 100644 index f3916fada6f..00000000000 --- a/packages/plugins/typescript-resolvers/tests/typescript-resolvers.spec.ts +++ /dev/null @@ -1,1433 +0,0 @@ -import 'graphql-codegen-core/dist/testing'; -import { plugin } from '../dist'; -import { makeExecutableSchema } from 'graphql-tools'; -import { buildSchema } from 'graphql'; - -function stripBlockComments(input: string): string { - return input.replace(/^\/\/ [=]+\n\/\/ .*\n\/\/ [=]+/gim, ''); -} - -describe('Resolvers', () => { - const schema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest: String - } - - schema { - query: Query - } - ` - }); - - it('should contain the Resolver type', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(`import { GraphQLResolveInfo } from 'graphql';`); - expect(content).toBeSimilarStringTo(` - export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ) => Promise | Result; - - export interface ISubscriptionResolverObject { - subscribe( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): AsyncIterator | Promise>; - resolve?( - parent: P, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ): R | Result | Promise; - } - - export type SubscriptionResolver = - | ((...args: any[]) => ISubscriptionResolverObject) - | ISubscriptionResolverObject; - `); - }); - - it('should make fields optional', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - fieldTest?: FieldTestResolver, TypeParent, TContext>; - } - `); - }); - - it('should provide a generic type of result', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - fieldTest?: FieldTestResolver, TypeParent, TContext>; - } - export type FieldTestResolver, Parent = {}, TContext = {}> = Resolver; - } - `); - }); - - it('should provide a generic type of arguments and support optionals', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest(last: Int!, sort: String): String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - fieldTest?: FieldTestResolver, TypeParent, TContext>; - } - - export type FieldTestResolver, Parent = {}, TContext = {}> = Resolver; - - export interface FieldTestArgs { - last: number; - sort?: Maybe; - } - } - `); - }); - - it('should handle subscription', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Subscription { - fieldTest: String - } - - schema { - subscription: Subscription - } - ` - }); - - const content = stripBlockComments( - await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ) - ); - - expect(content).toBeSimilarStringTo(` - export namespace SubscriptionResolvers { - export interface Resolvers { - fieldTest?: FieldTestResolver, TypeParent, TContext>; - } - - export type FieldTestResolver, Parent = {}, TContext = {}> = SubscriptionResolver; - } - `); - }); - - it('should handle noNamespaces', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { noNamespaces: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface QueryResolvers { - fieldTest?: QueryFieldTestResolver, TypeParent, TContext>; - } - - export type QueryFieldTestResolver, Parent = {}, TContext = {}> = Resolver; - `); - }); - - it('should override custom context', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { contextType: 'MyContext' }, - { - outputFile: 'graphql.ts' - } - ); - - // make sure nothing was imported - expect(content).toBeSimilarStringTo(` - import { GraphQLResolveInfo } from 'graphql'; - - export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ) => Promise | Result; - `); - - expect(content).toBeSimilarStringTo(` - export interface Resolvers { - fieldTest?: FieldTestResolver, TypeParent, TContext>; - } - - export type FieldTestResolver, Parent = {}, TContext = MyContext> = Resolver; - `); - }); - - it('should override custom context with type from a module', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { contextType: './path/to/types#MyContext' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { MyContext } from './path/to/types'; - `); - - expect(content).toBeSimilarStringTo(` - export interface Resolvers { - fieldTest?: FieldTestResolver, TypeParent, TContext>; - } - - export type FieldTestResolver, Parent = {}, TContext = MyContext> = Resolver; - `); - }); - - it('should handle snake case and convert it to pascal case', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type snake_case_arg { - test: String - } - - type snake_case_result { - test: String - } - - type Query { - snake_case_root_query( - arg: snake_case_arg - ): snake_case_result - } - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type SnakeCaseRootQueryResolver, Parent = {}, TContext = {}> = Resolver; - `); - expect(content).toBeSimilarStringTo(` - export interface SnakeCaseRootQueryArgs { - arg?: Maybe; - } - `); - }); - - it('Should handle primitives option', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type TestType { - id: ID! - } - ` - }); - - const content = await plugin( - testSchema, - [], - { scalars: { ID: 'number' } }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(`id?: IdResolver;`); - }); - - it('should define default parent type', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - author: User - } - - type User { - id: String - name: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - post?: PostResolver, TypeParent, TContext>; - } - - export type PostResolver, Parent = {}, TContext = {}> = Resolver; - } - `); - - expect(content).toBeSimilarStringTo(` - export namespace PostResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - author?: AuthorResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = Post, TContext = {}> = Resolver; - export type AuthorResolver, Parent = Post, TContext = {}> = Resolver; - } - `); - - expect(content).toBeSimilarStringTo(` - export namespace UserResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - name?: NameResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = User, TContext = {}> = Resolver; - export type NameResolver, Parent = User, TContext = {}> = Resolver; - } - `); - }); - - it('should define default parent type with noNamespaces', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - author: User - } - - type User { - id: String - name: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { noNamespaces: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface QueryResolvers { - post?: QueryPostResolver, TypeParent, TContext>; - } - - export type QueryPostResolver, Parent = {}, TContext = {}> = Resolver; - `); - - expect(content).toBeSimilarStringTo(` - export interface PostResolvers { - id?: PostIdResolver, TypeParent, TContext>; - author?: PostAuthorResolver, TypeParent, TContext>; - } - - export type PostIdResolver, Parent = Post, TContext = {}> = Resolver; - export type PostAuthorResolver, Parent = Post, TContext = {}> = Resolver; - `); - - expect(content).toBeSimilarStringTo(` - export interface UserResolvers { - id?: UserIdResolver, TypeParent, TContext>; - name?: UserNameResolver, TypeParent, TContext>; - } - - export type UserIdResolver, Parent = User, TContext = {}> = Resolver; - export type UserNameResolver, Parent = User, TContext = {}> = Resolver; - `); - }); - - it('should accept a map of parent types', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - author: User - } - - type User { - id: String - name: String - post: Post - } - - schema { - query: Query - } - ` - }); - - // type UserParent = string; - // interface PostParent { - // id: string; - // author: string; - // } - const content = await plugin( - testSchema, - [], - { - mappers: { - // it means that User type expects UserParent to be a parent - User: './interfaces#UserParent', - // it means that Post type expects UserParent to be a parent - Post: './interfaces#PostParent' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - // import parents - // merge duplicates into single module - expect(content).toBeSimilarStringTo(` - import { UserParent, PostParent } from './interfaces'; - `); - - // should check field's result and match it with provided parents - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - post?: PostResolver, TypeParent, TContext>; - } - - export type PostResolver, Parent = {}, TContext = {}> = Resolver; - } - `); - - // should check if type has a defined parent and use it as TypeParent - expect(content).toBeSimilarStringTo(` - export namespace PostResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - author?: AuthorResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = PostParent, TContext = {}> = Resolver; - export type AuthorResolver, Parent = PostParent, TContext = {}> = Resolver; - } - `); - - // should check if type has a defined parent and use it as TypeParent - // should match field's result with provided parent type - expect(content).toBeSimilarStringTo(` - export namespace UserResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - name?: NameResolver, TypeParent, TContext>; - post?: PostResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = UserParent, TContext = {}> = Resolver; - export type NameResolver, Parent = UserParent, TContext = {}> = Resolver; - export type PostResolver, Parent = UserParent, TContext = {}> = Resolver; - } - `); - }); - - it('should accept mappers that reuse generated types', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - mappers: { - // it means that Post type expects Post to be a parent - Post: 'Post' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - // should check field's result and match it with provided parents - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - post?: PostResolver, TypeParent, TContext>; - } - - export type PostResolver, Parent = {}, TContext = {}> = Resolver; - } - `); - - // should check if type has a defined parent and use it as TypeParent - expect(content).toBeSimilarStringTo(` - export namespace PostResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = Post, TContext = {}> = Resolver; - } - `); - }); - - it('should use default mapper for non mapped types (external)', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - defaultMapper: './interfaces#AnyParent' - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { AnyParent } from './interfaces'; - `); - - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - post?: PostResolver, TypeParent, TContext>; - } - - export type PostResolver, Parent = {}, TContext = {}> = Resolver; - } - `); - - // should get AnyParent as a parent and result shouldn't use AnyParent - expect(content).toBeSimilarStringTo(` - export namespace PostResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = AnyParent, TContext = {}> = Resolver; - } - `); - }); - - it('should use variable from mapper only', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - mappers: { - Post: './interfaces#Post.Model' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - import { Post } from './interfaces'; - `); - }); - - it('should use default mapper for non mapped types (primitive)', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - defaultMapper: 'any' - }, - { - outputFile: 'graphql.ts' - } - ); - - // make sure nothing was imported - expect(content).toBeSimilarStringTo(` - import { GraphQLResolveInfo } from 'graphql'; - - export type Resolver = ( - parent: Parent, - args: Args, - context: TContext, - info: GraphQLResolveInfo - ) => Promise | Result; - `); - - // should check field's result and match it with provided parents - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - post?: PostResolver, TypeParent, TContext>; - } - - export type PostResolver, Parent = {}, TContext = {}> = Resolver; - } - `); - - // should check if type has a defined parent and use it as TypeParent - expect(content).toBeSimilarStringTo(` - export namespace PostResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - } - - export type IdResolver, Parent = any, TContext = {}> = Resolver; - } - `); - }); - - it('make sure mappers work with mutations', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type RootMutation { - upvotePost(id: String!): UpvotePostPayload - } - - type UpvotePostPayload { - post: Post - } - - type Post { - id: String - } - - schema { - query: Query - mutation: RootMutation - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - mappers: { - // whenever there's something receives or resolves a Post, use PostEntity - Post: 'PostEntity' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - // RootMutation should expect {} as a parent - // RootMutation.upvotePost should expect {} as a parent - // RootMutation.upvotePost should return the UpvotePostPayload - expect(content).toBeSimilarStringTo(` - export namespace RootMutationResolvers { - export interface Resolvers { - upvotePost?: UpvotePostResolver, TypeParent, TContext>; - } - - export type UpvotePostResolver, Parent = {}, TContext = {}> = Resolver; - - export interface UpvotePostArgs { - id: string; - } - } - `); - - // UpvotePostPayload should expect UpvotePostPayload as parent - // UpvotePostPayload.post should expect UpvotePostPayload as parent - // UpvotePostPayload.post should return PostEntity - expect(content).toBeSimilarStringTo(` - export namespace UpvotePostPayloadResolvers { - export interface Resolvers { - post?: PostResolver, TypeParent, TContext>; - } - - export type PostResolver, Parent = UpvotePostPayload, TContext = {}> = Resolver; - } - `); - }); - - it('should provide a generic type of arguments in noNamespaces', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest(last: Int!, sort: String): String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - noNamespaces: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface QueryResolvers { - fieldTest?: QueryFieldTestResolver, TypeParent, TContext>; - } - - export type QueryFieldTestResolver, Parent = {}, TContext = {}> = Resolver; - - export interface QueryFieldTestArgs { - last: number; - sort?: Maybe; - } - `); - }); - - it('should define TypeResolveFn', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - fieldTest(last: Int!, sort: String): String - } - - schema { - query: Query - } - ` - }); - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type TypeResolveFn = ( - parent: Parent, - context: TContext, - info: GraphQLResolveInfo - ) => Maybe; - `); - }); - - it('should create a type with __resolveType for a union', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Post { - title: String - text: String - } - - type Comment { - text: String - } - - union Entry = Post | Comment - - type Query { - feed: Entry - - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace EntryResolvers { - export interface Resolvers { - __resolveType: ResolveType; - } - - export type ResolveType = TypeResolveFn; - } - `); - }); - - it('should create a type with __resolveType for a union (with noNamespaces)', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Post { - title: String - text: String - } - - type Comment { - text: String - } - - union Entry = Post | Comment - - type Query { - feed: Entry - - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - noNamespaces: true - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface EntryResolvers { - __resolveType: EntryResolveType; - } - - export type EntryResolveType = TypeResolveFn; - `); - }); - - it('should create NextResolverFn and DirectiveResolverFn', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - field: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type NextResolverFn = () => Promise; - - export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, - ) => TResult | Promise; - `); - }); - - it('should create a type that maches DirectiveResolverFn from graphql-tools', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Post { - title: String - text: String - } - - type Query { - post: Post - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type NextResolverFn = () => Promise; - - export type DirectiveResolverFn = ( - next: NextResolverFn, - source: any, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, - ) => TResult | Promise; - `); - }); - - it('should create a resolver for a directive and its arguments', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - directive @modify(limit: Int) on FIELD_DEFINITION - - type Post { - title: String - text: String - } - - type Query { - post: Post - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type ModifyDirectiveResolver = DirectiveResolverFn; - `); - - expect(content).toBeSimilarStringTo(` - export interface ModifyDirectiveArgs { - limit?: Maybe; - } - `); - }); - - it('should create a resolver for a scalar', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - scalar JSON - scalar Date - - type Query { - post: JSON - date: Date - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { - scalars: { - JSON: 'Object' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - // should import GraphQLScalarType and GraphQLScalarTypeConfig - expect(content).toBeSimilarStringTo(` - import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; - `); - - // XXX: `any` becasue right now we can't tell in which form we ship it to the client - expect(content).toBeSimilarStringTo(` - export interface JSONScalarConfig extends GraphQLScalarTypeConfig { - name: 'JSON' - } - `); - expect(content).toBeSimilarStringTo(` - export interface DateScalarConfig extends GraphQLScalarTypeConfig { - name: 'Date' - } - `); - }); - - it('should import GraphQL types for scalars only if schema has scalars', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - field: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).not.toContain('GraphQLScalarType'); - expect(content).not.toContain('GraphQLScalarTypeConfig'); - }); - - it('should generate Resolvers interface', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - - directive @modify(limit: Int) on FIELD_DEFINITION - - scalar Date - - type Query { - post: Post - entity: PostOrUser - } - - interface Node { - id: String - } - - union PostOrUser = Post | User - - type Post implements Node { - author: User - } - - type User implements Node { - id: String - name: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { noNamespaces: true, scalars: { Date: 'Date' } }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export type IResolvers = { - Query?: QueryResolvers; - Post?: PostResolvers; - User?: UserResolvers; - Node?: NodeResolvers; - PostOrUser?: PostOrUserResolvers; - Date?: GraphQLScalarType; - } & { [typeName: string] : { [ fieldName: string ]: ( Resolver | SubscriptionResolver ) } }; - `); - - expect(content).toBeSimilarStringTo(` - export type IDirectiveResolvers = { - modify?: ModifyDirectiveResolver; - skip?: SkipDirectiveResolver; - include?: IncludeDirectiveResolver; - deprecated?: DeprecatedDirectiveResolver; - } & { [directiveName: string] : DirectiveResolverFn }; - `); - }); - - it('should insert Field Resolvers prefix if configured', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - user: User - post: UserPost - } - - type User { - postId: String - post: Post - } - - type UserPost { - id: String - } - - type Post { - id: String - } - - schema { - query: Query - } - ` - }); - - const content = await plugin( - testSchema, - [], - { noNamespaces: true, fieldResolverNamePrefix: '_' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface UserResolvers { - postId?: User_PostIdResolver, TypeParent, TContext>; - post?: User_PostResolver, TypeParent, TContext>; - } - - export type User_PostIdResolver, Parent = User, TContext = {}> = Resolver; - export type User_PostResolver, Parent = User, TContext = {}> = Resolver; - `); - - expect(content).toBeSimilarStringTo(` - export interface UserPostResolvers { - id?: UserPost_IdResolver, TypeParent, TContext>; - } - - export type UserPost_IdResolver, Parent = UserPost, TContext = {}> = Resolver; - `); - }); - - it('should output strict resolvers', async () => { - const content = await plugin( - schema, - [], - { strict: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export namespace QueryResolvers { - export interface Resolvers { - fieldTest: FieldTestResolver, TypeParent, TContext>; - } - `); - }); - - describe('enums should stay consistent with common plugin', () => { - const testSchema = buildSchema(` - enum FOODEnum { - PIZZA, - BURGER, - } - - type Query { - fieldTest: FOODEnum - } - - schema { - query: Query - } - `); - - it('should match default naming convention', async () => { - const content = await plugin( - testSchema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - fieldTest?: FieldTestResolver, TypeParent, TContext>; - `); - - expect(content).toBeSimilarStringTo(` - export type FieldTestResolver, Parent = {}, TContext = {}> = Resolver; - `); - }); - - it('should match custom naming convention', async () => { - const content = await plugin( - testSchema, - [], - { - namingConvention: { - typeNames: 'change-case#upperCase' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - fieldTest?: FieldTestResolver, TypeParent, TContext>; - `); - - expect(content).toBeSimilarStringTo(` - export type FieldTestResolver, Parent = {}, TContext = {}> = Resolver; - `); - }); - }); -}); - -describe('And Interfaces should be imported when used in mapping', () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Query { - post: Post - } - - type Post { - id: String - author: User - } - - interface User { - id: String - name: String - post: Post - } - - schema { - query: Query - } - ` - }); - - it('should import interface mapping', async () => { - const content = await plugin( - testSchema, - [], - { - mappers: { - // it means that User type expects UserParent to be a parent - User: './interfaces#UserParent', - // it means that Post type expects UserParent to be a parent - Post: './interfaces#PostParent' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - // import parents - // merge duplicates into single module - expect(content).toBeSimilarStringTo(` - import { UserParent, PostParent } from './interfaces'; - `); - }); -}); diff --git a/packages/plugins/typescript-resolvers/tsconfig.json b/packages/plugins/typescript-resolvers/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/typescript-resolvers/tsconfig.json +++ b/packages/plugins/typescript-resolvers/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/typescript-server/package.json b/packages/plugins/typescript-server/package.json deleted file mode 100644 index 135dd92df8e..00000000000 --- a/packages/plugins/typescript-server/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "graphql-codegen-typescript-server", - "version": "0.18.0", - "description": "graphql-codegen-cli template for TypeScript typings for both client side and server side", - "repository": "git@github.com:dotansimha/graphql-code-generator.git", - "license": "MIT", - "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" - }, - "dependencies": { - "graphql-codegen-typescript-common": "0.18.0" - }, - "devDependencies": { - "codegen-templates-scripts": "0.18.0", - "graphql": "14.1.1", - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0" - }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] - } -} diff --git a/packages/plugins/typescript-server/src/index.ts b/packages/plugins/typescript-server/src/index.ts deleted file mode 100644 index 2908751dabd..00000000000 --- a/packages/plugins/typescript-server/src/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { TypeScriptCommonConfig, initCommonTemplate } from 'graphql-codegen-typescript-common'; -import { PluginFunction, DocumentFile } from 'graphql-codegen-core'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; - -export interface TypeScriptServerConfig extends TypeScriptCommonConfig { - schemaNamespace?: string; -} - -export const plugin: PluginFunction = async ( - schema: GraphQLSchema, - documents: DocumentFile[], - config: TypeScriptServerConfig -): Promise => { - const { templateContext } = initCommonTemplate(Handlebars, schema, [], config); - - return Handlebars.compile(rootTemplate)(templateContext); -}; diff --git a/packages/plugins/typescript-server/src/polyfills.d.ts b/packages/plugins/typescript-server/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-server/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-server/src/root.handlebars b/packages/plugins/typescript-server/src/root.handlebars deleted file mode 100644 index 22b59d904f8..00000000000 --- a/packages/plugins/typescript-server/src/root.handlebars +++ /dev/null @@ -1,34 +0,0 @@ -{{#if @root.config.schemaNamespace ~}}export namespace {{@root.config.schemaNamespace}} { {{/if}} -{{{ blockCommentIf 'Scalars' scalars }}} - -{{{ blockCommentIf 'Interfaces' interfaces }}} -{{#each interfaces}} - {{~> type }} - -{{/each}} - -{{{ blockCommentIf 'Types' types }}} -{{#each types}} - {{~> type }} - -{{/each}} -{{{ blockCommentIf 'Arguments' types }}} -{{~#each types}} - {{~#each fields}} - {{~# if hasArguments }} -export interface {{@root.config.interfacePrefix}}{{ convert name 'typeNames' }}{{ convert ../name 'typeNames' }}Args { -{{#each arguments}} - {{ toComment description }} - {{ name }}{{ getOptionals this }}: {{ convertedType this }}; -{{/each}} -} - {{/if}} - {{/each}} -{{/each}} -{{{ blockCommentIf 'Unions' unions }}} -{{#each unions}} -{{ toComment description }} -export type {{@root.config.interfacePrefix}}{{ convert name 'typeNames' }} = {{#each possibleTypes}}{{@root.config.interfacePrefix}}{{ convert this 'typeNames' }}{{#unless @last}} | {{/unless}}{{/each}}; - -{{/each}} -{{#if @root.config.schemaNamespace ~}} } {{~/if}} diff --git a/packages/plugins/typescript-server/tests/typescript-server.spec.ts b/packages/plugins/typescript-server/tests/typescript-server.spec.ts deleted file mode 100644 index 28cc7c48772..00000000000 --- a/packages/plugins/typescript-server/tests/typescript-server.spec.ts +++ /dev/null @@ -1,537 +0,0 @@ -import 'graphql-codegen-core/dist/testing'; -import { GraphQLSchema } from 'graphql'; -import { makeExecutableSchema } from 'graphql-tools'; -import { plugin } from '../dist'; - -describe('TypeScript Server', () => { - function buildSchema(ast: string): GraphQLSchema { - return makeExecutableSchema({ - typeDefs: ast, - allowUndefinedInResolve: true, - resolverValidationOptions: { - requireResolversForResolveType: false - } - }); - } - - const schema = buildSchema(` - type Foo { - bar: Bar - } - - type Bar { - qux: String - } - - type Query { - fieldTest: String - } - - type Immut { - fieldTest: String - fieldTestMandatory: String! - arrayTest1: [String] - arrayTest2: [String]! - arrayTest3: [String!]! - arrayTest4: [String!] - } - `); - - describe('Config', () => { - it('Should wrap with namepsace when schemaNamespace is specified', async () => { - const content = await plugin( - schema, - [], - { schemaNamespace: 'Models' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toContain(`export namespace Models {`); - }); - }); - - describe('Unions', () => { - const schema = buildSchema(` - type Query { - fieldTest: C! - } - - type A { - f1: String - } - - type B { - f2: String - } - - # Union description - union C = A | B - `); - - it('Should generate unions correctly', async () => { - const content = await plugin( - schema, - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest: C; - } - `); - expect(content).toBeSimilarStringTo(` - export interface A { - f1?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface B { - f2?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - /** Union description */ - export type C = A | B; - `); - }); - - it('Should generate unions correctly with interfacePrefix', async () => { - const content = await plugin( - schema, - [], - { interfacePrefix: 'Gql' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface GqlQuery { - fieldTest: GqlC; - } - `); - expect(content).toBeSimilarStringTo(` - export interface GqlA { - f1?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface GqlB { - f2?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - /** Union description */ - export type GqlC = GqlA | GqlB; - `); - }); - }); - - describe('Arguments', () => { - it('Should generate type arguments types correctly when using simple Scalar', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest(myArgument: T!): Return - } - - type Return { - ok: Boolean! - msg: String! - } - - input T { - f1: String - f2: Int! - f3: [String] - f4: [String]! - f5: [String!]! - f6: [String!] - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface Return { - ok: boolean; - msg: string; - } - `); - expect(content).toBeSimilarStringTo(` - export interface FieldTestQueryArgs { - myArgument: T; - } - `); - }); - - it('Should generate type arguments types correctly when using simple Scalar', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest(arg1: String): String! - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest: string; - } - `); - expect(content).toBeSimilarStringTo(` - export interface FieldTestQueryArgs { - arg1?: Maybe; - } - `); - }); - }); - - describe('Interface', () => { - it('Should generate correctly when using simple type that extends interface', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: A! - } - - interface Base { - f1: String - } - - type A implements Base { - f1: String - f2: String - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Base { - f1?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface A extends Base { - f1?: Maybe; - f2?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest: A; - } - `); - }); - }); - - describe('Types', () => { - it('Should generate names correctly (default pascalCase)', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: [CBText] - } - union CBText = ABText | BBText - scalar ABText - scalar BBText - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe<(Maybe)[]>; - } - `); - expect(content).toBeSimilarStringTo(` - export type CbText = AbText | BbText; - `); - }); - - it('Should generate names correctly (custom naming)', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: [CBText] - } - union CBText = ABText | BBText - scalar ABText - scalar BBText - `), - [], - { namingConvention: 'change-case#lowerCase' }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface query { - fieldTest?: Maybe<(Maybe)[]>; - } - `); - expect(content).toBeSimilarStringTo(` - export type cbtext = abtext | bbtext; - `); - }); - - it('Should generate correctly when using a simple Query with some fields and types', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: String - } - - type T { - f1: String - f2: Int - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface T { - f1?: Maybe; - f2?: Maybe; - } - `); - }); - - it('Should generate correctly when using a simple Query with arrays and required', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: T - } - - type T { - f1: [String] - f2: Int! - f3: A - f4: [[[String]]] - } - - type A { - f4: T - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface A { - f4?: Maybe; - } - `); - expect(content).toBeSimilarStringTo(` - export interface T { - f1?: Maybe<(Maybe)[]>; - f2: number; - f3?: Maybe; - f4?: Maybe<(Maybe)[][][]>; - } - `); - }); - - it('Should handle immutable type correctly with immutableTypes', async () => { - const content = await plugin( - schema, - [], - { immutableTypes: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Bar { - readonly qux?: Maybe; - } - `); - - expect(content).toBeSimilarStringTo(` - export interface Immut { - readonly fieldTest?: Maybe; - readonly fieldTestMandatory: string; - readonly arrayTest1?: Maybe>>; - readonly arrayTest2: ReadonlyArray>; - readonly arrayTest3: ReadonlyArray; - readonly arrayTest4?: Maybe>; - } - `); - }); - - it('Should generate the correct output when using avoidOptionals=true', async () => { - const content = await plugin( - schema, - [], - { avoidOptionals: true }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Bar { - qux: Maybe; - } - `); - }); - - it('Should output docstring correctly', async () => { - const content = await plugin( - buildSchema(` - # type-description - type Query { - # field-description - fieldTest: String - } - - schema { - query: Query - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(`/** type-description */`); - expect(content).toBeSimilarStringTo(` - export interface Query { - /** field-description */ - fieldTest?: Maybe; - }`); - }); - }); - - describe('Scalars', () => { - it('Should generate correctly scalars without definition of it', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: [Date] - } - - scalar Date - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe<(Maybe)[]>; - } - `); - }); - - it('Should generate correctly scalars with custom scalar type', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest: [Date] - } - - scalar Date - `), - [], - { - scalars: { - Date: 'MyCustomDate' - } - }, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe<(Maybe)[]>; - } - `); - }); - }); - - it('should generate correctly when using a Query with some fields and variables', async () => { - const content = await plugin( - buildSchema(` - type Query { - fieldTest(limit: Int = 42): [String] - } - `), - [], - {}, - { - outputFile: 'graphql.ts' - } - ); - - expect(content).toBeSimilarStringTo(` - export interface Query { - fieldTest?: Maybe<(Maybe)[]>; - } - `); - - expect(content).toBeSimilarStringTo(` - export interface FieldTestQueryArgs { - limit?: number; - } - `); - }); -}); diff --git a/packages/plugins/typescript-stencil-apollo/package.json b/packages/plugins/typescript-stencil-apollo/package.json index da5e24f383d..7b8b12e32d8 100644 --- a/packages/plugins/typescript-stencil-apollo/package.json +++ b/packages/plugins/typescript-stencil-apollo/package.json @@ -5,49 +5,33 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "test": "codegen-templates-scripts test", - "pretest": "yarn build" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" }, "peerDependencies": { "graphql-tag": "^2.0.0", "stencil-apollo": "^0.0.2" }, "dependencies": { - "dependency-graph": "^0.8.0", - "graphql-codegen-core": "0.18.0", - "graphql-codegen-plugin-helpers": "0.18.0", - "graphql-codegen-typescript-common": "0.18.0" + "tslib": "1.9.3", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" }, "devDependencies": { - "@types/node": "10.14.1", - "codegen-templates-scripts": "0.18.0", + "graphql-codegen-testing": "0.18.0", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333", + "flow-bin": "0.94.0", + "flow-parser": "0.94.0", "graphql": "14.1.1", - "graphql-codegen-plugin-handlebars-helpers": "0.18.0" + "@types/node": "10.12.30" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/plugins/typescript-stencil-apollo/src/helpers.ts b/packages/plugins/typescript-stencil-apollo/src/helpers.ts deleted file mode 100644 index 3ee1a97fb4f..00000000000 --- a/packages/plugins/typescript-stencil-apollo/src/helpers.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { DepGraph } from 'dependency-graph'; -import gqlTag from 'graphql-tag'; -import { Operation } from 'graphql-codegen-core'; -import { Fragment } from 'graphql-codegen-core'; - -export const generateFragments = convert => (fragments: Fragment[], options: Handlebars.HelperOptions): string => { - const cachedFragments: Record = {}; - if (!fragments) { - return ''; - } - const graph = new DepGraph({ circular: true }); - fragments.forEach(fragment => { - graph.addNode(fragment.name, fragment); - }); - fragments.forEach(fragment => { - const depends = extractFragments(fragment.document); - if (depends) { - depends.forEach(name => { - graph.addDependency(fragment.name, name); - }); - } - }); - return graph - .overallOrder() - .map(name => generateFragment(graph.getNodeData(name), options)) - .join('\n'); - - function generateFragment(fragment: any, options: any): string | void { - const cached = cachedFragments[fragment.name]; - if (!cached) { - cachedFragments[fragment.name] = fragment; - const config = options.data.root.config || {}; - const pascalCasedFragmentName = convert(fragment.name); - // fooBar, FooBar and foo_bar may cause conflict due to the pascalCase. - // Because all of them will have same namespace FooBar - if (config.noNamespaces) { - return ` - export const ${pascalCasedFragmentName}FragmentDoc = ${gql(convert)(fragment, options)}; - `; - } else { - return ` - export namespace ${pascalCasedFragmentName} { - export const FragmentDoc = ${gql(convert)(fragment, options)}; - } - `; - } - } else { - if (fragment.document !== cached.document) { - throw new Error(`Duplicated fragment called '${fragment.name}'`); - } - } - } -}; - -export const gql = convert => (operation: Operation, options: Handlebars.HelperOptions): string => { - const config = options.data.root.config || {}; - - const doc = ` - ${operation.document} - ${includeFragments(transformFragments(convert)(operation.document, options))} - `; - - return config.noGraphqlTag ? JSON.stringify(gqlTag(doc)) : 'gql`' + doc + '`'; -}; - -function includeFragments(fragments: string[]): string { - if (fragments) { - return ` - ${fragments - .filter((name, i, all) => all.indexOf(name) === i) - .map(name => '${' + name + '}') - .join('\n')} - `; - } - - return ''; -} - -export function extractFragments(document: string): string[] | undefined { - return (document.match(/\.\.\.[a-z0-9\_]+/gi) || []).map(name => name.replace('...', '')); -} - -const transformFragments = convert => (document: string, options: Handlebars.HelperOptions): string[] | undefined => { - return extractFragments(document).map(document => toFragmentName(convert)(document, options)); -}; - -export const toFragmentName = convert => (fragmentName: string, options: Handlebars.HelperOptions): string => { - const config = options.data.root.config || {}; - - if (config.noNamespaces) { - return convert(`${fragmentName}FragmentDoc`); - } else { - return convert(fragmentName) + '.FragmentDoc'; - } -}; diff --git a/packages/plugins/typescript-stencil-apollo/src/index.ts b/packages/plugins/typescript-stencil-apollo/src/index.ts index b38949ffe8a..198bb02a48a 100644 --- a/packages/plugins/typescript-stencil-apollo/src/index.ts +++ b/packages/plugins/typescript-stencil-apollo/src/index.ts @@ -1,42 +1,49 @@ -import { initCommonTemplate, TypeScriptCommonConfig } from 'graphql-codegen-typescript-common'; -import { DocumentFile, PluginFunction, PluginValidateFn, transformDocumentsFiles } from 'graphql-codegen-core'; -import { flattenTypes } from 'graphql-codegen-plugin-helpers'; -import { GraphQLSchema } from 'graphql'; -import * as Handlebars from 'handlebars'; -import * as rootTemplate from './root.handlebars'; -import { generateFragments, gql } from './helpers'; +import { DocumentFile, PluginValidateFn, PluginFunction } from 'graphql-codegen-plugin-helpers'; +import { visit, GraphQLSchema, concatAST, Kind, FragmentDefinitionNode } from 'graphql'; +import { RawClientSideBasePluginConfig } from 'graphql-codegen-visitor-plugin-common'; +import { StencilApolloVisitor } from './visitor'; import { extname } from 'path'; -import { pascalCase } from 'change-case'; -export interface TypeScriptStencilApolloConfig extends TypeScriptCommonConfig { - noGraphqlTag?: boolean; - noNamespaces?: boolean; +export enum StencilComponentType { + functional = 'functional', + class = 'class' } -export const plugin: PluginFunction = async ( +export interface StencilApolloRawPluginConfig extends RawClientSideBasePluginConfig { + componentType?: StencilComponentType; +} + +export const plugin: PluginFunction = ( schema: GraphQLSchema, documents: DocumentFile[], - config: TypeScriptStencilApolloConfig -): Promise => { - const { templateContext, convert } = initCommonTemplate(Handlebars, schema, documents, config); - const transformedDocuments = transformDocumentsFiles(schema, documents); - const flattenDocuments = flattenTypes(transformedDocuments); - Handlebars.registerHelper('generateFragments', generateFragments(convert)); - Handlebars.registerHelper('gql', gql(convert)); - Handlebars.registerHelper('toPascalCase', pascalCase); + config: StencilApolloRawPluginConfig +) => { + const allAst = concatAST( + documents.reduce((prev, v) => { + return [...prev, v.content]; + }, []) + ); + const operationsCount = allAst.definitions.filter(d => d.kind === Kind.OPERATION_DEFINITION); + + if (operationsCount.length === 0) { + return ''; + } - const hbsContext = { - ...templateContext, - ...flattenDocuments - }; + const allFragments = allAst.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION) as FragmentDefinitionNode[]; + const visitor = new StencilApolloVisitor(allFragments, config) as any; + const visitorResult = visit(allAst, { leave: visitor }); - return Handlebars.compile(rootTemplate)(hbsContext); + return [ + visitor.getImports(), + visitor.fragments, + ...visitorResult.definitions.filter(t => typeof t === 'string') + ].join('\n'); }; export const validate: PluginValidateFn = async ( schema: GraphQLSchema, documents: DocumentFile[], - config: any, + config: StencilApolloRawPluginConfig, outputFile: string ) => { if (extname(outputFile) !== '.tsx') { diff --git a/packages/plugins/typescript-stencil-apollo/src/polyfills.d.ts b/packages/plugins/typescript-stencil-apollo/src/polyfills.d.ts deleted file mode 100644 index 6f7203f25bd..00000000000 --- a/packages/plugins/typescript-stencil-apollo/src/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.handlebars' { - const content: string; - export = content; -} diff --git a/packages/plugins/typescript-stencil-apollo/src/root.handlebars b/packages/plugins/typescript-stencil-apollo/src/root.handlebars deleted file mode 100644 index 52fb3d57118..00000000000 --- a/packages/plugins/typescript-stencil-apollo/src/root.handlebars +++ /dev/null @@ -1,25 +0,0 @@ -{{#ifCond operations.length '!==' 0}} - -{{#unless @root.config.noGraphqlTag}} -import gql from 'graphql-tag'; -{{/unless}} - -{{ blockCommentIf 'Fragments' fragments }} -{{{generateFragments fragments}}} - -{{ blockCommentIf 'Components' operations }} -{{#each operations }} - {{#unless @root.config.noNamespaces}} -export namespace {{convert name 'typeNames'}} { - {{/unless}} - export const {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Document = {{{ gql this }}}; - export interface {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}ComponentProps { - variables ?: {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Variables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-{{ toLowerCase operationType }}/types').On{{ toPascalCase operationType }}ReadyFn<{{#if @root.config.noNamespaces}}{{ convert name }}{{/if}}{{ toPascalCase operationType }}, {{#if @root.config.noNamespaces}}{{ convert name }}{{/if}}Variables>; - } - export const {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}Component = (props: {{#if @root.config.noNamespaces}}{{ convert name 'typeNames' }}{{/if}}ComponentProps) => ; - {{#unless @root.config.noNamespaces}} -} - {{/unless}} -{{/each}} -{{/ifCond}} diff --git a/packages/plugins/typescript-stencil-apollo/src/visitor.ts b/packages/plugins/typescript-stencil-apollo/src/visitor.ts new file mode 100644 index 00000000000..845dfedc2eb --- /dev/null +++ b/packages/plugins/typescript-stencil-apollo/src/visitor.ts @@ -0,0 +1,118 @@ +import { + ClientSideBaseVisitor, + ClientSideBasePluginConfig, + getConfigValue +} from 'graphql-codegen-visitor-plugin-common'; +import { StencilApolloRawPluginConfig, StencilComponentType } from './index'; +import * as autoBind from 'auto-bind'; +import { FragmentDefinitionNode, print, OperationDefinitionNode } from 'graphql'; +import { toPascalCase } from 'graphql-codegen-plugin-helpers'; +import * as changeCase from 'change-case'; + +export interface StencilApolloPluginConfig extends ClientSideBasePluginConfig { + componentType: StencilComponentType; +} + +export class StencilApolloVisitor extends ClientSideBaseVisitor< + StencilApolloRawPluginConfig, + StencilApolloPluginConfig +> { + constructor(fragments: FragmentDefinitionNode[], rawConfig: StencilApolloRawPluginConfig) { + super(fragments, rawConfig, { + componentType: getConfigValue(rawConfig.componentType, StencilComponentType.functional) + } as any); + + autoBind(this); + } + + public getImports(): string { + const baseImports = super.getImports(); + const imports = []; + + if (this.config.componentType === StencilComponentType.class) { + imports.push(`import { Component } from '@stencil/core';`); + } + + return [baseImports, ...imports].join('\n'); + } + + private _buildOperationFunctionalComponent( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + const operationName: string = this.convertName(node.name.value); + const propsTypeName: string = this.convertName(operationName + 'Props'); + const apolloStencilComponentTag = changeCase.paramCase(`Apollo${operationType}`); + const onReadySignature = toPascalCase(`On${operationType}ReadyFn`); + const componentName = this.convertName(`${operationName}Component`); + + const propsVar = ` + export type ${propsTypeName} = { + variables ?: ${operationVariablesTypes}; + onReady ?: import('stencil-apollo/dist/types/components/${apolloStencilComponentTag}/types').${onReadySignature}<${operationResultType}, ${operationVariablesTypes}>; + }; + `; + + const component = ` + export const ${componentName} = (props: ${propsTypeName}) => <${apolloStencilComponentTag} ${operationType.toLowerCase()}={ ${documentVariableName} } { ...props } />; + `; + + return [propsVar, component].filter(a => a).join('\n'); + } + + private _buildClassComponent( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + const componentName: string = this.convertName(node.name.value + 'Component'); + const apolloStencilComponentTag = changeCase.paramCase(`Apollo${operationType}`); + const onReadySignature = toPascalCase(`On${operationType}ReadyFn`); + + return ` + @Component({ + tag: '${changeCase.paramCase(`Apollo${toPascalCase(node.name.value)}`)}' + }) + export class ${componentName} { + @Prop() onReady: import('stencil-apollo/dist/types/components/${apolloStencilComponentTag}/types').${onReadySignature}<${operationResultType}, ${operationVariablesTypes}>; + render() { + return <${apolloStencilComponentTag} ${operationType.toLowerCase()}={ ${documentVariableName} } onReady={ this.onReady } />; + } + } + `; + } + + protected buildOperation( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + switch (this.config.componentType) { + case StencilComponentType.class: + return this._buildClassComponent( + node, + documentVariableName, + operationType, + operationResultType, + operationVariablesTypes + ); + case StencilComponentType.functional: + return this._buildOperationFunctionalComponent( + node, + documentVariableName, + operationType, + operationResultType, + operationVariablesTypes + ); + default: + return ''; + } + } +} diff --git a/packages/plugins/typescript-stencil-apollo/tests/files/schema.json b/packages/plugins/typescript-stencil-apollo/tests/files/schema.json deleted file mode 100644 index e9ce20244e9..00000000000 --- a/packages/plugins/typescript-stencil-apollo/tests/files/schema.json +++ /dev/null @@ -1,1739 +0,0 @@ -{ - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": { - "name": "Mutation" - }, - "subscriptionType": { - "name": "Subscription" - }, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": "", - "fields": [ - { - "name": "feed", - "description": "A feed of repository submissions", - "args": [ - { - "name": "type", - "description": "The sort order for the feed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "FeedType", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "The number of items to skip, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "limit", - "description": "The number of items to fetch starting from the offset, for pagination", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "entry", - "description": "A single entry", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "currentUser", - "description": "Return the currently logged in user, or null if nobody is logged in", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FeedType", - "description": "A list of options for the sort order of the feed", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "HOT", - "description": "Sort by a combination of freshness and score, using Reddit's algorithm", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NEW", - "description": "Newest entries first", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "TOP", - "description": "Highest score entries first", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Entry", - "description": "Information about a GitHub repository submitted to GitHunt", - "fields": [ - { - "name": "repository", - "description": "Information about the repository from GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Repository", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who submitted this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the entry was submitted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "score", - "description": "The score of this repository, upvotes - downvotes", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hotScore", - "description": "The hot score of this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "comments", - "description": "Comments posted about this repository", - "args": [ - { - "name": "limit", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "offset", - "description": "", - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commentCount", - "description": "The number of comments posted about this repository", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "XXX to be changed", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "Vote", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Repository", - "description": "A repository object from the GitHub API. This uses the exact field names returned by the\nGitHub API for simplicity, even though the convention for GraphQL is usually to camel case.", - "fields": [ - { - "name": "name", - "description": "Just the name of the repository, e.g. GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full_name", - "description": "The full name of the repository with the username, e.g. apollostack/GitHunt-API", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "The description of the repository", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The link to the repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "stargazers_count", - "description": "The number of people who have starred this repository on GitHub", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "open_issues_count", - "description": "The number of open issues on this repository on GitHub", - "args": [], - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "owner", - "description": "The owner of this repository on GitHub, e.g. apollostack", - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "User", - "description": "A user object from the GitHub API. This uses the exact field names returned from the GitHub API.", - "fields": [ - { - "name": "login", - "description": "The name of the user, e.g. apollostack", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "avatar_url", - "description": "The URL to a directly embeddable image for this user's avatar", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "html_url", - "description": "The URL of this user's GitHub page", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Float", - "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Comment", - "description": "A comment about an entry, submitted by a user", - "fields": [ - { - "name": "id", - "description": "The SQL ID of this entry", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "postedBy", - "description": "The GitHub user who posted the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "User", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "createdAt", - "description": "A timestamp of when the comment was posted", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Float", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "content", - "description": "The text of the comment", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "repoName", - "description": "The repository which this comment is about", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Vote", - "description": "XXX to be removed", - "fields": [ - { - "name": "vote_value", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Mutation", - "description": "", - "fields": [ - { - "name": "submitRepository", - "description": "Submit a new repository, returns the new submission", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "vote", - "description": "Vote on a repository submission, returns the submission that was voted on", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "type", - "description": "The type of vote - UP, DOWN, or CANCEL", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "VoteType", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Entry", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "submitComment", - "description": "Comment on a repository, returns the new comment", - "args": [ - { - "name": "repoFullName", - "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "commentContent", - "description": "The text content for the new comment", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "VoteType", - "description": "The type of vote to record, when submitting a vote", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "UP", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "DOWN", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "CANCEL", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Subscription", - "description": "", - "fields": [ - { - "name": "commentAdded", - "description": "Subscription fires on every comment added", - "args": [ - { - "name": "repoFullName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "Comment", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "locations", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__DirectiveLocation", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "QUERY", - "description": "Location adjacent to a query operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MUTATION", - "description": "Location adjacent to a mutation operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SUBSCRIPTION", - "description": "Location adjacent to a subscription operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD", - "description": "Location adjacent to a field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_DEFINITION", - "description": "Location adjacent to a fragment definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_SPREAD", - "description": "Location adjacent to a fragment spread.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INLINE_FRAGMENT", - "description": "Location adjacent to an inline fragment.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCHEMA", - "description": "Location adjacent to a schema definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCALAR", - "description": "Location adjacent to a scalar definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Location adjacent to an object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD_DEFINITION", - "description": "Location adjacent to a field definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ARGUMENT_DEFINITION", - "description": "Location adjacent to an argument definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Location adjacent to an interface definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Location adjacent to a union definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Location adjacent to an enum definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM_VALUE", - "description": "Location adjacent to an enum value definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Location adjacent to an input object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_FIELD_DEFINITION", - "description": "Location adjacent to an input object field definition.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - } - ], - "directives": [ - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "deprecated", - "description": "Marks an element of a GraphQL schema as no longer supported.", - "locations": ["FIELD_DEFINITION", "ENUM_VALUE"], - "args": [ - { - "name": "reason", - "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": "\"No longer supported\"" - } - ] - } - ] - } -} diff --git a/packages/plugins/typescript-stencil-apollo/tests/stencil-apollo.spec.ts b/packages/plugins/typescript-stencil-apollo/tests/stencil-apollo.spec.ts index f2eeda5fdbd..22dc8e51363 100644 --- a/packages/plugins/typescript-stencil-apollo/tests/stencil-apollo.spec.ts +++ b/packages/plugins/typescript-stencil-apollo/tests/stencil-apollo.spec.ts @@ -1,16 +1,14 @@ -import 'graphql-codegen-core/dist/testing'; -import { makeExecutableSchema } from 'graphql-tools'; -import { plugin } from '../dist'; -import * as fs from 'fs'; +import 'graphql-codegen-testing'; +import { plugin, StencilComponentType } from '../src/index'; import { buildClientSchema } from 'graphql'; import gql from 'graphql-tag'; +import { readFileSync } from 'fs'; describe('Components', () => { - const schema = buildClientSchema(JSON.parse(fs.readFileSync('./tests/files/schema.json').toString())); - - it('should import dependencies', async () => { + const schema = buildClientSchema(JSON.parse(readFileSync('../../../dev-test/githunt/schema.json').toString())); + it('should import dependencies if class components are generated', async () => { const documents = gql` - query { + query Feed { feed { id commentCount @@ -25,16 +23,21 @@ describe('Components', () => { } `; - const content = await plugin(schema, [{ filePath: '', content: documents }], {}); + const content = await plugin( + schema, + [{ filePath: '', content: documents }], + { componentType: StencilComponentType.class }, + { outputFile: '' } + ); expect(content).toBeSimilarStringTo(` - import gql from 'graphql-tag'; + import { Component } from '@stencil/core'; `); }); - it('should generate Document variable', async () => { + it('should generate Functional Component', async () => { const documents = gql` - query { + query Feed { feed { id commentCount @@ -49,30 +52,28 @@ describe('Components', () => { } `; - const content = await plugin(schema, [{ filePath: '', content: documents }], {}); + const content = await plugin( + schema, + [{ filePath: '', content: documents }], + { componentType: StencilComponentType.functional }, + { outputFile: '' } + ); expect(content).toBeSimilarStringTo(` - export const Document = gql\` - { - feed { - id - commentCount - repository { - full_name - html_url - owner { - avatar_url - } - } - } - } - \`; - `); + export type FeedProps = { + variables ?: FeedQueryVariables; + onReady ?: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + }; + `); + + expect(content).toBeSimilarStringTo(` + export const FeedComponent = (props: FeedProps) => ; + `); }); - it('should generate Component', async () => { + it('should generate Class Component', async () => { const documents = gql` - query { + query Feed { feed { id commentCount @@ -87,261 +88,23 @@ describe('Components', () => { } `; - const content = await plugin(schema, [{ filePath: '', content: documents }], {}, { outputFile: '' }); + const content = await plugin( + schema, + [{ filePath: '', content: documents }], + { componentType: StencilComponentType.class }, + { outputFile: '' } + ); expect(content).toBeSimilarStringTo(` - export interface ComponentProps { - variables ?: Variables; - onReady ?: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; - } - export const Component = (props: ComponentProps) => ; - `); - }); - - it('should generate Document variables for inline fragments', async () => { - const repositoryWithOwner = gql` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - `; - const feedWithRepository = gql` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } - - ${repositoryWithOwner} - `; - const myFeed = gql` - query MyFeed { - feed { - ...FeedWithRepository - } - } - - ${feedWithRepository} - `; - - const content = await plugin(schema, [{ filePath: '', content: myFeed }], {}); - - expect(content).toBeSimilarStringTo(` - export namespace FeedWithRepository { - export const FragmentDoc = gql\` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner + @Component({ + tag: 'apollo-feed' + }) + export class FeedComponent { + @Prop() onReady: import('stencil-apollo/dist/types/components/apollo-query/types').OnQueryReadyFn; + render() { + return ; + } } - } - - \${RepositoryWithOwner.FragmentDoc} - - \`; - } `); - expect(content).toBeSimilarStringTo(` - export namespace RepositoryWithOwner { - export const FragmentDoc = gql\` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - \`; - } - `); - }); - - it('should embed inline fragments inside query document', async () => { - const repositoryWithOwner = gql` - fragment RepositoryWithOwner on Repository { - full_name - html_url - owner { - avatar_url - } - } - `; - const feedWithRepository = gql` - fragment FeedWithRepository on FeedType { - id - commentCount - repository(search: "phrase") { - ...RepositoryWithOwner - } - } - - ${repositoryWithOwner} - `; - const myFeed = gql` - query MyFeed { - feed { - ...FeedWithRepository - } - } - - ${feedWithRepository} - `; - - const content = await plugin(schema, [{ filePath: '', content: myFeed }], {}); - - expect(content).toBeSimilarStringTo(` - export const Document = gql\` - query MyFeed { - feed { - ...FeedWithRepository - } - } - - \${FeedWithRepository.FragmentDoc} - \`; - `); - }); - it('no duplicated fragments', async () => { - const simpleFeed = gql` - fragment SimpleFeed on FeedType { - id - commentCount - } - `; - const myFeed = gql` - query MyFeed { - feed { - ...SimpleFeed - } - allFeeds { - ...SimpleFeed - } - } - `; - const documents = [simpleFeed, myFeed]; - const content = await plugin(schema, documents.map(content => ({ content, filePath: '' })), {}); - - expect(content).toBeSimilarStringTo(` - const Document = gql\` query MyFeed { - feed { - ...SimpleFeed - } - allFeeds { - ...SimpleFeed - } - } - \${SimpleFeed.FragmentDoc} - \` - `); - expect(content).toBeSimilarStringTo(` - const FragmentDoc = gql\` fragment SimpleFeed on FeedType { - id - commentCount - } - \`; - `); - }); - - it('write fragments in proper order (when one depends on other)', async () => { - const myFeed = gql` - fragment FeedWithRepository on FeedType { - id - repository { - ...RepositoryWithOwner - } - } - fragment RepositoryWithOwner on Repository { - full_name - } - query MyFeed { - feed { - ...FeedWithRepository - } - } - `; - const documents = [myFeed]; - const content = await plugin(schema, documents.map(content => ({ content, filePath: '' })), {}); - - const feedWithRepositoryPos = content.indexOf('fragment FeedWithRepository'); - const repositoryWithOwnerPos = content.indexOf('fragment RepositoryWithOwner'); - expect(repositoryWithOwnerPos).toBeLessThan(feedWithRepositoryPos); - }); - - it('Issue 702 - handle duplicated documents when fragment and query have the same name', async () => { - const testSchema = makeExecutableSchema({ - typeDefs: ` - type Event { - type: String! - name: String! - } - - type Query { - events: [Event] - } - - schema { - query: Query - } - ` - }); - - const query = gql` - fragment event on Event { - name - } - - query event { - events { - ...event - } - } - `; - - const content = await plugin(testSchema, [{ filePath: '', content: query }], {}); - - expect(content).toBeSimilarStringTo(` - export namespace Event { - export const FragmentDoc = gql\` - fragment event on Event { - name - } - \`; - } - `); - - expect(content).toBeSimilarStringTo(` - export namespace Event { - export const FragmentDoc = gql\` - fragment event on Event { - name - } - \`; - } - `); - - expect(content).toBeSimilarStringTo(` - export namespace Event { - export const Document = gql\` - query event { - events { - ...event - } - } - - \${Event.FragmentDoc} - \`; - `); - }); - - it(`should skip if there's no operations`, async () => { - const content = await plugin(schema, [], { noNamespaces: true }); - - expect(content).not.toContain(`import gql from 'graphql-tag';`); }); }); diff --git a/packages/plugins/typescript-stencil-apollo/tsconfig.json b/packages/plugins/typescript-stencil-apollo/tsconfig.json index 77f658f5db3..c378ea0a8ed 100644 --- a/packages/plugins/typescript-stencil-apollo/tsconfig.json +++ b/packages/plugins/typescript-stencil-apollo/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", @@ -17,5 +18,6 @@ "noUnusedLocals": false, "noUnusedParameters": false }, + "include": ["src/**/*.ts"], "exclude": ["node_modules", "tests", "dist", "example"] } diff --git a/packages/plugins/typescript-common/.gitignore b/packages/plugins/typescript/.gitignore similarity index 100% rename from packages/plugins/typescript-common/.gitignore rename to packages/plugins/typescript/.gitignore diff --git a/packages/plugins/typescript-common/.npmignore b/packages/plugins/typescript/.npmignore similarity index 100% rename from packages/plugins/typescript-common/.npmignore rename to packages/plugins/typescript/.npmignore diff --git a/packages/plugins/typescript/package.json b/packages/plugins/typescript/package.json new file mode 100644 index 00000000000..9e2174b2a58 --- /dev/null +++ b/packages/plugins/typescript/package.json @@ -0,0 +1,30 @@ +{ + "name": "graphql-codegen-typescript", + "version": "0.18.0", + "description": "GraphQL Code Generator plugin for generating TypeScript types", + "repository": "git@github.com:dotansimha/graphql-code-generator.git", + "license": "MIT", + "scripts": { + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs", + "test": "jest --config ../../../jest.config.js" + }, + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-visitor-plugin-common": "0.18.0", + "graphql-codegen-plugin-helpers": "0.18.0" + }, + "devDependencies": { + "graphql-codegen-testing": "0.18.0", + "graphql": "14.1.1", + "jest": "24.1.0", + "ts-jest": "24.0.0", + "typescript": "3.3.3333" + }, + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" + } +} diff --git a/packages/plugins/typescript/src/index.ts b/packages/plugins/typescript/src/index.ts new file mode 100644 index 00000000000..6e5bfa0f735 --- /dev/null +++ b/packages/plugins/typescript/src/index.ts @@ -0,0 +1,94 @@ +import { DocumentFile, PluginFunction } from 'graphql-codegen-plugin-helpers'; +import { + parse, + printSchema, + visit, + GraphQLSchema, + TypeInfo, + GraphQLNamedType, + visitWithTypeInfo, + getNamedType, + isIntrospectionType, + DocumentNode, + printIntrospectionSchema, + isObjectType +} from 'graphql'; +import { RawTypesConfig } from 'graphql-codegen-visitor-plugin-common'; +import { TsVisitor } from './visitor'; +import { TsIntrospectionVisitor } from './introspection-visitor'; +export * from './typescript-variables-to-object'; +export * from './visitor'; + +export interface TypeScriptPluginConfig extends RawTypesConfig { + avoidOptionals?: boolean; + constEnums?: boolean; + enumsAsTypes?: boolean; + immutableTypes?: boolean; + maybeValue?: string; +} + +export const plugin: PluginFunction = ( + schema: GraphQLSchema, + documents: DocumentFile[], + config: TypeScriptPluginConfig +) => { + const visitor = new TsVisitor(config) as any; + const printedSchema = printSchema(schema); + const astNode = parse(printedSchema); + const header = `type Maybe = ${visitor.config.maybeValue};`; + const visitorResult = visit(astNode, { leave: visitor }); + const introspectionDefinitions = includeIntrospectionDefinitions(schema, documents, config); + + return [header, ...visitorResult.definitions, ...introspectionDefinitions].join('\n'); +}; + +function includeIntrospectionDefinitions( + schema: GraphQLSchema, + documents: DocumentFile[], + config: TypeScriptPluginConfig +): string[] { + const typeInfo = new TypeInfo(schema); + const usedTypes: GraphQLNamedType[] = []; + const documentsVisitor = visitWithTypeInfo(typeInfo, { + Field() { + const type = getNamedType(typeInfo.getType()); + + if (isIntrospectionType(type) && !usedTypes.includes(type)) { + usedTypes.push(type); + } + } + }); + + documents.forEach(doc => visit(doc.content, documentsVisitor)); + + const typesToInclude: GraphQLNamedType[] = []; + + usedTypes.forEach(type => { + collectTypes(type); + }); + + const visitor = new TsIntrospectionVisitor(config, typesToInclude); + const result: DocumentNode = visit(parse(printIntrospectionSchema(schema)), { leave: visitor }); + + // recursively go through each `usedTypes` and their children and collect all used types + // we don't care about Interfaces, Unions and others, but Objects and Enums + function collectTypes(type: GraphQLNamedType): void { + if (typesToInclude.includes(type)) { + return; + } + + typesToInclude.push(type); + + if (isObjectType(type)) { + const fields = type.getFields(); + + Object.keys(fields).forEach(key => { + const field = fields[key]; + const type = getNamedType(field.type); + collectTypes(type); + }); + } + } + + return result.definitions as any[]; +} diff --git a/packages/plugins/typescript/src/introspection-visitor.ts b/packages/plugins/typescript/src/introspection-visitor.ts new file mode 100644 index 00000000000..966866beda9 --- /dev/null +++ b/packages/plugins/typescript/src/introspection-visitor.ts @@ -0,0 +1,39 @@ +import { GraphQLNamedType, EnumTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql'; +import { TsVisitor } from './visitor'; +import { TypeScriptPluginConfig } from './index'; +import * as autoBind from 'auto-bind'; + +export class TsIntrospectionVisitor extends TsVisitor { + private typesToInclude: GraphQLNamedType[] = []; + + constructor(pluginConfig: TypeScriptPluginConfig = {}, typesToInclude: GraphQLNamedType[]) { + super(pluginConfig); + + this.typesToInclude = typesToInclude; + autoBind(this); + } + + DirectiveDefinition() { + return null; + } + + ObjectTypeDefinition(node: ObjectTypeDefinitionNode, key: string | number, parent: any) { + const name: string = node.name as any; + + if (this.typesToInclude.some(type => type.name === name)) { + return super.ObjectTypeDefinition(node, key, parent); + } + + return null; + } + + EnumTypeDefinition(node: EnumTypeDefinitionNode): string { + const name: string = node.name as any; + + if (this.typesToInclude.some(type => type.name === name)) { + return super.EnumTypeDefinition(node); + } + + return null; + } +} diff --git a/packages/plugins/typescript/src/typescript-variables-to-object.ts b/packages/plugins/typescript/src/typescript-variables-to-object.ts new file mode 100644 index 00000000000..ca4f3f848fa --- /dev/null +++ b/packages/plugins/typescript/src/typescript-variables-to-object.ts @@ -0,0 +1,51 @@ +import { OperationVariablesToObject, ScalarsMap, ConvertNameFn } from 'graphql-codegen-visitor-plugin-common'; +import { TypeNode, Kind } from 'graphql'; + +export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject { + constructor( + _scalars: ScalarsMap, + _convertName: ConvertNameFn, + private _avoidOptionals: boolean, + private _immutableTypes: boolean + ) { + super(_scalars, _convertName); + } + + private clearOptional(str: string): string { + if (str.startsWith('Maybe')) { + return str.replace(/^Maybe<(.*?)>$/i, '$1'); + } + + return str; + } + + public wrapAstTypeWithModifiers(baseType: string, typeNode: TypeNode): string { + if (typeNode.kind === Kind.NON_NULL_TYPE) { + const type = this.wrapAstTypeWithModifiers(baseType, typeNode.type); + + return this.clearOptional(type); + } else if (typeNode.kind === Kind.LIST_TYPE) { + const innerType = this.wrapAstTypeWithModifiers(baseType, typeNode.type); + + return `Maybe<${this._immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>>`; + } else { + return `Maybe<${baseType}>`; + } + } + + protected formatFieldString(fieldName: string, isNonNullType: boolean, hasDefaultValue: boolean): string { + if (hasDefaultValue || isNonNullType || this._avoidOptionals) { + return fieldName; + } else { + return `${fieldName}?`; + } + } + + protected formatTypeString(fieldType: string, isNonNullType: boolean, hasDefaultValue: boolean): string { + if (hasDefaultValue) { + return this.clearOptional(fieldType); + } + + return fieldType; + } +} diff --git a/packages/plugins/typescript/src/visitor.ts b/packages/plugins/typescript/src/visitor.ts new file mode 100644 index 00000000000..88d76ffd47b --- /dev/null +++ b/packages/plugins/typescript/src/visitor.ts @@ -0,0 +1,108 @@ +import { DeclarationBlock, indent, BaseTypesVisitor, ParsedTypesConfig } from 'graphql-codegen-visitor-plugin-common'; +import { TypeScriptPluginConfig } from './index'; +import * as autoBind from 'auto-bind'; + +import { + FieldDefinitionNode, + NamedTypeNode, + ListTypeNode, + NonNullTypeNode, + EnumTypeDefinitionNode, + Kind +} from 'graphql'; +import { TypeScriptOperationVariablesToObject } from './typescript-variables-to-object'; + +export interface TypeScriptPluginParsedConfig extends ParsedTypesConfig { + avoidOptionals: boolean; + constEnums: boolean; + enumsAsTypes: boolean; + immutableTypes: boolean; + maybeValue: string; +} + +export class TsVisitor< + TRawConfig extends TypeScriptPluginConfig = TypeScriptPluginConfig, + TParsedConfig extends TypeScriptPluginParsedConfig = TypeScriptPluginParsedConfig +> extends BaseTypesVisitor { + constructor(pluginConfig: TRawConfig, additionalConfig: Partial = {}) { + super( + pluginConfig, + { + avoidOptionals: pluginConfig.avoidOptionals || false, + maybeValue: pluginConfig.maybeValue || 'T | null', + constEnums: pluginConfig.constEnums || false, + enumsAsTypes: pluginConfig.enumsAsTypes || false, + immutableTypes: pluginConfig.immutableTypes || false, + ...(additionalConfig || {}) + } as TParsedConfig, + null + ); + + autoBind(this); + this.setArgumentsTransformer( + new TypeScriptOperationVariablesToObject( + this.scalars, + this.convertName, + this.config.avoidOptionals, + this.config.immutableTypes + ) + ); + this.setDeclarationBlockConfig({ + enumNameValueSeparator: ' =' + }); + } + + private clearOptional(str: string): string { + if (str.startsWith('Maybe')) { + return str.replace(/Maybe<(.*?)>/, '$1'); + } + + return str; + } + + NamedType(node: NamedTypeNode): string { + return `Maybe<${super.NamedType(node)}>`; + } + + ListType(node: ListTypeNode): string { + return `Maybe<${super.ListType(node)}>`; + } + + protected wrapWithListType(str: string): string { + return `${this.config.immutableTypes ? 'ReadonlyArray' : 'Array'}<${str}>`; + } + + NonNullType(node: NonNullTypeNode): string { + const baseValue = super.NonNullType(node); + + return this.clearOptional(baseValue); + } + + FieldDefinition(node: FieldDefinitionNode, key?: number | string, parent?: any): string { + const typeString = (node.type as any) as string; + const originalFieldNode = parent[key] as FieldDefinitionNode; + const addOptionalSign = !this.config.avoidOptionals && originalFieldNode.type.kind !== Kind.NON_NULL_TYPE; + + return indent( + `${this.config.immutableTypes ? 'readonly ' : ''}${node.name}${addOptionalSign ? '?' : ''}: ${typeString},` + ); + } + + EnumTypeDefinition(node: EnumTypeDefinitionNode): string { + if (this.config.enumsAsTypes) { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node)) + .withContent( + node.values.map(v => `'${this.config.enumValues[(v.name as any) as string] || v.name}'`).join(' | ') + ).string; + } else { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind(this.config.constEnums ? 'const enum' : 'enum') + .withName(this.convertName(node)) + .withBlock(this.buildEnumValuesBlock(node.values)).string; + } + } +} diff --git a/packages/plugins/typescript/tests/typescript.spec.ts b/packages/plugins/typescript/tests/typescript.spec.ts new file mode 100644 index 00000000000..7afe7f724fb --- /dev/null +++ b/packages/plugins/typescript/tests/typescript.spec.ts @@ -0,0 +1,791 @@ +import 'graphql-codegen-testing'; +import { buildSchema, parse } from 'graphql'; +import { validateTs } from './validate'; +import { plugin } from '../src/index'; + +describe('TypeScript', () => { + describe('Config', () => { + it('Should build type correctly when specified with avoidOptionals config', async () => { + const schema = buildSchema(` + type MyType { + foo: String + bar: String! + }`); + const result = await plugin(schema, [], { avoidOptionals: true }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyType = { + foo: Maybe, + bar: string, + }; + `); + validateTs(result); + }); + + it('Should build type correctly when specified with immutableTypes config', async () => { + const schema = buildSchema(` + type MyType { + foo: [String!]! + }`); + const result = await plugin(schema, [], { immutableTypes: true }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyType = { + readonly foo: ReadonlyArray, + }; + `); + validateTs(result); + }); + + it('Should use const enums when constEnums is set', async () => { + const schema = buildSchema(` + enum MyEnum { + A + }`); + const result = await plugin(schema, [], { constEnums: true }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export const enum MyEnum { + A = 'A' + }; + `); + validateTs(result); + }); + + it('Should use enum as type when enumsAsTypes is set', async () => { + const schema = buildSchema(` + enum MyEnum { + A + B + }`); + const result = await plugin(schema, [], { enumsAsTypes: true }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyEnum = 'A' | 'B'; + `); + validateTs(result); + }); + + it('Should use enum as type when enumsAsTypes is set and also enumValues', async () => { + const schema = buildSchema(` + enum MyEnum { + A + B + }`); + const result = await plugin(schema, [], { enumValues: { A: 'BOOP' }, enumsAsTypes: true }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyEnum = 'BOOP' | 'B'; + `); + validateTs(result); + }); + + it('Should use custom namingConvention for enums (keep)', async () => { + const schema = buildSchema(/* GraphQL */ ` + enum Foo { + YES + NO + } + type MyType { + foo(a: String!, b: String, c: [String], d: [Int!]!): Foo + } + `); + const result = await plugin( + schema, + [], + { + namingConvention: { + typeNames: 'change-case#lowerCase', + enumValues: 'keep' + } + }, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + export enum foo { + YES = 'YES', + NO = 'NO' + } + `); + + expect(result).toBeSimilarStringTo(` + export type mytypefooargs = { + a: string, + b?: Maybe, + c?: Maybe>>, + d: Array + }; + `); + expect(result).toBeSimilarStringTo(` + export type mytype = { + foo?: Maybe, + }; + `); + + validateTs(result); + }); + + it('Should use custom namingConvention for enums', async () => { + const schema = buildSchema(/* GraphQL */ ` + enum Foo { + YES + NO + } + type MyType { + foo(a: String!, b: String, c: [String], d: [Int!]!): Foo + } + `); + const result = await plugin( + schema, + [], + { + namingConvention: { + typeNames: 'keep', + enumValues: 'change-case#lowerCase' + } + }, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + export enum Foo { + yes = 'YES', + no = 'NO' + } + `); + + expect(result).toBeSimilarStringTo(` + export type MyTypefooArgs = { + a: string, + b?: Maybe, + c?: Maybe>>, + d: Array + }; + `); + + expect(result).toBeSimilarStringTo(` + export type MyType = { + foo?: Maybe, + }; + `); + + validateTs(result); + }); + + it('should handle introspection types (like __TypeKind)', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Post { + title: String + } + type Query { + post: Post! + } + `); + const query = parse(/* GraphQL */ ` + query Info { + __type(name: "Post") { + name + fields { + name + type { + name + kind + } + } + } + } + `); + + const content = await plugin( + testSchema, + [{ filePath: '', content: query }], + {}, + { + outputFile: 'graphql.ts' + } + ); + + expect(content).toBeSimilarStringTo(` + export enum __TypeKind { + Scalar = 'SCALAR', + Object = 'OBJECT', + Interface = 'INTERFACE', + Union = 'UNION', + Enum = 'ENUM', + Input_Object = 'INPUT_OBJECT', + List = 'LIST', + Non_Null = 'NON_NULL' + } + `); + }); + }); + + describe('Object (type)', () => { + it('Should build type correctly', async () => { + const schema = buildSchema(` + type MyType { + foo: String + bar: String! + }`); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyType = { + foo?: Maybe, + bar: string, + }; + `); + validateTs(result); + }); + + it('Should build type correctly when implementing interface', async () => { + const schema = buildSchema(` + interface MyInterface { + foo: String! + } + + type MyType implements MyInterface { + foo: String! + } + `); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyInterface = { + foo: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type MyType = MyInterface & { + foo: string, + }; + `); + validateTs(result); + }); + + it('Should build type correctly when implementing multiple interfaces', async () => { + const schema = buildSchema(` + interface MyInterface { + foo: String! + } + + interface MyOtherInterface { + bar: String! + } + + type MyType implements MyInterface & MyOtherInterface { + foo: String! + bar: String! + } + `); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyInterface = { + foo: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type MyOtherInterface = { + bar: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type MyType = MyInterface & MyOtherInterface & { + foo: string, + bar: string, + }; + `); + validateTs(result); + }); + + it('Should build type correctly with links between types', async () => { + const schema = buildSchema(` + type MyType { + foo: MyOtherType! + } + + type MyOtherType { + bar: String! + } + `); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyType = { + foo: MyOtherType, + }; + `); + expect(result).toBeSimilarStringTo(` + export type MyOtherType = { + bar: string, + }; + `); + validateTs(result); + }); + }); + + describe('Union', () => { + it('Should build union as type correctly', async () => { + const schema = buildSchema(` + type MyType { + foo: String! + } + + type MyOtherType { + bar: String! + } + + union MyUnion = MyType | MyOtherType + `); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyUnion = MyType | MyOtherType; + `); + validateTs(result); + }); + }); + + describe('Interface', () => { + it('Should build interface correctly', async () => { + const schema = buildSchema(` + interface MyInterface { + foo: String + bar: String! + }`); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyInterface = { + foo?: Maybe, + bar: string, + }; + `); + validateTs(result); + }); + }); + + describe('Directives', () => { + it('Should handle directive declarations correctly', async () => { + const schema = buildSchema(` + directive @simple on FIELD_DEFINITION + directive @withArgument(arg: Int!) on FIELD_DEFINITION + directive @objSimple on OBJECT + directive @universal on OBJECT | FIELD_DEFINITION | ENUM_VALUE + `); + + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).not.toContain('simple'); + expect(result).not.toContain('withArguments'); + expect(result).not.toContain('objSimple'); + expect(result).not.toContain('universal'); + validateTs(result); + }); + }); + + describe('Naming Convention & Types Prefix', () => { + it('Should use custom namingConvention for type name and args typename', async () => { + const schema = buildSchema(`type MyType { foo(a: String!, b: String, c: [String], d: [Int!]!): String }`); + const result = await plugin(schema, [], { namingConvention: 'change-case#lowerCase' }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type mytypefooargs = { + a: string, + b?: Maybe, + c?: Maybe>>, + d: Array + }; + `); + expect(result).toBeSimilarStringTo(` + export type mytype = { + foo?: Maybe, + }; + `); + + validateTs(result); + }); + + it('Should use custom namingConvention and add custom prefix', async () => { + const schema = buildSchema(`type MyType { foo(a: String!, b: String, c: [String], d: [Int!]!): String }`); + const result = await plugin( + schema, + [], + { namingConvention: 'change-case#lowerCase', typesPrefix: 'I' }, + { outputFile: '' } + ); + + expect(result).toBeSimilarStringTo(` + export type Imytypefooargs = { + a: string, + b?: Maybe, + c?: Maybe>>, + d: Array + }; + `); + + expect(result).toBeSimilarStringTo(` + export type Imytype = { + foo?: Maybe, + }; + `); + + validateTs(result); + }); + + const schema = buildSchema(` + enum MyEnum { + A + B + C + } + + type MyType { + f: String + bar: MyEnum + b_a_r: String + myOtherField: String + } + + type My_Type { + linkTest: MyType + } + + union MyUnion = My_Type | MyType + + interface Some_Interface { + id: ID! + } + + type Impl1 implements Some_Interface { + id: ID! + } + + type Impl_2 implements Some_Interface { + id: ID! + } + + type impl_3 implements Some_Interface { + id: ID! + } + + type Query { + something: MyUnion + use_interface: Some_Interface + } + `); + + it('Should generate correct values when using links between types - lowerCase', async () => { + const result = await plugin(schema, [], { namingConvention: 'change-case#lowerCase' }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export enum myenum { + a = 'A', + b = 'B', + c = 'C' + } + `); + expect(result).toBeSimilarStringTo(` + export type mytype = { + f?: Maybe, + bar?: Maybe, + b_a_r?: Maybe, + myOtherField?: Maybe, + }; + `); + expect(result).toBeSimilarStringTo(` + export type my_type = { + linkTest?: Maybe, + }; + `); + expect(result).toBeSimilarStringTo(` + export type myunion = my_type | mytype; + `); + expect(result).toBeSimilarStringTo(` + export type some_interface = { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type impl1 = some_interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type impl_2 = some_interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type impl_3 = some_interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type query = { + something?: Maybe, + use_interface?: Maybe, + }; + `); + + validateTs(result); + }); + + it('Should generate correct values when using links between types - pascalCase (default)', async () => { + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export enum MyEnum { + A = 'A', + B = 'B', + C = 'C' + } + `); + expect(result).toBeSimilarStringTo(` + export type MyType = { + f?: Maybe, + bar?: Maybe, + b_a_r?: Maybe, + myOtherField?: Maybe, + }; + `); + expect(result).toBeSimilarStringTo(` + export type My_Type = { + linkTest?: Maybe, + }; + `); + expect(result).toBeSimilarStringTo(` + export type MyUnion = My_Type | MyType; + `); + expect(result).toBeSimilarStringTo(` + export type Some_Interface = { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type Impl1 = Some_Interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type Impl_2 = Some_Interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type Impl_3 = Some_Interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type Query = { + something?: Maybe, + use_interface?: Maybe, + }; + `); + + validateTs(result); + }); + + it('Should generate correct values when using links between types - pascalCase (default) with custom prefix', async () => { + const result = await plugin(schema, [], { typesPrefix: 'I' }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export enum IMyEnum { + IA = 'A', + IB = 'B', + IC = 'C' + }`); + + expect(result).toBeSimilarStringTo(` + export type IMyType = { + f?: Maybe, + bar?: Maybe, + b_a_r?: Maybe, + myOtherField?: Maybe, + };`); + expect(result).toBeSimilarStringTo(` + export type IMy_Type = { + linkTest?: Maybe, + }; + `); + expect(result).toBeSimilarStringTo(`export type IMyUnion = IMy_Type | IMyType;`); + expect(result).toBeSimilarStringTo(` + export type ISome_Interface = { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type IImpl1 = ISome_Interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type IImpl_2 = ISome_Interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type IImpl_3 = ISome_Interface & { + id: string, + }; + `); + expect(result).toBeSimilarStringTo(` + export type IQuery = { + something?: Maybe, + use_interface?: Maybe, + }; + `); + + validateTs(result); + }); + }); + + describe('Arguments', () => { + it('Should generate correctly types for field arguments - with basic fields', async () => { + const schema = buildSchema(`type MyType { foo(a: String!, b: String, c: [String], d: [Int!]!): String }`); + + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyTypeFooArgs = { + a: string, + b?: Maybe, + c?: Maybe>>, + d: Array + }; + `); + + validateTs(result); + }); + + it('Should generate correctly types for field arguments - with default value', async () => { + const schema = buildSchema( + `type MyType { foo(a: String = "default", b: String! = "default", c: String): String }` + ); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyTypeFooArgs = { + a: string, + b: string, + c?: Maybe + }; + `); + + validateTs(result); + }); + + it('Should generate correctly types for field arguments - with input type', async () => { + const schema = buildSchema( + `input MyInput { f: String } type MyType { foo(a: MyInput, b: MyInput!, c: [MyInput], d: [MyInput]!, e: [MyInput!]!): String }` + ); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type MyTypeFooArgs = { + a?: Maybe, + b: MyInput, + c?: Maybe>>, + d: Array>, + e: Array + }; + `); + + validateTs(result); + }); + + it('Should add custom prefix for mutation arguments', async () => { + const schema = buildSchema( + `input Input { name: String } type Mutation { foo(id: String, input: Input): String }` + ); + const result = await plugin(schema, [], { typesPrefix: 'T' }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export type TInput = { + name: Maybe, + }; + `); + + expect(result).toBeSimilarStringTo(` + export type TMutation = { + foo?: Maybe, + }; + + export type TMutationFooArgs = { + id?: Maybe, + input?: Maybe + }; + `); + + validateTs(result); + }); + }); + + describe('Enum', () => { + it('Should build basic enum correctly', async () => { + const schema = buildSchema(`enum MyEnum { A, B, C }`); + const result = await plugin(schema, [], {}, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export enum MyEnum { + A = 'A', + B = 'B', + C = 'C' + } + `); + + validateTs(result); + }); + + it('Should build enum correctly with custom values', async () => { + const schema = buildSchema(`enum MyEnum { A, B, C }`); + const result = await plugin(schema, [], { enumValues: { A: 'SomeValue', B: 'TEST' } }, { outputFile: '' }); + + expect(result).toBeSimilarStringTo(` + export enum MyEnum { + A = 'SomeValue', + B = 'TEST', + C = 'C' + } + `); + + validateTs(result); + }); + }); + + it('should not have [object Object]', async () => { + const schema = buildSchema(/* GraphQL */ ` + type User { + id: Int! + name: String! + email: String! + } + + type QueryRoot { + allUsers: [User]! + userById(id: Int!): User + + # Generates a new answer for the guessing game + answer: [Int!]! + } + + type SubscriptionRoot { + newUser: User + } + + schema { + query: QueryRoot + subscription: SubscriptionRoot + } + `); + + const content = await plugin(schema, [], {}, { outputFile: '' }); + + expect(content).not.toContainEqual('[object Object]'); + + validateTs(content); + }); +}); diff --git a/packages/plugins/typescript/tests/validate.ts b/packages/plugins/typescript/tests/validate.ts new file mode 100644 index 00000000000..a10c2b79538 --- /dev/null +++ b/packages/plugins/typescript/tests/validate.ts @@ -0,0 +1,78 @@ +import * as ts from 'typescript'; +import * as fs from 'fs'; +import * as path from 'path'; + +export function validateTs( + contents: string, + options: ts.CompilerOptions = { + noEmitOnError: true, + noImplicitAny: true, + moduleResolution: ts.ModuleResolutionKind.NodeJs, + experimentalDecorators: true, + emitDecoratorMetadata: true, + target: ts.ScriptTarget.ES5, + typeRoots: [path.resolve(require.resolve('typescript'), '../../../@types/')], + jsx: ts.JsxEmit.Preserve, + allowJs: true, + lib: [ + path.join(path.dirname(require.resolve('typescript')), 'lib.es5.d.ts'), + path.join(path.dirname(require.resolve('typescript')), 'lib.es6.d.ts'), + path.join(path.dirname(require.resolve('typescript')), 'lib.dom.d.ts'), + path.join(path.dirname(require.resolve('typescript')), 'lib.scripthost.d.ts'), + path.join(path.dirname(require.resolve('typescript')), 'lib.es2015.d.ts'), + path.join(path.dirname(require.resolve('typescript')), 'lib.esnext.asynciterable.d.ts') + ], + module: ts.ModuleKind.ESNext + }, + isTsx = false +): void { + const testFile = `test-file.${isTsx ? 'tsx' : 'ts'}`; + const host = ts.createCompilerHost(options); + let program = ts.createProgram([testFile], options, { + ...host, + getSourceFile: ( + fileName: string, + languageVersion: ts.ScriptTarget, + onError?: (message: string) => void, + shouldCreateNewSourceFile?: boolean + ) => { + if (fileName === testFile) { + return ts.createSourceFile(fileName, contents, options.target); + } + + return host.getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile); + }, + writeFile: function(name, text, writeByteOrderMark) {}, + useCaseSensitiveFileNames: function() { + return false; + }, + getCanonicalFileName: function(filename) { + return filename; + }, + getCurrentDirectory: function() { + return ''; + }, + getNewLine: function() { + return '\n'; + } + }); + let emitResult = program.emit(); + let allDiagnostics = emitResult.diagnostics; + const errors = []; + + allDiagnostics.forEach(diagnostic => { + if (diagnostic.file) { + let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!); + let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + errors.push(`${line + 1},${character + 1}: ${message}`); + } else { + errors.push(`${ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')}`); + } + }); + + const relevantErrors = errors.filter(e => !e.includes('Cannot find module')); + + if (relevantErrors && relevantErrors.length > 0) { + throw new Error(relevantErrors.join('\n')); + } +} diff --git a/packages/plugins/typescript-common/tsconfig.json b/packages/plugins/typescript/tsconfig.json similarity index 87% rename from packages/plugins/typescript-common/tsconfig.json rename to packages/plugins/typescript/tsconfig.json index 782f215152c..79e3b8114de 100644 --- a/packages/plugins/typescript-common/tsconfig.json +++ b/packages/plugins/typescript/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", diff --git a/packages/plugins/typescript-server/.gitignore b/packages/plugins/visitor-plugin-common/.gitignore similarity index 100% rename from packages/plugins/typescript-server/.gitignore rename to packages/plugins/visitor-plugin-common/.gitignore diff --git a/packages/plugins/typescript-server/.npmignore b/packages/plugins/visitor-plugin-common/.npmignore similarity index 100% rename from packages/plugins/typescript-server/.npmignore rename to packages/plugins/visitor-plugin-common/.npmignore diff --git a/packages/plugins/visitor-plugin-common/package.json b/packages/plugins/visitor-plugin-common/package.json new file mode 100644 index 00000000000..ad516bee6dc --- /dev/null +++ b/packages/plugins/visitor-plugin-common/package.json @@ -0,0 +1,31 @@ +{ + "name": "graphql-codegen-visitor-plugin-common", + "version": "0.18.0", + "license": "MIT", + "scripts": { + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs" + }, + "dependencies": { + "tslib": "1.9.3", + "graphql-codegen-plugin-helpers": "0.18.0", + "auto-bind": "2.0.0", + "graphql-tag": "2.10.1", + "dependency-graph": "0.8.0" + }, + "peerDependencies": { + "graphql": "14.1.1" + }, + "devDependencies": { + "graphql-codegen-testing": "0.18.0", + "typescript": "3.3.3333", + "graphql": "14.1.1", + "@types/graphql": "14.0.7" + }, + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" + } +} diff --git a/packages/plugins/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/visitor-plugin-common/src/base-documents-visitor.ts new file mode 100644 index 00000000000..c271d30e517 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/base-documents-visitor.ts @@ -0,0 +1,167 @@ +import { ScalarsMap, NamingConvention, ConvertFn, ConvertOptions } from './types'; +import * as autoBind from 'auto-bind'; +import { DEFAULT_SCALARS } from './scalars'; +import { toPascalCase, DeclarationBlock, DeclarationBlockConfig } from './utils'; +import { + GraphQLSchema, + FragmentDefinitionNode, + GraphQLObjectType, + OperationDefinitionNode, + VariableDefinitionNode, + OperationTypeNode, + ASTNode +} from 'graphql'; +import { SelectionSetToObject } from './selection-set-to-object'; +import { OperationVariablesToObject } from './variables-to-object'; +import { convertFactory } from './naming'; +import { BaseVisitorConvertOptions } from './base-visitor'; + +function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) { + switch (operation) { + case 'query': + return schema.getQueryType(); + case 'mutation': + return schema.getMutationType(); + case 'subscription': + return schema.getSubscriptionType(); + } +} + +export interface ParsedDocumentsConfig { + scalars: ScalarsMap; + convert: ConvertFn; + typesPrefix: string; + addTypename: boolean; +} + +export interface RawDocumentsConfig { + scalars?: ScalarsMap; + namingConvention?: NamingConvention; + typesPrefix?: string; + skipTypename?: boolean; +} + +export class BaseDocumentsVisitor< + TRawConfig extends RawDocumentsConfig = RawDocumentsConfig, + TPluginConfig extends ParsedDocumentsConfig = ParsedDocumentsConfig +> { + protected _parsedConfig: TPluginConfig; + protected _declarationBlockConfig: DeclarationBlockConfig = {}; + protected _unnamedCounter = 1; + protected _variablesTransfomer: OperationVariablesToObject; + protected _selectionSetToObject: SelectionSetToObject; + + constructor( + rawConfig: TRawConfig, + additionalConfig: TPluginConfig, + protected _schema: GraphQLSchema, + defaultScalars: ScalarsMap = DEFAULT_SCALARS + ) { + this._parsedConfig = { + addTypename: !rawConfig.skipTypename, + scalars: { ...(defaultScalars || DEFAULT_SCALARS), ...(rawConfig.scalars || {}) }, + convert: convertFactory(rawConfig), + typesPrefix: rawConfig.typesPrefix || '', + ...((additionalConfig || {}) as any) + }; + + autoBind(this); + this._variablesTransfomer = new OperationVariablesToObject(this.scalars, this.convertName); + } + + setSelectionSetHandler(handler: SelectionSetToObject) { + this._selectionSetToObject = handler; + } + + setDeclarationBlockConfig(config: DeclarationBlockConfig): void { + this._declarationBlockConfig = config; + } + + setVariablesTransformer(variablesTransfomer: OperationVariablesToObject): void { + this._variablesTransfomer = variablesTransfomer; + } + + public convertName(node: ASTNode | string, options?: ConvertOptions & BaseVisitorConvertOptions): string { + const useTypesPrefix = options && typeof options.useTypesPrefix === 'boolean' ? options.useTypesPrefix : true; + return (useTypesPrefix ? this._parsedConfig.typesPrefix : '') + this._parsedConfig.convert(node, options); + } + + public get config(): TPluginConfig { + return this._parsedConfig; + } + + public get schema(): GraphQLSchema { + return this._schema; + } + + public get scalars(): ScalarsMap { + return this.config.scalars; + } + + public get addTypename(): boolean { + return this._parsedConfig.addTypename; + } + + private handleAnonymouseOperation(node: OperationDefinitionNode): string { + const name = node.name && node.name.value; + + if (name) { + return this.convertName(node, { + useTypesPrefix: false + }); + } + + return this.convertName(this._unnamedCounter++ + '', { + prefix: 'Unnamed_', + suffix: '_', + useTypesPrefix: false + }); + } + + FragmentDefinition(node: FragmentDefinitionNode): string { + const fragmentRootType = this._schema.getType(node.typeCondition.name.value) as GraphQLObjectType; + const selectionSet = this._selectionSetToObject.createNext(fragmentRootType, node.selectionSet); + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName( + this.convertName(node, { + useTypesPrefix: true, + suffix: 'Fragment' + }) + ) + .withContent(selectionSet.string).string; + } + + OperationDefinition(node: OperationDefinitionNode): string { + const name = this.handleAnonymouseOperation(node); + const operationRootType = getRootType(node.operation, this._schema); + const selectionSet = this._selectionSetToObject.createNext(operationRootType, node.selectionSet); + const visitedOperationVariables = this._variablesTransfomer.transform( + node.variableDefinitions + ); + + const operationResult = new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName( + this.convertName(name, { + suffix: toPascalCase(node.operation) + }) + ) + .withContent(selectionSet.string).string; + + const operationVariables = new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName( + this.convertName(name, { + suffix: toPascalCase(node.operation) + 'Variables' + }) + ) + .withBlock(visitedOperationVariables).string; + + return [operationVariables, operationResult].filter(r => r).join('\n\n'); + } +} diff --git a/packages/plugins/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/visitor-plugin-common/src/base-resolvers-visitor.ts new file mode 100644 index 00000000000..fb79716fc8e --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -0,0 +1,348 @@ +import * as autoBind from 'auto-bind'; +import { DEFAULT_SCALARS } from './scalars'; +import { ScalarsMap, NamingConvention, ConvertFn, ConvertOptions } from './types'; +import { DeclarationBlock, DeclarationBlockConfig, indent, getBaseTypeNode } from './utils'; +import { + NameNode, + ListTypeNode, + NamedTypeNode, + FieldDefinitionNode, + ObjectTypeDefinitionNode, + GraphQLSchema +} from 'graphql'; +import { + NonNullTypeNode, + UnionTypeDefinitionNode, + ScalarTypeDefinitionNode, + InterfaceTypeDefinitionNode +} from 'graphql/language/ast'; +import { DirectiveDefinitionNode, GraphQLObjectType, InputValueDefinitionNode } from 'graphql'; +import { OperationVariablesToObject } from './variables-to-object'; +import { convertFactory } from './naming'; +import { BaseVisitorConvertOptions } from './base-visitor'; + +interface ParsedMapper { + isExternal: boolean; + type: string; + source?: string; +} + +export interface ParsedResolversConfig { + scalars: ScalarsMap; + convert: ConvertFn; + typesPrefix: string; + contextType: string; + mappers: { + [typeName: string]: ParsedMapper; + }; +} + +export interface RawResolversConfig { + contextType?: string; + mappers?: { [typeName: string]: string }; + scalars?: ScalarsMap; + namingConvention?: NamingConvention; + typesPrefix?: string; +} + +export class BaseResolversVisitor< + TRawConfig extends RawResolversConfig = RawResolversConfig, + TPluginConfig extends ParsedResolversConfig = ParsedResolversConfig +> { + protected _parsedConfig: TPluginConfig; + protected _declarationBlockConfig: DeclarationBlockConfig = {}; + protected _collectedResolvers: { [key: string]: string } = {}; + protected _collectedDirectiveResolvers: { [key: string]: string } = {}; + protected _variablesTransfomer: OperationVariablesToObject; + + constructor( + rawConfig: TRawConfig, + additionalConfig: TPluginConfig, + private _schema: GraphQLSchema, + defaultScalars: ScalarsMap = DEFAULT_SCALARS + ) { + this._parsedConfig = { + scalars: { ...(defaultScalars || DEFAULT_SCALARS), ...(rawConfig.scalars || {}) }, + convert: convertFactory(rawConfig), + typesPrefix: rawConfig.typesPrefix || '', + contextType: rawConfig.contextType || 'any', + mappers: this.transformMappers(rawConfig.mappers || {}), + ...((additionalConfig || {}) as any) + }; + + autoBind(this); + this._variablesTransfomer = new OperationVariablesToObject(this.scalars, this.convertName); + } + + private isExternalMapper(value: string): boolean { + return value.includes('#'); + } + + private parseMapper(mapper: string): ParsedMapper { + if (this.isExternalMapper(mapper)) { + const [source, type] = mapper.split('#'); + return { + isExternal: true, + source, + type + }; + } + + return { + isExternal: false, + type: mapper + }; + } + + private transformMappers(rawMappers: TRawConfig['mappers']): TPluginConfig['mappers'] { + const result: TPluginConfig['mappers'] = {}; + + Object.keys(rawMappers).forEach(gqlTypeName => { + const mapperDef = rawMappers[gqlTypeName]; + const parsedMapper = this.parseMapper(mapperDef); + result[gqlTypeName] = parsedMapper; + }); + + return result; + } + + public get config(): TPluginConfig { + return this._parsedConfig; + } + + public get schema(): GraphQLSchema { + return this._schema; + } + + public get scalars(): ScalarsMap { + return this.config.scalars; + } + + public get mappersImports(): string[] { + const groupedMappers: { [sourceFile: string]: string[] } = {}; + + Object.keys(this.config.mappers) + .filter(gqlTypeName => this.config.mappers[gqlTypeName].isExternal) + .forEach(gqlTypeName => { + const mapper = this.config.mappers[gqlTypeName]; + + if (!groupedMappers[mapper.source]) { + groupedMappers[mapper.source] = []; + } + + groupedMappers[mapper.source].push(mapper.type); + }); + + return Object.keys(groupedMappers).map(source => this.buildMapperImport(source, groupedMappers[source])); + } + + protected buildMapperImport(source: string, types: string[]): string { + return `import { ${types.join(', ')} } from '${source}';`; + } + + public convertName(name: any, options?: ConvertOptions & BaseVisitorConvertOptions): string { + const useTypesPrefix = options && typeof options.useTypesPrefix === 'boolean' ? options.useTypesPrefix : true; + return (useTypesPrefix ? this.config.typesPrefix : '') + this.config.convert(name, options); + } + + setDeclarationBlockConfig(config: DeclarationBlockConfig): void { + this._declarationBlockConfig = config; + } + + setVariablesTransformer(variablesTransfomer: OperationVariablesToObject): void { + this._variablesTransfomer = variablesTransfomer; + } + + public getRootResolver(): string { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName('IResolvers'), ``) + .withBlock( + Object.keys(this._collectedResolvers) + .map(schemaTypeName => { + const resolverType = this._collectedResolvers[schemaTypeName]; + + return indent(this.formatRootResolver(schemaTypeName, resolverType)); + }) + .join('\n') + ).string; + } + + protected formatRootResolver(schemaTypeName: string, resolverType: string): string { + return `${schemaTypeName}?: ${resolverType},`; + } + + public getAllDirectiveResolvers(): string { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName('IDirectiveResolvers'), ``) + .withBlock( + Object.keys(this._collectedDirectiveResolvers) + .map(schemaTypeName => { + const resolverType = this._collectedDirectiveResolvers[schemaTypeName]; + + return indent(this.formatRootResolver(schemaTypeName, resolverType)); + }) + .join('\n') + ).string; + } + + Name(node: NameNode): string { + return node.value; + } + + ListType(node: ListTypeNode): string { + const asString = (node.type as any) as string; + + return `Array<${asString}>`; + } + + NamedType(node: NamedTypeNode): string { + const type = this.config.scalars[(node.name as any) as string] || this.convertName(node); + + return `${type}`; + } + + NonNullType(node: NonNullTypeNode): string { + const asString = (node.type as any) as string; + + return asString; + } + + FieldDefinition(node: FieldDefinitionNode, key: string | number, parent: any) { + const hasArguments = node.arguments && node.arguments.length > 0; + + return (parentName: string) => { + const original = parent[key]; + const realType = getBaseTypeNode(original.type).name.value; + const mappedType = this.config.mappers[realType] + ? this._variablesTransfomer.wrapAstTypeWithModifiers(this.config.mappers[realType].type, original.type) + : node.type; + const subscriptionType = this._schema.getSubscriptionType(); + const isSubscriptionType = subscriptionType && subscriptionType.name === parentName; + + return indent( + `${node.name}?: ${isSubscriptionType ? 'SubscriptionResolver' : 'Resolver'}<${mappedType}, ParentType, Context${ + hasArguments + ? `, ${this.convertName(parentName, { + useTypesPrefix: true + }) + + this.convertName(node.name, { + useTypesPrefix: false + }) + + 'Args'}` + : '' + }>,` + ); + }; + } + + ObjectTypeDefinition(node: ObjectTypeDefinitionNode) { + const name = this.convertName(node, { + suffix: 'Resolvers' + }); + let type: string = null; + + if (this.config.mappers[node.name as any]) { + type = this.config.mappers[node.name as any].type; + } else { + type = this.config.scalars[node.name as any] || this.convertName(node); + } + + const block = new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('interface') + .withName(name, ``) + .withBlock(node.fields.map((f: any) => f(node.name)).join('\n')); + + this._collectedResolvers[node.name as any] = name + ''; + + return block.string; + } + + UnionTypeDefinition(node: UnionTypeDefinitionNode, key: string | number, parent: any): string { + const name = this.convertName(node, { + suffix: 'Resolvers' + }); + const originalNode = parent[key] as UnionTypeDefinitionNode; + const possibleTypes = originalNode.types + .map(node => this.convertName(node)) + .map(f => `'${f}'`) + .join(' | '); + + this._collectedResolvers[node.name as any] = name; + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('interface') + .withName(name, ``) + .withBlock(indent(`__resolveType: TypeResolveFn<${possibleTypes}>`)).string; + } + + ScalarTypeDefinition(node: ScalarTypeDefinitionNode): string { + const baseName = this.convertName(node); + + this._collectedResolvers[node.name as any] = 'GraphQLScalarType'; + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('interface') + .withName( + this.convertName(node, { + suffix: 'ScalarConfig' + }), + ` extends GraphQLScalarTypeConfig<${baseName}, any>` + ) + .withBlock(indent(`name: '${node.name}'`)).string; + } + + DirectiveDefinition(node: DirectiveDefinitionNode): string { + const directiveName = this.convertName(node, { + suffix: 'DirectiveResolver' + }); + const hasArguments = node.arguments && node.arguments.length > 0; + const directiveArgs = hasArguments + ? this._variablesTransfomer.transform(node.arguments) + : ''; + + this._collectedDirectiveResolvers[node.name as any] = directiveName + ''; + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(directiveName, ``) + .withContent(`DirectiveResolverFn`).string; + } + + InterfaceTypeDefinition(node: InterfaceTypeDefinitionNode): string { + const name = this.convertName(node, { + suffix: 'Resolvers' + }); + const allTypesMap = this._schema.getTypeMap(); + const implementingTypes: string[] = []; + + this._collectedResolvers[node.name as any] = name; + + for (const graphqlType of Object.values(allTypesMap)) { + if (graphqlType instanceof GraphQLObjectType) { + const allInterfaces = graphqlType.getInterfaces(); + if (allInterfaces.find(int => int.name === ((node.name as any) as string))) { + implementingTypes.push(graphqlType.name); + } + } + } + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('interface') + .withName(name, ``) + .withBlock(indent(`__resolveType: TypeResolveFn<${implementingTypes.map(name => `'${name}'`).join(' | ')}>`)) + .string; + } + + SchemaDefinition() { + return null; + } +} diff --git a/packages/plugins/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/visitor-plugin-common/src/base-types-visitor.ts new file mode 100644 index 00000000000..ddbe3a24d58 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/base-types-visitor.ts @@ -0,0 +1,195 @@ +import { BaseVisitor, ParsedConfig, RawConfig } from './base-visitor'; +import { EnumValuesMap, ScalarsMap } from './types'; +import { OperationVariablesToObject } from './variables-to-object'; +import { DeclarationBlockConfig, DeclarationBlock, indent, wrapWithSingleQuotes } from './utils'; +import { + NonNullTypeNode, + UnionTypeDefinitionNode, + InterfaceTypeDefinitionNode, + ScalarTypeDefinitionNode, + EnumValueDefinitionNode, + NamedTypeNode +} from 'graphql/language/ast'; +import { + InputObjectTypeDefinitionNode, + InputValueDefinitionNode, + NameNode, + FieldDefinitionNode, + ObjectTypeDefinitionNode, + EnumTypeDefinitionNode, + DirectiveDefinitionNode, + ListTypeNode +} from 'graphql'; +import { DEFAULT_SCALARS } from './scalars'; +import { ASTNode } from 'graphql'; + +export interface ParsedTypesConfig extends ParsedConfig { + enumValues: EnumValuesMap; +} + +export interface RawTypesConfig extends RawConfig { + enumValues?: EnumValuesMap; +} + +export class BaseTypesVisitor< + TRawConfig extends RawTypesConfig = RawTypesConfig, + TPluginConfig extends ParsedTypesConfig = ParsedTypesConfig +> extends BaseVisitor { + protected _argumentsTransformer: OperationVariablesToObject; + + constructor(rawConfig: TRawConfig, additionalConfig: TPluginConfig, defaultScalars: ScalarsMap = DEFAULT_SCALARS) { + super( + rawConfig, + { + enumValues: rawConfig.enumValues || {}, + ...additionalConfig + }, + defaultScalars + ); + + this._argumentsTransformer = new OperationVariablesToObject(this.scalars, this.convertName); + } + + setDeclarationBlockConfig(config: DeclarationBlockConfig): void { + this._declarationBlockConfig = config; + } + + setArgumentsTransformer(argumentsTransfomer: OperationVariablesToObject): void { + this._argumentsTransformer = argumentsTransfomer; + } + + NonNullType(node: NonNullTypeNode): string { + const asString = (node.type as any) as string; + + return asString; + } + + InputObjectTypeDefinition(node: InputObjectTypeDefinitionNode): string { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node)) + .withBlock(node.fields.join('\n')).string; + } + + InputValueDefinition(node: InputValueDefinitionNode): string { + return indent(`${node.name}: ${node.type},`); + } + + Name(node: NameNode): string { + return node.value; + } + + FieldDefinition(node: FieldDefinitionNode): string { + const typeString = (node.type as any) as string; + + return indent(`${node.name}: ${typeString},`); + } + + UnionTypeDefinition(node: UnionTypeDefinitionNode, key: string | number, parent: any): string { + const originalNode = parent[key] as UnionTypeDefinitionNode; + const possibleTypes = originalNode.types.map(t => this.convertName(t)).join(' | '); + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node)) + .withContent(possibleTypes).string; + } + + ObjectTypeDefinition(node: ObjectTypeDefinitionNode, key: number | string, parent: any): string { + const originalNode = parent[key] as ObjectTypeDefinitionNode; + const interfaces = + originalNode.interfaces && node.interfaces.length > 0 + ? originalNode.interfaces.map(i => this.convertName(i)).join(' & ') + ' & ' + : ''; + + const typeDefinition = new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node)) + .withContent(interfaces) + .withBlock(node.fields.join('\n')).string; + + const original = parent[key]; + const fieldsWithArguments = original.fields.filter(field => field.arguments && field.arguments.length > 0); + const fieldsArguments = fieldsWithArguments.map(field => { + const name = + original.name.value + + this.convertName(field, { + useTypesPrefix: false + }) + + 'Args'; + + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(name)) + .withBlock(this._argumentsTransformer.transform(field.arguments)).string; + }); + + return [typeDefinition, ...fieldsArguments].filter(f => f).join('\n\n'); + } + + InterfaceTypeDefinition(node: InterfaceTypeDefinitionNode): string { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node)) + .withBlock(node.fields.join('\n')).string; + } + + ScalarTypeDefinition(node: ScalarTypeDefinitionNode): string { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(this.convertName(node)) + .withContent(this.config.scalars[node.name as any] || 'any').string; + } + + EnumTypeDefinition(node: EnumTypeDefinitionNode): string { + return new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('enum') + .withName(this.convertName(node)) + .withBlock(this.buildEnumValuesBlock(node.values)).string; + } + + protected buildEnumValuesBlock(values: ReadonlyArray): string { + return values + .map(enumOption => + indent( + `${this.convertName(enumOption)}${this._declarationBlockConfig.enumNameValueSeparator} ${wrapWithSingleQuotes( + this.config.enumValues[(enumOption.name as any) as string] || enumOption.name + )}` + ) + ) + .join(',\n'); + } + + DirectiveDefinition(node: DirectiveDefinitionNode): string { + return ''; + } + + protected _getTypeForNode(node: NamedTypeNode): string { + return this.scalars[(node.name as any) as string] || this.convertName(node); + } + + NamedType(node: NamedTypeNode): string { + return this._getTypeForNode(node); + } + + ListType(node: ListTypeNode): string { + const asString = (node.type as any) as string; + + return this.wrapWithListType(asString); + } + + SchemaDefinition() { + return null; + } + + protected wrapWithListType(str: string): string { + return `Array<${str}>`; + } +} diff --git a/packages/plugins/visitor-plugin-common/src/base-visitor.ts b/packages/plugins/visitor-plugin-common/src/base-visitor.ts new file mode 100644 index 00000000000..2e804217ca4 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/base-visitor.ts @@ -0,0 +1,52 @@ +import { ScalarsMap, NamingConvention, ConvertFn, ConvertOptions } from './types'; +import { DeclarationBlockConfig } from './utils'; +import * as autoBind from 'auto-bind'; +import { DEFAULT_SCALARS } from './scalars'; +import { convertFactory } from './naming'; +import { ASTNode } from 'graphql'; + +export interface BaseVisitorConvertOptions { + useTypesPrefix?: boolean; +} + +export interface ParsedConfig { + scalars: ScalarsMap; + convert: ConvertFn; + typesPrefix: string; +} + +export interface RawConfig { + scalars?: ScalarsMap; + namingConvention?: NamingConvention; + typesPrefix?: string; +} + +export class BaseVisitor { + protected _parsedConfig: TPluginConfig; + protected _declarationBlockConfig: DeclarationBlockConfig = {}; + + constructor(rawConfig: TRawConfig, additionalConfig: TPluginConfig, defaultScalars: ScalarsMap = DEFAULT_SCALARS) { + this._parsedConfig = { + scalars: { ...(defaultScalars || DEFAULT_SCALARS), ...(rawConfig.scalars || {}) }, + convert: convertFactory(rawConfig), + typesPrefix: rawConfig.typesPrefix || '', + ...((additionalConfig || {}) as any) + }; + + autoBind(this); + } + + get config(): TPluginConfig { + return this._parsedConfig; + } + + get scalars(): ScalarsMap { + return this.config.scalars; + } + + protected convertName(node: ASTNode | string, options?: BaseVisitorConvertOptions & ConvertOptions): string { + const useTypesPrefix = typeof (options && options.useTypesPrefix) === 'boolean' ? options.useTypesPrefix : true; + + return (useTypesPrefix ? this.config.typesPrefix : '') + this.config.convert(node, options); + } +} diff --git a/packages/plugins/visitor-plugin-common/src/client-side-base-visitor.ts b/packages/plugins/visitor-plugin-common/src/client-side-base-visitor.ts new file mode 100644 index 00000000000..c2cbfc5306e --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/client-side-base-visitor.ts @@ -0,0 +1,182 @@ +import { BaseVisitor, ParsedConfig, RawConfig } from './index'; +import * as autoBind from 'auto-bind'; +import { FragmentDefinitionNode, print, OperationDefinitionNode } from 'graphql'; +import { DepGraph } from 'dependency-graph'; +import gqlTag from 'graphql-tag'; +import { toPascalCase } from 'graphql-codegen-plugin-helpers'; +import { getConfigValue } from './utils'; + +export interface RawClientSideBasePluginConfig extends RawConfig { + noGraphQLTag?: boolean; + gqlImport?: string; +} + +export interface ClientSideBasePluginConfig extends ParsedConfig { + noGraphQLTag: boolean; + gqlImport: string; +} + +export class ClientSideBaseVisitor< + TRawConfig extends RawClientSideBasePluginConfig = RawClientSideBasePluginConfig, + TPluginConfig extends ClientSideBasePluginConfig = ClientSideBasePluginConfig +> extends BaseVisitor { + constructor( + protected _fragments: FragmentDefinitionNode[], + rawConfig: TRawConfig, + additionalConfig: Partial + ) { + super(rawConfig, { + noGraphQLTag: getConfigValue(rawConfig.noGraphQLTag, false), + gqlImport: rawConfig.gqlImport || null, + ...additionalConfig + } as any); + + autoBind(this); + } + + protected _getFragmentName(fragment: FragmentDefinitionNode | string): string { + return (typeof fragment === 'string' ? fragment : fragment.name.value) + 'FragmentDoc'; + } + + protected _extractFragments(document: FragmentDefinitionNode | OperationDefinitionNode): string[] | undefined { + return (print(document).match(/\.\.\.[a-z0-9\_]+/gi) || []).map(name => name.replace('...', '')); + } + + protected _transformFragments(document: FragmentDefinitionNode | OperationDefinitionNode): string[] | undefined { + return this._extractFragments(document).map(document => this._getFragmentName(document)); + } + + protected _includeFragments(fragments: string[]): string { + if (fragments) { + return `${fragments + .filter((name, i, all) => all.indexOf(name) === i) + .map(name => '${' + name + '}') + .join('\n')}`; + } + + return ''; + } + + protected _prepareDocument(documentStr: string): string { + return documentStr; + } + + protected _gql(node: FragmentDefinitionNode | OperationDefinitionNode): string { + const doc = this._prepareDocument(` + ${print(node)} + ${this._includeFragments(this._transformFragments(node))}`); + + if (this.config.noGraphQLTag) { + return JSON.stringify(gqlTag(doc)); + } + + return 'gql`' + doc + '`'; + } + + protected _generateFragment(fragmentDocument: FragmentDefinitionNode): string | void { + const name = this._getFragmentName(fragmentDocument); + + return `export const ${name}${this.config.noGraphQLTag ? ': DocumentNode' : ''} = ${this._gql(fragmentDocument)};`; + } + + public get fragments(): string { + if (this._fragments.length === 0) { + return ''; + } + + const graph = new DepGraph({ circular: true }); + + for (const fragment of this._fragments) { + if (graph.hasNode(fragment.name.value)) { + const cachedAsString = print(graph.getNodeData(fragment.name.value)); + const asString = print(fragment); + + if (cachedAsString !== asString) { + throw new Error(`Duplicated fragment called '${fragment.name}'!`); + } + } + + graph.addNode(fragment.name.value, fragment); + } + + this._fragments.forEach(fragment => { + const depends = this._extractFragments(fragment); + + if (depends) { + depends.forEach(name => { + graph.addDependency(fragment.name.value, name); + }); + } + }); + + return graph + .overallOrder() + .map(name => this._generateFragment(graph.getNodeData(name))) + .join('\n'); + } + + protected _parseImport(importStr: string) { + const [moduleName, propName] = importStr.split('#'); + + return { + moduleName, + propName + }; + } + + public getImports(): string { + const gqlImport = this._parseImport(this.config.gqlImport || 'graphql-tag'); + let imports = []; + + if (!this.config.noGraphQLTag) { + imports.push(` +import ${ + gqlImport.propName ? `{ ${gqlImport.propName === 'gql' ? 'gql' : `${gqlImport.propName} as gql`} }` : 'gql' + } from '${gqlImport.moduleName}';`); + } else { + imports.push(`import { DocumentNode } from 'graphql';`); + } + + return imports.join('\n'); + } + + protected buildOperation( + node: OperationDefinitionNode, + documentVariableName: string, + operationType: string, + operationResultType: string, + operationVariablesTypes: string + ): string { + return null; + } + + public OperationDefinition(node: OperationDefinitionNode): string { + if (!node.name || !node.name.value) { + return null; + } + + const documentVariableName = this.convertName(node, { + suffix: 'Document' + }); + const documentString = `export const ${documentVariableName}${ + this.config.noGraphQLTag ? ': DocumentNode' : '' + } = ${this._gql(node)};`; + const operationType: string = toPascalCase(node.operation); + const operationResultType: string = this.convertName(node, { + suffix: operationType + }); + const operationVariablesTypes: string = this.convertName(node, { + suffix: operationType + 'Variables' + }); + + const additional = this.buildOperation( + node, + documentVariableName, + operationType, + operationResultType, + operationVariablesTypes + ); + + return [documentString, additional].filter(a => a).join('\n'); + } +} diff --git a/packages/plugins/visitor-plugin-common/src/index.ts b/packages/plugins/visitor-plugin-common/src/index.ts new file mode 100644 index 00000000000..ccf7d419634 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/index.ts @@ -0,0 +1,12 @@ +export * from './types'; +export * from './utils'; +export * from './scalars'; + +export * from './base-visitor'; +export * from './base-types-visitor'; +export * from './base-documents-visitor'; +export * from './base-resolvers-visitor'; +export * from './client-side-base-visitor'; + +export * from './variables-to-object'; +export * from './selection-set-to-object'; diff --git a/packages/plugins/visitor-plugin-common/src/naming.ts b/packages/plugins/visitor-plugin-common/src/naming.ts new file mode 100644 index 00000000000..49556bd1f59 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/naming.ts @@ -0,0 +1,88 @@ +import { ASTNode } from 'graphql'; +import { resolveExternalModuleAndFn } from 'graphql-codegen-plugin-helpers'; +import { NamingConventionMap, NamingConvention, ConvertFn } from './types'; +import { toPascalCase } from './utils'; + +function getKind(node: ASTNode | string): keyof NamingConventionMap { + if (typeof node === 'string') { + return 'typeNames'; + } + + if (['EnumValueDefinition', 'EnumValue'].includes(node.kind)) { + return 'enumValues'; + } + + return 'typeNames'; +} + +function getName(node: ASTNode | string): string | undefined { + if (typeof node === 'string') { + return node; + } + + switch (node.kind) { + case 'OperationDefinition': + case 'Variable': + case 'Argument': + case 'FragmentSpread': + case 'FragmentDefinition': + case 'ObjectField': + case 'Directive': + case 'NamedType': + case 'ScalarTypeDefinition': + case 'ObjectTypeDefinition': + case 'FieldDefinition': + case 'InputValueDefinition': + case 'InterfaceTypeDefinition': + case 'UnionTypeDefinition': + case 'EnumTypeDefinition': + case 'EnumValueDefinition': + case 'InputObjectTypeDefinition': + case 'DirectiveDefinition': { + return getName(node.name); + } + case 'Name': { + return node.value; + } + case 'Field': { + return getName(node.alias || node.name); + } + case 'VariableDefinition': { + return getName(node.variable); + } + } + + return undefined; +} + +export function convertFactory(config: { namingConvention?: NamingConvention }): ConvertFn { + function resolveConventionName(type: keyof NamingConventionMap): (str: string) => string { + if (!config.namingConvention) { + return toPascalCase; + } + + if (typeof config.namingConvention === 'string') { + return resolveExternalModuleAndFn(config.namingConvention); + } + + if (config.namingConvention[type] === 'keep') { + return str => str; + } + + if (typeof config.namingConvention[type] === 'string') { + return resolveExternalModuleAndFn(config.namingConvention[type]); + } + + return config.namingConvention[type] as any; + } + + return (node, opts) => { + const prefix = opts && opts.prefix; + const suffix = opts && opts.suffix; + + const kind = getKind(node); + const str = [prefix || '', getName(node), suffix || ''].join(''); + + return resolveConventionName(kind)(str); + }; +} diff --git a/packages/plugins/visitor-plugin-common/src/scalars.ts b/packages/plugins/visitor-plugin-common/src/scalars.ts new file mode 100644 index 00000000000..1baa12cc14c --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/scalars.ts @@ -0,0 +1,10 @@ +export const DEFAULT_SCALARS = { + ID: 'string', + String: 'string', + Boolean: 'boolean', + Int: 'number', + Float: 'number', + string: 'string', + number: 'number', + boolean: 'boolean' +}; diff --git a/packages/plugins/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/visitor-plugin-common/src/selection-set-to-object.ts new file mode 100644 index 00000000000..f34e4ae1656 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/selection-set-to-object.ts @@ -0,0 +1,242 @@ +import { + SelectionSetNode, + Kind, + FieldNode, + FragmentSpreadNode, + InlineFragmentNode, + GraphQLNamedType, + isObjectType, + isUnionType, + isInterfaceType, + isEnumType, + GraphQLSchema, + isEqualType, + GraphQLField, + SchemaMetaFieldDef, + TypeMetaFieldDef +} from 'graphql'; +import { getBaseType, quoteIfNeeded } from './utils'; +import { ScalarsMap, ConvertNameFn } from './types'; +import { GraphQLObjectType, GraphQLNonNull, GraphQLList, isNonNullType, isListType } from 'graphql'; +import { BaseVisitorConvertOptions } from './base-visitor'; + +export type PrimitiveField = string; +export type PrimitiveAliasedFields = { alias: string; fieldName: string }; +export type LinkField = { alias: string; name: string; type: string; selectionSet: string }; +export type FragmentSpreadField = string; +export type InlineFragmentField = { [onType: string]: string[] }; + +function isMetadataFieldName(name: string) { + return ['__schema', '__type'].includes(name); +} + +function isRootType(type: GraphQLNamedType, schema: GraphQLSchema): type is GraphQLObjectType { + return ( + isEqualType(type, schema.getQueryType()) || + isEqualType(type, schema.getMutationType()) || + isEqualType(type, schema.getSubscriptionType()) + ); +} + +const metadataFieldMap: Record> = { + __schema: SchemaMetaFieldDef, + __type: TypeMetaFieldDef +}; + +export class SelectionSetToObject { + protected _primitiveFields: PrimitiveField[] = []; + protected _primitiveAliasedFields: PrimitiveAliasedFields[] = []; + protected _linksFields: LinkField[] = []; + protected _fragmentSpreads: FragmentSpreadField[] = []; + protected _inlineFragments: InlineFragmentField = {}; + protected _queriedForTypename = false; + + constructor( + protected _scalars: ScalarsMap, + protected _schema: GraphQLSchema, + protected _convertName: ConvertNameFn, + protected _addTypename: boolean, + protected _parentSchemaType?: GraphQLNamedType, + protected _selectionSet?: SelectionSetNode + ) {} + + public createNext(parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode): SelectionSetToObject { + throw new Error(`You must override createNext in your SelectionSetToObject implementation!`); + } + + protected wrapTypeWithModifiers( + baseType: string, + type: GraphQLObjectType | GraphQLNonNull | GraphQLList + ): string { + throw new Error(`You must override wrapTypeWithModifiers in your SelectionSetToObject implementation!`); + } + + _collectField(field: FieldNode) { + if (field.name.value === '__typename') { + this._queriedForTypename = true; + + return; + } + + if (isObjectType(this._parentSchemaType) || isInterfaceType(this._parentSchemaType)) { + let schemaField: GraphQLField; + + if (isRootType(this._parentSchemaType, this._schema) && isMetadataFieldName(field.name.value)) { + schemaField = metadataFieldMap[field.name.value]; + } else { + schemaField = this._parentSchemaType.getFields()[field.name.value]; + } + + const rawType = schemaField.type as any; + const baseType = getBaseType(rawType); + const typeName = baseType.name; + + if (this._scalars[typeName] || isEnumType(baseType)) { + if (field.alias && field.alias.value) { + this._primitiveAliasedFields.push({ + fieldName: field.name.value, + alias: field.alias.value + }); + } else { + this._primitiveFields.push(field.name.value); + } + } else { + const selectionSetToObject = this.createNext(baseType, field.selectionSet); + + this._linksFields.push({ + alias: field.alias ? field.alias.value : null, + name: field.name.value, + type: typeName, + selectionSet: this.wrapTypeWithModifiers(selectionSetToObject.string, rawType) + }); + } + } + } + + _collectFragmentSpread(node: FragmentSpreadNode) { + this._fragmentSpreads.push(node.name.value); + } + + _collectInlineFragment(node: InlineFragmentNode) { + const onType = node.typeCondition.name.value; + const schemaType = this._schema.getType(onType); + const selectionSet = this.createNext(schemaType, node.selectionSet); + + if (!this._inlineFragments[onType]) { + this._inlineFragments[onType] = []; + } + + this._inlineFragments[onType].push(selectionSet.string); + } + + get string(): string { + if (!this._selectionSet || !this._selectionSet.selections || this._selectionSet.selections.length === 0) { + return ''; + } + + const { selections } = this._selectionSet; + + for (const selection of selections) { + switch (selection.kind) { + case Kind.FIELD: + this._collectField(selection as FieldNode); + break; + case Kind.FRAGMENT_SPREAD: + this._collectFragmentSpread(selection as FragmentSpreadNode); + break; + case Kind.INLINE_FRAGMENT: + this._collectInlineFragment(selection as InlineFragmentNode); + break; + } + } + + const parentName = this._convertName(this._parentSchemaType.name, { + useTypesPrefix: true + }); + const typeName = this._addTypename || this._queriedForTypename ? this.buildTypeNameField() : null; + const baseFields = this.buildPrimitiveFields(parentName, this._primitiveFields); + const aliasBaseFields = this.buildAliasedPrimitiveFields(parentName, this._primitiveAliasedFields); + const linksFields = this.buildLinkFields(this._linksFields); + const inlineFragments = this.buildInlineFragments(this._inlineFragments); + const fragmentSpreads = this.buildFragmentSpread(this._fragmentSpreads); + const fieldsSet = [typeName, baseFields, aliasBaseFields, linksFields, fragmentSpreads, inlineFragments].filter( + f => f && f !== '' + ); + + return this.mergeAllFields(fieldsSet); + } + + protected mergeAllFields(fieldsSet: Array): string { + return quoteIfNeeded(fieldsSet, ' & '); + } + + protected buildTypeNameField(): string | null { + const possibleTypes = []; + + if (!isUnionType(this._parentSchemaType) && !isInterfaceType(this._parentSchemaType)) { + possibleTypes.push(this._parentSchemaType.name); + } + + if (possibleTypes.length === 0) { + return null; + } + + return `{ ${this.formatNamedField('__typename')}${this._queriedForTypename ? '' : '?'}: ${possibleTypes + .map(t => `'${t}'`) + .join(' | ')} }`; + } + + protected buildPrimitiveFields(parentName: string, fields: PrimitiveField[]): string | null { + if (fields.length === 0) { + return null; + } + + return `Pick<${parentName}, ${fields.map(field => `'${field}'`).join(' | ')}>`; + } + + protected buildAliasedPrimitiveFields(parentName: string, fields: PrimitiveAliasedFields[]): string | null { + if (fields.length === 0) { + return null; + } + + return `{ ${fields + .map(aliasedField => `${this.formatNamedField(aliasedField.alias)}: ${parentName}['${aliasedField.fieldName}']`) + .join(', ')} }`; + } + + protected formatNamedField(name: string): string { + return name; + } + + protected buildLinkFields(fields: LinkField[]): string | null { + if (fields.length === 0) { + return null; + } + + return `{ ${fields + .map(field => `${this.formatNamedField(field.alias || field.name)}: ${field.selectionSet}`) + .join(', ')} }`; + } + + protected buildInlineFragments(inlineFragments: InlineFragmentField): string | null { + const allPossibleTypes = Object.keys(inlineFragments).map(typeName => inlineFragments[typeName].join(' & ')); + + return allPossibleTypes.length === 0 ? null : `(${allPossibleTypes.join(' | ')})`; + } + + protected buildFragmentSpread(fragmentsSpread: FragmentSpreadField[]): string | null { + if (fragmentsSpread.length === 0) { + return null; + } + + return quoteIfNeeded( + fragmentsSpread.map(fragmentName => + this._convertName(fragmentName, { + suffix: 'Fragment', + useTypesPrefix: true + }) + ), + ' & ' + ); + } +} diff --git a/packages/plugins/visitor-plugin-common/src/types.ts b/packages/plugins/visitor-plugin-common/src/types.ts new file mode 100644 index 00000000000..53a0e56cf1a --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/types.ts @@ -0,0 +1,17 @@ +import { ASTNode } from 'graphql'; + +export type ScalarsMap = { [name: string]: string }; +export type EnumValuesMap = { [key: string]: string }; +export type ConvertNameFn = ConvertFn; + +export interface ConvertOptions { + prefix?: string; + suffix?: string; +} +export type ConvertFn = (node: ASTNode | string, options?: ConvertOptions & T) => string; +export type NamingConventionResolvePath = string; // module-name#exportedFunction +export type NamingConvention = string | NamingConventionMap; +export interface NamingConventionMap { + enumValues?: 'keep' | NamingConventionResolvePath | Function; + typeNames?: 'keep' | NamingConventionResolvePath | Function; +} diff --git a/packages/plugins/flow/src/utils.ts b/packages/plugins/visitor-plugin-common/src/utils.ts similarity index 59% rename from packages/plugins/flow/src/utils.ts rename to packages/plugins/visitor-plugin-common/src/utils.ts index 9e75573f290..568bdb20dbe 100644 --- a/packages/plugins/flow/src/utils.ts +++ b/packages/plugins/visitor-plugin-common/src/utils.ts @@ -8,9 +8,40 @@ import { GraphQLObjectType, GraphQLNonNull, GraphQLList, - isListType + isListType, + GraphQLOutputType, + GraphQLNamedType } from 'graphql'; -import { FlowPluginConfig } from './index'; + +function isWrapperType(t: GraphQLOutputType): t is GraphQLNonNull | GraphQLList { + return isListType(t) || isNonNullType(t); +} + +export const getConfigValue = (value: T, defaultValue: T): T => { + if (value === null || value === undefined) { + return defaultValue; + } + + return value; +}; + +export function getBaseType(type: GraphQLOutputType): GraphQLNamedType { + if (isWrapperType(type)) { + return getBaseType(type.ofType); + } else { + return type; + } +} + +export function quoteIfNeeded(array: string[], joinWith = ' & '): string { + if (array.length === 0) { + return ''; + } else if (array.length === 1) { + return array[0]; + } else { + return `(${array.join(joinWith)})`; + } +} export function block(array) { return array && array.length !== 0 ? '{\n' + array.join('\n') + '\n}' : ''; @@ -24,8 +55,13 @@ export function breakLine(str: string): string { return str + '\n'; } -export function indent(str: string): string { - return ' ' + str; +export function indent(str: string, count = 1): string { + return new Array(count).fill(' ').join('') + str; +} + +export interface DeclarationBlockConfig { + blockWrapper?: string; + enumNameValueSeparator?: string; } export class DeclarationBlock { @@ -36,10 +72,13 @@ export class DeclarationBlock { _content = null; _block = null; _nameGenerics = null; - _config = null; - constructor(config: FlowPluginConfig) { - this._config = config; + constructor(private _config: DeclarationBlockConfig) { + this._config = { + blockWrapper: '', + enumNameValueSeparator: ':', + ...this._config + }; } export(exp = true): DeclarationBlock { @@ -79,24 +118,7 @@ export class DeclarationBlock { return this; } - getFlowReadOnlyTypeBlock(): string { - return ( - (this._block && - this._block - .split('\n') - .map((item: string): string => `${' '.repeat(item.search(/\S|$/))}+${item.substr(item.search(/\S|$/))}`) - .join('\n')) || - '' - ); - } - public get string(): string { - const useFlowExactObject: boolean = this._config.useFlowExactObjects || false; - const useFlowReadOnlyTypes: boolean = this._config.useFlowReadOnlyTypes || false; - const block: string = - this._block && useFlowReadOnlyTypes && this._methodName !== 'Object.freeze' - ? this.getFlowReadOnlyTypeBlock() - : this._block; let result = ''; if (this._export) { @@ -118,19 +140,19 @@ export class DeclarationBlock { result += this._kind + ' ' + name + extra; } - if (block) { + if (this._block) { if (this._content) { result += this._content; } if (this._methodName) { - result += `${this._methodName}({ -${block} -})`; + result += `${this._methodName}({${this._config.blockWrapper} +${this._block} +${this._config.blockWrapper}})`; } else { - result += `{${useFlowExactObject ? '|' : ''} -${block} -${useFlowExactObject ? '|' : ''}}`; + result += `{${this._config.blockWrapper} +${this._block} +${this._config.blockWrapper}}`; } } else if (this._content) { result += this._content; @@ -138,7 +160,7 @@ ${useFlowExactObject ? '|' : ''}}`; result += '{}'; } - return result + (this._kind === 'interface' ? '' : ';') + '\n'; + return result + (this._kind === 'interface' || this._kind === 'enum' ? '' : ';') + '\n'; } } @@ -150,36 +172,24 @@ export function getBaseTypeNode(typeNode: TypeNode): NamedTypeNode { return typeNode; } -export function wrapAstTypeWithModifiers(baseType: string, typeNode: TypeNode): string { - if (typeNode.kind === Kind.NON_NULL_TYPE) { - return wrapAstTypeWithModifiers(baseType, typeNode.type).substr(1); - } else if (typeNode.kind === Kind.LIST_TYPE) { - const innerType = wrapAstTypeWithModifiers(baseType, typeNode.type); - - return `?Array<${innerType}>`; - } else { - return `?${baseType}`; - } +export function toPascalCase(str: string) { + return str + .split('_') + .map(s => pascalCase(s)) + .join('_'); } -export function wrapTypeWithModifiers( +export const wrapTypeWithModifiers = (prefix = '') => ( baseType: string, type: GraphQLObjectType | GraphQLNonNull | GraphQLList -): string { +): string => { if (isNonNullType(type)) { - return wrapTypeWithModifiers(baseType, type.ofType).substr(1); + return wrapTypeWithModifiers(prefix)(baseType, type.ofType).substr(1); } else if (isListType(type)) { - const innerType = wrapTypeWithModifiers(baseType, type.ofType); + const innerType = wrapTypeWithModifiers(prefix)(baseType, type.ofType); - return `?Array<${innerType}>`; + return `${prefix}Array<${innerType}>`; } else { - return `?${baseType}`; + return `${prefix}${baseType}`; } -} - -export function toPascalCase(str: string) { - return str - .split('_') - .map(s => pascalCase(s)) - .join('_'); -} +}; diff --git a/packages/plugins/visitor-plugin-common/src/variables-to-object.ts b/packages/plugins/visitor-plugin-common/src/variables-to-object.ts new file mode 100644 index 00000000000..25e6ac700d4 --- /dev/null +++ b/packages/plugins/visitor-plugin-common/src/variables-to-object.ts @@ -0,0 +1,73 @@ +import { Kind, TypeNode, VariableNode, NameNode, ValueNode } from 'graphql'; +import { indent, getBaseTypeNode } from './utils'; +import { ScalarsMap, ConvertNameFn } from './types'; +import { BaseVisitorConvertOptions } from './base-visitor'; +import * as autoBind from 'auto-bind'; + +export interface InterfaceOrVariable { + name?: NameNode; + variable?: VariableNode; + type: TypeNode; + defaultValue?: ValueNode; +} + +export class OperationVariablesToObject { + constructor(protected _scalars: ScalarsMap, protected _convertName: ConvertNameFn) { + autoBind(this); + } + + getName(node: TDefinitionType): string { + if (node.name) { + if (typeof node.name === 'string') { + return node.name; + } + + return node.name.value; + } else if (node.variable) { + return node.variable.name.value; + } + + return null; + } + + transform(variablesNode: ReadonlyArray): string { + if (!variablesNode || variablesNode.length === 0) { + return null; + } + + return variablesNode.map(variable => indent(this.transformVariable(variable))).join(',\n'); + } + + protected transformVariable(variable: TDefinitionType): string { + const baseType = typeof variable.type === 'string' ? variable.type : getBaseTypeNode(variable.type); + const typeName = typeof baseType === 'string' ? baseType : baseType.name.value; + const typeValue = + this._scalars[typeName] || + this._convertName(baseType, { + useTypesPrefix: true + }); + + const fieldName = this.getName(variable); + const fieldType = this.wrapAstTypeWithModifiers(typeValue, variable.type); + + const hasDefaultValue = variable.defaultValue != null && typeof variable.defaultValue !== 'undefined'; + const isNonNullType = variable.type.kind === Kind.NON_NULL_TYPE; + + const formattedFieldString = this.formatFieldString(fieldName, isNonNullType, hasDefaultValue); + const formattedTypeString = this.formatTypeString(fieldType, isNonNullType, hasDefaultValue); + + return `${formattedFieldString}: ${formattedTypeString}`; + } + + public wrapAstTypeWithModifiers(baseType: string, typeNode: TypeNode): string { + throw new Error(`You must override "wrapAstTypeWithModifiers" of OperationVariablesToObject!`); + } + + protected formatFieldString(fieldName: string, isNonNullType: boolean, hasDefaultValue: boolean): string { + return fieldName; + } + + protected formatTypeString(fieldType: string, isNonNullType: boolean, hasDefaultValue: boolean): string { + return fieldType; + } +} diff --git a/packages/plugins/typescript-server/tsconfig.json b/packages/plugins/visitor-plugin-common/tsconfig.json similarity index 77% rename from packages/plugins/typescript-server/tsconfig.json rename to packages/plugins/visitor-plugin-common/tsconfig.json index 782f215152c..42d8ecdd098 100644 --- a/packages/plugins/typescript-server/tsconfig.json +++ b/packages/plugins/visitor-plugin-common/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", @@ -17,5 +18,5 @@ "noUnusedLocals": false, "noUnusedParameters": false }, - "exclude": ["node_modules", "tests", "dist"] + "exclude": ["node_modules", "tests", "dist", "example"] } diff --git a/packages/utils/codegen-templates-scripts/.npmignore b/packages/utils/codegen-templates-scripts/.npmignore deleted file mode 100644 index 6e4a6ed0831..00000000000 --- a/packages/utils/codegen-templates-scripts/.npmignore +++ /dev/null @@ -1,11 +0,0 @@ -./src -node_modules -./tests -!dist -!boilerplate -!boilerplate/src/ -!boilerplate/tests/ -!boilerplate/src -!boilerplate/tests -!boilerplate/src/* -!boilerplate/tests/* diff --git a/packages/utils/codegen-templates-scripts/README.md b/packages/utils/codegen-templates-scripts/README.md deleted file mode 100644 index 1f9637bd6aa..00000000000 --- a/packages/utils/codegen-templates-scripts/README.md +++ /dev/null @@ -1,196 +0,0 @@ -# Script utils for Handlebars Templates - -Create GraphQL Codegen templates easily with this Handlebars. - -This package exposes a CLI util called `codegen-templates-scripts` which allow you to easily create a GraphQL Codegen Template project, and built it without dealing with external utils. - -To get started with this package, install it globally, or as local dependency inside an existing directory: - - $ yarn global add codegen-templates-scripts - -Then, to start a new project, create a directory for your template project: - - $ mkdir my-codegen-template - $ cd my-codegen-template - -Now, run the following command inside your directory: - - yarn codegen-templates-scripts init - -> If some files such as `package.json` are already exists in this dir, please use `--overwrite` to make sure it changes it as well. - -Now, install the boilerplate dependencies by running: - - yarn - -The CLI util will create the boilerplate for you, so all you have to do it to write your own templates under `src/` and defined it in `config.ts` file. - -## Testing your template locally - -To test your template locally, you can either test it on a real project and use `--template` and point it to your development directory (make sure to build it before). - -Or, take a look at the tests directory and see the unit-tests examples. To run these test just use `yarn test`. - -## Building and Publishing your template - -This package comes with a built-in `build` command. - -All you have to do is to run `yarn build` inside your project directory, in order to build it. - -To publish your package, just use `npm publish` - everything else it already set for you. - -## `config.ts` - -This file is in charge of configuration and declaration of your templates. - -### inputType - -Allowed values: `EInputType.SINGLE_FILE`, `EInputType.MULTIPLE_FILES` - -`inputType` defined the template input type of the generator, and also declares the generator output. - -For example, we have TypeScript generators for both single and multiple files. - -The input type field effects the rest of the fields: - -#### _SINGLE_FILE_ - -When using `SINGLE_FILE`, you must specify the main template name, with a key called `index`, and this will be the root of your app. - -You also need to specify the `outFile` of the package, which is the default file name in case of output filename was not specified through the CLI. - -#### _MULTIPLE_FILES_ - -When using `MULTIPLE_FILES`, you need to specify a template for each available compilation context (refer to `templates` section for the list of available contexts). - -You also need to specify the `filesExtension` for the generated files. - -### templates - -`templates` field should contains an object, where the key is the name of the template, and the value is a string. - -There are special context types for templates, and each type of templates will compile with a different context: - -- `index`: use with `SINGLE_FILE` to declare the main entry point of the generated file, compiled with a merged object, containing all [`SchemaTemplateContext`](../../graphql-codegen-core/src/types.ts#L78-L94) and [`Document`](../../graphql-codegen-core/src/types.ts#L170-L175) fields. -- `type`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL schema `type`, this template will compile with _each_ [type](../../graphql-codegen-core/src/types.ts#L38-L46) in your schema. -- `inputType`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL schema `input`, this template will compile with _each_ [input type](../../graphql-codegen-core/src/types.ts#L38-L46) in your schema. -- `union`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL schema `union`, this template will compile with _each_ [union](../../graphql-codegen-core/src/types.ts#L65-L69) in your schema. -- `scalar`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL schema `scalar`, this template will compile with _each_ [scalar](../../graphql-codegen-core/src/types.ts#L48-L51) in your schema. -- `enum`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL schema `enum`, this template will compile with _each_ [enum](../../graphql-codegen-core/src/types.ts#L53-L57) in your schema. -- `interface`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL schema `interface`, this template will compile with _each_ [interface](../../graphql-codegen-core/src/types.ts#L71-L76) in your schema. -- `operation`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL operation (`query`/`mutation`/`subsription`), this template will compile with [`Operation` context](../../graphql-codegen-core/src/types.ts#L151-L161). -- `fragment`: use with `MULTIPLE_FILES` to declare that this template belongs to GraphQL `fragment`, this template will compile with [`Fragment` context](../../graphql-codegen-core/src/types.ts#L144-L149). -- `schema`: use with `MULTIPLE_FILES` to compile with [`SchemaTemplateContext`](../../graphql-codegen-core/src/types.ts#L78-L94). -- `documents`: use with `MULTIPLE_FILES` to compile with all operations, the context will be [`Document`](../../graphql-codegen-core/src/types.ts#L170-L175). -- `all`: same as to `index`. - -Also, all templates specified under `templates` will be loaded as Handlebars template partials, so you can use it any time inside other templates, for example, the following templates definitions: - -```typescript -const config = { - // ... - templates: { - index: '{{>selectionSet}}', - selectionSet: 'Hello' - } - // ... -}; -``` - -The `index` template loads `selectionSet` template, and it can also provide a context for the specific partial: - -```typescript -const config = { - // ... - templates: { - index: '{{>selectionSet types}}', - selectionSet: '{{#each this }} Type name: {{ name }}{{/each}}' - } - // ... -}; -``` - -> You can also load a template from itself, and create a recursive generation of the template. - -### flattenTypes - -Type flattening is a useful feature when generation a template, when `true` is specified, the generator will return a flatten version of the GraphQL selection set when using inner types. - -For example, let's take a look in the following GraphQL schema and `query`: - -```graphql schema -type NameFields { - firstName: String - lastName: String -} - -type User { - name: NameFields - email: String - age: Int -} - -type Query { - me: User -} - -schema { - query: Query -} -``` - -```graphql -query myQuery { - user { - me { - firstName - lastName - } - } -} -``` - -This query uses multiple levels of selection set (`user` > `name` > `firstName`), but when adding `flattenTypes: true`, the generator will append a new field to the operation/fragment context, called `innerModels`, and it this case it will contains the following: - -``` -[ - { - schemaBaseType: 'User', - modelType: 'Me', - fields: [ ... ] // Original SelectionSetFieldNode from the operation - // .. more fields - }, - { - schemaBaseType: 'NameFields', - modelType: 'Name', - fields: [ ... ] // Original SelectionSetFieldNode from the operation - // .. more fields - } -] -``` - -So the two available levels of selection set were flatten into a single level, so you can generate you whole selection set in a single iteration. - -The `modelType` becomes the name of the selection set field, because we use only part of the available fields (for example, the query only asks for part of the `User` fields), so we can't use the actual GraphQL `type` from the schema - so each selection set creates new "types", and the usage in the selection set also changes, so the `type` of `me` is not `User` - it's `Me`. - -The actual compilation context when using `flattenTypes: true` is [available here](../../graphql-codegen-compiler/src/types.ts#L11-L37). - -### primitives - -Specify `primitives` object map to replace the original GraphQL built-in types to a language-specific primitives. - -For example, GraphQL type of `String` is actually a `string` in TypeScript. - -### outFile - -Use with `SINGLE_FILE`, specify the default filename for the generated file. - -### filesExtension - -Use with `MULTIPLE_FILES`, specify the file extension for the generated files. - -### customHelpers - -With `customHelpers` you can add custom helpers that executes with your custom templates. - -Provide an object with `key` as the name of the helper, and a `Function` for the helper execution. you can also specify a path to a local JavaScript file. diff --git a/packages/utils/codegen-templates-scripts/boilerplate/.gitignore b/packages/utils/codegen-templates-scripts/boilerplate/.gitignore deleted file mode 100644 index 911ea64d58a..00000000000 --- a/packages/utils/codegen-templates-scripts/boilerplate/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -npm-debug.log -dist -temp -yarn-error.log \ No newline at end of file diff --git a/packages/utils/codegen-templates-scripts/boilerplate/.npmignore b/packages/utils/codegen-templates-scripts/boilerplate/.npmignore deleted file mode 100644 index 4a44cedef75..00000000000 --- a/packages/utils/codegen-templates-scripts/boilerplate/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -src -node_modules -tests -!dist diff --git a/packages/utils/codegen-templates-scripts/boilerplate/package.json b/packages/utils/codegen-templates-scripts/boilerplate/package.json deleted file mode 100644 index 88e8615533f..00000000000 --- a/packages/utils/codegen-templates-scripts/boilerplate/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "my-codegen-template", - "version": "0.0.1", - "description": "", - "license": "MIT", - "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build", - "test": "codegen-templates-scripts test" - }, - "devDependencies": {}, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - }, - "jest": { - "globals": { - "ts-jest": { - "enableTsDiagnostics": false - } - }, - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ] - } -} diff --git a/packages/utils/codegen-templates-scripts/boilerplate/src/index.ts b/packages/utils/codegen-templates-scripts/boilerplate/src/index.ts deleted file mode 100644 index c1835c3e2e4..00000000000 --- a/packages/utils/codegen-templates-scripts/boilerplate/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { PluginFunction, DocumentFile, PluginValidateFn, Types } from 'graphql-codegen-core'; -import { GraphQLSchema } from 'graphql'; - -export const plugin: PluginFunction = (schema: GraphQLSchema, documents: DocumentFile[], config: any): string => { - return '// This is my plugin!'; // Replace with your plugin's output -}; - -export const validate: PluginValidateFn = ( - schema: GraphQLSchema, - documents: DocumentFile[], - config: any, - outputFile: string, - allPlugins: Types.ConfiguredPlugin[] -) => { - // Use this function to verify that you got everything you need to run your - // plugin, and throw an Error if something is not right. -}; diff --git a/packages/utils/codegen-templates-scripts/boilerplate/tests/example.spec.ts b/packages/utils/codegen-templates-scripts/boilerplate/tests/example.spec.ts deleted file mode 100644 index 43afa350b04..00000000000 --- a/packages/utils/codegen-templates-scripts/boilerplate/tests/example.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { makeExecutableSchema } from 'graphql-tools'; -import gql from 'graphql-tag'; -import { GraphQLSchema } from 'graphql'; - -describe('Tests Example', () => { - const testSchema = gql` - type Query { - fieldTest: String - } - - schema { - query: Query - } - `; - - describe('Example', () => { - it('Example', async () => { - const schema: GraphQLSchema = makeExecutableSchema({ typeDefs: testSchema, allowUndefinedInResolve: true }); - - expect(schema).toBeDefined(); - }); - }); -}); diff --git a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-build.js b/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-build.js deleted file mode 100755 index 2b3c54a9fff..00000000000 --- a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-build.js +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env node - -const program = require('commander'); -const webpack = require('webpack'); -const path = require('path'); -const rimraf = require('rimraf'); - -program.parse(process.argv); - -const newProjectDir = process.cwd(); -const scriptsPath = path.resolve(__dirname); -const webpackConfigPath = path.join(scriptsPath, '../webpack.config.js'); -const webpackConfig = require(webpackConfigPath); - -console.log('Building GraphQL Code Generator template project: ' + newProjectDir); - -webpackConfig.context = path.join(newProjectDir, './src/'); -webpackConfig.output.path = path.join(newProjectDir, './dist/'); - -rimraf.sync(webpackConfig.output.path); - -webpack(webpackConfig, (err, stats) => { - if (err) { - console.error(err.stack || err); - - if (err.details) { - console.error(err.details); - } - - return; - } - - const info = stats.toString({ - colors: true, - hash: false, - chunks: false, - assets: false, - children: false, - version: false, - timings: false, - modules: false - }); - - if (info) { - console.log(info); - } - - if (stats.hasErrors()) { - process.exit(1); - } -}); diff --git a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-init.js b/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-init.js deleted file mode 100755 index d8865a125a2..00000000000 --- a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-init.js +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env node - -const program = require('commander'); -const copyfiles = require('copyfiles'); -const path = require('path'); -const fs = require('fs'); -const pack = require('../package.json'); - -program.option('-o, --overwrite', 'Overwrite existing files'); -program.parse(process.argv); - -const newProjectDir = process.cwd(); -const boilerplatePath = path.join(__dirname, '../boilerplate'); - -console.log('Creating a new GraphQL Code Generator template project under: ' + newProjectDir); - -copyfiles( - [boilerplatePath + '/**/*', newProjectDir], - { all: true, soft: !program.overwrite, up: boilerplatePath.match(/\//g).length + 1 }, - function(err, result) { - const packageFilePath = path.join(newProjectDir, './package.json'); - const content = JSON.parse(fs.readFileSync(packageFilePath)); - - if (content.name === 'my-codegen-template') { - content.name = path.basename(newProjectDir); - } - - content.devDependencies = content.devDependencies || {}; - content.devDependencies[pack.name] = pack.version; - content.devDependencies['graphql-codegen-core'] = pack.version; - content.devDependencies['graphql'] = '14.1.1'; - content.devDependencies['@types/graphql'] = '14.0.5'; - fs.writeFileSync(packageFilePath, JSON.stringify(content, null, 2)); - } -); diff --git a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-test.js b/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-test.js deleted file mode 100755 index a5d57ab3e7a..00000000000 --- a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts-test.js +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env node - -const program = require('commander'); -const jest = require('jest-cli'); - -program.option('-o, --overwrite', 'Overwrite existing files'); -program.parse(process.argv); - -const projectDir = process.cwd(); - -jest.run([], projectDir); diff --git a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts.js b/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts.js deleted file mode 100755 index ce5897548eb..00000000000 --- a/packages/utils/codegen-templates-scripts/cli/codegen-templates-scripts.js +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env node - -const program = require('commander'); -const pack = require('../package.json'); - -program.version(pack.version); - -program - .command('init', 'Initialize a new template boilerplate in the current directory') - .command('build', 'Executes build using Webpack and Handlebars') - .command('test', 'Executes unit tests using Jest'); - -program.parse(process.argv); diff --git a/packages/utils/codegen-templates-scripts/package.json b/packages/utils/codegen-templates-scripts/package.json deleted file mode 100644 index 9b94ad63136..00000000000 --- a/packages/utils/codegen-templates-scripts/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "codegen-templates-scripts", - "version": "0.18.0", - "main": "cli.js", - "license": "MIT", - "repository": "git@github.com:dotansimha/graphql-code-generator.git", - "dependencies": { - "awesome-typescript-loader": "5.2.1", - "commander": "2.19.0", - "copyfiles": "2.1.0", - "jest": "24.5.0", - "raw-loader": "1.0.0", - "rimraf": "2.6.3", - "ts-jest": "24.0.0", - "typescript": "3.3.3333", - "webpack": "4.29.6", - "webpack-cli": "3.2.3", - "webpack-node-externals": "1.7.2" - }, - "bin": { - "codegen-templates-scripts": "./cli/codegen-templates-scripts.js" - } -} diff --git a/packages/utils/codegen-templates-scripts/tsconfig.json b/packages/utils/codegen-templates-scripts/tsconfig.json deleted file mode 100644 index c345287d132..00000000000 --- a/packages/utils/codegen-templates-scripts/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", - "lib": ["es6", "esnext", "es2015"], - "suppressImplicitAnyIndexErrors": true, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "sourceMap": true, - "declaration": true, - "outDir": "./dist/", - "noImplicitAny": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noUnusedParameters": true - }, - "exclude": ["node_modules", "tests", "dist"] -} diff --git a/packages/utils/codegen-templates-scripts/webpack.config.js b/packages/utils/codegen-templates-scripts/webpack.config.js deleted file mode 100644 index 257671f2508..00000000000 --- a/packages/utils/codegen-templates-scripts/webpack.config.js +++ /dev/null @@ -1,45 +0,0 @@ -const nodeExternals = require('webpack-node-externals'); - -module.exports = { - context: '/src/', - entry: './index.ts', - output: { - path: '/dist/', - filename: 'index.js', - libraryTarget: 'commonjs' - }, - mode: 'production', - target: 'node', - optimization: { - minimize: false - }, - externals: [ - nodeExternals(), - 'graphql', - 'graphql-codegen-core', - 'graphql-tag', - 'lodash', - 'graphql-codegen-plugin-helpers', - 'moment' - ], - resolve: { - mainFields: ['browser', 'main', 'module'], - extensions: ['.ts', '.tsx', '.js', '.jsx'], - alias: { - handlebars: 'handlebars/dist/handlebars.js' - } - }, - devtool: 'source-map', - module: { - rules: [ - { - test: /\.tsx?$/, - loader: 'awesome-typescript-loader' - }, - { - test: /\.handlebars/, - use: 'raw-loader' - } - ] - } -}; diff --git a/packages/utils/codegen-templates-scripts/yarn.lock b/packages/utils/codegen-templates-scripts/yarn.lock deleted file mode 100644 index 8429004ddfd..00000000000 --- a/packages/utils/codegen-templates-scripts/yarn.lock +++ /dev/null @@ -1,7 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" diff --git a/packages/utils/codegen-templates-scripts/.gitignore b/packages/utils/graphql-codegen-testing/.gitignore similarity index 100% rename from packages/utils/codegen-templates-scripts/.gitignore rename to packages/utils/graphql-codegen-testing/.gitignore diff --git a/packages/utils/graphql-codegen-testing/.npmignore b/packages/utils/graphql-codegen-testing/.npmignore new file mode 100644 index 00000000000..9ee5e2fb4d5 --- /dev/null +++ b/packages/utils/graphql-codegen-testing/.npmignore @@ -0,0 +1,5 @@ +../graphql-codegen-generators/dev-test +src +node_modules +tests +!dist diff --git a/packages/utils/graphql-codegen-testing/package.json b/packages/utils/graphql-codegen-testing/package.json new file mode 100644 index 00000000000..4a44f56b1d7 --- /dev/null +++ b/packages/utils/graphql-codegen-testing/package.json @@ -0,0 +1,28 @@ +{ + "name": "graphql-codegen-testing", + "version": "0.18.0", + "description": "GraphQL Codegen Testing Utils", + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "scripts": { + "build": "node_modules/.bin/tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs" + }, + "repository": "git@github.com:dotansimha/graphql-code-generator.git", + "author": "Dotan Simha ", + "license": "MIT", + "bugs": { + "url": "https://github.com/dotansimha/graphql-code-generator/issues" + }, + "homepage": "https://github.com/dotansimha/graphql-code-generator#readme", + "dependencies": { + "tslib": "1.9.3", + "common-tags": "1.8.0" + }, + "devDependencies": { + "typescript": "3.3.3333" + }, + "typings": "dist/esnext/index.d.ts", + "typescript": { + "definition": "dist/esnext/index.d.ts" + } +} diff --git a/packages/graphql-codegen-core/src/testing/index.ts b/packages/utils/graphql-codegen-testing/src/index.ts similarity index 100% rename from packages/graphql-codegen-core/src/testing/index.ts rename to packages/utils/graphql-codegen-testing/src/index.ts diff --git a/packages/utils/codegen-templates-scripts/boilerplate/tsconfig.json b/packages/utils/graphql-codegen-testing/tsconfig.json similarity index 66% rename from packages/utils/codegen-templates-scripts/boilerplate/tsconfig.json rename to packages/utils/graphql-codegen-testing/tsconfig.json index c345287d132..3d951c24dd6 100644 --- a/packages/utils/codegen-templates-scripts/boilerplate/tsconfig.json +++ b/packages/utils/graphql-codegen-testing/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", @@ -10,12 +11,15 @@ "sourceMap": true, "declaration": true, "outDir": "./dist/", + "rootDir": "./src/", "noImplicitAny": true, "noImplicitThis": true, "alwaysStrict": true, "noImplicitReturns": true, "noUnusedLocals": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "resolveJsonModule": true }, - "exclude": ["node_modules", "tests", "dist"] + "files": ["src/index.ts"], + "exclude": ["node_modules"] } diff --git a/packages/utils/plugins-handlebars-helpers/.gitignore b/packages/utils/plugins-handlebars-helpers/.gitignore deleted file mode 100644 index 911ea64d58a..00000000000 --- a/packages/utils/plugins-handlebars-helpers/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -npm-debug.log -dist -temp -yarn-error.log \ No newline at end of file diff --git a/packages/utils/plugins-handlebars-helpers/.npmignore b/packages/utils/plugins-handlebars-helpers/.npmignore deleted file mode 100644 index 4a44cedef75..00000000000 --- a/packages/utils/plugins-handlebars-helpers/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -src -node_modules -tests -!dist diff --git a/packages/utils/plugins-handlebars-helpers/package.json b/packages/utils/plugins-handlebars-helpers/package.json deleted file mode 100644 index 0d1c6ab6ca5..00000000000 --- a/packages/utils/plugins-handlebars-helpers/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "graphql-codegen-plugin-handlebars-helpers", - "version": "0.18.0", - "description": "graphql-codegen-cli template for TypeScript typings for both client side and server side", - "repository": "git@github.com:dotansimha/graphql-code-generator.git", - "license": "MIT", - "scripts": { - "prepublishOnly": "yarn build", - "build": "codegen-templates-scripts build", - "pretest": "yarn build" - }, - "dependencies": { - "change-case": "3.1.0", - "common-tags": "1.8.0", - "handlebars": "4.1.0" - }, - "devDependencies": { - "@types/common-tags": "1.8.0" - }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", - "typescript": { - "definition": "dist/index.d.ts" - } -} diff --git a/packages/utils/plugins-handlebars-helpers/src/index.ts b/packages/utils/plugins-handlebars-helpers/src/index.ts deleted file mode 100644 index c1dd80331cf..00000000000 --- a/packages/utils/plugins-handlebars-helpers/src/index.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { SafeString } from 'handlebars'; -import { oneLine } from 'common-tags'; - -function blockComment(str: string) { - if (!str || str === '') { - return ''; - } - - return new SafeString( - [ - '\n', - '// ====================================================', - '// ' + oneLine`${str || ''}`, - '// ====================================================', - '\n' - ].join('\n') - ); -} - -export const helpers = { - for(from: any, to: any, incr: any, block: any) { - let accum = ''; - - for (let i = from; i < to; i += incr) { - accum += block.fn(i); - } - - return accum; - }, - ifCond(this: any, v1: any, operator: string, v2: any, options: any) { - switch (operator) { - case '==': - return v1 === v2 ? options.fn(this) : options.inverse(this); - case '===': - return v1 === v2 ? options.fn(this) : options.inverse(this); - case '!=': - return v1 !== v2 ? options.fn(this) : options.inverse(this); - case '!==': - return v1 !== v2 ? options.fn(this) : options.inverse(this); - case '<': - return v1 < v2 ? options.fn(this) : options.inverse(this); - case '<=': - return v1 <= v2 ? options.fn(this) : options.inverse(this); - case '>': - return v1 > v2 ? options.fn(this) : options.inverse(this); - case '>=': - return v1 >= v2 ? options.fn(this) : options.inverse(this); - case '&&': - return v1 && v2 ? options.fn(this) : options.inverse(this); - case '||': - return v1 || v2 ? options.fn(this) : options.inverse(this); - default: - return options.inverse(this); - } - }, - toScalar: (scalars: any) => (type: string) => { - return scalars[type] || type || ''; - }, - blockCommentIf(str: string, list: any[] = []) { - if (list && list.length > 0) { - return blockComment(str); - } - - return ''; - }, - blockComment, - toComment(str: string) { - if (!str || str === '') { - return ''; - } - - return new SafeString('/** ' + oneLine`${str || ''}` + ' */'); - }, - toLowerCase(str: string) { - return (str || '').toLowerCase(); - }, - toUpperCase(str: string) { - return (str || '').toUpperCase(); - }, - stringify(obj: any) { - return new SafeString(JSON.stringify(obj)); - }, - times(n: number, block: any) { - let accum = ''; - - for (let i = 0; i < n; ++i) { - accum += block.fn(i); - } - - return accum; - }, - ifDirective(context: any, directiveName: string, options: { inverse: Function; fn: Function; data: { root: any } }) { - if (context && context['directives'] && directiveName && typeof directiveName === 'string') { - const directives = context['directives']; - const directiveValue = directives[directiveName]; - - if (directiveValue) { - return options && options.fn ? options.fn({ ...(directiveValue || {}), ...context }) : ''; - } else { - return options && options.inverse ? options.inverse(context) : ''; - } - } - - return options && options.inverse ? options.inverse(context) : ''; - }, - unlessDirective( - context: any, - directiveName: string, - options: { inverse: Function; fn: Function; data: { root: any } } - ) { - if (context && context['directives'] && directiveName && typeof directiveName === 'string') { - const directives = context['directives']; - const directiveValue = directives[directiveName]; - - if (!directiveValue) { - return options && options.fn ? options.fn({ ...(directiveValue || {}), ...context }) : ''; - } else { - return options && options.inverse ? options.inverse(context) : ''; - } - } - - return options && options.inverse ? options.inverse(context) : ''; - } -}; diff --git a/packages/utils/plugins-handlebars-helpers/tsconfig.json b/packages/utils/plugins-handlebars-helpers/tsconfig.json deleted file mode 100644 index a6d80f6ad76..00000000000 --- a/packages/utils/plugins-handlebars-helpers/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", - "lib": ["es6", "esnext", "es2015"], - "suppressImplicitAnyIndexErrors": true, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "sourceMap": true, - "declaration": true, - "outDir": "./dist/", - "noImplicitAny": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noImplicitReturns": true, - "noUnusedLocals": false, - "noUnusedParameters": false - }, - "exclude": ["node_modules", "tests", "dist"] -} diff --git a/packages/utils/plugins-helpers/package.json b/packages/utils/plugins-helpers/package.json index 4ef79c7bfd8..e9fa5313715 100644 --- a/packages/utils/plugins-helpers/package.json +++ b/packages/utils/plugins-helpers/package.json @@ -5,19 +5,26 @@ "repository": "git@github.com:dotansimha/graphql-code-generator.git", "license": "MIT", "scripts": { - "prepublishOnly": "yarn build", - "build": "tsc" + "build": "tsc -m esnext --outDir dist/esnext && tsc -m commonjs --outDir dist/commonjs" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" }, "dependencies": { - "graphql-codegen-core": "0.18.0", + "tslib": "1.9.3", + "change-case": "3.1.0", + "common-tags": "1.8.0", + "ts-log": "2.1.4", "import-from": "2.1.0" }, "devDependencies": { "typescript": "3.3.3333" }, - "main": "./dist/index.js", - "typings": "dist/index.d.ts", + "sideEffects": false, + "main": "dist/commonjs/index.js", + "module": "dist/esnext/index.js", + "typings": "dist/esnext/index.d.ts", "typescript": { - "definition": "dist/index.d.ts" + "definition": "dist/esnext/index.d.ts" } } diff --git a/packages/utils/plugins-helpers/src/build-files-array.ts b/packages/utils/plugins-helpers/src/build-files-array.ts deleted file mode 100644 index 0bd3bd57e99..00000000000 --- a/packages/utils/plugins-helpers/src/build-files-array.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AstNode, Document } from 'graphql-codegen-core'; -import { resolve, extname, basename } from 'path'; - -export interface TemplateDocumentFileReference { - relative: string; - absolute: string; - cwd: string; - filename: string; - extension: string; - documents: AstNode[]; -} - -function getFileAttrs( - filePath: string -): { cwd: string; relative: string; absolute: string; filename: string; extension: string } { - const cwd = process.cwd(); - - return { - cwd, - relative: filePath, - absolute: resolve(filePath), - filename: basename(filePath), - extension: extname(filePath) - }; -} - -export function buildFilesArray(parsedDocument: Document): TemplateDocumentFileReference[] { - const filesMap: { [filename: string]: AstNode[] } = {}; - const relevantOperations = [...parsedDocument.operations, ...parsedDocument.fragments].filter(o => o.originalFile); - - for (const operation of relevantOperations) { - if (!filesMap[operation.originalFile]) { - filesMap[operation.originalFile] = []; - } - - filesMap[operation.originalFile].push(operation); - } - - return Object.keys(filesMap).map(filename => ({ documents: filesMap[filename], ...getFileAttrs(filename) })); -} diff --git a/packages/graphql-codegen-core/src/debugging.ts b/packages/utils/plugins-helpers/src/debugging.ts similarity index 91% rename from packages/graphql-codegen-core/src/debugging.ts rename to packages/utils/plugins-helpers/src/debugging.ts index a3ca3e7ad53..4ec1c566199 100644 --- a/packages/graphql-codegen-core/src/debugging.ts +++ b/packages/utils/plugins-helpers/src/debugging.ts @@ -1,4 +1,4 @@ -import { getLogger } from './utils/logger'; +import { getLogger } from './logger'; let queue: Array<{ message: string; diff --git a/packages/utils/plugins-helpers/src/flatten-types.ts b/packages/utils/plugins-helpers/src/flatten-types.ts deleted file mode 100644 index 87e665dff1e..00000000000 --- a/packages/utils/plugins-helpers/src/flatten-types.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { pascalCase } from 'change-case'; -import { - Operation, - Document, - Fragment, - SelectionSetFragmentSpread, - SelectionSetFieldNode, - SelectionSetInlineFragment, - SelectionSetItem, - isFieldNode, - isInlineFragmentNode -} from 'graphql-codegen-core'; - -export interface FlattenOperation extends Operation { - innerModels: FlattenModel[]; - isFlatten: boolean; -} - -export interface FlattenFragment extends Fragment { - innerModels: FlattenModel[]; - isFlatten: boolean; -} - -export interface FlattenDocument extends Document { - operations: FlattenOperation[]; - fragments: FlattenFragment[]; - hasFragments: boolean; - hasOperations: boolean; -} - -export interface FlattenModel { - schemaBaseType: string; - modelType: string; - fields: SelectionSetFieldNode[]; - fragmentsSpread: SelectionSetFragmentSpread[]; - inlineFragments: SelectionSetInlineFragment[]; - hasFragmentsSpread: boolean; - hasFields: boolean; - hasInlineFragments: boolean; - hasTypename: boolean; -} - -const operationTypes = ['query', 'mutation', 'subscription'].map(name => pascalCase(name)); - -export const handleNameDuplications = (name: string, existing: FlattenModel[]): string => { - if (operationTypes.includes(name) || existing.find(model => model.modelType === name)) { - return handleNameDuplications('_' + name, existing); - } - - return name; -}; - -function buildModelFromField(field: SelectionSetFieldNode, result: FlattenModel[]): FlattenModel { - const modelName = handleNameDuplications(pascalCase(field.name), result); - - return { - schemaBaseType: field.type, - modelType: modelName, - fields: field.fields, - fragmentsSpread: field.fragmentsSpread, - inlineFragments: field.inlineFragments, - hasFields: field.hasFields, - hasFragmentsSpread: field.hasFragmentsSpread, - hasInlineFragments: field.hasInlineFragments, - hasTypename: field.hasTypename - }; -} - -function buildModelFromInlineFragment(fragment: SelectionSetInlineFragment, result: FlattenModel[]): FlattenModel { - const modelName = handleNameDuplications(pascalCase(fragment.onType) + 'InlineFragment', result); - - return { - schemaBaseType: fragment.onType, - modelType: modelName, - fields: fragment.fields, - fragmentsSpread: fragment.fragmentsSpread, - inlineFragments: fragment.inlineFragments, - hasFields: fragment.hasFields, - hasFragmentsSpread: fragment.hasFragmentsSpread, - hasInlineFragments: fragment.hasInlineFragments, - hasTypename: fragment.hasTypename - }; -} - -export function flattenSelectionSet(selectionSet: SelectionSetItem[], result: FlattenModel[] = []): FlattenModel[] { - selectionSet.forEach((item: SelectionSetItem) => { - if (isFieldNode(item)) { - if (item.selectionSet.length > 0) { - const model = buildModelFromField(item, result); - item.type = model.modelType; - result.push(model); - - flattenSelectionSet(item.selectionSet, result); - } - } else if (isInlineFragmentNode(item)) { - const model = buildModelFromInlineFragment(item, result); - item.name = model.modelType; - item.onType = model.schemaBaseType; - result.push(model); - - flattenSelectionSet(item.selectionSet, result); - } - }); - - return result; -} - -export function flattenTypes(document: Document): FlattenDocument { - return { - operations: document.operations.map( - (operation: Operation): FlattenOperation => { - return { - isFlatten: true, - ...operation, - innerModels: flattenSelectionSet(operation.selectionSet) - } as FlattenOperation; - } - ), - fragments: document.fragments.map( - (fragment: Fragment): FlattenFragment => { - return { - isFlatten: true, - ...fragment, - innerModels: flattenSelectionSet(fragment.selectionSet) - } as FlattenFragment; - } - ), - hasOperations: document.hasOperations, - hasFragments: document.hasFragments - }; -} diff --git a/packages/utils/plugins-helpers/src/index.ts b/packages/utils/plugins-helpers/src/index.ts index a77f28648a0..0aaa655b2eb 100644 --- a/packages/utils/plugins-helpers/src/index.ts +++ b/packages/utils/plugins-helpers/src/index.ts @@ -1,3 +1,6 @@ export { resolveExternalModuleAndFn } from './resolve-external-module-and-fn'; -export { buildFilesArray } from './build-files-array'; -export { handleNameDuplications, flattenSelectionSet, flattenTypes } from './flatten-types'; +export { toPascalCase } from './to-pascal-case'; +export * from './types'; +export * from './yml-config-types'; +export { debugLog, printLogs, resetLogs } from './debugging'; +export { getLogger, setLogger, setSilentLogger, useWinstonLogger } from './logger'; diff --git a/packages/graphql-codegen-core/src/utils/logger.ts b/packages/utils/plugins-helpers/src/logger.ts similarity index 100% rename from packages/graphql-codegen-core/src/utils/logger.ts rename to packages/utils/plugins-helpers/src/logger.ts diff --git a/packages/graphql-codegen-core/src/utils/to-pascal-case.ts b/packages/utils/plugins-helpers/src/to-pascal-case.ts similarity index 100% rename from packages/graphql-codegen-core/src/utils/to-pascal-case.ts rename to packages/utils/plugins-helpers/src/to-pascal-case.ts diff --git a/packages/graphql-codegen-core/src/types.ts b/packages/utils/plugins-helpers/src/types.ts similarity index 92% rename from packages/graphql-codegen-core/src/types.ts rename to packages/utils/plugins-helpers/src/types.ts index 69fa355d3e7..35d5455f05d 100644 --- a/packages/graphql-codegen-core/src/types.ts +++ b/packages/utils/plugins-helpers/src/types.ts @@ -168,16 +168,16 @@ export interface SelectionSetFieldNode extends SelectionSetItem { isEnum: boolean; } -export function isFieldNode(node: SelectionSetItem): node is SelectionSetFieldNode { - return node['name'] !== undefined && node['selectionSet'] !== undefined && node['type'] !== undefined; +export function isFieldNode(node: any): node is SelectionSetFieldNode { + return node.name !== undefined && node.selectionSet !== undefined && node.type !== undefined; } -export function isFragmentSpreadNode(node: SelectionSetItem): node is SelectionSetFragmentSpread { - return node['fragmentName'] !== undefined; +export function isFragmentSpreadNode(node: any): node is SelectionSetFragmentSpread { + return node.fragmentName !== undefined; } -export function isInlineFragmentNode(node: SelectionSetItem): node is SelectionSetInlineFragment { - return node['selectionSet'] !== undefined && node['onType'] !== undefined; +export function isInlineFragmentNode(node: any): node is SelectionSetInlineFragment { + return node.selectionSet !== undefined && node.onType !== undefined; } export interface Fragment extends AstNode { diff --git a/packages/graphql-codegen-core/src/yml-config-types.ts b/packages/utils/plugins-helpers/src/yml-config-types.ts similarity index 100% rename from packages/graphql-codegen-core/src/yml-config-types.ts rename to packages/utils/plugins-helpers/src/yml-config-types.ts diff --git a/packages/utils/plugins-helpers/tsconfig.json b/packages/utils/plugins-helpers/tsconfig.json index a6d80f6ad76..8b085279f7b 100644 --- a/packages/utils/plugins-helpers/tsconfig.json +++ b/packages/utils/plugins-helpers/tsconfig.json @@ -1,15 +1,16 @@ { "compilerOptions": { + "importHelpers": true, "experimentalDecorators": true, - "module": "commonjs", - "target": "es5", + "module": "esnext", + "target": "es2018", "lib": ["es6", "esnext", "es2015"], - "suppressImplicitAnyIndexErrors": true, "moduleResolution": "node", "emitDecoratorMetadata": true, "sourceMap": true, "declaration": true, "outDir": "./dist/", + "rootDir": "./src", "noImplicitAny": true, "noImplicitThis": true, "alwaysStrict": true, diff --git a/tslint.json b/tslint.json index 2a91e7fdcf6..29f628a7714 100644 --- a/tslint.json +++ b/tslint.json @@ -9,7 +9,7 @@ "label-position": true, "max-line-length": [false], "member-access": false, - "member-ordering": [true, "static-before-instance", "variables-before-functions"], + "member-ordering": [false], "no-arg": true, "no-bitwise": true, "no-console": true, diff --git a/website/i18n/en.json b/website/i18n/en.json index fbdb4b24f26..b25e6888ef7 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -11,8 +11,8 @@ "custom-codegen/index": { "title": "What are Plugins?" }, - "custom-codegen/using-handlebars": { - "title": "Using Handlebars" + "custom-codegen/using-visitor": { + "title": "Visitor Pattern" }, "custom-codegen/validate-configuration": { "title": "Validate Plugin Configuration" @@ -56,8 +56,8 @@ "plugins/add": { "title": "Add" }, - "plugins/flow-documents": { - "title": "Flow Documents" + "plugins/flow-operations": { + "title": "Flow Operations" }, "plugins/flow-resolvers": { "title": "Flow Resolvers" @@ -83,26 +83,26 @@ "plugins/typescript-apollo-angular": { "title": "Typescript Apollo Angular" }, - "plugins/typescript-client": { - "title": "Typescript Client" - }, - "plugins/typescript-common": { - "title": "TypeScript Common" - }, "plugins/typescript-graphql-files-modules": { "title": "TypeScript GraphQL Files Modules" }, "plugins/typescript-mongodb": { "title": "TypeScript MongoDB" }, + "plugins/typescript-operations": { + "title": "Typescript Operations" + }, "plugins/typescript-react-apollo": { "title": "TypeScript React Apollo" }, "plugins/typescript-resolvers": { "title": "TypeScript Resolvers" }, - "plugins/typescript-server": { - "title": "TypeScript Server" + "plugins/typescript-stencil-apollo": { + "title": "TypeScript Stencil Apollo" + }, + "plugins/typescript": { + "title": "TypeScrip" } }, "links": { diff --git a/website/live-demo/package.json b/website/live-demo/package.json index 67b9ce7761c..5d7299db3cc 100644 --- a/website/live-demo/package.json +++ b/website/live-demo/package.json @@ -14,27 +14,26 @@ "codemirror": "5.44.0", "codemirror-graphql": "0.8.3", "js-yaml": "3.12.2", - "graphql-code-generator": "0.17.0", - "graphql-codegen-flow": "0.17.0", - "graphql-codegen-flow-documents": "0.17.0", - "graphql-codegen-flow-resolvers": "0.17.0", - "graphql-codegen-typescript-common": "0.17.0", - "graphql-codegen-typescript-client": "0.17.0", - "graphql-codegen-typescript-server": "0.17.0", - "graphql-codegen-add": "0.17.0", - "graphql-codegen-time": "0.17.0", - "graphql-codegen-introspection": "0.17.0", - "graphql-codegen-schema-ast": "0.17.0", - "graphql-codegen-typescript-apollo-angular": "0.17.0", - "graphql-codegen-typescript-graphql-files-modules": "0.17.0", - "graphql-codegen-typescript-mongodb": "0.17.0", - "graphql-codegen-typescript-react-apollo": "0.17.0", - "graphql-codegen-typescript-resolvers": "0.17.0", + "graphql-code-generator": "0.18.0", + "graphql-codegen-flow": "0.18.0", + "graphql-codegen-flow-operations": "0.18.0", + "graphql-codegen-flow-resolvers": "0.18.0", + "graphql-codegen-add": "0.18.0", + "graphql-codegen-time": "0.18.0", + "graphql-codegen-introspection": "0.18.0", + "graphql-codegen-schema-ast": "0.18.0", + "graphql-codegen-typescript": "0.18.0", + "graphql-codegen-typescript-operations": "0.18.0", + "graphql-codegen-typescript-resolvers": "0.18.0", + "graphql-codegen-typescript-apollo-angular": "0.18.0", + "graphql-codegen-typescript-graphql-files-modules": "0.18.0", + "graphql-codegen-typescript-mongodb": "0.18.0", + "graphql-codegen-typescript-react-apollo": "0.18.0", "prettier": "1.16.4", "@material-ui/core": "3.9.2" }, "scripts": { - "analyze": "source-map-explorer build/static/js/main.*", + "analyze": "NODE_OPTIONS=--max_old_space_size=8192 react-scripts build && source-map-explorer build/static/js/main.*", "start": "NODE_OPTIONS=--max_old_space_size=8192 react-scripts start", "build": "GENERATE_SOURCEMAP=false NODE_OPTIONS=--max_old_space_size=8192 react-scripts build" }, diff --git a/website/live-demo/src/App.js b/website/live-demo/src/App.js index d96a3bbd4b4..3fe16c284e7 100644 --- a/website/live-demo/src/App.js +++ b/website/live-demo/src/App.js @@ -1,9 +1,7 @@ import React, { Component } from 'react'; import './App.css'; import { Editor } from './editor.component'; -import { executeCodegen } from 'graphql-code-generator'; import { safeLoad } from 'js-yaml'; -import * as prettier from 'prettier/standalone'; import MagicIcon from './magic.svg'; import CodegenLogo from './logo.svg'; import GraphQLLogo from './GraphQL_Logo.svg'; @@ -14,13 +12,6 @@ import FormControl from '@material-ui/core/FormControl'; import Select from '@material-ui/core/Select'; import { pascalCase } from 'change-case'; -const plugins = [ - require('prettier/parser-graphql'), - require('prettier/parser-babylon'), - require('prettier/parser-yaml'), - require('prettier/parser-typescript') -]; - const EXT_TO_FORMATTER = { ts: 'typescript', graphql: 'graphql', @@ -28,24 +19,37 @@ const EXT_TO_FORMATTER = { json: 'json' }; -const DEFAULT_EXAMPLE = 'typescript-client'; +const DEFAULT_EXAMPLE = 'typescript'; + +const getPrettierPlugins = async mode => { + switch (mode) { + case 'graphql': + return [await import('prettier/parser-graphql')]; + case 'yaml': + return [await import('prettier/parser-yaml')]; + case 'typescript': + return [await import('prettier/parser-typescript')]; + default: + return [await import('prettier/parser-babylon')]; + } +}; const pluginsMap = { - 'graphql-codegen-flow': require('graphql-codegen-flow'), - 'graphql-codegen-flow-documents': require('graphql-codegen-flow-documents'), - 'graphql-codegen-flow-resolvers': require('graphql-codegen-flow-resolvers'), - 'graphql-codegen-typescript-common': require('graphql-codegen-typescript-common'), - 'graphql-codegen-typescript-client': require('graphql-codegen-typescript-client'), - 'graphql-codegen-typescript-server': require('graphql-codegen-typescript-server'), - 'graphql-codegen-add': require('graphql-codegen-add'), - 'graphql-codegen-time': require('graphql-codegen-time'), - 'graphql-codegen-introspection': require('graphql-codegen-introspection'), - 'graphql-codegen-schema-ast': require('graphql-codegen-schema-ast'), - 'graphql-codegen-typescript-apollo-angular': require('graphql-codegen-typescript-apollo-angular'), - 'graphql-codegen-typescript-graphql-files-modules': require('graphql-codegen-typescript-graphql-files-modules'), - 'graphql-codegen-typescript-mongodb': require('graphql-codegen-typescript-mongodb'), - 'graphql-codegen-typescript-react-apollo': require('graphql-codegen-typescript-react-apollo'), - 'graphql-codegen-typescript-resolvers': require('graphql-codegen-typescript-resolvers') + 'graphql-codegen-flow': () => import('graphql-codegen-flow'), + 'graphql-codegen-flow-operations': () => import('graphql-codegen-flow-operations'), + 'graphql-codegen-flow-resolvers': () => import('graphql-codegen-flow-resolvers'), + 'graphql-codegen-typescript': () => import('graphql-codegen-typescript'), + 'graphql-codegen-typescript-operations': () => import('graphql-codegen-typescript-operations'), + 'graphql-codegen-typescript-resolvers': () => import('graphql-codegen-typescript-resolvers'), + 'graphql-codegen-typescript-apollo-angular': () => import('graphql-codegen-typescript-apollo-angular'), + 'graphql-codegen-typescript-react-apollo': () => import('graphql-codegen-typescript-react-apollo'), + 'graphql-codegen-typescript-stencil-apollo': () => import('graphql-codegen-typescript-stencil-apollo'), + 'graphql-codegen-typescript-graphql-files-modules': () => import('graphql-codegen-typescript-graphql-files-modules'), + 'graphql-codegen-typescript-mongodb': () => import('graphql-codegen-typescript-mongodb'), + 'graphql-codegen-add': () => import('graphql-codegen-add'), + 'graphql-codegen-time': () => import('graphql-codegen-time'), + 'graphql-codegen-introspection': () => import('graphql-codegen-introspection'), + 'graphql-codegen-schema-ast': () => import('graphql-codegen-schema-ast') }; class App extends Component { @@ -74,62 +78,60 @@ class App extends Component { return EXT_TO_FORMATTER[ext]; } - prettify(str, config) { + async prettify(str, config, tabWidth) { try { const mode = this.getMode(config) || 'typescript'; - - return prettier.format(str, { parser: mode, plugins }); + const prettier = await import('prettier/standalone'); + return prettier.format(str, { parser: mode, plugins: await getPrettierPlugins(mode), tabWidth }); } catch (e) { return str; } } - generate = () => { + generate = async () => { try { const cleanTabs = this.state.config.replace(/\t/g, ' '); - const prettyYaml = prettier.format(cleanTabs, { parser: 'yaml', plugins, tabWidth: 2 }); + const prettier = await import('prettier/standalone'); + const prettyYaml = prettier.format(cleanTabs, { + parser: 'yaml', + plugins: await getPrettierPlugins('yaml'), + tabWidth: 2 + }); const config = safeLoad(prettyYaml); config.namingConvention = pascalCase; const fullConfig = { - pluginLoader: m => pluginsMap[m] || null, + pluginLoader: m => (m in pluginsMap ? pluginsMap[m]() : null || null), schema: [this.state.schema], documents: this.state.documents, ...config }; - - executeCodegen(fullConfig) - .then(([{ content }]) => { - this.setState({ output: this.prettify(content, config) }); - }) - .catch(e => { - if (e.details) { - this.setState({ - output: ` - ${e.message}: - - ${e.details} - ` - }); - } else if (e.errors) { - this.setState({ - output: e.errors - .map( - subError => `${subError.message}: - ${subError.details}` - ) - .join('\n') - }); - } else { - this.setState({ - output: e.message - }); - } - }); + const { executeCodegen } = await import('graphql-code-generator'); + const [{ content }] = await executeCodegen(fullConfig); + this.setState({ output: await this.prettify(content, config) }); } catch (e) { - this.setState({ - output: e.message - }); + if (e.details) { + this.setState({ + output: ` + ${e.message}: + + ${e.details} + ` + }); + } else if (e.errors) { + this.setState({ + output: e.errors + .map( + subError => `${subError.message}: +${subError.details}` + ) + .join('\n') + }); + } else { + this.setState({ + output: e.message + }); + } } }; diff --git a/website/live-demo/src/editor.component.js b/website/live-demo/src/editor.component.js index de79c28bf96..66f076934bd 100644 --- a/website/live-demo/src/editor.component.js +++ b/website/live-demo/src/editor.component.js @@ -1,8 +1,31 @@ import React from 'react'; -import CodeMirror from 'codemirror'; export class Editor extends React.Component { - componentDidMount() { + async componentDidMount() { + const [{ default: CodeMirror }] = await Promise.all([ + import('codemirror'), + import('codemirror/addon/lint/lint'), + import('codemirror/addon/lint/yaml-lint'), + import('codemirror/addon/hint/show-hint'), + import('codemirror/addon/comment/comment'), + import('codemirror/addon/edit/matchbrackets'), + import('codemirror/addon/edit/closebrackets'), + import('codemirror/addon/fold/foldgutter'), + import('codemirror/addon/fold/brace-fold'), + import('codemirror/addon/search/search'), + import('codemirror/addon/search/searchcursor'), + import('codemirror/addon/search/jump-to-line'), + import('codemirror/addon/dialog/dialog'), + import('codemirror/addon/lint/lint'), + import('codemirror/mode/yaml/yaml'), + import('codemirror/mode/javascript/javascript'), + import('codemirror/keymap/sublime'), + import('codemirror-graphql/hint'), + import('codemirror-graphql/lint'), + import('codemirror-graphql/info'), + import('codemirror-graphql/jump'), + import('codemirror-graphql/mode') + ]); this.editor = CodeMirror(this._node, { value: this.props.value || '', lineNumbers: true, diff --git a/website/live-demo/src/examples.js b/website/live-demo/src/examples.js index e54538b242e..842ded6ad4d 100644 --- a/website/live-demo/src/examples.js +++ b/website/live-demo/src/examples.js @@ -52,44 +52,28 @@ const TS_QUERY = f` `; export const EXAMPLES = { - 'typescript-server': { - name: 'TypeScript (Server)', + typescript: { + name: 'TypeScript', state: { config: yaml` generates: server-types.ts: - add: "/* tslint:disable */" - time - - typescript-common - - typescript-server`, + - typescript`, schema: TS_SCHEMA, documents: '' } }, - 'typescript-client': { - name: 'TypeScript (Client)', + 'typescript-operations': { + name: 'TypeScript (Types and documents)', state: { config: yaml` generates: client-types.ts: - add: "// THIS IS A GENERATED FILE, DO NOT EDIT IT!" - - typescript-common - - typescript-client`, - schema: TS_SCHEMA, - documents: TS_QUERY - } - }, - 'typescript-client-no-namespaces': { - name: 'TypeScript (Client, no namespaces)', - state: { - config: yaml` - generates: - client-types.ts: - config: - noNamespaces: true - plugins: - - typescript-common - - typescript-client`, + - typescript + - typescript-operations`, schema: TS_SCHEMA, documents: TS_QUERY } @@ -101,8 +85,8 @@ export const EXAMPLES = { generates: components.tsx: plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations - typescript-react-apollo`, schema: TS_SCHEMA, documents: TS_QUERY @@ -115,13 +99,27 @@ export const EXAMPLES = { generates: components.ts: plugins: - - typescript-common - - typescript-client + - typescript + - typescript-operations - typescript-apollo-angular`, schema: TS_SCHEMA, documents: TS_QUERY } }, + 'stencil-apollo': { + name: 'TypeScript Stencil-Apollo Components', + state: { + config: yaml` + generates: + components.tsx: + plugins: + - typescript + - typescript-operations + - typescript-stencil-apollo`, + schema: TS_SCHEMA, + documents: TS_QUERY + } + }, 'typescript-server-resolvers': { name: 'TypeScript Resolvers Signature', state: { @@ -129,8 +127,7 @@ export const EXAMPLES = { generates: resolvers.ts: plugins: - - typescript-common - - typescript-server + - typescript - typescript-resolvers`, schema: TS_SCHEMA, documents: TS_QUERY @@ -168,7 +165,7 @@ export const EXAMPLES = { generates: types.flow.js: - flow - - flow-documents + - flow-operations `, schema: TS_SCHEMA, documents: TS_QUERY diff --git a/website/live-demo/src/index.js b/website/live-demo/src/index.js index 4c001397e04..773c5133aae 100644 --- a/website/live-demo/src/index.js +++ b/website/live-demo/src/index.js @@ -12,26 +12,4 @@ process.stdout = process.stderr = { write: () => null }; -require('codemirror/addon/lint/lint'); -require('codemirror/addon/lint/yaml-lint'); -require('codemirror/addon/hint/show-hint'); -require('codemirror/addon/comment/comment'); -require('codemirror/addon/edit/matchbrackets'); -require('codemirror/addon/edit/closebrackets'); -require('codemirror/addon/fold/foldgutter'); -require('codemirror/addon/fold/brace-fold'); -require('codemirror/addon/search/search'); -require('codemirror/addon/search/searchcursor'); -require('codemirror/addon/search/jump-to-line'); -require('codemirror/addon/dialog/dialog'); -require('codemirror/addon/lint/lint'); -require('codemirror/mode/yaml/yaml'); -require('codemirror/mode/javascript/javascript'); -require('codemirror/keymap/sublime'); -require('codemirror-graphql/hint'); -require('codemirror-graphql/lint'); -require('codemirror-graphql/info'); -require('codemirror-graphql/jump'); -require('codemirror-graphql/mode'); - ReactDOM.render(, document.getElementById('root')); diff --git a/website/sidebars.json b/website/sidebars.json index 6409faea257..734ada2c3a7 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -12,9 +12,8 @@ ], "Plugins": [ "plugins/index", - "plugins/typescript-common", - "plugins/typescript-client", - "plugins/typescript-server", + "plugins/typescript", + "plugins/typescript-operations", "plugins/typescript-resolvers", "plugins/typescript-graphql-files-modules", "plugins/typescript-mongodb", @@ -23,7 +22,7 @@ "plugins/typescript-stencil-apollo", "plugins/flow", "plugins/flow-resolvers", - "plugins/flow-documents", + "plugins/flow-operations", "plugins/fragment-matcher", "plugins/add", "plugins/time", @@ -36,7 +35,7 @@ "custom-codegen/write-your-plugin", "custom-codegen/validate-configuration", "custom-codegen/extend-schema", - "custom-codegen/using-handlebars" + "custom-codegen/using-visitor" ], "Migration": ["migration/from-0-13"] } diff --git a/yarn.lock b/yarn.lock index 27237895736..7893b4221a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -49,7 +49,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.0.1", "@babel/core@^7.1.0": +"@babel/core@^7.0.1", "@babel/core@^7.1.0", "@babel/core@^7.2.2": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.4.tgz#921a5a13746c21e32445bf0798680e9d11a6530b" integrity sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA== @@ -112,7 +112,7 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-create-class-features-plugin@^7.3.0": +"@babel/helper-create-class-features-plugin@^7.2.1", "@babel/helper-create-class-features-plugin@^7.3.0": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.4.tgz#092711a7a3ad8ea34de3e541644c2ce6af1f6f0c" integrity sha512-uFpzw6L2omjibjxa8VGZsJUPL5wJH0zzGKpoz0ccBkzIa6C8kWNUbiBmQ0rgOKWlHJ6qzmfa6lTiGchiV8SC+g== @@ -287,6 +287,14 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" +"@babel/plugin-proposal-class-properties@7.2.1": + version "7.2.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.2.1.tgz#c734a53e0a1ec40fe5c22ee5069d26da3b187d05" + integrity sha512-/4FKFChkQ2Jgb8lBDsvFX496YTi7UWTetVgS8oJUpX1e/DlaoeEK57At27ug8Hu2zI2g8bzkJ+8k9qrHZRPGPA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.2.1" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-class-properties@7.3.0": version "7.3.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd" @@ -710,6 +718,14 @@ "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" +"@babel/polyfill@^7.0.0": + version "7.2.5" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d" + integrity sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug== + dependencies: + core-js "^2.5.7" + regenerator-runtime "^0.12.0" + "@babel/preset-env@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db" @@ -1129,9 +1145,9 @@ loader-utils "^1.1.0" "@types/babel-types@*": - version "7.0.5" - resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.5.tgz#26f5bba8c58acd9b84d1a9135fb2789a1c191bc1" - integrity sha512-0t0R7fKAXT/P++S98djRkXbL9Sxd9NNtfNg3BNw2EQOjVIkiMBdmO55N2Tp3wGK3mylmM7Vck9h5tEoSuSUabA== + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.6.tgz#a7cfaaeee96e90c4c54da0e580aaff3f4cffacac" + integrity sha512-8zYZyy2kgwBXdz2j8Ix7LOghGiZbOiHf6vqmmBX1r76FdAzVNv7cODyJTEglUWiOdRnXh0s/o58neUwv5vaitQ== "@types/babel__core@^7.1.0": version "7.1.0" @@ -1174,9 +1190,9 @@ "@types/babel-types" "*" "@types/caseless@*": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" - integrity sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A== + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" + integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== "@types/chokidar@1.7.5": version "1.7.5" @@ -1196,6 +1212,11 @@ resolved "https://registry.yarnpkg.com/@types/detect-indent/-/detect-indent-5.0.0.tgz#8b1bbd7891268d5ed20d23ecd23ae333d33934cd" integrity sha512-eOFBOFCqusnH0i1s9XoURksqTZbsv5vbMMgOBKgSt67TsOw6ViaHO0Ii5DMhRoiU5TJ51uf9NsOpnxXsN96ywg== +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -1258,9 +1279,9 @@ integrity sha512-UGEe/6RsNAxgWdknhzFZbCxuYc5I7b/YEKlfKbo+76SM8CJzGs7XKCj7zyugXViRbKYpXhSXhCYVQZL5tmDbpQ== "@types/jss@^9.5.6": - version "9.5.7" - resolved "https://registry.yarnpkg.com/@types/jss/-/jss-9.5.7.tgz#fa57a6d0b38a3abef8a425e3eb6a53495cb9d5a0" - integrity sha512-OZimStu2QdDMtZ0h72JXqvLVbWUjXd5ZLk8vxLmfuC/nM1AabRyyGoxSufnzixrbpEcVcyy/JV5qeQu2JnjVZw== + version "9.5.8" + resolved "https://registry.yarnpkg.com/@types/jss/-/jss-9.5.8.tgz#258391f42211c042fc965508d505cbdc579baa5b" + integrity sha512-bBbHvjhm42UKki+wZpR89j73ykSXg99/bhuKuYYePtpma3ZAnmeGnl0WxXiZhPGsIfzKwCUkpPC0jlrVMBfRxA== dependencies: csstype "^2.0.0" indefinite-observable "^1.0.1" @@ -1290,9 +1311,14 @@ "@types/node" "*" "@types/node@*": - version "11.9.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.5.tgz#011eece9d3f839a806b63973e228f85967b79ed3" - integrity sha512-vVjM0SVzgaOUpflq4GYBvCpozes8OgIIS5gVXVka+OfK3hvnkC1i93U8WiY2OtNE4XUWyyy/86Kf6e0IHTQw1Q== + version "11.11.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.3.tgz#7c6b0f8eaf16ae530795de2ad1b85d34bf2f5c58" + integrity sha512-wp6IOGu1lxsfnrD+5mX6qwSwWuqsdkKKxTN4aQc4wByHAKZJf9/D4KXPQ1POUjEbnCP5LMggB0OEFNY9OTsMqg== + +"@types/node@10.12.30": + version "10.12.30" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.30.tgz#4c2b4f0015f214f8158a347350481322b3b29b2f" + integrity sha512-nsqTN6zUcm9xtdJiM9OvOJ5EF0kOI8f1Zuug27O/rgtxCRJHGqncSWfCMZUP852dCKPsDsYXGvBhxfRjDBkF5Q== "@types/node@10.14.1": version "10.14.1" @@ -1305,14 +1331,14 @@ integrity sha512-db6pZL5QY3JrlCHBhYQzYDci0xnoDuxfseUuguLRr3JNk+bnCfpkK6p8quiUDyO8A0vbpBKkk59Fw125etrNeA== "@types/prop-types@*": - version "15.5.9" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.9.tgz#f2d14df87b0739041bc53a7d75e3d77d726a3ec0" - integrity sha512-Nha5b+jmBI271jdTMwrHiNXM+DvThjHOfyZtMX9kj/c/LUj2xiLHsG/1L3tJ8DjAoQN48cHwUwtqBotjyXaSdQ== + version "15.7.0" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.0.tgz#4c48fed958d6dcf9487195a0ef6456d5f6e0163a" + integrity sha512-eItQyV43bj4rR3JPV0Skpl1SncRCdziTEK9/v8VwXmV6d/qOUO8/EuWeHBbCZcsfSHfzI5UyMJLCSXtxxznyZg== "@types/q@^1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" - integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== "@types/react-transition-group@^2.0.8": version "2.0.16" @@ -1322,9 +1348,9 @@ "@types/react" "*" "@types/react@*": - version "16.8.5" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.5.tgz#03b9a6597bc20f6eaaed43f377a160f7e41c2b90" - integrity sha512-8LRySaaSJVLNZb2dbOGvGmzn88cbAfrgDpuWy+6lLgQ0OJFgHHvyuaCX4/7ikqJlpmCPf4uazJAZcfTQRdJqdQ== + version "16.8.8" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.8.tgz#4b60a469fd2469f7aa6eaa0f8cfbc51f6d76e662" + integrity sha512-xwEvyet96u7WnB96kqY0yY7qxx/pEpU51QeACkKFtrgjjXITQn0oO1iwPEraXVgh10ZFPix7gs1R4OJXF7P5sg== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -1482,45 +1508,21 @@ "@webassemblyjs/wast-parser" "1.7.6" mamacro "^0.0.3" -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== - dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - "@webassemblyjs/floating-point-hex-parser@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.6.tgz#7cb37d51a05c3fe09b464ae7e711d1ab3837801f" integrity sha512-VBOZvaOyBSkPZdIt5VBMg3vPWxouuM13dPXGWI1cBh3oFLNcFJ8s9YA7S9l4mPI7+Q950QqOmqj06oa83hNWBA== -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== - "@webassemblyjs/helper-api-error@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.6.tgz#99b7e30e66f550a2638299a109dda84a622070ef" integrity sha512-SCzhcQWHXfrfMSKcj8zHg1/kL9kb3aa5TN4plc/EREOs5Xop0ci5bdVBApbk2yfVi8aL+Ly4Qpp3/TRAUInjrg== -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== - "@webassemblyjs/helper-buffer@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.6.tgz#ba0648be12bbe560c25c997e175c2018df39ca3e" integrity sha512-1/gW5NaGsEOZ02fjnFiU8/OEEXU1uVbv2um0pQ9YVL3IHSkyk6xOwokzyqqO1qDZQUAllb+V8irtClPWntbVqw== -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== - "@webassemblyjs/helper-code-frame@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.6.tgz#5a94d21b0057b69a7403fca0c253c3aaca95b1a5" @@ -1528,23 +1530,11 @@ dependencies: "@webassemblyjs/wast-printer" "1.7.6" -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== - dependencies: - "@webassemblyjs/wast-printer" "1.8.5" - "@webassemblyjs/helper-fsm@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.6.tgz#ae1741c6f6121213c7a0b587fb964fac492d3e49" integrity sha512-HCS6KN3wgxUihGBW7WFzEC/o8Eyvk0d56uazusnxXthDPnkWiMv+kGi9xXswL2cvfYfeK5yiM17z2K5BVlwypw== -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== - "@webassemblyjs/helper-module-context@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.6.tgz#116d19a51a6cebc8900ad53ca34ff8269c668c23" @@ -1552,24 +1542,11 @@ dependencies: mamacro "^0.0.3" -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== - dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" - "@webassemblyjs/helper-wasm-bytecode@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.6.tgz#98e515eaee611aa6834eb5f6a7f8f5b29fefb6f1" integrity sha512-PzYFCb7RjjSdAOljyvLWVqd6adAOabJW+8yRT+NWhXuf1nNZWH+igFZCUK9k7Cx7CsBbzIfXjJc7u56zZgFj9Q== -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== - "@webassemblyjs/helper-wasm-section@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.6.tgz#783835867bdd686df7a95377ab64f51a275e8333" @@ -1580,16 +1557,6 @@ "@webassemblyjs/helper-wasm-bytecode" "1.7.6" "@webassemblyjs/wasm-gen" "1.7.6" -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/ieee754@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.6.tgz#c34fc058f2f831fae0632a8bb9803cf2d3462eb1" @@ -1597,13 +1564,6 @@ dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== - dependencies: - "@xtuc/ieee754" "^1.2.0" - "@webassemblyjs/leb128@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.6.tgz#197f75376a29f6ed6ace15898a310d871d92f03b" @@ -1611,23 +1571,11 @@ dependencies: "@xtuc/long" "4.2.1" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== - dependencies: - "@xtuc/long" "4.2.2" - "@webassemblyjs/utf8@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.6.tgz#eb62c66f906af2be70de0302e29055d25188797d" integrity sha512-oId+tLxQ+AeDC34ELRYNSqJRaScB0TClUU6KQfpB8rNT6oelYlz8axsPhf6yPTg7PBJ/Z5WcXmUYiHEWgbbHJw== -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== - "@webassemblyjs/wasm-edit@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.6.tgz#fa41929160cd7d676d4c28ecef420eed5b3733c5" @@ -1642,20 +1590,6 @@ "@webassemblyjs/wasm-parser" "1.7.6" "@webassemblyjs/wast-printer" "1.7.6" -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" - "@webassemblyjs/wasm-gen@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.6.tgz#695ac38861ab3d72bf763c8c75e5f087ffabc322" @@ -1667,17 +1601,6 @@ "@webassemblyjs/leb128" "1.7.6" "@webassemblyjs/utf8" "1.7.6" -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - "@webassemblyjs/wasm-opt@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.6.tgz#fbafa78e27e1a75ab759a4b658ff3d50b4636c21" @@ -1688,16 +1611,6 @@ "@webassemblyjs/wasm-gen" "1.7.6" "@webassemblyjs/wasm-parser" "1.7.6" -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wasm-parser@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.6.tgz#84eafeeff405ad6f4c4b5777d6a28ae54eed51fe" @@ -1710,18 +1623,6 @@ "@webassemblyjs/leb128" "1.7.6" "@webassemblyjs/utf8" "1.7.6" -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - "@webassemblyjs/wast-parser@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.6.tgz#ca4d20b1516e017c91981773bd7e819d6bd9c6a7" @@ -1735,18 +1636,6 @@ "@xtuc/long" "4.2.1" mamacro "^0.0.3" -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" - "@xtuc/long" "4.2.2" - "@webassemblyjs/wast-printer@1.7.6": version "1.7.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.6.tgz#a6002c526ac5fa230fe2c6d2f1bdbf4aead43a5e" @@ -1756,15 +1645,6 @@ "@webassemblyjs/wast-parser" "1.7.6" "@xtuc/long" "4.2.1" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - "@xtuc/long" "4.2.2" - "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -1775,11 +1655,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8" integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g== -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -1826,7 +1701,7 @@ acorn-globals@^4.1.0, acorn-globals@^4.3.0: acorn "^6.0.1" acorn-walk "^6.0.1" -acorn-jsx@^5.0.0: +acorn-jsx@^5.0.0, acorn-jsx@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== @@ -1841,10 +1716,10 @@ acorn@^5.0.0, acorn@^5.5.3, acorn@^5.6.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4, acorn@^6.0.5: - version "6.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" - integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw== +acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4, acorn@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== add-stream@^1.0.0: version "1.0.0" @@ -1875,24 +1750,24 @@ ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== ajv@^6.0.1, ajv@^6.1.0, ajv@^6.5.3, ajv@^6.5.5: - version "6.9.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.2.tgz#4927adb83e7f48e5a32b45729744c71ec39c9c7b" - integrity sha512-4UFy0/LgDo7Oa/+wOAlj44tp9K78u38E5/359eSrqEp1Z5PdVfimCcs7SluXMP755RUQu6d2b4AvF0R1C9RZjg== + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -alphanum-sort@^1.0.0: +alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= ansi-colors@^3.0.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: version "3.2.0" @@ -1914,10 +1789,10 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" - integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== +ansi-regex@^4.0.0, ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== ansi-styles@^2.2.1: version "2.2.1" @@ -1944,7 +1819,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -apollo-link@1.2.11: +apollo-link@1.2.11, apollo-link@^1.2.3: version "1.2.11" resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.11.tgz#493293b747ad3237114ccd22e9f559e5e24a194d" integrity sha512-PQvRCg13VduLy3X/0L79M6uOpTh5iHdxnxYuo8yL7sJlWybKRJwsv4IcRBJpMFbChOOaHY7Og9wgPo6DLKDKDA== @@ -1954,22 +1829,7 @@ apollo-link@1.2.11: tslib "^1.9.3" zen-observable-ts "^0.8.18" -apollo-link@^1.2.3: - version "1.2.8" - resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.8.tgz#0f252adefd5047ac1a9f35ba9439d216587dcd84" - integrity sha512-lfzGRxhK9RmiH3HPFi7TIEBhhDY9M5a2ZDnllcfy5QDk7cCQHQ1WQArcw1FK0g1B+mV4Kl72DSrlvZHZJEolrA== - dependencies: - zen-observable-ts "^0.8.15" - -apollo-utilities@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.1.3.tgz#a8883c0392f6b46eac0d366204ebf34be9307c87" - integrity sha512-pF9abhiClX5gfj/WFWZh8DiI33nOLGxRhXH9ZMquaM1V8bhq1WLFPt2QjShWH3kGQVeIGUK+FQefnhe+ZaaAYg== - dependencies: - fast-json-stable-stringify "^2.0.0" - tslib "^1.9.3" - -apollo-utilities@^1.2.1: +apollo-utilities@^1.0.1, apollo-utilities@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.2.1.tgz#1c3a1ebf5607d7c8efe7636daaf58e7463b41b3c" integrity sha512-Zv8Udp9XTSFiN8oyXOjf6PMHepD4yxxReLsl6dPUy5Ths7jti3nmlBzZUOxuTWRwZn0MoclqL7RQ5UEJN8MAxg== @@ -2166,9 +2026,9 @@ astral-regex@^1.0.0: integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== async-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= + version "1.0.2" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.2.tgz#8b8a7ca2a658f927e9f307d6d1a42f4199f0f735" + integrity sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg== async-limiter@~1.0.0: version "1.0.0" @@ -2192,37 +2052,45 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +asyncro@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/asyncro/-/asyncro-3.0.0.tgz#3c7a732e263bc4a42499042f48d7d858e9c0134e" + integrity sha512-nEnWYfrBmA3taTiuiOoZYmgJ/CNrSoQLeLs29SeLcPu60yaw/mHDBHV0iOZ051fTvsTHxpCY+gXibqT9wbQYfg== + atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^9.3.1: - version "9.4.9" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.4.9.tgz#0d3eb86bc1d1228551abcf55220d6fd246b6cb31" - integrity sha512-OyUl7KvbGBoFQbGQu51hMywz1aaVeud/6uX8r1R1DNcqFvqGUUy6+BDHnAZE8s5t5JyEObaSw+O1DpAdjAmLuw== +auto-bind@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-2.0.0.tgz#9a55a461b521f58daf955169203bed1a07a970a9" + integrity sha512-rvRBv0/O7iriUMqSzTDhAfyAD1vVnElAEruo5rMSFeYLA0iKDEzLPSJiwMnL86+IPpTlhfOIAzjoKZ9TaySYdA== + +autoprefixer@^6.3.1: + version "6.7.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" + integrity sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ= + dependencies: + browserslist "^1.7.6" + caniuse-db "^1.0.30000634" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^5.2.16" + postcss-value-parser "^3.2.3" + +autoprefixer@^9.0.0, autoprefixer@^9.3.1: + version "9.4.10" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.4.10.tgz#e1be61fc728bacac8f4252ed242711ec0dcc6a7b" + integrity sha512-XR8XZ09tUrrSzgSlys4+hy5r2/z4Jp7Ag3pHm31U4g/CTccYPOVe19AkaJ4ey/vRd1sfj+5TtuD6I0PXtutjvQ== dependencies: browserslist "^4.4.2" - caniuse-lite "^1.0.30000939" + caniuse-lite "^1.0.30000940" normalize-range "^0.1.2" num2fraction "^1.2.2" postcss "^7.0.14" postcss-value-parser "^3.3.1" -awesome-typescript-loader@5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz#a41daf7847515f4925cdbaa3075d61f289e913fc" - integrity sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g== - dependencies: - chalk "^2.4.1" - enhanced-resolve "^4.0.0" - loader-utils "^1.1.0" - lodash "^4.17.5" - micromatch "^3.1.9" - mkdirp "^0.5.1" - source-map-support "^0.5.3" - webpack-log "^1.2.0" - aws-sdk@2.421.0: version "2.421.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.421.0.tgz#39c8066b103ef01849f7da587cec40cc874f2fbc" @@ -2439,6 +2307,11 @@ babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= +babel-plugin-transform-async-to-promises@^0.8.3: + version "0.8.5" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-promises/-/babel-plugin-transform-async-to-promises-0.8.5.tgz#8d9817a4a99d36df57616857650522b7c2be511c" + integrity sha512-1aDXPwLbgMpXyR1XBntTIBDKidxCuJW4zd8LByK6pJpflXL2WXtV5CNPeGMJjZnoHtNX0QS+JikXRJQAupjRVQ== + babel-plugin-transform-object-rest-spread@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" @@ -2469,9 +2342,9 @@ babel-preset-jest@^24.3.0: babel-plugin-jest-hoist "^24.3.0" babel-preset-react-app@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-7.0.1.tgz#8dd7fef73fba124a6e140d245185ca657a943313" - integrity sha512-cic2V+GftWwt82XNMKGxvkFAVvuaBISy0/mzNLLPlALXXJxUvxJgVy2DI8HVk311oewJsmBiu/unE4wINUCvkg== + version "7.0.2" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-7.0.2.tgz#d01ae973edc93b9f1015cb0236dd55889a584308" + integrity sha512-mwCk/u2wuiO8qQqblN5PlDa44taY0acq7hw6W+a70W522P7a9mIcdggL1fe5/LgAT7tqCq46q9wwhqaMoYKslQ== dependencies: "@babel/core" "7.2.2" "@babel/plugin-proposal-class-properties" "7.3.0" @@ -2564,11 +2437,16 @@ babylon@7.0.0-beta.47: resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.47.tgz#6d1fa44f0abec41ab7c780481e62fd9aafbdea80" integrity sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ== -babylon@^6.18.0: +babylon@^6.15.0, babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + integrity sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -2604,6 +2482,13 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bdd-stdin@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bdd-stdin/-/bdd-stdin-0.2.0.tgz#04e66aa480e0e0df861e288a4062fb8557db2441" + integrity sha1-BOZqpIDg4N+GHiiKQGL7hVfbJEE= + dependencies: + mock-stdin "0.3.0" + bfj@6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" @@ -2614,6 +2499,11 @@ bfj@6.1.1: hoopy "^0.1.2" tryer "^1.0.0" +big.js@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" + integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -2624,6 +2514,14 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + bluebird@^3.5.1, bluebird@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" @@ -2710,6 +2608,14 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +brotli-size@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/brotli-size/-/brotli-size-0.0.3.tgz#1d3855b38f182591a6f69da1516131676e5f62f2" + integrity sha512-bBIdd8uUGxKGldAVykxOqPegl+HlIm4FpXJamwWw5x77WCE8jO7AhXFE1YXOhOB28gS+2pTQete0FqRE6U5hQQ== + dependencies: + duplexer "^0.1.1" + iltorb "^2.0.5" + browser-process-hrtime@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" @@ -2790,6 +2696,14 @@ browserslist@4.4.1: electron-to-chromium "^1.3.103" node-releases "^1.1.3" +browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + integrity sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk= + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.4.2.tgz#6ea8a74d6464bb0bd549105f659b41197d8f0ba2" @@ -2818,6 +2732,38 @@ btoa@^1.1.2: resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== +buble@^0.19.6: + version "0.19.7" + resolved "https://registry.yarnpkg.com/buble/-/buble-0.19.7.tgz#1dfd080ab688101aad5388d3304bc82601a244fd" + integrity sha512-YLgWxX/l+NnfotydBlxqCMPR4FREE4ubuHphALz0FxQ7u2hp3BzxTKQ4nKpapOaRJfEm1gukC68KnT2OymRK0g== + dependencies: + acorn "^6.1.1" + acorn-dynamic-import "^4.0.0" + acorn-jsx "^5.0.1" + chalk "^2.4.2" + magic-string "^0.25.2" + minimist "^1.2.0" + os-homedir "^1.0.1" + regexpu-core "^4.5.4" + +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2847,6 +2793,11 @@ builtin-modules@^1.1.1: resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= +builtin-modules@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.0.0.tgz#1e587d44b006620d90286cc7a9238bbc6129cab1" + integrity sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg== + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -2993,9 +2944,19 @@ camelcase@^4.1.0: integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= camelcase@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" - integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + version "5.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.2.0.tgz#e7522abda5ed94cc0489e1b8466610e88404cf45" + integrity sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ== + +caniuse-api@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" + integrity sha1-tTTnxzTE+B7F++isoq0kNUuWLGw= + dependencies: + browserslist "^1.3.6" + caniuse-db "^1.0.30000529" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" caniuse-api@^3.0.0: version "3.0.0" @@ -3007,10 +2968,15 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000905, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000939: - version "1.0.30000939" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000939.tgz#b9ab7ac9e861bf78840b80c5dfbc471a5cd7e679" - integrity sha512-oXB23ImDJOgQpGjRv1tCtzAvJr4/OvrHi5SO2vUgB0g0xpdZZoA/BxfImiWfdwoYdUTtQrPsXsvYU/dmCSM8gg== +caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: + version "1.0.30000947" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000947.tgz#cf9b36f9456bd926fa17a912436ebd2730053193" + integrity sha512-hCrT/wM4PuUHif1+2XbQbutQJynvTNWK3yGzIgnyHdhtuuuUfyvNHKbpYIjWzYT3MrARw2zew6R44lWyxhE+Qg== + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000905, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000939, caniuse-lite@^1.0.30000940: + version "1.0.30000947" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000947.tgz#c30305e9701449c22e97f4e9837cea3d76aa3273" + integrity sha512-ubgBUfufe5Oi3W1+EHyh2C3lfBIEcZ6bTuvl5wNOpIuRB978GF/Z+pQ7pGGUpeYRB0P+8C7i/3lt6xkeu2hwnA== capture-exit@^1.2.0: version "1.2.0" @@ -3043,7 +3009,7 @@ chalk@2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3161,6 +3127,13 @@ circular-json@^0.3.1: resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + integrity sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA== + dependencies: + chalk "^1.1.3" + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -3274,6 +3247,13 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + integrity sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0= + dependencies: + q "^1.1.2" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -3300,7 +3280,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0, color-convert@^1.9.1: +color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -3317,6 +3297,13 @@ color-name@^1.0.0: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + integrity sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE= + dependencies: + color-name "^1.0.0" + color-string@^1.5.2: version "1.5.3" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" @@ -3325,13 +3312,14 @@ color-string@^1.5.2: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" - integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w== +color@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" + integrity sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q= dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" + clone "^1.0.2" + color-convert "^1.3.0" + color-string "^0.3.0" color@^3.0.0: version "3.1.0" @@ -3341,23 +3329,19 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colornames@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96" - integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y= - -colors@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" - integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== - -colorspace@1.1.x: - version "1.1.1" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.1.tgz#9ac2491e1bc6f8fb690e2176814f8d091636d972" - integrity sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw== +colormin@^1.0.5: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" + integrity sha1-6i90IKcrlogaOKrlnsEkpvcpgTM= dependencies: - color "3.0.x" - text-hex "1.0.x" + color "^0.11.0" + css-color-names "0.0.4" + has "^1.0.1" + +colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= columnify@^1.5.4: version "1.5.4" @@ -3384,7 +3368,7 @@ commander@2.17.x, commander@~2.17.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@2.19.0, commander@^2.11.0, commander@^2.12.1, commander@^2.14.1, commander@^2.9.0: +commander@2.19.0, commander@^2.11.0, commander@^2.12.1, commander@^2.14.1, commander@^2.19.0, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== @@ -3457,10 +3441,17 @@ concat-stream@^1.4.10, concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" -confusing-browser-globals@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.5.tgz#0171050cfdd4261e278978078bc00c4d88e135f4" - integrity sha512-tHo1tQL/9Ox5RELbkCAJhnViqWlzBz3MG1bB2czbHjH2mWd4aYUgNCNLfysFL7c4LoDws7pjg2tj48Gmpw4QHA== +concat-with-sourcemaps@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== + dependencies: + source-map "^0.6.1" + +confusing-browser-globals@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.6.tgz#5918188e8244492cdd46d6be1cab60edef3063ce" + integrity sha512-GzyX86c2TvaagAOR+lHL2Yq4T4EnoBcnojZBcNbxVKSunxmGTnioXHR5Mo2ha/XnCoQw8eurvj6Ta+SwPEPkKg== connect-history-api-fallback@^1.3.0: version "1.6.0" @@ -3708,18 +3699,6 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copyfiles@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.1.0.tgz#0e2a4188162d6b2f3c5adfe34e9c0bd564d23164" - integrity sha512-cAeDE0vL/koE9WSEGxqPpSyvU638Kgfu6wfrnj7kqp9FWa1CWsU54Coo6sdYZP4GstWa39tL/wIVJWfXcujgNA== - dependencies: - glob "^7.0.5" - minimatch "^3.0.3" - mkdirp "^0.5.1" - noms "0.0.0" - through2 "^2.0.1" - yargs "^11.0.0" - core-js@2.6.4: version "2.6.4" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.4.tgz#b8897c062c4d769dd30a0ac5c73976c47f92ea0d" @@ -3730,7 +3709,7 @@ core-js@^1.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.4.0, core-js@^2.5.0: +core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7: version "2.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895" integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A== @@ -3740,6 +3719,19 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892" + integrity sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A== + dependencies: + is-directory "^0.3.1" + js-yaml "^3.4.3" + minimist "^1.2.0" + object-assign "^4.1.0" + os-homedir "^1.0.1" + parse-json "^2.2.0" + require-from-string "^1.1.0" + cosmiconfig@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" @@ -3875,6 +3867,18 @@ css-loader@1.0.0: postcss-value-parser "^3.3.0" source-list-map "^2.0.0" +css-modules-loader-core@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16" + integrity sha1-WQhmgpShvs0mGuCkziGwtVHyHRY= + dependencies: + icss-replace-symbols "1.1.0" + postcss "6.0.1" + postcss-modules-extract-imports "1.1.0" + postcss-modules-local-by-default "1.2.0" + postcss-modules-scope "1.1.0" + postcss-modules-values "1.3.0" + css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" @@ -3948,9 +3952,9 @@ css-what@2.1, css-what@^2.1.2: integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== cssdb@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.3.0.tgz#2e1229900616f80c66ff2d568ea2b4f92db1c78c" - integrity sha512-VHPES/+c9s+I0ryNj+PXvp84nz+ms843z/efpaEINwP/QfGsINL3gpLp5qjapzDNzNzbXxur8uxKxSXImrg4ag== + version "4.4.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" + integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== cssesc@^0.1.0: version "0.1.0" @@ -4020,7 +4024,45 @@ cssnano-util-same-parent@^4.0.0: resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== -cssnano@^4.1.0: +cssnano@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" + integrity sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg= + dependencies: + autoprefixer "^6.3.1" + decamelize "^1.1.2" + defined "^1.0.0" + has "^1.0.1" + object-assign "^4.0.1" + postcss "^5.0.14" + postcss-calc "^5.2.0" + postcss-colormin "^2.1.8" + postcss-convert-values "^2.3.4" + postcss-discard-comments "^2.0.4" + postcss-discard-duplicates "^2.0.1" + postcss-discard-empty "^2.0.1" + postcss-discard-overridden "^0.1.1" + postcss-discard-unused "^2.2.1" + postcss-filter-plugins "^2.0.0" + postcss-merge-idents "^2.1.5" + postcss-merge-longhand "^2.0.1" + postcss-merge-rules "^2.0.3" + postcss-minify-font-values "^1.0.2" + postcss-minify-gradients "^1.0.1" + postcss-minify-params "^1.0.4" + postcss-minify-selectors "^2.0.4" + postcss-normalize-charset "^1.1.0" + postcss-normalize-url "^3.0.7" + postcss-ordered-values "^2.1.0" + postcss-reduce-idents "^2.2.2" + postcss-reduce-initial "^1.0.0" + postcss-reduce-transforms "^1.0.3" + postcss-svgo "^2.1.1" + postcss-unique-selectors "^2.0.2" + postcss-value-parser "^3.2.3" + postcss-zindex "^2.0.1" + +cssnano@^4.1.0, cssnano@^4.1.7: version "4.1.10" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== @@ -4037,6 +4079,14 @@ csso@^3.5.1: dependencies: css-tree "1.0.0-alpha.29" +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + integrity sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U= + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0", cssom@^0.3.4: version "0.3.6" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.6.tgz#f85206cee04efa841f3c5982a74ba96ab20d65ad" @@ -4050,9 +4100,9 @@ cssstyle@^1.0.0, cssstyle@^1.1.1: cssom "0.3.x" csstype@^2.0.0, csstype@^2.2.0, csstype@^2.5.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.2.tgz#3043d5e065454579afc7478a18de41909c8a2f01" - integrity sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow== + version "2.6.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa" + integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg== currently-unhandled@^0.4.1: version "0.4.1" @@ -4066,13 +4116,6 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - integrity sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8= - dependencies: - es5-ext "^0.10.9" - damerau-levenshtein@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" @@ -4167,6 +4210,13 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -4187,11 +4237,6 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.1.0.tgz#a612626ce4803da410d77554bfd80361599c034d" - integrity sha512-/TnecbwXEdycfbsM2++O3eGiatEFHjjNciHEwJclM+T5Kd94qD1AP+2elP/Mq0L5b9VZJao5znR01Mz6eX8Seg== - deepmerge@3.2.0, deepmerge@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.0.tgz#58ef463a57c08d376547f8869fdc5bcee957f44e" @@ -4255,6 +4300,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + del@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" @@ -4282,7 +4332,7 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -dependency-graph@0.8.0, dependency-graph@^0.8.0: +dependency-graph@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.8.0.tgz#2da2d35ed852ecc24a5d6c17788ba57c3708755b" integrity sha512-DCvzSq2UiMsuLnj/9AL484ummEgLtZIcRS7YvtO38QnpX3vqh9nJ8P+zhu8Ja+SmLrBHO2iDbva20jq38qvBkQ== @@ -4305,11 +4355,6 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - detect-indent@5.0.0, detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" @@ -4322,7 +4367,7 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" -detect-libc@^1.0.2: +detect-libc@^1.0.2, detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= @@ -4345,15 +4390,6 @@ detect-port-alt@1.1.6: address "^1.0.1" debug "^2.6.0" -diagnostics@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a" - integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ== - dependencies: - colorspace "1.1.x" - enabled "1.0.x" - kuler "1.0.x" - diff-sequences@^24.3.0: version "24.3.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975" @@ -4552,10 +4588,10 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== -electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.113: - version "1.3.113" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz#b1ccf619df7295aea17bc6951dc689632629e4a9" - integrity sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g== +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.113: + version "1.3.116" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz#1dbfee6a592a0c14ade77dbdfe54fef86387d702" + integrity sha512-NKwKAXzur5vFCZYBHpdWjTMO8QptNLNP80nItkSIgUOapPAo9Uia+RvkCaZJtO7fhQaVElSvBPWEc2ku6cKsPA== elegant-spinner@^1.0.1: version "1.0.1" @@ -4590,13 +4626,6 @@ emojis-list@^2.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= -enabled@1.0.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93" - integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M= - dependencies: - env-variable "0.0.x" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -4616,7 +4645,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== @@ -4630,11 +4659,6 @@ entities@^1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -env-variable@0.0.x: - version "0.0.5" - resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88" - integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA== - errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -4670,31 +4694,10 @@ es-to-primitive@^1.2.0: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.48" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.48.tgz#9a0b31eeded39e64453bcedf6f9d50bbbfb43850" - integrity sha512-CdRvPlX/24Mj5L4NVxTs4804sxiS2CjVprgCmrgoDkdmjdY4D+ySHa7K3jJf8R40dFg0tIm3z/dk326LrnuSGw== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.1" - next-tick "1" - -es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" +es6-promisify@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.1.tgz#6edaa45f3bd570ffe08febce66f7116be4b1cdb6" + integrity sha512-J3ZkwbEnnO+fGAKrjVpeUAnZshAdfZvbhQpqfIH9kSAspReRC4nJnu8ewm55b4y9ElyeuhCTzJD0XiH8Tsbhlw== escape-html@~1.0.3: version "1.0.3" @@ -4719,11 +4722,11 @@ escodegen@^1.11.0, escodegen@^1.9.1: source-map "~0.6.1" eslint-config-react-app@^3.0.6: - version "3.0.7" - resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-3.0.7.tgz#d58c9216ff285e2b4de0eb8403c28b0600e45b3e" - integrity sha512-Mmmc9lIY/qvX6OEV09+ZLqVTz1aX8VVCrgCjBHXdmMGaC+pldD+87oj3BiJWXMSfcYs5iOo9gy0mGnQ8f/fMsQ== + version "3.0.8" + resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-3.0.8.tgz#6f606828ba30bafee7d744c41cd07a3fea8f3035" + integrity sha512-Ovi6Bva67OjXrom9Y/SLJRkrGqKhMAL0XCH8BizPhjEVEhYczl2ZKiNZI2CuqO5/CJwAfMwRXAVGY0KToWr1aA== dependencies: - confusing-browser-globals "^1.0.5" + confusing-browser-globals "^1.0.6" eslint-import-resolver-node@^0.3.1: version "0.3.2" @@ -4809,9 +4812,9 @@ eslint-scope@3.7.1: estraverse "^4.1.1" eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" - integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.2.tgz#5f10cd6cabb1965bf479fa65745673439e21cb0e" + integrity sha512-5q1+B/ogmHl8+paxtOKx38Z8LtWkVGuNt3+GQNErqwLl6ViNp/gdJGMCjZNxZ8j/VYjDNZ2Fo+eQc1TAVPIzbg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -4879,6 +4882,11 @@ espree@^4.0.0: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -4908,6 +4916,21 @@ estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + integrity sha1-va/oCVOD2EFNXcLs9MkXO225QS4= + +estree-walker@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" + integrity sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig== + +estree-walker@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.0.tgz#5d865327c44a618dde5699f763891ae31f257dae" + integrity sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw== + esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -5044,12 +5067,10 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== expect@^23.6.0: version "23.6.0" @@ -5207,11 +5228,6 @@ fast-levenshtein@~2.0.4: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fast-safe-stringify@^2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2" - integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg== - fastparse@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" @@ -5251,17 +5267,12 @@ fbjs@^0.8.1: setimmediate "^1.0.5" ua-parser-js "^0.7.18" -fecha@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" - integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg== - figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== -figures@^1.7.0: +figures@^1.0.1, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= @@ -5305,7 +5316,7 @@ fileset@^2.0.2, fileset@^2.0.3: glob "^7.0.3" minimatch "^3.0.3" -filesize@3.6.1: +filesize@3.6.1, filesize@^3.5.11: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== @@ -5363,12 +5374,12 @@ find-cache-dir@^1.0.0: pkg-dir "^2.0.0" find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" - make-dir "^1.0.0" + make-dir "^2.0.0" pkg-dir "^3.0.0" find-parent-dir@^0.3.0: @@ -5398,16 +5409,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= - dependencies: - detect-file "^1.0.0" - is-glob "^3.1.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - flat-cache@^1.2.1: version "1.3.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" @@ -5433,6 +5434,14 @@ flow-parser@0.94.0: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.94.0.tgz#bae54cd3365c800dbe8062f82611a85c5ce872f4" integrity sha512-zKVDm2rq9Z4GZDNT2GjEtoSat4NW/aZBkHsXs/XNnf39VOAzB0ufkxpuS6XgwuEaMUnhZEAA0gk7ASGxP/TQCQ== +flow-remove-types@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-1.2.3.tgz#6131aefc7da43364bb8b479758c9dec7735d1a18" + integrity sha512-ypq/U3V+t9atYiOuSJd40tekCra03EHKoRsiK/wXGrsZimuum0kdwVY7Yv0HTaoXgHW1WiayomYd+Q3kkvPl9Q== + dependencies: + babylon "^6.15.0" + vlq "^0.2.1" + flush-write-stream@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" @@ -5530,6 +5539,11 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" @@ -5539,16 +5553,7 @@ fs-extra@7.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^4.0.1, fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^7.0.0: +fs-extra@7.0.1, fs-extra@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -5557,6 +5562,24 @@ fs-extra@^7.0.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^4.0.1, fs-extra@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + integrity sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" @@ -5628,6 +5651,13 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +generic-names@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917" + integrity sha1-LXhqEhruUIh2eWk56OO/+DbCCRc= + dependencies: + loader-utils "^0.2.16" + get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" @@ -5722,6 +5752,11 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -5750,7 +5785,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.3, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: +glob@7.1.3, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -5769,26 +5804,6 @@ global-modules@2.0.0: dependencies: global-prefix "^3.0.0" -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - global-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" @@ -5808,6 +5823,11 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalyzer@^0.1.0: + version "0.1.4" + resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.4.tgz#bc8e273afe1ac7c24eea8def5b802340c5cc534f" + integrity sha512-LeguVWaxgHN0MNbWC6YljNMzHkrCny9fzjmEUdnF1kQ7wATFD1RHFRqA1qxaX2tgxGENlcxjOflopBwj3YZiXA== + globby@8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" @@ -5832,6 +5852,11 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +globrex@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" + integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -5854,183 +5879,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -graphql-code-generator@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-code-generator/-/graphql-code-generator-0.17.0.tgz#7e76f7c2e7df69af89c478094137385c2761ce4d" - integrity sha512-91KIkyAhdfoYvd2tArwvPql14iaC9x9PN0CmFM2ubnceQZFsIUgPHr4Gmpv+YNYSY97ePmuP6Ui0IHZydvrTPw== - dependencies: - "@types/babylon" "6.16.5" - "@types/is-glob" "4.0.0" - "@types/prettier" "1.16.1" - "@types/valid-url" "1.0.2" - babel-types "7.0.0-beta.3" - babylon "7.0.0-beta.47" - chalk "2.4.2" - change-case "3.1.0" - chokidar "2.1.2" - commander "2.19.0" - common-tags "1.8.0" - detect-indent "5.0.0" - glob "7.1.3" - graphql-codegen-core "0.17.0" - graphql-config "2.2.1" - graphql-import "0.7.1" - graphql-tag-pluck "0.5.0" - graphql-toolkit "0.0.5" - graphql-tools "4.0.4" - indent-string "3.2.0" - inquirer "6.2.2" - is-glob "4.0.0" - is-valid-path "0.1.1" - js-yaml "3.12.1" - json-to-pretty-yaml "1.2.2" - listr "0.14.3" - listr-update-renderer "0.5.0" - log-symbols "2.2.0" - log-update "2.3.0" - mkdirp "0.5.1" - prettier "1.16.4" - request "2.88.0" - valid-url "1.0.9" - -graphql-codegen-add@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-add/-/graphql-codegen-add-0.17.0.tgz#b7ceb77f5328ed25fc4c097023b61e05cd903f16" - integrity sha512-wylxGAxggIWlN44FcpX4XMauAk4/lEijtlhwXfDRYRoI58nzzwP9n3LGuAP73jqZrp0ZdmBD53l9xvnX62ixPA== - dependencies: - graphql-codegen-core "0.17.0" - -graphql-codegen-core@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-core/-/graphql-codegen-core-0.17.0.tgz#e0e23cf0e1138ff3e75912604cf04aae82aa27be" - integrity sha512-3WULDb+XaRrSsVbTU8VBf7yzGGnW9pAKl+wE3p2NjaKPm0IPBKlWrDtVCUPpTXE0oANv0V4ytsHjMMJ8oTtRLg== - dependencies: - chalk "2.4.2" - change-case "3.1.0" - common-tags "1.8.0" - graphql-tag "2.10.1" - graphql-toolkit "0.0.5" - graphql-tools "4.0.4" - ts-log "2.1.4" - winston "3.2.1" - -graphql-codegen-flow-documents@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-flow-documents/-/graphql-codegen-flow-documents-0.17.0.tgz#8de2460e887caaafab793e101424224693193122" - integrity sha512-rdfUHY1scin+q12L6tqwM858zmvSuwS1ELzLjyCAaCZABc1g6Wz5BzSPzsGJovfRu/SFUl/+p6E/iDCmKoTsog== - dependencies: - graphql-codegen-core "0.17.0" - graphql-codegen-flow "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - -graphql-codegen-flow-resolvers@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-flow-resolvers/-/graphql-codegen-flow-resolvers-0.17.0.tgz#1609ae51177ff8cdcf9695f60364709410a2050e" - integrity sha512-NsJto9ARVm1DazWy7kKlQsgiVDaA8tQzMyHUzsA2Zq1o5yN/y2QlesX5DeBvNITtPMAFSwJgSyFQchHOWNG7eg== - dependencies: - graphql-codegen-core "0.17.0" - graphql-codegen-flow "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - -graphql-codegen-flow@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-flow/-/graphql-codegen-flow-0.17.0.tgz#0aede0a16dd3bb36cd6653ef3c3643d16aad78d4" - integrity sha512-AlZykOyDuIzHQXgf5fYCglpJZi4SqN1XmGXo1VsiDhcY2ISCp/WktmVKPSEiZ/6IxVrN651xmw9vtC3pQ7x/RA== - dependencies: - graphql-codegen-core "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - -graphql-codegen-introspection@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-introspection/-/graphql-codegen-introspection-0.17.0.tgz#b87776a9177fc0448bad5bd288c8795af23e3eea" - integrity sha512-UYP7XvGnT6ZMR2bJ9i1QWVPInizGqeS8j9u61BZPYfyMBZz3SA5yJwfZMv+65wRrKEbnXIiuYG1a81cVpjMTcQ== - -graphql-codegen-plugin-helpers@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-plugin-helpers/-/graphql-codegen-plugin-helpers-0.17.0.tgz#f65edde8a0810c457a85171d2e8bd0d29c8c7ac3" - integrity sha512-zcTvtvJqGrGTUjM9qz4vGml967uORX5yeSBc9n4du+Ah+y4TLG0GdjmEqfP7Jokwb8YpCGKivY6hXF8AZ7yPdw== - dependencies: - graphql-codegen-core "0.17.0" - import-from "2.1.0" - -graphql-codegen-schema-ast@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-schema-ast/-/graphql-codegen-schema-ast-0.17.0.tgz#cd26275881cfaaf6777a2a02511206668b2c0868" - integrity sha512-dLaFSpaXMM5UB/Qpig+ME/RKdjlysNdvN4gqj+e3KWEMMd98YQQJY4wAbzZPCwL+8DM8fKvs0Rqkkk6Vga54ng== - -graphql-codegen-time@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-time/-/graphql-codegen-time-0.17.0.tgz#77e1add6981f84c6055c1aeb71b08e05c86f4db0" - integrity sha512-zRqaOFq+BZ8Owa3PCFY3rvwNWNlf1LBmfmqcjYFWWIpueZWh/slSDVlFBhCu2xboRFNEYjMv27SmorRvnarv2A== - dependencies: - moment "2.24.0" - -graphql-codegen-typescript-apollo-angular@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-apollo-angular/-/graphql-codegen-typescript-apollo-angular-0.17.0.tgz#c3a9825b66dba99f8a1259bd986c49d88b5f524f" - integrity sha512-e5zddWaEUxSJGJ0cByhwctLhRJ7N0c6lu/TqhmJeotXsrfNBLPGYuAaPm/K9SfyODCMjAUQSp7IiHra2biZPvw== - dependencies: - dependency-graph "0.8.0" - graphql-codegen-plugin-helpers "0.17.0" - graphql-codegen-typescript-common "0.17.0" - -graphql-codegen-typescript-client@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-client/-/graphql-codegen-typescript-client-0.17.0.tgz#cafb228f6ed7b4f8d202ab58f7a162d73ead236b" - integrity sha512-SHrG1oVMKqIm4xirxZFlHdeQHpDpXJLmkPc6JNS0Mz4g14//muiP3tDlSJRtxSCcC2azRc/k+YkZ4yWFKoLDxQ== - dependencies: - graphql-codegen-core "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - graphql-codegen-typescript-common "0.17.0" - -graphql-codegen-typescript-common@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-common/-/graphql-codegen-typescript-common-0.17.0.tgz#76cfeefa92ee8420f2c9a687576fd5ac3d6e14fb" - integrity sha512-tUaJB4fuHHgZa1JFroe5V4kIn69HKmKwaHEvizXhuAmJUnHGThzjnn71Ot0FMSpF6RLcMf/adDsNts/BQrUEYg== - dependencies: - change-case "3.1.0" - common-tags "1.8.0" - graphql-codegen-core "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - -graphql-codegen-typescript-graphql-files-modules@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-graphql-files-modules/-/graphql-codegen-typescript-graphql-files-modules-0.17.0.tgz#887cf015ca0c13f870cf7cd5511a28240b089f89" - integrity sha512-kxb6qRg6IDW4tvN6cNLuXRCeTmPULYSEozGqURtiTekwsvejDICgtTu/2MVQBoWB9mFwZ3TjI0F2W7jYbbu2kw== - -graphql-codegen-typescript-mongodb@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-mongodb/-/graphql-codegen-typescript-mongodb-0.17.0.tgz#6ee64f9f9014f087fe16e99a8a698b2095740267" - integrity sha512-6I/2uJwVURwAYIToRXaeZwdt9O+FjOffA3Gonw3KfjHCAWddXDUcQeFpBfLpct0kpJuc3CJNFUdoYC+sJOEx4g== - dependencies: - graphql-codegen-core "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - graphql-codegen-typescript-common "0.17.0" - -graphql-codegen-typescript-react-apollo@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-react-apollo/-/graphql-codegen-typescript-react-apollo-0.17.0.tgz#1ea7162afaf7ea2a3cc581cff141837581948c81" - integrity sha512-xG8Rs+pu84ZHlxasjbEhQrcbJv42WXC0hlT5WNPWCgsdF3TpVKHaNepUm12gDPO13RmNuXsmn3VLa/xpn2eNrw== - dependencies: - graphql-codegen-core "0.17.0" - graphql-codegen-plugin-helpers "0.17.0" - graphql-codegen-typescript-common "0.17.0" - -graphql-codegen-typescript-resolvers@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-resolvers/-/graphql-codegen-typescript-resolvers-0.17.0.tgz#b08ad97c36f742fe08acafc28f19192021873049" - integrity sha512-yFYUZ0mXNIhzBKWv1qWnDWPm9SnXR30AfAFsp2DGY6v5834NS48pLHsiHp3z+Fgv+MvANhW+tI1LeViB0Ds5jg== - dependencies: - graphql-codegen-plugin-helpers "0.17.0" - graphql-codegen-typescript-common "0.17.0" - -graphql-codegen-typescript-server@0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-server/-/graphql-codegen-typescript-server-0.17.0.tgz#6c6e70cfe72d73db33662469d83c3a0edcaf3178" - integrity sha512-70EqTJTJ1K8nVvhkpTdzmY4k04/OV1KsGEZeQeH7rPtVxJ2acrxlpFAJIqjQgsCPSnuZJotQfZDNAWmn4bd5nQ== - dependencies: - graphql-codegen-typescript-common "0.17.0" - graphql-config@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-2.0.1.tgz#d34a9bdf1d7360af7b01db9b20260a342ddc7390" @@ -6108,17 +5956,6 @@ graphql-request@^1.5.0: dependencies: cross-fetch "2.2.2" -graphql-tag-pluck@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/graphql-tag-pluck/-/graphql-tag-pluck-0.5.0.tgz#81f5dee3a6ca829f205ab032336be7b107398b2e" - integrity sha512-SlsIpXKbrKIV2+QxYZ7bFPQ0DpIXFd0BEz3U+Krt8tuHYMFtElcctNDppW4EeQTrSX9H5zpStBZyfOYQjQOH1w== - dependencies: - "@babel/parser" "^7.2.0" - "@babel/traverse" "^7.1.6" - "@babel/types" "^7.2.0" - source-map-support "^0.5.9" - typescript "^3.2.2" - graphql-tag-pluck@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/graphql-tag-pluck/-/graphql-tag-pluck-0.7.0.tgz#95481a144d3a6a6923a2851cc3fbe46b39192be3" @@ -6135,21 +5972,6 @@ graphql-tag@2.10.1: resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.1.tgz#10aa41f1cd8fae5373eaf11f1f67260a3cad5e02" integrity sha512-jApXqWBzNXQ8jYa/HLkZJaVw9jgwNqZkywa2zfFn16Iv1Zb7ELNHkJaXHR7Quvd5SIGsy6Ny7SUKATgnu05uEg== -graphql-toolkit@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/graphql-toolkit/-/graphql-toolkit-0.0.5.tgz#9e6ebe3d4b33fc329e5ee3b7775bfe7fba2f48a5" - integrity sha512-655RP1y8cn65mOa9EE/jnttczHE0lFXpOV1zYLTsE1A0b5j8RVuKWllSZBnnL2WHSAPPqLZ1oJEZV2uzSdV9VQ== - dependencies: - deepmerge "3.1.0" - glob "7.1.3" - graphql-import "0.7.1" - graphql-tag-pluck "0.5.0" - is-glob "4.0.0" - is-valid-path "0.1.1" - lodash "4.17.11" - request "2.88.0" - valid-url "1.0.9" - graphql-toolkit@0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/graphql-toolkit/-/graphql-toolkit-0.2.6.tgz#539f82450c85d81ecb81b5c825d0c7271b458ece" @@ -6190,7 +6012,7 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gzip-size@5.0.0: +gzip-size@5.0.0, gzip-size@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== @@ -6198,6 +6020,13 @@ gzip-size@5.0.0: duplexer "^0.1.1" pify "^3.0.0" +gzip-size@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520" + integrity sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA= + dependencies: + duplexer "^0.1.1" + h2x-core@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/h2x-core/-/h2x-core-1.1.1.tgz#7fb31ab28e30ebf11818e3c7d183487ecf489f9f" @@ -6246,7 +6075,7 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== -handlebars@4.1.0, handlebars@^4.0.2, handlebars@^4.0.3, handlebars@^4.1.0: +handlebars@^4.0.2, handlebars@^4.0.3, handlebars@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a" integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w== @@ -6408,13 +6237,6 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - hoopy@^0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" @@ -6588,7 +6410,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, ic dependencies: safer-buffer ">= 2.1.2 < 3" -icss-replace-symbols@^1.1.0: +icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= @@ -6639,12 +6461,23 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +iltorb@^2.0.5: + version "2.4.2" + resolved "https://registry.yarnpkg.com/iltorb/-/iltorb-2.4.2.tgz#51e341045ad5181bf64832a569ec576e7df0faf2" + integrity sha512-RvsVTHt1Pw1/Zcepfd+3jinu38rO8IBFVONcroT9Dwrb5RSNE/CEX7uy1yZKN/kYCQB7FWx/oQgXhN9qAwZY9Q== + dependencies: + detect-libc "^1.0.3" + nan "^2.12.1" + npmlog "^4.1.2" + prebuild-install "^5.2.4" + which-pm-runs "^1.0.0" + immer@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== -import-cwd@^2.0.0: +import-cwd@^2.0.0, import-cwd@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= @@ -6734,7 +6567,7 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= -ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -6805,11 +6638,6 @@ internal-ip@^3.0.1: default-gateway "^2.6.0" ipaddr.js "^1.5.2" -interpret@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== - invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -7064,6 +6892,11 @@ is-lower-case@^1.1.0: dependencies: lower-case "^1.1.0" +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -7183,6 +7016,13 @@ is-subset@^0.1.1: resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= +is-svg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" + integrity sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk= + dependencies: + html-comment-regex "^1.1.0" + is-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" @@ -7228,7 +7068,7 @@ is-valid-path@0.1.1: dependencies: is-invalid-path "^0.1.0" -is-windows@^1.0.1, is-windows@^1.0.2: +is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -7238,11 +7078,6 @@ is-wsl@^1.1.0: resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -7489,7 +7324,7 @@ jest-cli@^23.6.0: which "^1.2.12" yargs "^11.0.0" -jest-cli@^24.5.0: +jest-cli@^24.1.0, jest-cli@^24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.5.0.tgz#598139d3446d1942fb7dc93944b9ba766d756d4b" integrity sha512-P+Jp0SLO4KWN0cGlNtC7JV0dW1eSFR7eRpoOucP2UM0sqlzp/bVHeo71Omonvigrj9AvCKy7NtQANtqJ7FXz8g== @@ -8095,6 +7930,14 @@ jest@23.6.0: import-local "^1.0.0" jest-cli "^23.6.0" +jest@24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2" + integrity sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A== + dependencies: + import-local "^2.0.0" + jest-cli "^24.1.0" + jest@24.5.0: version "24.5.0" resolved "https://registry.yarnpkg.com/jest/-/jest-24.5.0.tgz#38f11ae2c2baa2f86c2bc4d8a91d2b51612cd19a" @@ -8117,6 +7960,11 @@ joi@^11.1.1: isemail "3.x.x" topo "2.x.x" +js-base64@^2.1.9: + version "2.5.1" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" + integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== + js-levenshtein@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -8132,15 +7980,7 @@ js-tokens@^3.0.2: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= -js-yaml@3.12.1, js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" - integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@3.12.2: +js-yaml@3.12.2, js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.0: version "3.12.2" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc" integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q== @@ -8148,15 +7988,23 @@ js-yaml@3.12.2: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + integrity sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A= + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsdom@>=11.0.0: - version "13.2.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-13.2.0.tgz#b1a0dbdadc255435262be8ea3723d2dba0d7eb3a" - integrity sha512-cG1NtMWO9hWpqRNRR3dSvEQa8bFI6iLlqU2x4kwX51FQjp0qus8T9aBaAO6iGp3DeBrhdwuKxckknohkmfvsFw== + version "14.0.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.0.0.tgz#c7f1441ebcc57902d08d5fb2f6ba2baf746da7c6" + integrity sha512-/VkyPmdtbwqpJSkwDx3YyJ3U1oawYNB/h5z8vTUZGAzjtu2OHTeFRfnJqyMHsJ5Cyes23trOmvUpM1GfHH1leA== dependencies: abab "^2.0.0" acorn "^6.0.4" @@ -8284,7 +8132,7 @@ json5@2.x, json5@^2.1.0: dependencies: minimist "^1.2.0" -json5@^0.5.1: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= @@ -8421,13 +8269,6 @@ kleur@^3.0.2: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.2.tgz#83c7ec858a41098b613d5998a7b653962b504f68" integrity sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q== -kuler@1.0.x: - version "1.0.1" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6" - integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ== - dependencies: - colornames "^1.1.1" - last-call-webpack-plugin@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" @@ -8651,6 +8492,16 @@ loader-utils@1.2.3, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1. emojis-list "^2.0.0" json5 "^1.0.1" +loader-utils@^0.2.16: + version "0.2.17" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" + integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= + dependencies: + big.js "^3.1.3" + emojis-list "^2.0.0" + json5 "^0.5.0" + object-assign "^4.0.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -8677,6 +8528,11 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -8692,6 +8548,11 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash.sumby@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.sumby/-/lodash.sumby-4.6.0.tgz#7d87737ddb216da2f7e5e7cd2dd9c403a7887346" + integrity sha1-fYdzfdshbaL35efNLdnEA6eIc0Y= + lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" @@ -8722,7 +8583,7 @@ lodash@4.17.11, "lodash@>=3.5 <5", lodash@^4.17.10, lodash@^4.17.11, lodash@^4.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== -log-symbols@2.2.0, log-symbols@^2.1.0, log-symbols@^2.2.0: +log-symbols@2.2.0, log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== @@ -8736,15 +8597,6 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" -log-update@2.3.0, log-update@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" - integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= - dependencies: - ansi-escapes "^3.0.0" - cli-cursor "^2.0.0" - wrap-ansi "^3.0.1" - log-update@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-3.1.0.tgz#fa22abbbcb30f505906758bbbd0f292b71bc2ad9" @@ -8754,30 +8606,20 @@ log-update@3.1.0: cli-cursor "^2.1.0" wrap-ansi "^5.0.0" -logform@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360" - integrity sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ== +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= dependencies: - colors "^1.2.1" - fast-safe-stringify "^2.0.4" - fecha "^2.3.3" - ms "^2.1.1" - triple-beam "^1.3.0" + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" loglevel@^1.4.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= -loglevelnext@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2" - integrity sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A== - dependencies: - es6-symbol "^3.1.1" - object.assign "^4.1.0" - loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -8825,6 +8667,20 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== + dependencies: + vlq "^0.2.2" + +magic-string@^0.25.1, magic-string@^0.25.2: + version "0.25.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" + integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== + dependencies: + sourcemap-codec "^1.4.4" + make-dir@^1.0.0, make-dir@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -8832,6 +8688,14 @@ make-dir@^1.0.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + make-error@1.x: version "1.3.5" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" @@ -8885,11 +8749,26 @@ matcher@^1.0.0: dependencies: escape-string-regexp "^1.0.4" +math-expression-evaluator@^1.2.14: + version "1.2.17" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" + integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= + math-random@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== +maxmin@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/maxmin/-/maxmin-2.1.0.tgz#4d3b220903d95eee7eb7ac7fa864e72dc09a3166" + integrity sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY= + dependencies: + chalk "^1.0.0" + figures "^1.0.1" + gzip-size "^3.0.0" + pretty-bytes "^3.0.0" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -8917,12 +8796,12 @@ mem@^1.1.0: mimic-fn "^1.0.0" mem@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" - integrity sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.2.0.tgz#5ee057680ed9cb8dad8a78d820f9a8897a102025" + integrity sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA== dependencies: map-age-cleaner "^0.1.1" - mimic-fn "^1.0.0" + mimic-fn "^2.0.0" p-is-promise "^2.0.0" memory-fs@^0.4.0, memory-fs@~0.4.1: @@ -9000,6 +8879,45 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= +microbundle@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/microbundle/-/microbundle-0.11.0.tgz#266bcf4210192698c23fe3bf3581ab81d31a14d0" + integrity sha512-Lt2f8OhC2y2uKyJ5zA8lEEiDsIAbk6yllBuoAWLIdYVIXYqOdN9mO3DI7VW7x/fw87gdnCLIJdVtpP6kaI99LA== + dependencies: + "@babel/core" "^7.2.2" + "@babel/plugin-proposal-class-properties" "7.2.1" + "@babel/plugin-syntax-jsx" "^7.2.0" + "@babel/polyfill" "^7.0.0" + asyncro "^3.0.0" + autoprefixer "^9.0.0" + babel-plugin-transform-async-to-promises "^0.8.3" + brotli-size "^0.0.3" + camelcase "^5.0.0" + chalk "^2.4.0" + cssnano "^4.1.7" + es6-promisify "^6.0.1" + gzip-size "^5.0.0" + pretty-bytes "^5.1.0" + rollup "^0.67.3" + rollup-plugin-alias "^1.5.1" + rollup-plugin-babel "^4.1.0-0" + rollup-plugin-buble "^0.19.4" + rollup-plugin-bundle-size "^1.0.1" + rollup-plugin-commonjs "^9.0.0" + rollup-plugin-es3 "^1.1.0" + rollup-plugin-flow "^1.1.1" + rollup-plugin-json "^3.1.0" + rollup-plugin-node-resolve "^4.0.0" + rollup-plugin-postcss "^1.6.1" + rollup-plugin-preserve-shebang "^0.1.6" + rollup-plugin-sizes "^0.4.2" + rollup-plugin-terser "^3.0.0" + rollup-plugin-typescript2 "^0.19.0" + sade "^1.4.0" + tiny-glob "^0.2.6" + tslib "^1.9.0" + typescript ">=2.8.3" + micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -9019,7 +8937,7 @@ micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9: +micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -9073,6 +8991,16 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.0.0.tgz#0913ff0b121db44ef5848242c38bbb35d44cabde" + integrity sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA== + +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + mini-css-extract-plugin@0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.3.tgz#98d60fcc5d228c3e36a9bd15a1d6816d6580beb8" @@ -9092,7 +9020,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -9197,11 +9125,21 @@ mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0. dependencies: minimist "0.0.8" +mock-stdin@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mock-stdin/-/mock-stdin-0.3.0.tgz#f40d2a513a114e6d547480625b5ef5190744bd4d" + integrity sha1-9A0qUToRTm1UdIBiW171GQdEvU0= + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== +module-details-from-path@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" + integrity sha1-EUyUlnPiqKNenTV4hSeqN7Z52is= + moment@2.24.0, moment@^2.6.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" @@ -9219,6 +9157,11 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mri@^1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" + integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9247,10 +9190,10 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.9.2: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== +nan@^2.12.1, nan@^2.9.2: + version "2.13.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.0.tgz#7bdfc27dd3c060c46e60b62c72b74012d1a4cd68" + integrity sha512-5DDQvN0luhXdut8SCwzm/ZuAX2W+fwhqNzfq7CZ+OJzQ6NwpcqmIGyLD1R8MEt7BeErzcsI0JLr4pND2pNp2Cw== nanomatch@^1.2.9: version "1.2.13" @@ -9269,6 +9212,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +napi-build-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" + integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -9293,11 +9241,6 @@ neo-async@^2.5.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== -next-tick@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -9310,6 +9253,13 @@ no-case@^2.2.0, no-case@^2.3.2: dependencies: lower-case "^1.1.1" +node-abi@^2.7.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.7.1.tgz#a8997ae91176a5fbaa455b194976e32683cda643" + integrity sha512-OV8Bq1OrPh6z+Y4dqwo05HqrRL9YNF7QVMRfq1/pguwKLG+q9UB/Lk0x5qXjO23JjJg+/jqCHSTaG1P3tfKfuw== + dependencies: + semver "^5.4.1" + node-fetch@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -9395,19 +9345,16 @@ node-pre-gyp@^0.10.0: tar "^4" node-releases@^1.1.3, node-releases@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.8.tgz#32a63fff63c5e51b7e0f540ac95947d220fc6862" - integrity sha512-gQm+K9mGCiT/NXHy+V/ZZS1N/LOaGGqRAAJJs3X9Ah1g+CIbRcBgNyoNYQ+SEtcyAtB9KqDruu+fF7nWjsqRaA== + version "1.1.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.10.tgz#5dbeb6bc7f4e9c85b899e2e7adcc0635c9b2adf7" + integrity sha512-KbUPCpfoBvb3oBkej9+nrU0/7xPlVhmhhUJ1PZqwIP5/1dJkRWKWD3OONjo6M2J7tSCBtDCumLwwqeI+DWWaLQ== dependencies: semver "^5.3.0" -noms@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859" - integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk= - dependencies: - inherits "^2.0.1" - readable-stream "~1.0.31" +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= nopt@^4.0.1: version "4.0.1" @@ -9449,6 +9396,16 @@ normalize-scroll-left@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz#6b79691ba79eb5fb107fa5edfbdc06b55caee2aa" integrity sha512-F9YMRls0zCF6BFIE2YnXDRpHPpfd91nOIaNdDgrx5YMoPLo8Wqj+6jNXHQsYBavJeXP4ww8HCt0xQAKc5qk2Fg== +normalize-url@^1.4.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= + dependencies: + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -9490,7 +9447,7 @@ npm-which@^3.0.1: npm-path "^2.0.2" which "^1.2.10" -npmlog@^4.0.2, npmlog@^4.1.2: +npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -9625,11 +9582,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -one-time@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e" - integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4= - onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -9684,7 +9636,7 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= @@ -9750,9 +9702,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" - integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== dependencies: p-try "^2.0.0" @@ -9780,6 +9732,11 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.0.0.tgz#be18c5a5adeb8e156460651421aceca56c213a50" integrity sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w== +p-queue@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-2.4.2.tgz#03609826682b743be9a22dba25051bd46724fc34" + integrity sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng== + p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" @@ -9806,9 +9763,9 @@ package-json@^4.0.1: semver "^5.1.0" pako@~1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.8.tgz#6844890aab9c635af868ad5fecc62e8acbba3ea4" - integrity sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA== + version "1.0.10" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== parallel-transform@^1.1.0: version "1.1.0" @@ -9868,11 +9825,6 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - parse5@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" @@ -10004,6 +9956,11 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -10100,6 +10057,15 @@ postcss-attribute-case-insensitive@^4.0.0: postcss "^7.0.2" postcss-selector-parser "^5.0.0" +postcss-calc@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" + integrity sha1-d7rnypKK2FcW4v2kLyYb98HWW14= + dependencies: + postcss "^5.0.2" + postcss-message-helpers "^2.0.0" + reduce-css-calc "^1.2.6" + postcss-calc@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" @@ -10152,6 +10118,15 @@ postcss-color-rebeccapurple@^4.0.1: postcss "^7.0.2" postcss-values-parser "^2.0.0" +postcss-colormin@^2.1.8: + version "2.2.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" + integrity sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks= + dependencies: + colormin "^1.0.5" + postcss "^5.0.13" + postcss-value-parser "^3.2.3" + postcss-colormin@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" @@ -10163,6 +10138,14 @@ postcss-colormin@^4.0.3: postcss "^7.0.0" postcss-value-parser "^3.0.0" +postcss-convert-values@^2.3.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" + integrity sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0= + dependencies: + postcss "^5.0.11" + postcss-value-parser "^3.1.2" + postcss-convert-values@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" @@ -10202,6 +10185,13 @@ postcss-dir-pseudo-class@^5.0.0: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" +postcss-discard-comments@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" + integrity sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0= + dependencies: + postcss "^5.0.14" + postcss-discard-comments@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" @@ -10209,6 +10199,13 @@ postcss-discard-comments@^4.0.2: dependencies: postcss "^7.0.0" +postcss-discard-duplicates@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" + integrity sha1-uavye4isGIFYpesSq8riAmO5GTI= + dependencies: + postcss "^5.0.4" + postcss-discard-duplicates@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" @@ -10216,6 +10213,13 @@ postcss-discard-duplicates@^4.0.2: dependencies: postcss "^7.0.0" +postcss-discard-empty@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" + integrity sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU= + dependencies: + postcss "^5.0.14" + postcss-discard-empty@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" @@ -10223,6 +10227,13 @@ postcss-discard-empty@^4.0.1: dependencies: postcss "^7.0.0" +postcss-discard-overridden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" + integrity sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg= + dependencies: + postcss "^5.0.16" + postcss-discard-overridden@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" @@ -10230,6 +10241,14 @@ postcss-discard-overridden@^4.0.1: dependencies: postcss "^7.0.0" +postcss-discard-unused@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" + integrity sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM= + dependencies: + postcss "^5.0.14" + uniqs "^2.0.0" + postcss-double-position-gradients@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" @@ -10246,6 +10265,13 @@ postcss-env-function@^2.0.2: postcss "^7.0.2" postcss-values-parser "^2.0.0" +postcss-filter-plugins@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" + integrity sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ== + dependencies: + postcss "^5.0.4" + postcss-flexbugs-fixes@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.1.0.tgz#e094a9df1783e2200b7b19f875dcad3b3aff8b20" @@ -10306,6 +10332,16 @@ postcss-lab-function@^2.0.1: postcss "^7.0.2" postcss-values-parser "^2.0.0" +postcss-load-config@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" + integrity sha1-U56a/J3chiASHr+djDZz4M5Q0oo= + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + postcss-load-options "^1.2.0" + postcss-load-plugins "^2.3.0" + postcss-load-config@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" @@ -10314,6 +10350,22 @@ postcss-load-config@^2.0.0: cosmiconfig "^4.0.0" import-cwd "^2.0.0" +postcss-load-options@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" + integrity sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw= + dependencies: + cosmiconfig "^2.1.0" + object-assign "^4.1.0" + +postcss-load-plugins@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" + integrity sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI= + dependencies: + cosmiconfig "^2.1.1" + object-assign "^4.1.0" + postcss-loader@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" @@ -10338,6 +10390,22 @@ postcss-media-minmax@^4.0.0: dependencies: postcss "^7.0.2" +postcss-merge-idents@^2.1.5: + version "2.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" + integrity sha1-TFUwMTwI4dWzu/PSu8dH4njuonA= + dependencies: + has "^1.0.1" + postcss "^5.0.10" + postcss-value-parser "^3.1.1" + +postcss-merge-longhand@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" + integrity sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg= + dependencies: + postcss "^5.0.4" + postcss-merge-longhand@^4.0.11: version "4.0.11" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" @@ -10348,6 +10416,17 @@ postcss-merge-longhand@^4.0.11: postcss-value-parser "^3.0.0" stylehacks "^4.0.0" +postcss-merge-rules@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" + integrity sha1-0d9d+qexrMO+VT8OnhDofGG19yE= + dependencies: + browserslist "^1.5.2" + caniuse-api "^1.5.2" + postcss "^5.0.4" + postcss-selector-parser "^2.2.2" + vendors "^1.0.0" + postcss-merge-rules@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" @@ -10360,6 +10439,20 @@ postcss-merge-rules@^4.0.3: postcss-selector-parser "^3.0.0" vendors "^1.0.0" +postcss-message-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" + integrity sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4= + +postcss-minify-font-values@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" + integrity sha1-S1jttWZB66fIR0qzUmyv17vey2k= + dependencies: + object-assign "^4.0.1" + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + postcss-minify-font-values@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" @@ -10368,6 +10461,14 @@ postcss-minify-font-values@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" +postcss-minify-gradients@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" + integrity sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE= + dependencies: + postcss "^5.0.12" + postcss-value-parser "^3.3.0" + postcss-minify-gradients@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" @@ -10378,6 +10479,16 @@ postcss-minify-gradients@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" +postcss-minify-params@^1.0.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" + integrity sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM= + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.2" + postcss-value-parser "^3.0.2" + uniqs "^2.0.0" + postcss-minify-params@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" @@ -10390,9 +10501,19 @@ postcss-minify-params@^4.0.2: postcss-value-parser "^3.0.0" uniqs "^2.0.0" -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" +postcss-minify-selectors@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" + integrity sha1-ssapjAByz5G5MtGkllCBFDEXNb8= + dependencies: + alphanum-sort "^1.0.2" + has "^1.0.1" + postcss "^5.0.14" + postcss-selector-parser "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== dependencies: alphanum-sort "^1.0.0" @@ -10400,6 +10521,13 @@ postcss-minify-selectors@^4.0.2: postcss "^7.0.0" postcss-selector-parser "^3.0.0" +postcss-modules-extract-imports@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" + integrity sha1-thTJcgvmgW6u41+zpfqh26agXds= + dependencies: + postcss "^6.0.1" + postcss-modules-extract-imports@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a" @@ -10407,7 +10535,7 @@ postcss-modules-extract-imports@^1.2.0: dependencies: postcss "^6.0.1" -postcss-modules-local-by-default@^1.2.0: +postcss-modules-local-by-default@1.2.0, postcss-modules-local-by-default@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= @@ -10415,7 +10543,7 @@ postcss-modules-local-by-default@^1.2.0: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" -postcss-modules-scope@^1.1.0: +postcss-modules-scope@1.1.0, postcss-modules-scope@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= @@ -10423,7 +10551,7 @@ postcss-modules-scope@^1.1.0: css-selector-tokenizer "^0.7.0" postcss "^6.0.1" -postcss-modules-values@^1.3.0: +postcss-modules-values@1.3.0, postcss-modules-values@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= @@ -10431,6 +10559,17 @@ postcss-modules-values@^1.3.0: icss-replace-symbols "^1.1.0" postcss "^6.0.1" +postcss-modules@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-1.4.1.tgz#8aa35bd3461db67e27377a7ce770d77b654a84ef" + integrity sha512-btTrbK+Xc3NBuYF8TPBjCMRSp5h6NoQ1iVZ6WiDQENIze6KIYCSf0+UFQuV3yJ7gRHA+4AAtF8i2jRvUpbBMMg== + dependencies: + css-modules-loader-core "^1.1.0" + generic-names "^1.0.3" + lodash.camelcase "^4.3.0" + postcss "^7.0.1" + string-hash "^1.1.1" + postcss-nesting@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.0.tgz#6e26a770a0c8fcba33782a6b6f350845e1a448f6" @@ -10438,6 +10577,13 @@ postcss-nesting@^7.0.0: dependencies: postcss "^7.0.2" +postcss-normalize-charset@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" + integrity sha1-757nEhLX/nWceO0WL2HtYrXLk/E= + dependencies: + postcss "^5.0.5" + postcss-normalize-charset@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" @@ -10501,6 +10647,16 @@ postcss-normalize-unicode@^4.0.1: postcss "^7.0.0" postcss-value-parser "^3.0.0" +postcss-normalize-url@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" + integrity sha1-EI90s/L82viRov+j6kWSJ5/HgiI= + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^1.4.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + postcss-normalize-url@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" @@ -10519,6 +10675,14 @@ postcss-normalize-whitespace@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" +postcss-ordered-values@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" + integrity sha1-7sbCpntsQSqNsgQud/6NpD+VwR0= + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.1" + postcss-ordered-values@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" @@ -10598,6 +10762,21 @@ postcss-pseudo-class-any-link@^6.0.0: postcss "^7.0.2" postcss-selector-parser "^5.0.0-rc.3" +postcss-reduce-idents@^2.2.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" + integrity sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM= + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-reduce-initial@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" + integrity sha1-aPgGlfBF0IJjqHmtJA343WT2ROo= + dependencies: + postcss "^5.0.4" + postcss-reduce-initial@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" @@ -10608,6 +10787,15 @@ postcss-reduce-initial@^4.0.3: has "^1.0.0" postcss "^7.0.0" +postcss-reduce-transforms@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" + integrity sha1-/3b02CEkN7McKYpC0uFEQCV3GuE= + dependencies: + has "^1.0.1" + postcss "^5.0.8" + postcss-value-parser "^3.0.1" + postcss-reduce-transforms@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" @@ -10648,6 +10836,15 @@ postcss-selector-not@^4.0.0: balanced-match "^1.0.0" postcss "^7.0.2" +postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + integrity sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A= + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + postcss-selector-parser@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" @@ -10666,6 +10863,16 @@ postcss-selector-parser@^5.0.0, postcss-selector-parser@^5.0.0-rc.3, postcss-sel indexes-of "^1.0.1" uniq "^1.0.1" +postcss-svgo@^2.1.1: + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" + integrity sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0= + dependencies: + is-svg "^2.0.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + svgo "^0.7.0" + postcss-svgo@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" @@ -10676,6 +10883,15 @@ postcss-svgo@^4.0.2: postcss-value-parser "^3.0.0" svgo "^1.0.0" +postcss-unique-selectors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" + integrity sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0= + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + postcss-unique-selectors@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" @@ -10685,7 +10901,7 @@ postcss-unique-selectors@^4.0.1: postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: +postcss-value-parser@^3.0.0, postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== @@ -10699,7 +10915,35 @@ postcss-values-parser@^2.0.0: indexes-of "^1.0.1" uniq "^1.0.1" -postcss@^6.0.1, postcss@^6.0.23: +postcss-zindex@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" + integrity sha1-0hCd3AVbka9n/EyzsCWUZjnSryI= + dependencies: + has "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" + integrity sha1-AA29H47vIXqjaLmiEsX8QLKo8/I= + dependencies: + chalk "^1.1.3" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg== + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.1, postcss@^6.0.21, postcss@^6.0.23: version "6.0.23" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== @@ -10717,12 +10961,34 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.5: source-map "^0.6.1" supports-color "^6.1.0" +prebuild-install@^5.2.4: + version "5.2.5" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.2.5.tgz#c7485911fe98950b7f7cd15bb9daee11b875cc44" + integrity sha512-6uZgMVg7yDfqlP5CPurVhtq3hUKBFNufiar4J5hZrlHTo59DDBEtyxw01xCdFss9j0Zb9+qzFVf/s4niayba3w== + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.0" + mkdirp "^0.5.1" + napi-build-utils "^1.0.1" + node-abi "^2.7.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + os-homedir "^1.0.1" + pump "^2.0.1" + rc "^1.2.7" + simple-get "^2.7.0" + tar-fs "^1.13.0" + tunnel-agent "^0.6.0" + which-pm-runs "^1.0.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= -prepend-http@^1.0.1: +prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= @@ -10737,11 +11003,23 @@ prettier@1.16.4, prettier@^1.14.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717" integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g== +pretty-bytes@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-3.0.1.tgz#27d0008d778063a0b4811bb35c79f1bd5d5fbccf" + integrity sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8= + dependencies: + number-is-nan "^1.0.0" + pretty-bytes@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" integrity sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk= +pretty-bytes@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.1.0.tgz#6237ecfbdc6525beaef4de722cc60a58ae0e6c6d" + integrity sha512-wa5+qGVg9Yt7PB6rYm3kXlKzgzgivYTLRandezh43jjRqgyDyP+9YxfJpJiLs9yKD1WeU8/OvtToWpW7255FtA== + pretty-error@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" @@ -10793,6 +11071,11 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= +promise.series@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/promise.series/-/promise.series-0.2.0.tgz#2cc7ebe959fc3a6619c04ab4dbdc9e452d864bbd" + integrity sha1-LMfr6Vn8OmYZwEq029yeRS2GS70= + promise@8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.2.tgz#9dcd0672192c589477d56891271bdc27547ae9f0" @@ -10872,6 +11155,14 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pump@^2.0.0, pump@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -10922,6 +11213,14 @@ qs@6.5.2, qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -10988,14 +11287,6 @@ raw-body@2.3.3: iconv-lite "0.4.23" unpipe "1.0.0" -raw-loader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-1.0.0.tgz#3f9889e73dadbda9a424bce79809b4133ad46405" - integrity sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA== - dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" - rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -11007,9 +11298,9 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: strip-json-comments "~2.0.1" react-app-polyfill@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-0.2.1.tgz#96c701a40b9671c8547f70bdbb4a47f4d5767790" - integrity sha512-rcpR+WKmLOoYGDAxXaLlxl5Sw6jqbcD1qg2Okn1Ta2RHCxLuQv75B9Em2L2GvuOTx3lAxDpNl/TYGWbKnO/Aag== + version "0.2.2" + resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-0.2.2.tgz#a903b61a8bfd9c5e5f16fc63bebe44d6922a44fb" + integrity sha512-mAYn96B/nB6kWG87Ry70F4D4rsycU43VYTj3ZCbKP+SLJXwC0x6YCbwcICh3uW8/C9s1VgP197yx+w7SCWeDdQ== dependencies: core-js "2.6.4" object-assign "4.1.1" @@ -11018,9 +11309,9 @@ react-app-polyfill@^0.2.0: whatwg-fetch "3.0.0" react-dev-utils@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-7.0.3.tgz#f1316cfffd792fd41b0c28ad5db86c1d74484d6f" - integrity sha512-KEFsH1CewnmddPLXIuU+QWKTH/hpJKZClL2+74XN54NkPnR2KnB5gGmuQ0E7DwcCkUpdMxxqBX+rB7aB5sZS4A== + version "7.0.5" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-7.0.5.tgz#cb95375d01ae71ca27b3c7616006ef7a77d14e8e" + integrity sha512-zJnqqb0x6gd63E3xoz5pXAxBPNaW75Hyz7GgQp0qPhMroBCRQtRvG67AoTZZY1z4yCYVJQZAfQJFdnea0Ujbug== dependencies: "@babel/code-frame" "7.0.0" address "1.0.3" @@ -11040,7 +11331,7 @@ react-dev-utils@^7.0.1: loader-utils "1.2.3" opn "5.4.0" pkg-up "2.0.0" - react-error-overlay "^5.1.3" + react-error-overlay "^5.1.4" recursive-readdir "2.2.2" shell-quote "1.6.1" sockjs-client "1.3.0" @@ -11057,10 +11348,10 @@ react-dom@16.8.4: prop-types "^15.6.2" scheduler "^0.13.4" -react-error-overlay@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.3.tgz#16fcbde75ed4dc6161dc6dc959b48e92c6ffa9ad" - integrity sha512-GoqeM3Xadie7XUApXOjkY3Qhs8RkwB/Za4WMedBGrOKH1eTuKGyoAECff7jiVonJchOx6KZ9i8ILO5XIoHB+Tg== +react-error-overlay@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-5.1.4.tgz#88dfb88857c18ceb3b9f95076f850d7121776991" + integrity sha512-fp+U98OMZcnduQ+NSEiQa4s/XMsbp+5KlydmkbESOw4P69iWZ68ZMFM5a2BuE0FgqPBKApJyRuYHR95jM8lAmg== react-event-listener@^0.6.2: version "0.6.6" @@ -11071,12 +11362,7 @@ react-event-listener@^0.6.2: prop-types "^15.6.0" warning "^4.0.1" -react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1: - version "16.8.3" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d" - integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA== - -react-is@^16.8.4: +react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4: version "16.8.4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== @@ -11142,9 +11428,9 @@ react-scripts-rewired@2.1.3: fsevents "1.2.4" react-transition-group@^2.2.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.6.0.tgz#3c41cbdd9c044c5f8604d4e8d319e860919c9fae" - integrity sha512-VzZ+6k/adL3pJHo4PU/MHEPjW59/TGQtRsXC+wnxsx2mxjQKNHnDdJL/GpYuPJIsyHGjYbBQfIJ2JNOAdPc8GQ== + version "2.6.1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.6.1.tgz#abf4a95e2f13fb9ba83a970a896fedbc5c4856a2" + integrity sha512-9DHwCy0aOYEe35frlEN68N9ut/THDQBLnVoQuKTvzF4/s3tk7lqkefCqxK2Nv96fOh6JXk6tQtliygk6tl3bQA== dependencies: dom-helpers "^3.3.1" loose-envify "^1.4.0" @@ -11236,7 +11522,7 @@ read-pkg@^4.0.1: parse-json "^4.0.0" pify "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -11250,24 +11536,14 @@ read-pkg@^4.0.1: util-deprecate "~1.0.1" readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" - integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== + version "3.2.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.2.0.tgz#de17f229864c120a9f56945756e4f32c4045245d" + integrity sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@~1.0.31: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -11319,10 +11595,26 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" -regenerate-unicode-properties@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" - integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== +reduce-css-calc@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" + integrity sha1-dHyRTgSWFKTJz7umKYca0dKSdxY= + dependencies: + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-function-call@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" + integrity sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk= + dependencies: + balanced-match "^0.4.2" + +regenerate-unicode-properties@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz#7b38faa296252376d363558cfbda90c9ce709662" + integrity sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ== dependencies: regenerate "^1.4.0" @@ -11382,17 +11674,17 @@ regexpu-core@^1.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.4.0.tgz#8d43e0d1266883969720345e70c275ee0aec0d32" - integrity sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA== +regexpu-core@^4.1.3, regexpu-core@^4.2.0, regexpu-core@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" + integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^7.0.0" + regenerate-unicode-properties "^8.0.2" regjsgen "^0.5.0" regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.0.2" + unicode-match-property-value-ecmascript "^1.1.0" registry-auth-token@^3.0.1: version "3.3.2" @@ -11528,6 +11820,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= + require-from-string@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" @@ -11551,6 +11848,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +reserved-words@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/reserved-words/-/reserved-words-0.1.2.tgz#00a0940f98cd501aeaaac316411d9adc52b31ab1" + integrity sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE= + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -11558,14 +11860,6 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" @@ -11643,6 +11937,168 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rollup-plugin-alias@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-alias/-/rollup-plugin-alias-1.5.1.tgz#80cce3a967befda5b09c86abc14a043a78035b46" + integrity sha512-pQTYBRNfLedoVOO7AYHNegIavEIp4jKTga5jUi1r//KYgHKGWgG4qJXYhbcWKt2k1FwGlR5wCYoY+IFkme0t4A== + dependencies: + slash "^2.0.0" + +rollup-plugin-babel@^4.1.0-0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.3.2.tgz#8c0e1bd7aa9826e90769cf76895007098ffd1413" + integrity sha512-KfnizE258L/4enADKX61ozfwGHoqYauvoofghFJBhFnpH9Sb9dNPpWg8QHOaAfVASUYV8w0mCx430i9z0LJoJg== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + rollup-pluginutils "^2.3.0" + +rollup-plugin-buble@^0.19.4: + version "0.19.6" + resolved "https://registry.yarnpkg.com/rollup-plugin-buble/-/rollup-plugin-buble-0.19.6.tgz#55ee0995d8870d536f01f4277c3eef4276e8747e" + integrity sha512-El5Fut4/wEO17ZN/n9BZvqd7DXXB2WbJr/DKvr89LXChC/cHllE0XwiUDeAalrTkgr0WrnyLDTCQvEv+cGywWQ== + dependencies: + buble "^0.19.6" + rollup-pluginutils "^2.3.3" + +rollup-plugin-bundle-size@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/rollup-plugin-bundle-size/-/rollup-plugin-bundle-size-1.0.3.tgz#d245cd988486b4040279f9fd33f357f61673e90f" + integrity sha512-aWj0Pvzq90fqbI5vN1IvUrlf4utOqy+AERYxwWjegH1G8PzheMnrRIgQ5tkwKVtQMDP0bHZEACW/zLDF+XgfXQ== + dependencies: + chalk "^1.1.3" + maxmin "^2.1.0" + +rollup-plugin-commonjs@^9.0.0: + version "9.2.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.1.tgz#bb151ca8fa23600c7a03e25f9f0a45b1ee922dac" + integrity sha512-X0A/Cp/t+zbONFinBhiTZrfuUaVwRIp4xsbKq/2ohA2CDULa/7ONSJTelqxon+Vds2R2t2qJTqJQucKUC8GKkw== + dependencies: + estree-walker "^0.5.2" + magic-string "^0.25.1" + resolve "^1.10.0" + rollup-pluginutils "^2.3.3" + +rollup-plugin-es3@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-es3/-/rollup-plugin-es3-1.1.0.tgz#f866f91b4db839e5b475d8e4a7b9d4c77ecade14" + integrity sha512-jTMqQgMZ/tkjRW4scf4ln5c0OiTSi+Lx/IEyFd41ldgGoLvvg9AQxmVOl93+KaoyB7XRYToYjiHDvO40NPF/fA== + dependencies: + magic-string "^0.22.4" + +rollup-plugin-flow@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-flow/-/rollup-plugin-flow-1.1.1.tgz#6ce568f1dd559666b77ab76b4bae251407528db6" + integrity sha1-bOVo8d1Vlma3erdrS64lFAdSjbY= + dependencies: + flow-remove-types "^1.1.0" + rollup-pluginutils "^1.5.1" + +rollup-plugin-json@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-3.1.0.tgz#7c1daf60c46bc21021ea016bd00863561a03321b" + integrity sha512-BlYk5VspvGpjz7lAwArVzBXR60JK+4EKtPkCHouAWg39obk9S61hZYJDBfMK+oitPdoe11i69TlxKlMQNFC/Uw== + dependencies: + rollup-pluginutils "^2.3.1" + +rollup-plugin-node-resolve@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.1.tgz#f95765d174e5daeef9ea6268566141f53aa9d422" + integrity sha512-fSS7YDuCe0gYqKsr5OvxMloeZYUSgN43Ypi1WeRZzQcWtHgFayV5tUSPYpxuaioIIWaBXl6NrVk0T2/sKwueLg== + dependencies: + builtin-modules "^3.0.0" + is-module "^1.0.0" + resolve "^1.10.0" + +rollup-plugin-postcss@^1.6.1: + version "1.6.3" + resolved "https://registry.yarnpkg.com/rollup-plugin-postcss/-/rollup-plugin-postcss-1.6.3.tgz#18256ba66f29ecd9d42a68f4ef136b92b939ddb8" + integrity sha512-se1qftVETua9ZGViud4A4gbgEQenjYnLPvjh3kTqbBZU+f0mQ9YvJptIuzPhEk5kZAHZhkwIkk2jk+byrn1XPA== + dependencies: + chalk "^2.0.0" + concat-with-sourcemaps "^1.0.5" + cssnano "^3.10.0" + fs-extra "^5.0.0" + import-cwd "^2.1.0" + p-queue "^2.4.2" + pify "^3.0.0" + postcss "^6.0.21" + postcss-load-config "^1.2.0" + postcss-modules "^1.1.0" + promise.series "^0.2.0" + reserved-words "^0.1.2" + resolve "^1.5.0" + rollup-pluginutils "^2.0.1" + style-inject "^0.3.0" + +rollup-plugin-preserve-shebang@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/rollup-plugin-preserve-shebang/-/rollup-plugin-preserve-shebang-0.1.6.tgz#8cfc4c555d4ca87b9fbb7712869158db0e080d4a" + integrity sha512-b+psdlXZOjmlnKmL6/YAkR8PR15VPcUNXdT35urBRJ8jE6UxHyb4HXeeN3qRZJbMJJaX1eRP72XwH6IvGFh5Jw== + dependencies: + magic-string "^0.22.4" + +rollup-plugin-sizes@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-sizes/-/rollup-plugin-sizes-0.4.2.tgz#1d97ecda2667a43afbb19d801e2476f80f67d12f" + integrity sha512-6VsnWb4aBPcW++3IBMNPo4NLSheoaXh+itXk1OcaolLhYemoQFb7A9hVNocwa0j2BctdmPNFcP7UJ3g///VVaA== + dependencies: + filesize "^3.5.11" + lodash.foreach "^4.5.0" + lodash.sumby "^4.6.0" + module-details-from-path "^1.0.3" + +rollup-plugin-terser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-3.0.0.tgz#045bd7cf625ee1affcfe6971dab6fffe6fb48c65" + integrity sha512-Ed9zRD7OoCBnh0XGlEAJle5TCUsFXMLClwKzZWnS1zbNO4MelHjfCSdFZxCAdH70M40nhZ1nRrY2GZQJhSMcjA== + dependencies: + "@babel/code-frame" "^7.0.0" + jest-worker "^23.2.0" + serialize-javascript "^1.5.0" + terser "^3.8.2" + +rollup-plugin-typescript2@^0.19.0: + version "0.19.3" + resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.19.3.tgz#713063233461765f030a2baa2640905c2656164f" + integrity sha512-lsRqfBCZhMl/tq9AT5YnQvzQWzXtnx3EQYFcHD72gul7nyyoOrzx5yCEH20smpw58v6UkHHZz03FbdLEPoHWjA== + dependencies: + fs-extra "7.0.1" + resolve "1.8.1" + rollup-pluginutils "2.3.3" + tslib "1.9.3" + +rollup-pluginutils@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz#3aad9b1eb3e7fe8262820818840bf091e5ae6794" + integrity sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA== + dependencies: + estree-walker "^0.5.2" + micromatch "^2.3.11" + +rollup-pluginutils@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + integrity sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg= + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + +rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.3.0, rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.3.3: + version "2.4.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.4.1.tgz#de43ab54965bbf47843599a7f3adceb723de38db" + integrity sha512-wesMQ9/172IJDIW/lYWm0vW0LiKe5Ekjws481R7z9WTRtmO59cqyM/2uUlxvf6yzm/fElFmHUobeQOYz46dZJw== + dependencies: + estree-walker "^0.6.0" + micromatch "^3.1.10" + +rollup@^0.67.3: + version "0.67.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.67.4.tgz#8ed6b0993337f84ec8a0387f824fa6c197e833ec" + integrity sha512-AVuP73mkb4BBMUmksQ3Jw0jTrBTU1i7rLiUYjFxLZGb3xiFmtVEg40oByphkZAsiL0bJC3hRAJUQos/e5EBd+w== + dependencies: + "@types/estree" "0.0.39" + "@types/node" "*" + rsvp@^3.3.3: version "3.6.2" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" @@ -11686,6 +12142,13 @@ rxjs@^6.1.0, rxjs@^6.3.3, rxjs@^6.4.0: dependencies: tslib "^1.9.0" +sade@^1.4.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.4.2.tgz#b1946ef9ec62450b74e17d9fec30156c94f193a6" + integrity sha512-MTrQm+Nhl4m1mbssYDgAculC/HbShjj08QtHnA2GTpzivfU5aUp8EoHlECmrIHEaa8hZRZSp2Gygv8VMlpXEBw== + dependencies: + mri "^1.1.0" + safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -11751,7 +12214,7 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= -sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -11837,7 +12300,7 @@ sentence-case@^2.1.0: no-case "^2.2.0" upper-case-first "^1.1.2" -serialize-javascript@^1.4.0: +serialize-javascript@^1.4.0, serialize-javascript@^1.5.0: version "1.6.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== @@ -11959,6 +12422,20 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= + +simple-get@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + simple-git@^1.85.0: version "1.107.0" resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.107.0.tgz#12cffaf261c14d6f450f7fdb86c21ccee968b383" @@ -12062,6 +12539,13 @@ sockjs@0.3.19: faye-websocket "^0.10.0" uuid "^3.0.1" +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= + dependencies: + is-plain-obj "^1.0.0" + sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" @@ -12106,10 +12590,10 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.3, source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.9: - version "0.5.10" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" - integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== +source-map-support@^0.5.6, source-map-support@^0.5.9, source-map-support@~0.5.10: + version "0.5.11" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" + integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -12129,6 +12613,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sourcemap-codec@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" + integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -12238,11 +12727,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= - stack-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" @@ -12308,11 +12792,21 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + string-argv@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" integrity sha1-2sMECGkMIfPDYwo/86BYd73L1zY= +string-hash@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= + string-length@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" @@ -12339,13 +12833,13 @@ string-width@^1.0.1: strip-ansi "^4.0.0" string-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" - integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.0.0" + strip-ansi "^5.1.0" string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.2.0" @@ -12354,11 +12848,6 @@ string_decoder@^1.0.0, string_decoder@^1.1.1: dependencies: safe-buffer "~5.1.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -12375,7 +12864,7 @@ stringify-object@^3.2.2: is-obj "^1.0.1" is-regexp "^1.0.0" -strip-ansi@5.0.0, strip-ansi@^5.0.0: +strip-ansi@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== @@ -12396,6 +12885,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0, strip-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.1.0.tgz#55aaa54e33b4c0649a7338a43437b1887d153ec4" + integrity sha512-TjxrkPONqO2Z8QDCpeE2j6n0M6EwxzyDgzEeGp+FbdvaJAt//ClYi6W5my+3ROlC/hZX2KACUwDfK49Ka5eDvg== + dependencies: + ansi-regex "^4.1.0" + strip-bom@3.0.0, strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -12449,6 +12945,11 @@ strong-log-transformer@^1.0.6: moment "^2.6.0" through "^2.3.4" +style-inject@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-inject/-/style-inject-0.3.0.tgz#d21c477affec91811cc82355832a700d22bf8dd3" + integrity sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw== + style-loader@0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.0.tgz#8377fefab68416a2e05f1cabd8c3a3acfcce74f1" @@ -12471,14 +12972,14 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^3.1.2: +supports-color@^3.1.2, supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= dependencies: has-flag "^1.0.0" -supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: +supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -12492,6 +12993,19 @@ supports-color@^6.0.0, supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + integrity sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U= + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + svgo@^1.0.0, svgo@^1.0.5: version "1.2.0" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.0.tgz#305a8fc0f4f9710828c65039bb93d5793225ffc3" @@ -12552,6 +13066,29 @@ tapable@^1.0.0, tapable@^1.1.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA== +tar-fs@^1.13.0: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" @@ -12611,28 +13148,14 @@ terser-webpack-plugin@1.1.0: webpack-sources "^1.1.0" worker-farm "^1.5.2" -terser-webpack-plugin@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz#3f98bc902fac3e5d0de730869f50668561262ec8" - integrity sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA== +terser@^3.8.1, terser@^3.8.2: + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== dependencies: - cacache "^11.0.2" - find-cache-dir "^2.0.0" - schema-utils "^1.0.0" - serialize-javascript "^1.4.0" - source-map "^0.6.1" - terser "^3.16.1" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" - -terser@^3.16.1, terser@^3.8.1: - version "3.16.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.16.1.tgz#5b0dd4fa1ffd0b0b43c2493b2c364fd179160493" - integrity sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow== - dependencies: - commander "~2.17.1" + commander "^2.19.0" source-map "~0.6.1" - source-map-support "~0.5.9" + source-map-support "~0.5.10" test-exclude@^4.2.1: version "4.2.3" @@ -12660,11 +13183,6 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - text-table@0.2.0, text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -12675,7 +13193,7 @@ throat@^4.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -through2@^2.0.0, through2@^2.0.1, through2@^2.0.2: +through2@^2.0.0, through2@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -12710,6 +13228,14 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= +tiny-glob@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.6.tgz#9e056e169d9788fe8a734dfa1ff02e9b92ed7eda" + integrity sha512-A7ewMqPu1B5PWwC3m7KVgAu96Ch5LA0w4SnEN/LbDREj/gAD0nPWboRbn8YoP9ISZXqeNAlMvKSKoEuhcfK3Pw== + dependencies: + globalyzer "^0.1.0" + globrex "^0.1.1" + title-case@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" @@ -12735,6 +13261,11 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -12825,11 +13356,6 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= -triple-beam@^1.2.0, triple-beam@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" - integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== - tryer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -12869,7 +13395,7 @@ ts-log@2.1.4: resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.1.4.tgz#063c5ad1cbab5d49d258d18015963489fb6fb59a" integrity sha512-P1EJSoyV+N3bR/IWFeAqXzKPZwHpnLY6j7j58mAvewHRipo+BQM2Y1f9Y9BjEQznKwgqqZm7H8iuixmssU7tYQ== -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@1.9.3, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== @@ -12937,7 +13463,7 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.3.3333, typescript@^3.2.2: +typescript@3.3.3333, typescript@>=2.8.3, typescript@^3.2.2: version "3.3.3333" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6" integrity sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw== @@ -12990,15 +13516,15 @@ unicode-match-property-ecmascript@^1.0.4: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" -unicode-match-property-value-ecmascript@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" - integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" - integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== union-value@^1.0.0: version "1.0.0" @@ -13183,11 +13709,6 @@ uuid@^2.0.1: resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" integrity sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho= -v8-compile-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" - integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== - valid-url@1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" @@ -13220,6 +13741,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vlq@^0.2.1, vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== + vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -13300,23 +13826,6 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-cli@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.3.tgz#13653549adfd8ccd920ad7be1ef868bacc22e346" - integrity sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q== - dependencies: - chalk "^2.4.1" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.0" - findup-sync "^2.0.0" - global-modules "^1.0.0" - import-local "^2.0.0" - interpret "^1.1.0" - loader-utils "^1.1.0" - supports-color "^5.5.0" - v8-compile-cache "^2.0.2" - yargs "^12.0.4" - webpack-dev-middleware@3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890" @@ -13363,16 +13872,6 @@ webpack-dev-server@3.1.14: webpack-log "^2.0.0" yargs "12.0.2" -webpack-log@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d" - integrity sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA== - dependencies: - chalk "^2.1.0" - log-symbols "^2.1.0" - loglevelnext "^1.0.1" - uuid "^3.1.0" - webpack-log@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" @@ -13390,12 +13889,7 @@ webpack-manifest-plugin@2.0.4: lodash ">=3.5 <5" tapable "^1.0.0" -webpack-node-externals@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" - integrity sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg== - -webpack-sources@^1.1.0, webpack-sources@^1.2.0, webpack-sources@^1.3.0: +webpack-sources@^1.1.0, webpack-sources@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== @@ -13433,36 +13927,6 @@ webpack@4.19.1: watchpack "^1.5.0" webpack-sources "^1.2.0" -webpack@4.29.6: - version "4.29.6" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.6.tgz#66bf0ec8beee4d469f8b598d3988ff9d8d90e955" - integrity sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" - enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" - json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" - schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" - websocket-driver@>=0.5.1: version "0.7.0" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" @@ -13516,12 +13980,22 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + integrity sha1-+HfVv2SMl+WqVC+twW1qJZucEaE= + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: +which-pm-runs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" + integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= + +which@^1.2.10, which@^1.2.12, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -13535,29 +14009,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" -winston-transport@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.3.0.tgz#df68c0c202482c448d9b47313c07304c2d7c2c66" - integrity sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A== - dependencies: - readable-stream "^2.3.6" - triple-beam "^1.2.0" - -winston@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.2.1.tgz#63061377976c73584028be2490a1846055f77f07" - integrity sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw== - dependencies: - async "^2.6.1" - diagnostics "^1.1.1" - is-stream "^1.1.0" - logform "^2.1.1" - one-time "0.0.4" - readable-stream "^3.1.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.3.0" - wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" @@ -13785,9 +14236,9 @@ ws@^5.2.0: async-limiter "~1.0.0" ws@^6.1.2: - version "6.1.4" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" - integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== + version "6.2.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526" + integrity sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w== dependencies: async-limiter "~1.0.0" @@ -13909,7 +14360,7 @@ yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@^12.0.2, yargs@^12.0.4: +yargs@^12.0.2: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== @@ -13958,13 +14409,6 @@ yup@^0.26.10: synchronous-promise "^2.0.5" toposort "^2.0.2" -zen-observable-ts@^0.8.15: - version "0.8.15" - resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.15.tgz#6cf7df6aa619076e4af2f707ccf8a6290d26699b" - integrity sha512-sXKPWiw6JszNEkRv5dQ+lQCttyjHM2Iks74QU5NP8mMPS/NrzTlHDr780gf/wOBqmHkPO6NCLMlsa+fAQ8VE8w== - dependencies: - zen-observable "^0.8.0" - zen-observable-ts@^0.8.18: version "0.8.18" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.18.tgz#ade44b1060cc4a800627856ec10b9c67f5f639c8"