forked from prisma-labs/get-graphql-schema
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
circle, renovate, prettier, semantic-release, tests
- Loading branch information
Showing
12 changed files
with
12,643 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
version: 2 | ||
jobs: | ||
build: | ||
docker: | ||
- image: 'circleci/node:latest' | ||
steps: | ||
- checkout | ||
- run: | ||
name: install | ||
command: yarn install | ||
- run: | ||
name: test | ||
command: yarn test | ||
- run: | ||
name: coverage | ||
command: yarn coverage | ||
- run: | ||
name: release | ||
command: yarn release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
node_modules | ||
dist | ||
coverage | ||
|
||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module.exports = { | ||
roots: ['<rootDir>/src'], | ||
testEnvironment: 'node', | ||
transform: { | ||
'^.+\\.tsx?$': 'ts-jest', | ||
}, | ||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$', | ||
testPathIgnorePatterns: ['/node_modules/', '/__fixtures__/'], | ||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], | ||
collectCoverage: true, | ||
collectCoverageFrom: [ | ||
'**/*.{ts,tsx}', | ||
'!**/node_modules/**', | ||
'!**/vendor/**', | ||
'!**/generated/**', | ||
], | ||
verbose: true, | ||
coverageDirectory: './coverage', | ||
coverageReporters: ['json', 'lcov', 'text', 'clover', 'html'], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,51 @@ | ||
{ | ||
"name": "get-graphql-schema", | ||
"bin": "dist/index.js", | ||
"files": [ | ||
"README.md", | ||
"dist/" | ||
], | ||
"version": "2.1.2", | ||
"version": "0.0.0-semantic-release", | ||
"description": "Downloads the GraphQL Schema of an GraphQL endpoint URL", | ||
"scripts": { | ||
"build": "tsc", | ||
"prepublish": "npm run build && chmod +x dist/index.js", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"author": "Johannes Schickling <johannes@graph.cool>", | ||
"bin": { | ||
"get-schema": "dist/index.js" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/graphcool/get-graphql-schema.git" | ||
}, | ||
"author": "Johannes Schickling <johannes@graph.cool>", | ||
"license": "MIT", | ||
"scripts": { | ||
"build": "tsc -d", | ||
"prepublish": "npm run build", | ||
"test": "NODE_ENV=test jest", | ||
"release": "semantic-release" | ||
}, | ||
"dependencies": { | ||
"chalk": "^2.4.1", | ||
"graphql": "^14.0.2", | ||
"meow": "^5.0.0", | ||
"minimist": "^1.2.0", | ||
"mkdirp": "^0.5.1", | ||
"node-fetch": "^2.2.0" | ||
}, | ||
"devDependencies": { | ||
"@types/chalk": "^2.2.0", | ||
"@types/graphql": "^14.0.3", | ||
"@types/jest": "^23.3.10", | ||
"@types/meow": "^5.0.0", | ||
"@types/minimist": "^1.2.0", | ||
"@types/mkdirp": "^0.5.2", | ||
"@types/node": "^10.12.0", | ||
"@types/node-fetch": "^2.1.2", | ||
"jest": "^23.6.0", | ||
"jest-fetch-mock": "^2.0.1", | ||
"prettier": "^1.15.3", | ||
"semantic-release": "^15.12.4", | ||
"ts-jest": "^23.10.5", | ||
"ts-node": "^7.0.1", | ||
"typescript": "^3.1.3" | ||
} | ||
}, | ||
"release": { | ||
"branch": "master" | ||
}, | ||
"license": "MIT" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
semi: false, | ||
trailingComma: 'all', | ||
singleQuote: true, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"extends": ["config:base", "docker:disable"], | ||
"automerge": true, | ||
"major": { | ||
"automerge": false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#!/usr/bin/env node | ||
|
||
import meow = require('meow') | ||
import { getHeadersFromInput, getRemoteSchema, printToFile } from '.' | ||
|
||
const cli = meow( | ||
` | ||
Usage: | ||
$ get-graphql-schema ENDPOINT_URL > schema.graphql | ||
Fetch and print the GraphQL schema from a GraphQL HTTP endpoint (Outputs schema in IDL syntax by default). | ||
Options: | ||
--header, -h Add a custom header (ex. 'X-API-KEY=ABC123'), can be used multiple times | ||
--json, -j Output in JSON format (based on introspection query) | ||
--method Use method (GET,POST, PUT, DELETE) | ||
--output Save schema to file. | ||
`, | ||
{ | ||
flags: { | ||
header: { | ||
type: 'string', | ||
alias: 'h', | ||
}, | ||
json: { | ||
type: 'boolean', | ||
alias: 'j', | ||
default: false, | ||
}, | ||
method: { | ||
type: 'string', | ||
default: 'POST', | ||
}, | ||
output: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
) | ||
|
||
/* istanbul ignore next */ | ||
if (process.env.NODE_ENV !== 'test') main(cli) | ||
|
||
/** | ||
* Main | ||
*/ | ||
export async function main(cli: meow.Result): Promise<void> { | ||
/* Get remote endpoint from args */ | ||
const [endpoint] = cli.input | ||
|
||
if (!endpoint) { | ||
console.warn('No endpoint provided') | ||
return | ||
} | ||
|
||
/* Headers */ | ||
const defaultHeaders = { | ||
'Content-Type': 'application/json', | ||
} | ||
|
||
const headers = getHeadersFromInput(cli).reduce( | ||
(acc, { key, value }) => ({ ...acc, [key]: value }), | ||
defaultHeaders, | ||
) | ||
|
||
/* Fetch schema */ | ||
const schema = await getRemoteSchema(endpoint, { | ||
method: cli.flags.method, | ||
headers, | ||
json: cli.flags.json, | ||
}) | ||
|
||
if (schema.status === 'err') { | ||
console.warn(schema.message) | ||
return | ||
} | ||
|
||
if (cli.flags.output !== undefined) { | ||
printToFile(cli.flags.output, schema.schema) | ||
} else { | ||
console.log(schema.schema) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,106 @@ | ||
#!/usr/bin/env node | ||
|
||
import fetch from 'node-fetch' | ||
import * as fs from 'fs' | ||
import * as path from 'path' | ||
import meow = require('meow') | ||
import mkdirp = require('mkdirp') | ||
import { introspectionQuery } from 'graphql/utilities/introspectionQuery' | ||
import { buildClientSchema } from 'graphql/utilities/buildClientSchema' | ||
import { printSchema } from 'graphql/utilities/schemaPrinter' | ||
import * as minimist from 'minimist' | ||
import chalk from 'chalk' | ||
|
||
const { version } = require('../package.json') | ||
|
||
const usage = ` Usage: get-graphql-schema ENDPOINT_URL > schema.graphql | ||
${chalk.bold( | ||
'Fetch and print the GraphQL schema from a GraphQL HTTP endpoint', | ||
)} | ||
(Outputs schema in IDL syntax by default) | ||
Options: | ||
--header, -h Add a custom header (ex. 'X-API-KEY=ABC123'), can be used multiple times | ||
--json, -j Output in JSON format (based on introspection query) | ||
--version, -v Print version of get-graphql-schema | ||
` | ||
|
||
async function main() { | ||
const argv = minimist(process.argv.slice(2)) | ||
|
||
if (argv._.length < 1) { | ||
console.log(usage) | ||
return | ||
} | ||
|
||
if (argv['version'] || argv['v']) { | ||
console.log(version) | ||
process.exit(0) | ||
/** | ||
* | ||
* Normalizes header input from CLI | ||
* | ||
* @param cli | ||
*/ | ||
export function getHeadersFromInput( | ||
cli: meow.Result, | ||
): { key: string; value: string }[] { | ||
switch (typeof cli.flags.header) { | ||
case 'string': { | ||
const [key, value] = cli.flags.header.split('=') | ||
return [{ key, value }] | ||
} | ||
case 'object': { | ||
return cli.flags.header.map(header => { | ||
const [key, value] = header.split('=') | ||
return { key, value } | ||
}) | ||
} | ||
default: { | ||
return [] | ||
} | ||
} | ||
} | ||
|
||
const endpoint = argv._[0] | ||
|
||
const defaultHeaders = { | ||
'Content-Type': 'application/json', | ||
} | ||
|
||
const headers = toArray(argv['header']) | ||
.concat(toArray(argv['h'])) | ||
.reduce((obj, header: string) => { | ||
const [key, value] = header.split('=') | ||
obj[key] = value | ||
return obj | ||
}, defaultHeaders) | ||
|
||
const response = await fetch(endpoint, { | ||
method: 'POST', | ||
headers: headers, | ||
body: JSON.stringify({ query: introspectionQuery }), | ||
}) | ||
|
||
const { data, errors } = await response.json() | ||
|
||
if (errors) { | ||
throw new Error(JSON.stringify(errors, null, 2)) | ||
} | ||
interface Options { | ||
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | ||
headers?: { [key: string]: string } | ||
json?: boolean | ||
} | ||
|
||
if (argv['j'] || argv['json']) { | ||
console.log(JSON.stringify(data, null, 2)) | ||
} else { | ||
const schema = buildClientSchema(data) | ||
console.log(printSchema(schema)) | ||
/** | ||
* | ||
* Fetch remote schema and turn it into string | ||
* | ||
* @param endpoint | ||
* @param options | ||
*/ | ||
export async function getRemoteSchema( | ||
endpoint: string, | ||
options: Options, | ||
): Promise< | ||
{ status: 'ok'; schema: string } | { status: 'err'; message: string } | ||
> { | ||
try { | ||
const { data, errors } = await fetch(endpoint, { | ||
method: options.method, | ||
headers: options.headers, | ||
body: JSON.stringify({ query: introspectionQuery }), | ||
}).then(res => res.json()) | ||
|
||
if (errors) { | ||
return { status: 'err', message: JSON.stringify(errors, null, 2) } | ||
} | ||
|
||
if (options.json) { | ||
return { | ||
status: 'ok', | ||
schema: JSON.stringify(data, null, 2), | ||
} | ||
} else { | ||
const schema = buildClientSchema(data) | ||
return { | ||
status: 'ok', | ||
schema: printSchema(schema), | ||
} | ||
} | ||
} catch (err) { | ||
return { status: 'err', message: err.message } | ||
} | ||
} | ||
|
||
function toArray(value = []) { | ||
return Array.isArray(value) ? value : [value] | ||
/** | ||
* | ||
* Prints schema to file. | ||
* | ||
* @param dist | ||
* @param schema | ||
*/ | ||
export function printToFile( | ||
dist: string, | ||
schema: string, | ||
): { status: 'ok'; path: string } | { status: 'err'; message: string } { | ||
try { | ||
const output = path.resolve(process.cwd(), dist) | ||
|
||
if (!fs.existsSync(output)) { | ||
mkdirp.sync(output) | ||
} | ||
fs.writeFileSync(output, schema) | ||
|
||
return { status: 'ok', path: output } | ||
} catch (err) { | ||
return { status: 'err', message: err.message } | ||
} | ||
} | ||
|
||
main().catch(e => console.error(e)) |
Oops, something went wrong.