diff --git a/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-resolver-generator.ts b/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-resolver-generator.ts index 81597f7268..c3312c4334 100644 --- a/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-resolver-generator.ts +++ b/packages/amplify-graphql-conversation-transformer/src/transformer-steps/conversation-resolver-generator.ts @@ -1,6 +1,11 @@ import { conversation } from '@aws-amplify/ai-constructs'; import { overrideIndexAtCfnLevel } from '@aws-amplify/graphql-index-transformer'; -import { getModelDataSourceNameForTypeName, getTable, TransformerResolver } from '@aws-amplify/graphql-transformer-core'; +import { + getModelDataSourceNameForTypeName, + getGlobalSecondaryIndexes, + getTable, + TransformerResolver, +} from '@aws-amplify/graphql-transformer-core'; import { DataSourceProvider, TransformerContextProvider } from '@aws-amplify/graphql-transformer-interfaces'; import { BackendOutputEntry, BackendOutputStorageStrategy } from '@aws-amplify/plugin-types'; import * as cdk from 'aws-cdk-lib'; @@ -331,10 +336,7 @@ export class ConversationResolverGenerator { writeCapacity: cdk.Fn.ref(ResourceConstants.PARAMETERS.DynamoDBModelTableWriteIOPS), }); - // aws-cdk-lib 2.260 renamed the private `globalSecondaryIndexes` array on the DynamoDB L2 `Table` to - // `_globalSecondaryIndexes` (an `ArrayBox` exposing the same `find` surface and `{ indexName, keySchema }` - // element shape); Amplify's managed-table construct keeps the public `globalSecondaryIndexes` array. - const globalSecondaryIndexes = table['_globalSecondaryIndexes'] ?? table.globalSecondaryIndexes; + const globalSecondaryIndexes = getGlobalSecondaryIndexes(table); const gsi = globalSecondaryIndexes.find((g: any) => g.indexName === indexName); const newIndex = { diff --git a/packages/amplify-graphql-relational-transformer/src/resolvers.ts b/packages/amplify-graphql-relational-transformer/src/resolvers.ts index a29d4c9196..be908c2ce5 100644 --- a/packages/amplify-graphql-relational-transformer/src/resolvers.ts +++ b/packages/amplify-graphql-relational-transformer/src/resolvers.ts @@ -1,6 +1,6 @@ import { attributeTypeFromType, overrideIndexAtCfnLevel } from '@aws-amplify/graphql-index-transformer'; import { generateApplyDefaultsToInputTemplate } from '@aws-amplify/graphql-model-transformer'; -import { InvalidDirectiveError, MappingTemplate, getTable } from '@aws-amplify/graphql-transformer-core'; +import { InvalidDirectiveError, MappingTemplate, getGlobalSecondaryIndexes, getTable } from '@aws-amplify/graphql-transformer-core'; import { TransformerContextProvider, TransformerPrepareStepContextProvider, @@ -29,18 +29,6 @@ import { getSortKeyFields } from './schema'; import { HasManyDirectiveConfiguration, HasOneDirectiveConfiguration } from './types'; import { getConnectionAttributeName, getObjectPrimaryKey } from './utils'; -/** - * Reads the list of global secondary indexes tracked on a DynamoDB L2 `Table` construct. - * - * `aws-cdk-lib` 2.260 renamed the (private) `globalSecondaryIndexes` array to `_globalSecondaryIndexes` - * and now backs it with an `ArrayBox`, which still exposes the array-like `some`/`find`/`length` surface - * and the same element shape (`{ indexName, keySchema }`). Amplify's own managed-table construct - * (`AmplifyDynamoDBTable`) instead keeps its indexes on a public `globalSecondaryIndexes` array. Reading - * `_globalSecondaryIndexes` first and falling back to `globalSecondaryIndexes` works for both table types - * and preserves the duplicate-index-name detection rather than silently disabling it. - */ -const getGlobalSecondaryIndexes = (table: any): any => table['_globalSecondaryIndexes'] ?? table.globalSecondaryIndexes; - /** * Creates a GSI on the table of the `relatedType` based on the config's `references` / `referenceNodes` * diff --git a/packages/amplify-graphql-transformer-core/API.md b/packages/amplify-graphql-transformer-core/API.md index 9003af9f34..6f8087566c 100644 --- a/packages/amplify-graphql-transformer-core/API.md +++ b/packages/amplify-graphql-transformer-core/API.md @@ -250,6 +250,9 @@ export const getFieldNameFor: (op: Operation, typeName: string) => string; // @public (undocumented) export const getFilterInputName: (modelName: string) => string; +// @public (undocumented) +export const getGlobalSecondaryIndexes: (table: any) => any; + // @public (undocumented) export const getImportedRDSTypeFromStrategyDbType: (dbType: ModelDataSourceStrategyDbType) => ImportedRDSType; diff --git a/packages/amplify-graphql-transformer-core/src/index.ts b/packages/amplify-graphql-transformer-core/src/index.ts index 55912dcc30..252cc64c8f 100644 --- a/packages/amplify-graphql-transformer-core/src/index.ts +++ b/packages/amplify-graphql-transformer-core/src/index.ts @@ -39,6 +39,7 @@ export { getDefaultStrategyNameForDbType, getField, getFilterInputName, + getGlobalSecondaryIndexes, getImportedRDSTypeFromStrategyDbType, getKeySchema, getModelDataSourceNameForTypeName, diff --git a/packages/amplify-graphql-transformer-core/src/utils/index.ts b/packages/amplify-graphql-transformer-core/src/utils/index.ts index 7a23d67b90..cc98fad1a2 100644 --- a/packages/amplify-graphql-transformer-core/src/utils/index.ts +++ b/packages/amplify-graphql-transformer-core/src/utils/index.ts @@ -9,7 +9,7 @@ export { export { DirectiveWrapper, GetArgumentsOptions, generateGetArgumentsInput } from './directive-wrapper'; export { collectDirectives, collectDirectivesByTypeNames } from './type-map-utils'; export { stripDirectives } from './strip-directives'; -export { getTable, getKeySchema, getSortKeyFieldNames, getStrategyDbTypeFromTypeNode } from './schema-utils'; +export { getTable, getKeySchema, getGlobalSecondaryIndexes, getSortKeyFieldNames, getStrategyDbTypeFromTypeNode } from './schema-utils'; export { DEFAULT_SCHEMA_DEFINITION } from './defaultSchema'; export { constructArrayFieldsStatement, diff --git a/packages/amplify-graphql-transformer-core/src/utils/schema-utils.ts b/packages/amplify-graphql-transformer-core/src/utils/schema-utils.ts index 5d5259a687..7389fe3349 100644 --- a/packages/amplify-graphql-transformer-core/src/utils/schema-utils.ts +++ b/packages/amplify-graphql-transformer-core/src/utils/schema-utils.ts @@ -6,15 +6,26 @@ import { ListValueNode, ObjectTypeDefinitionNode, StringValueNode, TypeNode } fr import { ModelResourceIDs, getBaseType } from 'graphql-transformer-common'; import { getModelDataSourceStrategy } from './model-datasource-strategy-utils'; +/** + * Reads the list of global secondary indexes tracked on a DynamoDB L2 `Table` construct. + * + * aws-cdk-lib 2.260 renamed the private `globalSecondaryIndexes` array on the DynamoDB L2 `Table` to + * `_globalSecondaryIndexes` (now an `ArrayBox` exposing the same `find`/`some`/`length` surface and the + * same `{ indexName, keySchema }` element shape); Amplify's managed-table construct keeps the public + * `globalSecondaryIndexes` array. This reads whichever exists (covers standard `Table` + Amplify managed + * table). Centralized so a future CDK rename is a one-line fix. + */ +export const getGlobalSecondaryIndexes = (table: any): any => table['_globalSecondaryIndexes'] ?? table.globalSecondaryIndexes; + /** * getKeySchema */ export const getKeySchema = (table: any, indexName?: string): any => { - // aws-cdk-lib 2.260 renamed the private `globalSecondaryIndexes`/`localSecondaryIndexes` arrays on the - // DynamoDB L2 `Table` to `_globalSecondaryIndexes`/`_localSecondaryIndexes` (now `ArrayBox`es exposing the - // same `find` surface and element shape). Amplify's managed-table construct keeps the public array names. - // Read the renamed fields first, falling back to the public ones so both table types resolve correctly. - const globalSecondaryIndexes = table['_globalSecondaryIndexes'] ?? table.globalSecondaryIndexes; + // aws-cdk-lib 2.260 renamed the private `localSecondaryIndexes` array on the DynamoDB L2 `Table` to + // `_localSecondaryIndexes` (now an `ArrayBox` exposing the same `find` surface and element shape). + // Amplify's managed-table construct keeps the public array name. Read the renamed field first, falling + // back to the public one so both table types resolve correctly. + const globalSecondaryIndexes = getGlobalSecondaryIndexes(table); const localSecondaryIndexes = table['_localSecondaryIndexes'] ?? table.localSecondaryIndexes; return ( (