Skip to content

Instantly share code, notes, and snippets.

@dex4er
Created May 20, 2019 00:33
Show Gist options
  • Save dex4er/330fb7fed04f88b58ec5388744bf78f7 to your computer and use it in GitHub Desktop.
Save dex4er/330fb7fed04f88b58ec5388744bf78f7 to your computer and use it in GitHub Desktop.
make-ts-from-graphql
#!/usr/bin/env ts-node
/// <reference types="node" />
import glob from 'fast-glob'
import fs from 'fs'
import path from 'path'
import yargs from 'yargs'
const defaultPatterns = ['**/*.graphql', '**/*.gql', '!node_modules']
const argv = yargs
.usage('$0 [options] [patterns]\n\n patterns default: ' + defaultPatterns.join(' '))
.option('target', {
alias: 't',
describe: 'Generate code for language (ts or js)',
string: true,
default: fs.existsSync('tsconfig.json') ? 'ts' : 'js',
})
.option('quiet', {
alias: 'q',
describe: 'Do not log currently processed files',
boolean: true,
default: false,
})
.help('help')
.alias('help', 'h')
.alias('version', 'V')
.strict().argv
const patterns = argv._.length ? argv._ : defaultPatterns
function upperFirst(str: string): string {
return str[0].toUpperCase() + str.slice(1)
}
function camelize(str: string): string {
return str.split(/[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/).reduce((result, word, index) => {
word = word.toLowerCase()
return result + (index ? upperFirst(word) : word)
}, '')
}
const BACKTICK = '`'
const LF = '\n'
function jsTemplate(variable: string, graphqlContent: string): string {
const content = graphqlContent
.replace(/\s*$/, '')
.replace(/'/g, "\\'")
.replace(/\n/g, '\\n')
return [
'// eslint:disable',
'"use strict"',
'var gql = require("graphql-tag")',
`module.exports = gql(['${content}'])`,
`module.exports.default = module.exports`,
`module.exports.${variable} = module.exports`,
'',
].join('\n')
}
function tsTemplate(variable: string, graphqlContent: string): string {
const content = graphqlContent.replace(/^/gm, ' ').replace(/\s*$/, '')
return [
'// tslint:disable',
'import {DocumentNode} from "graphql"',
'import gql from "graphql-tag"',
'// prettier-ignore',
`export const ${variable}: DocumentNode = gql${BACKTICK}${LF}${content}${LF}${BACKTICK}`,
`export default ${variable}`,
'',
].join('\n')
}
function targetTemplate(variable: string, graphqlContent: string): string {
if (argv.target === 'ts') {
return tsTemplate(variable, graphqlContent)
} else {
return jsTemplate(variable, graphqlContent)
}
}
glob<string>(patterns, {stats: false}).then(files => {
for (const graphqlFile of files) {
const graphqlExt = path.extname(graphqlFile)
if (graphqlExt !== '.graphql' && graphqlExt !== '.gql') {
console.info(`Skipping file ${graphqlFile}`)
continue
}
const graphqlBasename = path.basename(graphqlFile, graphqlExt)
const targetExt = argv.target === 'ts' ? '.ts' : '.js'
const targetFile = path.join(path.dirname(graphqlFile), graphqlBasename) + targetExt
if (!argv.quiet) {
console.info(`Creating ${targetFile} from ${graphqlFile}`)
}
const graphqlContent = fs.readFileSync(graphqlFile).toString()
const targetVariable = camelize(`${graphqlBasename} Query`)
const targetContent = targetTemplate(targetVariable, graphqlContent)
fs.writeFileSync(targetFile, targetContent)
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment