import { readFileSync } from 'node:fs'; import { join } from 'node:path'; import { buildSchema, type GraphQLSchema } from 'graphql'; import type { SchemaGroupConfig } from './types'; const EXTEND_RE = /\bextend\s+(type|interface)\b/g; export interface LoadedSchemaGroup { name: string; schema: GraphQLSchema; } /** * Build one `GraphQLSchema` from a group's SDL file(s). Files are concatenated * in the order given. When `mergeExtends` is set, `extend type X` / `extend * interface X` in every file is rewritten to `type X` / `interface X` first — * this lets a file that declares `extend type Query` against root fields only * present in the composed supergraph (not in the group's own base SDL) build * as a single self-contained schema instead of requiring the extend target to * pre-exist. */ export function loadSchemaGroup(group: SchemaGroupConfig, repoRoot: string): LoadedSchemaGroup { const parts = group.files.map((file) => { const text = readFileSync(join(repoRoot, file), 'utf8'); return group.mergeExtends ? text.replace(EXTEND_RE, '$1') : text; }); const sdl = parts.join('\n\n'); return { name: group.name, schema: buildSchema(sdl, { assumeValidSDL: true, assumeValid: true }), }; } export function loadSchemaGroups( groups: readonly SchemaGroupConfig[], repoRoot: string ): LoadedSchemaGroup[] { if (groups.length === 0) { throw new Error('schema-drift.config.json must declare at least one entry in schemaGroups.'); } return groups.map((g) => loadSchemaGroup(g, repoRoot)); }