Skip to content

Add --skip-typedefs option #4

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
.DS_Store
/output
/.vscode
/.nyc_output
/coverage
/tmp
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ Takes a glob of GraphQL files and writes a typescript module that exports the gr


```
Usage: graphql-to-typescript \[options\] \<graphqlFileGlob\> \<outputFile\>
Usage: graphql-to-typescript [options] <graphqlFileGlob> <outputFile>

Options:

-h, --help output usage information
--skip-typedefs skip writing typeDefs declaration to output files
-h, --help output usage information
```

Converts graphql files such as:

```
```graphql
schema {
query: RootQuery
}
Expand All @@ -29,7 +30,7 @@ type User {

Into the typescript file:

```
```typescript
export const typeDefs = ["schema {\n query: RootQuery\n}\ntype RootQuery {\n user(id: Int!): User\n}\ntype User {\n id: Int!\n name: String\n}\n"];

export interface RootQuery {
Expand All @@ -47,4 +48,4 @@ export interface User {

```

This allows you to import the interfaces and the schema elsewhere in your typescript project and use them in your resolvers.
This allows you to import the interfaces and the schema elsewhere in your typescript project and use them in your resolvers.
27 changes: 22 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
},
"dependencies": {
"chalk": "^1.1.3",
"commander": "^2.9.0",
"commander": "^2.12.2",
"graphql": "^0.9.1",
"graphql-code-generator": "^0.5.1",
"graphql-subscriptions": "^0.3.1",
Expand All @@ -21,12 +21,14 @@
"devDependencies": {
"@types/chai": "^3.4.35",
"@types/chalk": "^0.4.31",
"@types/commander": "^2.3.31",
"@types/mocha": "^2.2.40",
"@types/node": "^7.0.12",
"chai": "^3.5.0",
"istanbul": "^0.4.5",
"mocha": "^3.2.0",
"nyc": "^11.4.1",
"rimraf": "^2.6.1",
"ts-node": "^4.1.0",
"tslint": "^4.5.1",
"typescript": "^2.2.2",
"watch": "^1.0.2"
Expand All @@ -37,12 +39,27 @@
"clean": "rimraf dist/*",
"prepublish": "npm run clean && npm run lint && npm run test && npm run build",
"start": "npm run build:watch",
"pretest": "npm run clean && npm run build",
"test": "mocha \"dist/**/*.test.js\"",
"test:watch": "watch --wait=1 'npm run test' src/",
"test": "mocha --require ts-node/register src/**/*.test.ts",
"test:watch": "npm run test -- --watch --watch-extensions test.ts",
"test:coverage": "nyc npm run test",
"lint": "tslint src/**/*.ts"
},
"bin": {
"graphql-to-typescript": "./dist/index.js"
},
"nyc": {
"extension": [
".ts"
],
"include": [
"src/**/*.ts"
],
"exclude": [
"src/tests/**"
],
"reporter": [
"html"
],
"all": true
}
}
57 changes: 57 additions & 0 deletions src/application.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as chalk from 'chalk';
import { Command } from 'commander';

import { compileGraphql } from './compile-graphql';
import { CompileOptions } from './interfaces';
import { Commander } from './typings';

/**
* Application Factory
*
* calling this factory will always generate new application instance (useful for testing)
*/
export function application(): Commander.Command {
const application = new Command();

application
.arguments('<graphqlFileGlob> <outputFile>')
.option('--skip-typedefs', 'skip writing typeDefs declaration to output files');

return application;
}

/**
* Action Handler
*
* @param graphqlFileGlob
* @param outputFile
* @param command
*/
export async function handler(graphqlFileGlob, outputFile, command) {
try {
const options = parseOptions(graphqlFileGlob, outputFile, command);
await compileGraphql(options);

// tslint:disable-next-line:no-console
console.log(chalk.bold.green('Graphql output files compiled'));
} catch (e) {
console.error(chalk.bold.red(e));
}
}

/**
* Options Parser
*
* @param graphqlFileGlob
* @param outputFile
* @param command
*/
export function parseOptions(graphqlFileGlob, outputFile, command): CompileOptions {
const options = {
graphqlFileGlob,
outputFile,
skipTypeDefs: !!command.skipTypedefs
} as CompileOptions;

return options;
}
36 changes: 10 additions & 26 deletions src/compile-graphql.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,36 @@
import * as fs from 'fs';
import * as glob from 'glob';
import { graphql, introspectionQuery } from 'graphql';
import { Transform, TransformedOptions, getTemplateGenerator } from 'graphql-code-generator';
import { getTemplateGenerator, Transform, TransformedOptions } from 'graphql-code-generator';
import { makeExecutableSchema } from 'graphql-tools';

import { CompileOptions } from './interfaces';

export const compileGraphql = async (options: CompileOptions) => {

return new Promise((resolve, reject) => {

glob(options.graphqlFileGlob, {}, async (er, files) => {

try {

const output = [];
const typeDefs = [];

for (let file of files) {

typeDefs.push(fs.readFileSync(file, 'utf8'));

}

if (typeDefs.length === 0) {

throw new Error(`No type definitions were found matching: ${options.graphqlFileGlob}`);

}

output.push(`export const typeDefs = ${JSON.stringify(typeDefs)};`);
if (!options.skipTypeDefs) {
output.push(`export const typeDefs = ${JSON.stringify(typeDefs)};`);
}

const schema = makeExecutableSchema({ typeDefs });

const [introspectionResult, template] = await Promise.all(
[
graphql(schema, introspectionQuery),
getTemplateGenerator('typescript'),
]
);
const [introspectionResult, template] = await Promise.all([
graphql(schema, introspectionQuery),
getTemplateGenerator('typescript')
]);

const introspection = introspectionResult.data;

Expand All @@ -49,29 +41,21 @@ export const compileGraphql = async (options: CompileOptions) => {
outPath: './',
isDev: false,
noSchema: false,
noDocuments: true,
noDocuments: true
} as TransformedOptions;

const outFiles = await Transform(transformOptions);

for (let file of outFiles) {

output.push(file.content);

}

fs.writeFileSync(options.outputFile, output.join('\n'));

resolve();

} catch (e) {

reject(e);

}

});

});

}
};
35 changes: 9 additions & 26 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,14 @@
#! /usr/bin/env node
import * as chalk from 'chalk';
import * as commander from 'commander';
import { CompileOptions } from './interfaces';
#!/usr/bin/env node
import { application, handler } from './application';
import { compileGraphql } from './compile-graphql';
import { CompileOptions } from './interfaces';

commander
.arguments('<graphqlFileGlob> <outputFile>')
.action(async (graphqlFileGlob, outputFile) => {

try {

const options = {
graphqlFileGlob,
outputFile
} as CompileOptions;

await compileGraphql(options);

console.info(chalk.bold.green('Graphql output files compiled'));

} catch ( e ) {

console.error(chalk.bold.red(e));
const app = application();

}
app.action(handler).parse(process.argv);

})
.parse(process.argv);
if (!app.args.length) {
app.help();
}

export { CompileOptions, compileGraphql };
export { CompileOptions, compileGraphql };
7 changes: 3 additions & 4 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export interface CompileOptions {
graphqlFileGlob: string;
outputFile:string;
};


outputFile: string;
skipTypeDefs: boolean;
}
36 changes: 36 additions & 0 deletions src/tests/application.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { expect } from 'chai';

import { parseOptions } from '../application';
import { mockApp, mockArgs } from './helpers';

describe('Application - OptionParser', () => {
let parsedOptions;
const graphqlFileGlob = './src/tests/graphql/**/*.graphql';
const outputFile = './tmp/type-defs.ts';
const appMock = mockApp((arg1, arg2, cmd) => {
parsedOptions = parseOptions(arg1, arg2, cmd);
});

// reset parsedOptions before each test
beforeEach(() => {
parsedOptions = {};
});

it('should produce correct CompileOptions object when omit all optional options', () => {
const args = mockArgs([graphqlFileGlob, outputFile]);
const expectedOptions = { graphqlFileGlob, outputFile, skipTypeDefs: false };

appMock.parse(args);

expect(parsedOptions).to.eqls(expectedOptions);
});

it('should recognize --skip-typedefs options', () => {
const args = mockArgs([graphqlFileGlob, outputFile, '--skip-typedefs']);
const expectedOptions = { graphqlFileGlob, outputFile, skipTypeDefs: true };

appMock.parse(args);

expect(parsedOptions).to.eqls(expectedOptions);
});
});
Loading