Created
July 24, 2023 17:38
-
-
Save karlrwjohnson/cbd2e24abe1326e4a7e8eb537f77b799 to your computer and use it in GitHub Desktop.
Split GraphQL Schema files
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
/* | |
GraphQL schema file splitter | |
Not guaranteed to work 100% of the time -- I just needed it to work once, for me, in my project | |
But I'm saving it in case I need it again | |
Basic idea is that I started a project with a rather loose policy toward file organization. | |
Every file had multiple "things" in it. | |
But I wanted to split it up along the lines of "one file per thing". | |
-- when one thing exists per file, you no longer argue what order things should appear in! | |
At time of writing, IntelliJ's "Move to another file" refactoring doesn't work on GraphQLS files | |
and moving them manually was getting annoying. | |
*/ | |
import { readdir, readFile, writeFile } from 'node:fs/promises'; | |
import { dirname, resolve } from 'node:path'; | |
import { fileURLToPath } from 'node:url'; | |
const __dirname = dirname(fileURLToPath(import.meta.url)); | |
const sourceDir = resolve(__dirname, 'graphql/_mixed'); | |
const destDirs = { | |
directive: resolve(__dirname, 'graphql/directives'), | |
enum: resolve(__dirname, 'graphql/enums'), | |
input: resolve(__dirname, 'graphql/inputs'), | |
interface: resolve(__dirname, 'graphql/interfaces'), | |
scalar: resolve(__dirname, 'graphql/scalars'), | |
type: resolve(__dirname, 'graphql/types'), | |
union: resolve(__dirname, 'graphql/unions'), | |
} | |
/** @type{({ sourceFilename: string, sourceLineNumber: number, kind: string, name: string, sourceLines: string[] })[]} **/ | |
const identifiedSections = []; | |
for (const filename of await readdir(sourceDir)) { | |
const lines = (await readFile(resolve(sourceDir, filename), { encoding: 'utf-8' })).split(/\r?\n/); | |
let lineNumber = 0; | |
let sourceLines = []; | |
while (lineNumber < lines.length) { | |
const line = lines[lineNumber++]; | |
sourceLines.push(line); | |
const sectionHeaderMatch = line.match(/^\s*(directive|enum|input|interface|scalar|type|union)\s+((?:\w|@)+)/); | |
if (sectionHeaderMatch) { | |
const [, kind, name] = sectionHeaderMatch; | |
console.log(`${filename}:${lineNumber}: ${kind} ${name}`); | |
const sectionStartLineNumber = lineNumber; | |
gatherSectionLines: switch (kind) { | |
case 'directive': { | |
if (line.match(/^\s*(directive|enum|input|interface|scalar|type|union)\s+((?:\w|@))\s+\(.+\)/)) { | |
break; | |
} else { | |
while (lineNumber < lines.length) { | |
const line = lines[lineNumber++]; | |
sourceLines.push(line); | |
const endSectionMatch = line.match(/^\s*\)/); | |
if (endSectionMatch) { | |
break gatherSectionLines; | |
} | |
} | |
throw new Error(`Ran off the end of ${filename} while parsing ${kind} ${name}`); | |
} | |
} | |
case 'scalar': { | |
break; // these are all one-liners | |
} | |
case 'union': { | |
while (lineNumber < lines.length) { | |
const line = lines[lineNumber++]; | |
sourceLines.push(line); | |
const continueSectionMatch = line.match(/^\s+[|A-Za-z]/); | |
if (!continueSectionMatch) { | |
break gatherSectionLines; | |
} | |
} | |
break gatherSectionLines; | |
} | |
default: { | |
if (line.match(/^\s*(directive|enum|input|interface|scalar|type|union)\s+((?:\w|@))\s+\{.+\}/)) { | |
break; | |
} else { | |
while (lineNumber < lines.length) { | |
const line = lines[lineNumber++]; | |
sourceLines.push(line); | |
const endSectionMatch = line.match(/^\s*\}/); | |
if (endSectionMatch) { | |
break gatherSectionLines; | |
} | |
} | |
throw new Error(`Ran off the end of ${filename} while parsing ${kind} ${name}`); | |
} | |
} | |
} | |
identifiedSections.push({ | |
sourceFilename: filename, | |
sourceLineNumber: sectionStartLineNumber, | |
kind, | |
name, | |
sourceLines, | |
}); | |
sourceLines = []; | |
} | |
} | |
} | |
for (const section of identifiedSections) { | |
await writeFile(resolve(destDirs[section.kind], section.name + '.graphqls'), | |
section.sourceLines.join('\n').trim() + '\n', | |
{ encoding: 'utf-8' }); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment