From 34e0793e5d4f6b2d804906387595f28429bbdb14 Mon Sep 17 00:00:00 2001 From: Aaron Adams Date: Tue, 4 Feb 2025 07:51:36 +0000 Subject: [PATCH] feat: multi-project support --- src/index.ts | 6 +++ .../graphql-multi-project.spec.ts.snap | 30 +++++++++++++ .../graphql-multi-project.spec.ts | 42 +++++++++++++++++++ test/graphql-multi-project/graphql.config.yml | 11 +++++ .../graphql/queries/Foo.graphql | 3 ++ test/graphql-multi-project/schema.graphql | 3 ++ 6 files changed, 95 insertions(+) create mode 100644 test/graphql-multi-project/__snapshots__/graphql-multi-project.spec.ts.snap create mode 100644 test/graphql-multi-project/graphql-multi-project.spec.ts create mode 100644 test/graphql-multi-project/graphql.config.yml create mode 100644 test/graphql-multi-project/graphql/queries/Foo.graphql create mode 100644 test/graphql-multi-project/schema.graphql diff --git a/src/index.ts b/src/index.ts index 0181798..a920438 100644 --- a/src/index.ts +++ b/src/index.ts @@ -54,6 +54,10 @@ export interface Options { * @default false */ matchOnSchemas?: boolean; + /** + * Name of a project in a multi-project config file. + */ + project?: string; /** * Manually define the codegen config. */ @@ -98,6 +102,7 @@ export function GraphQLCodegen(options?: Options): Plugin { throwOnBuild = true, matchOnDocuments = true, matchOnSchemas = false, + project = null, config = null, configOverride = {}, configOverrideOnStart = {}, @@ -140,6 +145,7 @@ export function GraphQLCodegen(options?: Options): Plugin { log("Loading codegen context:", configFilePathOverride ?? cwd); codegenContext = await loadContext(configFilePathOverride); } + if (project != null) codegenContext.useProject(project); log("Loading codegen context successful"); } catch (error) { log("Loading codegen context failed"); diff --git a/test/graphql-multi-project/__snapshots__/graphql-multi-project.spec.ts.snap b/test/graphql-multi-project/__snapshots__/graphql-multi-project.spec.ts.snap new file mode 100644 index 0000000..26fbde0 --- /dev/null +++ b/test/graphql-multi-project/__snapshots__/graphql-multi-project.spec.ts.snap @@ -0,0 +1,30 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`graphql-multi-project > generates 1`] = ` +"export type Maybe = T | null; +export type InputMaybe = Maybe; +export type Exact = { [K in keyof T]: T[K] }; +export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; +export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +export type MakeEmpty = { [_ in K]?: never }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } +}; + +export type Query = { + __typename?: 'Query'; + foo?: Maybe; +}; + +export type FooQueryVariables = Exact<{ [key: string]: never; }>; + + +export type FooQuery = { __typename?: 'Query', foo?: string | null }; +" +`; diff --git a/test/graphql-multi-project/graphql-multi-project.spec.ts b/test/graphql-multi-project/graphql-multi-project.spec.ts new file mode 100644 index 0000000..4a577b6 --- /dev/null +++ b/test/graphql-multi-project/graphql-multi-project.spec.ts @@ -0,0 +1,42 @@ +import { promises as fs } from "node:fs"; +import { createServer, type UserConfig, type ViteDevServer } from "vite"; +import { afterAll, afterEach, beforeAll, describe, expect, it } from "vitest"; +import codegen from "../../src/index"; + +const TEST_PATH = "./test/graphql-multi-project" as const; +const OUTPUT_PATH = `${TEST_PATH}/generated` as const; +const OUTPUT_FILE = `${OUTPUT_PATH}/graphql.ts` as const; + +const viteConfig = { + root: import.meta.dirname, + plugins: [ + codegen({ + configFilePathOverride: `${TEST_PATH}/graphql.config.yml`, + project: "foo", + }), + ], +} satisfies UserConfig; + +describe("graphql-multi-project", () => { + let viteServer: ViteDevServer | null = null; + + beforeAll(async () => { + viteServer = await createServer(viteConfig).then((s) => s.listen()); + }); + + afterAll(async () => { + await viteServer?.close(); + viteServer = null; + }); + + afterEach(async () => { + await fs.rm(OUTPUT_PATH, { recursive: true }); + }); + + it("generates", async () => { + await new Promise((resolve) => setTimeout(resolve, 200)); + const file = await fs.readFile(OUTPUT_FILE, "utf-8"); + + expect(file).toMatchSnapshot(); + }); +}); diff --git a/test/graphql-multi-project/graphql.config.yml b/test/graphql-multi-project/graphql.config.yml new file mode 100644 index 0000000..685d437 --- /dev/null +++ b/test/graphql-multi-project/graphql.config.yml @@ -0,0 +1,11 @@ +projects: + foo: + schema: ./test/graphql-multi-project/schema.graphql + documents: ./test/graphql-multi-project/graphql/**/*.graphql + extensions: + codegen: + generates: + ./test/graphql-multi-project/generated/graphql.ts: + plugins: + - typescript + - typescript-operations diff --git a/test/graphql-multi-project/graphql/queries/Foo.graphql b/test/graphql-multi-project/graphql/queries/Foo.graphql new file mode 100644 index 0000000..09a7362 --- /dev/null +++ b/test/graphql-multi-project/graphql/queries/Foo.graphql @@ -0,0 +1,3 @@ +query Foo { + foo +} diff --git a/test/graphql-multi-project/schema.graphql b/test/graphql-multi-project/schema.graphql new file mode 100644 index 0000000..6a59a3a --- /dev/null +++ b/test/graphql-multi-project/schema.graphql @@ -0,0 +1,3 @@ +type Query { + foo: String +}