@aws/nx-plugin 1.0.0-rc.57 → 1.0.0-rc.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/LICENSE-THIRD-PARTY +2917 -1295
  2. package/migrations.json +31 -26
  3. package/package.json +13 -13
  4. package/src/agentcore-gateway/generator.d.ts +16 -1
  5. package/src/agentcore-gateway/generator.js +3 -2
  6. package/src/agentcore-gateway/generator.js.map +1 -1
  7. package/src/agentcore-gateway/schema.json +1 -0
  8. package/src/connection/scaffold-catalog.d.ts +160 -0
  9. package/src/connection/scaffold-catalog.js +207 -0
  10. package/src/connection/scaffold-catalog.js.map +1 -0
  11. package/src/connection/schema-resolver.d.ts +5 -0
  12. package/src/connection/schema-resolver.js +27 -0
  13. package/src/connection/schema-resolver.js.map +1 -0
  14. package/src/infra/app/__snapshots__/generator.spec.ts.snap +7 -7
  15. package/src/migrations/latest/smithy-ssdk-bundle-pins/migration.js +78 -0
  16. package/src/migrations/latest/smithy-ssdk-bundle-pins/migration.js.map +1 -0
  17. package/src/migrations/v1.0.0-rc.50/modernize-function-props-cast/migration.js.map +1 -0
  18. package/src/migrations/v1.0.0-rc.50/restrict-cors-to-custom-domains/migration.js.map +1 -0
  19. package/src/migrations/v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
  20. package/src/migrations/v1.0.0-rc.52/user-identity-waf-allow-localhost-callback/migration.js.map +1 -0
  21. package/src/migrations/v1.0.0-rc.54/order-access-log-delivery-after-bucket-policy/migration.js.map +1 -0
  22. package/src/migrations/v1.0.0-rc.55/backfill-generator-metadata/migration.js.map +1 -0
  23. package/src/migrations/v1.0.0-rc.56/dynamodb-local-remove-optimize-flag/migration.js.map +1 -0
  24. package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/migration.d.ts +6 -0
  25. package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/migration.js.map +1 -0
  26. package/src/preset/__snapshots__/generator.spec.ts.snap +5 -5
  27. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +8 -8
  28. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +8 -8
  29. package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +2 -2
  30. package/src/py/agent/a2a-connection/generator.d.ts +1 -1
  31. package/src/py/agent/gateway-connection/generator.d.ts +1 -1
  32. package/src/py/agent/mcp-connection/generator.d.ts +1 -1
  33. package/src/py/agent/schema.json +1 -0
  34. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
  35. package/src/py/dynamodb/schema.json +1 -0
  36. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +12 -12
  37. package/src/py/fast-api/generator.d.ts +5 -0
  38. package/src/py/fast-api/generator.js +3 -2
  39. package/src/py/fast-api/generator.js.map +1 -1
  40. package/src/py/fast-api/schema.json +1 -0
  41. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
  42. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +5 -5
  43. package/src/py/mcp-server/schema.json +1 -0
  44. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2 -2
  45. package/src/py/rdb/schema.json +1 -0
  46. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +4 -4
  47. package/src/smithy/project/files/service/build.Dockerfile.template +2 -2
  48. package/src/smithy/project/generator.d.ts +25 -0
  49. package/src/smithy/project/generator.js +24 -3
  50. package/src/smithy/project/generator.js.map +1 -1
  51. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +7 -7
  52. package/src/smithy/ts/api/generator.d.ts +6 -1
  53. package/src/smithy/ts/api/generator.js +3 -2
  54. package/src/smithy/ts/api/generator.js.map +1 -1
  55. package/src/smithy/ts/api/schema.json +1 -0
  56. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +12 -12
  57. package/src/trpc/backend/generator.d.ts +6 -1
  58. package/src/trpc/backend/generator.js +3 -2
  59. package/src/trpc/backend/generator.js.map +1 -1
  60. package/src/trpc/backend/schema.json +1 -0
  61. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +5 -5
  62. package/src/ts/agent/generator.d.ts +32 -1
  63. package/src/ts/agent/generator.js +7 -4
  64. package/src/ts/agent/generator.js.map +1 -1
  65. package/src/ts/agent/schema.json +1 -0
  66. package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +1 -1
  67. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
  68. package/src/ts/dynamodb/schema.json +1 -0
  69. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
  70. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +2 -2
  71. package/src/ts/mcp-server/generator.d.ts +32 -1
  72. package/src/ts/mcp-server/generator.js +7 -4
  73. package/src/ts/mcp-server/generator.js.map +1 -1
  74. package/src/ts/mcp-server/schema.json +1 -0
  75. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +6 -6
  76. package/src/ts/rdb/generator.d.ts +8 -0
  77. package/src/ts/rdb/generator.js +3 -2
  78. package/src/ts/rdb/generator.js.map +1 -1
  79. package/src/ts/rdb/schema.json +1 -0
  80. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +61 -45
  81. package/src/ts/react-website/app/generator.d.ts +6 -1
  82. package/src/ts/react-website/app/generator.js +3 -2
  83. package/src/ts/react-website/app/generator.js.map +1 -1
  84. package/src/ts/react-website/app/schema.json +1 -0
  85. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -2
  86. package/src/ts/react-website/cognito-auth/generator.d.ts +6 -1
  87. package/src/ts/react-website/cognito-auth/generator.js +3 -2
  88. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  89. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +18 -0
  90. package/src/utils/agent-core-constructs/agent-core-constructs.js +22 -1
  91. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  92. package/src/utils/api-constructs/api-constructs.d.ts +9 -0
  93. package/src/utils/api-constructs/api-constructs.js +11 -1
  94. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  95. package/src/utils/docker.d.ts +27 -2
  96. package/src/utils/docker.js +31 -2
  97. package/src/utils/docker.js.map +1 -1
  98. package/src/utils/identity-constructs/identity-constructs.d.ts +10 -0
  99. package/src/utils/identity-constructs/identity-constructs.js +11 -1
  100. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  101. package/src/utils/shared-constructs-constants.d.ts +6 -0
  102. package/src/utils/shared-constructs-constants.js +5 -0
  103. package/src/utils/shared-constructs-constants.js.map +1 -1
  104. package/src/utils/version-upgrade-migration/owned-dependencies.d.ts +26 -0
  105. package/src/utils/version-upgrade-migration/owned-dependencies.js +52 -4
  106. package/src/utils/version-upgrade-migration/owned-dependencies.js.map +1 -1
  107. package/src/utils/version-upgrade-migration/register.d.ts +5 -1
  108. package/src/utils/version-upgrade-migration/register.js +6 -2
  109. package/src/utils/version-upgrade-migration/register.js.map +1 -1
  110. package/src/utils/version-upgrade-migration/sync-embedded-versions.d.ts +26 -0
  111. package/src/utils/version-upgrade-migration/sync-embedded-versions.js +304 -0
  112. package/src/utils/version-upgrade-migration/sync-embedded-versions.js.map +1 -0
  113. package/src/utils/version-upgrade-migration/sync-vended-versions.js +14 -0
  114. package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -1
  115. package/src/utils/versions.d.ts +90 -77
  116. package/src/utils/versions.js +86 -75
  117. package/src/utils/versions.js.map +1 -1
  118. package/src/utils/website-constructs/website-constructs.d.ts +11 -0
  119. package/src/utils/website-constructs/website-constructs.js +12 -1
  120. package/src/utils/website-constructs/website-constructs.js.map +1 -1
  121. package/src/migrations/latest/backfill-generator-metadata/migration.js.map +0 -1
  122. package/src/migrations/latest/dynamodb-local-remove-optimize-flag/migration.js.map +0 -1
  123. package/src/migrations/latest/modernize-function-props-cast/migration.js.map +0 -1
  124. package/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.js.map +0 -1
  125. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +0 -1
  126. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +0 -1
  127. package/src/migrations/latest/ts-agent-session-management-support/migration.js.map +0 -1
  128. package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js.map +0 -1
  129. /package/src/migrations/latest/{modernize-function-props-cast → smithy-ssdk-bundle-pins}/migration.d.ts +0 -0
  130. /package/src/migrations/{latest/restrict-cors-to-custom-domains → v1.0.0-rc.50/modernize-function-props-cast}/migration.d.ts +0 -0
  131. /package/src/migrations/{latest → v1.0.0-rc.50}/modernize-function-props-cast/migration.js +0 -0
  132. /package/src/migrations/{latest/terraform-bootstrap-adopt-existing-bucket → v1.0.0-rc.50/restrict-cors-to-custom-domains}/migration.d.ts +0 -0
  133. /package/src/migrations/{latest → v1.0.0-rc.50}/restrict-cors-to-custom-domains/migration.js +0 -0
  134. /package/src/migrations/{latest/ts-agent-session-management-support → v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket}/migration.d.ts +0 -0
  135. /package/src/migrations/{latest → v1.0.0-rc.50}/terraform-bootstrap-adopt-existing-bucket/migration.js +0 -0
  136. /package/src/migrations/{latest/dynamodb-local-remove-optimize-flag → v1.0.0-rc.52/user-identity-waf-allow-localhost-callback}/migration.d.ts +0 -0
  137. /package/src/migrations/{latest → v1.0.0-rc.52}/user-identity-waf-allow-localhost-callback/migration.js +0 -0
  138. /package/src/migrations/{latest → v1.0.0-rc.54}/order-access-log-delivery-after-bucket-policy/migration.d.ts +0 -0
  139. /package/src/migrations/{latest → v1.0.0-rc.54}/order-access-log-delivery-after-bucket-policy/migration.js +0 -0
  140. /package/src/migrations/{latest → v1.0.0-rc.55}/backfill-generator-metadata/migration.d.ts +0 -0
  141. /package/src/migrations/{latest → v1.0.0-rc.55}/backfill-generator-metadata/migration.js +0 -0
  142. /package/src/migrations/{latest/user-identity-waf-allow-localhost-callback → v1.0.0-rc.56/dynamodb-local-remove-optimize-flag}/migration.d.ts +0 -0
  143. /package/src/migrations/{latest → v1.0.0-rc.56}/dynamodb-local-remove-optimize-flag/migration.js +0 -0
  144. /package/src/migrations/{latest → v1.0.0-rc.57}/ts-agent-session-management-support/migration.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/modernize-function-props-cast/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs\n *\n * The legacy `<FunctionProps>{ ... }` cast form is not supported by GritQL's\n * TypeScript parser, which silently breaks parsing (and therefore matching)\n * for the entire containing file. Since several other migrations rely on\n * GritQL to update these API construct files, this cast is replaced here with\n * the equivalent, GritQL-compatible `{ ... } as FunctionProps` form. This is\n * matched as an exact literal (rather than via GritQL) since GritQL cannot\n * parse the file while the legacy cast is still present.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, or consider a\n * hybrid migration, rather than clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\nconst APIS_APP_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/app/apis`;\n\nconst OLD_CAST_OPEN = 'defaultIntegrationOptions: <FunctionProps>{';\nconst NEW_CAST_OPEN = 'defaultIntegrationOptions: {';\nconst OLD_CAST_CLOSE = '\\n },\\n buildDefaultIntegration:';\nconst NEW_CAST_CLOSE =\n '\\n } as FunctionProps,\\n buildDefaultIntegration:';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (!tree.exists(APIS_APP_DIR)) {\n return { nextSteps };\n }\n\n const apiAppFiles: string[] = [];\n visitNotIgnoredFiles(tree, APIS_APP_DIR, (filePath) => {\n apiAppFiles.push(filePath);\n });\n\n for (const filePath of apiAppFiles) {\n if (!filePath.endsWith('.ts') || filePath.endsWith('/index.ts')) {\n continue;\n }\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes(OLD_CAST_OPEN)) {\n // Already migrated, or doesn't use this shape.\n continue;\n }\n if (!contents.includes(OLD_CAST_CLOSE)) {\n nextSteps.push(\n `${filePath}: the defaultIntegrationOptions cast has diverged from the generated shape - left untouched. Manually replace \\`<FunctionProps>{ ... }\\` with \\`{ ... } as FunctionProps\\`.`,\n );\n continue;\n }\n tree.write(\n filePath,\n contents\n .replace(OLD_CAST_OPEN, NEW_CAST_OPEN)\n .replace(OLD_CAST_CLOSE, NEW_CAST_CLOSE),\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["visitNotIgnoredFiles","formatFilesInSubtree","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","APIS_APP_DIR","OLD_CAST_OPEN","NEW_CAST_OPEN","OLD_CAST_CLOSE","NEW_CAST_CLOSE","migration","tree","nextSteps","exists","apiAppFiles","filePath","push","endsWith","contents","read","includes","write","replace"],"mappings":"AAAA;;;CAGC,GACD,SAGEA,oBAAoB,QACf,aAAa;AACpB,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAA6C;AAEpD;;;;;;;;;;;;;;;;;;;;;;CAsBC,GAED,MAAMC,eAAe,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,aAAa,CAAC;AAE5E,MAAME,gBAAgB;AACtB,MAAMC,gBAAgB;AACtB,MAAMC,iBAAiB;AACvB,MAAMC,iBACJ;AAEF,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,IAAI,CAACD,KAAKE,MAAM,CAACR,eAAe;QAC9B,OAAO;YAAEO;QAAU;IACrB;IAEA,MAAME,cAAwB,EAAE;IAChCb,qBAAqBU,MAAMN,cAAc,CAACU;QACxCD,YAAYE,IAAI,CAACD;IACnB;IAEA,KAAK,MAAMA,YAAYD,YAAa;QAClC,IAAI,CAACC,SAASE,QAAQ,CAAC,UAAUF,SAASE,QAAQ,CAAC,cAAc;YAC/D;QACF;QACA,MAAMC,WAAWP,KAAKQ,IAAI,CAACJ,UAAU,YAAY;QACjD,IAAI,CAACG,SAASE,QAAQ,CAACd,gBAAgB;YAErC;QACF;QACA,IAAI,CAACY,SAASE,QAAQ,CAACZ,iBAAiB;YACtCI,UAAUI,IAAI,CACZ,GAAGD,SAAS,2KAA2K,CAAC;YAE1L;QACF;QACAJ,KAAKU,KAAK,CACRN,UACAG,SACGI,OAAO,CAAChB,eAAeC,eACvBe,OAAO,CAACd,gBAAgBC;IAE/B;IAEA,MAAMP,qBAAqBS;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { MigrationReturnObject, Tree } from '@nx/devkit';\nimport {\n addDestructuredImport,\n applyGritQL,\n captureGritQL,\n matchGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Order the S3 server access log delivery source after the bucket policy.\n *\n * S3 rejects concurrent configuration writes against the same bucket with a 409\n * (OperationAborted). The generated StaticWebsite construct left the delivery\n * source and the bucket policy unordered, so CloudFormation could submit both at\n * once and fail the stack.\n */\n\nconst STATIC_WEBSITE_FILE = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/core/static-website.ts`;\n\nconst BUCKET_ARN_SUFFIX = '.bucketArn';\n\n/**\n * The bucket whose policy the delivery source must be ordered after is the one\n * the delivery source itself targets, so read it off `resourceArn` rather than\n * assuming the generated parameter name. Returns undefined unless exactly one\n * simple identifier is found, so a diverged helper is left alone.\n */\nconst findDeliverySourceBucket = async (\n tree: Tree,\n filePath: string,\n): Promise<string | undefined> => {\n const captured = await captureGritQL(\n tree,\n filePath,\n '`resourceArn: $bucket.bucketArn`',\n );\n if (!captured) return undefined;\n\n const bucket = captured\n .slice(captured.indexOf(':') + 1)\n .replace(BUCKET_ARN_SUFFIX, '')\n .trim();\n\n // Only a plain identifier can be cast and dereferenced safely in the\n // statement this migration writes.\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(bucket) ? bucket : undefined;\n};\n\n/**\n * Confirm the bucket the delivery source targets is declared as a parameter of\n * the enclosing helper, so the statement this migration writes references a\n * variable that is actually in scope.\n */\nconst isBucketDeclaredParameter = async (\n tree: Tree,\n filePath: string,\n bucket: string,\n): Promise<boolean> =>\n await matchGritQL(\n tree,\n filePath,\n `\\`private deliverAccessLogsToCloudWatch($params) { $_ }\\` where {\n $params <: contains \\`${bucket}: $bucketType\\`,\n $bucketType <: or { \\`IBucket\\`, \\`Bucket\\` }\n }`,\n );\n\n// Inserts the bucket policy dependency between the delivery source and the\n// delivery destination, matching the shape generators produced prior to this\n// fix. Anchored on the destination declaration so the source's own (multi-line,\n// Lazy-valued) arguments don't need to be matched.\nconst addDependencyPattern = (bucket: string) =>\n `\\`const $dest: CfnDeliveryDestination = new CfnDeliveryDestination($destArgs)\\` as $decl where {\n $dest <: \\`destination\\`\n} => \\`const bucketPolicy = (${bucket} as Bucket).policy;\n if (bucketPolicy) {\n source.node.addDependency(bucketPolicy);\n }\n $decl\\``;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (!tree.exists(STATIC_WEBSITE_FILE)) {\n // No vended StaticWebsite construct in this workspace - nothing to migrate.\n return { nextSteps };\n }\n\n const contents = tree.read(STATIC_WEBSITE_FILE, 'utf-8') ?? '';\n if (contents.includes('source.node.addDependency(bucketPolicy)')) {\n // Already migrated.\n return { nextSteps };\n }\n\n const divergedMessage = `${STATIC_WEBSITE_FILE}: deliverAccessLogsToCloudWatch has diverged from the generated shape - left untouched. Manually order the S3 server access log delivery source after the bucket policy of the bucket it targets (\\`source.node.addDependency(bucketPolicy)\\`), avoiding a 409 (OperationAborted) from concurrent bucket configuration writes.`;\n\n // The rewrite is anchored on the delivery destination but references the\n // `source` variable, so only apply it when the delivery source still has the\n // generated shape.\n const hasGeneratedSource = await matchGritQL(\n tree,\n STATIC_WEBSITE_FILE,\n '`const source: CfnDeliverySource = new CfnDeliverySource($_)`',\n );\n\n const bucket = hasGeneratedSource\n ? await findDeliverySourceBucket(tree, STATIC_WEBSITE_FILE)\n : undefined;\n\n if (\n !bucket ||\n !(await isBucketDeclaredParameter(tree, STATIC_WEBSITE_FILE, bucket))\n ) {\n nextSteps.push(divergedMessage);\n return { nextSteps };\n }\n\n const rewrote = await applyGritQL(\n tree,\n STATIC_WEBSITE_FILE,\n addDependencyPattern(bucket),\n );\n\n if (!rewrote) {\n nextSteps.push(divergedMessage);\n return { nextSteps };\n }\n\n // The inserted statement casts to the concrete Bucket to reach its policy,\n // which the helper's own `IBucket` parameter type does not expose.\n await addDestructuredImport(\n tree,\n STATIC_WEBSITE_FILE,\n ['Bucket'],\n 'aws-cdk-lib/aws-s3',\n );\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["addDestructuredImport","applyGritQL","captureGritQL","matchGritQL","formatFilesInSubtree","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","STATIC_WEBSITE_FILE","BUCKET_ARN_SUFFIX","findDeliverySourceBucket","tree","filePath","captured","undefined","bucket","slice","indexOf","replace","trim","test","isBucketDeclaredParameter","addDependencyPattern","migration","nextSteps","exists","contents","read","includes","divergedMessage","hasGeneratedSource","push","rewrote"],"mappings":"AAAA;;;CAGC,GAED,SACEA,qBAAqB,EACrBC,WAAW,EACXC,aAAa,EACbC,WAAW,QACN,wBAAqB;AAC5B,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAA6C;AAEpD;;;;;;;CAOC,GAED,MAAMC,sBAAsB,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,2BAA2B,CAAC;AAEjG,MAAME,oBAAoB;AAE1B;;;;;CAKC,GACD,MAAMC,2BAA2B,OAC/BC,MACAC;IAEA,MAAMC,WAAW,MAAMV,cACrBQ,MACAC,UACA;IAEF,IAAI,CAACC,UAAU,OAAOC;IAEtB,MAAMC,SAASF,SACZG,KAAK,CAACH,SAASI,OAAO,CAAC,OAAO,GAC9BC,OAAO,CAACT,mBAAmB,IAC3BU,IAAI;IAEP,qEAAqE;IACrE,mCAAmC;IACnC,OAAO,6BAA6BC,IAAI,CAACL,UAAUA,SAASD;AAC9D;AAEA;;;;CAIC,GACD,MAAMO,4BAA4B,OAChCV,MACAC,UACAG,SAEA,MAAMX,YACJO,MACAC,UACA,CAAC;4BACuB,EAAEG,OAAO;;KAEhC,CAAC;AAGN,2EAA2E;AAC3E,6EAA6E;AAC7E,gFAAgF;AAChF,mDAAmD;AACnD,MAAMO,uBAAuB,CAACP,SAC5B,CAAC;;6BAE0B,EAAEA,OAAO;;;;WAI3B,CAAC;AAEZ,eAAe,eAAeQ,UAC5BZ,IAAU;IAEV,MAAMa,YAAsB,EAAE;IAE9B,IAAI,CAACb,KAAKc,MAAM,CAACjB,sBAAsB;QACrC,4EAA4E;QAC5E,OAAO;YAAEgB;QAAU;IACrB;IAEA,MAAME,WAAWf,KAAKgB,IAAI,CAACnB,qBAAqB,YAAY;IAC5D,IAAIkB,SAASE,QAAQ,CAAC,4CAA4C;QAChE,oBAAoB;QACpB,OAAO;YAAEJ;QAAU;IACrB;IAEA,MAAMK,kBAAkB,GAAGrB,oBAAoB,8TAA8T,CAAC;IAE9W,yEAAyE;IACzE,6EAA6E;IAC7E,mBAAmB;IACnB,MAAMsB,qBAAqB,MAAM1B,YAC/BO,MACAH,qBACA;IAGF,MAAMO,SAASe,qBACX,MAAMpB,yBAAyBC,MAAMH,uBACrCM;IAEJ,IACE,CAACC,UACD,CAAE,MAAMM,0BAA0BV,MAAMH,qBAAqBO,SAC7D;QACAS,UAAUO,IAAI,CAACF;QACf,OAAO;YAAEL;QAAU;IACrB;IAEA,MAAMQ,UAAU,MAAM9B,YACpBS,MACAH,qBACAc,qBAAqBP;IAGvB,IAAI,CAACiB,SAAS;QACZR,UAAUO,IAAI,CAACF;QACf,OAAO;YAAEL;QAAU;IACrB;IAEA,2EAA2E;IAC3E,mEAAmE;IACnE,MAAMvB,sBACJU,MACAH,qBACA;QAAC;KAAS,EACV;IAGF,MAAMH,qBAAqBM;IAE3B,OAAO;QAAEa;IAAU;AACrB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/restrict-cors-to-custom-domains/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport {\n addDestructuredImport,\n addStarExport,\n applyGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { isEsmWorkspace } from '../../../utils/module-format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Include CloudFront custom domain aliases in restrictCorsTo and UserIdentity callback URLs\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, rather than\n * clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\nconst CORE_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/core`;\nconst APIS_APP_DIR = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/app/apis`;\nconst CLOUDFRONT_CORE_FILE = `${CORE_DIR}/cloudfront.ts`;\nconst CORE_INDEX_FILE = `${CORE_DIR}/index.ts`;\nconst USER_IDENTITY_FILE = `${CORE_DIR}/user-identity.ts`;\n\nconst CLOUDFRONT_HELPER_CONTENT = `import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';\n\n/**\n * Finds the domain names associated with a CloudFront distribution.\n *\n * Includes the distribution's default \\`*.cloudfront.net\\` domain name plus any custom\n * domain names (aliases) configured on it.\n */\nexport const findCloudFrontDomainNames = (\n distribution: Distribution,\n): string[] => {\n const cfnDistribution = distribution.node.defaultChild as CfnDistribution;\n const distributionConfig =\n cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;\n return [distribution.domainName, ...(distributionConfig.aliases ?? [])];\n};\n`;\n\n// Rewrites the `restrictCorsTo` body as produced by generators prior to this fix.\nconst RESTRICT_CORS_TO_GRITQL_PATTERN =\n \"`origins.map(($o) => typeof $o === 'string' ? $o : 'cloudFrontDistribution' in $o ? $branch1 : $branch2)` where { $branch1 <: contains `distributionDomainName`, $branch2 <: contains `distributionDomainName` } => raw`origins.flatMap(($o) => typeof $o === 'string' ? [$o] : findCloudFrontDomainNames('cloudFrontDistribution' in $o ? $o.cloudFrontDistribution : $o).map((domain) => \\\\`https://${domain}\\\\`))`\";\n\n// Rewrites UserIdentity's callback/logout URL logic as produced by generators\n// prior to this fix.\nconst USER_IDENTITY_CALLBACK_URLS_GRITQL_PATTERN =\n '`this.findCloudFrontDomainNames()` => `Stack.of(this).node.findAll().filter((child): child is Distribution => child instanceof Distribution).flatMap(findCloudFrontDomainNames)`';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (!tree.exists(CORE_INDEX_FILE)) {\n // No common/constructs shared library in this workspace - nothing to migrate.\n return { nextSteps };\n }\n\n const esm = isEsmWorkspace(tree);\n const apiCloudFrontImportSpecifier = esm\n ? '../../core/cloudfront.js'\n : '../../core/cloudfront';\n const coreCloudFrontImportSpecifier = esm\n ? './cloudfront.js'\n : './cloudfront';\n\n if (!tree.exists(CLOUDFRONT_CORE_FILE)) {\n tree.write(CLOUDFRONT_CORE_FILE, CLOUDFRONT_HELPER_CONTENT);\n }\n await addStarExport(tree, CORE_INDEX_FILE, './cloudfront.js');\n\n const apiAppFiles: string[] = [];\n visitNotIgnoredFiles(tree, APIS_APP_DIR, (filePath) => {\n apiAppFiles.push(filePath);\n });\n\n for (const filePath of apiAppFiles) {\n if (!filePath.endsWith('.ts') || filePath.endsWith('/index.ts')) {\n continue;\n }\n const rewrote = await applyGritQL(\n tree,\n filePath,\n RESTRICT_CORS_TO_GRITQL_PATTERN,\n );\n if (rewrote) {\n await addDestructuredImport(\n tree,\n filePath,\n ['findCloudFrontDomainNames'],\n apiCloudFrontImportSpecifier,\n );\n continue;\n }\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('findCloudFrontDomainNames(')) {\n nextSteps.push(\n `${filePath}: restrictCorsTo has diverged from the generated shape - left untouched. Manually apply the CloudFront custom domain fix (see findCloudFrontDomainNames in common/constructs/src/core/cloudfront.ts).`,\n );\n }\n // Otherwise already migrated - silent skip.\n }\n\n if (tree.exists(USER_IDENTITY_FILE)) {\n const rewrote = await applyGritQL(\n tree,\n USER_IDENTITY_FILE,\n USER_IDENTITY_CALLBACK_URLS_GRITQL_PATTERN,\n );\n if (rewrote) {\n await applyGritQL(\n tree,\n USER_IDENTITY_FILE,\n \"`import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront'` => `import { Distribution } from 'aws-cdk-lib/aws-cloudfront';`\",\n );\n await applyGritQL(\n tree,\n USER_IDENTITY_FILE,\n \"or { `// Includes each distribution's default domain name plus any custom domain names (aliases) configured on it.` => ., `private findCloudFrontDomainNames = (): string[] => $body` => . }\",\n );\n await addDestructuredImport(\n tree,\n USER_IDENTITY_FILE,\n ['findCloudFrontDomainNames'],\n coreCloudFrontImportSpecifier,\n );\n } else {\n const contents = tree.read(USER_IDENTITY_FILE, 'utf-8') ?? '';\n if (!contents.includes('.flatMap(findCloudFrontDomainNames)')) {\n nextSteps.push(\n `${USER_IDENTITY_FILE}: the callback URL logic has diverged from the generated shape - left untouched. Manually apply the shared findCloudFrontDomainNames helper (see common/constructs/src/core/cloudfront.ts).`,\n );\n }\n // Otherwise already migrated - silent skip.\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["visitNotIgnoredFiles","addDestructuredImport","addStarExport","applyGritQL","formatFilesInSubtree","isEsmWorkspace","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","CORE_DIR","APIS_APP_DIR","CLOUDFRONT_CORE_FILE","CORE_INDEX_FILE","USER_IDENTITY_FILE","CLOUDFRONT_HELPER_CONTENT","RESTRICT_CORS_TO_GRITQL_PATTERN","USER_IDENTITY_CALLBACK_URLS_GRITQL_PATTERN","migration","tree","nextSteps","exists","esm","apiCloudFrontImportSpecifier","coreCloudFrontImportSpecifier","write","apiAppFiles","filePath","push","endsWith","rewrote","contents","read","includes"],"mappings":"AAAA;;;CAGC,GACD,SAGEA,oBAAoB,QACf,aAAa;AACpB,SACEC,qBAAqB,EACrBC,aAAa,EACbC,WAAW,QACN,wBAAqB;AAC5B,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,cAAc,QAAQ,kCAA+B;AAC9D,SACEC,YAAY,EACZC,qBAAqB,QAChB,gDAA6C;AAEpD;;;;;;;;;;;;;;CAcC,GAED,MAAMC,WAAW,GAAGF,aAAa,CAAC,EAAEC,sBAAsB,SAAS,CAAC;AACpE,MAAME,eAAe,GAAGH,aAAa,CAAC,EAAEC,sBAAsB,aAAa,CAAC;AAC5E,MAAMG,uBAAuB,GAAGF,SAAS,cAAc,CAAC;AACxD,MAAMG,kBAAkB,GAAGH,SAAS,SAAS,CAAC;AAC9C,MAAMI,qBAAqB,GAAGJ,SAAS,iBAAiB,CAAC;AAEzD,MAAMK,4BAA4B,CAAC;;;;;;;;;;;;;;;;AAgBnC,CAAC;AAED,kFAAkF;AAClF,MAAMC,kCACJ;AAEF,8EAA8E;AAC9E,qBAAqB;AACrB,MAAMC,6CACJ;AAEF,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,IAAI,CAACD,KAAKE,MAAM,CAACR,kBAAkB;QACjC,8EAA8E;QAC9E,OAAO;YAAEO;QAAU;IACrB;IAEA,MAAME,MAAMf,eAAeY;IAC3B,MAAMI,+BAA+BD,MACjC,6BACA;IACJ,MAAME,gCAAgCF,MAClC,oBACA;IAEJ,IAAI,CAACH,KAAKE,MAAM,CAACT,uBAAuB;QACtCO,KAAKM,KAAK,CAACb,sBAAsBG;IACnC;IACA,MAAMX,cAAce,MAAMN,iBAAiB;IAE3C,MAAMa,cAAwB,EAAE;IAChCxB,qBAAqBiB,MAAMR,cAAc,CAACgB;QACxCD,YAAYE,IAAI,CAACD;IACnB;IAEA,KAAK,MAAMA,YAAYD,YAAa;QAClC,IAAI,CAACC,SAASE,QAAQ,CAAC,UAAUF,SAASE,QAAQ,CAAC,cAAc;YAC/D;QACF;QACA,MAAMC,UAAU,MAAMzB,YACpBc,MACAQ,UACAX;QAEF,IAAIc,SAAS;YACX,MAAM3B,sBACJgB,MACAQ,UACA;gBAAC;aAA4B,EAC7BJ;YAEF;QACF;QACA,MAAMQ,WAAWZ,KAAKa,IAAI,CAACL,UAAU,YAAY;QACjD,IAAI,CAACI,SAASE,QAAQ,CAAC,+BAA+B;YACpDb,UAAUQ,IAAI,CACZ,GAAGD,SAAS,qMAAqM,CAAC;QAEtN;IACA,4CAA4C;IAC9C;IAEA,IAAIR,KAAKE,MAAM,CAACP,qBAAqB;QACnC,MAAMgB,UAAU,MAAMzB,YACpBc,MACAL,oBACAG;QAEF,IAAIa,SAAS;YACX,MAAMzB,YACJc,MACAL,oBACA;YAEF,MAAMT,YACJc,MACAL,oBACA;YAEF,MAAMX,sBACJgB,MACAL,oBACA;gBAAC;aAA4B,EAC7BU;QAEJ,OAAO;YACL,MAAMO,WAAWZ,KAAKa,IAAI,CAAClB,oBAAoB,YAAY;YAC3D,IAAI,CAACiB,SAASE,QAAQ,CAAC,wCAAwC;gBAC7Db,UAAUQ,IAAI,CACZ,GAAGd,mBAAmB,2LAA2L,CAAC;YAEtN;QACA,4CAA4C;QAC9C;IACF;IAEA,MAAMR,qBAAqBa;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n} from '@nx/devkit';\nimport { TERRAFORM_PROJECT_GENERATOR_INFO } from '../../../terraform/project/generator';\nimport {\n applyGritQL,\n GRIT_INSERT_PLACEHOLDER,\n insertViaGritQL,\n matchGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\n\n/**\n * Adopt an existing Terraform state bucket in the vended bootstrap script when its state object is missing\n *\n * The state bucket stores its own tfstate inside itself, so if that object is\n * deleted while the bucket survives, `bootstrap` reads the 404 as a first run\n * and asks terraform to create a bucket that already exists — failing with\n * `BucketAlreadyOwnedByYou` on every subsequent run, with no retry that clears\n * it. The vended script now imports the existing bucket instead.\n *\n * Every edit is expressed as a GritQL rewrite so the script is matched on its\n * AST rather than its formatting.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, or consider a\n * hybrid migration, rather than clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\n// Guards the whole migration: present only once the import step exists.\nconst MIGRATED_PATTERN = '`bucketExists($_, $_)`';\n\n// Every edit site, matched structurally so formatting and argument layout\n// don't affect whether the script is recognised.\nconst STATE_FETCH_TRY_PATTERN =\n 'try_statement() as $try where { $try <: contains `GetObjectCommand` }';\nconst STATE_FLAG_SET_PATTERN = '`if (out.Body) { $body }`';\nconst HELPER_PATTERN = '`const main = async () => { $body }`';\nconst INIT_PATTERN = \"`execFileSync('terraform', ['init'], $opts)`\";\nconst S3_IMPORT_PATTERN =\n \"`import { $before, GetObjectCommand, $after } from '@aws-sdk/client-s3'`\";\nconst HEADER_COMMENT_PATTERN =\n 'comment() as $c where { $c <: includes \"state back to S3.\" }';\n\n// GritQL snippets are parsed as backtick-quoted patterns, so any backtick in\n// the inserted source has to survive that layer escaped.\nconst BUCKET_EXISTS_HELPER = `// S3 answers 404 only when the name is genuinely free; 403 means it exists\n// but is not readable with these credentials.\nconst bucketExists = async (s3: S3Client, bucket: string) => {\n try {\n await s3.send(new HeadBucketCommand({ Bucket: bucket }));\n return true;\n } catch (err: any) {\n const status = err?.$metadata?.httpStatusCode;\n if (status === 404) return false;\n if (status === 403) return true;\n throw err;\n }\n};`;\n\nconst IMPORT_STEP = `// The bucket holds its own state, so losing the state object while the\n // bucket survives would otherwise wedge bootstrap on a permanent\n // \\`BucketAlreadyOwnedByYou\\`. Adopt the existing bucket instead.\n if (!haveState && (await bucketExists(s3, bucket))) {\n console.log(\n \\`State bucket \\${bucket} already exists but its bootstrap state is missing — importing it.\\`,\n );\n execFileSync(\n 'terraform',\n [\n 'import',\n \\`-state=\\${tfStatePath}\\`,\n \\`-var=aws_region=\\${region}\\`,\n 'aws_s3_bucket.terraform_state',\n bucket,\n ],\n { cwd: bootstrapDir, stdio: 'inherit' },\n );\n }`;\n\n// Rewritten wholesale rather than appended to, since the summary sentence\n// changes rather than gaining a clause.\nconst NEW_HEADER_COMMENT = `/**\n * Bootstraps the remote Terraform state bucket.\n *\n * Equivalent to \\\\\\`cdk bootstrap\\\\\\` — resolves account + region from the AWS\n * SDK credential chain, pulls any existing bootstrap tfstate from S3,\n * runs \\\\\\`terraform apply\\\\\\` in the \\\\\\`bootstrap\\\\\\` dir, then pushes the new\n * state back to S3. Adopts an already-existing state bucket when its\n * state object is missing.\n */`;\n\nconst DIVERGED_NEXT_STEP = (filePath: string) =>\n `${filePath}: the bootstrap script has diverged from the generated shape - left untouched. Manually \\`terraform import aws_s3_bucket.terraform_state <bucket>\\` before \\`terraform apply\\` when the state bucket exists but its \\`bootstrap.tfstate\\` object does not, otherwise bootstrap fails with BucketAlreadyOwnedByYou.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n // Terraform application projects are the only ones that vend bootstrap.ts.\n const bootstrapScripts = [...getProjects(tree).values()]\n .filter(\n (project) =>\n (project.metadata as any)?.generator ===\n TERRAFORM_PROJECT_GENERATOR_INFO.id,\n )\n .map((project) => joinPathFragments(project.root, 'scripts/bootstrap.ts'))\n .filter((filePath) => tree.exists(filePath));\n\n for (const filePath of bootstrapScripts) {\n if (await matchGritQL(tree, filePath, MIGRATED_PATTERN)) {\n // Already migrated - silent skip keeps re-runs a no-op.\n continue;\n }\n\n // Confirm every edit site is present before writing any of them, so a\n // script that only partly matches is left whole rather than half-edited.\n const allSitesPresent = (\n await Promise.all(\n [\n STATE_FETCH_TRY_PATTERN,\n STATE_FLAG_SET_PATTERN,\n HELPER_PATTERN,\n INIT_PATTERN,\n S3_IMPORT_PATTERN,\n HEADER_COMMENT_PATTERN,\n ].map((pattern) => matchGritQL(tree, filePath, pattern)),\n )\n ).every(Boolean);\n\n if (!allSitesPresent) {\n nextSteps.push(DIVERGED_NEXT_STEP(filePath));\n continue;\n }\n\n // `haveState` distinguishes \"no remote state\" from \"no bucket\", so the\n // import only runs when terraform has no prior knowledge of the bucket.\n await insertViaGritQL(\n tree,\n filePath,\n `${STATE_FETCH_TRY_PATTERN} => \\`${GRIT_INSERT_PLACEHOLDER}\\n $try\\``,\n 'let haveState = false;',\n );\n await applyGritQL(\n tree,\n filePath,\n `${STATE_FLAG_SET_PATTERN} => \\`if (out.Body) {\\n $body\\n haveState = true;\\n }\\``,\n );\n await insertViaGritQL(\n tree,\n filePath,\n `${HELPER_PATTERN} => \\`${GRIT_INSERT_PLACEHOLDER}\\n\\nconst main = async () => { $body }\\``,\n BUCKET_EXISTS_HELPER,\n );\n await insertViaGritQL(\n tree,\n filePath,\n `${INIT_PATTERN} => \\`execFileSync('terraform', ['init'], $opts);\\n\\n ${GRIT_INSERT_PLACEHOLDER}\\n\\``,\n IMPORT_STEP,\n );\n\n // Placed in the generator's import position rather than appended, so a\n // migrated workspace matches a freshly generated one.\n await applyGritQL(\n tree,\n filePath,\n `${S3_IMPORT_PATTERN} => \\`import { $before, GetObjectCommand, HeadBucketCommand, $after } from '@aws-sdk/client-s3'\\``,\n );\n\n await applyGritQL(\n tree,\n filePath,\n `${HEADER_COMMENT_PATTERN} => \\`${NEW_HEADER_COMMENT}\\``,\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","TERRAFORM_PROJECT_GENERATOR_INFO","applyGritQL","GRIT_INSERT_PLACEHOLDER","insertViaGritQL","matchGritQL","formatFilesInSubtree","MIGRATED_PATTERN","STATE_FETCH_TRY_PATTERN","STATE_FLAG_SET_PATTERN","HELPER_PATTERN","INIT_PATTERN","S3_IMPORT_PATTERN","HEADER_COMMENT_PATTERN","BUCKET_EXISTS_HELPER","IMPORT_STEP","NEW_HEADER_COMMENT","DIVERGED_NEXT_STEP","filePath","migration","tree","nextSteps","bootstrapScripts","values","filter","project","metadata","generator","id","map","root","exists","allSitesPresent","Promise","all","pattern","every","Boolean","push"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,QAGZ,aAAa;AACpB,SAASC,gCAAgC,QAAQ,0CAAuC;AACxF,SACEC,WAAW,EACXC,uBAAuB,EACvBC,eAAe,EACfC,WAAW,QACN,wBAAqB;AAC5B,SAASC,oBAAoB,QAAQ,2BAAwB;AAE7D;;;;;;;;;;;;;;;;;;;;;;;CAuBC,GAED,wEAAwE;AACxE,MAAMC,mBAAmB;AAEzB,0EAA0E;AAC1E,iDAAiD;AACjD,MAAMC,0BACJ;AACF,MAAMC,yBAAyB;AAC/B,MAAMC,iBAAiB;AACvB,MAAMC,eAAe;AACrB,MAAMC,oBACJ;AACF,MAAMC,yBACJ;AAEF,6EAA6E;AAC7E,yDAAyD;AACzD,MAAMC,uBAAuB,CAAC;;;;;;;;;;;;EAY5B,CAAC;AAEH,MAAMC,cAAc,CAAC;;;;;;;;;;;;;;;;;;GAkBlB,CAAC;AAEJ,0EAA0E;AAC1E,wCAAwC;AACxC,MAAMC,qBAAqB,CAAC;;;;;;;;GAQzB,CAAC;AAEJ,MAAMC,qBAAqB,CAACC,WAC1B,GAAGA,SAAS,kTAAkT,CAAC;AAEjU,eAAe,eAAeC,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAE9B,2EAA2E;IAC3E,MAAMC,mBAAmB;WAAIvB,YAAYqB,MAAMG,MAAM;KAAG,CACrDC,MAAM,CACL,CAACC,UACC,AAACA,QAAQC,QAAQ,EAAUC,cAC3B1B,iCAAiC2B,EAAE,EAEtCC,GAAG,CAAC,CAACJ,UAAYzB,kBAAkByB,QAAQK,IAAI,EAAE,yBACjDN,MAAM,CAAC,CAACN,WAAaE,KAAKW,MAAM,CAACb;IAEpC,KAAK,MAAMA,YAAYI,iBAAkB;QACvC,IAAI,MAAMjB,YAAYe,MAAMF,UAAUX,mBAAmB;YAEvD;QACF;QAEA,sEAAsE;QACtE,yEAAyE;QACzE,MAAMyB,kBAAkB,AACtB,CAAA,MAAMC,QAAQC,GAAG,CACf;YACE1B;YACAC;YACAC;YACAC;YACAC;YACAC;SACD,CAACgB,GAAG,CAAC,CAACM,UAAY9B,YAAYe,MAAMF,UAAUiB,UACjD,EACAC,KAAK,CAACC;QAER,IAAI,CAACL,iBAAiB;YACpBX,UAAUiB,IAAI,CAACrB,mBAAmBC;YAClC;QACF;QAEA,uEAAuE;QACvE,wEAAwE;QACxE,MAAMd,gBACJgB,MACAF,UACA,GAAGV,wBAAwB,MAAM,EAAEL,wBAAwB,UAAU,CAAC,EACtE;QAEF,MAAMD,YACJkB,MACAF,UACA,GAAGT,uBAAuB,oEAAoE,CAAC;QAEjG,MAAML,gBACJgB,MACAF,UACA,GAAGR,eAAe,MAAM,EAAEP,wBAAwB,wCAAwC,CAAC,EAC3FW;QAEF,MAAMV,gBACJgB,MACAF,UACA,GAAGP,aAAa,uDAAuD,EAAER,wBAAwB,IAAI,CAAC,EACtGY;QAGF,uEAAuE;QACvE,sDAAsD;QACtD,MAAMb,YACJkB,MACAF,UACA,GAAGN,kBAAkB,iGAAiG,CAAC;QAGzH,MAAMV,YACJkB,MACAF,UACA,GAAGL,uBAAuB,MAAM,EAAEG,mBAAmB,EAAE,CAAC;IAE5D;IAEA,MAAMV,qBAAqBc;IAE3B,OAAO;QAAEC;IAAU;AACrB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/ts-agent-session-management-support/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type ProjectConfiguration,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport { TS_AGENT_GENERATOR_INFO } from '../../../ts/agent/generator';\nimport { AGENT_CONNECTION_PROJECT_DIR } from '../../../utils/agent-connection/agent-connection';\nimport {\n applyGritQL,\n captureGritQLVariable,\n matchGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { isEsmWorkspace } from '../../../utils/module-format';\nimport { kebabCase } from '../../../utils/names';\nimport type { ComponentMetadata } from '../../../utils/nx';\nimport {\n getRelativePathToRootByDirectory,\n toProjectRelativePath,\n} from '../../../utils/paths';\n\n/**\n * Add session management support to ts#agent.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, or consider a\n * hybrid migration, rather than clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\n// Reshapes an `agentRuntimes` rc.set entry from a bare ARN to `{ arn }`. Only\n// the 'agentcore' namespace — 'connection' (client-facing) stays a string,\n// since it shouldn't carry the session bucket name to the browser. No\n// `session` field added here; a fresh session.ts (created below) defaults to\n// in-memory. Idempotent: only matches the pre-migration shape.\nconst CDK_RC_SET_PATTERN = `\\`rc.set('agentcore', 'agentRuntimes', { ...rc.get('agentcore').agentRuntimes, $name: this.agentCoreRuntime.agentRuntimeArn });\\` => raw\\`rc.set('agentcore', 'agentRuntimes', {\n ...rc.get('agentcore').agentRuntimes,\n $name: {\n arn: this.agentCoreRuntime.agentRuntimeArn,\n },\n});\\``;\n\n// Terraform equivalent, anchored on the module's fixed name/shape so it\n// doesn't also match the 'connection' module's identical-looking `value` line.\nconst TF_VALUE_PATTERN = `language hcl\\n\\`module \"add_agent_runtime_to_runtime_config\" {\n source = \"../../../core/runtime-config/entry\"\n\n namespace = \"agentcore\"\n key = \"agentRuntimes\"\n value = { \"$name\" = module.agent_core_runtime.agent_core_runtime_arn }\n\n depends_on = [module.agent_core_runtime]\n}\\` => \\`module \"add_agent_runtime_to_runtime_config\" {\n source = \"../../../core/runtime-config/entry\"\n\n namespace = \"agentcore\"\n key = \"agentRuntimes\"\n value = { \"$name\" = { arn = module.agent_core_runtime.agent_core_runtime_arn } }\n\n depends_on = [module.agent_core_runtime]\n}\\``;\n\n// Shared `AgentCoreRuntimeConfig` interface, vended into\n// `packages/common/agent-connection/src/core/runtime-config.ts`.\nconst TS_RUNTIME_CONFIG_INTERFACE_PATTERN = `\\`export interface AgentCoreRuntimeConfig {\n agentRuntimes?: Record<string, string>;\n gateways?: Record<string, string>;\n}\\` => raw\\`export interface AgentRuntimeEntry {\n arn: string;\n /** Session storage details. Only set when the agent has S3 session storage configured. */\n session?: {\n /** Name of the S3 bucket storing session data. */\n bucketName: string;\n };\n}\n\nexport interface AgentCoreRuntimeConfig {\n agentRuntimes?: Record<string, AgentRuntimeEntry>;\n gateways?: Record<string, string>;\n}\\``;\n\n// `config.agentRuntimes?.['Name']` as read by generated TS a2a/mcp clients and\n// the agent-chat CLI. Idempotent via the `not contains ?.arn` guard.\nconst TS_CLIENT_ARN_PATTERNS = [\n '`config.agentRuntimes?.[$name]` => `config.agentRuntimes?.[$name]?.arn` where { $program <: not contains `config.agentRuntimes?.[$name]?.arn` }',\n '`config?.agentRuntimes?.[$name]` => `config?.agentRuntimes?.[$name]?.arn` where { $program <: not contains `config?.agentRuntimes?.[$name]?.arn` }',\n];\n\n// The agent-chat CLI's agentcore.ts calls `getAppConfig` directly rather than\n// the shared `AgentCoreRuntimeConfig` type, so its own inline cast needs the\n// same { arn } reshape TS_RUNTIME_CONFIG_INTERFACE_PATTERN gives the shared\n// interface.\nconst AGENTCORE_CHAT_SCRIPT_TYPE_PATTERN =\n '`{ agentRuntimes?: Record<string, string> }` => `{ agentRuntimes?: Record<string, { arn: string }> }`';\n\n// Python equivalent (Strands + LangChain client templates).\nconst PY_CLIENT_ARN_PATTERN =\n 'language python\\n`agent_runtime_arn = config.get(\"agentRuntimes\", {}).get($name)` => `agent_runtime = config.get(\"agentRuntimes\", {}).get($name)\\nagent_runtime_arn = agent_runtime.get(\"arn\") if agent_runtime else None`';\n\n// Removes the imperative logModelErrors(agent)/logToolErrors(agent) calls.\n// Required for AG-UI (its adapter clones the template agent per-thread, and\n// hooks added directly to the template don't carry over — the equivalent\n// behaviour is restored via the AGUI_INDEX_* plugins below). For HTTP/A2A\n// it's a style unification, since the imperative form already worked there.\nconst AGENT_TS_LOG_MODEL_CALL_PATTERN = '`logModelErrors(agent);` => .';\nconst AGENT_TS_LOG_TOOL_CALL_PATTERN = '`logToolErrors(agent);` => .';\n\n// HTTP/A2A agents build one Agent per session, so wiring `sessionManager`\n// directly into the constructor is safe. Generic over `$props` so this works\n// regardless of customised systemPrompt/tools, as long as it's an inline\n// object literal. Prepended (not appended) to sidestep a trailing-comma\n// double-comma when `$props` is captured as raw source text.\nconst AGENT_TS_SESSION_MANAGER_CONSTRUCTOR_PATTERN =\n '`new Agent({ $props })` => `new Agent({ sessionManager: await getSessionManager(), $props })` where { $props <: not contains `sessionManager` }';\n\n// Match-only gate for the rewrites above/below: only applies when the Agent\n// is an inline object literal, not e.g. a variable.\nconst AGENT_TS_CONSTRUCTOR_MATCH_PATTERN = '`new Agent({ $props })`';\n\n// Moves the model/tool error hooks to Agent constructor plugins, mirroring\n// the AG-UI rewrite for consistency (HTTP/A2A already worked with the\n// imperative form).\nconst AGENT_TS_PLUGINS_CONSTRUCTOR_PATTERN =\n '`new Agent({ $props })` => `new Agent({ plugins: [new ModelErrorLoggingPlugin(), new ToolErrorLoggingPlugin()], $props })` where { $props <: not contains `plugins` }';\n\n// Captures the agent-connection package specifier so the new imports (and the\n// session.ts this migration creates) target the same module. Generic over\n// `$names` since a connection generator may have merged its own import here.\nconst AGENT_TS_LOG_IMPORT_CAPTURE_PATTERN =\n \"`import { $names } from '$mod';` where { $names <: contains `logModelErrors`, $names <: contains `logToolErrors` }\";\n\n// Removes `logModelErrors`/`logToolErrors` from the import, preserving any\n// other merged specifiers (or the whole statement if none remain). Decomposed\n// via `import_clause(name=named_imports($imports))` since a naive\n// `$rest`-based rewrite silently fails once 2+ other specifiers are merged in.\nconst AGENT_TS_REMOVE_LOG_ERRORS_IMPORT_PATTERN =\n \"`import $clause from '$mod';` as $import where { $clause <: import_clause(name=named_imports($imports)), $imports <: contains `logModelErrors`, $imports <: contains `logToolErrors`, if ($imports <: [`logModelErrors`, `logToolErrors`]) { $import => . } else { $imports <: some import_specifier(name=or { `logModelErrors`, `logToolErrors` }) => . } }\";\n\n// Existing agents predate session.ts, so there's no prior storage to\n// preserve — default to in-memory.\nconst legacySessionManagerContent = (\n agentConnectionModule: string,\n localSessionsDir: string,\n): string => `import { SessionManager } from '@strands-agents/sdk';\nimport { InMemoryStorage, LocalFileStorage } from '@strands-agents/sdk/storage';\nimport { getCurrentSessionId } from '${agentConnectionModule}';\n\n/**\n * Returns a SessionManager for persisting conversation state across\n * invocations. Local development always uses local file storage for\n * convenience, regardless of the configured session option. Without a\n * configured session option, conversation state is kept in memory only and\n * does not survive process restarts.\n */\nexport const getSessionManager = async (): Promise<SessionManager> => {\n const sessionId = getCurrentSessionId();\n if (!sessionId) {\n throw new Error(\n 'No current session id — cannot resolve a SessionManager outside of a request scope.',\n );\n }\n if (process.env.LOCAL_DEV === 'true') {\n return new SessionManager({\n sessionId,\n storage: new LocalFileStorage('${localSessionsDir}'),\n });\n }\n return new SessionManager({ sessionId, storage: new InMemoryStorage() });\n};\n`;\n\n/** The Nx project owning `dirPath`, if any (the longest-matching project.root). */\nconst findOwningProject = (\n tree: Tree,\n dirPath: string,\n): ProjectConfiguration | undefined => {\n let best: ProjectConfiguration | undefined;\n for (const project of getProjects(tree).values()) {\n if (\n (dirPath === project.root || dirPath.startsWith(`${project.root}/`)) &&\n (!best || project.root.length > best.root.length)\n ) {\n best = project;\n }\n }\n return best;\n};\n\n/** This agent's own ComponentMetadata entry, as written by the ts#agent generator. */\nconst findAgentComponentMetadata = (\n project: ProjectConfiguration,\n dirRelativeToProjectRoot: string,\n): ComponentMetadata | undefined =>\n (project.metadata as { components?: ComponentMetadata[] })?.components?.find(\n (component) =>\n component.generator === TS_AGENT_GENERATOR_INFO.id &&\n component.path === dirRelativeToProjectRoot,\n );\n\n/** This agent's real kebab-case name, from ComponentMetadata's `rc` (class-name) field. */\nconst agentTmpNameFor = (\n project: ProjectConfiguration,\n dir: string,\n): string | undefined => {\n const dirRelativeToProjectRoot = toProjectRelativePath(project, dir);\n const rc = findAgentComponentMetadata(project, dirRelativeToProjectRoot)?.rc;\n return rc ? kebabCase(rc) : undefined;\n};\n\n/** This agent's protocol, from ComponentMetadata's `protocol` field. */\nconst agentProtocolFor = (\n project: ProjectConfiguration,\n dir: string,\n): string | undefined => {\n const dirRelativeToProjectRoot = toProjectRelativePath(project, dir);\n return findAgentComponentMetadata(project, dirRelativeToProjectRoot)\n ?.protocol;\n};\n\n/** The relative path from `projectRoot` up to this agent's workspace-root-level local session storage. */\nconst localSessionsDirFor = (\n projectRoot: string,\n agentTmpName: string,\n): string =>\n joinPathFragments(\n getRelativePathToRootByDirectory(projectRoot),\n `tmp/agents/strands/${agentTmpName}`,\n );\n\n// Wires ModelErrorLoggingPlugin/ToolErrorLoggingPlugin into the StrandsAgent\n// constructor, restoring the error-logging behaviour removed from agent.ts.\nconst AGUI_INDEX_IMPORT_PATTERN =\n \"`import { $names } from '$mod'` => `import { ModelErrorLoggingPlugin, ToolErrorLoggingPlugin, $names } from '$mod'` where { $names <: contains `runWithSessionId`, $names <: not contains `ModelErrorLoggingPlugin` }\";\n// Match-only form of the target shape, used to gate before touching the\n// sibling agent.ts, and before committing to the rewrite here.\nconst AGUI_INDEX_CONSTRUCTOR_MATCH_PATTERN =\n '`new StrandsAgent({ agent, name: $name, description: $desc })`';\nconst AGUI_INDEX_CONSTRUCTOR_PATTERN = `${AGUI_INDEX_CONSTRUCTOR_MATCH_PATTERN} => \\`new StrandsAgent({ agent, name: $name, description: $desc, plugins: [new ModelErrorLoggingPlugin(), new ToolErrorLoggingPlugin()] })\\``;\n\nconst AGUI_INDEX_IMPORT_CAPTURE_PATTERN =\n \"`import { $names } from '$mod';` where { $names <: contains `runWithSessionId` }\";\n\n// AG-UI's StrandsAgent adapter needs a sessionManagerProvider (called once\n// per threadId), mirroring AGENT_TS_SESSION_MANAGER_CONSTRUCTOR_PATTERN.\nconst aguiIndexSessionManagerImportPattern = (esm: boolean) =>\n `\\`import { getAgent } from '$mod';\\` => raw\\`import { getAgent } from '$mod';\nimport { getSessionManager } from './session${esm ? '.js' : ''}';\\` where { $program <: not contains \\`getSessionManager\\` }`;\n// Anchored on the exact 4-property shape produced above, so this only fires\n// once plugins are wired in. Used both to gate and to rewrite.\nconst AGUI_INDEX_SESSION_MANAGER_MATCH_PATTERN =\n '`new StrandsAgent({ agent, name: $name, description: $desc, plugins: $plugins })`';\nconst AGUI_INDEX_SESSION_MANAGER_CONSTRUCTOR_PATTERN = `${AGUI_INDEX_SESSION_MANAGER_MATCH_PATTERN} => \\`new StrandsAgent({ agent, name: $name, description: $desc, plugins: $plugins, config: { sessionManagerProvider: getSessionManager } })\\``;\n\n// The plugin classes referenced above only exist once model-errors-strands.ts\n// / tool-errors-strands.ts are converted from their plain logXErrors function\n// form (see checkPluginClass/applyPluginClass below). Anchored on the\n// `agent.addHook(...)` call so this doesn't re-match its own output.\nconst MODEL_ERRORS_IMPORT_PATTERN =\n \"`import { AfterModelCallEvent, type LocalAgent } from '@strands-agents/sdk';` => `import { AfterModelCallEvent, type LocalAgent, type Plugin } from '@strands-agents/sdk';`\";\n// Match-only form of the target shape, checked before committing to either\n// this or the sibling tool-errors conversion — see checkPluginClass.\nconst MODEL_ERRORS_CLASS_MATCH_PATTERN =\n '`export const logModelErrors = (agent: LocalAgent): void => { agent.addHook(AfterModelCallEvent, $callback); };`';\nconst MODEL_ERRORS_CLASS_PATTERN = `${MODEL_ERRORS_CLASS_MATCH_PATTERN} => raw\\`export class ModelErrorLoggingPlugin implements Plugin {\\n readonly name = 'model-error-logging';\\n\\n initAgent(agent: LocalAgent): void {\\n agent.addHook(AfterModelCallEvent, $callback);\\n }\\n}\\``;\n\nconst TOOL_ERRORS_IMPORT_PATTERN =\n \"`import { AfterToolCallEvent, type LocalAgent, TextBlock } from '@strands-agents/sdk';` => `import { AfterToolCallEvent, type LocalAgent, type Plugin, TextBlock } from '@strands-agents/sdk';`\";\nconst TOOL_ERRORS_CLASS_MATCH_PATTERN =\n '`export const logToolErrors = (agent: LocalAgent): void => { agent.addHook(AfterToolCallEvent, $callback); };`';\nconst TOOL_ERRORS_CLASS_PATTERN = `${TOOL_ERRORS_CLASS_MATCH_PATTERN} => raw\\`export class ToolErrorLoggingPlugin implements Plugin {\\n readonly name = 'tool-error-logging';\\n\\n initAgent(agent: LocalAgent): void {\\n agent.addHook(AfterToolCallEvent, $callback);\\n }\\n}\\``;\n\ntype PluginClassStatus = 'ready' | 'done' | 'diverged';\n\n/**\n * Checks (without writing) whether `filePath` still needs converting from its\n * plain `logXErrors` function to `className`, and whether the conversion\n * pattern would actually apply. `'done'` covers both \"already converted\" and\n * \"file doesn't exist\" — either way there's nothing to do and nothing\n * blocking the sibling conversion.\n */\nasync function checkPluginClass(\n tree: Tree,\n filePath: string,\n className: string,\n classMatchPattern: string,\n): Promise<PluginClassStatus> {\n if (!tree.exists(filePath)) {\n return 'done';\n }\n if ((tree.read(filePath, 'utf-8') ?? '').includes(`class ${className}`)) {\n return 'done';\n }\n return (await matchGritQL(tree, filePath, classMatchPattern))\n ? 'ready'\n : 'diverged';\n}\n\n/** Applies the class + import rewrite for a file already confirmed `'ready'`. */\nasync function applyPluginClass(\n tree: Tree,\n filePath: string,\n importPattern: string,\n classPattern: string,\n): Promise<void> {\n // The class rewrite is applied first, and the import only added once it's\n // confirmed to have actually happened here — not because either could fail\n // at this point (checkPluginClass already confirmed the pattern matches),\n // but to keep this file's own edit order self-evidently safe to read.\n await applyGritQL(tree, filePath, classPattern);\n await applyGritQL(tree, filePath, importPattern);\n}\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n let anyChanges = false;\n\n // Both classes live in one shared agent-connection package, so their\n // readiness is resolved once up front rather than per agent.\n const modelErrorsPath = joinPathFragments(\n AGENT_CONNECTION_PROJECT_DIR,\n 'src',\n 'core',\n 'model-errors-strands.ts',\n );\n const toolErrorsPath = joinPathFragments(\n AGENT_CONNECTION_PROJECT_DIR,\n 'src',\n 'core',\n 'tool-errors-strands.ts',\n );\n // Checked together, before writing either: all-or-nothing, so a run either\n // converts both or leaves both untouched — never just one.\n const modelPluginStatus = await checkPluginClass(\n tree,\n modelErrorsPath,\n 'ModelErrorLoggingPlugin',\n MODEL_ERRORS_CLASS_MATCH_PATTERN,\n );\n const toolPluginStatus = await checkPluginClass(\n tree,\n toolErrorsPath,\n 'ToolErrorLoggingPlugin',\n TOOL_ERRORS_CLASS_MATCH_PATTERN,\n );\n const pluginsReady =\n modelPluginStatus !== 'diverged' && toolPluginStatus !== 'diverged';\n\n if (pluginsReady) {\n if (modelPluginStatus === 'ready') {\n await applyPluginClass(\n tree,\n modelErrorsPath,\n MODEL_ERRORS_IMPORT_PATTERN,\n MODEL_ERRORS_CLASS_PATTERN,\n );\n }\n if (toolPluginStatus === 'ready') {\n await applyPluginClass(\n tree,\n toolErrorsPath,\n TOOL_ERRORS_IMPORT_PATTERN,\n TOOL_ERRORS_CLASS_PATTERN,\n );\n }\n } else {\n if (modelPluginStatus === 'diverged') {\n nextSteps.push(\n `${modelErrorsPath}: diverged from the generated shape - left as-is. Manually convert it to a \\`ModelErrorLoggingPlugin\\` class implementing \\`Plugin\\` (see the ts#agent generator's template); agent.ts/index.ts files that reference it are left unmigrated until both this and ${toolErrorsPath} are converted.`,\n );\n }\n if (toolPluginStatus === 'diverged') {\n nextSteps.push(\n `${toolErrorsPath}: diverged from the generated shape - left as-is. Manually convert it to a \\`ToolErrorLoggingPlugin\\` class implementing \\`Plugin\\` (see the ts#agent generator's template); agent.ts/index.ts files that reference it are left unmigrated until both this and ${modelErrorsPath} are converted.`,\n );\n }\n }\n\n const filePaths: string[] = [];\n visitNotIgnoredFiles(tree, '', (filePath) => filePaths.push(filePath));\n\n for (const filePath of filePaths) {\n if (filePath === modelErrorsPath || filePath === toolErrorsPath) {\n continue;\n }\n if (filePath.endsWith('.d.ts')) {\n continue;\n }\n\n // session.ts already targets the new { arn, session } shape via\n // `config.agentRuntimes?.[$name]?.session?.bucketName` — the generic\n // reshape branch below would otherwise corrupt that into `?.arn?.session?.bucketName`.\n if (filePath.endsWith('/session.ts')) {\n continue;\n }\n\n if (filePath.endsWith('/agent.ts')) {\n const dir = filePath.split('/').slice(0, -1).join('/');\n const project = findOwningProject(tree, dir);\n\n // Without a registered project there's no ComponentMetadata, so this\n // agent's protocol/name/agent-connection module can't be resolved — and\n // a pre-migration AG-UI agent.ts is textually identical to an\n // HTTP/A2A one, so there's nothing left to safely guess from.\n if (!project) {\n if (\n await matchGritQL(tree, filePath, AGENT_TS_LOG_IMPORT_CAPTURE_PATTERN)\n ) {\n nextSteps.push(\n `${filePath}: could not determine the project root — manually verify whether this is an AG-UI or HTTP/A2A agent and complete its session-manager/error-logging-plugin migration accordingly (see the ts#agent generator's template).`,\n );\n }\n continue;\n }\n\n const protocol = agentProtocolFor(project, dir);\n\n if (protocol === 'ag-ui') {\n const hasLogCalls =\n (await matchGritQL(\n tree,\n filePath,\n AGENT_TS_LOG_MODEL_CALL_PATTERN,\n )) ||\n (await matchGritQL(tree, filePath, AGENT_TS_LOG_TOOL_CALL_PATTERN));\n if (!hasLogCalls) {\n continue;\n }\n\n // The sibling index.ts restores error-logging via StrandsAgent\n // plugins — removing the calls here without that succeeding would\n // drop error logging rather than move it.\n const indexPath = `${dir}/index.ts`;\n const indexReady =\n pluginsReady &&\n (await matchGritQL(\n tree,\n indexPath,\n AGUI_INDEX_CONSTRUCTOR_MATCH_PATTERN,\n ));\n\n if (!indexReady) {\n nextSteps.push(\n `${filePath}: left the logModelErrors/logToolErrors calls in place — ${indexPath} could not be automatically wired with the equivalent StrandsAgent plugins. Move error logging to plugins there manually (see the ts#agent generator's template), then remove these calls.`,\n );\n continue;\n }\n\n const rewroteImport = await applyGritQL(\n tree,\n filePath,\n AGENT_TS_REMOVE_LOG_ERRORS_IMPORT_PATTERN,\n );\n const rewroteModelCall = await applyGritQL(\n tree,\n filePath,\n AGENT_TS_LOG_MODEL_CALL_PATTERN,\n );\n const rewroteToolCall = await applyGritQL(\n tree,\n filePath,\n AGENT_TS_LOG_TOOL_CALL_PATTERN,\n );\n if (rewroteImport || rewroteModelCall || rewroteToolCall) {\n anyChanges = true;\n }\n continue;\n }\n\n if (!protocol) {\n if (\n await matchGritQL(tree, filePath, AGENT_TS_LOG_IMPORT_CAPTURE_PATTERN)\n ) {\n nextSteps.push(\n `${filePath}: could not determine this agent's protocol from its ComponentMetadata — manually verify whether it's AG-UI or HTTP/A2A and wire sessionManager/the error-logging plugins in accordingly (see the ts#agent generator's template).`,\n );\n }\n continue;\n }\n\n // HTTP/A2A: wire sessionManager into the Agent constructor and create\n // the sibling session.ts if it doesn't exist yet.\n if (\n !(await matchGritQL(\n tree,\n filePath,\n AGENT_TS_LOG_IMPORT_CAPTURE_PATTERN,\n ))\n ) {\n continue;\n }\n\n const sessionPath = `${dir}/session.ts`;\n\n // Checked before any writes: if the plugin classes aren't available, or\n // the Agent isn't an inline object literal, leave the file untouched\n // entirely rather than ending up half-migrated.\n if (!pluginsReady) {\n nextSteps.push(\n `${filePath}: left as-is — ModelErrorLoggingPlugin/ToolErrorLoggingPlugin are not available yet (see the model-errors-strands.ts/tool-errors-strands.ts next step above). Wire sessionManager and the plugins in manually once those classes exist.`,\n );\n continue;\n }\n if (\n !(await matchGritQL(tree, filePath, AGENT_TS_CONSTRUCTOR_MATCH_PATTERN))\n ) {\n nextSteps.push(\n `${filePath}: the Agent is not constructed with an inline object literal (\\`new Agent({ ... })\\`), so sessionManager and the error-logging plugins could not be wired in automatically. Manually add \\`sessionManager: await getSessionManager()\\` and \\`plugins: [new ModelErrorLoggingPlugin(), new ToolErrorLoggingPlugin()]\\` to its constructor (see the ts#agent generator's template), creating ${sessionPath} first if it doesn't already exist.`,\n );\n continue;\n }\n\n if (!tree.exists(sessionPath)) {\n const mod = await captureGritQLVariable(\n tree,\n filePath,\n AGENT_TS_LOG_IMPORT_CAPTURE_PATTERN,\n 'mod',\n );\n const agentName = agentTmpNameFor(project, dir);\n\n if (mod && agentName) {\n tree.write(\n sessionPath,\n legacySessionManagerContent(\n mod,\n localSessionsDirFor(project.root, agentName),\n ),\n );\n } else {\n nextSteps.push(\n `${filePath}: could not determine the agent-connection module or this agent's name from its ComponentMetadata — manually create a session.ts (see the ts#agent generator's template) and wire \\`sessionManager: await getSessionManager()\\` into the Agent constructor.`,\n );\n continue;\n }\n }\n\n // Merges the plugin imports into the existing logModelErrors/\n // logToolErrors import clause (rather than a redundant second import),\n // and adds getSessionManager as its own line. The old specifiers are\n // stripped separately below, after this rewrite anchors on them.\n const esm = isEsmWorkspace(tree);\n await applyGritQL(\n tree,\n filePath,\n `\\`import { $names } from '$mod';\\` => raw\\`import { ModelErrorLoggingPlugin, ToolErrorLoggingPlugin, $names } from '$mod';\nimport { getSessionManager } from './session${esm ? '.js' : ''}';\\` where { $names <: contains \\`logModelErrors\\`, $names <: contains \\`logToolErrors\\`, $program <: not contains \\`getSessionManager\\` }`,\n );\n\n // Only rewrite the constructor once the import is confirmed present.\n if (!(tree.read(filePath, 'utf-8') ?? '').includes('getSessionManager')) {\n nextSteps.push(\n `${filePath}: found ${sessionPath} but couldn't confirm the getSessionManager import — wire \\`sessionManager: await getSessionManager()\\` into the Agent constructor manually.`,\n );\n continue;\n }\n\n await applyGritQL(tree, filePath, AGENT_TS_LOG_MODEL_CALL_PATTERN);\n await applyGritQL(tree, filePath, AGENT_TS_LOG_TOOL_CALL_PATTERN);\n await applyGritQL(\n tree,\n filePath,\n AGENT_TS_REMOVE_LOG_ERRORS_IMPORT_PATTERN,\n );\n\n const rewrotePlugins = await applyGritQL(\n tree,\n filePath,\n AGENT_TS_PLUGINS_CONSTRUCTOR_PATTERN,\n );\n const rewroteConstructor = await applyGritQL(\n tree,\n filePath,\n AGENT_TS_SESSION_MANAGER_CONSTRUCTOR_PATTERN,\n );\n if (rewrotePlugins || rewroteConstructor) {\n anyChanges = true;\n }\n continue;\n }\n\n if (\n filePath.endsWith('/index.ts') &&\n (tree.read(filePath, 'utf-8') ?? '').includes('@ag-ui/aws-strands')\n ) {\n const alreadyWired = (tree.read(filePath, 'utf-8') ?? '').includes(\n 'ModelErrorLoggingPlugin',\n );\n\n if (!alreadyWired) {\n // Import and constructor only apply cleanly together — adding the\n // import while the constructor can't be rewritten would leave an\n // unused import and no plugins wired in.\n const needsPluginWiring = await matchGritQL(\n tree,\n filePath,\n AGUI_INDEX_CONSTRUCTOR_MATCH_PATTERN,\n );\n if (!pluginsReady) {\n if (needsPluginWiring) {\n nextSteps.push(\n `${filePath}: left the StrandsAgent constructor as-is — ModelErrorLoggingPlugin/ToolErrorLoggingPlugin are not available yet (see the model-errors-strands.ts/tool-errors-strands.ts next step above). Wire them in manually once those classes exist.`,\n );\n }\n continue;\n }\n if (!needsPluginWiring) {\n nextSteps.push(\n `${filePath}: the StrandsAgent constructor has diverged from the generated shape - left as-is. Manually add \\`plugins: [new ModelErrorLoggingPlugin(), new ToolErrorLoggingPlugin()]\\` to it (see the ts#agent generator's template).`,\n );\n continue;\n }\n\n const rewroteImport = await applyGritQL(\n tree,\n filePath,\n AGUI_INDEX_IMPORT_PATTERN,\n );\n const rewroteConstructor = await applyGritQL(\n tree,\n filePath,\n AGUI_INDEX_CONSTRUCTOR_PATTERN,\n );\n if (rewroteImport || rewroteConstructor) {\n anyChanges = true;\n }\n }\n\n // Create the sibling session.ts (once plugins are present) and wire in\n // sessionManagerProvider. Gated on the exact post-plugins shape, so a\n // customised constructor is left alone rather than creating an unused\n // session.ts.\n if (\n !(await matchGritQL(\n tree,\n filePath,\n AGUI_INDEX_SESSION_MANAGER_MATCH_PATTERN,\n ))\n ) {\n continue;\n }\n\n const dir = filePath.split('/').slice(0, -1).join('/');\n const sessionPath = `${dir}/session.ts`;\n\n if (!tree.exists(sessionPath)) {\n const project = findOwningProject(tree, dir);\n const mod = await captureGritQLVariable(\n tree,\n filePath,\n AGUI_INDEX_IMPORT_CAPTURE_PATTERN,\n 'mod',\n );\n const agentName = project && agentTmpNameFor(project, dir);\n\n if (project && mod && agentName) {\n tree.write(\n sessionPath,\n legacySessionManagerContent(\n mod,\n localSessionsDirFor(project.root, agentName),\n ),\n );\n } else {\n nextSteps.push(\n `${filePath}: could not determine the project root, agent-connection module, or this agent's name from its ComponentMetadata — manually create a session.ts (see the ts#agent generator's template) and wire \\`config: { sessionManagerProvider: getSessionManager }\\` into the StrandsAgent constructor.`,\n );\n continue;\n }\n }\n\n const esm = isEsmWorkspace(tree);\n await applyGritQL(\n tree,\n filePath,\n aguiIndexSessionManagerImportPattern(esm),\n );\n\n if (!(tree.read(filePath, 'utf-8') ?? '').includes('getSessionManager')) {\n nextSteps.push(\n `${filePath}: found ${sessionPath} but couldn't confirm the getSessionManager import — wire \\`config: { sessionManagerProvider: getSessionManager }\\` into the StrandsAgent constructor manually.`,\n );\n continue;\n }\n\n const rewroteSessionManagerConstructor = await applyGritQL(\n tree,\n filePath,\n AGUI_INDEX_SESSION_MANAGER_CONSTRUCTOR_PATTERN,\n );\n if (rewroteSessionManagerConstructor) {\n anyChanges = true;\n }\n continue;\n }\n\n if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('agentRuntimes')) {\n continue;\n }\n // Only the 'agentcore' namespace is reshaped — see CDK_RC_SET_PATTERN.\n const rewroteAgentcoreRcSet = await applyGritQL(\n tree,\n filePath,\n CDK_RC_SET_PATTERN,\n );\n const rewroteInterface = await applyGritQL(\n tree,\n filePath,\n TS_RUNTIME_CONFIG_INTERFACE_PATTERN,\n );\n let rewroteClientArn = false;\n for (const pattern of TS_CLIENT_ARN_PATTERNS) {\n rewroteClientArn = (await applyGritQL(tree, filePath, pattern))\n ? true\n : rewroteClientArn;\n }\n const rewroteChatScriptType = await applyGritQL(\n tree,\n filePath,\n AGENTCORE_CHAT_SCRIPT_TYPE_PATTERN,\n );\n\n if (\n rewroteAgentcoreRcSet ||\n rewroteInterface ||\n rewroteClientArn ||\n rewroteChatScriptType\n ) {\n anyChanges = true;\n }\n } else if (filePath.endsWith('.tf')) {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('\"agentRuntimes\"')) {\n continue;\n }\n const rewrote = await applyGritQL(tree, filePath, TF_VALUE_PATTERN);\n if (rewrote) {\n anyChanges = true;\n }\n } else if (filePath.endsWith('.py')) {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('agentRuntimes')) {\n continue;\n }\n const rewrote = await applyGritQL(tree, filePath, PY_CLIENT_ARN_PATTERN);\n if (rewrote) {\n anyChanges = true;\n }\n }\n }\n\n if (anyChanges) {\n nextSteps.push(\n 'If you have custom code reading the runtime config `agentcore.agentRuntimes` entries ' +\n 'as plain ARN strings (e.g. custom Lambda handlers or agent code), update it to read ' +\n 'the ARN from `.arn` on the new `{ arn }` shape.',\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","visitNotIgnoredFiles","TS_AGENT_GENERATOR_INFO","AGENT_CONNECTION_PROJECT_DIR","applyGritQL","captureGritQLVariable","matchGritQL","formatFilesInSubtree","isEsmWorkspace","kebabCase","getRelativePathToRootByDirectory","toProjectRelativePath","CDK_RC_SET_PATTERN","TF_VALUE_PATTERN","TS_RUNTIME_CONFIG_INTERFACE_PATTERN","TS_CLIENT_ARN_PATTERNS","AGENTCORE_CHAT_SCRIPT_TYPE_PATTERN","PY_CLIENT_ARN_PATTERN","AGENT_TS_LOG_MODEL_CALL_PATTERN","AGENT_TS_LOG_TOOL_CALL_PATTERN","AGENT_TS_SESSION_MANAGER_CONSTRUCTOR_PATTERN","AGENT_TS_CONSTRUCTOR_MATCH_PATTERN","AGENT_TS_PLUGINS_CONSTRUCTOR_PATTERN","AGENT_TS_LOG_IMPORT_CAPTURE_PATTERN","AGENT_TS_REMOVE_LOG_ERRORS_IMPORT_PATTERN","legacySessionManagerContent","agentConnectionModule","localSessionsDir","findOwningProject","tree","dirPath","best","project","values","root","startsWith","length","findAgentComponentMetadata","dirRelativeToProjectRoot","metadata","components","find","component","generator","id","path","agentTmpNameFor","dir","rc","undefined","agentProtocolFor","protocol","localSessionsDirFor","projectRoot","agentTmpName","AGUI_INDEX_IMPORT_PATTERN","AGUI_INDEX_CONSTRUCTOR_MATCH_PATTERN","AGUI_INDEX_CONSTRUCTOR_PATTERN","AGUI_INDEX_IMPORT_CAPTURE_PATTERN","aguiIndexSessionManagerImportPattern","esm","AGUI_INDEX_SESSION_MANAGER_MATCH_PATTERN","AGUI_INDEX_SESSION_MANAGER_CONSTRUCTOR_PATTERN","MODEL_ERRORS_IMPORT_PATTERN","MODEL_ERRORS_CLASS_MATCH_PATTERN","MODEL_ERRORS_CLASS_PATTERN","TOOL_ERRORS_IMPORT_PATTERN","TOOL_ERRORS_CLASS_MATCH_PATTERN","TOOL_ERRORS_CLASS_PATTERN","checkPluginClass","filePath","className","classMatchPattern","exists","read","includes","applyPluginClass","importPattern","classPattern","migration","nextSteps","anyChanges","modelErrorsPath","toolErrorsPath","modelPluginStatus","toolPluginStatus","pluginsReady","push","filePaths","endsWith","split","slice","join","hasLogCalls","indexPath","indexReady","rewroteImport","rewroteModelCall","rewroteToolCall","sessionPath","mod","agentName","write","rewrotePlugins","rewroteConstructor","alreadyWired","needsPluginWiring","rewroteSessionManagerConstructor","contents","rewroteAgentcoreRcSet","rewroteInterface","rewroteClientArn","pattern","rewroteChatScriptType","rewrote"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { MigrationReturnObject, Tree } from '@nx/devkit';\nimport { applyGritQL, matchGritQL } from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../../../utils/shared-constructs-constants';\n\n/**\n * Count the EC2MetaDataSSRF_QUERYARGUMENTS WAF rule on the UserIdentity Web ACL\n *\n * `AWSManagedRulesCommonRuleSet` treats the loopback `redirect_uri` the Cognito\n * Hosted UI receives during local sign-in as an SSRF attempt, so sign-in against\n * a local dev server fails with an opaque 403 before the login page renders. The\n * rule is overridden to Count while a local callback URL is allowed; every other\n * rule in the group still blocks.\n *\n * The local callback URLs are lifted into a named constant so the override can be\n * derived from them rather than restating the condition.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Pattern-match before writing: skip files that have diverged from the shape\n * your generators produce and report them via `nextSteps`, rather than\n * clobbering the user's changes.\n * - Idempotent: re-running must be a no-op.\n * - Format what you write: finish with `formatFilesInSubtree` so the files your\n * migration wrote are formatted correctly.\n */\n\nconst CDK_USER_IDENTITY_FILE = `${PACKAGES_DIR}/${SHARED_CONSTRUCTS_DIR}/src/core/user-identity.ts`;\nconst TERRAFORM_IDENTITY_FILE = `${PACKAGES_DIR}/${SHARED_TERRAFORM_DIR}/src/core/user-identity/identity/identity.tf`;\n\nconst SSRF_RULE_NAME = 'EC2MetaDataSSRF_QUERYARGUMENTS';\n\n// Guards each file: present only once the override has been added.\nconst CDK_MIGRATED_PATTERN = `\\`ruleActionOverrides: allowsLocalCallback ? $_ : undefined\\``;\nconst TERRAFORM_MIGRATED_PATTERN = `language hcl\\n\\`name = \"${SSRF_RULE_NAME}\"\\``;\n\n// Every CDK edit site, matched structurally so formatting doesn't affect whether\n// the construct is recognised.\nconst CDK_CONSTANT_ANCHOR_PATTERN = \"`const WEB_CLIENT_ID = 'WebClient'`\";\n// Scoped to the `.concat` callsite so it can't also rewrite the array literal\n// inside the constant this migration inserts.\nconst CDK_LOCAL_URLS_PATTERN =\n \"`['http://localhost:4200', 'http://localhost:4300'].concat($rest)`\";\nconst CDK_CALL_PATTERN = '`this.createWebAcl($id, this.userPool)`';\nconst CDK_SIGNATURE_PATTERN =\n '`private createWebAcl = ($id: string, $pool: UserPool) => $body`';\nconst CDK_STATEMENT_PATTERN =\n \"`managedRuleGroupStatement: { name: 'AWSManagedRulesCommonRuleSet', vendorName: 'AWS' }`\";\n\nconst CDK_EDITS: Array<[string, string]> = [\n // Local callback URLs become a named constant the override can key off.\n [\n CDK_CONSTANT_ANCHOR_PATTERN,\n `${CDK_CONSTANT_ANCHOR_PATTERN} => \\`const WEB_CLIENT_ID = 'WebClient';\n\n/** Local dev server origins permitted to complete the sign-in redirect */\nconst LOCAL_CALLBACK_URLS = ['http://localhost:4200', 'http://localhost:4300']\\``,\n ],\n [\n CDK_LOCAL_URLS_PATTERN,\n `${CDK_LOCAL_URLS_PATTERN} => \\`LOCAL_CALLBACK_URLS.concat($rest)\\``,\n ],\n [\n CDK_CALL_PATTERN,\n `${CDK_CALL_PATTERN} => \\`this.createWebAcl($id, this.userPool, LOCAL_CALLBACK_URLS.length > 0)\\``,\n ],\n [\n CDK_SIGNATURE_PATTERN,\n `${CDK_SIGNATURE_PATTERN} => \\`private createWebAcl = (\n $id: string,\n $pool: UserPool,\n allowsLocalCallback: boolean\n ) => $body\\``,\n ],\n [\n CDK_STATEMENT_PATTERN,\n `${CDK_STATEMENT_PATTERN} => \\`managedRuleGroupStatement: {\n name: 'AWSManagedRulesCommonRuleSet',\n vendorName: 'AWS',\n // ${SSRF_RULE_NAME} treats the loopback redirect_uri the\n // Hosted UI receives during local sign-in as an SSRF attempt. Counted\n // only while a local callback URL is allowed; every other rule blocks.\n ruleActionOverrides: allowsLocalCallback\n ? [\n {\n name: '${SSRF_RULE_NAME}',\n actionToUse: { count: {} },\n },\n ]\n : undefined,\n }\\``,\n ],\n];\n\nconst TERRAFORM_DATA_SOURCES_PATTERN = [\n 'language hcl',\n '`data \"aws_region\" \"current\" {}`',\n].join('\\n');\n\nconst TERRAFORM_EDITS: Array<[string, string]> = [\n // Local callback URLs become a local the override can key off.\n [\n TERRAFORM_DATA_SOURCES_PATTERN,\n [\n 'language hcl',\n '`data \"aws_region\" \"current\" {}` => `data \"aws_region\" \"current\" {}',\n '',\n 'locals {',\n ' # Local dev server origins permitted to complete the sign-in redirect',\n ' local_callback_urls = [',\n ' \"http://localhost:4200\",',\n ' \"http://localhost:4300\"',\n ' ]',\n '}`',\n ].join('\\n'),\n ],\n [\n [\n 'language hcl',\n '`callback_urls = concat([',\n ' \"http://localhost:4200\",',\n ' \"http://localhost:4300\"',\n ' ], var.callback_urls)`',\n ].join('\\n'),\n [\n 'language hcl',\n '`callback_urls = concat([',\n ' \"http://localhost:4200\",',\n ' \"http://localhost:4300\"',\n ' ], var.callback_urls)` => `callback_urls = concat(local.local_callback_urls, var.callback_urls)`',\n ].join('\\n'),\n ],\n [\n [\n 'language hcl',\n '`logout_urls = concat([',\n ' \"http://localhost:4200\",',\n ' \"http://localhost:4300\"',\n ' ], var.logout_urls)`',\n ].join('\\n'),\n [\n 'language hcl',\n '`logout_urls = concat([',\n ' \"http://localhost:4200\",',\n ' \"http://localhost:4300\"',\n ' ], var.logout_urls)` => `logout_urls = concat(local.local_callback_urls, var.logout_urls)`',\n ].join('\\n'),\n ],\n [\n [\n 'language hcl',\n '`managed_rule_group_statement {',\n ' name = \"AWSManagedRulesCommonRuleSet\"',\n ' vendor_name = \"AWS\"',\n ' }`',\n ].join('\\n'),\n [\n 'language hcl',\n '`managed_rule_group_statement {',\n ' name = \"AWSManagedRulesCommonRuleSet\"',\n ' vendor_name = \"AWS\"',\n ' }` => `managed_rule_group_statement {',\n ' name = \"AWSManagedRulesCommonRuleSet\"',\n ' vendor_name = \"AWS\"',\n '',\n ` # ${SSRF_RULE_NAME} treats the loopback redirect_uri the`,\n ' # Hosted UI receives during local sign-in as an SSRF attempt. Counted',\n ' # only while a local callback URL is allowed; every other rule blocks.',\n ' dynamic \"rule_action_override\" {',\n ' for_each = length(local.local_callback_urls) > 0 ? [1] : []',\n '',\n ' content {',\n ` name = \"${SSRF_RULE_NAME}\"`,\n '',\n ' action_to_use {',\n ' count {}',\n ' }',\n ' }',\n ' }',\n ' }`',\n ].join('\\n'),\n ],\n];\n\nconst divergedNextStep = (filePath: string) =>\n `${filePath}: the UserIdentity Web ACL has diverged from the generated shape - left untouched. To sign in against a local dev server, override ${SSRF_RULE_NAME} in the AWSManagedRulesCommonRuleSet rule group to Count, otherwise the Cognito Hosted UI returns 403 for localhost redirect URIs.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n for (const [filePath, migratedPattern, edits] of [\n [CDK_USER_IDENTITY_FILE, CDK_MIGRATED_PATTERN, CDK_EDITS],\n [TERRAFORM_IDENTITY_FILE, TERRAFORM_MIGRATED_PATTERN, TERRAFORM_EDITS],\n ] as const) {\n if (!tree.exists(filePath)) {\n // This workspace doesn't use this IaC provider, or has no UserIdentity.\n continue;\n }\n\n if (await matchGritQL(tree, filePath, migratedPattern)) {\n // Already migrated - silent skip keeps re-runs a no-op.\n continue;\n }\n\n // Confirm every edit site is present before writing any of them, so a file\n // that only partly matches is left whole rather than half-edited.\n const allSitesPresent = (\n await Promise.all(\n edits.map(([match]) => matchGritQL(tree, filePath, match)),\n )\n ).every(Boolean);\n\n if (!allSitesPresent) {\n nextSteps.push(divergedNextStep(filePath));\n continue;\n }\n\n for (const [, rewrite] of edits) {\n await applyGritQL(tree, filePath, rewrite);\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["applyGritQL","matchGritQL","formatFilesInSubtree","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","CDK_USER_IDENTITY_FILE","TERRAFORM_IDENTITY_FILE","SSRF_RULE_NAME","CDK_MIGRATED_PATTERN","TERRAFORM_MIGRATED_PATTERN","CDK_CONSTANT_ANCHOR_PATTERN","CDK_LOCAL_URLS_PATTERN","CDK_CALL_PATTERN","CDK_SIGNATURE_PATTERN","CDK_STATEMENT_PATTERN","CDK_EDITS","TERRAFORM_DATA_SOURCES_PATTERN","join","TERRAFORM_EDITS","divergedNextStep","filePath","migration","tree","nextSteps","migratedPattern","edits","exists","allSitesPresent","Promise","all","map","match","every","Boolean","push","rewrite"],"mappings":"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"}