From 1587ef757b7a35ef78bd86b813edd0553a44b340 Mon Sep 17 00:00:00 2001 From: dotansimha Date: Thu, 29 Dec 2016 08:07:56 +0200 Subject: [PATCH] feat(core): add support for loading GraphQL schema from js export file --- README.md | 23 ++++++++++++----------- dev-test/githunt/schema-export.js | 15 +++++++++++++++ package.json | 2 +- src/cli.ts | 16 ++++++++++++---- src/introspection-from-export.ts | 27 +++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 dev-test/githunt/schema-export.js create mode 100644 src/introspection-from-export.ts diff --git a/README.md b/README.md index 0d8ccfa8b0b..b8b86879a0a 100644 --- a/README.md +++ b/README.md @@ -69,17 +69,18 @@ CLI usage is as follow: Allowed flags: -| Flag Name | Type | Description | -|-----------------|----------|----------------------------------------------------------------------------------------| -| -f,--file | String | Introspection JSON file, must provide file or URL flag | -| -u,--url | String | GraphQL server endpoint to fetch the introspection from, must provide URL or file flag | -| -h,--header | String | Header to add to the introspection HTTP request when using --url | -| -t,--template | String | Template name, for example: "typescript" | -| -o,--out | String | Path for output file/directory. When using single-file generator specify filename, and when using multiple-files generator specify a directory | -| -nm,--no-model | void | If specified, server side schema won't be generated through the template (enums won't omit) | -| -nd,--no-documents | void | If specified, client side documents won't be generated through the template | -| -d,--dev | void | Turns ON development mode - prints output to console instead of files | -| documents... | [String] | Space separated paths of `.graphql` files or code files (glob path is supported) that contains GraphQL documents inside strings, or with `gql` tag (JavaScript), this field is optional - if no documents specified, only server side schema types will be generated | +| Flag Name | Type | Description | +|--------------------|----------|----------------------------------------------------------------------------------------| +| -f,--file | String | Introspection JSON file, must provide file or URL flag | +| -u,--url | String | GraphQL server endpoint to fetch the introspection from, must provide URL or file flag | +| -e,--export | String | Path to a JavaScript (es5/6) file that exports (as default export) your `GraphQLSchema` object | +| -h,--header | String | Header to add to the introspection HTTP request when using --url | +| -t,--template | String | Template name, for example: "typescript" | +| -o,--out | String | Path for output file/directory. When using single-file generator specify filename, and when using multiple-files generator specify a directory | +| -m,--no-schema | void | If specified, server side schema won't be generated through the template (enums won't omit) | +| -c,--no-documents | void | If specified, client side documents won't be generated through the template | +| -d,--dev | void | Turns ON development mode - prints output to console instead of files | +| documents... | [String] | Space separated paths of `.graphql` files or code files (glob path is supported) that contains GraphQL documents inside strings, or with `gql` tag (JavaScript), this field is optional - if no documents specified, only server side schema types will be generated | **Usage examples:*** diff --git a/dev-test/githunt/schema-export.js b/dev-test/githunt/schema-export.js new file mode 100644 index 00000000000..2ed22ae8c00 --- /dev/null +++ b/dev-test/githunt/schema-export.js @@ -0,0 +1,15 @@ +const GraphQL = require('graphql'); + +module.exports = new GraphQL.GraphQLSchema({ + query: new GraphQL.GraphQLObjectType({ + name: 'RootQueryType', + fields: { + hello: { + type: GraphQL.GraphQLString, + resolve() { + return 'world'; + } + } + } + }) +}); diff --git a/package.json b/package.json index 64f036ed70b..ce4e4bd9ed7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "debug": "cd dist && node --inspect --debug-brk gql-gen.js", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", "create-git-tag": "git tag $(cat package.json | $(npm bin)/json version)", - "dev": "cd dist && nodemon --ext ts,js,d.ts,template,graphql,json,handlebars gql-gen.js --dev --file ../dev-test/githunt/schema.json --template ts --out ../dev-test/githunt/typings.d.ts", + "dev": "cd dist && nodemon --ext ts,js,d.ts,template,graphql,json,handlebars gql-gen.js --dev --export ../dev-test/githunt/schema-export.js --template ts --out ../dev-test/githunt/typings.d.ts", "prepare": "npm run build && npm run test && npm run create-git-tag && git push && git push --tags", "test": "jest" }, diff --git a/src/cli.ts b/src/cli.ts index b604c889d24..c8ce68f0c58 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -4,6 +4,7 @@ import {introspectionFromUrl} from './introspection-from-url'; import {introspectionFromFile} from './introspection-from-file'; import {documentsFromGlobs} from './documents-glob'; import {getTemplateGenerator} from './template-loader'; +import {introspectionFromExport} from './introspection-from-export'; function collect(val, memo) { memo.push(val); @@ -17,10 +18,11 @@ export const initCLI = (args): commander.IExportedCommand => { .option('-d, --dev', 'Turn on development mode - prints results to console') .option('-f, --file ', 'Parse local GraphQL introspection JSON file') .option('-u, --url ', 'Parse remote GraphQL endpoint as introspection file') + .option('-u, --export ', 'Path to a JavaScript (es5/6) file that exports (as default export) your `GraphQLSchema` object') .option('-h, --header [header]', 'Header to add to the introspection HTTP request when using --url', collect, []) .option('-t, --template ', 'Language/platform name templates') - .option('-nm, --no-schema', 'Generates only client side documents, without server side schema types') - .option('-nd, --no-documents', 'Generates only server side schema types, without client side documents') + .option('-m, --no-schema', 'Generates only client side documents, without server side schema types') + .option('-c, --no-documents', 'Generates only server side schema types, without client side documents') .option('-o, --out ', 'Output file(s) path', String, './') .arguments(' [documents...]') .parse(args); @@ -42,11 +44,12 @@ export const cliError = (err: string) => { export const validateCliOptions = (options) => { const file = options['file']; const url = options['url']; + const fsExport = options['export']; const template = options['template']; const out = options['out']; - if (!file && !url) { - cliError('Please specify one of --file or --url flags!'); + if (!file && !url && !fsExport) { + cliError('Please specify one of --file, --url or --export flags!'); } if (!template) { @@ -57,6 +60,7 @@ export const validateCliOptions = (options) => { export const transformOptions = (options): Promise => { const file: string = options['file']; const url: string = options['url']; + const fsExport: string = options['export']; const documents: string[] = options['args'] || []; const template: string = options['template']; const out: string = options['out']; @@ -77,6 +81,10 @@ export const transformOptions = (options): Promise => { else if (url) { introspectionPromise = introspectionFromUrl(url, headers); } + else if (fsExport) { + introspectionPromise = introspectionFromExport(fsExport); + } + const documentsPromise = documentsFromGlobs(documents); const generatorTemplatePromise = getTemplateGenerator(template); diff --git a/src/introspection-from-export.ts b/src/introspection-from-export.ts new file mode 100644 index 00000000000..0deacaf5d30 --- /dev/null +++ b/src/introspection-from-export.ts @@ -0,0 +1,27 @@ +import * as fs from 'fs'; +import {IntrospectionQuery} from 'graphql/utilities/introspectionQuery'; +import {GraphQLSchema} from 'graphql/type/schema'; +import { graphql, introspectionQuery } from 'graphql'; + +export const introspectionFromExport = (file: string) => { + return new Promise((resolve, reject) => { + if (fs.existsSync(file)) { + try { + const schema = require(file); + + if (schema && schema instanceof GraphQLSchema) { + resolve(graphql(schema, introspectionQuery).then(res => res.data)); + } + else { + reject(new Error(`Invalid export from export file ${file}, make sure to default export your GraphQLSchema object!`)); + } + } + catch (e) { + reject(e); + } + } + else { + reject(`Unable to locate introspection export file: ${file}`); + } + }); +};