cosmo icon indicating copy to clipboard operation
cosmo copied to clipboard

Allow publishing/checking a subgraph schema from multiple files (e.g. a glob)

Open RMHonor opened this issue 9 months ago • 2 comments

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

RMHonor avatar Mar 14 '25 10:03 RMHonor

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.

github-actions[bot] avatar Mar 14 '25 10:03 github-actions[bot]

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:

  1. Single schema files (maintaining backward compatibility)
  2. Directories containing schema files
  3. 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:

  1. Add a Schema Loading Helper Function: Create a new function in cli/src/utils.ts that 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;
      }
    }
    
  2. 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);
      }
    });
    
  3. Update Subgraph Commands: Similarly update the subgraph publish and check commands.

  4. Add Dependencies: Ensure the glob package is added to dependencies:

    pnpm add glob
    pnpm add -D @types/glob
    
  5. Update Documentation: Update the help text to reflect the new functionality.

  6. 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:

  1. Fork and Clone the Repository:

    git clone https://github.com/YOUR_USERNAME/cosmo.git
    cd cosmo
    
  2. Create a Branch:

    git checkout -b feature/schema-glob-support
    
  3. Install Dependencies:

    pnpm install
    
  4. Implement the Changes as outlined above.

  5. Test Your Changes:

    pnpm run build
    ./bin/wgc schema publish path/to/schema/dir -g myGraph -s mySubgraph
    
  6. Commit and Push:

    git add .
    git commit -m "Add support for multiple schema files using glob patterns"
    git push origin feature/schema-glob-support
    
  7. Create a Pull Request to the main Cosmo repository.

buger avatar Mar 30 '25 14:03 buger