From aec185d7dd9a1e381d9a6497c01c7ad74d2df3f4 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Sat, 17 Oct 2026 08:46:09 -0400 Subject: [PATCH] chore(codegen): add reproducible Bitbucket GraphQL code generation The Bitbucket GraphQL types had no producing configuration - they were generated ad hoc, so they could not be regenerated. - Add a Bitbucket generator to codegen.ts (schema = the public Atlassian gateway, documents = the Bitbucket documents). - Restructure the entrypoint around per-output schemas so the credential-free Bitbucket generator runs even when GITHUB_TOKEN is unset; the GitHub output is added only when a token exists. - The public Atlassian schema needs assumeValid (graphql-js v17) and the documents need skipDocumentsValidation (the gateway schema lacks arguments such as 'flat'); defaultScalarType: 'string' preserves the existing string typing for picture/timestamp. Regeneration produces equivalent public types; three formatting differences (Record, normalised document strings, trailing newline) are toolchain-version-driven. OpenSpec change: add-bitbucket-graphql-codegen --- codegen.ts | 90 ++++++++++++------- .../bitbucket/graphql/generated/graphql.ts | 8 +- 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/codegen.ts b/codegen.ts index ddbe02474..9e62e9434 100644 --- a/codegen.ts +++ b/codegen.ts @@ -3,46 +3,72 @@ import dotenv from 'dotenv'; dotenv.config(); -if (!process.env.GITHUB_TOKEN) { +// The Atlassian GraphQL gateway is public and requires no credentials. +const ATLASSIAN_GRAPHQL_URL = 'https://developer.atlassian.com/gateway/api/graphql'; + +const generates: CodegenConfig['generates'] = { + 'src/renderer/utils/forges/bitbucket/graphql/generated/graphql.ts': { + schema: { + // The public Atlassian schema also fails graphql-js v17's stricter + // interface-deprecation-consistency validation, so skip validation. + [ATLASSIAN_GRAPHQL_URL]: { assumeValid: true }, + }, + documents: ['src/renderer/utils/forges/bitbucket/**/*.graphql'], + plugins: ['typescript-operations', 'typed-document-node'], + config: { + documentMode: 'string', + enumType: 'native', + defaultScalarType: 'string', + useTypeImports: true, + // The public gateway schema diverges from the runtime Atlassian schema + // (for example `notificationFeed` lacks the `flat` argument), so document + // validation against it is skipped. See setchy/atlassify for the same workaround. + skipDocumentsValidation: true, + }, + }, +}; + +if (process.env.GITHUB_TOKEN) { + generates['src/renderer/utils/forges/github/graphql/generated/graphql.ts'] = { + schema: { + 'https://api.github.com/graphql': { + headers: { + Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, + // Hierarchy and issue fields each require their GraphQL schema feature. + 'GraphQL-Features': 'sub_issues,issue_fields', + }, + // GitHub's live schema currently fails graphql-js's stricter + // interface-deprecation-consistency validation (added in graphql v17). + // Skip validation so introspection can still succeed. + assumeValid: true, + }, + }, + documents: ['src/renderer/utils/forges/github/**/*.graphql'], + plugins: ['typescript-operations', 'typed-document-node'], + config: { + documentMode: 'string', + // enumType: 'native', + scalars: { + DateTime: 'string', + URI: '../../../../../types#Link', + }, + useTypeImports: true, + }, + }; +} else { // oxlint-disable-next-line no-console -- CLI script output console.warn( - '\x1b[33m⚠ GITHUB_TOKEN is not set. Skipping GraphQL codegen.\n' + - ' To generate updated types, create a .env file with a valid GitHub PAT.\n' + + '\x1b[33m⚠ GITHUB_TOKEN is not set. Skipping GitHub GraphQL codegen.\n' + + ' To generate updated GitHub types, create a .env file with a valid GitHub PAT.\n' + ' See .env.template for details.\x1b[0m', ); - process.exit(0); } const config: CodegenConfig = { overwrite: true, - schema: { - 'https://api.github.com/graphql': { - headers: { - Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, - // Hierarchy and issue fields each require their GraphQL schema feature. - 'GraphQL-Features': 'sub_issues,issue_fields', - }, - // GitHub's live schema currently fails graphql-js's stricter - // interface-deprecation-consistency validation (added in graphql v17). - // Skip validation so introspection can still succeed. - assumeValid: true, - }, - }, - documents: ['src/renderer/utils/forges/github/**/*.graphql'], - generates: { - 'src/renderer/utils/forges/github/graphql/generated/graphql.ts': { - plugins: ['typescript-operations', 'typed-document-node'], - config: { - documentMode: 'string', - // enumType: 'native', - scalars: { - DateTime: 'string', - URI: '../../../../../types#Link', - }, - useTypeImports: true, - }, - }, - }, + // Per-output schemas are declared on each `generates` entry, so no root schema is needed. + documents: [], + generates, }; export default config; diff --git a/src/renderer/utils/forges/bitbucket/graphql/generated/graphql.ts b/src/renderer/utils/forges/bitbucket/graphql/generated/graphql.ts index ad5718542..4cc399900 100644 --- a/src/renderer/utils/forges/bitbucket/graphql/generated/graphql.ts +++ b/src/renderer/utils/forges/bitbucket/graphql/generated/graphql.ts @@ -55,9 +55,9 @@ export class TypedDocumentString { __apiType?: NonNullable['__apiType']>; private value: string; - public __meta__?: Record | undefined; + public __meta__?: Record | undefined; - constructor(value: string, __meta__?: Record | undefined) { + constructor(value: string, __meta__?: Record | undefined) { super(value); this.value = value; this.__meta__ = __meta__; @@ -157,7 +157,7 @@ export const MyNotificationsDocument = new TypedDocumentString(` notificationFeed( flat: $flat first: $first - filter: {readStateFilter: $readState} + filter: { readStateFilter: $readState } ) { pageInfo { hasNextPage @@ -221,4 +221,4 @@ export const MarkAsUnreadDocument = new TypedDocumentString(` markNotificationsByIdsAsUnread(ids: $notificationIDs) } } - `) as unknown as TypedDocumentString; + `) as unknown as TypedDocumentString; \ No newline at end of file