@@ -1494,3 +1494,226 @@ describe('extractAllFieldsToTypes: true', () => {
14941494 await validate ( content ) ;
14951495 } ) ;
14961496} ) ;
1497+
1498+ describe ( 'extractAllFieldsToTypesCompact: true' , ( ) => {
1499+ const validate = async ( content : Types . PluginOutput ) => {
1500+ const m = mergeOutputs ( [ content ] ) ;
1501+ validateTs ( m , undefined , undefined , undefined , [ ] ) ;
1502+
1503+ return m ;
1504+ } ;
1505+
1506+ const companySchema = buildSchema ( /* GraphQL */ `
1507+ type Query {
1508+ company(id: ID!): Company
1509+ }
1510+ type Company {
1511+ id: ID!
1512+ name: String!
1513+ score: Float
1514+ reviewCount: Int
1515+ office: Office
1516+ }
1517+ type Office {
1518+ id: ID!
1519+ location: Location
1520+ }
1521+ type Location {
1522+ formatted: String
1523+ }
1524+ ` ) ;
1525+
1526+ const companyDoc = parse ( /* GraphQL */ `
1527+ query GetCompanyInfo($id: ID!) {
1528+ company(id: $id) {
1529+ id
1530+ name
1531+ score
1532+ reviewCount
1533+ office {
1534+ id
1535+ location {
1536+ formatted
1537+ }
1538+ }
1539+ }
1540+ }
1541+ ` ) ;
1542+
1543+ it ( 'should generate compact type names without GraphQL type names (Apollo Tooling style)' , async ( ) => {
1544+ const config : TypeScriptDocumentsPluginConfig = {
1545+ extractAllFieldsToTypesCompact : true ,
1546+ nonOptionalTypename : true ,
1547+ omitOperationSuffix : true ,
1548+ } ;
1549+ const { content } = await plugin ( companySchema , [ { location : 'test-file.ts' , document : companyDoc } ] , config , {
1550+ outputFile : '' ,
1551+ } ) ;
1552+ expect ( content ) . toMatchInlineSnapshot ( `
1553+ "export type GetCompanyInfo_company_office_location = { __typename: 'Location', formatted: string | null };
1554+
1555+ export type GetCompanyInfo_company_office = { __typename: 'Office', id: string, location: GetCompanyInfo_company_office_location | null };
1556+
1557+ export type GetCompanyInfo_company = { __typename: 'Company', id: string, name: string, score: number | null, reviewCount: number | null, office: GetCompanyInfo_company_office | null };
1558+
1559+ export type GetCompanyInfo = { __typename: 'Query', company: GetCompanyInfo_company | null };
1560+
1561+
1562+ export type GetCompanyInfoVariables = Exact<{
1563+ id: string;
1564+ }>;
1565+ "
1566+ ` ) ;
1567+
1568+ await validate ( content ) ;
1569+ } ) ;
1570+
1571+ it ( 'should work with unions and interfaces in compact mode' , async ( ) => {
1572+ const schema = buildSchema ( /* GraphQL */ `
1573+ type Query {
1574+ animals: [Animal!]!
1575+ }
1576+ interface Animal {
1577+ name: String!
1578+ owner: Person!
1579+ }
1580+ type Cat implements Animal {
1581+ name: String!
1582+ owner: Person!
1583+ }
1584+ type Dog implements Animal {
1585+ name: String!
1586+ owner: Person!
1587+ }
1588+ union Person = Trainer | Veterinarian
1589+ type Trainer {
1590+ name: String!
1591+ }
1592+ type Veterinarian {
1593+ name: String!
1594+ }
1595+ ` ) ;
1596+
1597+ const doc = parse ( /* GraphQL */ `
1598+ query GetAnimals {
1599+ animals {
1600+ name
1601+ owner {
1602+ ... on Trainer {
1603+ name
1604+ }
1605+ ... on Veterinarian {
1606+ name
1607+ }
1608+ }
1609+ }
1610+ }
1611+ ` ) ;
1612+
1613+ const config : TypeScriptDocumentsPluginConfig = {
1614+ extractAllFieldsToTypesCompact : true ,
1615+ nonOptionalTypename : true ,
1616+ omitOperationSuffix : true ,
1617+ } ;
1618+ const { content } = await plugin ( schema , [ { location : 'test-file.ts' , document : doc } ] , config , { outputFile : '' } ) ;
1619+
1620+ // Verify the naming follows Apollo Tooling style (field names only, no intermediate type names)
1621+ expect ( content ) . toContain ( 'GetAnimals_animals_owner_Trainer' ) ;
1622+ expect ( content ) . toContain ( 'GetAnimals_animals_owner_Veterinarian' ) ;
1623+ expect ( content ) . toContain ( 'GetAnimals_animals_owner' ) ;
1624+ expect ( content ) . toContain ( 'GetAnimals_animals_Cat' ) ;
1625+ expect ( content ) . toContain ( 'GetAnimals_animals_Dog' ) ;
1626+ expect ( content ) . toContain ( 'GetAnimals_animals' ) ;
1627+
1628+ // Should NOT contain intermediate type names in the field paths (like Animal between animals and owner)
1629+ expect ( content ) . not . toContain ( 'GetAnimals_animals_Animal_owner' ) ;
1630+
1631+ await validate ( content ) ;
1632+ } ) ;
1633+
1634+ it ( 'should automatically enable extractAllFieldsToTypes when extractAllFieldsToTypesCompact is true' , async ( ) => {
1635+ const config : TypeScriptDocumentsPluginConfig = {
1636+ extractAllFieldsToTypes : false ,
1637+ extractAllFieldsToTypesCompact : true ,
1638+ nonOptionalTypename : true ,
1639+ omitOperationSuffix : true ,
1640+ } ;
1641+ const { content } = await plugin ( companySchema , [ { location : 'test-file.ts' , document : companyDoc } ] , config , {
1642+ outputFile : '' ,
1643+ } ) ;
1644+
1645+ // When extractAllFieldsToTypesCompact is true, extractAllFieldsToTypes should be automatically enabled
1646+ // So types should be extracted, not inlined
1647+ expect ( content ) . toContain ( 'GetCompanyInfo_company_office_location' ) ;
1648+ expect ( content ) . toContain ( 'GetCompanyInfo_company_office' ) ;
1649+ expect ( content ) . toContain ( 'GetCompanyInfo_company' ) ;
1650+ expect ( content ) . toContain ( 'export type GetCompanyInfo' ) ;
1651+
1652+ await validate ( content ) ;
1653+ } ) ;
1654+
1655+ it ( 'should apply compact naming to fragments' , async ( ) => {
1656+ const schema = buildSchema ( /* GraphQL */ `
1657+ type Query {
1658+ user(id: ID!): User
1659+ }
1660+ interface User {
1661+ id: ID!
1662+ profile: Profile
1663+ }
1664+ type AdminUser implements User {
1665+ id: ID!
1666+ profile: Profile
1667+ permissions: [String!]!
1668+ }
1669+ type RegularUser implements User {
1670+ id: ID!
1671+ profile: Profile
1672+ }
1673+ type Profile {
1674+ name: String!
1675+ contact: Contact
1676+ }
1677+ type Contact {
1678+ email: String
1679+ }
1680+ ` ) ;
1681+
1682+ const doc = parse ( /* GraphQL */ `
1683+ fragment UserProfile on User {
1684+ id
1685+ profile {
1686+ name
1687+ contact {
1688+ email
1689+ }
1690+ }
1691+ }
1692+ query GetUser($id: ID!) {
1693+ user(id: $id) {
1694+ ...UserProfile
1695+ ... on AdminUser {
1696+ permissions
1697+ }
1698+ }
1699+ }
1700+ ` ) ;
1701+
1702+ const config : TypeScriptDocumentsPluginConfig = {
1703+ extractAllFieldsToTypesCompact : true ,
1704+ nonOptionalTypename : true ,
1705+ omitOperationSuffix : true ,
1706+ } ;
1707+ const { content } = await plugin ( schema , [ { location : 'test-file.ts' , document : doc } ] , config , { outputFile : '' } ) ;
1708+
1709+ // Fragment types should use compact naming (no intermediate type names)
1710+ expect ( content ) . toContain ( 'UserProfile_profile_contact' ) ;
1711+ expect ( content ) . toContain ( 'UserProfile_profile' ) ;
1712+
1713+ // Should NOT contain type names in fragment paths
1714+ expect ( content ) . not . toContain ( 'UserProfile_profile_Profile_contact' ) ;
1715+ expect ( content ) . not . toContain ( 'UserProfile_profile_Profile_contact_Contact' ) ;
1716+
1717+ await validate ( content ) ;
1718+ } ) ;
1719+ } ) ;
0 commit comments