Skip to content

Instantly share code, notes, and snippets.

@Mikhus
Last active October 29, 2019 21:56
Show Gist options
  • Save Mikhus/cd7e5bed59df898703f612ca4dd09459 to your computer and use it in GitHub Desktop.
Save Mikhus/cd7e5bed59df898703f612ca4dd09459 to your computer and use it in GitHub Desktop.
GraphQL schema to TypeScript definitions. Usage: ./gqlts.js /path/to/schema.graphql > /path/to/schema.d.ts
#!/usr/bin/env node
/*!
* ISC License
*
* Copyright (c) 2019, Mykhailo Stadnyk <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* Typescript typedefs code generation from a given GraphQL schema
*/
const fs = require('fs');
const schemaPath = process.argv.pop();
const schemaText = fs.readFileSync(schemaPath, { encoding: 'utf8' });
const schemaCode = schemaText
.replace(/(^|\n)(\s*)#/g, '$1$2\/\/')
.replace(/(input|type)\s/g, 'export interface ')
.replace(/enum\s/g, 'export enum ')
.replace(/schema\s/, 'export interface schema ')
.replace(/union\s/, 'export type ')
.replace(/^(\s+[a-zA-Z0-9_-]+\s*)\([^\)]+\)(\s*:\s*)/g, '$1$2')
.replace(
/("""((?!""")[\s\S])+""")?\s*scalar\s+(.*?)\r?\n/g,
'export type $3 = any;\n'
)
.replace(/(\s*)"""([\s\S]*?)"""/g, (m, s, p) => {
const pad = ' '.repeat(s.replace(/\r?\n/g, '').length);
return `\n${pad}/**\n${p
.replace(/(\r?\n){2,}/, '')
.trim()
.split(/\r?\n/)
.map(l => `${pad} * ${l.trim()}`)
.join('\n')
}\n ${pad}*/\n`
})
.replace(/(\r?\n){2,}/g, '\n')
.replace(
/([:=|]\s*)\[ID!?\](!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}string[];${e}`,
)
.replace(
/([:=|]\s*)ID(!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}string;${e}`,
)
.replace(
/([:=|]\s*)\[String!?\](!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}string[];${e}`,
)
.replace(
/([:=|]\s*)String(!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}string;${e}`,
)
.replace(
/([:=|]\s*)\[Float!?\](!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}number[];${e}`,
)
.replace(
/([:=|]\s*)Float(!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}number;${e}`,
)
.replace(
/([:=|]\s*)\[Int!?\](!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}number[];${e}`,
)
.replace(
/([:=|]\s*)Int(!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}number;${e}`,
)
.replace(
/([:=|]\s*)\[DateTime!?\](!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}Date[];${e}`,
)
.replace(
/([:=|]\s*)DateTime(!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}Date;${e}`,
)
.replace(
/([:=|]\s*)\[Boolean!?\](!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}boolean[];${e}`,
)
.replace(
/([:=|]\s*)Boolean(!?)($|\s+|\))/g,
(m, f, r, e) => `${r ? '' : '?'}${f}boolean;${e}`,
)
.replace(
/([:=|]\s*)\[([a-zA-Z0-9_-]+)!?\](!?)/g,
(m, f, t, r) => `${r ? '' : '?'}${f}${t}[];`,
)
.replace(
/([:=|]\s*)((?!string|number|boolean|Date)[a-zA-Z0-9_-]+)(!?)/g,
(m, f, t, r) => `${r ? '' : '?'}${f}${t};`,
)
.replace(/\?{2,}:/g, '?:')
.replace(/;{2,}/g, ';')
.replace(
/(enum\s+[^{]+?\s*\{)([^}]*)(\})/g,
(m, d, b, e) => {
b = b.split(/\r?\n/)
.filter(l => l.trim())
.map(l => `${l} = '${l.trim()}'`)
.join(',\n')
;
return `${d}\n${b}\n${e}`;
},
)
.replace(
/(\([^\)]+\))\??/g,
(m, b) => b.replace(/(.+:.+);/g, '$1,')
)
.replace(/;\[\];/g, '[];')
.replace(/(\s+)\?=/g, '$1=')
.replace(/(interface\s+.*?\s+)implements\s/g, '$1extends ')
.replace(/,\)/g, ')')
.replace(/(enum[^{]+\{[^}]+[^\s,])(\s*\})/g, '$1,$2')
.replace(/\s*$/, '\n')
;
console.log(`${schemaCode.trim()}`);
@shicholas
Copy link

this is amazing, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment