From 82ac3510a492bd78973a8fa2fd475945ee46d69d Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Mon, 1 Dec 2025 13:58:21 -0800 Subject: [PATCH 1/5] feat(mixins-preview): L1 property mixins have typed relationships --- .../scripts/spec2mixins/builder.ts | 2 +- .../spec2cdk/lib/cdk/relationship-decider.ts | 35 ++++++++++--------- .../spec2cdk/lib/cdk/resolver-builder.ts | 4 +-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts b/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts index 8f9c07bf03755..1262979ab91dc 100644 --- a/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts +++ b/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts @@ -126,7 +126,7 @@ class L1PropsMixin extends ClassType { }, }); - this.relationshipDecider = new RelationshipDecider(this.resource, db, false); + this.relationshipDecider = new RelationshipDecider(this.resource, db, true, true); this.converter = TypeConverter.forMixin({ db: db, resource: this.resource, diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts index d14f3a35ed913..0e159c2a0d55d 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts @@ -5,20 +5,6 @@ import { ResourceReference } from './reference-props'; import { log } from '../util'; import { SelectiveImport } from './service-submodule'; -/** - * We currently disable the relationship on the properties of types because they would create a backwards incompatible change - * by broadening the output type as types are used both in input and output. This represents: - * Relationship counts: - * Resource-level (non-nested): 598 - * Type-level (nested): 483 <- these are disabled by this flag - * Total: 1081 - * Properties with relationships: - * Resource-level (non-nested): 493 - * Type-level (nested): 358 - * Total: 851 - */ -export const GENERATE_RELATIONSHIPS_ON_TYPES = false; - /** * Represents a cross-service property relationship that enables references * between resources from different AWS services. @@ -41,7 +27,24 @@ export class RelationshipDecider { private readonly namespace: string; public readonly imports = new Array(); - constructor(readonly resource: Resource, private readonly db: SpecDatabase, private readonly enableRelationships = true) { + constructor( + readonly resource: Resource, + private readonly db: SpecDatabase, + public readonly enableRelationships = true, + /** + * We currently disable the relationship on the properties of types because they would create a backwards incompatible change + * by broadening the output type as types are used both in input and output. This represents: + * Relationship counts: + * Resource-level (non-nested): 598 + * Type-level (nested): 483 <- these are disabled by this flag + * Total: 1081 + * Properties with relationships: + * Resource-level (non-nested): 493 + * Type-level (nested): 358 + * Total: 851 + */ + public readonly enableNestedRelationships = false, + ) { this.namespace = namespaceFromResource(resource); } @@ -146,7 +149,7 @@ export class RelationshipDecider { * Checks if a given property needs a flattening function or not */ public needsFlatteningFunction(propName: string, prop: Property, visited = new Set()): boolean { - if (!GENERATE_RELATIONSHIPS_ON_TYPES) { + if (!this.enableNestedRelationships) { return false; } if (this.hasValidRelationships(propName, prop.relationshipRefs)) { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts index 83e1cc462d9cc..296d518589446 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts @@ -1,7 +1,7 @@ import { DefinitionReference, Property } from '@aws-cdk/service-spec-types'; import { expr, Expression, Module, Type } from '@cdklabs/typewriter'; import { CDK_CORE } from './cdk'; -import { RelationshipDecider, Relationship, GENERATE_RELATIONSHIPS_ON_TYPES } from './relationship-decider'; +import { RelationshipDecider, Relationship } from './relationship-decider'; import { NON_RESOLVABLE_PROPERTY_NAMES } from './tagging'; import { TypeConverter } from './type-converter'; import { flattenFunctionNameFromType, propertyNameFromCloudFormation } from '../naming'; @@ -29,7 +29,7 @@ export class ResolverBuilder { ) {} public buildResolver(prop: Property, cfnName: string, isTypeProp = false): ResolverResult { - const shouldGenerateRelationships = isTypeProp ? GENERATE_RELATIONSHIPS_ON_TYPES : true; + const shouldGenerateRelationships = isTypeProp ? this.relationshipDecider.enableNestedRelationships : true; const name = propertyNameFromCloudFormation(cfnName); const baseType = this.converter.typeFromProperty(prop); From e5dfb11234ef87f9f8fd6a5d55df3040e2638d0a Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Fri, 5 Dec 2025 16:15:48 -0800 Subject: [PATCH 2/5] update typewriter --- packages/@aws-cdk/custom-resource-handlers/package.json | 2 +- packages/@aws-cdk/mixins-preview/package.json | 2 +- tools/@aws-cdk/spec2cdk/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/custom-resource-handlers/package.json b/packages/@aws-cdk/custom-resource-handlers/package.json index b09c7931ebab8..203ce043be1c5 100644 --- a/packages/@aws-cdk/custom-resource-handlers/package.json +++ b/packages/@aws-cdk/custom-resource-handlers/package.json @@ -48,7 +48,7 @@ "@types/jest": "^29.5.14", "aws-sdk-client-mock": "4.1.0", "aws-sdk-client-mock-jest": "4.1.0", - "@cdklabs/typewriter": "^0.0.12", + "@cdklabs/typewriter": "^0.0.14", "jest": "^29.7.0", "sinon": "^9.2.4", "nock": "^13.5.6", diff --git a/packages/@aws-cdk/mixins-preview/package.json b/packages/@aws-cdk/mixins-preview/package.json index 1fa31a50715e5..20c6d4e455f78 100644 --- a/packages/@aws-cdk/mixins-preview/package.json +++ b/packages/@aws-cdk/mixins-preview/package.json @@ -659,7 +659,7 @@ "@aws-cdk/service-spec-types": "^0.0.193", "@aws-cdk/spec2cdk": "0.0.0", "@cdklabs/tskb": "^0.0.4", - "@cdklabs/typewriter": "^0.0.12", + "@cdklabs/typewriter": "^0.0.14", "@types/jest": "^29.5.14", "aws-cdk-lib": "0.0.0", "constructs": "^10.0.0", diff --git a/tools/@aws-cdk/spec2cdk/package.json b/tools/@aws-cdk/spec2cdk/package.json index 2ab23f4bcad89..444fcb1212cdb 100644 --- a/tools/@aws-cdk/spec2cdk/package.json +++ b/tools/@aws-cdk/spec2cdk/package.json @@ -35,7 +35,7 @@ "@aws-cdk/service-spec-importers": "^0.0.99", "@aws-cdk/service-spec-types": "^0.0.193", "@cdklabs/tskb": "^0.0.4", - "@cdklabs/typewriter": "^0.0.12", + "@cdklabs/typewriter": "^0.0.14", "camelcase": "^6", "fs-extra": "^9", "p-limit": "^3.1.0", From 0fc7f0696dc1e2fb736ec2b08b2306746df1ab7b Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Fri, 5 Dec 2025 16:56:35 -0800 Subject: [PATCH 3/5] this works for mixins --- .../scripts/spec2logs/builder.ts | 18 ++--- .../scripts/spec2logs/helpers.ts | 7 -- .../scripts/spec2mixins/builder.ts | 6 +- .../@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts | 17 ++--- tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts | 5 ++ .../spec2cdk/lib/cdk/library-builder.ts | 14 +--- .../spec2cdk/lib/cdk/relationship-decider.ts | 76 +++++++------------ .../spec2cdk/lib/cdk/resolver-builder.ts | 12 +-- .../spec2cdk/lib/cdk/resource-class.ts | 4 - .../spec2cdk/lib/cdk/service-submodule.ts | 47 ------------ .../spec2cdk/lib/naming/conventions.ts | 22 ++++++ yarn.lock | 8 +- 12 files changed, 83 insertions(+), 153 deletions(-) diff --git a/packages/@aws-cdk/mixins-preview/scripts/spec2logs/builder.ts b/packages/@aws-cdk/mixins-preview/scripts/spec2logs/builder.ts index 0f108b150cfb2..06823a8897725 100644 --- a/packages/@aws-cdk/mixins-preview/scripts/spec2logs/builder.ts +++ b/packages/@aws-cdk/mixins-preview/scripts/spec2logs/builder.ts @@ -1,10 +1,10 @@ import type { Resource, Service, SpecDatabase } from '@aws-cdk/service-spec-types'; import { naming, util } from '@aws-cdk/spec2cdk'; -import { CDK_CORE, CONSTRUCTS } from '@aws-cdk/spec2cdk/lib/cdk/cdk'; +import { CDK_CORE, CDK_INTERFACES, CONSTRUCTS } from '@aws-cdk/spec2cdk/lib/cdk/cdk'; import type { Method } from '@cdklabs/typewriter'; import { Module, ExternalModule, ClassType, Stability, Type, expr, stmt, ThingSymbol, $this, CallableProxy, NewExpression, $E } from '@cdklabs/typewriter'; -import { CDK_AWS_LOGS, MIXINS_LOGS_DELIVERY, REF_INTERFACES } from './helpers'; -import type { ServiceSubmoduleProps, SelectiveImport, LocatedModule } from '@aws-cdk/spec2cdk/lib/cdk/service-submodule'; +import { CDK_AWS_LOGS, MIXINS_LOGS_DELIVERY } from './helpers'; +import type { ServiceSubmoduleProps, LocatedModule } from '@aws-cdk/spec2cdk/lib/cdk/service-submodule'; import { BaseServiceSubmodule, relativeImportPath } from '@aws-cdk/spec2cdk/lib/cdk/service-submodule'; import type { AddServiceProps, LibraryBuilderProps } from '@aws-cdk/spec2cdk/lib/cdk/library-builder'; import { LibraryBuilder } from '@aws-cdk/spec2cdk/lib/cdk/library-builder'; @@ -48,8 +48,6 @@ export class LogsDeliveryBuilder extends LibraryBuilder(); public readonly mixin: LogsMixin; private readonly helpers: LogsHelper[] = []; @@ -157,7 +154,7 @@ class LogsHelper extends ClassType { const paramS3 = toS3.addParameter({ name: 'bucket', - type: REF_INTERFACES.IBucketRef, + type: CDK_INTERFACES.IBucketRef, }); const permissions = this.resource.vendedLogs!.permissionsVersion === 'V2' ? MIXINS_LOGS_DELIVERY.S3LogsDeliveryPermissionsVersion.V2 : MIXINS_LOGS_DELIVERY.S3LogsDeliveryPermissionsVersion.V1; @@ -179,7 +176,7 @@ class LogsHelper extends ClassType { const paramCWL = toCWL.addParameter({ name: 'logGroup', - type: REF_INTERFACES.ILogGroupRef, + type: CDK_INTERFACES.ILogGroupRef, }); toCWL.addBody(stmt.block( @@ -199,7 +196,7 @@ class LogsHelper extends ClassType { const paramFH = toFH.addParameter({ name: 'deliveryStream', - type: REF_INTERFACES.IDeliveryStreamRef, + type: CDK_INTERFACES.IDeliveryStreamRef, }); toFH.addBody(stmt.block( @@ -238,7 +235,6 @@ class LogsHelper extends ClassType { } class LogsMixin extends ClassType { - public readonly imports = new Array(); private readonly resourceType: Type; constructor( diff --git a/packages/@aws-cdk/mixins-preview/scripts/spec2logs/helpers.ts b/packages/@aws-cdk/mixins-preview/scripts/spec2logs/helpers.ts index 8161f8dbd2a05..0c12c14f2a57a 100644 --- a/packages/@aws-cdk/mixins-preview/scripts/spec2logs/helpers.ts +++ b/packages/@aws-cdk/mixins-preview/scripts/spec2logs/helpers.ts @@ -9,16 +9,9 @@ class MixinsLogsDelivery extends ExternalModule { public readonly S3LogsDeliveryPermissionsVersion = $T(Type.fromName(this, 'S3LogsDeliveryPermissionsVersion')); } -class CdkRefInterfaces extends ExternalModule { - public readonly IBucketRef = Type.fromName(this, 'aws_s3.IBucketRef'); - public readonly ILogGroupRef = Type.fromName(this, 'aws_logs.ILogGroupRef'); - public readonly IDeliveryStreamRef = Type.fromName(this, 'aws_kinesisfirehose.IDeliveryStreamRef'); -} - class CdkAwsLogs extends ExternalModule { public readonly CfnDeliverySource = Type.fromName(this, 'CfnDeliverySource'); } export const MIXINS_LOGS_DELIVERY = new MixinsLogsDelivery('@aws-cdk/mixins-preview/services/aws-logs'); -export const REF_INTERFACES = new CdkRefInterfaces('aws-cdk-lib/interfaces'); export const CDK_AWS_LOGS = new CdkAwsLogs('aws-cdk-lib/aws-logs'); diff --git a/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts b/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts index 1262979ab91dc..17fc00e378b61 100644 --- a/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts +++ b/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts @@ -9,7 +9,7 @@ import { ExternalModule, Module, ClassType, Stability, StructType, Type, expr, s import { MIXINS_COMMON, MIXINS_CORE, MIXINS_UTILS } from './helpers'; import type { AddServiceProps, LibraryBuilderProps } from '@aws-cdk/spec2cdk/lib/cdk/library-builder'; import { LibraryBuilder } from '@aws-cdk/spec2cdk/lib/cdk/library-builder'; -import type { LocatedModule, SelectiveImport, ServiceSubmoduleProps } from '@aws-cdk/spec2cdk/lib/cdk/service-submodule'; +import type { LocatedModule, ServiceSubmoduleProps } from '@aws-cdk/spec2cdk/lib/cdk/service-submodule'; import { BaseServiceSubmodule, relativeImportPath } from '@aws-cdk/spec2cdk/lib/cdk/service-submodule'; class MixinsServiceModule extends BaseServiceSubmodule { @@ -47,8 +47,6 @@ export class MixinsBuilder extends LibraryBuilder { submodule.registerResource(resource.cloudFormationType, l1PropsMixin); l1PropsMixin.build(); - - submodule.registerSelectiveImports(...l1PropsMixin.imports); } private createMixinsModule(submodule: MixinsServiceModule, service: Service): LocatedModule { @@ -86,7 +84,6 @@ class L1PropsMixin extends ClassType { private readonly decider: ResourceDecider; private readonly relationshipDecider: RelationshipDecider; private readonly converter: TypeConverter; - public readonly imports = new Array(); constructor( scope: Module, @@ -133,7 +130,6 @@ class L1PropsMixin extends ClassType { resourceClass: this, relationshipDecider: this.relationshipDecider, }); - this.imports = this.relationshipDecider.imports; this.decider = new ResourceDecider(this.resource, this.converter, this.relationshipDecider); } diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts index ffb9bf74adf5b..f726d4130149f 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts @@ -184,7 +184,6 @@ export class AwsCdkLibBuilder extends LibraryBuilder resourceClass.build(); submodule.registerResource(resource.cloudFormationType, resourceClass); - submodule.registerSelectiveImports(...resourceClass.imports); submodule.augmentations?.module.augmentResource(resource, resourceClass); } @@ -260,14 +259,14 @@ export class AwsCdkLibBuilder extends LibraryBuilder } // Apply selective imports only to resources module - for (const selectiveImport of submodule.imports) { - const sourceModule = new Module(selectiveImport.moduleName); - sourceModule.importSelective( - submodule.resourcesMod.module, - selectiveImport.types.map((t) => `${t.originalType} as ${t.aliasedType}`), - { fromLocation: relativeImportPath(submodule.resourcesMod, sourceModule.name) }, - ); - } + // for (const selectiveImport of submodule.imports) { + // const sourceModule = new Module(selectiveImport.moduleName); + // sourceModule.importSelective( + // submodule.resourcesMod.module, + // selectiveImport.types.map((t) => `${t.originalType} as ${t.aliasedType}`), + // { fromLocation: relativeImportPath(submodule.resourcesMod, sourceModule.name) }, + // ); + // } // Add an import for the interfaces file to the entry point file (make sure not to do it twice) if (!submodule.interfaces?.module.isEmpty() && this.interfacesEntry && submodule.didCreateInterfaceModule) { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts index b6c64f49f11d1..70c9fbaa7d3ea 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/cdk.ts @@ -85,6 +85,10 @@ export class CdkCore extends ExternalModule { export class Interfaces extends ExternalModule { public readonly IEnvironmentAware = Type.fromName(this, 'IEnvironmentAware'); + + public readonly IBucketRef = Type.fromName(this, 'aws_s3.IBucketRef'); + public readonly ILogGroupRef = Type.fromName(this, 'aws_logs.ILogGroupRef'); + public readonly IDeliveryStreamRef = Type.fromName(this, 'aws_kinesisfirehose.IDeliveryStreamRef'); } export class CdkInternalHelpers extends ExternalModule { @@ -121,6 +125,7 @@ export class CdkCloudWatch extends ExternalModule { public readonly MetricOptions = Type.fromName(this, 'MetricOptions'); } +export const CDK_INTERFACES = new Interfaces('aws-cdk-lib/interfaces'); export const CDK_INTERFACES_ENVIRONMENT_AWARE = new Interfaces('aws-cdk-lib/interfaces/environment-aware'); export const CDK_CORE = new CdkCore('aws-cdk-lib/core'); export const CDK_CLOUDWATCH = new CdkCloudWatch('aws-cdk-lib/aws-cloudwatch'); diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/library-builder.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/library-builder.ts index 0b7670d20dc66..3e1bf06ac93aa 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/library-builder.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/library-builder.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import { SpecDatabase, Resource, Service } from '@aws-cdk/service-spec-types'; import { Module } from '@cdklabs/typewriter'; import { IWriter, substituteFilePattern } from '../util'; -import { BaseServiceSubmodule, LocatedModule, relativeImportPath } from './service-submodule'; +import { BaseServiceSubmodule, LocatedModule } from './service-submodule'; export interface AddServiceProps { /** @@ -142,16 +142,8 @@ export abstract class LibraryBuilder `${t.originalType} as ${t.aliasedType}`), { - fromLocation: relativeImportPath(mod.filePath, sourceModule.name), - }); - } - } + protected postprocessSubmodule(_submodule: ServiceSubmodule, _props?: AddServiceProps): void { + // does nothing, this is a hook for implementations } private obtainServiceSubmodule(service: Service, targetSubmodule?: string, grantsConfig?: string): ServiceSubmodule { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts index 0e159c2a0d55d..fe54b3d3fb1a6 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts @@ -1,9 +1,9 @@ import { Property, RelationshipRef, Resource, RichProperty, SpecDatabase } from '@aws-cdk/service-spec-types'; +import { Module, SelectiveModuleImport, Type } from '@cdklabs/typewriter'; import * as naming from '../naming'; -import { namespaceFromResource, referenceInterfaceName, referenceInterfaceAttributeName, referencePropertyName, typeAliasPrefixFromResource } from '../naming'; +import { CDK_INTERFACES } from './cdk'; import { ResourceReference } from './reference-props'; import { log } from '../util'; -import { SelectiveImport } from './service-submodule'; /** * Represents a cross-service property relationship that enables references @@ -11,21 +11,19 @@ import { SelectiveImport } from './service-submodule'; */ export interface Relationship { /** The TypeScript interface type that provides the reference (e.g. "IRoleRef") */ - readonly referenceType: string; + readonly refType: Type; + /** Human friendly name of the reference type for error generation (e.g. "iam.IRoleRef") */ + readonly refTypeDisplayName: string; /** The property name on the reference interface that holds the reference object (e.g. "roleRef") */ - readonly referenceName: string; + readonly refPropStructName: string; /** The property to extract from the reference object (e.g. "roleArn") */ - readonly propName: string; - /** Human friendly name of the reference type for error generation (e.g. "iam.IRoleRef") */ - readonly typeDisplayName: string; + readonly refPropName: string; } /** * Extracts resource relationship information from the database for cross-service property references. */ export class RelationshipDecider { - private readonly namespace: string; - public readonly imports = new Array(); constructor( readonly resource: Resource, @@ -44,30 +42,7 @@ export class RelationshipDecider { * Total: 851 */ public readonly enableNestedRelationships = false, - ) { - this.namespace = namespaceFromResource(resource); - } - - private registerRequiredImport({ namespace, originalType, aliasedType }: { - namespace: string; - originalType: string; - aliasedType: string; - }) { - const moduleName = naming.modulePartsFromNamespace(namespace).moduleName; - const moduleImport = this.imports.find(i => i.moduleName === moduleName); - if (!moduleImport) { - this.imports.push({ - moduleName, - types: [{ originalType, aliasedType }], - }); - } else { - if (!moduleImport.types.find(t => - t.originalType === originalType && t.aliasedType === aliasedType, - )) { - moduleImport.types.push({ originalType, aliasedType }); - } - } - } + ) {} /** * Retrieves the target resource for a relationship. @@ -80,7 +55,7 @@ export class RelationshipDecider { } const targetResource = this.db.lookup('resource', 'cloudFormationType', 'equals', relationship.cloudFormationType).only(); const refProps = new ResourceReference(targetResource).referenceProps; - const expectedPropName = referencePropertyName(relationship.propertyName, targetResource.name); + const expectedPropName = naming.referencePropertyName(relationship.propertyName, targetResource.name); const prop = refProps.find(p => p.declaration.name === expectedPropName); if (!prop) { log.debug( @@ -93,7 +68,7 @@ export class RelationshipDecider { return targetResource; } - public parseRelationship(sourcePropName: string, relationships?: RelationshipRef[]) { + public parseRelationship(targetModule: Module, sourcePropName: string, relationships?: RelationshipRef[]) { const parsedRelationships: Relationship[] = []; if (!relationships) { return parsedRelationships; @@ -103,22 +78,25 @@ export class RelationshipDecider { if (!targetResource) { continue; } - // Ignore the suffix part because it's an edge case that happens only for one module - const interfaceName = referenceInterfaceName(targetResource.name); - const refPropStructName = referenceInterfaceAttributeName(targetResource.name); - const targetNamespace = namespaceFromResource(targetResource); - let aliasedTypeName = undefined; - if (this.namespace !== targetNamespace) { - // If this is not in our namespace we need to alias the import type - aliasedTypeName = `${typeAliasPrefixFromResource(targetResource)}${interfaceName}`; - this.registerRequiredImport({ namespace: targetNamespace, originalType: interfaceName, aliasedType: aliasedTypeName }); - } + // import the ref module + const refsAlias = naming.interfaceModuleImportName(targetResource); + const selectiveImport = new SelectiveModuleImport(CDK_INTERFACES, CDK_INTERFACES.importName, [ + [naming.submoduleSymbolFromResource(targetResource), refsAlias] + ]); + targetModule.addImport(selectiveImport); + + // Ignore the suffix part because it's an edge case that happens only for one module + const interfaceName = naming.referenceInterfaceName(targetResource.name); + const referenceType = Type.fromName(targetModule, `${refsAlias}.${interfaceName}`); + const referenceTypeDisplayName = `${naming.typeAliasPrefixFromResource(targetResource).toLowerCase()}.${interfaceName}`; + const refPropStructName = naming.referenceInterfaceAttributeName(targetResource.name); + parsedRelationships.push({ - referenceType: aliasedTypeName ?? interfaceName, - referenceName: refPropStructName, - propName: referencePropertyName(relationship.propertyName, targetResource.name), - typeDisplayName: `${typeAliasPrefixFromResource(targetResource).toLowerCase()}.${interfaceName}`, + refType: referenceType, + refTypeDisplayName: referenceTypeDisplayName, + refPropStructName: refPropStructName, + refPropName: naming.referencePropertyName(relationship.propertyName, targetResource.name), }); } return parsedRelationships; diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts index 296d518589446..f941270ffb377 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resolver-builder.ts @@ -39,7 +39,7 @@ export class ResolverBuilder { const resolvableType = cfnName in NON_RESOLVABLE_PROPERTY_NAMES ? baseType : this.converter.makeTypeResolvable(baseType); if (shouldGenerateRelationships) { - const relationships = this.relationshipDecider.parseRelationship(name, prop.relationshipRefs); + const relationships = this.relationshipDecider.parseRelationship(this.module, name, prop.relationshipRefs); if (relationships.length > 0) { return this.buildRelationshipResolver({ relationships, baseType, name, resolvableType }); } @@ -72,13 +72,13 @@ export class ResolverBuilder { if (!(baseType === Type.STRING || baseType.arrayOfType === Type.STRING)) { throw Error('Trying to map to a non string property'); } - const newTypes = relationships.map(t => Type.fromName(this.module, t.referenceType)); + const newTypes = relationships.map(t => t.refType); const propType = resolvableType.arrayOfType ? Type.arrayOf(Type.distinctUnionOf(resolvableType.arrayOfType, ...newTypes)) : Type.distinctUnionOf(resolvableType, ...newTypes); const typeDisplayNames = [ - ...relationships.map(r => r.typeDisplayName), + ...relationships.map(r => r.refTypeDisplayName), resolvableType.arrayOfType?.toString() ?? resolvableType.toString(), ].join(' | '); @@ -86,12 +86,12 @@ export class ResolverBuilder { // For single value T | string : (props.xx as IxxxRef)?.xxxRef?.xxxArn ?? cdk.ensureStringOrUndefined(props.xxx, "xxx", "iam.IxxxRef | string"); // For array []: (props.xx?.forEach((item: T | string, i: number, arr: Array) => { arr[i] = (item as T)?.xxxRef?.xx ?? cdk.ensureStringOrUndefined(item, "xxx", "lambda.T | string"); }), props.xxx as Array); // Ensures that arn properties always appear first in the chain as they are more general - const arnRels = relationships.filter(r => r.propName.toLowerCase().endsWith('arn')); - const otherRels = relationships.filter(r => !r.propName.toLowerCase().endsWith('arn')); + const arnRels = relationships.filter(r => r.refPropName.toLowerCase().endsWith('arn')); + const otherRels = relationships.filter(r => !r.refPropName.toLowerCase().endsWith('arn')); const buildChain = (itemName: string) => [ ...[...arnRels, ...otherRels] - .map(r => `(${itemName} as ${r.referenceType})?.${r.referenceName}?.${r.propName}`), + .map(r => `(${itemName} as ${r.refType})?.${r.refPropStructName}?.${r.refPropName}`), `cdk.ensureStringOrUndefined(${itemName}, "${name}", "${typeDisplayNames}")`, ].join(' ?? '); const resolver = (_: Expression) => { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index b0a6152ec40e3..751dc429dce8f 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -51,7 +51,6 @@ import { } from '../naming'; import { isDefined, splitDocumentation, maybeDeprecated } from '../util'; import { RelationshipDecider } from './relationship-decider'; -import { SelectiveImport } from './service-submodule'; export interface ITypeHost { typeFromSpecType(type: PropertyType): Type; @@ -77,7 +76,6 @@ export class ResourceClass extends ClassType implements Referenceable { private readonly relationshipDecider: RelationshipDecider; private readonly converter: TypeConverter; private readonly module: Module; - public readonly imports = new Array(); public ref: ReferenceInterfaceTypes; constructor( @@ -114,8 +112,6 @@ export class ResourceClass extends ClassType implements Referenceable { resourceClass: this, relationshipDecider: this.relationshipDecider, }); - - this.imports = this.relationshipDecider.imports; this.decider = new ResourceDecider(this.resource, this.converter, this.relationshipDecider); this.propsType = new StructType(this.scope, { diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/service-submodule.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/service-submodule.ts index 37bc2d67add27..a606f1e5438b7 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/service-submodule.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/service-submodule.ts @@ -24,23 +24,6 @@ export function relativeImportPath(source: LocatedModule | string, target: return ret.startsWith('.') ? ret : './' + ret; } -/** - * Represents a selective import statement for cross-module type references. - * Used to import specific types from other CDK modules when relationships - * are between different modules. - */ -export interface SelectiveImport { - /** The module name to import from */ - readonly moduleName: string; - /** Array of types that need to be imported */ - readonly types: { - /** The original type name in the source module */ - originalType: string; - /** The aliased name to avoid naming conflicts */ - aliasedType: string; - }[]; -} - /** * Create a service submodule. */ @@ -77,15 +60,10 @@ export class BaseServiceSubmodule { */ public readonly resources: Map = new Map(); - public get imports(): SelectiveImport[] { - return this.selectiveImports.sort((a, b) => a.moduleName.localeCompare(b.moduleName)); - } - public get locatedModules(): LocatedModule[] { return this.modules; } - private selectiveImports: SelectiveImport[] = []; private modules: LocatedModule[] = []; public constructor(props: ServiceSubmoduleProps) { @@ -100,29 +78,4 @@ export class BaseServiceSubmodule { public registerResource(cfnResourceName: string, type: TypeDeclaration) { this.resources.set(cfnResourceName, type); } - - public registerSelectiveImports(...selectiveImports: SelectiveImport[]) { - for (const theImport of selectiveImports) { - const existingModuleImport = this.findSelectiveImport(theImport); - if (!existingModuleImport) { - this.selectiveImports.push(theImport); - continue; - } - - // We need to avoid importing the same reference multiple times - for (const type of theImport.types) { - if (!existingModuleImport.types.find((t) => - t.originalType === type.originalType && t.aliasedType === type.aliasedType, - )) { - existingModuleImport.types.push(type); - } - } - } - } - - private findSelectiveImport(selectiveImport: SelectiveImport): SelectiveImport | undefined { - return this.selectiveImports.find( - (imp) => imp.moduleName === selectiveImport.moduleName, - ); - } } diff --git a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts index 5ba483c5851f4..6cd66159ec7d0 100644 --- a/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts +++ b/tools/@aws-cdk/spec2cdk/lib/naming/conventions.ts @@ -62,6 +62,14 @@ export function interfaceNameFromResource(res: Resource, suffix?: string) { return `I${classNameFromResource(res, suffix)}`; } +/** + * resource to alias for interface imports + * `AWS::S3::Bucket` -> `s3Refs` + */ +export function interfaceModuleImportName(res: Resource) { + return camelcase(`${modulePartsFromResource(res).moduleBaseName}Refs`); +} + export function namespaceFromResource(res: Resource) { return res.cloudFormationType.split('::').slice(0, 2).join('::'); } @@ -145,6 +153,13 @@ export function modulePartsFromNamespace(namespace: string) { }; } +/** + * resource to module name parts (`AWS::S3::Bucket` -> ['aws-s3', 'AWS', 'S3']) + */ +export function modulePartsFromResource(res: Resource) { + return modulePartsFromNamespace(namespaceFromResource(res)); +} + /** * Submodule identifier from name (`aws-s3` -> `aws_s3`) */ @@ -152,6 +167,13 @@ export function submoduleSymbolFromName(name: string) { return name.replace(/-/g, '_'); } +/** + * Submodule identifier from name (`AWS::S3::Bucket` -> `aws_s3`) + */ +export function submoduleSymbolFromResource(res: Resource) { + return modulePartsFromResource(res).moduleName.replace(/-/g, '_'); +} + /** * Get the namespace name from the event name */ diff --git a/yarn.lock b/yarn.lock index 9007f43c55c02..d3a3fe46ee2fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2938,10 +2938,10 @@ resolved "https://registry.npmjs.org/@cdklabs/tskb/-/tskb-0.0.4.tgz#6d7af32427ef947dddcb6f1f1d76d75924e33323" integrity sha512-NFx1X0l7p5DyHtLLEyNeh1hPN4UN9hTkZkzFs/Mp+kFk7dpdINGmGVpCfRDjJ2DrcNSNENUmT+w8g73TvmBbTw== -"@cdklabs/typewriter@^0.0.12": - version "0.0.12" - resolved "https://registry.npmjs.org/@cdklabs/typewriter/-/typewriter-0.0.12.tgz#dd6348ff5284535c0134b5e43d5bb349aaf5c1db" - integrity sha512-xjiGYgMvCGwl5HFaauOjlvgBVXHtYdx8TFgn0T0E6ka95wnMhsKWvGolp8KFsK9sQ9vUr11B205DwUqquKBqLQ== +"@cdklabs/typewriter@^0.0.14": + version "0.0.14" + resolved "https://registry.npmjs.org/@cdklabs/typewriter/-/typewriter-0.0.14.tgz#57f10a3acb36c1e3604a8c5233e381579939d03e" + integrity sha512-Om+W7PT4OOwdgkxXGm6Xyk3sj3aGWcAys3qMs9tWivENKfluD2WvL4J7+ZhmIcNdJ9oqE8X/9kR+ne92QdsJLA== "@colors/colors@1.6.0", "@colors/colors@^1.6.0": version "1.6.0" From bb57ce0c1a01a33dadb2fedd28137cf5573d1b17 Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Fri, 5 Dec 2025 17:45:58 -0800 Subject: [PATCH 4/5] yay --- .../scripts/spec2mixins/builder.ts | 6 ++- .../@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts | 28 ++++++------- .../spec2cdk/lib/cdk/relationship-decider.ts | 42 ++++++++++++++----- .../spec2cdk/lib/cdk/resource-class.ts | 12 ++++-- 4 files changed, 58 insertions(+), 30 deletions(-) diff --git a/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts b/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts index 17fc00e378b61..3c706a8bdda53 100644 --- a/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts +++ b/packages/@aws-cdk/mixins-preview/scripts/spec2mixins/builder.ts @@ -123,7 +123,11 @@ class L1PropsMixin extends ClassType { }, }); - this.relationshipDecider = new RelationshipDecider(this.resource, db, true, true); + this.relationshipDecider = new RelationshipDecider(this.resource, db, { + enableRelationships: true, + enableNestedRelationships: true, + refsImportLocation: 'aws-cdk-lib/interfaces' + }); this.converter = TypeConverter.forMixin({ db: db, resource: this.resource, diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts index f726d4130149f..027e1a7e9b8fe 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/aws-cdk-lib.ts @@ -175,10 +175,11 @@ export class AwsCdkLibBuilder extends LibraryBuilder const resourceClass = new ResourceClass(resourceModule, this.db, resource, { suffix: props?.nameSuffix, deprecated: props?.deprecated, - interfacesModule: submodule.interfaces ? { - module: submodule.interfaces?.module, + importPaths: this.resolveImportPaths(submodule.resourcesMod.filePath), + interfacesModule: { + module: submodule.interfaces.module, importLocation: relativeImportPath(submodule.resourcesMod, submodule.interfaces), - } : undefined, + }, }); resourceClass.build(); @@ -258,18 +259,8 @@ export class AwsCdkLibBuilder extends LibraryBuilder grantModule.build(Object.fromEntries(submodule.resources), props?.nameSuffix); } - // Apply selective imports only to resources module - // for (const selectiveImport of submodule.imports) { - // const sourceModule = new Module(selectiveImport.moduleName); - // sourceModule.importSelective( - // submodule.resourcesMod.module, - // selectiveImport.types.map((t) => `${t.originalType} as ${t.aliasedType}`), - // { fromLocation: relativeImportPath(submodule.resourcesMod, sourceModule.name) }, - // ); - // } - // Add an import for the interfaces file to the entry point file (make sure not to do it twice) - if (!submodule.interfaces?.module.isEmpty() && this.interfacesEntry && submodule.didCreateInterfaceModule) { + if (!submodule.interfaces.module.isEmpty() && this.interfacesEntry && submodule.didCreateInterfaceModule) { const exportName = submoduleSymbolFromName(submodule.service.name); const importLocation = relativeImportPath(this.interfacesEntry, submodule.interfaces); @@ -283,7 +274,8 @@ export class AwsCdkLibBuilder extends LibraryBuilder if (!this.inCdkLib) { return { core: 'aws-cdk-lib/core', - interfacesEnvironmentAware: 'aws-cdk-lib/interfaces', + interfaces: 'aws-cdk-lib/interfaces', + interfacesEnvironmentAware: 'aws-cdk-lib/interfaces/environment-aware', coreHelpers: 'aws-cdk-lib/core/lib/helpers-internal', coreErrors: 'aws-cdk-lib/core/lib/errors', cloudwatch: 'aws-cdk-lib/aws-cloudwatch', @@ -293,6 +285,7 @@ export class AwsCdkLibBuilder extends LibraryBuilder return { core: relativeImportPath(sourceModule, 'core/lib'), + interfaces: relativeImportPath(sourceModule, 'interfaces'), interfacesEnvironmentAware: relativeImportPath(sourceModule, 'interfaces/environment-aware'), coreHelpers: relativeImportPath(sourceModule, 'core/lib/helpers-internal'), coreErrors: relativeImportPath(sourceModule, 'core/lib/errors'), @@ -320,6 +313,11 @@ export interface ImportPaths { */ readonly core: string; + /** + * The import name used import the `interfaces` module + */ + readonly interfaces: string; + /** * The import name used import a specific interface from the `interfaces` module * diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts index fe54b3d3fb1a6..f5eb0ca219e3a 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts @@ -20,15 +20,12 @@ export interface Relationship { readonly refPropName: string; } -/** - * Extracts resource relationship information from the database for cross-service property references. - */ -export class RelationshipDecider { +export interface RelationshipDeciderProps { + /** + * Render relationships + */ + readonly enableRelationships: boolean; - constructor( - readonly resource: Resource, - private readonly db: SpecDatabase, - public readonly enableRelationships = true, /** * We currently disable the relationship on the properties of types because they would create a backwards incompatible change * by broadening the output type as types are used both in input and output. This represents: @@ -41,8 +38,31 @@ export class RelationshipDecider { * Type-level (nested): 358 * Total: 851 */ - public readonly enableNestedRelationships = false, - ) {} + readonly enableNestedRelationships: boolean; + + /** + * The location to import reference interfaces from. + */ + readonly refsImportLocation: string; +} + +/** + * Extracts resource relationship information from the database for cross-service property references. + */ +export class RelationshipDecider { + public readonly enableRelationships: boolean; + public readonly enableNestedRelationships: boolean; + private readonly refsImportLocation: string; + + constructor( + readonly resource: Resource, + private readonly db: SpecDatabase, + props: RelationshipDeciderProps, + ) { + this.enableRelationships = props.enableRelationships ?? true; + this.enableNestedRelationships = props.enableNestedRelationships ?? false; + this.refsImportLocation = props.refsImportLocation; + } /** * Retrieves the target resource for a relationship. @@ -81,7 +101,7 @@ export class RelationshipDecider { // import the ref module const refsAlias = naming.interfaceModuleImportName(targetResource); - const selectiveImport = new SelectiveModuleImport(CDK_INTERFACES, CDK_INTERFACES.importName, [ + const selectiveImport = new SelectiveModuleImport(CDK_INTERFACES, this.refsImportLocation, [ [naming.submoduleSymbolFromResource(targetResource), refsAlias] ]); targetModule.addImport(selectiveImport); diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 751dc429dce8f..0545d920f9e28 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -51,6 +51,7 @@ import { } from '../naming'; import { isDefined, splitDocumentation, maybeDeprecated } from '../util'; import { RelationshipDecider } from './relationship-decider'; +import { ImportPaths } from './aws-cdk-lib'; export interface ITypeHost { typeFromSpecType(type: PropertyType): Type; @@ -62,7 +63,8 @@ export interface Referenceable { } export interface ResourceClassProps { - readonly interfacesModule?: { + readonly importPaths: ImportPaths, + readonly interfacesModule: { readonly module: Module; readonly importLocation: string; }; @@ -82,7 +84,7 @@ export class ResourceClass extends ClassType implements Referenceable { scope: IScope, private readonly db: SpecDatabase, private readonly resource: Resource, - private readonly props: ResourceClassProps = {}, + private readonly props: ResourceClassProps, ) { // A mutable array we pass to super() const implements_: Type[] = [CDK_CORE.IInspectable]; @@ -105,7 +107,11 @@ export class ResourceClass extends ClassType implements Referenceable { this.module = Module.of(this); - this.relationshipDecider = new RelationshipDecider(this.resource, db); + this.relationshipDecider = new RelationshipDecider(this.resource, db, { + enableRelationships: true, + enableNestedRelationships: false, + refsImportLocation: this.props.importPaths.interfaces + }); this.converter = TypeConverter.forResource({ db: db, resource: this.resource, From 0bd59a712874c3b96e8e8c14812f1954a15db16a Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Fri, 5 Dec 2025 17:48:24 -0800 Subject: [PATCH 5/5] eslint --- .../spec2cdk/lib/cdk/relationship-decider.ts | 52 +++++++++---------- .../spec2cdk/lib/cdk/resource-class.ts | 6 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts index f5eb0ca219e3a..8a66477afe6c4 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/relationship-decider.ts @@ -21,29 +21,29 @@ export interface Relationship { } export interface RelationshipDeciderProps { - /** - * Render relationships - */ - readonly enableRelationships: boolean; - - /** - * We currently disable the relationship on the properties of types because they would create a backwards incompatible change - * by broadening the output type as types are used both in input and output. This represents: - * Relationship counts: - * Resource-level (non-nested): 598 - * Type-level (nested): 483 <- these are disabled by this flag - * Total: 1081 - * Properties with relationships: - * Resource-level (non-nested): 493 - * Type-level (nested): 358 - * Total: 851 - */ - readonly enableNestedRelationships: boolean; - - /** - * The location to import reference interfaces from. - */ - readonly refsImportLocation: string; + /** + * Render relationships + */ + readonly enableRelationships: boolean; + + /** + * We currently disable the relationship on the properties of types because they would create a backwards incompatible change + * by broadening the output type as types are used both in input and output. This represents: + * Relationship counts: + * Resource-level (non-nested): 598 + * Type-level (nested): 483 <- these are disabled by this flag + * Total: 1081 + * Properties with relationships: + * Resource-level (non-nested): 493 + * Type-level (nested): 358 + * Total: 851 + */ + readonly enableNestedRelationships: boolean; + + /** + * The location to import reference interfaces from. + */ + readonly refsImportLocation: string; } /** @@ -102,16 +102,16 @@ export class RelationshipDecider { // import the ref module const refsAlias = naming.interfaceModuleImportName(targetResource); const selectiveImport = new SelectiveModuleImport(CDK_INTERFACES, this.refsImportLocation, [ - [naming.submoduleSymbolFromResource(targetResource), refsAlias] + [naming.submoduleSymbolFromResource(targetResource), refsAlias], ]); targetModule.addImport(selectiveImport); - + // Ignore the suffix part because it's an edge case that happens only for one module const interfaceName = naming.referenceInterfaceName(targetResource.name); const referenceType = Type.fromName(targetModule, `${refsAlias}.${interfaceName}`); const referenceTypeDisplayName = `${naming.typeAliasPrefixFromResource(targetResource).toLowerCase()}.${interfaceName}`; const refPropStructName = naming.referenceInterfaceAttributeName(targetResource.name); - + parsedRelationships.push({ refType: referenceType, refTypeDisplayName: referenceTypeDisplayName, diff --git a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts index 0545d920f9e28..1ec15114f1932 100644 --- a/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts +++ b/tools/@aws-cdk/spec2cdk/lib/cdk/resource-class.ts @@ -32,6 +32,7 @@ import { $this, } from '@cdklabs/typewriter'; import { extractVariablesFromArnFormat, findNonIdentifierArnProperty } from './arn'; +import { ImportPaths } from './aws-cdk-lib'; import { CDK_CORE, CDK_INTERFACES_ENVIRONMENT_AWARE, CONSTRUCTS } from './cdk'; import { CloudFormationMapping } from './cloudformation-mapping'; import { ResourceDecider } from './resource-decider'; @@ -51,7 +52,6 @@ import { } from '../naming'; import { isDefined, splitDocumentation, maybeDeprecated } from '../util'; import { RelationshipDecider } from './relationship-decider'; -import { ImportPaths } from './aws-cdk-lib'; export interface ITypeHost { typeFromSpecType(type: PropertyType): Type; @@ -63,7 +63,7 @@ export interface Referenceable { } export interface ResourceClassProps { - readonly importPaths: ImportPaths, + readonly importPaths: ImportPaths; readonly interfacesModule: { readonly module: Module; readonly importLocation: string; @@ -110,7 +110,7 @@ export class ResourceClass extends ClassType implements Referenceable { this.relationshipDecider = new RelationshipDecider(this.resource, db, { enableRelationships: true, enableNestedRelationships: false, - refsImportLocation: this.props.importPaths.interfaces + refsImportLocation: this.props.importPaths.interfaces, }); this.converter = TypeConverter.forResource({ db: db,