@aws/nx-plugin 1.0.0-rc.97 → 1.0.0
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.
- package/LICENSE-THIRD-PARTY +9 -9
- package/migrations.json +125 -115
- package/package.json +3 -3
- package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +4 -4
- package/src/infra/app/generator.js +5 -2
- package/src/infra/app/generator.js.map +1 -1
- package/src/internal/test-matrix/generator.js +2 -2
- package/src/internal/test-matrix/generator.js.map +1 -1
- package/src/license/sync/generator.d.ts +10 -0
- package/src/license/sync/generator.js +1 -1
- package/src/license/sync/generator.js.map +1 -1
- package/src/migrations/latest/sandbox-pattern-nested-stacks/metadata.json +3 -0
- package/src/migrations/latest/sandbox-pattern-nested-stacks/migration.js +68 -0
- package/src/migrations/latest/sandbox-pattern-nested-stacks/migration.js.map +1 -0
- package/src/migrations/latest/shadcn-cn-package/metadata.json +3 -0
- package/src/migrations/latest/shadcn-cn-package/migration.js +114 -0
- package/src/migrations/latest/shadcn-cn-package/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0001-dev-target-depends-on-pull-image/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0002-open-api-codegen-executor/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0003-terraform-provider-plugin-cache/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0004-python-test-input-scoping/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0005-vitest-coverage-output-dir/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0006-add-assemble-target/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0007-docker-target-cache-soundness/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0008-declare-cacheable-target-inputs/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.90/0009-terraform-fmt-check/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.92/0001-react-website-unique-dev-ports/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.94/0001-infra-deploy-express-mode/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.94/0002-shx-fs-commands/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.94/0003-agent-core-vendor-target/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.95/0001-rolldown-config-bundle-transient/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.95/0002-agent-connection-pin-strands-peers/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.95/0003-ignore-package-manager-temp-files/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.95/0004-shadcn-package-imports-exports/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.97/0001-gateway-url-accessor/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.97/0002-checkov-scan-cache-inputs/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.97/0003-terraform-validate-without-backend/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.97/0004-py-lambda-powertools-context/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.97/0004-py-lambda-powertools-context/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.97/0005-smithy-extension-trait-aliases/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.97/0006-script-project-quality-gates/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.97/0006-script-project-quality-gates/migration.js.map +1 -0
- package/src/preset/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +2 -2
- package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +4 -4
- package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +4 -4
- package/src/py/agent/a2a-connection/generator.d.ts +1 -1
- package/src/py/agent/gateway-connection/generator.d.ts +1 -1
- package/src/py/agent/mcp-connection/generator.d.ts +1 -1
- package/src/py/agent/react-connection/generator.d.ts +1 -7
- package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +12 -12
- package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/smithy/project/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +8 -8
- package/src/terraform/project/schema.d.js +0 -3
- package/src/terraform/project/schema.d.js.map +1 -1
- package/src/terraform/project/schema.d.ts +0 -4
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +12 -12
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +4 -4
- package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/agent/react-connection/generator.d.ts +1 -9
- package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +47 -2
- package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +6 -6
- package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/mcp-server/files/app/http.ts.template +1 -1
- package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/nx-generator/files/local/generator.spec.ts.template +2 -2
- package/src/ts/nx-migration/generator.js +3 -1
- package/src/ts/nx-migration/generator.js.map +1 -1
- package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +1 -25
- package/src/ts/nx-plugin/generator.js +19 -17
- package/src/ts/nx-plugin/generator.js.map +1 -1
- package/src/ts/nx-plugin/utils.d.ts +21 -0
- package/src/ts/nx-plugin/utils.js +41 -1
- package/src/ts/nx-plugin/utils.js.map +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +10 -10
- package/src/ts/react-website/agui/generator.d.ts +1 -5
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +26 -26
- package/src/ts/react-website/app/generator.d.ts +1 -5
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -2
- package/src/utils/ast.js +55 -16
- package/src/utils/ast.js.map +1 -1
- package/src/utils/dependencies.d.ts +10 -0
- package/src/utils/dependencies.js +93 -1
- package/src/utils/dependencies.js.map +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/alert.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/avatar.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/breadcrumb.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/button.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/card.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/input.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/separator.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/sheet.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/sidebar.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/skeleton.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/spinner.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/textarea.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/components/ui/tooltip.tsx.template +1 -2
- package/src/utils/files/common/shadcn/src/lib/utils.ts.template +1 -6
- package/src/utils/shared-shadcn.d.ts +1 -3
- package/src/utils/shared-shadcn.js +1 -4
- package/src/utils/shared-shadcn.js.map +1 -1
- package/src/utils/versions.d.ts +52 -53
- package/src/utils/versions.js +51 -52
- package/src/utils/versions.js.map +1 -1
- package/src/migrations/latest/add-assemble-target/migration.js.map +0 -1
- package/src/migrations/latest/agent-connection-pin-strands-peers/migration.js.map +0 -1
- package/src/migrations/latest/agent-core-vendor-target/migration.js.map +0 -1
- package/src/migrations/latest/checkov-scan-cache-inputs/migration.js.map +0 -1
- package/src/migrations/latest/declare-cacheable-target-inputs/migration.js.map +0 -1
- package/src/migrations/latest/dev-target-depends-on-pull-image/migration.js.map +0 -1
- package/src/migrations/latest/docker-target-cache-soundness/migration.js.map +0 -1
- package/src/migrations/latest/gateway-url-accessor/migration.js.map +0 -1
- package/src/migrations/latest/ignore-package-manager-temp-files/migration.js.map +0 -1
- package/src/migrations/latest/infra-deploy-express-mode/migration.js.map +0 -1
- package/src/migrations/latest/open-api-codegen-executor/migration.js.map +0 -1
- package/src/migrations/latest/py-lambda-powertools-context/migration.js.map +0 -1
- package/src/migrations/latest/python-test-input-scoping/migration.js.map +0 -1
- package/src/migrations/latest/react-website-unique-dev-ports/migration.js.map +0 -1
- package/src/migrations/latest/rolldown-config-bundle-transient/migration.js.map +0 -1
- package/src/migrations/latest/script-project-quality-gates/migration.js.map +0 -1
- package/src/migrations/latest/shadcn-package-imports-exports/migration.js.map +0 -1
- package/src/migrations/latest/shx-fs-commands/migration.js.map +0 -1
- package/src/migrations/latest/smithy-extension-trait-aliases/migration.js.map +0 -1
- package/src/migrations/latest/terraform-fmt-check/migration.js.map +0 -1
- package/src/migrations/latest/terraform-provider-plugin-cache/migration.js.map +0 -1
- package/src/migrations/latest/terraform-validate-without-backend/migration.js.map +0 -1
- package/src/migrations/latest/vitest-coverage-output-dir/migration.js.map +0 -1
- /package/src/migrations/latest/{add-assemble-target → sandbox-pattern-nested-stacks}/migration.d.ts +0 -0
- /package/src/migrations/latest/{agent-core-vendor-target → shadcn-cn-package}/migration.d.ts +0 -0
- /package/src/migrations/{latest/dev-target-depends-on-pull-image → v1.0.0-rc.90/0001-dev-target-depends-on-pull-image}/metadata.json +0 -0
- /package/src/migrations/{latest/checkov-scan-cache-inputs → v1.0.0-rc.90/0001-dev-target-depends-on-pull-image}/migration.d.ts +0 -0
- /package/src/migrations/{latest/dev-target-depends-on-pull-image → v1.0.0-rc.90/0001-dev-target-depends-on-pull-image}/migration.js +0 -0
- /package/src/migrations/{latest/open-api-codegen-executor → v1.0.0-rc.90/0002-open-api-codegen-executor}/metadata.json +0 -0
- /package/src/migrations/{latest/declare-cacheable-target-inputs → v1.0.0-rc.90/0002-open-api-codegen-executor}/migration.d.ts +0 -0
- /package/src/migrations/{latest/open-api-codegen-executor → v1.0.0-rc.90/0002-open-api-codegen-executor}/migration.js +0 -0
- /package/src/migrations/{latest/terraform-provider-plugin-cache → v1.0.0-rc.90/0003-terraform-provider-plugin-cache}/metadata.json +0 -0
- /package/src/migrations/{latest/dev-target-depends-on-pull-image → v1.0.0-rc.90/0003-terraform-provider-plugin-cache}/migration.d.ts +0 -0
- /package/src/migrations/{latest/terraform-provider-plugin-cache → v1.0.0-rc.90/0003-terraform-provider-plugin-cache}/migration.js +0 -0
- /package/src/migrations/{latest/python-test-input-scoping → v1.0.0-rc.90/0004-python-test-input-scoping}/metadata.json +0 -0
- /package/src/migrations/{latest/docker-target-cache-soundness → v1.0.0-rc.90/0004-python-test-input-scoping}/migration.d.ts +0 -0
- /package/src/migrations/{latest/python-test-input-scoping → v1.0.0-rc.90/0004-python-test-input-scoping}/migration.js +0 -0
- /package/src/migrations/{latest/vitest-coverage-output-dir → v1.0.0-rc.90/0005-vitest-coverage-output-dir}/metadata.json +0 -0
- /package/src/migrations/{latest/infra-deploy-express-mode → v1.0.0-rc.90/0005-vitest-coverage-output-dir}/migration.d.ts +0 -0
- /package/src/migrations/{latest/vitest-coverage-output-dir → v1.0.0-rc.90/0005-vitest-coverage-output-dir}/migration.js +0 -0
- /package/src/migrations/{latest/add-assemble-target → v1.0.0-rc.90/0006-add-assemble-target}/metadata.json +0 -0
- /package/src/migrations/{latest/open-api-codegen-executor → v1.0.0-rc.90/0006-add-assemble-target}/migration.d.ts +0 -0
- /package/src/migrations/{latest/add-assemble-target → v1.0.0-rc.90/0006-add-assemble-target}/migration.js +0 -0
- /package/src/migrations/{latest/docker-target-cache-soundness → v1.0.0-rc.90/0007-docker-target-cache-soundness}/metadata.json +0 -0
- /package/src/migrations/{latest/py-lambda-powertools-context → v1.0.0-rc.90/0007-docker-target-cache-soundness}/migration.d.ts +0 -0
- /package/src/migrations/{latest/docker-target-cache-soundness → v1.0.0-rc.90/0007-docker-target-cache-soundness}/migration.js +0 -0
- /package/src/migrations/{latest/declare-cacheable-target-inputs → v1.0.0-rc.90/0008-declare-cacheable-target-inputs}/metadata.json +0 -0
- /package/src/migrations/{latest/python-test-input-scoping → v1.0.0-rc.90/0008-declare-cacheable-target-inputs}/migration.d.ts +0 -0
- /package/src/migrations/{latest/declare-cacheable-target-inputs → v1.0.0-rc.90/0008-declare-cacheable-target-inputs}/migration.js +0 -0
- /package/src/migrations/{latest/terraform-fmt-check → v1.0.0-rc.90/0009-terraform-fmt-check}/metadata.json +0 -0
- /package/src/migrations/{latest/react-website-unique-dev-ports → v1.0.0-rc.90/0009-terraform-fmt-check}/migration.d.ts +0 -0
- /package/src/migrations/{latest/terraform-fmt-check → v1.0.0-rc.90/0009-terraform-fmt-check}/migration.js +0 -0
- /package/src/migrations/{latest/react-website-unique-dev-ports → v1.0.0-rc.92/0001-react-website-unique-dev-ports}/metadata.json +0 -0
- /package/src/migrations/{latest/rolldown-config-bundle-transient → v1.0.0-rc.92/0001-react-website-unique-dev-ports}/migration.d.ts +0 -0
- /package/src/migrations/{latest/react-website-unique-dev-ports → v1.0.0-rc.92/0001-react-website-unique-dev-ports}/migration.js +0 -0
- /package/src/migrations/{latest/infra-deploy-express-mode → v1.0.0-rc.94/0001-infra-deploy-express-mode}/metadata.json +0 -0
- /package/src/migrations/{latest/script-project-quality-gates → v1.0.0-rc.94/0001-infra-deploy-express-mode}/migration.d.ts +0 -0
- /package/src/migrations/{latest/infra-deploy-express-mode → v1.0.0-rc.94/0001-infra-deploy-express-mode}/migration.js +0 -0
- /package/src/migrations/{latest/shx-fs-commands → v1.0.0-rc.94/0002-shx-fs-commands}/metadata.json +0 -0
- /package/src/migrations/{latest/shadcn-package-imports-exports → v1.0.0-rc.94/0002-shx-fs-commands}/migration.d.ts +0 -0
- /package/src/migrations/{latest/shx-fs-commands → v1.0.0-rc.94/0002-shx-fs-commands}/migration.js +0 -0
- /package/src/migrations/{latest/agent-core-vendor-target → v1.0.0-rc.94/0003-agent-core-vendor-target}/metadata.json +0 -0
- /package/src/migrations/{latest/shx-fs-commands → v1.0.0-rc.94/0003-agent-core-vendor-target}/migration.d.ts +0 -0
- /package/src/migrations/{latest/agent-core-vendor-target → v1.0.0-rc.94/0003-agent-core-vendor-target}/migration.js +0 -0
- /package/src/migrations/{latest/rolldown-config-bundle-transient → v1.0.0-rc.95/0001-rolldown-config-bundle-transient}/metadata.json +0 -0
- /package/src/migrations/{latest/terraform-fmt-check → v1.0.0-rc.95/0001-rolldown-config-bundle-transient}/migration.d.ts +0 -0
- /package/src/migrations/{latest/rolldown-config-bundle-transient → v1.0.0-rc.95/0001-rolldown-config-bundle-transient}/migration.js +0 -0
- /package/src/migrations/{latest/agent-connection-pin-strands-peers → v1.0.0-rc.95/0002-agent-connection-pin-strands-peers}/metadata.json +0 -0
- /package/src/migrations/{latest/agent-connection-pin-strands-peers → v1.0.0-rc.95/0002-agent-connection-pin-strands-peers}/migration.d.ts +0 -0
- /package/src/migrations/{latest/agent-connection-pin-strands-peers → v1.0.0-rc.95/0002-agent-connection-pin-strands-peers}/migration.js +0 -0
- /package/src/migrations/{latest/ignore-package-manager-temp-files → v1.0.0-rc.95/0003-ignore-package-manager-temp-files}/metadata.json +0 -0
- /package/src/migrations/{latest/ignore-package-manager-temp-files → v1.0.0-rc.95/0003-ignore-package-manager-temp-files}/migration.d.ts +0 -0
- /package/src/migrations/{latest/ignore-package-manager-temp-files → v1.0.0-rc.95/0003-ignore-package-manager-temp-files}/migration.js +0 -0
- /package/src/migrations/{latest/shadcn-package-imports-exports → v1.0.0-rc.95/0004-shadcn-package-imports-exports}/metadata.json +0 -0
- /package/src/migrations/{latest/terraform-provider-plugin-cache → v1.0.0-rc.95/0004-shadcn-package-imports-exports}/migration.d.ts +0 -0
- /package/src/migrations/{latest/shadcn-package-imports-exports → v1.0.0-rc.95/0004-shadcn-package-imports-exports}/migration.js +0 -0
- /package/src/migrations/{latest/gateway-url-accessor → v1.0.0-rc.97/0001-gateway-url-accessor}/__snapshots__/migration.spec.ts.snap +0 -0
- /package/src/migrations/{latest/gateway-url-accessor → v1.0.0-rc.97/0001-gateway-url-accessor}/metadata.json +0 -0
- /package/src/migrations/{latest/gateway-url-accessor → v1.0.0-rc.97/0001-gateway-url-accessor}/migration.d.ts +0 -0
- /package/src/migrations/{latest/gateway-url-accessor → v1.0.0-rc.97/0001-gateway-url-accessor}/migration.js +0 -0
- /package/src/migrations/{latest/checkov-scan-cache-inputs → v1.0.0-rc.97/0002-checkov-scan-cache-inputs}/metadata.json +0 -0
- /package/src/migrations/{latest/terraform-validate-without-backend → v1.0.0-rc.97/0002-checkov-scan-cache-inputs}/migration.d.ts +0 -0
- /package/src/migrations/{latest/checkov-scan-cache-inputs → v1.0.0-rc.97/0002-checkov-scan-cache-inputs}/migration.js +0 -0
- /package/src/migrations/{latest/terraform-validate-without-backend → v1.0.0-rc.97/0003-terraform-validate-without-backend}/metadata.json +0 -0
- /package/src/migrations/{latest/vitest-coverage-output-dir → v1.0.0-rc.97/0003-terraform-validate-without-backend}/migration.d.ts +0 -0
- /package/src/migrations/{latest/terraform-validate-without-backend → v1.0.0-rc.97/0003-terraform-validate-without-backend}/migration.js +0 -0
- /package/src/migrations/{latest/py-lambda-powertools-context → v1.0.0-rc.97/0004-py-lambda-powertools-context}/metadata.json +0 -0
- /package/src/migrations/{latest/py-lambda-powertools-context → v1.0.0-rc.97/0004-py-lambda-powertools-context}/migration.js +0 -0
- /package/src/migrations/{latest/smithy-extension-trait-aliases → v1.0.0-rc.97/0005-smithy-extension-trait-aliases}/__snapshots__/migration.spec.ts.snap +0 -0
- /package/src/migrations/{latest/smithy-extension-trait-aliases → v1.0.0-rc.97/0005-smithy-extension-trait-aliases}/metadata.json +0 -0
- /package/src/migrations/{latest/smithy-extension-trait-aliases → v1.0.0-rc.97/0005-smithy-extension-trait-aliases}/migration.d.ts +0 -0
- /package/src/migrations/{latest/smithy-extension-trait-aliases → v1.0.0-rc.97/0005-smithy-extension-trait-aliases}/migration.js +0 -0
- /package/src/migrations/{latest/script-project-quality-gates → v1.0.0-rc.97/0006-script-project-quality-gates}/metadata.json +0 -0
- /package/src/migrations/{latest/script-project-quality-gates → v1.0.0-rc.97/0006-script-project-quality-gates}/migration.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/nx-plugin/utils.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n joinPathFragments,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n writeJson,\n} from '@nx/devkit';\nimport type { PackageJson } from 'nx/src/utils/package-json';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from '../../utils/declared-dependencies.js';\nimport { addDependenciesToPackageJson } from '../../utils/dependencies.js';\nimport { isEsmWorkspace } from '../../utils/module-format.js';\nimport {\n nxPluginSelfDependency,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { type ITsDepVersion, withVersions } from '../../utils/versions.js';\n\n/** Dependencies a caller must declare to configure an Nx Plugin project. */\nexport const NX_PLUGIN_DEPENDENCIES = [\n { name: '@nx/devkit' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n/**\n * Read the configuration of a project which can host Nx Plugin generators or\n * migrations, ie a TypeScript project.\n */\nexport const readNxPluginProject = (\n tree: Tree,\n projectName: string,\n): ProjectConfiguration => {\n const project = readProjectConfigurationUnqualified(tree, projectName);\n\n const tsConfigPath = joinPathFragments(project.root, 'tsconfig.json');\n if (!tree.exists(tsConfigPath)) {\n throw new Error(\n `Selected plugin project ${projectName} is not a TypeScript project`,\n );\n }\n\n return project;\n};\n\n/** `package.json` field pointing Nx at one of a plugin's manifests. */\ntype NxPluginManifestField = 'generators' | 'nx-migrations';\n\n/**\n * Create the plugin project's package.json if absent and point it at the given\n * manifest, returning its path.\n */\nexport const configureNxPluginPackageJson = <\n TField extends NxPluginManifestField,\n>(\n tree: Tree,\n project: ProjectConfiguration,\n manifestField: TField,\n manifestValue: PackageJson[TField],\n): string => {\n const pluginPackageJsonPath = joinPathFragments(project.root, 'package.json');\n if (!tree.exists(pluginPackageJsonPath)) {\n writeJson(tree, pluginPackageJsonPath, {\n name: project.name,\n });\n }\n const esm = isEsmWorkspace(tree);\n updateJson(tree, pluginPackageJsonPath, (pkg) => {\n // Match the plugin's module system to the workspace. Nx loads `.ts` files\n // via Node's native type stripping, as ESM (workspace root is\n // `type: module`) or CommonJS accordingly.\n pkg.type ??= esm ? 'module' : 'commonjs';\n pkg.main ??= esm ? './src/index.js' : './src/index';\n pkg[manifestField] ??= manifestValue;\n return pkg;\n });\n return pluginPackageJsonPath;\n};\n\n/**\n * Declare the dependencies the plugin's `.ts` files import on both the\n * workspace and the plugin, since both must resolve for Nx to load them. A\n * no-op inside the plugin's own monorepo, where they are already present.\n */\nexport const addNxPluginDependencies = <const D extends DependencyDeclaration>(\n tree: Tree,\n pluginPackageJsonPath: string,\n declaration: D & MustDeclare<typeof NX_PLUGIN_DEPENDENCIES, D>,\n): void => {\n const selfDependency = nxPluginSelfDependency(tree);\n if (Object.keys(selfDependency).length === 0) {\n return;\n }\n const deps = {\n ...withVersions(\n forDependencies<typeof NX_PLUGIN_DEPENDENCIES>(declaration),\n ['@nx/devkit'],\n ),\n ...selfDependency,\n };\n addDependenciesToPackageJson(tree, {}, deps);\n addDependenciesToPackageJson(tree, deps, {}, pluginPackageJsonPath);\n};\n\n/**\n * Configures a TypeScript project as an Nx Plugin\n */\nexport const configureTsProjectAsNxPlugin = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n projectName: string,\n declaration: D & MustDeclare<typeof NX_PLUGIN_DEPENDENCIES, D>,\n) => {\n const project = readNxPluginProject(tree, projectName);\n\n // Create an empty generators.json if one dosn't exist\n const generatorsJsonPath = joinPathFragments(project.root, 'generators.json');\n if (!tree.exists(generatorsJsonPath)) {\n writeJson(tree, generatorsJsonPath, {\n generators: {},\n });\n }\n\n const pluginPackageJsonPath = configureNxPluginPackageJson(\n tree,\n project,\n 'generators',\n './generators.json',\n );\n\n addNxPluginDependencies(\n tree,\n pluginPackageJsonPath,\n forDependencies<typeof NX_PLUGIN_DEPENDENCIES>(declaration),\n );\n};\n"],"names":["joinPathFragments","updateJson","writeJson","forDependencies","addDependenciesToPackageJson","isEsmWorkspace","nxPluginSelfDependency","readProjectConfigurationUnqualified","withVersions","NX_PLUGIN_DEPENDENCIES","name","readNxPluginProject","tree","projectName","project","tsConfigPath","root","exists","Error","configureNxPluginPackageJson","manifestField","manifestValue","pluginPackageJsonPath","esm","pkg","type","main","addNxPluginDependencies","declaration","selfDependency","Object","keys","
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/nx-plugin/utils.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n joinPathFragments,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n updateProjectConfiguration,\n writeJson,\n} from '@nx/devkit';\nimport type { PackageJson } from 'nx/src/utils/package-json';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from '../../utils/declared-dependencies.js';\nimport { addDependenciesToPackageJson } from '../../utils/dependencies.js';\nimport { isEsmWorkspace } from '../../utils/module-format.js';\nimport {\n nxPluginSelfDependency,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { type ITsDepVersion, withVersions } from '../../utils/versions.js';\n\n/** Dependencies a caller must declare to configure an Nx Plugin project. */\nexport const NX_PLUGIN_DEPENDENCIES = [\n { name: '@nx/devkit' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n/**\n * Read the configuration of a project which can host Nx Plugin generators or\n * migrations, ie a TypeScript project.\n */\nexport const readNxPluginProject = (\n tree: Tree,\n projectName: string,\n): ProjectConfiguration => {\n const project = readProjectConfigurationUnqualified(tree, projectName);\n\n const tsConfigPath = joinPathFragments(project.root, 'tsconfig.json');\n if (!tree.exists(tsConfigPath)) {\n throw new Error(\n `Selected plugin project ${projectName} is not a TypeScript project`,\n );\n }\n\n return project;\n};\n\n/** `package.json` field pointing Nx at one of a plugin's manifests. */\ntype NxPluginManifestField = 'generators' | 'nx-migrations';\n\n/**\n * The manifests Nx reads from a published plugin, copied beside the compiled\n * code by the `package` target. `nx migrate` resolves `migrations.json` from the\n * tarball, so it ships even though only `ts#nx-migration` writes it.\n */\nexport const NX_PLUGIN_MANIFESTS = [\n 'generators.json',\n 'executors.json',\n 'migrations.json',\n] as const;\n\n/** The `package` target assets that copy the plugin's manifests into dist. */\nexport const nxPluginManifestAssets = (): {\n input: string;\n glob: string;\n output: string;\n}[] =>\n NX_PLUGIN_MANIFESTS.map((glob) => ({\n input: './{projectRoot}',\n glob,\n output: '.',\n }));\n\n/**\n * Ensure the plugin's `package` target copies every manifest into dist, so a\n * manifest added after the project was generated is still published.\n *\n * Anchored to the `generators.json` asset the target is vended with: a `package`\n * target without it belongs to something other than an Nx Plugin, or has been\n * rewritten, so it is left as it is.\n */\nexport const addNxPluginManifestAssets = (\n tree: Tree,\n project: ProjectConfiguration,\n): void => {\n const assets = project.targets?.package?.options?.assets;\n if (!Array.isArray(assets)) {\n return;\n }\n const globs = new Set(\n assets\n .filter((asset) => typeof asset === 'object' && asset !== null)\n .map((asset) => asset.glob),\n );\n if (!globs.has('generators.json')) {\n return;\n }\n const missing = nxPluginManifestAssets().filter(\n (asset) => !globs.has(asset.glob),\n );\n if (missing.length === 0) {\n return;\n }\n project.targets.package.options.assets = [...assets, ...missing];\n updateProjectConfiguration(tree, project.name, project);\n};\n\n/**\n * Create the plugin project's package.json if absent and point it at the given\n * manifest, returning its path.\n */\nexport const configureNxPluginPackageJson = <\n TField extends NxPluginManifestField,\n>(\n tree: Tree,\n project: ProjectConfiguration,\n manifestField: TField,\n manifestValue: PackageJson[TField],\n): string => {\n const pluginPackageJsonPath = joinPathFragments(project.root, 'package.json');\n if (!tree.exists(pluginPackageJsonPath)) {\n writeJson(tree, pluginPackageJsonPath, {\n name: project.name,\n });\n }\n const esm = isEsmWorkspace(tree);\n updateJson(tree, pluginPackageJsonPath, (pkg) => {\n // Match the plugin's module system to the workspace. Nx loads `.ts` files\n // via Node's native type stripping, as ESM (workspace root is\n // `type: module`) or CommonJS accordingly.\n pkg.type ??= esm ? 'module' : 'commonjs';\n pkg.main ??= esm ? './src/index.js' : './src/index';\n pkg[manifestField] ??= manifestValue;\n return pkg;\n });\n return pluginPackageJsonPath;\n};\n\n/**\n * Declare the dependencies the plugin's `.ts` files import on both the\n * workspace and the plugin, since both must resolve for Nx to load them. A\n * no-op inside the plugin's own monorepo, where they are already present.\n */\nexport const addNxPluginDependencies = <const D extends DependencyDeclaration>(\n tree: Tree,\n pluginPackageJsonPath: string,\n declaration: D & MustDeclare<typeof NX_PLUGIN_DEPENDENCIES, D>,\n): void => {\n const selfDependency = nxPluginSelfDependency(tree);\n if (Object.keys(selfDependency).length === 0) {\n return;\n }\n const deps = {\n ...withVersions(\n forDependencies<typeof NX_PLUGIN_DEPENDENCIES>(declaration),\n ['@nx/devkit'],\n ),\n ...selfDependency,\n };\n addDependenciesToPackageJson(tree, {}, deps);\n addDependenciesToPackageJson(tree, deps, {}, pluginPackageJsonPath);\n};\n\n/**\n * Configures a TypeScript project as an Nx Plugin\n */\nexport const configureTsProjectAsNxPlugin = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n projectName: string,\n declaration: D & MustDeclare<typeof NX_PLUGIN_DEPENDENCIES, D>,\n) => {\n const project = readNxPluginProject(tree, projectName);\n\n // Create an empty generators.json if one dosn't exist\n const generatorsJsonPath = joinPathFragments(project.root, 'generators.json');\n if (!tree.exists(generatorsJsonPath)) {\n writeJson(tree, generatorsJsonPath, {\n generators: {},\n });\n }\n\n const pluginPackageJsonPath = configureNxPluginPackageJson(\n tree,\n project,\n 'generators',\n './generators.json',\n );\n\n addNxPluginDependencies(\n tree,\n pluginPackageJsonPath,\n forDependencies<typeof NX_PLUGIN_DEPENDENCIES>(declaration),\n );\n};\n"],"names":["joinPathFragments","updateJson","updateProjectConfiguration","writeJson","forDependencies","addDependenciesToPackageJson","isEsmWorkspace","nxPluginSelfDependency","readProjectConfigurationUnqualified","withVersions","NX_PLUGIN_DEPENDENCIES","name","readNxPluginProject","tree","projectName","project","tsConfigPath","root","exists","Error","NX_PLUGIN_MANIFESTS","nxPluginManifestAssets","map","glob","input","output","addNxPluginManifestAssets","assets","targets","package","options","Array","isArray","globs","Set","filter","asset","has","missing","length","configureNxPluginPackageJson","manifestField","manifestValue","pluginPackageJsonPath","esm","pkg","type","main","addNxPluginDependencies","declaration","selfDependency","Object","keys","deps","configureTsProjectAsNxPlugin","generatorsJsonPath","generators"],"mappings":"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"}
|
|
@@ -99,8 +99,8 @@ export const handler = async (
|
|
|
99
99
|
`;
|
|
100
100
|
|
|
101
101
|
exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/src/index.ts 1`] = `
|
|
102
|
-
"
|
|
103
|
-
|
|
102
|
+
"// Export your library code here
|
|
103
|
+
export * from './prisma.js';
|
|
104
104
|
"
|
|
105
105
|
`;
|
|
106
106
|
|
|
@@ -848,7 +848,7 @@ terraform {
|
|
|
848
848
|
required_providers {
|
|
849
849
|
aws = {
|
|
850
850
|
source = "hashicorp/aws"
|
|
851
|
-
version = "6.
|
|
851
|
+
version = "6.63.0"
|
|
852
852
|
}
|
|
853
853
|
null = {
|
|
854
854
|
source = "hashicorp/null"
|
|
@@ -1519,7 +1519,7 @@ exports[`ts#rdb generator > should generate terraform modules when iac is Terraf
|
|
|
1519
1519
|
}
|
|
1520
1520
|
aws = {
|
|
1521
1521
|
source = "hashicorp/aws"
|
|
1522
|
-
version = "6.
|
|
1522
|
+
version = "6.63.0"
|
|
1523
1523
|
}
|
|
1524
1524
|
external = {
|
|
1525
1525
|
source = "hashicorp/external"
|
|
@@ -2214,7 +2214,7 @@ terraform {
|
|
|
2214
2214
|
required_providers {
|
|
2215
2215
|
aws = {
|
|
2216
2216
|
source = "hashicorp/aws"
|
|
2217
|
-
version = "6.
|
|
2217
|
+
version = "6.63.0"
|
|
2218
2218
|
}
|
|
2219
2219
|
null = {
|
|
2220
2220
|
source = "hashicorp/null"
|
|
@@ -2885,7 +2885,7 @@ exports[`ts#rdb generator > should generate terraform modules with MySQL engine
|
|
|
2885
2885
|
}
|
|
2886
2886
|
aws = {
|
|
2887
2887
|
source = "hashicorp/aws"
|
|
2888
|
-
version = "6.
|
|
2888
|
+
version = "6.63.0"
|
|
2889
2889
|
}
|
|
2890
2890
|
external = {
|
|
2891
2891
|
source = "hashicorp/external"
|
|
@@ -3679,8 +3679,8 @@ export const handler = async (
|
|
|
3679
3679
|
`;
|
|
3680
3680
|
|
|
3681
3681
|
exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/src/index.ts 1`] = `
|
|
3682
|
-
"
|
|
3683
|
-
|
|
3682
|
+
"// Export your library code here
|
|
3683
|
+
export * from './prisma.js';
|
|
3684
3684
|
"
|
|
3685
3685
|
`;
|
|
3686
3686
|
|
|
@@ -4540,8 +4540,8 @@ WORKDIR \${LAMBDA_TASK_ROOT}
|
|
|
4540
4540
|
# HIGH/CRITICAL vulnerabilities into the image.
|
|
4541
4541
|
RUN printf 'allow-scripts[]=prisma\\nallow-scripts[]=@prisma/engines\\n' > .npmrc \\
|
|
4542
4542
|
&& npm init -y \\
|
|
4543
|
-
&& npm pkg set "overrides.deepmerge-ts=8.0.
|
|
4544
|
-
&& npm pkg set "overrides.mysql2=3.
|
|
4543
|
+
&& npm pkg set "overrides.deepmerge-ts=8.0.2" \\
|
|
4544
|
+
&& npm pkg set "overrides.mysql2=3.24.3" \\
|
|
4545
4545
|
&& npm install prisma@7.10.0 \\
|
|
4546
4546
|
&& rm .npmrc \\
|
|
4547
4547
|
&& npm uninstall -g npm
|
|
@@ -50,11 +50,7 @@ export declare const DEPENDENCIES: import("../../../utils/declared-dependencies.
|
|
|
50
50
|
} & {
|
|
51
51
|
versionOnly: true;
|
|
52
52
|
}, {
|
|
53
|
-
readonly name: "
|
|
54
|
-
} & {
|
|
55
|
-
versionOnly: true;
|
|
56
|
-
}, {
|
|
57
|
-
readonly name: "tailwind-merge";
|
|
53
|
+
readonly name: "cn";
|
|
58
54
|
} & {
|
|
59
55
|
versionOnly: true;
|
|
60
56
|
}, {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`react-website generator > TailwindCSS integration > should configure vite with TailwindCSS plugin by default > vite.config.mts-with-tailwind 1`] = `
|
|
4
|
-
"
|
|
4
|
+
"/// <reference types='vitest' />
|
|
5
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
5
6
|
import { resolve } from 'path';
|
|
6
7
|
import { tanstackRouter } from '@tanstack/router-plugin/vite';
|
|
7
|
-
/// <reference types='vitest' />
|
|
8
8
|
import { defineConfig } from 'vite';
|
|
9
9
|
import react from '@vitejs/plugin-react';
|
|
10
10
|
|
|
@@ -59,9 +59,9 @@ export default defineConfig(() => ({
|
|
|
59
59
|
`;
|
|
60
60
|
|
|
61
61
|
exports[`react-website generator > TailwindCSS integration > should configure vite without TailwindCSS plugin when disabled > vite.config.mts-without-tailwind 1`] = `
|
|
62
|
-
"
|
|
62
|
+
"/// <reference types='vitest' />
|
|
63
|
+
import { resolve } from 'path';
|
|
63
64
|
import { tanstackRouter } from '@tanstack/router-plugin/vite';
|
|
64
|
-
/// <reference types='vitest' />
|
|
65
65
|
import { defineConfig } from 'vite';
|
|
66
66
|
import react from '@vitejs/plugin-react';
|
|
67
67
|
|
|
@@ -131,7 +131,7 @@ exports[`react-website generator > TailwindCSS integration > terraform iac > sho
|
|
|
131
131
|
required_providers {
|
|
132
132
|
aws = {
|
|
133
133
|
source = "hashicorp/aws"
|
|
134
|
-
version = "6.
|
|
134
|
+
version = "6.63.0"
|
|
135
135
|
configuration_aliases = [aws.us_east_1]
|
|
136
136
|
}
|
|
137
137
|
null = {
|
|
@@ -745,7 +745,7 @@ resource "null_resource" "upload_website_files" {
|
|
|
745
745
|
provisioner "local-exec" {
|
|
746
746
|
command = <<-EOT
|
|
747
747
|
cd "$ROOT_PATH"
|
|
748
|
-
uv run --with boto3==1.43.
|
|
748
|
+
uv run --with boto3==1.43.89 python3 -c "
|
|
749
749
|
import os
|
|
750
750
|
import sys
|
|
751
751
|
import boto3
|
|
@@ -868,7 +868,7 @@ resource "null_resource" "cloudfront_invalidation" {
|
|
|
868
868
|
|
|
869
869
|
provisioner "local-exec" {
|
|
870
870
|
command = <<-EOT
|
|
871
|
-
uv run --with boto3==1.43.
|
|
871
|
+
uv run --with boto3==1.43.89 python3 -c "
|
|
872
872
|
import boto3
|
|
873
873
|
import os
|
|
874
874
|
import sys
|
|
@@ -954,7 +954,7 @@ output "waf_web_acl_arn" {
|
|
|
954
954
|
required_providers {
|
|
955
955
|
aws = {
|
|
956
956
|
source = "hashicorp/aws"
|
|
957
|
-
version = "6.
|
|
957
|
+
version = "6.63.0"
|
|
958
958
|
configuration_aliases = [aws.us_east_1]
|
|
959
959
|
}
|
|
960
960
|
}
|
|
@@ -1060,7 +1060,7 @@ runtime-config.json"
|
|
|
1060
1060
|
|
|
1061
1061
|
exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > biome.json 1`] = `
|
|
1062
1062
|
"{
|
|
1063
|
-
"$schema": "https://biomejs.dev/schemas/2.5.
|
|
1063
|
+
"$schema": "https://biomejs.dev/schemas/2.5.12/schema.json",
|
|
1064
1064
|
"root": true,
|
|
1065
1065
|
"formatter": {
|
|
1066
1066
|
"enabled": true,
|
|
@@ -2325,18 +2325,18 @@ exports[`react-website generator > Tanstack router integration > should generate
|
|
|
2325
2325
|
- test-app
|
|
2326
2326
|
- packages/common/*
|
|
2327
2327
|
catalog:
|
|
2328
|
-
'@types/node': 26.4.
|
|
2328
|
+
'@types/node': 26.4.1
|
|
2329
2329
|
vite: 8.2.2
|
|
2330
2330
|
vitest: 4.1.11
|
|
2331
2331
|
'@vitest/coverage-v8': 4.1.11
|
|
2332
|
-
jsdom:
|
|
2332
|
+
jsdom: 29.1.1
|
|
2333
2333
|
'@nx/vitest': 23.2.0
|
|
2334
2334
|
constructs: 10.8.1
|
|
2335
|
-
aws-cdk-lib: 2.
|
|
2335
|
+
aws-cdk-lib: 2.268.0
|
|
2336
2336
|
react: 19.2.8
|
|
2337
2337
|
react-dom: 19.2.8
|
|
2338
|
-
'@cloudscape-design/components': 3.0.
|
|
2339
|
-
'@cloudscape-design/board-components': 3.0.
|
|
2338
|
+
'@cloudscape-design/components': 3.0.1359
|
|
2339
|
+
'@cloudscape-design/board-components': 3.0.222
|
|
2340
2340
|
'@cloudscape-design/global-styles': 1.0.67
|
|
2341
2341
|
tailwindcss: 4.3.3
|
|
2342
2342
|
'@nx/react': 23.2.0
|
|
@@ -2827,8 +2827,8 @@ exports[`react-website generator > Tanstack router integration > should generate
|
|
|
2827
2827
|
`;
|
|
2828
2828
|
|
|
2829
2829
|
exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > test-app/vite.config.mts 1`] = `
|
|
2830
|
-
"
|
|
2831
|
-
|
|
2830
|
+
"/// <reference types='vitest' />
|
|
2831
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
2832
2832
|
import { defineConfig } from 'vite';
|
|
2833
2833
|
import react from '@vitejs/plugin-react';
|
|
2834
2834
|
|
|
@@ -2936,7 +2936,7 @@ runtime-config.json"
|
|
|
2936
2936
|
|
|
2937
2937
|
exports[`react-website generator > Tanstack router integration > should generate website with router correctly > biome.json 1`] = `
|
|
2938
2938
|
"{
|
|
2939
|
-
"$schema": "https://biomejs.dev/schemas/2.5.
|
|
2939
|
+
"$schema": "https://biomejs.dev/schemas/2.5.12/schema.json",
|
|
2940
2940
|
"root": true,
|
|
2941
2941
|
"formatter": {
|
|
2942
2942
|
"enabled": true,
|
|
@@ -4205,18 +4205,18 @@ exports[`react-website generator > Tanstack router integration > should generate
|
|
|
4205
4205
|
- test-app
|
|
4206
4206
|
- packages/common/*
|
|
4207
4207
|
catalog:
|
|
4208
|
-
'@types/node': 26.4.
|
|
4208
|
+
'@types/node': 26.4.1
|
|
4209
4209
|
vite: 8.2.2
|
|
4210
4210
|
vitest: 4.1.11
|
|
4211
4211
|
'@vitest/coverage-v8': 4.1.11
|
|
4212
|
-
jsdom:
|
|
4212
|
+
jsdom: 29.1.1
|
|
4213
4213
|
'@nx/vitest': 23.2.0
|
|
4214
4214
|
constructs: 10.8.1
|
|
4215
|
-
aws-cdk-lib: 2.
|
|
4215
|
+
aws-cdk-lib: 2.268.0
|
|
4216
4216
|
react: 19.2.8
|
|
4217
4217
|
react-dom: 19.2.8
|
|
4218
|
-
'@cloudscape-design/components': 3.0.
|
|
4219
|
-
'@cloudscape-design/board-components': 3.0.
|
|
4218
|
+
'@cloudscape-design/components': 3.0.1359
|
|
4219
|
+
'@cloudscape-design/board-components': 3.0.222
|
|
4220
4220
|
'@cloudscape-design/global-styles': 1.0.67
|
|
4221
4221
|
tailwindcss: 4.3.3
|
|
4222
4222
|
'@tanstack/react-router': 1.170.32
|
|
@@ -4897,10 +4897,10 @@ exports[`react-website generator > Tanstack router integration > should generate
|
|
|
4897
4897
|
`;
|
|
4898
4898
|
|
|
4899
4899
|
exports[`react-website generator > Tanstack router integration > should generate website with router correctly > test-app/vite.config.mts 1`] = `
|
|
4900
|
-
"
|
|
4900
|
+
"/// <reference types='vitest' />
|
|
4901
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
4901
4902
|
import { resolve } from 'path';
|
|
4902
4903
|
import { tanstackRouter } from '@tanstack/router-plugin/vite';
|
|
4903
|
-
/// <reference types='vitest' />
|
|
4904
4904
|
import { defineConfig } from 'vite';
|
|
4905
4905
|
import react from '@vitejs/plugin-react';
|
|
4906
4906
|
|
|
@@ -5026,10 +5026,10 @@ exports[`react-website generator > should configure TypeScript correctly > tscon
|
|
|
5026
5026
|
`;
|
|
5027
5027
|
|
|
5028
5028
|
exports[`react-website generator > should configure vite correctly > vite.config.mts 1`] = `
|
|
5029
|
-
"
|
|
5029
|
+
"/// <reference types='vitest' />
|
|
5030
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
5030
5031
|
import { resolve } from 'path';
|
|
5031
5032
|
import { tanstackRouter } from '@tanstack/router-plugin/vite';
|
|
5032
|
-
/// <reference types='vitest' />
|
|
5033
5033
|
import { defineConfig } from 'vite';
|
|
5034
5034
|
import react from '@vitejs/plugin-react';
|
|
5035
5035
|
|
|
@@ -96,11 +96,7 @@ export declare const DEPENDENCIES: import("../../../utils/declared-dependencies.
|
|
|
96
96
|
} & {
|
|
97
97
|
versionOnly: true;
|
|
98
98
|
}, {
|
|
99
|
-
readonly name: "
|
|
100
|
-
} & {
|
|
101
|
-
versionOnly: true;
|
|
102
|
-
}, {
|
|
103
|
-
readonly name: "tailwind-merge";
|
|
99
|
+
readonly name: "cn";
|
|
104
100
|
} & {
|
|
105
101
|
versionOnly: true;
|
|
106
102
|
}, {
|
|
@@ -6,7 +6,7 @@ exports[`cognito-auth generator terraform iac > should generate terraform files
|
|
|
6
6
|
required_providers {
|
|
7
7
|
aws = {
|
|
8
8
|
source = "hashicorp/aws"
|
|
9
|
-
version = "6.
|
|
9
|
+
version = "6.63.0"
|
|
10
10
|
}
|
|
11
11
|
null = {
|
|
12
12
|
source = "hashicorp/null"
|
|
@@ -67,7 +67,7 @@ resource "null_resource" "add_callback_url" {
|
|
|
67
67
|
|
|
68
68
|
provisioner "local-exec" {
|
|
69
69
|
command = <<-EOT
|
|
70
|
-
uv run --with boto3==1.43.
|
|
70
|
+
uv run --with boto3==1.43.89 python -c "
|
|
71
71
|
import boto3
|
|
72
72
|
import os
|
|
73
73
|
import sys
|
package/src/utils/ast.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/ import { QueryBuilder } from "@getgrit/gritql";
|
|
5
5
|
import * as path from "path";
|
|
6
|
+
import { LANGUAGE_COMMENT_SYNTAX, readLicenseConfig } from "../license/config.js";
|
|
7
|
+
import { parseFile } from "../license/sync/generator.js";
|
|
6
8
|
import { updateGitIgnore } from "./git.js";
|
|
7
9
|
import { isEsmWorkspace } from "./module-format.js";
|
|
8
10
|
const GRIT_DIR = '.grit';
|
|
@@ -31,6 +33,49 @@ const assertFilePath = (tree, filePath)=>{
|
|
|
31
33
|
throw new Error(`No file located at ${filePath}`);
|
|
32
34
|
}
|
|
33
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Insert `statement` at the top of a file, below any hashbang and leading
|
|
38
|
+
* comment block. Keeps a license header first in the file, so `license#sync`
|
|
39
|
+
* doesn't see it displaced and prepend a second one.
|
|
40
|
+
*
|
|
41
|
+
* The leading comment is skipped whatever it says — a header, a placeholder or a
|
|
42
|
+
* note — so nothing here has to identify a license.
|
|
43
|
+
*
|
|
44
|
+
* Splits the file with the sync generator's own `parseFile`, resolving the
|
|
45
|
+
* comment syntax the way the sync does: the workspace's configured
|
|
46
|
+
* `commentSyntax` for the extension first, then the built-in table. That way an
|
|
47
|
+
* extension only the user's config covers is still recognised. An extension
|
|
48
|
+
* neither covers has no comment syntax to find, so the statement goes at the top.
|
|
49
|
+
*/ const insertBelowLeadingComments = async (tree, filePath, contents, statement)=>{
|
|
50
|
+
const extension = filePath.split('.').pop() ?? '';
|
|
51
|
+
let syntax;
|
|
52
|
+
try {
|
|
53
|
+
syntax = (await readLicenseConfig(tree))?.source?.header?.commentSyntax?.[extension];
|
|
54
|
+
} catch {
|
|
55
|
+
// Reading the config evaluates it, which throws on a config that doesn't
|
|
56
|
+
// load — including this file itself while a generator is mid-edit. A config
|
|
57
|
+
// we can't read must not stop an import being added, so fall back to the
|
|
58
|
+
// defaults. (A config that simply doesn't exist reads as undefined.)
|
|
59
|
+
}
|
|
60
|
+
syntax ??= LANGUAGE_COMMENT_SYNTAX[extension];
|
|
61
|
+
if (!syntax) {
|
|
62
|
+
return `${statement}\n${contents}`;
|
|
63
|
+
}
|
|
64
|
+
const { hashbang, header, body } = parseFile(contents, syntax);
|
|
65
|
+
if (!hashbang && !header) {
|
|
66
|
+
return `${statement}\n${contents}`;
|
|
67
|
+
}
|
|
68
|
+
return [
|
|
69
|
+
...hashbang ? [
|
|
70
|
+
hashbang
|
|
71
|
+
] : [],
|
|
72
|
+
...header ? [
|
|
73
|
+
header
|
|
74
|
+
] : [],
|
|
75
|
+
statement,
|
|
76
|
+
body
|
|
77
|
+
].join('\n');
|
|
78
|
+
};
|
|
34
79
|
export const addDestructuredImport = async (tree, filePath, variableNames, from)=>{
|
|
35
80
|
assertFilePath(tree, filePath);
|
|
36
81
|
from = normalizeModuleSpecifier(tree, from);
|
|
@@ -44,16 +89,10 @@ export const addDestructuredImport = async (tree, filePath, variableNames, from)
|
|
|
44
89
|
await applyGritQL(tree, filePath, `\`import { $imports } from '${from}'\` => \`import { $imports, ${variableName} } from '${from}'\` where { $imports <: not contains \`${localName}\` }`);
|
|
45
90
|
}
|
|
46
91
|
} else {
|
|
47
|
-
// No existing import —
|
|
92
|
+
// No existing import — add a new one below any hashbang and leading comment
|
|
48
93
|
const specifiers = variableNames.join(', ');
|
|
49
94
|
const contents = tree.read(filePath).toString();
|
|
50
|
-
|
|
51
|
-
if (contents.startsWith('#!')) {
|
|
52
|
-
const newlineIndex = contents.indexOf('\n');
|
|
53
|
-
tree.write(filePath, `${contents.substring(0, newlineIndex + 1)}${newImport}${contents.substring(newlineIndex + 1)}`);
|
|
54
|
-
} else {
|
|
55
|
-
tree.write(filePath, `${newImport}${contents}`);
|
|
56
|
-
}
|
|
95
|
+
tree.write(filePath, await insertBelowLeadingComments(tree, filePath, contents, `import { ${specifiers} } from '${from}';`));
|
|
57
96
|
}
|
|
58
97
|
};
|
|
59
98
|
/**
|
|
@@ -93,10 +132,11 @@ export const addDestructuredImport = async (tree, filePath, variableNames, from)
|
|
|
93
132
|
if (allAlreadyPresent) {
|
|
94
133
|
return;
|
|
95
134
|
}
|
|
96
|
-
// No existing `from <module> import` line —
|
|
97
|
-
// sorter will place it in the right group on
|
|
135
|
+
// No existing `from <module> import` line — add one below any hashbang and
|
|
136
|
+
// leading comment. Ruff's import sorter will place it in the right group on
|
|
137
|
+
// the next formatter pass.
|
|
98
138
|
const specifiers = variableNames.join(', ');
|
|
99
|
-
tree.write(filePath, `from ${from} import ${specifiers}
|
|
139
|
+
tree.write(filePath, await insertBelowLeadingComments(tree, filePath, beforeContents, `from ${from} import ${specifiers}`));
|
|
100
140
|
};
|
|
101
141
|
/**
|
|
102
142
|
* Adds an `import <variableName> from '<from>'; statement to the beginning of the file,
|
|
@@ -115,9 +155,9 @@ export const addDestructuredImport = async (tree, filePath, variableNames, from)
|
|
|
115
155
|
if (identifierTaken) {
|
|
116
156
|
throw new Error(`Cannot import ${variableName} from '${from}' in ${filePath}: ${variableName} is already imported from a different module. Rename the project so its generated identifier does not collide.`);
|
|
117
157
|
}
|
|
118
|
-
//
|
|
158
|
+
// Add the import below any hashbang and leading comment
|
|
119
159
|
const contents = tree.read(filePath).toString();
|
|
120
|
-
tree.write(filePath, `import ${variableName} from '${from}'
|
|
160
|
+
tree.write(filePath, await insertBelowLeadingComments(tree, filePath, contents, `import ${variableName} from '${from}';`));
|
|
121
161
|
};
|
|
122
162
|
/**
|
|
123
163
|
* Adds an `export * from '<from>'; statement to the given TypeScript file.
|
|
@@ -135,8 +175,7 @@ export const addDestructuredImport = async (tree, filePath, variableNames, from)
|
|
|
135
175
|
if (alreadyExported) {
|
|
136
176
|
return;
|
|
137
177
|
}
|
|
138
|
-
|
|
139
|
-
tree.write(filePath, `export * from '${from}';\n${contents}`);
|
|
178
|
+
tree.write(filePath, await insertBelowLeadingComments(tree, filePath, contents, `export * from '${from}';`));
|
|
140
179
|
};
|
|
141
180
|
/**
|
|
142
181
|
* Adds an `export { <names> } from '<from>';` statement to the given TypeScript
|
|
@@ -169,7 +208,7 @@ export const addDestructuredImport = async (tree, filePath, variableNames, from)
|
|
|
169
208
|
if (missing.length === 0) {
|
|
170
209
|
return;
|
|
171
210
|
}
|
|
172
|
-
tree.write(filePath, `export { ${missing.join(', ')} } from '${from}'
|
|
211
|
+
tree.write(filePath, await insertBelowLeadingComments(tree, filePath, contents, `export { ${missing.join(', ')} } from '${from}';`));
|
|
173
212
|
};
|
|
174
213
|
/**
|
|
175
214
|
* Return whether or not the given identifier is exported in the source file.
|
package/src/utils/ast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/ast.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { QueryBuilder } from '@getgrit/gritql';\nimport type { Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport { updateGitIgnore } from './git.js';\nimport { isEsmWorkspace } from './module-format.js';\n\nconst GRIT_DIR = '.grit';\n\n/**\n * Normalize a relative module specifier for the workspace's module format.\n * ESM (`nodenext`) requires an explicit `.js` extension on relative imports;\n * CommonJS (`node16`) resolves them extensionless. Callers always pass the ESM\n * form (with `.js`); this strips the extension for CommonJS workspaces.\n */\nconst normalizeModuleSpecifier = (tree: Tree, from: string): string => {\n if (isEsmWorkspace(tree)) {\n return from;\n }\n const isRelative = from.startsWith('./') || from.startsWith('../');\n return isRelative && from.endsWith('.js')\n ? from.slice(0, -'.js'.length)\n : from;\n};\n\n// Pin the gritql native library's \"global\" stdlib directory to <workspace>/.grit so it doesn't try to write to /usr/local/.grit (or wherever node's grandparent resolves to).\nconst ensureGritDir = (tree: Tree) => {\n process.env.GRIT_GLOBAL_DIR ??= path.join(tree.root, GRIT_DIR);\n updateGitIgnore(tree, '.', (patterns) => [...patterns, GRIT_DIR]);\n};\n\nconst assertFilePath = (tree: Tree, filePath: string) => {\n if (!tree.exists(filePath)) {\n throw new Error(`No file located at ${filePath}`);\n }\n};\n\nexport const addDestructuredImport = async (\n tree: Tree,\n filePath: string,\n variableNames: string[],\n from: string,\n) => {\n assertFilePath(tree, filePath);\n from = normalizeModuleSpecifier(tree, from);\n\n // Check if there's an existing import from this module\n const hasExistingImport = await matchGritQL(\n tree,\n filePath,\n `\\`import { $_ } from '${from}'\\``,\n );\n\n if (hasExistingImport) {\n // For each new variable, use GritQL rewrite to add it if not already present\n for (const variableName of variableNames) {\n const localName = variableName.includes(' as ')\n ? variableName.split(' as ')[1]\n : variableName;\n // Use rewrite (=>) which correctly handles comma-separated import specifier lists\n await applyGritQL(\n tree,\n filePath,\n `\\`import { $imports } from '${from}'\\` => \\`import { $imports, ${variableName} } from '${from}'\\` where { $imports <: not contains \\`${localName}\\` }`,\n );\n }\n } else {\n // No existing import — prepend a new one (after shebang if present)\n const specifiers = variableNames.join(', ');\n const contents = tree.read(filePath)!.toString();\n const newImport = `import { ${specifiers} } from '${from}';\\n`;\n if (contents.startsWith('#!')) {\n const newlineIndex = contents.indexOf('\\n');\n tree.write(\n filePath,\n `${contents.substring(0, newlineIndex + 1)}${newImport}${contents.substring(newlineIndex + 1)}`,\n );\n } else {\n tree.write(filePath, `${newImport}${contents}`);\n }\n }\n};\n\n/**\n * Ensure a Python `from <module> import <name1>, <name2>, ...` statement\n * exists in the given file. If the module already has a `from <module> import`\n * line, any missing names are appended; otherwise a fresh import statement is\n * prepended to the file (ruff's import sorter will reorder it into place on\n * the next format pass).\n *\n * We try to append first (which only succeeds if an import-from for the\n * module already exists AND the name isn't yet in the list). If nothing\n * was rewritten after trying every requested name, we fall back to checking\n * whether the module is imported at all; if not, we prepend a fresh\n * `from <module> import ...` line.\n */\nexport const addPythonDestructuredImport = async (\n tree: Tree,\n filePath: string,\n variableNames: string[],\n from: string,\n) => {\n assertFilePath(tree, filePath);\n\n // Determine whether there's any `from <module> import ...` line in the file.\n // We detect this by attempting a no-op transformation — the file is unchanged,\n // but a successful match tells us the line exists.\n const beforeContents = tree.read(filePath)!.toString();\n let moduleAlreadyImported = false;\n for (const variableName of variableNames) {\n // Appends the name if the import-from exists and the name isn't already there.\n const appended = await applyGritQL(\n tree,\n filePath,\n `language python\\n\\`from ${from} import $names\\` where { $names <: not contains \\`${variableName}\\`, $names += \\`, ${variableName}\\` }`,\n );\n if (appended) {\n moduleAlreadyImported = true;\n }\n }\n\n // If the append succeeded for at least one name, we know the module line\n // exists; we're done. If nothing was appended we need to distinguish\n // between \"module not imported\" (need to add a new line) and \"module\n // imported but all names already present\" (no-op).\n if (moduleAlreadyImported) {\n return;\n }\n\n const allAlreadyPresent = await matchGritQL(\n tree,\n filePath,\n `language python\\n\\`from ${from} import $names\\` where { ${variableNames\n .map((n) => `$names <: contains \\`${n}\\``)\n .join(', ')} }`,\n );\n if (allAlreadyPresent) {\n return;\n }\n\n // No existing `from <module> import` line — prepend one. Ruff's import\n // sorter will place it in the right group on the next formatter pass.\n const specifiers = variableNames.join(', ');\n tree.write(filePath, `from ${from} import ${specifiers}\\n${beforeContents}`);\n};\n\n/**\n * Adds an `import <variableName> from '<from>'; statement to the beginning of the file,\n * if it doesn't already exist\n */\nexport const addSingleImport = async (\n tree: Tree,\n filePath: string,\n variableName: string,\n from: string,\n) => {\n assertFilePath(tree, filePath);\n from = normalizeModuleSpecifier(tree, from);\n\n // Check if default import already exists using GritQL\n const alreadyImported = await matchGritQL(\n tree,\n filePath,\n `\\`import ${variableName} from '${from}'\\``,\n );\n if (alreadyImported) {\n return;\n }\n\n // The same identifier bound to a different module would be a duplicate\n // declaration, so refuse rather than emit a file that cannot compile.\n const identifierTaken = await matchGritQL(\n tree,\n filePath,\n `\\`import ${variableName} from $module\\``,\n );\n if (identifierTaken) {\n throw new Error(\n `Cannot import ${variableName} from '${from}' in ${filePath}: ${variableName} is already imported from a different module. Rename the project so its generated identifier does not collide.`,\n );\n }\n\n // Prepend new import to file\n const contents = tree.read(filePath)!.toString();\n tree.write(filePath, `import ${variableName} from '${from}';\\n${contents}`);\n};\n\n/**\n * Adds an `export * from '<from>'; statement to the given TypeScript file.\n * Note that this will create the file if it does not exist in the tree.\n */\nexport const addStarExport = async (\n tree: Tree,\n filePath: string,\n from: string,\n) => {\n from = normalizeModuleSpecifier(tree, from);\n const contents = tree.read(filePath)?.toString() ?? '';\n\n // For empty/non-existent files, just write the export\n if (!contents.trim()) {\n tree.write(filePath, `export * from '${from}';\\n`);\n return;\n }\n\n // Check if already exported using GritQL\n const alreadyExported = await matchGritQL(\n tree,\n filePath,\n `\\`export * from '${from}'\\``,\n );\n if (alreadyExported) {\n return;\n }\n\n // Prepend new export to file\n tree.write(filePath, `export * from '${from}';\\n${contents}`);\n};\n\n/**\n * Adds an `export { <names> } from '<from>';` statement to the given TypeScript\n * file, merging into an existing re-export of the same module when there is one.\n * Note that this will create the file if it does not exist in the tree.\n *\n * Adding to whatever is already there is what lets a barrel the user curates —\n * their own entities, models or components — survive a generator re-run while\n * the generated entry is still registered.\n */\nexport const addNamedExport = async (\n tree: Tree,\n filePath: string,\n names: string[],\n from: string,\n) => {\n from = normalizeModuleSpecifier(tree, from);\n const contents = tree.read(filePath)?.toString() ?? '';\n\n if (!contents.trim()) {\n tree.write(filePath, `export { ${names.join(', ')} } from '${from}';\\n`);\n return;\n }\n\n const hasExistingExport = await matchGritQL(\n tree,\n filePath,\n `\\`export { $_ } from '${from}'\\``,\n );\n\n if (hasExistingExport) {\n for (const name of names) {\n await applyGritQL(\n tree,\n filePath,\n `\\`export { $names } from '${from}'\\` => \\`export { $names, ${name} } from '${from}'\\` where { $names <: not contains \\`${name}\\` }`,\n );\n }\n return;\n }\n\n const missing: string[] = [];\n for (const name of names) {\n if (!(await matchGritQL(tree, filePath, `\\`${name}\\``))) {\n missing.push(name);\n }\n }\n if (missing.length === 0) {\n return;\n }\n\n tree.write(\n filePath,\n `export { ${missing.join(', ')} } from '${from}';\\n${contents}`,\n );\n};\n\n/**\n * Return whether or not the given identifier is exported in the source file.\n * Checks for both `export { Identifier }` and `export type Identifier = ...`.\n */\nexport const hasExportDeclaration = async (\n tree: Tree,\n source: string,\n identifierName: string,\n): Promise<boolean> => {\n ensureGritDir(tree);\n const patterns = [\n `\\`export type ${identifierName} = $_\\``,\n `\\`export { ${identifierName} }\\``,\n `\\`export type { ${identifierName} } from $_\\``,\n ];\n\n for (const pattern of patterns) {\n try {\n const q = new QueryBuilder(`$p => $p where { $p <: ${pattern} }`);\n const result = await q.applyToFile({\n path: 'check.ts',\n content: source,\n });\n if (result !== null) return true;\n } catch {\n // Pattern didn't match, try next\n }\n }\n\n return false;\n};\n\n/**\n * Apply a GritQL pattern to a file in the Nx tree.\n */\nexport const applyGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<boolean> => {\n if (!tree.exists(filePath)) throw new Error(`No file at ${filePath}`);\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n const query = new QueryBuilder(pattern);\n const result = await query.applyToFile({ path: filePath, content: source });\n if (result && result.content !== source) {\n tree.write(filePath, result.content);\n return true;\n }\n return false;\n};\n\n/**\n * Check whether a GritQL pattern matches anywhere in a file.\n * Returns true if the pattern matches at least once.\n *\n * Accepts raw GritQL, including patterns that start with a `language <name>`\n * header (e.g. `language python\\n\\`print($_)\\``) — the pattern is passed\n * straight through to QueryBuilder without any wrapping rewrite.\n */\nexport const matchGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<boolean> => {\n if (!tree.exists(filePath)) return false;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n let matched = false;\n try {\n const query = new QueryBuilder(pattern);\n query.filter(() => {\n matched = true;\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return false;\n }\n return matched;\n};\n\n/**\n * Capture the source text of the first match of a GritQL pattern.\n *\n * For example `` `dependencyCheck: $_` `` returns the whole\n * `dependencyCheck: { ... }` property text. Returns undefined if nothing\n * matches. The file is not modified.\n */\nexport const captureGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<string | undefined> => {\n if (!tree.exists(filePath)) return undefined;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n let captured: string | undefined;\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n captured ??= node.text();\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return undefined;\n }\n return captured;\n};\n\n/**\n * Like `captureGritQL`, but returns one metavariable's binding (e.g. `mod`\n * for `$mod`) instead of the whole matched node.\n */\nexport const captureGritQLVariable = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n variableName: string,\n): Promise<string | undefined> => {\n if (!tree.exists(filePath)) return undefined;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n // The underlying binding lookup requires the `$` sigil.\n const name = variableName.startsWith('$') ? variableName : `$${variableName}`;\n let captured: string | undefined;\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n captured ??= node.var(name) ?? undefined;\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return undefined;\n }\n return captured;\n};\n\n/**\n * Like {@link captureAllGritQL}, but returns one metavariable's binding for every\n * match rather than the whole matched node.\n *\n * This is what lets a caller work on the value a pattern isolated — matching\n * `` `runtime: $value` `` and reading `$value` gives `Runtime.NODEJS_24_X` alone,\n * so nothing downstream has to re-derive the assignment around it.\n *\n * A match whose metavariable is unbound contributes nothing, so the result holds\n * only real bindings. Returns undefined if the pattern could not be applied,\n * which an empty array cannot express.\n */\nexport const captureAllGritQLVariable = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n variableName: string,\n): Promise<string[] | undefined> => {\n if (!tree.exists(filePath)) return undefined;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n // The underlying binding lookup requires the `$` sigil.\n const name = variableName.startsWith('$') ? variableName : `$${variableName}`;\n const captured: string[] = [];\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n const bound = node.var(name);\n if (bound !== null && bound !== undefined) {\n captured.push(bound);\n }\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return undefined;\n }\n return captured;\n};\n\n/**\n * Return the text of every node matching the GritQL pattern, in document order.\n */\nexport const captureAllGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<string[]> => {\n if (!tree.exists(filePath)) return [];\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n const captured: string[] = [];\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n captured.push(node.text());\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return [];\n }\n return captured;\n};\n\n/**\n * A unique token that is a valid identifier, so it can stand in for an array\n * element or object property inside a GritQL rewrite.\n */\nexport const GRIT_INSERT_PLACEHOLDER = '__GRIT_INSERT_PLACEHOLDER__';\n\n/**\n * Apply a GritQL rewrite that inserts {@link GRIT_INSERT_PLACEHOLDER}, then\n * replace the placeholder with `text`. Routing user-provided text through a\n * placeholder keeps it out of the GritQL pattern, where quotes, backticks or\n * `${...}` would otherwise break parsing.\n *\n * Any separator (e.g. a leading `, ` when appending to an array) must be part\n * of the GritQL pattern, not `text`. The one adjustment made here: if the\n * placeholder lands after a trailing line comment (`// ...`) — which would\n * comment out the text — the text is moved to its own line.\n *\n * The caller formats afterwards. Returns true if the pattern matched and the\n * file changed.\n */\nexport const insertViaGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n text: string,\n): Promise<boolean> => {\n if (!(await applyGritQL(tree, filePath, pattern))) return false;\n const content = tree.read(filePath)!.toString();\n const at = content.indexOf(GRIT_INSERT_PLACEHOLDER);\n const lineSoFar = content.slice(content.lastIndexOf('\\n', at) + 1, at);\n const replacement = lineSoFar.includes('//') ? `\\n${text}` : text;\n\n // Function replacer so `$` in `text` isn't treated as a replacement pattern.\n tree.write(\n filePath,\n content.replace(GRIT_INSERT_PLACEHOLDER, () => replacement),\n );\n return true;\n};\n\n/**\n * Append `entry` to an array, skipping arrays that already contain it, e.g.\n * `` appendToArrayViaGritQL(tree, file, 'tools:', 'myTool', { scope: 'new Agent($_)' }) ``\n * turns `tools: [a, b]` into `tools: [a, b, myTool]`.\n *\n * `arrayPrefix` is whatever precedes the array literal, including its separator —\n * `'tools:'` for an object property, `'tools='` for a keyword argument or\n * assignment, `'\"tools\":'` for a quoted key. Which separator applies depends on\n * the construct rather than the language, so the caller states it.\n *\n * Appends after the last *element* rather than rewriting the element list with\n * `=>`. GritQL binds a `[$items]` list to its trailing comma too, so\n * `` `[$items]` => `[$items, entry]` `` emits the sparse array `[a, b, , entry]`\n * once the formatter has wrapped the array — a hole that is `undefined` at\n * runtime. (Accumulating with `$items += \", entry\"` is safe by comparison, since\n * it appends within the list rather than re-emitting it; both forms appear in\n * this repo.)\n *\n * `scope` limits the match to an enclosing pattern, so same-named arrays\n * elsewhere in the file are left alone. `skipIfContains` overrides what the\n * append dedupes on, for when the rendered entry is not the identifier to match.\n *\n * The caller formats afterwards. Returns true if the entry was appended.\n */\nexport const appendToArrayViaGritQL = async (\n tree: Tree,\n filePath: string,\n arrayPrefix: string,\n entry: string,\n options: { scope?: string; skipIfContains?: string; language?: 'py' } = {},\n): Promise<boolean> => {\n const { scope, skipIfContains, language } = options;\n const within = (variable: string) =>\n scope ? `${variable} <: within \\`${scope}\\`, ` : '';\n const pattern =\n `or {` +\n // An empty array has no last element to append after.\n ` \\`${arrayPrefix}$arr\\` where { $arr <: \\`[]\\`, ${within('$arr')}` +\n ` $arr => \\`[${GRIT_INSERT_PLACEHOLDER}]\\` },` +\n // Dedupe on the list, append after its last element.\n ` \\`${arrayPrefix}[$items]\\` where {` +\n ` $items <: not contains \\`${skipIfContains ?? entry}\\`, ${within('$items')}` +\n ` $items <: [$..., $last], $last += \\`, ${GRIT_INSERT_PLACEHOLDER}\\` }` +\n ` }`;\n\n return insertViaGritQL(\n tree,\n filePath,\n language === 'py' ? `language python\\n${pattern}` : pattern,\n entry,\n );\n};\n"],"names":["QueryBuilder","path","updateGitIgnore","isEsmWorkspace","GRIT_DIR","normalizeModuleSpecifier","tree","from","isRelative","startsWith","endsWith","slice","length","ensureGritDir","process","env","GRIT_GLOBAL_DIR","join","root","patterns","assertFilePath","filePath","exists","Error","addDestructuredImport","variableNames","hasExistingImport","matchGritQL","variableName","localName","includes","split","applyGritQL","specifiers","contents","read","toString","newImport","newlineIndex","indexOf","write","substring","addPythonDestructuredImport","beforeContents","moduleAlreadyImported","appended","allAlreadyPresent","map","n","addSingleImport","alreadyImported","identifierTaken","addStarExport","trim","alreadyExported","addNamedExport","names","hasExistingExport","name","missing","push","hasExportDeclaration","source","identifierName","pattern","q","result","applyToFile","content","query","matched","filter","captureGritQL","undefined","captured","node","text","captureGritQLVariable","var","captureAllGritQLVariable","bound","captureAllGritQL","GRIT_INSERT_PLACEHOLDER","insertViaGritQL","at","lineSoFar","lastIndexOf","replacement","replace","appendToArrayViaGritQL","arrayPrefix","entry","options","scope","skipIfContains","language","within","variable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/ast.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { QueryBuilder } from '@getgrit/gritql';\nimport type { Tree } from '@nx/devkit';\nimport * as path from 'path';\nimport {\n LANGUAGE_COMMENT_SYNTAX,\n readLicenseConfig,\n} from '../license/config.js';\nimport type { CommentSyntax } from '../license/config-types.js';\nimport { parseFile } from '../license/sync/generator.js';\nimport { updateGitIgnore } from './git.js';\nimport { isEsmWorkspace } from './module-format.js';\n\nconst GRIT_DIR = '.grit';\n\n/**\n * Normalize a relative module specifier for the workspace's module format.\n * ESM (`nodenext`) requires an explicit `.js` extension on relative imports;\n * CommonJS (`node16`) resolves them extensionless. Callers always pass the ESM\n * form (with `.js`); this strips the extension for CommonJS workspaces.\n */\nconst normalizeModuleSpecifier = (tree: Tree, from: string): string => {\n if (isEsmWorkspace(tree)) {\n return from;\n }\n const isRelative = from.startsWith('./') || from.startsWith('../');\n return isRelative && from.endsWith('.js')\n ? from.slice(0, -'.js'.length)\n : from;\n};\n\n// Pin the gritql native library's \"global\" stdlib directory to <workspace>/.grit so it doesn't try to write to /usr/local/.grit (or wherever node's grandparent resolves to).\nconst ensureGritDir = (tree: Tree) => {\n process.env.GRIT_GLOBAL_DIR ??= path.join(tree.root, GRIT_DIR);\n updateGitIgnore(tree, '.', (patterns) => [...patterns, GRIT_DIR]);\n};\n\nconst assertFilePath = (tree: Tree, filePath: string) => {\n if (!tree.exists(filePath)) {\n throw new Error(`No file located at ${filePath}`);\n }\n};\n\n/**\n * Insert `statement` at the top of a file, below any hashbang and leading\n * comment block. Keeps a license header first in the file, so `license#sync`\n * doesn't see it displaced and prepend a second one.\n *\n * The leading comment is skipped whatever it says — a header, a placeholder or a\n * note — so nothing here has to identify a license.\n *\n * Splits the file with the sync generator's own `parseFile`, resolving the\n * comment syntax the way the sync does: the workspace's configured\n * `commentSyntax` for the extension first, then the built-in table. That way an\n * extension only the user's config covers is still recognised. An extension\n * neither covers has no comment syntax to find, so the statement goes at the top.\n */\nconst insertBelowLeadingComments = async (\n tree: Tree,\n filePath: string,\n contents: string,\n statement: string,\n): Promise<string> => {\n const extension = filePath.split('.').pop() ?? '';\n let syntax: CommentSyntax | undefined;\n try {\n syntax = (await readLicenseConfig(tree))?.source?.header?.commentSyntax?.[\n extension\n ];\n } catch {\n // Reading the config evaluates it, which throws on a config that doesn't\n // load — including this file itself while a generator is mid-edit. A config\n // we can't read must not stop an import being added, so fall back to the\n // defaults. (A config that simply doesn't exist reads as undefined.)\n }\n syntax ??= LANGUAGE_COMMENT_SYNTAX[extension];\n if (!syntax) {\n return `${statement}\\n${contents}`;\n }\n\n const { hashbang, header, body } = parseFile(contents, syntax);\n if (!hashbang && !header) {\n return `${statement}\\n${contents}`;\n }\n return [\n ...(hashbang ? [hashbang] : []),\n ...(header ? [header] : []),\n statement,\n body,\n ].join('\\n');\n};\n\nexport const addDestructuredImport = async (\n tree: Tree,\n filePath: string,\n variableNames: string[],\n from: string,\n) => {\n assertFilePath(tree, filePath);\n from = normalizeModuleSpecifier(tree, from);\n\n // Check if there's an existing import from this module\n const hasExistingImport = await matchGritQL(\n tree,\n filePath,\n `\\`import { $_ } from '${from}'\\``,\n );\n\n if (hasExistingImport) {\n // For each new variable, use GritQL rewrite to add it if not already present\n for (const variableName of variableNames) {\n const localName = variableName.includes(' as ')\n ? variableName.split(' as ')[1]\n : variableName;\n // Use rewrite (=>) which correctly handles comma-separated import specifier lists\n await applyGritQL(\n tree,\n filePath,\n `\\`import { $imports } from '${from}'\\` => \\`import { $imports, ${variableName} } from '${from}'\\` where { $imports <: not contains \\`${localName}\\` }`,\n );\n }\n } else {\n // No existing import — add a new one below any hashbang and leading comment\n const specifiers = variableNames.join(', ');\n const contents = tree.read(filePath)!.toString();\n tree.write(\n filePath,\n await insertBelowLeadingComments(\n tree,\n filePath,\n contents,\n `import { ${specifiers} } from '${from}';`,\n ),\n );\n }\n};\n\n/**\n * Ensure a Python `from <module> import <name1>, <name2>, ...` statement\n * exists in the given file. If the module already has a `from <module> import`\n * line, any missing names are appended; otherwise a fresh import statement is\n * prepended to the file (ruff's import sorter will reorder it into place on\n * the next format pass).\n *\n * We try to append first (which only succeeds if an import-from for the\n * module already exists AND the name isn't yet in the list). If nothing\n * was rewritten after trying every requested name, we fall back to checking\n * whether the module is imported at all; if not, we prepend a fresh\n * `from <module> import ...` line.\n */\nexport const addPythonDestructuredImport = async (\n tree: Tree,\n filePath: string,\n variableNames: string[],\n from: string,\n) => {\n assertFilePath(tree, filePath);\n\n // Determine whether there's any `from <module> import ...` line in the file.\n // We detect this by attempting a no-op transformation — the file is unchanged,\n // but a successful match tells us the line exists.\n const beforeContents = tree.read(filePath)!.toString();\n let moduleAlreadyImported = false;\n for (const variableName of variableNames) {\n // Appends the name if the import-from exists and the name isn't already there.\n const appended = await applyGritQL(\n tree,\n filePath,\n `language python\\n\\`from ${from} import $names\\` where { $names <: not contains \\`${variableName}\\`, $names += \\`, ${variableName}\\` }`,\n );\n if (appended) {\n moduleAlreadyImported = true;\n }\n }\n\n // If the append succeeded for at least one name, we know the module line\n // exists; we're done. If nothing was appended we need to distinguish\n // between \"module not imported\" (need to add a new line) and \"module\n // imported but all names already present\" (no-op).\n if (moduleAlreadyImported) {\n return;\n }\n\n const allAlreadyPresent = await matchGritQL(\n tree,\n filePath,\n `language python\\n\\`from ${from} import $names\\` where { ${variableNames\n .map((n) => `$names <: contains \\`${n}\\``)\n .join(', ')} }`,\n );\n if (allAlreadyPresent) {\n return;\n }\n\n // No existing `from <module> import` line — add one below any hashbang and\n // leading comment. Ruff's import sorter will place it in the right group on\n // the next formatter pass.\n const specifiers = variableNames.join(', ');\n tree.write(\n filePath,\n await insertBelowLeadingComments(\n tree,\n filePath,\n beforeContents,\n `from ${from} import ${specifiers}`,\n ),\n );\n};\n\n/**\n * Adds an `import <variableName> from '<from>'; statement to the beginning of the file,\n * if it doesn't already exist\n */\nexport const addSingleImport = async (\n tree: Tree,\n filePath: string,\n variableName: string,\n from: string,\n) => {\n assertFilePath(tree, filePath);\n from = normalizeModuleSpecifier(tree, from);\n\n // Check if default import already exists using GritQL\n const alreadyImported = await matchGritQL(\n tree,\n filePath,\n `\\`import ${variableName} from '${from}'\\``,\n );\n if (alreadyImported) {\n return;\n }\n\n // The same identifier bound to a different module would be a duplicate\n // declaration, so refuse rather than emit a file that cannot compile.\n const identifierTaken = await matchGritQL(\n tree,\n filePath,\n `\\`import ${variableName} from $module\\``,\n );\n if (identifierTaken) {\n throw new Error(\n `Cannot import ${variableName} from '${from}' in ${filePath}: ${variableName} is already imported from a different module. Rename the project so its generated identifier does not collide.`,\n );\n }\n\n // Add the import below any hashbang and leading comment\n const contents = tree.read(filePath)!.toString();\n tree.write(\n filePath,\n await insertBelowLeadingComments(\n tree,\n filePath,\n contents,\n `import ${variableName} from '${from}';`,\n ),\n );\n};\n\n/**\n * Adds an `export * from '<from>'; statement to the given TypeScript file.\n * Note that this will create the file if it does not exist in the tree.\n */\nexport const addStarExport = async (\n tree: Tree,\n filePath: string,\n from: string,\n) => {\n from = normalizeModuleSpecifier(tree, from);\n const contents = tree.read(filePath)?.toString() ?? '';\n\n // For empty/non-existent files, just write the export\n if (!contents.trim()) {\n tree.write(filePath, `export * from '${from}';\\n`);\n return;\n }\n\n // Check if already exported using GritQL\n const alreadyExported = await matchGritQL(\n tree,\n filePath,\n `\\`export * from '${from}'\\``,\n );\n if (alreadyExported) {\n return;\n }\n\n tree.write(\n filePath,\n await insertBelowLeadingComments(\n tree,\n filePath,\n contents,\n `export * from '${from}';`,\n ),\n );\n};\n\n/**\n * Adds an `export { <names> } from '<from>';` statement to the given TypeScript\n * file, merging into an existing re-export of the same module when there is one.\n * Note that this will create the file if it does not exist in the tree.\n *\n * Adding to whatever is already there is what lets a barrel the user curates —\n * their own entities, models or components — survive a generator re-run while\n * the generated entry is still registered.\n */\nexport const addNamedExport = async (\n tree: Tree,\n filePath: string,\n names: string[],\n from: string,\n) => {\n from = normalizeModuleSpecifier(tree, from);\n const contents = tree.read(filePath)?.toString() ?? '';\n\n if (!contents.trim()) {\n tree.write(filePath, `export { ${names.join(', ')} } from '${from}';\\n`);\n return;\n }\n\n const hasExistingExport = await matchGritQL(\n tree,\n filePath,\n `\\`export { $_ } from '${from}'\\``,\n );\n\n if (hasExistingExport) {\n for (const name of names) {\n await applyGritQL(\n tree,\n filePath,\n `\\`export { $names } from '${from}'\\` => \\`export { $names, ${name} } from '${from}'\\` where { $names <: not contains \\`${name}\\` }`,\n );\n }\n return;\n }\n\n const missing: string[] = [];\n for (const name of names) {\n if (!(await matchGritQL(tree, filePath, `\\`${name}\\``))) {\n missing.push(name);\n }\n }\n if (missing.length === 0) {\n return;\n }\n\n tree.write(\n filePath,\n await insertBelowLeadingComments(\n tree,\n filePath,\n contents,\n `export { ${missing.join(', ')} } from '${from}';`,\n ),\n );\n};\n\n/**\n * Return whether or not the given identifier is exported in the source file.\n * Checks for both `export { Identifier }` and `export type Identifier = ...`.\n */\nexport const hasExportDeclaration = async (\n tree: Tree,\n source: string,\n identifierName: string,\n): Promise<boolean> => {\n ensureGritDir(tree);\n const patterns = [\n `\\`export type ${identifierName} = $_\\``,\n `\\`export { ${identifierName} }\\``,\n `\\`export type { ${identifierName} } from $_\\``,\n ];\n\n for (const pattern of patterns) {\n try {\n const q = new QueryBuilder(`$p => $p where { $p <: ${pattern} }`);\n const result = await q.applyToFile({\n path: 'check.ts',\n content: source,\n });\n if (result !== null) return true;\n } catch {\n // Pattern didn't match, try next\n }\n }\n\n return false;\n};\n\n/**\n * Apply a GritQL pattern to a file in the Nx tree.\n */\nexport const applyGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<boolean> => {\n if (!tree.exists(filePath)) throw new Error(`No file at ${filePath}`);\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n const query = new QueryBuilder(pattern);\n const result = await query.applyToFile({ path: filePath, content: source });\n if (result && result.content !== source) {\n tree.write(filePath, result.content);\n return true;\n }\n return false;\n};\n\n/**\n * Check whether a GritQL pattern matches anywhere in a file.\n * Returns true if the pattern matches at least once.\n *\n * Accepts raw GritQL, including patterns that start with a `language <name>`\n * header (e.g. `language python\\n\\`print($_)\\``) — the pattern is passed\n * straight through to QueryBuilder without any wrapping rewrite.\n */\nexport const matchGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<boolean> => {\n if (!tree.exists(filePath)) return false;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n let matched = false;\n try {\n const query = new QueryBuilder(pattern);\n query.filter(() => {\n matched = true;\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return false;\n }\n return matched;\n};\n\n/**\n * Capture the source text of the first match of a GritQL pattern.\n *\n * For example `` `dependencyCheck: $_` `` returns the whole\n * `dependencyCheck: { ... }` property text. Returns undefined if nothing\n * matches. The file is not modified.\n */\nexport const captureGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<string | undefined> => {\n if (!tree.exists(filePath)) return undefined;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n let captured: string | undefined;\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n captured ??= node.text();\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return undefined;\n }\n return captured;\n};\n\n/**\n * Like `captureGritQL`, but returns one metavariable's binding (e.g. `mod`\n * for `$mod`) instead of the whole matched node.\n */\nexport const captureGritQLVariable = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n variableName: string,\n): Promise<string | undefined> => {\n if (!tree.exists(filePath)) return undefined;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n // The underlying binding lookup requires the `$` sigil.\n const name = variableName.startsWith('$') ? variableName : `$${variableName}`;\n let captured: string | undefined;\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n captured ??= node.var(name) ?? undefined;\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return undefined;\n }\n return captured;\n};\n\n/**\n * Like {@link captureAllGritQL}, but returns one metavariable's binding for every\n * match rather than the whole matched node.\n *\n * This is what lets a caller work on the value a pattern isolated — matching\n * `` `runtime: $value` `` and reading `$value` gives `Runtime.NODEJS_24_X` alone,\n * so nothing downstream has to re-derive the assignment around it.\n *\n * A match whose metavariable is unbound contributes nothing, so the result holds\n * only real bindings. Returns undefined if the pattern could not be applied,\n * which an empty array cannot express.\n */\nexport const captureAllGritQLVariable = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n variableName: string,\n): Promise<string[] | undefined> => {\n if (!tree.exists(filePath)) return undefined;\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n // The underlying binding lookup requires the `$` sigil.\n const name = variableName.startsWith('$') ? variableName : `$${variableName}`;\n const captured: string[] = [];\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n const bound = node.var(name);\n if (bound !== null && bound !== undefined) {\n captured.push(bound);\n }\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return undefined;\n }\n return captured;\n};\n\n/**\n * Return the text of every node matching the GritQL pattern, in document order.\n */\nexport const captureAllGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n): Promise<string[]> => {\n if (!tree.exists(filePath)) return [];\n ensureGritDir(tree);\n const source = tree.read(filePath)!.toString();\n const captured: string[] = [];\n try {\n const query = new QueryBuilder(pattern);\n query.filter((node) => {\n captured.push(node.text());\n return true;\n });\n await query.applyToFile({ path: filePath, content: source });\n } catch {\n return [];\n }\n return captured;\n};\n\n/**\n * A unique token that is a valid identifier, so it can stand in for an array\n * element or object property inside a GritQL rewrite.\n */\nexport const GRIT_INSERT_PLACEHOLDER = '__GRIT_INSERT_PLACEHOLDER__';\n\n/**\n * Apply a GritQL rewrite that inserts {@link GRIT_INSERT_PLACEHOLDER}, then\n * replace the placeholder with `text`. Routing user-provided text through a\n * placeholder keeps it out of the GritQL pattern, where quotes, backticks or\n * `${...}` would otherwise break parsing.\n *\n * Any separator (e.g. a leading `, ` when appending to an array) must be part\n * of the GritQL pattern, not `text`. The one adjustment made here: if the\n * placeholder lands after a trailing line comment (`// ...`) — which would\n * comment out the text — the text is moved to its own line.\n *\n * The caller formats afterwards. Returns true if the pattern matched and the\n * file changed.\n */\nexport const insertViaGritQL = async (\n tree: Tree,\n filePath: string,\n pattern: string,\n text: string,\n): Promise<boolean> => {\n if (!(await applyGritQL(tree, filePath, pattern))) return false;\n const content = tree.read(filePath)!.toString();\n const at = content.indexOf(GRIT_INSERT_PLACEHOLDER);\n const lineSoFar = content.slice(content.lastIndexOf('\\n', at) + 1, at);\n const replacement = lineSoFar.includes('//') ? `\\n${text}` : text;\n\n // Function replacer so `$` in `text` isn't treated as a replacement pattern.\n tree.write(\n filePath,\n content.replace(GRIT_INSERT_PLACEHOLDER, () => replacement),\n );\n return true;\n};\n\n/**\n * Append `entry` to an array, skipping arrays that already contain it, e.g.\n * `` appendToArrayViaGritQL(tree, file, 'tools:', 'myTool', { scope: 'new Agent($_)' }) ``\n * turns `tools: [a, b]` into `tools: [a, b, myTool]`.\n *\n * `arrayPrefix` is whatever precedes the array literal, including its separator —\n * `'tools:'` for an object property, `'tools='` for a keyword argument or\n * assignment, `'\"tools\":'` for a quoted key. Which separator applies depends on\n * the construct rather than the language, so the caller states it.\n *\n * Appends after the last *element* rather than rewriting the element list with\n * `=>`. GritQL binds a `[$items]` list to its trailing comma too, so\n * `` `[$items]` => `[$items, entry]` `` emits the sparse array `[a, b, , entry]`\n * once the formatter has wrapped the array — a hole that is `undefined` at\n * runtime. (Accumulating with `$items += \", entry\"` is safe by comparison, since\n * it appends within the list rather than re-emitting it; both forms appear in\n * this repo.)\n *\n * `scope` limits the match to an enclosing pattern, so same-named arrays\n * elsewhere in the file are left alone. `skipIfContains` overrides what the\n * append dedupes on, for when the rendered entry is not the identifier to match.\n *\n * The caller formats afterwards. Returns true if the entry was appended.\n */\nexport const appendToArrayViaGritQL = async (\n tree: Tree,\n filePath: string,\n arrayPrefix: string,\n entry: string,\n options: { scope?: string; skipIfContains?: string; language?: 'py' } = {},\n): Promise<boolean> => {\n const { scope, skipIfContains, language } = options;\n const within = (variable: string) =>\n scope ? `${variable} <: within \\`${scope}\\`, ` : '';\n const pattern =\n `or {` +\n // An empty array has no last element to append after.\n ` \\`${arrayPrefix}$arr\\` where { $arr <: \\`[]\\`, ${within('$arr')}` +\n ` $arr => \\`[${GRIT_INSERT_PLACEHOLDER}]\\` },` +\n // Dedupe on the list, append after its last element.\n ` \\`${arrayPrefix}[$items]\\` where {` +\n ` $items <: not contains \\`${skipIfContains ?? entry}\\`, ${within('$items')}` +\n ` $items <: [$..., $last], $last += \\`, ${GRIT_INSERT_PLACEHOLDER}\\` }` +\n ` }`;\n\n return insertViaGritQL(\n tree,\n filePath,\n language === 'py' ? `language python\\n${pattern}` : pattern,\n entry,\n );\n};\n"],"names":["QueryBuilder","path","LANGUAGE_COMMENT_SYNTAX","readLicenseConfig","parseFile","updateGitIgnore","isEsmWorkspace","GRIT_DIR","normalizeModuleSpecifier","tree","from","isRelative","startsWith","endsWith","slice","length","ensureGritDir","process","env","GRIT_GLOBAL_DIR","join","root","patterns","assertFilePath","filePath","exists","Error","insertBelowLeadingComments","contents","statement","extension","split","pop","syntax","source","header","commentSyntax","hashbang","body","addDestructuredImport","variableNames","hasExistingImport","matchGritQL","variableName","localName","includes","applyGritQL","specifiers","read","toString","write","addPythonDestructuredImport","beforeContents","moduleAlreadyImported","appended","allAlreadyPresent","map","n","addSingleImport","alreadyImported","identifierTaken","addStarExport","trim","alreadyExported","addNamedExport","names","hasExistingExport","name","missing","push","hasExportDeclaration","identifierName","pattern","q","result","applyToFile","content","query","matched","filter","captureGritQL","undefined","captured","node","text","captureGritQLVariable","var","captureAllGritQLVariable","bound","captureAllGritQL","GRIT_INSERT_PLACEHOLDER","insertViaGritQL","at","indexOf","lineSoFar","lastIndexOf","replacement","replace","appendToArrayViaGritQL","arrayPrefix","entry","options","scope","skipIfContains","language","within","variable"],"mappings":"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"}
|
|
@@ -16,3 +16,13 @@ export declare const catalogsEnabled: (tree: Tree) => boolean;
|
|
|
16
16
|
* and the root for shared tooling.
|
|
17
17
|
*/
|
|
18
18
|
export declare const addDependenciesToPackageJson: (tree: Tree, dependencies: Record<string, string>, devDependencies: Record<string, string>, packageJsonPath?: string) => GeneratorCallback;
|
|
19
|
+
/**
|
|
20
|
+
* Drop-in replacement for devkit's `removeDependenciesFromPackageJson` that
|
|
21
|
+
* also drops the package manager's catalog entry, which devkit leaves behind
|
|
22
|
+
* pointing at a package nothing declares any more.
|
|
23
|
+
*
|
|
24
|
+
* The entry is only dropped once no manifest in the workspace declares the
|
|
25
|
+
* package, so removing it from one project leaves another project's reference
|
|
26
|
+
* resolvable.
|
|
27
|
+
*/
|
|
28
|
+
export declare const removeDependenciesFromPackageJson: (tree: Tree, dependencies: string[], devDependencies: string[], packageJsonPath?: string) => GeneratorCallback;
|