diff --git a/.changeset/upset-bars-call.md b/.changeset/upset-bars-call.md new file mode 100644 index 00000000000..1b09fb593e8 --- /dev/null +++ b/.changeset/upset-bars-call.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': minor +'@graphql-codegen/visitor-plugin-common': minor +--- + +Fixing 2 bugs: 1) including enums from external fragments; 2) extractAllFieldsToTypesCompact does not create duplicates diff --git a/dev-test-apollo-tooling/README.md b/dev-test-apollo-tooling/README.md new file mode 100644 index 00000000000..69e815dce45 --- /dev/null +++ b/dev-test-apollo-tooling/README.md @@ -0,0 +1,20 @@ +The `dev-test-apollo-tooling` package is an example of migrating from Apollo tooling to GraphQL Codegen. It attempts to generate output as close as possible to Apollo tooling’s output. Note: **this package is a work in progress** and currently requires a patch to `near-operation-file`. We will fix this package soon. + +How to run this package: + +1. Make sure you have the correct Yarn version installed (check the root package.json, `packageManager` entry). Otherwise, you might run into unexplained bugs. +2. In the monorepo root, run: + +yarn clean && yarn install && yarn build + +3. Patch `near-operation-file` manually (the automatic patch doesn’t always work). In the monorepo root, run: + +yarn postinstall + +4. Go to the `dev-test-apollo-tooling` directory and run: + +cd dev-test-apollo-tooling +yarn install +yarn start + +This will generate type files in `dev-test-apollo-tooling/src/__generated__/*`. diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts new file mode 100644 index 00000000000..72994ab2d47 --- /dev/null +++ b/dev-test-apollo-tooling/cli/index.ts @@ -0,0 +1,91 @@ +#!/usr/bin/env ts-node + +import { generate } from '@graphql-codegen/cli'; +import type { Types } from '@graphql-codegen/plugin-helpers'; + +export const GENERATED = '__generated__'; +export const GLOBAL_TYPES_FILE = 'globalTypes.ts'; +export const TS_GENERATED_FILE_HEADER = `\ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. +`; + +/** + * The following GraphQL Codegen config matches as closely as possible + * to the old apollo-tooling codegen + * @see https://github.com/apollographql/apollo-tooling/issues/2053 + * */ +const GRAPHQL_CODEGEN_CONFIG = { + useTypeImports: true, + namingConvention: 'keep', // Keeps naming as-is + avoidOptionals: false, // Allow '?' on variables fields + nonOptionalTypename: true, // Forces `__typename` on all selection sets + skipTypeNameForRoot: true, // Don't generate __typename for root types + omitOperationSuffix: true, // Don't add 'Query', 'Mutation' or 'Subscription' suffixes to operation result types + fragmentSuffix: '', // Don't add 'Fragment' suffix to fragment result types + extractAllFieldsToTypesCompact: true, // Extracts all fields to separate types (similar to apollo-codegen behavior) + printFieldsOnNewLines: true, // Prints each field on a new line (similar to apollo-codegen behavior) + importTypesNamespace: '', // Disable namespace prefix on imported types (preset config) + enumType: 'native', + generatesOperationTypes: true, +}; + +export const main = async () => { + const cwd = process.cwd(); + + const localSchemaFilePath = `${cwd}/schema.graphql`; + + const includes = ['src']; + + const generateFiles: { [scanPath: string]: Types.ConfiguredOutput } = {}; + + // Prepare the required structure for GraphQL Codegen + includes.forEach((include: string) => { + generateFiles[include] = { + preset: 'near-operation-file', // This preset tells the codegen to generate multiple files instead of one + presetConfig: { + extension: '.ts', // Matches the existing Apollo-Codegen file naming + // FIXME: The following config is required, but it is not needed with the recent version of typescript-operations. + // So - when the new version of near-operation-file' is available - fix this. + baseTypesPath: 'unused', + folder: GENERATED, // Output folder for generated files + importTypesNamespace: '', // Disable namespace prefix on imported types + }, + plugins: [ + 'typescript-operations', + { + add: { + content: TS_GENERATED_FILE_HEADER, + }, + }, + ], + }; + }); + + await generate( + { + schema: localSchemaFilePath, + documents: [ + // matching js extensins as well - there are cases where js files are not converted to typescript yet + // (but the package is typescript) + ...includes.map((include: any) => `${include}/**/*.{js,jsx,ts,tsx}`), + `!**/${GENERATED}/**`, + ], + config: GRAPHQL_CODEGEN_CONFIG, + generates: generateFiles, + silent: false, + debug: true, + verbose: true, + }, + true // overwrite existing files + ); +}; + +if (import.meta.url === process.argv[1] || import.meta.url === `file://${process.argv[1]}`) { + main().catch(e => { + console.error(e); + process.exit(1); + }); +} diff --git a/dev-test-apollo-tooling/package.json b/dev-test-apollo-tooling/package.json new file mode 100644 index 00000000000..164edd8d7cf --- /dev/null +++ b/dev-test-apollo-tooling/package.json @@ -0,0 +1,30 @@ +{ + "name": "dev-test-apollo-tooling", + "description": "A setup which mimics Apollo tooling generation as close as possible", + "version": "0.0.1", + "type": "module", + "dependencies": { + "@apollo/client": "3.13.8", + "@graphql-codegen/cli": "*", + "@graphql-codegen/plugin-helpers": "*", + "@graphql-codegen/typescript-operations": "*", + "@graphql-codegen/visitor-plugin-common": "*", + "@graphql-codegen/typed-document-node": "*" + }, + "devDependencies": { + "@types/node": "^25.0.3", + "tsx": "4.7.0", + "typescript": "^5.9.3", + "vitest": "4.0.4" + }, + "files": [ + "cli" + ], + "scripts": { + "start": "tsx cli/index.ts", + "start:debug": "NODE_OPTIONS='--trace-warnings' tsx cli/index.ts", + "start:verbose": "DEBUG='*' tsx cli/index.ts", + "test": "vitest --no-watch" + }, + "sideEffects": false +} diff --git a/dev-test-apollo-tooling/schema.graphql b/dev-test-apollo-tooling/schema.graphql new file mode 100644 index 00000000000..68909ce7a6e --- /dev/null +++ b/dev-test-apollo-tooling/schema.graphql @@ -0,0 +1,338 @@ +schema + @link(url: "https://specs.apollo.dev/link/v1.0") + @link(url: "https://specs.apollo.dev/join/v0.4", for: EXECUTION) + @link(url: "https://specs.apollo.dev/tag/v0.3") { + query: Query +} + +directive @join__graph(name: String!, url: String!) on ENUM_VALUE + +directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE + +directive @join__field( + graph: join__Graph + requires: join__FieldSet + provides: join__FieldSet + type: String + external: Boolean + override: String + usedOverridden: Boolean + overrideLabel: String +) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION + +directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE + +directive @join__type( + graph: join__Graph! + key: join__FieldSet + extension: Boolean! = false + resolvable: Boolean! = true + isInterfaceObject: Boolean! = false +) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR + +directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION + +directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA + +directive @tag( + name: String! +) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA + +scalar join__FieldSet + +scalar link__Import + +enum link__Purpose { + EXECUTION +} + +enum join__Graph { + SUPER_USER_MANAGER @join__graph(name: "super_user_management", url: "http://i.am.not.used.example.com") + GRAPHQL_MAIN__SHARD__BASE @join__graph(name: "graphql_main__shard__base", url: "http://i.am.not.used.example.com") + GRAPHQL_MAIN__SHARD__INTERNAL_TESTING + @join__graph(name: "graphql_main__shard__internal_testing", url: "http://i.am.not.used.example.com") +} + +type Query { + superUser: SuperUser! @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) + organization(id: String!): Organization @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +enum UserManagerRoleType @join__type(graph: SUPER_USER_MANAGER) { + ROLE_TYPE_1 @join__enumValue(graph: SUPER_USER_MANAGER) + + ROLE_TYPE_2 @join__enumValue(graph: SUPER_USER_MANAGER) + + ROLE_TYPE_3 @join__enumValue(graph: SUPER_USER_MANAGER) +} + +type UserManager @join__type(graph: SUPER_USER_MANAGER) { + fooUser: User! + + roleType: UserManagerRoleType! +} + +type User { + id: ID! + profilePhoto: UserProfilePhoto @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type AdminUser { + id: ID! + profilePhoto: UserProfilePhoto @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type UserProfilePhoto @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + photoUrl: UserPhotoUrl +} + +type UserPhotoUrl @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + url(size: UserPhotoSize!): String +} + +enum UserPhotoSize + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + SQUARE_300 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +type SuperUser @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + groupFromAlias(alias: String!): SuperUserGroup! +} + +type SuperUserGroup + @join__type(graph: SUPER_USER_MANAGER, key: "id") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + + managers(onlyPublic: Boolean! = false): [UserManager!] @join__field(graph: SUPER_USER_MANAGER) +} + +# Schema definitions for Duplicates.ts examples + +interface ConfigTypeDefinition @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! +} + +type ConfigActionId implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! +} + +type ConfigString implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + supportedHtmlTags: [String!] +} + +type ConfigEnum implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + values: [String!]! +} + +type ConfigIconResource implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + parameters: [ConfigParameterDefinition!]! +} + +type ConfigIllustrationResource implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + parameters: [ConfigParameterDefinition!]! +} + +type ConfigStruct implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + parameters: [ConfigParameterDefinition!]! +} + +type ConfigParameterDefinition @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + name: String! + typeId: String! + isRequired: Boolean! + defaultValue: String +} + +type Organization implements Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + internalOrgData: InternalOrgData @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type InternalOrgData @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + processableFeedback( + first: Int + after: String + sortBy: ProcessableFeedbackSortBy + sortOrder: ProcessableFeedbackSortOrder + scoreFilter: [Int] + ): FeedbackConnection @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +enum ProcessableFeedbackSortBy + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + OPTION_1 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + OPTION_2 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + OPTION_3 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + OPTION_4 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +enum ProcessableFeedbackSortOrder + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + ASC @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + DESC @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +type FeedbackConnection @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + edges: [FeedbackEdge] + pageInfo: PageInfo! + totalCount: Int +} + +type FeedbackEdge @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + cursor: String! + node: Feedback +} + +type Feedback implements Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + orgMemberThread: Thread @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type Thread implements Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + posts(after: String, first: Int): ThreadPostConnection @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type ThreadPostConnection @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + edges: [ThreadPostEdge] + pageInfo: PageInfo! +} + +type ThreadPostEdge @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + cursor: String! + node: ThreadPost +} + +type ThreadPost @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + creator: ThreadPostCreator + text: String + createdAt: DateTime +} + +union ThreadPostCreator + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__unionMember(graph: GRAPHQL_MAIN__SHARD__BASE, member: "OrgMember") + @join__unionMember(graph: GRAPHQL_MAIN__SHARD__BASE, member: "EndUser") = + OrgMember + | EndUser + +type OrgMember @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + fullName: String + avatar: OrgMemberAvatar +} + +type EndUser @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + fullName: String + avatar: EndUserAvatar +} + +type OrgMemberAvatar implements Photo & Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Photo") + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + imageUrl: OrgMemberImageUrl +} + +type OrgMemberImageUrl @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + url(size: OrgMemberImageSize!): String +} + +enum OrgMemberImageSize + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + LARGE + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + MEDIUM + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + SMALL + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +type EndUserAvatar implements Photo & Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Photo") + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + imageUrl: EndUserImageUrl +} + +type EndUserImageUrl @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + url(size: EndUserImageSize!): String +} + +enum EndUserImageSize + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + LARGE + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + MEDIUM + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + SMALL + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +interface Photo { + id: ID! +} + +interface Node { + id: ID! +} + +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: String + endCursor: String +} + +scalar DateTime diff --git a/dev-test-apollo-tooling/src/Component.ts b/dev-test-apollo-tooling/src/Component.ts new file mode 100644 index 00000000000..251f14a354d --- /dev/null +++ b/dev-test-apollo-tooling/src/Component.ts @@ -0,0 +1,26 @@ +/** + * This file tests generating enum from external fragement from another file. + * Check that UserManagerRoleType enum is generated in __generated__/Component.ts + */ + +import { useQuery, gql } from '@apollo/client'; +import Helper from './Helper'; + +export const getFooQuery = gql` + ${Helper.fragments.query} + query GetFoo($alias: String!, $collectionId: String!) { + superUser { + groupFromAlias(alias: $alias) { + managers(onlyPublic: true) { + ...HelperFields + } + } + } + } +`; + +const Component = () => { + useQuery(getFooQuery, {}); +}; + +export default Component; diff --git a/dev-test-apollo-tooling/src/Duplicates.ts b/dev-test-apollo-tooling/src/Duplicates.ts new file mode 100644 index 00000000000..54a4397a0db --- /dev/null +++ b/dev-test-apollo-tooling/src/Duplicates.ts @@ -0,0 +1,82 @@ +/** + * This file tests handing duplicates when using extractAllFieldsToTypesCompact: true + * Check the resultring __generated__/Duplicates.ts file - it should not contain any duplicate names. + */ + +import { gql } from '@apollo/client'; + +export const getTypeDefinitionsFragment = gql` + fragment ConfigTypeDefinitions on ConfigTypeDefinition { + __typename + ... on ConfigActionId { + identifier + } + ... on ConfigString { + identifier + supportedHtmlTags + } + ... on ConfigEnum { + identifier + values + } + } +`; + +export const GET_FEEDBACK_DATA = gql` + query GetFeedbackData( + $organizationId: String! + $first: Int + $after: String + $scoreFilter: [Int] + $sortBy: ProcessableFeedbackSortBy + $sortOrder: ProcessableFeedbackSortOrder + ) { + organization(id: $organizationId) { + internalOrgData { + processableFeedback( + first: $first + after: $after + sortBy: $sortBy + sortOrder: $sortOrder + scoreFilter: $scoreFilter + ) { + edges { + node { + id + orgMemberThread { + id + posts(first: 1, after: "") { + edges { + node { + creator { + __typename + ... on OrgMember { + id + fullName + avatar { + imageUrl { + url(size: SMALL) + } + } + } + ... on EndUser { + id + fullName + avatar { + imageUrl { + url(size: SMALL) + } + } + } + } + } + } + } + } + } + } + } + } + } + } +`; diff --git a/dev-test-apollo-tooling/src/Helper.ts b/dev-test-apollo-tooling/src/Helper.ts new file mode 100644 index 00000000000..c562fc0eb0a --- /dev/null +++ b/dev-test-apollo-tooling/src/Helper.ts @@ -0,0 +1,27 @@ +import { gql } from '@apollo/client'; + +const getHelperFieldsFragment = gql` + fragment HelperFields on UserManager { + roleType + fooUser { + profilePhoto { + photoUrl { + url(size: SQUARE_300) + } + } + } + } +`; + +export const helperPropsFromFragment = (fragment: any) => ({ + profilePhotoUrl: fragment.fooUser.profilePhoto?.photoUrl.url, + roleType: fragment.roleType, +}); + +const Helper = { fragments: { query: {} } }; + +Helper.fragments = { + query: getHelperFieldsFragment, +}; + +export default Helper; diff --git a/dev-test-apollo-tooling/src/__generated__/Component.ts b/dev-test-apollo-tooling/src/__generated__/Component.ts new file mode 100644 index 00000000000..72d65a65725 --- /dev/null +++ b/dev-test-apollo-tooling/src/__generated__/Component.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +import type * as Types from '../unused'; + +type Exact = { [K in keyof T]: T[K] }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export enum UserManagerRoleType { + ROLE_TYPE_1 = 'ROLE_TYPE_1', + ROLE_TYPE_2 = 'ROLE_TYPE_2', + ROLE_TYPE_3 = 'ROLE_TYPE_3', +} + +export type GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto_photoUrl = { + __typename: 'UserPhotoUrl'; + url: string | null; +}; + +export type GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto = { + __typename: 'UserProfilePhoto'; + photoUrl: GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto_photoUrl | null; +}; + +export type GetFoo_superUser_groupFromAlias_managers_fooUser = { + __typename: 'User'; + profilePhoto: GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto | null; +}; + +export type GetFoo_superUser_groupFromAlias_managers = { + __typename: 'UserManager'; + roleType: Types.UserManagerRoleType; + fooUser: GetFoo_superUser_groupFromAlias_managers_fooUser; +}; + +export type GetFoo_superUser_groupFromAlias = { + __typename: 'SuperUserGroup'; + managers: Array | null; +}; + +export type GetFoo_superUser = { + __typename: 'SuperUser'; + groupFromAlias: GetFoo_superUser_groupFromAlias; +}; + +export type GetFoo = { + superUser: GetFoo_superUser; +}; + +export type GetFooVariables = Exact<{ + alias: string; + collectionId: string; +}>; diff --git a/dev-test-apollo-tooling/src/__generated__/Duplicates.ts b/dev-test-apollo-tooling/src/__generated__/Duplicates.ts new file mode 100644 index 00000000000..48cecf574a6 --- /dev/null +++ b/dev-test-apollo-tooling/src/__generated__/Duplicates.ts @@ -0,0 +1,163 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +import type * as Types from '../unused'; + +type Exact = { [K in keyof T]: T[K] }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export enum ProcessableFeedbackSortBy { + OPTION_1 = 'OPTION_1', + OPTION_2 = 'OPTION_2', + OPTION_3 = 'OPTION_3', + OPTION_4 = 'OPTION_4', +} + +export enum ProcessableFeedbackSortOrder { + ASC = 'ASC', + DESC = 'DESC', +} + +export type ConfigTypeDefinitions_ConfigActionId = { + __typename: 'ConfigActionId'; + identifier: string; +}; + +export type ConfigTypeDefinitions_ConfigEnum = { + __typename: 'ConfigEnum'; + identifier: string; + values: Array; +}; + +export type ConfigTypeDefinitions_ConfigIconResource = { + __typename: 'ConfigIconResource'; +}; + +export type ConfigTypeDefinitions_ConfigIllustrationResource = { + __typename: 'ConfigIllustrationResource'; +}; + +export type ConfigTypeDefinitions_ConfigString = { + __typename: 'ConfigString'; + identifier: string; + supportedHtmlTags: Array | null; +}; + +export type ConfigTypeDefinitions_ConfigStruct = { + __typename: 'ConfigStruct'; +}; + +export type ConfigTypeDefinitions = + | ConfigTypeDefinitions_ConfigActionId + | ConfigTypeDefinitions_ConfigEnum + | ConfigTypeDefinitions_ConfigIconResource + | ConfigTypeDefinitions_ConfigIllustrationResource + | ConfigTypeDefinitions_ConfigString + | ConfigTypeDefinitions_ConfigStruct; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar_imageUrl = + { + __typename: 'EndUserImageUrl'; + url: string | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar = + { + __typename: 'EndUserAvatar'; + imageUrl: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar_imageUrl | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar_imageUrl = + { + __typename: 'OrgMemberImageUrl'; + url: string | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar = + { + __typename: 'OrgMemberAvatar'; + imageUrl: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar_imageUrl | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser = + { + __typename: 'EndUser'; + id: string; + fullName: string | null; + avatar: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember = + { + __typename: 'OrgMember'; + id: string; + fullName: string | null; + avatar: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator = + + | GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser + | GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node = + { + __typename: 'ThreadPost'; + creator: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges = { + __typename: 'ThreadPostEdge'; + node: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts = { + __typename: 'ThreadPostConnection'; + edges: Array | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread = { + __typename: 'Thread'; + id: string; + posts: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node = { + __typename: 'Feedback'; + id: string; + orgMemberThread: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges = { + __typename: 'FeedbackEdge'; + node: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback = { + __typename: 'FeedbackConnection'; + edges: Array | null; +}; + +export type GetFeedbackData_organization_internalOrgData = { + __typename: 'InternalOrgData'; + processableFeedback: GetFeedbackData_organization_internalOrgData_processableFeedback | null; +}; + +export type GetFeedbackData_organization = { + __typename: 'Organization'; + internalOrgData: GetFeedbackData_organization_internalOrgData | null; +}; + +export type GetFeedbackData = { + organization: GetFeedbackData_organization | null; +}; + +export type GetFeedbackDataVariables = Exact<{ + organizationId: string; + first?: number | null | undefined; + after?: string | null | undefined; + scoreFilter?: Array | number | null | undefined; + sortBy?: Types.ProcessableFeedbackSortBy | null | undefined; + sortOrder?: Types.ProcessableFeedbackSortOrder | null | undefined; +}>; diff --git a/dev-test-apollo-tooling/src/__generated__/Helper.ts b/dev-test-apollo-tooling/src/__generated__/Helper.ts new file mode 100644 index 00000000000..96087fb8869 --- /dev/null +++ b/dev-test-apollo-tooling/src/__generated__/Helper.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +import type * as Types from '../unused'; + +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export enum UserManagerRoleType { + ROLE_TYPE_1 = 'ROLE_TYPE_1', + ROLE_TYPE_2 = 'ROLE_TYPE_2', + ROLE_TYPE_3 = 'ROLE_TYPE_3', +} + +export type HelperFields_fooUser_profilePhoto_photoUrl = { + __typename: 'UserPhotoUrl'; + url: string | null; +}; + +export type HelperFields_fooUser_profilePhoto = { + __typename: 'UserProfilePhoto'; + photoUrl: HelperFields_fooUser_profilePhoto_photoUrl | null; +}; + +export type HelperFields_fooUser = { + __typename: 'User'; + profilePhoto: HelperFields_fooUser_profilePhoto | null; +}; + +export type HelperFields = { + __typename: 'UserManager'; + roleType: Types.UserManagerRoleType; + fooUser: HelperFields_fooUser; +}; diff --git a/dev-test-apollo-tooling/tests/Component.test.ts b/dev-test-apollo-tooling/tests/Component.test.ts new file mode 100644 index 00000000000..2ce5f6fa4c2 --- /dev/null +++ b/dev-test-apollo-tooling/tests/Component.test.ts @@ -0,0 +1,20 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('Component.ts', () => { + it('UserManagerRoleType enum should be exported', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Component.ts'), 'utf-8'); + + expect(fileContent).toMatch(/export enum UserManagerRoleType/); + }); + + it('UserManagerRoleType should be referenced without any prefix', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Component.ts'), 'utf-8'); + + expect(fileContent).toMatch(/roleType:\s*UserManagerRoleType;/); + }); +}); diff --git a/dev-test-apollo-tooling/tests/Duplicates.test.ts b/dev-test-apollo-tooling/tests/Duplicates.test.ts new file mode 100644 index 00000000000..9a7843a2e64 --- /dev/null +++ b/dev-test-apollo-tooling/tests/Duplicates.test.ts @@ -0,0 +1,31 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('Duplicates.ts', () => { + it('ConfigTypeDefinitions types should be exported', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Duplicates.ts'), 'utf-8'); + + expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigActionId\s*=/); + expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigEnum\s*=/); + expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigIconResource\s*=/); + expect(fileContent).toMatch(/export type ConfigTypeDefinitions\s*=/); + }); + + it('GetFeedbackData creator union type exports should exist', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Duplicates.ts'), 'utf-8'); + + expect(fileContent).toMatch( + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator\s*=/ + ); + expect(fileContent).toMatch( + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser\s*=/ + ); + expect(fileContent).toMatch( + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember\s*=/ + ); + }); +}); diff --git a/dev-test-apollo-tooling/tsconfig.json b/dev-test-apollo-tooling/tsconfig.json new file mode 100644 index 00000000000..39e2b63b53d --- /dev/null +++ b/dev-test-apollo-tooling/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "verbatimModuleSyntax": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "strict": true + } +} diff --git a/dev-test-apollo-tooling/vitest.config.ts b/dev-test-apollo-tooling/vitest.config.ts new file mode 100644 index 00000000000..b0ef9b2bc35 --- /dev/null +++ b/dev-test-apollo-tooling/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineProject, mergeConfig } from 'vitest/config'; +import { sharedConfig } from '../vitest.config.js'; + +export default mergeConfig( + sharedConfig, + defineProject({ + test: { + name: 'dev-test-apollo-tooling', + include: ['tests/**/*.spec.ts', 'tests/**/*.test.ts'], + }, + }) +); diff --git a/package.json b/package.json index 6aecdba989f..529ccb88301 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "packages/plugins/other/*", "packages/presets/*", "website", - "examples/**/*" + "examples/**/*", + "dev-test-apollo-tooling" ], "devDependencies": { "@babel/core": "7.25.2", @@ -78,6 +79,7 @@ "**/*.{js,jsx,cjs,mjs,ts,tsx,graphql,gql,yml,yaml,json,md}": [ "prettier --write" ], + "**/__generated__/**": [], "yarn.lock": [ "npx yarn-deduplicate" ] diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 77555e81019..be86cd0e84c 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -90,6 +90,10 @@ export class SelectionSetToObject< protected _primitiveAliasedFields: PrimitiveAliasedFields[] = []; protected _linksFields: LinkField[] = []; protected _queriedForTypename = false; + // Enables resolving conflics in extractAllFieldsToTypesCompact mode: + // key === GetFoo_user <-- full field name + // value === User <-- last field type + protected _seenFieldNames: Map = new Map(); constructor( protected _processor: BaseSelectionSetProcessor, @@ -106,7 +110,7 @@ export class SelectionSetToObject< } public createNext(parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode): SelectionSetToObject { - return new SelectionSetToObject( + const next = new SelectionSetToObject( this._processor, this._scalars, this._schema, @@ -117,6 +121,8 @@ export class SelectionSetToObject< parentSchemaType, selectionSet ); + next._seenFieldNames = this._seenFieldNames; + return next; } /** @@ -896,9 +902,15 @@ export class SelectionSetToObject< const mergedTypeString = this.buildFragmentTypeName(fragmentName, fragmentSuffix); const { grouped, dependentTypes } = this._buildGroupedSelections(mergedTypeString); + const hasMultipleTypes = Object.keys(grouped).length > 1; + const subTypes: DependentType[] = Object.keys(grouped).flatMap(typeName => { const possibleFields = grouped[typeName].filter(Boolean); - const declarationName = this.buildFragmentTypeName(fragmentName, fragmentSuffix, typeName); + // In compact mode, pass typeName only when there are multiple types + const declarationName = + this._config.extractAllFieldsToTypesCompact && !hasMultipleTypes + ? this.buildFragmentTypeName(fragmentName, fragmentSuffix) + : this.buildFragmentTypeName(fragmentName, fragmentSuffix, typeName); if (possibleFields.length === 0) { return []; @@ -969,14 +981,7 @@ export class SelectionSetToObject< } protected buildFragmentTypeName(name: string, suffix: string, typeName = ''): string { - // In compact mode, omit typeName from fragment type names - let fragmentSuffix: string; - if (this._config.extractAllFieldsToTypesCompact) { - fragmentSuffix = suffix; - } else { - fragmentSuffix = typeName && suffix ? `_${typeName}_${suffix}` : typeName ? `_${typeName}` : suffix; - } - + const fragmentSuffix = typeName && suffix ? `_${typeName}_${suffix}` : typeName ? `_${typeName}` : suffix; return this._convertName(name, { useTypesPrefix: true, suffix: fragmentSuffix, @@ -984,14 +989,31 @@ export class SelectionSetToObject< } protected buildParentFieldName(typeName: string, parentName: string): string { + // Sample input: + // typeName = User <-- last field type + // parentName = GetFoo_user <-- full field name + // queries/mutations/fragments are guaranteed to be unique type names, // so we can skip affixing the field names with typeName if (operationTypes.includes(typeName)) { return parentName; } - // When compact mode is enabled, skip appending typeName + // When compact mode is enabled, skip appending typeName initially + // but check for conflicts if (this._config.extractAllFieldsToTypesCompact) { + const existingTypeName = this._seenFieldNames.get(parentName); + if (!existingTypeName) { + // First time seeing this field name, record it's type + this._seenFieldNames.set(parentName, typeName); + return parentName; + } + if (existingTypeName !== typeName) { + // Conflict detected: same field name but different type + // Return field name with type suffix + return `${parentName}_${typeName}`; + } + // Same field name and same type, just return the plain name return parentName; } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 64ef7954336..d5f7c6e1437 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -123,7 +123,16 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ...(config.externalFragments || []), ]; - this._usedNamedInputTypes = this.collectUsedInputTypes({ schema, documentNode }); + // Create a combined document that includes operations, internal and external fragments for enum collection + const documentWithAllFragments: DocumentNode = { + ...documentNode, + definitions: [ + ...documentNode.definitions.filter(d => d.kind !== Kind.FRAGMENT_DEFINITION), + ...allFragments.map(f => f.node), + ], + }; + + this._usedNamedInputTypes = this.collectUsedInputTypes({ schema, documentNode: documentWithAllFragments }); const processorConfig: SelectionSetProcessorConfig = { namespacedImportName: this.config.namespacedImportName, diff --git a/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts new file mode 100644 index 00000000000..03daec54d3d --- /dev/null +++ b/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts @@ -0,0 +1,339 @@ +import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin, type TypeScriptDocumentsPluginConfig } from '../src/index.js'; + +describe('extractAllFieldsToTypesCompact: duplicate type names', () => { + const validate = async (content: Types.PluginOutput) => { + const m = mergeOutputs([content]); + validateTs(m, undefined, undefined, undefined, []); + + return m; + }; + + it('should add type suffix to disambiguate duplicate fragment type names in union types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + typeDefinitions: [TypeDefinition!]! + } + + interface TypeDefinition { + identifier: String! + } + + type StringType implements TypeDefinition { + identifier: String! + } + + type IntType implements TypeDefinition { + identifier: String! + min: Int + max: Int + } + + type ArrayType implements TypeDefinition { + identifier: String! + elementTypeId: String! + } + + type BooleanType implements TypeDefinition { + identifier: String! + } + `); + + const document = parse(/* GraphQL */ ` + fragment TypeDefinitions on TypeDefinition { + __typename + ... on StringType { + identifier + } + ... on IntType { + identifier + min + max + } + ... on ArrayType { + identifier + elementTypeId + } + ... on BooleanType { + identifier + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // Should generate unique type names with type suffixes + expect(content).toContain('type TypeDefinitions_StringType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_IntType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_ArrayType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_BooleanType_Fragment = {'); + + // Should generate a union type referencing the unique names + expect(content).toContain('export type TypeDefinitionsFragment ='); + expect(content).toContain('| TypeDefinitions_StringType_Fragment'); + expect(content).toContain('| TypeDefinitions_IntType_Fragment'); + expect(content).toContain('| TypeDefinitions_ArrayType_Fragment'); + expect(content).toContain('| TypeDefinitions_BooleanType_Fragment'); + + // Should NOT have duplicate type declarations with the same name + const typeDeclarationRegex = /type TypeDefinitions_StringType_Fragment = \{/g; + const matches = content.match(typeDeclarationRegex); + expect(matches).toHaveLength(1); // Should appear exactly once + }); + + it('should handle nested fields with parameters in union fragments', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + typeDefinitions: [TypeDefinition!]! + } + + interface TypeDefinition { + identifier: String! + } + + type Parameter { + name: String! + } + + type StructType implements TypeDefinition { + identifier: String! + parameters: [Parameter!]! + } + + type FunctionType implements TypeDefinition { + identifier: String! + parameters: [Parameter!]! + } + `); + + const document = parse(/* GraphQL */ ` + fragment ParameterDetails on Parameter { + __typename + } + + fragment TypeDefinitions on TypeDefinition { + __typename + ... on StructType { + identifier + parameters { + ...ParameterDetails + } + } + ... on FunctionType { + identifier + parameters { + ...ParameterDetails + } + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // Should generate unique names for the main types + expect(content).toContain('type TypeDefinitions_StructType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_FunctionType_Fragment = {'); + + // Should generate a union type + expect(content).toContain('export type TypeDefinitionsFragment ='); + expect(content).toContain('| TypeDefinitions_StructType_Fragment'); + expect(content).toContain('| TypeDefinitions_FunctionType_Fragment'); + + // Verify there are no duplicate type declarations + const structTypeRegex = /type TypeDefinitions_StructType_Fragment = \{/g; + const structMatches = content.match(structTypeRegex); + expect(structMatches).toHaveLength(1); + + const functionTypeRegex = /type TypeDefinitions_FunctionType_Fragment = \{/g; + const functionMatches = content.match(functionTypeRegex); + expect(functionMatches).toHaveLength(1); + }); + + it('should not add type suffix when there is only one inline fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + interface User { + id: ID! + } + + type PremiumUser implements User { + id: ID! + isPremium: Boolean! + } + `); + + const document = parse(/* GraphQL */ ` + fragment UserFragment on User { + __typename + ... on PremiumUser { + id + isPremium + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // With only one inline fragment, should use the base name without type suffix + expect(content).toContain('export type UserFragmentFragment = {'); + expect(content).not.toContain('UserFragment_PremiumUser_Fragment'); + }); + + it('should handle complex union with many types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + shapes: [Shape!]! + } + + interface Shape { + id: ID! + } + + type Circle implements Shape { + id: ID! + radius: Float! + } + + type Rectangle implements Shape { + id: ID! + width: Float! + height: Float! + } + + type Triangle implements Shape { + id: ID! + base: Float! + height: Float! + } + + type Square implements Shape { + id: ID! + side: Float! + } + + type Polygon implements Shape { + id: ID! + sides: Int! + vertices: [Float!]! + } + + type Ellipse implements Shape { + id: ID! + majorAxis: Float! + minorAxis: Float! + } + + type Pentagon implements Shape { + id: ID! + side: Float! + } + `); + + const document = parse(/* GraphQL */ ` + fragment ShapeDetails on Shape { + __typename + ... on Circle { + id + radius + } + ... on Rectangle { + id + width + height + } + ... on Triangle { + id + base + height + } + ... on Square { + id + side + } + ... on Polygon { + id + sides + vertices + } + ... on Ellipse { + id + majorAxis + minorAxis + } + ... on Pentagon { + id + side + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // Verify all unique type names exist + expect(content).toContain('type ShapeDetails_Circle_Fragment'); + expect(content).toContain('type ShapeDetails_Rectangle_Fragment'); + expect(content).toContain('type ShapeDetails_Triangle_Fragment'); + expect(content).toContain('type ShapeDetails_Square_Fragment'); + expect(content).toContain('type ShapeDetails_Polygon_Fragment'); + expect(content).toContain('type ShapeDetails_Ellipse_Fragment'); + expect(content).toContain('type ShapeDetails_Pentagon_Fragment'); + + // Verify union type exists + expect(content).toContain('export type ShapeDetailsFragment ='); + + // Verify all types are in the union + expect(content).toContain('| ShapeDetails_Circle_Fragment'); + expect(content).toContain('| ShapeDetails_Rectangle_Fragment'); + expect(content).toContain('| ShapeDetails_Triangle_Fragment'); + expect(content).toContain('| ShapeDetails_Square_Fragment'); + expect(content).toContain('| ShapeDetails_Polygon_Fragment'); + expect(content).toContain('| ShapeDetails_Ellipse_Fragment'); + expect(content).toContain('| ShapeDetails_Pentagon_Fragment'); + + // Verify there are no duplicate type declarations + const circleTypeRegex = /type ShapeDetails_Circle_Fragment = \{/g; + const circleMatches = content.match(circleTypeRegex); + expect(circleMatches).toHaveLength(1); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts new file mode 100644 index 00000000000..d1296b56719 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts @@ -0,0 +1,479 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - External Fragments with Enums', () => { + it('should include enum in document when enum is used in external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + name: String! + role: UserRole! + profile: UserProfile! + } + + type UserProfile { + bio: String! + } + + enum UserRole { + ADMIN + CUSTOMER + GUEST + } + `); + + // Fragment defined separately (external fragment) + const fragmentDocument = parse(/* GraphQL */ ` + fragment UserFields on User { + role + profile { + bio + } + } + `); + + // Query that uses the external fragment + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + id + ...UserFields + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: fragmentDef, + name: 'UserFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included in the output + expect(result).toContain('export enum UserRole'); + expect(result).toContain("Admin = 'ADMIN'"); + expect(result).toContain("Customer = 'CUSTOMER'"); + expect(result).toContain("Guest = 'GUEST'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should include enum in document when enum is nested deeply in external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + organization: Organization + } + + type Organization { + id: ID! + users: [User!]! + } + + type User { + id: ID! + manager: Manager! + } + + type Manager { + id: ID! + roleType: ManagerRole! + } + + enum ManagerRole { + SENIOR + JUNIOR + LEAD + } + `); + + const fragmentDocument = parse(/* GraphQL */ ` + fragment ManagerFields on User { + manager { + id + roleType + } + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetOrganization { + organization { + id + users { + id + ...ManagerFields + } + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: fragmentDef, + name: 'ManagerFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included even though it's nested deeply + expect(result).toContain('export enum ManagerRole'); + expect(result).toContain("Senior = 'SENIOR'"); + expect(result).toContain("Junior = 'JUNIOR'"); + expect(result).toContain("Lead = 'LEAD'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should include multiple enums from multiple external fragments', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + role: UserRole! + status: UserStatus! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + enum UserStatus { + ACTIVE + INACTIVE + } + `); + + const roleFragmentDocument = parse(/* GraphQL */ ` + fragment RoleFields on User { + role + } + `); + + const statusFragmentDocument = parse(/* GraphQL */ ` + fragment StatusFields on User { + status + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + id + ...RoleFields + ...StatusFields + } + } + `); + + const roleFragmentDef = roleFragmentDocument.definitions[0]; + const statusFragmentDef = statusFragmentDocument.definitions[0]; + + if (roleFragmentDef.kind !== 'FragmentDefinition' || statusFragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definitions'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: roleFragmentDef, + name: 'RoleFields', + onType: 'User', + isExternal: true, + }, + { + node: statusFragmentDef, + name: 'StatusFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // Both enums should be included + expect(result).toContain('export enum UserRole'); + expect(result).toContain("Admin = 'ADMIN'"); + expect(result).toContain("Customer = 'CUSTOMER'"); + + expect(result).toContain('export enum UserStatus'); + expect(result).toContain("Active = 'ACTIVE'"); + expect(result).toContain("Inactive = 'INACTIVE'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should not duplicate enum if it appears in both query and external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + admin: User + } + + type User { + id: ID! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + + const fragmentDocument = parse(/* GraphQL */ ` + fragment UserFields on User { + role + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUsers { + user { + id + ...UserFields + } + admin { + id + role + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: fragmentDef, + name: 'UserFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should appear only once + const enumMatches = result.match(/export enum UserRole/g); + expect(enumMatches).toHaveLength(1); + + expect(result).toContain('export enum UserRole'); + expect(result).toContain("Admin = 'ADMIN'"); + expect(result).toContain("Customer = 'CUSTOMER'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should handle external fragment with nested fragment spread containing enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + profile: UserProfile! + } + + type UserProfile { + id: ID! + visibility: Visibility! + } + + enum Visibility { + PUBLIC + PRIVATE + FRIENDS_ONLY + } + `); + + const profileFragmentDocument = parse(/* GraphQL */ ` + fragment ProfileVisibility on UserProfile { + visibility + } + `); + + const userFragmentDocument = parse(/* GraphQL */ ` + fragment UserWithProfile on User { + id + profile { + ...ProfileVisibility + } + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + ...UserWithProfile + } + } + `); + + const profileFragmentDef = profileFragmentDocument.definitions[0]; + const userFragmentDef = userFragmentDocument.definitions[0]; + + if (profileFragmentDef.kind !== 'FragmentDefinition' || userFragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definitions'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: profileFragmentDef, + name: 'ProfileVisibility', + onType: 'UserProfile', + isExternal: true, + }, + { + node: userFragmentDef, + name: 'UserWithProfile', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included even with nested fragment spreads + expect(result).toContain('export enum Visibility'); + expect(result).toContain("Public = 'PUBLIC'"); + expect(result).toContain("Private = 'PRIVATE'"); + expect(result).toContain("FriendsOnly = 'FRIENDS_ONLY'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should include enum with const enum type from external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + + const fragmentDocument = parse(/* GraphQL */ ` + fragment UserFields on User { + role + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + id + ...UserFields + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'const', + externalFragments: [ + { + node: fragmentDef, + name: 'UserFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included as const object + expect(result).toContain('export const UserRole = {'); + expect(result).toContain("Admin: 'ADMIN'"); + expect(result).toContain("Customer: 'CUSTOMER'"); + expect(result).toContain('} as const;'); + expect(result).toContain('export type UserRole = typeof UserRole[keyof typeof UserRole];'); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch b/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch new file mode 100644 index 00000000000..c57c897b7a5 --- /dev/null +++ b/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch @@ -0,0 +1,52 @@ +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js +index a0636cb..17ebece 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js +@@ -19,7 +19,7 @@ exports.preset = { + const fileName = options.presetConfig.fileName || ''; + const extension = options.presetConfig.extension || '.generated.ts'; + const folder = options.presetConfig.folder || ''; +- const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; ++ const importTypesNamespace = options.presetConfig.importTypesNamespace ?? 'Types'; + const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null; + const { baseTypesPath } = options.presetConfig; + if (!baseTypesPath) { +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js +index f8dae4c..50fde90 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js +@@ -24,7 +24,7 @@ function resolveDocumentImports(presetOptions, schemaObject, importResolverOptio + ...documentFile.document, + definitions: [...documentFile.document.definitions, ...externalFragments.map(fragment => fragment.node)], + }; +- if ((0, plugin_helpers_1.isUsingTypes)(externalFragmentsInjectedDocument, [], schemaObject)) { ++ if ((0, plugin_helpers_1.isUsingTypes)(externalFragmentsInjectedDocument, [], schemaObject) && schemaTypesSource.namespace) { + const schemaTypesImportStatement = (0, visitor_plugin_common_1.generateImportStatement)({ + baseDir, + emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js b/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js +index 6c71580..4747c07 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js +@@ -15,7 +15,7 @@ export const preset = { + const fileName = options.presetConfig.fileName || ''; + const extension = options.presetConfig.extension || '.generated.ts'; + const folder = options.presetConfig.folder || ''; +- const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; ++ const importTypesNamespace = options.presetConfig.importTypesNamespace ?? 'Types'; + const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null; + const { baseTypesPath } = options.presetConfig; + if (!baseTypesPath) { +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js b/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js +index e8796cb..4332e0f 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js +@@ -20,7 +20,7 @@ export function resolveDocumentImports(presetOptions, schemaObject, importResolv + ...documentFile.document, + definitions: [...documentFile.document.definitions, ...externalFragments.map(fragment => fragment.node)], + }; +- if (isUsingTypes(externalFragmentsInjectedDocument, [], schemaObject)) { ++ if (isUsingTypes(externalFragmentsInjectedDocument, [], schemaObject) && schemaTypesSource.namespace) { + const schemaTypesImportStatement = generateImportStatement({ + baseDir, + emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, diff --git a/yarn.lock b/yarn.lock index 02e31acdfbc..186c0003dce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33,10 +33,10 @@ resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d" integrity sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww== -"@apollo/client@^3.7.10": - version "3.11.4" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.11.4.tgz#8b0fed2d091d47597e8ddafca85776bf612ae3aa" - integrity sha512-bmgYKkULpym8wt8aXlAZ1heaYo0skLJ5ru0qJ+JCRoo03Pe+yIDbBCnqlDw6Mjj76hFkDw3HwFMgZC2Hxp30Mg== +"@apollo/client@3.13.8", "@apollo/client@^3.7.10": + version "3.13.8" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.13.8.tgz#ef1d49a5b134c69a55e3f137164a8e323aef4e2a" + integrity sha512-YM9lQpm0VfVco4DSyKooHS/fDTiKQcCHfxr7i3iL6a0kP/jNO5+4NFK6vtRDxaYisd5BrwOZHLJpPBnvRVpKPg== dependencies: "@graphql-typed-document-node/core" "^3.1.1" "@wry/caches" "^1.0.0" @@ -47,7 +47,6 @@ optimism "^0.18.0" prop-types "^15.7.2" rehackt "^0.1.0" - response-iterator "^0.2.6" symbol-observable "^4.0.0" ts-invariant "^0.10.3" tslib "^2.3.0" @@ -1750,6 +1749,11 @@ resolved "https://registry.yarnpkg.com/@epic-web/invariant/-/invariant-1.0.0.tgz#1073e5dee6dd540410784990eb73e4acd25c9813" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== +"@esbuild/aix-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" + integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== + "@esbuild/aix-ppc64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353" @@ -1760,6 +1764,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== +"@esbuild/android-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" + integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== + "@esbuild/android-arm64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018" @@ -1770,6 +1779,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== +"@esbuild/android-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" + integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== + "@esbuild/android-arm@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee" @@ -1780,6 +1794,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== +"@esbuild/android-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" + integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== + "@esbuild/android-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517" @@ -1790,6 +1809,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== +"@esbuild/darwin-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" + integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== + "@esbuild/darwin-arm64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16" @@ -1800,6 +1824,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== +"@esbuild/darwin-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" + integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== + "@esbuild/darwin-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931" @@ -1810,6 +1839,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== +"@esbuild/freebsd-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" + integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== + "@esbuild/freebsd-arm64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc" @@ -1820,6 +1854,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== +"@esbuild/freebsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" + integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== + "@esbuild/freebsd-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730" @@ -1830,6 +1869,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== +"@esbuild/linux-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" + integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== + "@esbuild/linux-arm64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383" @@ -1840,6 +1884,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== +"@esbuild/linux-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" + integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== + "@esbuild/linux-arm@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771" @@ -1850,6 +1899,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== +"@esbuild/linux-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" + integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== + "@esbuild/linux-ia32@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333" @@ -1860,6 +1914,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== +"@esbuild/linux-loong64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" + integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== + "@esbuild/linux-loong64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac" @@ -1870,6 +1929,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== +"@esbuild/linux-mips64el@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" + integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== + "@esbuild/linux-mips64el@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6" @@ -1880,6 +1944,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== +"@esbuild/linux-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" + integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== + "@esbuild/linux-ppc64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96" @@ -1890,6 +1959,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== +"@esbuild/linux-riscv64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" + integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== + "@esbuild/linux-riscv64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7" @@ -1900,6 +1974,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== +"@esbuild/linux-s390x@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" + integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== + "@esbuild/linux-s390x@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f" @@ -1910,6 +1989,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== +"@esbuild/linux-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" + integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== + "@esbuild/linux-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24" @@ -1925,6 +2009,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== +"@esbuild/netbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" + integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== + "@esbuild/netbsd-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653" @@ -1945,6 +2034,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== +"@esbuild/openbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" + integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== + "@esbuild/openbsd-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273" @@ -1955,6 +2049,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== +"@esbuild/sunos-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" + integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== + "@esbuild/sunos-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403" @@ -1965,6 +2064,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== +"@esbuild/win32-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" + integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== + "@esbuild/win32-arm64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2" @@ -1975,6 +2079,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== +"@esbuild/win32-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" + integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== + "@esbuild/win32-ia32@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac" @@ -1985,6 +2094,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== +"@esbuild/win32-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" + integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== + "@esbuild/win32-x64@0.23.1": version "0.23.1" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699" @@ -4801,7 +4915,14 @@ dependencies: "@types/unist" "*" -"@types/node@*", "@types/node@22.10.7", "@types/node@^22.0.0": +"@types/node@*", "@types/node@^25.0.3": + version "25.0.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.9.tgz#81ce3579ddf67cae812a9d49c8a0ab90c82e7782" + integrity sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw== + dependencies: + undici-types "~7.16.0" + +"@types/node@22.10.7", "@types/node@^22.0.0": version "22.10.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.7.tgz#14a1ca33fd0ebdd9d63593ed8d3fbc882a6d28d7" integrity sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg== @@ -4895,16 +5016,16 @@ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== -"@types/unist@*", "@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" - integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== - -"@types/unist@^3.0.0": +"@types/unist@*", "@types/unist@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.0.tgz#988ae8af1e5239e89f9fbb1ade4c935f4eeedf9a" integrity sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + "@types/ws@^8.0.0": version "8.5.4" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" @@ -7674,6 +7795,35 @@ esbuild@^0.23.0, esbuild@~0.23.0: "@esbuild/win32-ia32" "0.23.1" "@esbuild/win32-x64" "0.23.1" +esbuild@~0.19.10: + version "0.19.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" + integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.19.12" + "@esbuild/android-arm" "0.19.12" + "@esbuild/android-arm64" "0.19.12" + "@esbuild/android-x64" "0.19.12" + "@esbuild/darwin-arm64" "0.19.12" + "@esbuild/darwin-x64" "0.19.12" + "@esbuild/freebsd-arm64" "0.19.12" + "@esbuild/freebsd-x64" "0.19.12" + "@esbuild/linux-arm" "0.19.12" + "@esbuild/linux-arm64" "0.19.12" + "@esbuild/linux-ia32" "0.19.12" + "@esbuild/linux-loong64" "0.19.12" + "@esbuild/linux-mips64el" "0.19.12" + "@esbuild/linux-ppc64" "0.19.12" + "@esbuild/linux-riscv64" "0.19.12" + "@esbuild/linux-s390x" "0.19.12" + "@esbuild/linux-x64" "0.19.12" + "@esbuild/netbsd-x64" "0.19.12" + "@esbuild/openbsd-x64" "0.19.12" + "@esbuild/sunos-x64" "0.19.12" + "@esbuild/win32-arm64" "0.19.12" + "@esbuild/win32-ia32" "0.19.12" + "@esbuild/win32-x64" "0.19.12" + escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -8760,10 +8910,10 @@ get-symbol-description@^1.1.0: es-errors "^1.3.0" get-intrinsic "^1.2.6" -get-tsconfig@^4.10.0, get-tsconfig@^4.7.5, get-tsconfig@^4.8.1: - version "4.10.1" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" - integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== +get-tsconfig@^4.10.0, get-tsconfig@^4.7.2, get-tsconfig@^4.7.5, get-tsconfig@^4.8.1: + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== dependencies: resolve-pkg-maps "^1.0.0" @@ -14564,6 +14714,16 @@ tsx@4.17.0: optionalDependencies: fsevents "~2.3.3" +tsx@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.7.0.tgz#1689cfe7dda495ca1f9a66d4cad79cb57b9f6f4a" + integrity sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg== + dependencies: + esbuild "~0.19.10" + get-tsconfig "^4.7.2" + optionalDependencies: + fsevents "~2.3.3" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -14692,7 +14852,7 @@ typescript-json-schema@0.56.0: typescript "~4.9.5" yargs "^17.1.1" -typescript@5.5.4, typescript@^5, typescript@^5.0.0, typescript@~4.9.5: +typescript@5.5.4, typescript@^5, typescript@^5.0.0, typescript@^5.9.3, typescript@~4.9.5: version "5.5.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== @@ -14732,6 +14892,11 @@ undici-types@~6.20.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + undici@^5.28.5: version "5.28.5" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.5.tgz#b2b94b6bf8f1d919bc5a6f31f2c01deb02e54d4b"