Allow publishing/checking a subgraph schema from multiple files (e.g. a glob)
Component(s)
cli
Is your feature request related to a problem? Please describe.
Many of our subgraphs have a schema defined in multiple .graphql files, but the Cosmo CLI expects just a single schema file when publishing or checking a schema.
Describe the solution you'd like
Allow use of a glob when publishing a schema, this is what the Hive CLI allows. Or the CLI could just accept a directly to search for files within.
Describe alternatives you've considered
It's possible to use a bash command to pipe all the files into one (e.g. find "./src" -name "*.graphql" -print0 | xargs -0 cat > "./schema.graphql"), but this requires write access to the file system, and may not be a perfect solution.
We could also use our existing code generation tools (e.g. the schema-ast codegen plugin), but these appear to strip away directive definitions.
Both these solutions require a per-subgraph change which we'd like to avoid.
Additional context
No response
WunderGraph commits fully to Open Source and we want to make sure that we can help you as fast as possible. The roadmap is driven by our customers and we have to prioritize issues that are important to them. You can influence the priority by becoming a customer. Please contact us here.
I've investigated the problem and have a solution to propose.
Why This Happens
The Cosmo CLI currently only supports a single schema file when publishing or checking schemas. This is because the CLI reads the schema using:
const schemaSDL = readFileSync(resolve(schemaPath), 'utf8');
This approach doesn't handle directories or glob patterns, which is problematic for projects with modular schema definitions spread across multiple files.
The Hive CLI, on the other hand, supports glob patterns by finding and merging multiple schema files, which is the functionality you're looking for.
Proposed Solution
I propose enhancing the Cosmo CLI to support:
- Single schema files (maintaining backward compatibility)
- Directories containing schema files
- Glob patterns to match specific schema files
This would allow commands like:
# Single file (current behavior)
wgc schema publish schema.graphql -g myGraph -s mySubgraph
# Directory
wgc schema publish ./src/schema -g myGraph -s mySubgraph
# Glob pattern
wgc schema publish "./src/**/*.graphql" -g myGraph -s mySubgraph
Implementation Plan
Here's how we can implement this feature:
-
Add a Schema Loading Helper Function: Create a new function in
cli/src/utils.tsthat handles loading schemas from files, directories, or glob patterns:import { readFile } from 'node:fs/promises'; import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; import { glob } from 'glob'; /** * Loads schema content from a file path, directory, or glob pattern. * @param schemaPath Path to schema file, directory, or glob pattern * @returns Promise resolving to the combined schema content */ export async function loadSchemaFromPath(schemaPath: string): Promise<string> { const resolvedPath = resolve(schemaPath); // Check if it's a direct file path if (existsSync(resolvedPath) && !(await isDir(resolvedPath))) { return readFile(resolvedPath, 'utf8'); } // Handle directory or glob pattern let pattern = schemaPath; if (existsSync(resolvedPath) && (await isDir(resolvedPath))) { pattern = `${resolvedPath}/**/*.{graphql,gql}`; } const files = await glob(pattern, { absolute: true, }); if (files.length === 0) { throw new Error(`No GraphQL schema files found at path: ${schemaPath}`); } // Combine all schema files const schemaContents = await Promise.all(files.map(file => readFile(file, 'utf8'))); return schemaContents.join('\n\n'); } async function isDir(path: string): Promise<boolean> { try { const stat = await import('node:fs/promises').then((fs) => fs.stat(path)); return stat.isDirectory(); } catch (e) { return false; } } -
Update Schema Commands: Modify the schema check and publish commands to use this new function:
// In cli/src/commands/schema/check.ts and cli/src/commands/schema/publish.ts .argument('<schema>', 'Path to the schema file, directory, or glob pattern (e.g., "src/**/*.graphql")') // ... .action(async (schemaPath, options) => { try { const client = await createClient(); const schemaSDL = await loadSchemaFromPath(schemaPath); const schema = getSchemaFromString(schemaSDL); // Rest of the function remains the same // ... } catch (e: any) { printSchemaFromError(e); program.error(e.message); } }); -
Update Subgraph Commands: Similarly update the subgraph publish and check commands.
-
Add Dependencies: Ensure the
globpackage is added to dependencies:pnpm add glob pnpm add -D @types/glob -
Update Documentation: Update the help text to reflect the new functionality.
-
Write Tests: Add tests for the new functionality to ensure it works correctly.
How to Contribute This Change
If you'd like to implement this feature, here's how:
-
Fork and Clone the Repository:
git clone https://github.com/YOUR_USERNAME/cosmo.git cd cosmo -
Create a Branch:
git checkout -b feature/schema-glob-support -
Install Dependencies:
pnpm install -
Implement the Changes as outlined above.
-
Test Your Changes:
pnpm run build ./bin/wgc schema publish path/to/schema/dir -g myGraph -s mySubgraph -
Commit and Push:
git add . git commit -m "Add support for multiple schema files using glob patterns" git push origin feature/schema-glob-support -
Create a Pull Request to the main Cosmo repository.