@aws/nx-plugin 1.0.0-rc.93 → 1.0.0-rc.95
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/migrations.json +36 -1
- package/package.json +1 -1
- package/src/agentcore-harness/generator.d.ts +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/infra/app/generator.d.ts +1 -1
- package/src/infra/app/generator.js +5 -3
- package/src/infra/app/generator.js.map +1 -1
- package/src/init/generator.d.ts +1 -1
- package/src/migrations/latest/agent-connection-pin-strands-peers/metadata.json +3 -0
- package/src/migrations/latest/agent-connection-pin-strands-peers/migration.d.ts +18 -0
- package/src/migrations/latest/agent-connection-pin-strands-peers/migration.js +38 -0
- package/src/migrations/latest/agent-connection-pin-strands-peers/migration.js.map +1 -0
- package/src/migrations/latest/agent-core-vendor-target/metadata.json +3 -0
- package/src/migrations/latest/agent-core-vendor-target/migration.d.ts +6 -0
- package/src/migrations/latest/agent-core-vendor-target/migration.js +98 -0
- package/src/migrations/latest/agent-core-vendor-target/migration.js.map +1 -0
- package/src/migrations/latest/ignore-package-manager-temp-files/metadata.json +3 -0
- package/src/migrations/latest/ignore-package-manager-temp-files/migration.d.ts +12 -0
- package/src/migrations/latest/ignore-package-manager-temp-files/migration.js +25 -0
- package/src/migrations/latest/ignore-package-manager-temp-files/migration.js.map +1 -0
- package/src/migrations/latest/infra-deploy-express-mode/metadata.json +3 -0
- package/src/migrations/latest/infra-deploy-express-mode/migration.d.ts +6 -0
- package/src/migrations/latest/infra-deploy-express-mode/migration.js +83 -0
- package/src/migrations/latest/infra-deploy-express-mode/migration.js.map +1 -0
- package/src/migrations/latest/rolldown-config-bundle-transient/metadata.json +3 -0
- package/src/migrations/latest/rolldown-config-bundle-transient/migration.d.ts +6 -0
- package/src/migrations/latest/rolldown-config-bundle-transient/migration.js +80 -0
- package/src/migrations/latest/rolldown-config-bundle-transient/migration.js.map +1 -0
- package/src/migrations/latest/shadcn-package-imports-exports/metadata.json +3 -0
- package/src/migrations/latest/shadcn-package-imports-exports/migration.d.ts +6 -0
- package/src/migrations/latest/shadcn-package-imports-exports/migration.js +184 -0
- package/src/migrations/latest/shadcn-package-imports-exports/migration.js.map +1 -0
- package/src/migrations/latest/shx-fs-commands/metadata.json +3 -0
- package/src/migrations/latest/shx-fs-commands/migration.d.ts +6 -0
- package/src/migrations/latest/shx-fs-commands/migration.js +216 -0
- package/src/migrations/latest/shx-fs-commands/migration.js.map +1 -0
- package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +18 -12
- package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +5 -2
- package/src/open-api/utils/codegen-data/types.d.ts +6 -0
- package/src/open-api/utils/codegen-data/types.js.map +1 -1
- package/src/open-api/utils/codegen-data.js +32 -7
- package/src/open-api/utils/codegen-data.js.map +1 -1
- package/src/open-api/utils/normalise.js +39 -14
- package/src/open-api/utils/normalise.js.map +1 -1
- package/src/open-api/utils/parser.js +51 -5
- package/src/open-api/utils/parser.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +5 -1
- package/src/preset/generator.d.ts +1 -1
- 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/generator.d.ts +2 -26
- package/src/py/agent/generator.js +2 -2
- package/src/py/agent/generator.js.map +1 -1
- package/src/py/agent/mcp-connection/generator.d.ts +1 -1
- package/src/py/agent/react-connection/generator.d.ts +1 -1
- package/src/py/fast-api/generator.d.ts +1 -13
- package/src/py/fast-api/generator.js +1 -1
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/react/generator.d.ts +1 -1
- package/src/py/mcp-server/generator.d.ts +2 -26
- package/src/py/mcp-server/generator.js +2 -2
- package/src/py/mcp-server/generator.js.map +1 -1
- package/src/py/rdb/generator.d.ts +2 -26
- package/src/py/rdb/generator.js +6 -6
- package/src/py/rdb/generator.js.map +1 -1
- package/src/smithy/project/__snapshots__/generator.spec.ts.snap +24 -20
- package/src/smithy/project/generator.d.ts +2 -14
- package/src/smithy/project/generator.js +2 -1
- package/src/smithy/project/generator.js.map +1 -1
- package/src/smithy/react-connection/generator.d.ts +1 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +12 -8
- package/src/smithy/ts/api/generator.d.ts +1 -13
- package/src/smithy/ts/api/generator.js +1 -1
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/terraform/project/generator.d.ts +2 -2
- package/src/terraform/project/generator.js +4 -4
- package/src/terraform/project/generator.js.map +1 -1
- package/src/trpc/react/generator.d.ts +1 -1
- package/src/ts/agent/a2a-connection/generator.d.ts +5 -1
- package/src/ts/agent/gateway-connection/generator.d.ts +5 -1
- package/src/ts/agent/generator.d.ts +5 -37
- package/src/ts/agent/generator.js +1 -1
- package/src/ts/agent/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/generator.d.ts +5 -1
- package/src/ts/agent/react-connection/generator.d.ts +1 -1
- package/src/ts/astro-docs/generator.d.ts +1 -1
- package/src/ts/dcr-proxy/generator.d.ts +1 -1
- package/src/ts/dynamodb/generator.d.ts +1 -1
- package/src/ts/lambda-function/generator.d.ts +1 -1
- package/src/ts/lib/generator.d.ts +1 -1
- package/src/ts/mcp-server/generator.d.ts +3 -39
- package/src/ts/mcp-server/generator.js +1 -1
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/nx-generator/generator.d.ts +1 -1
- package/src/ts/nx-migration/generator.d.ts +1 -1
- package/src/ts/nx-plugin/generator.d.ts +1 -1
- package/src/ts/rdb/generator.d.ts +3 -27
- package/src/ts/rdb/generator.js +3 -3
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/react-website/agui/generator.d.ts +1 -1
- package/src/ts/react-website/agui/generator.js +2 -1
- package/src/ts/react-website/agui/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +2 -0
- package/src/ts/react-website/app/generator.js +2 -1
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/utils/agent-connection/agent-connection.d.ts +2 -0
- package/src/utils/agent-connection/agent-connection.js +11 -4
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-core-packaging.d.ts +25 -12
- package/src/utils/agent-core-packaging.js +47 -11
- package/src/utils/agent-core-packaging.js.map +1 -1
- package/src/utils/bundle/bundle.js +10 -0
- package/src/utils/bundle/bundle.js.map +1 -1
- package/src/utils/docker.d.ts +1 -7
- package/src/utils/docker.js +1 -1
- package/src/utils/docker.js.map +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/alert.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/avatar.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/breadcrumb.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/button.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/card.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/input.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/separator.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/sheet.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/sidebar.tsx.template +8 -8
- 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 -1
- package/src/utils/files/common/shadcn/src/components/ui/textarea.tsx.template +1 -1
- package/src/utils/files/common/shadcn/src/components/ui/tooltip.tsx.template +1 -1
- package/src/utils/files/shadcn/components.json.template +5 -5
- package/src/utils/format.d.ts +21 -0
- package/src/utils/format.js +20 -0
- package/src/utils/format.js.map +1 -1
- package/src/utils/fs.d.ts +21 -11
- package/src/utils/fs.js +30 -22
- package/src/utils/fs.js.map +1 -1
- package/src/utils/init.js +11 -4
- package/src/utils/init.js.map +1 -1
- package/src/utils/pnpm-workspace.d.ts +5 -5
- package/src/utils/pnpm-workspace.js +5 -5
- package/src/utils/pnpm-workspace.js.map +1 -1
- package/src/utils/shared-shadcn.d.ts +9 -0
- package/src/utils/shared-shadcn.js +36 -26
- package/src/utils/shared-shadcn.js.map +1 -1
- package/src/utils/version-lockstep/lockstep.d.ts +27 -0
- package/src/utils/version-lockstep/lockstep.js +46 -0
- package/src/utils/version-lockstep/lockstep.js.map +1 -0
- package/src/utils/versions.d.ts +9 -4
- package/src/utils/versions.js +24 -4
- package/src/utils/versions.js.map +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, updateProjectConfiguration } from "@nx/devkit";
|
|
5
|
+
import { INFRA_APP_GENERATOR_INFO } from "../../../infra/app/generator.js";
|
|
6
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
7
|
+
/**
|
|
8
|
+
* Deploy using CloudFormation express mode from the deploy and deploy-sandbox
|
|
9
|
+
* targets of ts#infra projects
|
|
10
|
+
*
|
|
11
|
+
* Express mode completes each resource operation as soon as its configuration
|
|
12
|
+
* is applied rather than waiting for full stabilization, which is a much faster
|
|
13
|
+
* iteration cycle for development deploys.
|
|
14
|
+
*
|
|
15
|
+
* Two targets keep waiting for full stabilization: `deploy-ci`, since pipeline
|
|
16
|
+
* deployments should never skip it, and - when stages are configured - `deploy`,
|
|
17
|
+
* which deploys whichever stage is named, including beta and prod.
|
|
18
|
+
*/ const DEPLOY_TARGETS = [
|
|
19
|
+
'deploy',
|
|
20
|
+
'deploy-sandbox'
|
|
21
|
+
];
|
|
22
|
+
const EXPRESS_FLAG = '--express';
|
|
23
|
+
/**
|
|
24
|
+
* Whether the command is one of the deploy commands this migration vends -
|
|
25
|
+
* either a direct `cdk deploy`, or the stage-config `infra-deploy.ts` script
|
|
26
|
+
* that wraps it. Anything else has been hand-written and is reported rather
|
|
27
|
+
* than rewritten.
|
|
28
|
+
*/ const isGeneratedDeployCommand = (command)=>/(^|\s)cdk\s+deploy(\s|$)/.test(command) || command.includes('infra-deploy.ts');
|
|
29
|
+
/** Whether the command runs the stage-config deploy script. */ const isStageConfigDeploy = (command)=>command.includes('infra-deploy.ts');
|
|
30
|
+
const divergedNextStep = (projectName, target)=>`${projectName}: its ${target} target has been customised, so it was left as it is. Add "${EXPRESS_FLAG}" to the target's command to deploy using CloudFormation express mode.`;
|
|
31
|
+
export default async function migration(tree) {
|
|
32
|
+
const nextSteps = [];
|
|
33
|
+
let migrated = false;
|
|
34
|
+
for (const [name, project] of getProjects(tree)){
|
|
35
|
+
if (project.metadata?.generator !== INFRA_APP_GENERATOR_INFO.id) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
let projectChanged = false;
|
|
39
|
+
for (const targetName of DEPLOY_TARGETS){
|
|
40
|
+
const target = project.targets?.[targetName];
|
|
41
|
+
const command = target?.options?.command;
|
|
42
|
+
if (!target || typeof command !== 'string') {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// Already migrated (or generated by a version that already passes it) -
|
|
46
|
+
// skip so re-running is a no-op.
|
|
47
|
+
if (command.split(/\s+/).includes(EXPRESS_FLAG)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
// `--no-express` is a deliberate opt-out, so honour it rather than
|
|
51
|
+
// flipping the user back to express mode.
|
|
52
|
+
if (command.split(/\s+/).includes('--no-express')) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (!isGeneratedDeployCommand(command)) {
|
|
56
|
+
nextSteps.push(divergedNextStep(name, targetName));
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// When stages are configured, `deploy` deploys whichever stage is named,
|
|
60
|
+
// including beta and prod, so it stays on full stabilization. Only its
|
|
61
|
+
// sandbox counterpart opts into express mode.
|
|
62
|
+
if (targetName === 'deploy' && isStageConfigDeploy(command)) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Appended last so it stays clear of the stage pattern, which the
|
|
66
|
+
// stage-config deploy script reads from the first positional argument.
|
|
67
|
+
target.options.command = `${command} ${EXPRESS_FLAG}`;
|
|
68
|
+
projectChanged = true;
|
|
69
|
+
}
|
|
70
|
+
if (projectChanged) {
|
|
71
|
+
updateProjectConfiguration(tree, name, project);
|
|
72
|
+
migrated = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (migrated) {
|
|
76
|
+
await formatFilesInSubtree(tree);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
nextSteps
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/infra-deploy-express-mode/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n type MigrationReturnObject,\n type TargetConfiguration,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { INFRA_APP_GENERATOR_INFO } from '../../../infra/app/generator.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\n\n/**\n * Deploy using CloudFormation express mode from the deploy and deploy-sandbox\n * targets of ts#infra projects\n *\n * Express mode completes each resource operation as soon as its configuration\n * is applied rather than waiting for full stabilization, which is a much faster\n * iteration cycle for development deploys.\n *\n * Two targets keep waiting for full stabilization: `deploy-ci`, since pipeline\n * deployments should never skip it, and - when stages are configured - `deploy`,\n * which deploys whichever stage is named, including beta and prod.\n */\n\nconst DEPLOY_TARGETS = ['deploy', 'deploy-sandbox'];\n\nconst EXPRESS_FLAG = '--express';\n\n/**\n * Whether the command is one of the deploy commands this migration vends -\n * either a direct `cdk deploy`, or the stage-config `infra-deploy.ts` script\n * that wraps it. Anything else has been hand-written and is reported rather\n * than rewritten.\n */\nconst isGeneratedDeployCommand = (command: string): boolean =>\n /(^|\\s)cdk\\s+deploy(\\s|$)/.test(command) ||\n command.includes('infra-deploy.ts');\n\n/** Whether the command runs the stage-config deploy script. */\nconst isStageConfigDeploy = (command: string): boolean =>\n command.includes('infra-deploy.ts');\n\nconst divergedNextStep = (projectName: string, target: string): string =>\n `${projectName}: its ${target} target has been customised, so it was left as it is. Add \"${EXPRESS_FLAG}\" to the target's command to deploy using CloudFormation express mode.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n let migrated = false;\n\n for (const [name, project] of getProjects(tree)) {\n if (\n (project.metadata as { generator?: string } | undefined)?.generator !==\n INFRA_APP_GENERATOR_INFO.id\n ) {\n continue;\n }\n\n let projectChanged = false;\n\n for (const targetName of DEPLOY_TARGETS) {\n const target: TargetConfiguration | undefined =\n project.targets?.[targetName];\n const command = target?.options?.command;\n if (!target || typeof command !== 'string') {\n continue;\n }\n\n // Already migrated (or generated by a version that already passes it) -\n // skip so re-running is a no-op.\n if (command.split(/\\s+/).includes(EXPRESS_FLAG)) {\n continue;\n }\n\n // `--no-express` is a deliberate opt-out, so honour it rather than\n // flipping the user back to express mode.\n if (command.split(/\\s+/).includes('--no-express')) {\n continue;\n }\n\n if (!isGeneratedDeployCommand(command)) {\n nextSteps.push(divergedNextStep(name, targetName));\n continue;\n }\n\n // When stages are configured, `deploy` deploys whichever stage is named,\n // including beta and prod, so it stays on full stabilization. Only its\n // sandbox counterpart opts into express mode.\n if (targetName === 'deploy' && isStageConfigDeploy(command)) {\n continue;\n }\n\n // Appended last so it stays clear of the stage pattern, which the\n // stage-config deploy script reads from the first positional argument.\n target.options.command = `${command} ${EXPRESS_FLAG}`;\n projectChanged = true;\n }\n\n if (projectChanged) {\n updateProjectConfiguration(tree, name, project);\n migrated = true;\n }\n }\n\n if (migrated) {\n await formatFilesInSubtree(tree);\n }\n\n return { nextSteps };\n}\n"],"names":["getProjects","updateProjectConfiguration","INFRA_APP_GENERATOR_INFO","formatFilesInSubtree","DEPLOY_TARGETS","EXPRESS_FLAG","isGeneratedDeployCommand","command","test","includes","isStageConfigDeploy","divergedNextStep","projectName","target","migration","tree","nextSteps","migrated","name","project","metadata","generator","id","projectChanged","targetName","targets","options","split","push"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EAIXC,0BAA0B,QACrB,aAAa;AACpB,SAASC,wBAAwB,QAAQ,kCAAkC;AAC3E,SAASC,oBAAoB,QAAQ,2BAA2B;AAEhE;;;;;;;;;;;CAWC,GAED,MAAMC,iBAAiB;IAAC;IAAU;CAAiB;AAEnD,MAAMC,eAAe;AAErB;;;;;CAKC,GACD,MAAMC,2BAA2B,CAACC,UAChC,2BAA2BC,IAAI,CAACD,YAChCA,QAAQE,QAAQ,CAAC;AAEnB,6DAA6D,GAC7D,MAAMC,sBAAsB,CAACH,UAC3BA,QAAQE,QAAQ,CAAC;AAEnB,MAAME,mBAAmB,CAACC,aAAqBC,SAC7C,GAAGD,YAAY,MAAM,EAAEC,OAAO,2DAA2D,EAAER,aAAa,sEAAsE,CAAC;AAEjL,eAAe,eAAeS,UAC5BC,IAAU;IAEV,MAAMC,YAAsB,EAAE;IAC9B,IAAIC,WAAW;IAEf,KAAK,MAAM,CAACC,MAAMC,QAAQ,IAAInB,YAAYe,MAAO;QAC/C,IACE,AAACI,QAAQC,QAAQ,EAAyCC,cAC1DnB,yBAAyBoB,EAAE,EAC3B;YACA;QACF;QAEA,IAAIC,iBAAiB;QAErB,KAAK,MAAMC,cAAcpB,eAAgB;YACvC,MAAMS,SACJM,QAAQM,OAAO,EAAE,CAACD,WAAW;YAC/B,MAAMjB,UAAUM,QAAQa,SAASnB;YACjC,IAAI,CAACM,UAAU,OAAON,YAAY,UAAU;gBAC1C;YACF;YAEA,wEAAwE;YACxE,iCAAiC;YACjC,IAAIA,QAAQoB,KAAK,CAAC,OAAOlB,QAAQ,CAACJ,eAAe;gBAC/C;YACF;YAEA,mEAAmE;YACnE,0CAA0C;YAC1C,IAAIE,QAAQoB,KAAK,CAAC,OAAOlB,QAAQ,CAAC,iBAAiB;gBACjD;YACF;YAEA,IAAI,CAACH,yBAAyBC,UAAU;gBACtCS,UAAUY,IAAI,CAACjB,iBAAiBO,MAAMM;gBACtC;YACF;YAEA,yEAAyE;YACzE,uEAAuE;YACvE,8CAA8C;YAC9C,IAAIA,eAAe,YAAYd,oBAAoBH,UAAU;gBAC3D;YACF;YAEA,kEAAkE;YAClE,uEAAuE;YACvEM,OAAOa,OAAO,CAACnB,OAAO,GAAG,GAAGA,QAAQ,CAAC,EAAEF,cAAc;YACrDkB,iBAAiB;QACnB;QAEA,IAAIA,gBAAgB;YAClBtB,2BAA2Bc,MAAMG,MAAMC;YACvCF,WAAW;QACb;IACF;IAEA,IAAIA,UAAU;QACZ,MAAMd,qBAAqBY;IAC7B;IAEA,OAAO;QAAEC;IAAU;AACrB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, joinPathFragments, updateJson } from "@nx/devkit";
|
|
5
|
+
import { BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE, formatFilesInSubtree, ROLLDOWN_CONFIG_BUNDLE_GLOB } from "../../../utils/format.js";
|
|
6
|
+
import { updateGitIgnore } from "../../../utils/git.js";
|
|
7
|
+
/**
|
|
8
|
+
* Keep rolldown's transient config bundle out of Biome's and git's reach.
|
|
9
|
+
*
|
|
10
|
+
* Loading a `rolldown.config.ts` bundles it to `rolldown.config.<hash>.js` in the
|
|
11
|
+
* config's own directory, imports it, then unlinks it. The `bundle`, `format` and
|
|
12
|
+
* `lint` targets of a project all run concurrently, so a `format` sweeping the
|
|
13
|
+
* project mid-bundle sees a machine-generated file and reports it unformatted —
|
|
14
|
+
* failing the target for no fault of the source. Being git-visible, the file
|
|
15
|
+
* could also be committed, or picked up by `license#sync`, which builds its
|
|
16
|
+
* candidate set from git-visible files rather than from `biome.json`.
|
|
17
|
+
*
|
|
18
|
+
* Guardrails:
|
|
19
|
+
* - The Biome exclude is anchored to the excludes we vend. A workspace whose
|
|
20
|
+
* `files.includes` has diverged keeps its own list, and is reported via
|
|
21
|
+
* `nextSteps` instead.
|
|
22
|
+
* - Only projects carrying a `rolldown.config.ts` get the git ignore, matching
|
|
23
|
+
* where the generator writes it.
|
|
24
|
+
* - Idempotent: both edits are guarded on the pattern already being present.
|
|
25
|
+
*/ /** The config filename whose loading produces the transient bundle. */ const ROLLDOWN_CONFIG = 'rolldown.config.ts';
|
|
26
|
+
/**
|
|
27
|
+
* Exclude the transient bundle from Biome. Anchored to `!**\/out-tsc`, the
|
|
28
|
+
* build-output exclude the vended list places these next to — without it the list
|
|
29
|
+
* has diverged from the one we vend, so leave it to the user.
|
|
30
|
+
*/ const excludeFromBiome = (tree)=>{
|
|
31
|
+
if (!tree.exists('biome.json')) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
let unrecognised = false;
|
|
35
|
+
updateJson(tree, 'biome.json', (biome)=>{
|
|
36
|
+
const includes = biome?.files?.includes;
|
|
37
|
+
if (!Array.isArray(includes) || includes.includes(BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE)) {
|
|
38
|
+
return biome;
|
|
39
|
+
}
|
|
40
|
+
if (!includes.includes('!**/out-tsc')) {
|
|
41
|
+
unrecognised = true;
|
|
42
|
+
return biome;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
...biome,
|
|
46
|
+
files: {
|
|
47
|
+
...biome.files,
|
|
48
|
+
includes: includes.flatMap((include)=>include === '!**/out-tsc' ? [
|
|
49
|
+
include,
|
|
50
|
+
BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE
|
|
51
|
+
] : [
|
|
52
|
+
include
|
|
53
|
+
])
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
return unrecognised ? [
|
|
58
|
+
`\`biome.json\`: add \`"${BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE}"\` to \`files.includes\` so the transient bundle rolldown writes while loading a TypeScript config is never formatted or linted. Its \`files.includes\` has diverged from the vended list, so it was left as it is.`
|
|
59
|
+
] : [];
|
|
60
|
+
};
|
|
61
|
+
export default async function migration(tree) {
|
|
62
|
+
const nextSteps = [
|
|
63
|
+
...excludeFromBiome(tree)
|
|
64
|
+
];
|
|
65
|
+
for (const [, project] of getProjects(tree)){
|
|
66
|
+
if (!tree.exists(joinPathFragments(project.root, ROLLDOWN_CONFIG))) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
updateGitIgnore(tree, project.root, (patterns)=>patterns.includes(ROLLDOWN_CONFIG_BUNDLE_GLOB) ? patterns : [
|
|
70
|
+
...patterns,
|
|
71
|
+
ROLLDOWN_CONFIG_BUNDLE_GLOB
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
await formatFilesInSubtree(tree);
|
|
75
|
+
return {
|
|
76
|
+
nextSteps
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/rolldown-config-bundle-transient/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport {\n BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE,\n formatFilesInSubtree,\n ROLLDOWN_CONFIG_BUNDLE_GLOB,\n} from '../../../utils/format.js';\nimport { updateGitIgnore } from '../../../utils/git.js';\n\n/**\n * Keep rolldown's transient config bundle out of Biome's and git's reach.\n *\n * Loading a `rolldown.config.ts` bundles it to `rolldown.config.<hash>.js` in the\n * config's own directory, imports it, then unlinks it. The `bundle`, `format` and\n * `lint` targets of a project all run concurrently, so a `format` sweeping the\n * project mid-bundle sees a machine-generated file and reports it unformatted —\n * failing the target for no fault of the source. Being git-visible, the file\n * could also be committed, or picked up by `license#sync`, which builds its\n * candidate set from git-visible files rather than from `biome.json`.\n *\n * Guardrails:\n * - The Biome exclude is anchored to the excludes we vend. A workspace whose\n * `files.includes` has diverged keeps its own list, and is reported via\n * `nextSteps` instead.\n * - Only projects carrying a `rolldown.config.ts` get the git ignore, matching\n * where the generator writes it.\n * - Idempotent: both edits are guarded on the pattern already being present.\n */\n\n/** The config filename whose loading produces the transient bundle. */\nconst ROLLDOWN_CONFIG = 'rolldown.config.ts';\n\n/**\n * Exclude the transient bundle from Biome. Anchored to `!**\\/out-tsc`, the\n * build-output exclude the vended list places these next to — without it the list\n * has diverged from the one we vend, so leave it to the user.\n */\nconst excludeFromBiome = (tree: Tree): string[] => {\n if (!tree.exists('biome.json')) {\n return [];\n }\n let unrecognised = false;\n updateJson(tree, 'biome.json', (biome) => {\n const includes: unknown = biome?.files?.includes;\n if (\n !Array.isArray(includes) ||\n includes.includes(BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE)\n ) {\n return biome;\n }\n if (!includes.includes('!**/out-tsc')) {\n unrecognised = true;\n return biome;\n }\n return {\n ...biome,\n files: {\n ...biome.files,\n includes: includes.flatMap((include) =>\n include === '!**/out-tsc'\n ? [include, BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE]\n : [include],\n ),\n },\n };\n });\n return unrecognised\n ? [\n `\\`biome.json\\`: add \\`\"${BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE}\"\\` to \\`files.includes\\` so the transient bundle rolldown writes while loading a TypeScript config is never formatted or linted. Its \\`files.includes\\` has diverged from the vended list, so it was left as it is.`,\n ]\n : [];\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [...excludeFromBiome(tree)];\n\n for (const [, project] of getProjects(tree)) {\n if (!tree.exists(joinPathFragments(project.root, ROLLDOWN_CONFIG))) {\n continue;\n }\n updateGitIgnore(tree, project.root, (patterns) =>\n patterns.includes(ROLLDOWN_CONFIG_BUNDLE_GLOB)\n ? patterns\n : [...patterns, ROLLDOWN_CONFIG_BUNDLE_GLOB],\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","updateJson","BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE","formatFilesInSubtree","ROLLDOWN_CONFIG_BUNDLE_GLOB","updateGitIgnore","ROLLDOWN_CONFIG","excludeFromBiome","tree","exists","unrecognised","biome","includes","files","Array","isArray","flatMap","include","migration","nextSteps","project","root","patterns"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SACEC,oCAAoC,EACpCC,oBAAoB,EACpBC,2BAA2B,QACtB,2BAA2B;AAClC,SAASC,eAAe,QAAQ,wBAAwB;AAExD;;;;;;;;;;;;;;;;;;CAkBC,GAED,qEAAqE,GACrE,MAAMC,kBAAkB;AAExB;;;;CAIC,GACD,MAAMC,mBAAmB,CAACC;IACxB,IAAI,CAACA,KAAKC,MAAM,CAAC,eAAe;QAC9B,OAAO,EAAE;IACX;IACA,IAAIC,eAAe;IACnBT,WAAWO,MAAM,cAAc,CAACG;QAC9B,MAAMC,WAAoBD,OAAOE,OAAOD;QACxC,IACE,CAACE,MAAMC,OAAO,CAACH,aACfA,SAASA,QAAQ,CAACV,uCAClB;YACA,OAAOS;QACT;QACA,IAAI,CAACC,SAASA,QAAQ,CAAC,gBAAgB;YACrCF,eAAe;YACf,OAAOC;QACT;QACA,OAAO;YACL,GAAGA,KAAK;YACRE,OAAO;gBACL,GAAGF,MAAME,KAAK;gBACdD,UAAUA,SAASI,OAAO,CAAC,CAACC,UAC1BA,YAAY,gBACR;wBAACA;wBAASf;qBAAqC,GAC/C;wBAACe;qBAAQ;YAEjB;QACF;IACF;IACA,OAAOP,eACH;QACE,CAAC,uBAAuB,EAAER,qCAAqC,oNAAoN,CAAC;KACrR,GACD,EAAE;AACR;AAEA,eAAe,eAAegB,UAC5BV,IAAU;IAEV,MAAMW,YAAsB;WAAIZ,iBAAiBC;KAAM;IAEvD,KAAK,MAAM,GAAGY,QAAQ,IAAIrB,YAAYS,MAAO;QAC3C,IAAI,CAACA,KAAKC,MAAM,CAACT,kBAAkBoB,QAAQC,IAAI,EAAEf,mBAAmB;YAClE;QACF;QACAD,gBAAgBG,MAAMY,QAAQC,IAAI,EAAE,CAACC,WACnCA,SAASV,QAAQ,CAACR,+BACdkB,WACA;mBAAIA;gBAAUlB;aAA4B;IAElD;IAEA,MAAMD,qBAAqBK;IAE3B,OAAO;QAAEW;IAAU;AACrB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, joinPathFragments, readJson, updateJson } from "@nx/devkit";
|
|
5
|
+
import { REACT_WEBSITE_APP_GENERATOR_INFO } from "../../../ts/react-website/app/generator.js";
|
|
6
|
+
import { applyGritQL, matchGritQL } from "../../../utils/ast.js";
|
|
7
|
+
import { addDependenciesToPackageJson, getLocalDependencySpecifier } from "../../../utils/dependencies.js";
|
|
8
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
9
|
+
import { PACKAGES_DIR, SHARED_SHADCN_DIR } from "../../../utils/shared-constructs-constants.js";
|
|
10
|
+
import { getSharedShadcnFullyQualifiedName } from "../../../utils/shared-shadcn.js";
|
|
11
|
+
/**
|
|
12
|
+
* Move the shared shadcn package off a `tsconfig.base.json` `paths` alias onto
|
|
13
|
+
* `package.json` `imports`/`exports`.
|
|
14
|
+
*
|
|
15
|
+
* shadcn 4.x's CLI resolves `components.json`'s aliases via Node's package
|
|
16
|
+
* resolution (`imports`/`exports`), not tsconfig `paths` - its own resolver
|
|
17
|
+
* naively joins a tsconfig-declared alias against whichever directory it's
|
|
18
|
+
* invoked from, so the repo-root-relative `paths` mapping this plugin used to
|
|
19
|
+
* vend breaks the moment `shadcn add` is run with `-c packages/common/shadcn`
|
|
20
|
+
* (as its own monorepo-root preflight now tells the user to). This migration
|
|
21
|
+
* carries an existing workspace onto the shape today's generators produce:
|
|
22
|
+
* local `#...` imports for the package's own internal component references,
|
|
23
|
+
* a public `exports` map for every other consumer, and a real `workspace:*`
|
|
24
|
+
* dependency on each consumer so that map actually resolves.
|
|
25
|
+
*
|
|
26
|
+
* How to write a migration:
|
|
27
|
+
* - https://nx.dev/docs/kb/migration-generators
|
|
28
|
+
* - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject
|
|
29
|
+
*
|
|
30
|
+
* Guardrails:
|
|
31
|
+
* - Only touches a `packages/common/shadcn` this plugin's generators produced
|
|
32
|
+
* (guarded by `components.json`'s aliases still matching the old shape).
|
|
33
|
+
* - Internal imports are rewritten by exact module specifier per file found
|
|
34
|
+
* under `src/{components/ui,lib,hooks}`, so a component a user added by hand
|
|
35
|
+
* after the original generation is covered too, and a specifier the
|
|
36
|
+
* migration doesn't recognise is left alone and reported.
|
|
37
|
+
* - Idempotent: every write is guarded by the old shape still being present.
|
|
38
|
+
*/ const libraryRoot = joinPathFragments(PACKAGES_DIR, SHARED_SHADCN_DIR);
|
|
39
|
+
const componentsJsonPath = joinPathFragments(libraryRoot, 'components.json');
|
|
40
|
+
const packageJsonPath = joinPathFragments(libraryRoot, 'package.json');
|
|
41
|
+
const oldAliases = (fqn)=>({
|
|
42
|
+
components: `${fqn}/components`,
|
|
43
|
+
utils: `${fqn}/lib/utils`,
|
|
44
|
+
hooks: `${fqn}/hooks`,
|
|
45
|
+
lib: `${fqn}/lib`,
|
|
46
|
+
ui: `${fqn}/components/ui`
|
|
47
|
+
});
|
|
48
|
+
const newAliases = {
|
|
49
|
+
components: '#components',
|
|
50
|
+
utils: '#lib/utils',
|
|
51
|
+
hooks: '#hooks',
|
|
52
|
+
lib: '#lib',
|
|
53
|
+
ui: '#components/ui'
|
|
54
|
+
};
|
|
55
|
+
const newPackageManifestFields = {
|
|
56
|
+
imports: {
|
|
57
|
+
'#components/*': './src/components/*.tsx',
|
|
58
|
+
'#lib/*': './src/lib/*.ts',
|
|
59
|
+
'#hooks/*': './src/hooks/*.ts'
|
|
60
|
+
},
|
|
61
|
+
exports: {
|
|
62
|
+
'.': './src/index.ts',
|
|
63
|
+
'./styles/*': './src/styles/*',
|
|
64
|
+
'./components/*': './src/components/*.tsx',
|
|
65
|
+
'./lib/*': './src/lib/*.ts',
|
|
66
|
+
'./hooks/*': './src/hooks/*.ts'
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Rewrite an import's module specifier, keeping its bindings - `$bindings`
|
|
71
|
+
* holds whatever the file imports, so a binding a user added survives.
|
|
72
|
+
*/ const importPattern = (from, to)=>`\`import { $bindings } from '${from}'\` => \`import { $bindings } from '${to}'\``;
|
|
73
|
+
/** Whether the file still imports the old specifier under any other form. */ const hasRemainingImport = (from)=>`\`import $_ from '${from}'\``;
|
|
74
|
+
export default async function migration(tree) {
|
|
75
|
+
const nextSteps = [];
|
|
76
|
+
if (!tree.exists(componentsJsonPath) || !tree.exists(packageJsonPath)) {
|
|
77
|
+
return {
|
|
78
|
+
nextSteps
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const fullyQualifiedName = getSharedShadcnFullyQualifiedName(tree);
|
|
82
|
+
const currentAliases = readJson(tree, componentsJsonPath).aliases ?? {};
|
|
83
|
+
const expectedOldAliases = oldAliases(fullyQualifiedName);
|
|
84
|
+
const onOldShape = Object.keys(newAliases).every((key)=>currentAliases[key] === expectedOldAliases[key]);
|
|
85
|
+
if (!onOldShape) {
|
|
86
|
+
if (Object.keys(newAliases).some((key)=>currentAliases[key] !== newAliases[key])) {
|
|
87
|
+
nextSteps.push(`${componentsJsonPath}: aliases have diverged from both the old and current generated shape - left untouched. Migrate them to the shadcn CLI's imports/exports monorepo pattern by hand: https://ui.shadcn.com/docs/monorepo`);
|
|
88
|
+
}
|
|
89
|
+
await formatFilesInSubtree(tree);
|
|
90
|
+
return {
|
|
91
|
+
nextSteps
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// Rewrite every source file's internal references to this package's own
|
|
95
|
+
// components/lib/hooks, keyed off the files actually present so a
|
|
96
|
+
// hand-added component is covered too.
|
|
97
|
+
const internalDirs = [
|
|
98
|
+
{
|
|
99
|
+
dir: joinPathFragments(libraryRoot, 'src', 'components', 'ui'),
|
|
100
|
+
extension: '.tsx',
|
|
101
|
+
oldSubpath: 'components/ui',
|
|
102
|
+
newPrefix: '#components/ui'
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
dir: joinPathFragments(libraryRoot, 'src', 'lib'),
|
|
106
|
+
extension: '.ts',
|
|
107
|
+
oldSubpath: 'lib',
|
|
108
|
+
newPrefix: '#lib'
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
dir: joinPathFragments(libraryRoot, 'src', 'hooks'),
|
|
112
|
+
extension: '.ts',
|
|
113
|
+
oldSubpath: 'hooks',
|
|
114
|
+
newPrefix: '#hooks'
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
const renames = [];
|
|
118
|
+
const sourceFiles = [];
|
|
119
|
+
for (const { dir, extension, oldSubpath, newPrefix } of internalDirs){
|
|
120
|
+
if (!tree.exists(dir)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
for (const entry of tree.children(dir)){
|
|
124
|
+
if (!entry.endsWith(extension)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const baseName = entry.slice(0, -extension.length);
|
|
128
|
+
renames.push({
|
|
129
|
+
old: `${fullyQualifiedName}/${oldSubpath}/${baseName}`,
|
|
130
|
+
renamed: `${newPrefix}/${baseName}`
|
|
131
|
+
});
|
|
132
|
+
sourceFiles.push(joinPathFragments(dir, entry));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const sourceFile of sourceFiles){
|
|
136
|
+
for (const { old, renamed } of renames){
|
|
137
|
+
await applyGritQL(tree, sourceFile, importPattern(old, renamed));
|
|
138
|
+
// A namespace or default import of the same specifier is left as it
|
|
139
|
+
// is - reported rather than rewritten, so a diverged file is never
|
|
140
|
+
// clobbered.
|
|
141
|
+
if (await matchGritQL(tree, sourceFile, hasRemainingImport(old))) {
|
|
142
|
+
nextSteps.push(`${sourceFile}: still imports '${old}' in a form this migration does not rewrite - update it to '${renamed}' by hand.`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
updateJson(tree, componentsJsonPath, (json)=>({
|
|
147
|
+
...json,
|
|
148
|
+
aliases: newAliases
|
|
149
|
+
}));
|
|
150
|
+
updateJson(tree, packageJsonPath, (json)=>({
|
|
151
|
+
...json,
|
|
152
|
+
...newPackageManifestFields
|
|
153
|
+
}));
|
|
154
|
+
updateJson(tree, 'tsconfig.base.json', (json)=>{
|
|
155
|
+
const paths = {
|
|
156
|
+
...json.compilerOptions?.paths ?? {}
|
|
157
|
+
};
|
|
158
|
+
delete paths[`${fullyQualifiedName}/*`];
|
|
159
|
+
return {
|
|
160
|
+
...json,
|
|
161
|
+
compilerOptions: {
|
|
162
|
+
...json.compilerOptions,
|
|
163
|
+
paths
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
// Every website generated with ux=shadcn needs a real dependency on the
|
|
168
|
+
// shared package now that it resolves through `exports`, not `paths`.
|
|
169
|
+
for (const project of getProjects(tree).values()){
|
|
170
|
+
const metadata = project.metadata;
|
|
171
|
+
if (metadata?.generator !== REACT_WEBSITE_APP_GENERATOR_INFO.id || metadata.ux !== 'shadcn') {
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
addDependenciesToPackageJson(tree, {
|
|
175
|
+
[fullyQualifiedName]: getLocalDependencySpecifier(tree)
|
|
176
|
+
}, {}, joinPathFragments(project.root, 'package.json'));
|
|
177
|
+
}
|
|
178
|
+
await formatFilesInSubtree(tree);
|
|
179
|
+
return {
|
|
180
|
+
nextSteps
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/shadcn-package-imports-exports/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n readJson,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { REACT_WEBSITE_APP_GENERATOR_INFO } from '../../../ts/react-website/app/generator.js';\nimport { applyGritQL, matchGritQL } from '../../../utils/ast.js';\nimport {\n addDependenciesToPackageJson,\n getLocalDependencySpecifier,\n} from '../../../utils/dependencies.js';\nimport { formatFilesInSubtree } from '../../../utils/format.js';\nimport {\n PACKAGES_DIR,\n SHARED_SHADCN_DIR,\n} from '../../../utils/shared-constructs-constants.js';\nimport { getSharedShadcnFullyQualifiedName } from '../../../utils/shared-shadcn.js';\n\n/**\n * Move the shared shadcn package off a `tsconfig.base.json` `paths` alias onto\n * `package.json` `imports`/`exports`.\n *\n * shadcn 4.x's CLI resolves `components.json`'s aliases via Node's package\n * resolution (`imports`/`exports`), not tsconfig `paths` - its own resolver\n * naively joins a tsconfig-declared alias against whichever directory it's\n * invoked from, so the repo-root-relative `paths` mapping this plugin used to\n * vend breaks the moment `shadcn add` is run with `-c packages/common/shadcn`\n * (as its own monorepo-root preflight now tells the user to). This migration\n * carries an existing workspace onto the shape today's generators produce:\n * local `#...` imports for the package's own internal component references,\n * a public `exports` map for every other consumer, and a real `workspace:*`\n * dependency on each consumer so that map actually resolves.\n *\n * How to write a migration:\n * - https://nx.dev/docs/kb/migration-generators\n * - What `nextSteps` means: https://nx.dev/docs/reference/devkit/MigrationReturnObject\n *\n * Guardrails:\n * - Only touches a `packages/common/shadcn` this plugin's generators produced\n * (guarded by `components.json`'s aliases still matching the old shape).\n * - Internal imports are rewritten by exact module specifier per file found\n * under `src/{components/ui,lib,hooks}`, so a component a user added by hand\n * after the original generation is covered too, and a specifier the\n * migration doesn't recognise is left alone and reported.\n * - Idempotent: every write is guarded by the old shape still being present.\n */\n\nconst libraryRoot = joinPathFragments(PACKAGES_DIR, SHARED_SHADCN_DIR);\nconst componentsJsonPath = joinPathFragments(libraryRoot, 'components.json');\nconst packageJsonPath = joinPathFragments(libraryRoot, 'package.json');\n\ninterface ComponentsJsonAliases {\n readonly components?: string;\n readonly utils?: string;\n readonly hooks?: string;\n readonly lib?: string;\n readonly ui?: string;\n}\n\nconst oldAliases = (fqn: string): ComponentsJsonAliases => ({\n components: `${fqn}/components`,\n utils: `${fqn}/lib/utils`,\n hooks: `${fqn}/hooks`,\n lib: `${fqn}/lib`,\n ui: `${fqn}/components/ui`,\n});\n\nconst newAliases: Required<ComponentsJsonAliases> = {\n components: '#components',\n utils: '#lib/utils',\n hooks: '#hooks',\n lib: '#lib',\n ui: '#components/ui',\n};\n\nconst newPackageManifestFields = {\n imports: {\n '#components/*': './src/components/*.tsx',\n '#lib/*': './src/lib/*.ts',\n '#hooks/*': './src/hooks/*.ts',\n },\n exports: {\n '.': './src/index.ts',\n './styles/*': './src/styles/*',\n './components/*': './src/components/*.tsx',\n './lib/*': './src/lib/*.ts',\n './hooks/*': './src/hooks/*.ts',\n },\n};\n\n/**\n * Rewrite an import's module specifier, keeping its bindings - `$bindings`\n * holds whatever the file imports, so a binding a user added survives.\n */\nconst importPattern = (from: string, to: string): string =>\n `\\`import { $bindings } from '${from}'\\` => \\`import { $bindings } from '${to}'\\``;\n\n/** Whether the file still imports the old specifier under any other form. */\nconst hasRemainingImport = (from: string): string =>\n `\\`import $_ from '${from}'\\``;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n if (!tree.exists(componentsJsonPath) || !tree.exists(packageJsonPath)) {\n return { nextSteps };\n }\n\n const fullyQualifiedName = getSharedShadcnFullyQualifiedName(tree);\n const currentAliases =\n readJson<{ aliases?: ComponentsJsonAliases }>(tree, componentsJsonPath)\n .aliases ?? {};\n const expectedOldAliases = oldAliases(fullyQualifiedName);\n const onOldShape = (\n Object.keys(newAliases) as (keyof ComponentsJsonAliases)[]\n ).every((key) => currentAliases[key] === expectedOldAliases[key]);\n\n if (!onOldShape) {\n if (\n (Object.keys(newAliases) as (keyof ComponentsJsonAliases)[]).some(\n (key) => currentAliases[key] !== newAliases[key],\n )\n ) {\n nextSteps.push(\n `${componentsJsonPath}: aliases have diverged from both the old and current generated shape - left untouched. Migrate them to the shadcn CLI's imports/exports monorepo pattern by hand: https://ui.shadcn.com/docs/monorepo`,\n );\n }\n await formatFilesInSubtree(tree);\n return { nextSteps };\n }\n\n // Rewrite every source file's internal references to this package's own\n // components/lib/hooks, keyed off the files actually present so a\n // hand-added component is covered too.\n const internalDirs: Array<{\n dir: string;\n extension: string;\n oldSubpath: string;\n newPrefix: string;\n }> = [\n {\n dir: joinPathFragments(libraryRoot, 'src', 'components', 'ui'),\n extension: '.tsx',\n oldSubpath: 'components/ui',\n newPrefix: '#components/ui',\n },\n {\n dir: joinPathFragments(libraryRoot, 'src', 'lib'),\n extension: '.ts',\n oldSubpath: 'lib',\n newPrefix: '#lib',\n },\n {\n dir: joinPathFragments(libraryRoot, 'src', 'hooks'),\n extension: '.ts',\n oldSubpath: 'hooks',\n newPrefix: '#hooks',\n },\n ];\n\n const renames: Array<{ old: string; renamed: string }> = [];\n const sourceFiles: string[] = [];\n for (const { dir, extension, oldSubpath, newPrefix } of internalDirs) {\n if (!tree.exists(dir)) {\n continue;\n }\n for (const entry of tree.children(dir)) {\n if (!entry.endsWith(extension)) {\n continue;\n }\n const baseName = entry.slice(0, -extension.length);\n renames.push({\n old: `${fullyQualifiedName}/${oldSubpath}/${baseName}`,\n renamed: `${newPrefix}/${baseName}`,\n });\n sourceFiles.push(joinPathFragments(dir, entry));\n }\n }\n\n for (const sourceFile of sourceFiles) {\n for (const { old, renamed } of renames) {\n await applyGritQL(tree, sourceFile, importPattern(old, renamed));\n // A namespace or default import of the same specifier is left as it\n // is - reported rather than rewritten, so a diverged file is never\n // clobbered.\n if (await matchGritQL(tree, sourceFile, hasRemainingImport(old))) {\n nextSteps.push(\n `${sourceFile}: still imports '${old}' in a form this migration does not rewrite - update it to '${renamed}' by hand.`,\n );\n }\n }\n }\n\n updateJson(tree, componentsJsonPath, (json) => ({\n ...json,\n aliases: newAliases,\n }));\n\n updateJson(tree, packageJsonPath, (json) => ({\n ...json,\n ...newPackageManifestFields,\n }));\n\n updateJson(tree, 'tsconfig.base.json', (json) => {\n const paths = { ...(json.compilerOptions?.paths ?? {}) };\n delete paths[`${fullyQualifiedName}/*`];\n return {\n ...json,\n compilerOptions: {\n ...json.compilerOptions,\n paths,\n },\n };\n });\n\n // Every website generated with ux=shadcn needs a real dependency on the\n // shared package now that it resolves through `exports`, not `paths`.\n for (const project of getProjects(tree).values()) {\n const metadata = project.metadata as\n | { generator?: string; ux?: string }\n | undefined;\n if (\n metadata?.generator !== REACT_WEBSITE_APP_GENERATOR_INFO.id ||\n metadata.ux !== 'shadcn'\n ) {\n continue;\n }\n addDependenciesToPackageJson(\n tree,\n { [fullyQualifiedName]: getLocalDependencySpecifier(tree) },\n {},\n joinPathFragments(project.root, 'package.json'),\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","readJson","updateJson","REACT_WEBSITE_APP_GENERATOR_INFO","applyGritQL","matchGritQL","addDependenciesToPackageJson","getLocalDependencySpecifier","formatFilesInSubtree","PACKAGES_DIR","SHARED_SHADCN_DIR","getSharedShadcnFullyQualifiedName","libraryRoot","componentsJsonPath","packageJsonPath","oldAliases","fqn","components","utils","hooks","lib","ui","newAliases","newPackageManifestFields","imports","exports","importPattern","from","to","hasRemainingImport","migration","tree","nextSteps","exists","fullyQualifiedName","currentAliases","aliases","expectedOldAliases","onOldShape","Object","keys","every","key","some","push","internalDirs","dir","extension","oldSubpath","newPrefix","renames","sourceFiles","entry","children","endsWith","baseName","slice","length","old","renamed","sourceFile","json","paths","compilerOptions","project","values","metadata","generator","id","ux","root"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|