@aws/nx-plugin-mcp 1.0.0-rc.4 → 1.0.0-rc.6

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/bin/aws-nx-mcp.js CHANGED
@@ -19413,26 +19413,6 @@ const buildGeneratorInfoList = (baseDir) => Object.entries(generators$1).map(([i
19413
19413
  ..."guidePages" in info && info.guidePages ? { guidePages: info.guidePages } : {}
19414
19414
  }));
19415
19415
  //#endregion
19416
- //#region ../nx-plugin/src/mcp-server/schema.ts
19417
- /**
19418
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
19419
- * SPDX-License-Identifier: Apache-2.0
19420
- */
19421
- const PACKAGE_MANAGERS = [
19422
- "pnpm",
19423
- "yarn",
19424
- "npm",
19425
- "bun"
19426
- ];
19427
- const PackageManagerSchema = _enum(PACKAGE_MANAGERS);
19428
- //#endregion
19429
- //#region ../nx-plugin/src/utils/iac-providers.ts
19430
- /**
19431
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
19432
- * SPDX-License-Identifier: Apache-2.0
19433
- */
19434
- const IAC_PROVIDERS = ["cdk", "terraform"];
19435
- //#endregion
19436
19416
  //#region ../nx-plugin/src/utils/commands.ts
19437
19417
  const PACKAGE_MANAGER_COMMANDS = {
19438
19418
  npm: {
@@ -19502,6 +19482,26 @@ const buildCreateNxWorkspaceCommand = (pm, workspace, iac, tag) => {
19502
19482
  ].join(" ");
19503
19483
  };
19504
19484
  //#endregion
19485
+ //#region ../nx-plugin/src/utils/iac-providers.ts
19486
+ /**
19487
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
19488
+ * SPDX-License-Identifier: Apache-2.0
19489
+ */
19490
+ const IAC_PROVIDERS = ["cdk", "terraform"];
19491
+ //#endregion
19492
+ //#region ../nx-plugin/src/mcp-server/schema.ts
19493
+ /**
19494
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
19495
+ * SPDX-License-Identifier: Apache-2.0
19496
+ */
19497
+ const PACKAGE_MANAGERS = [
19498
+ "pnpm",
19499
+ "yarn",
19500
+ "npm",
19501
+ "bun"
19502
+ ];
19503
+ const PackageManagerSchema = _enum(PACKAGE_MANAGERS);
19504
+ //#endregion
19505
19505
  //#region ../nx-plugin/src/mcp-server/tools/create-workspace-command.ts
19506
19506
  /**
19507
19507
  * Add a tool which tells a model how to create an Nx workspace
@@ -20546,88 +20546,6 @@ const kebabCase = (str) => {
20546
20546
  return (0, import_lodash_deburr.default)(str).replace(/[^a-zA-Z0-9]+/g, "-").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().replace(/^-+|-+$/g, "");
20547
20547
  };
20548
20548
  //#endregion
20549
- //#region ../nx-plugin/src/mcp-server/option-filter.ts
20550
- /**
20551
- * Turn the `data.estree` of an `MdxJsxAttributeValueExpression` into a
20552
- * `Predicate`. The estree is a Program wrapping a single ObjectExpression.
20553
- */
20554
- const parseWhenExpression = (estree) => {
20555
- const expression = unwrapProgram(estree);
20556
- if (expression.type !== "ObjectExpression") throw new Error(`[option-filter] Expected object literal in 'when' prop, got ${expression.type}`);
20557
- const result = {};
20558
- for (const prop of expression.properties) {
20559
- if (prop.type !== "Property") throw new Error(`[option-filter] Unsupported entry type '${prop.type}' in 'when' prop`);
20560
- result[extractKey(prop)] = extractValues(prop.value);
20561
- }
20562
- return result;
20563
- };
20564
- /**
20565
- * AND across keys, OR within a key's values, `not` negates. A key not
20566
- * present in `options` is "no opinion". A predicate whose keys have no
20567
- * intersection with `options` short-circuits to true.
20568
- */
20569
- const evaluatePredicate = (predicate, not, options) => {
20570
- let matched = true;
20571
- let anyKeyTested = false;
20572
- for (const [key, values] of Object.entries(predicate)) {
20573
- const selected = options[key];
20574
- if (selected === void 0) continue;
20575
- anyKeyTested = true;
20576
- if (!values.includes(selected)) {
20577
- matched = false;
20578
- break;
20579
- }
20580
- }
20581
- if (!anyKeyTested) return true;
20582
- return not ? !matched : matched;
20583
- };
20584
- /** Short human label used on the docs pill and in the `> [!NOTE] Only when …` marker. */
20585
- const describePredicate = (predicate, not) => {
20586
- const parts = Object.entries(predicate).map(([k, vs]) => `${k} = ${vs.join(" | ")}`);
20587
- return `${not ? "Not when " : "Only when "}${parts.join(", ")}`;
20588
- };
20589
- const unwrapProgram = (estree) => {
20590
- if (estree.type !== "Program") return estree;
20591
- const program = estree;
20592
- if (program.body.length !== 1) return estree;
20593
- const stmt = program.body[0];
20594
- return stmt.type === "ExpressionStatement" ? stmt.expression : estree;
20595
- };
20596
- const extractKey = (prop) => {
20597
- const k = prop.key;
20598
- if (k.type === "Identifier") return k.name;
20599
- if (k.type === "Literal" && typeof k.value === "string") return k.value;
20600
- throw new Error(`[option-filter] Unsupported key type '${k.type}' in 'when' prop`);
20601
- };
20602
- const extractValues = (value) => {
20603
- if (value.type === "ArrayExpression") return value.elements.map((el) => {
20604
- if (el === null || el.type === "SpreadElement") throw new Error(`[option-filter] Unsupported array element in 'when' prop`);
20605
- return extractScalar(el);
20606
- });
20607
- return [extractScalar(value)];
20608
- };
20609
- /**
20610
- * Extract a `string[]` from the estree of an attribute-value expression
20611
- * like `{['a', 'b']}`. Used by JSX attribute readers (e.g. the
20612
- * `commands={[...]}` prop on <NxCommands>). Throws if anything other than
20613
- * string / number / boolean literal array elements are encountered.
20614
- */
20615
- const extractStringArrayExpression = (estree) => {
20616
- const expression = unwrapProgram(estree);
20617
- if (expression.type !== "ArrayExpression") throw new Error(`[option-filter] Expected array literal, got ${expression.type}`);
20618
- return expression.elements.map((el) => {
20619
- if (el === null || el.type === "SpreadElement") throw new Error(`[option-filter] Unsupported array element`);
20620
- return extractScalar(el);
20621
- });
20622
- };
20623
- const extractScalar = (node) => {
20624
- if (node.type === "Literal") {
20625
- const lit = node;
20626
- if (typeof lit.value === "string" || typeof lit.value === "number" || typeof lit.value === "boolean") return String(lit.value);
20627
- }
20628
- throw new Error(`[option-filter] Unsupported value type '${node.type}' in 'when' prop. Use string, number, boolean literals or arrays of them.`);
20629
- };
20630
- //#endregion
20631
20549
  //#region ../nx-plugin/src/mcp-server/guide-render.ts
20632
20550
  /**
20633
20551
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
@@ -22995,7 +22913,93 @@ var import_js_yaml = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((ex
22995
22913
  var { Type, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, DEFAULT_SCHEMA, load, loadAll, dump, YAMLException, types: types$2, safeLoad, safeLoadAll, safeDump } = import_js_yaml.default;
22996
22914
  var index_vite_proxy_tmp_default = import_js_yaml.default;
22997
22915
  //#endregion
22916
+ //#region ../nx-plugin/src/mcp-server/option-filter.ts
22917
+ /**
22918
+ * Turn the `data.estree` of an `MdxJsxAttributeValueExpression` into a
22919
+ * `Predicate`. The estree is a Program wrapping a single ObjectExpression.
22920
+ */
22921
+ const parseWhenExpression = (estree) => {
22922
+ const expression = unwrapProgram(estree);
22923
+ if (expression.type !== "ObjectExpression") throw new Error(`[option-filter] Expected object literal in 'when' prop, got ${expression.type}`);
22924
+ const result = {};
22925
+ for (const prop of expression.properties) {
22926
+ if (prop.type !== "Property") throw new Error(`[option-filter] Unsupported entry type '${prop.type}' in 'when' prop`);
22927
+ result[extractKey(prop)] = extractValues(prop.value);
22928
+ }
22929
+ return result;
22930
+ };
22931
+ /**
22932
+ * AND across keys, OR within a key's values, `not` negates. A key not
22933
+ * present in `options` is "no opinion". A predicate whose keys have no
22934
+ * intersection with `options` short-circuits to true.
22935
+ */
22936
+ const evaluatePredicate = (predicate, not, options) => {
22937
+ let matched = true;
22938
+ let anyKeyTested = false;
22939
+ for (const [key, values] of Object.entries(predicate)) {
22940
+ const selected = options[key];
22941
+ if (selected === void 0) continue;
22942
+ anyKeyTested = true;
22943
+ if (!values.includes(selected)) {
22944
+ matched = false;
22945
+ break;
22946
+ }
22947
+ }
22948
+ if (!anyKeyTested) return true;
22949
+ return not ? !matched : matched;
22950
+ };
22951
+ /** Short human label used on the docs pill and in the `> [!NOTE] Only when …` marker. */
22952
+ const describePredicate = (predicate, not) => {
22953
+ const parts = Object.entries(predicate).map(([k, vs]) => `${k} = ${vs.join(" | ")}`);
22954
+ return `${not ? "Not when " : "Only when "}${parts.join(", ")}`;
22955
+ };
22956
+ const unwrapProgram = (estree) => {
22957
+ if (estree.type !== "Program") return estree;
22958
+ const program = estree;
22959
+ if (program.body.length !== 1) return estree;
22960
+ const stmt = program.body[0];
22961
+ return stmt.type === "ExpressionStatement" ? stmt.expression : estree;
22962
+ };
22963
+ const extractKey = (prop) => {
22964
+ const k = prop.key;
22965
+ if (k.type === "Identifier") return k.name;
22966
+ if (k.type === "Literal" && typeof k.value === "string") return k.value;
22967
+ throw new Error(`[option-filter] Unsupported key type '${k.type}' in 'when' prop`);
22968
+ };
22969
+ const extractValues = (value) => {
22970
+ if (value.type === "ArrayExpression") return value.elements.map((el) => {
22971
+ if (el === null || el.type === "SpreadElement") throw new Error(`[option-filter] Unsupported array element in 'when' prop`);
22972
+ return extractScalar(el);
22973
+ });
22974
+ return [extractScalar(value)];
22975
+ };
22976
+ /**
22977
+ * Extract a `string[]` from the estree of an attribute-value expression
22978
+ * like `{['a', 'b']}`. Used by JSX attribute readers (e.g. the
22979
+ * `commands={[...]}` prop on <NxCommands>). Throws if anything other than
22980
+ * string / number / boolean literal array elements are encountered.
22981
+ */
22982
+ const extractStringArrayExpression = (estree) => {
22983
+ const expression = unwrapProgram(estree);
22984
+ if (expression.type !== "ArrayExpression") throw new Error(`[option-filter] Expected array literal, got ${expression.type}`);
22985
+ return expression.elements.map((el) => {
22986
+ if (el === null || el.type === "SpreadElement") throw new Error(`[option-filter] Unsupported array element`);
22987
+ return extractScalar(el);
22988
+ });
22989
+ };
22990
+ const extractScalar = (node) => {
22991
+ if (node.type === "Literal") {
22992
+ const lit = node;
22993
+ if (typeof lit.value === "string" || typeof lit.value === "number" || typeof lit.value === "boolean") return String(lit.value);
22994
+ }
22995
+ throw new Error(`[option-filter] Unsupported value type '${node.type}' in 'when' prop. Use string, number, boolean literals or arrays of them.`);
22996
+ };
22997
+ //#endregion
22998
22998
  //#region ../nx-plugin/src/mcp-server/mdx-ast.ts
22999
+ /**
23000
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
23001
+ * SPDX-License-Identifier: Apache-2.0
23002
+ */
22999
23003
  const isJsxElement = (node) => node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement";
23000
23004
  const findAttr = (node, name) => node.attributes.find((a) => a.type === "mdxJsxAttribute" && a.name === name);
23001
23005
  const readStringAttr = (node, name) => {
@@ -52525,6 +52529,10 @@ var init_remark_frontmatter = __esmMin((() => {
52525
52529
  }));
52526
52530
  //#endregion
52527
52531
  //#region ../nx-plugin/src/mcp-server/guide-pipeline.ts
52532
+ /**
52533
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
52534
+ * SPDX-License-Identifier: Apache-2.0
52535
+ */
52528
52536
  let depsPromise;
52529
52537
  const loadRemarkDeps = () => {
52530
52538
  if (!depsPromise) depsPromise = (async () => ({
@@ -6,10 +6,12 @@ generator: license
6
6
  import { FileTree } from '@astrojs/starlight/components';
7
7
  import RunGenerator from '@components/run-generator.astro';
8
8
  import GeneratorParameters from '@components/generator-parameters.astro';
9
+ import Drawer from '@components/drawer.astro';
10
+ import LicenseAllowlist from '@components/license-allowlist.astro';
11
+ import NxCommands from '@components/nx-commands.astro';
12
+ import PackageManagerShortCommand from '@components/package-manager-short-command.astro';
9
13
 
10
- Automatically manage `LICENSE` files and source code headers in your workspace.
11
-
12
- This generator registers a [sync generator](https://nx.dev/concepts/sync-generators) to execute as part of your `lint` targets which will ensure that your source files conform to the desired license content and format, as well as ensuring that your project's `LICENSE` files are correct, and licensing information is included in relevant project files (`package.json`, `pyproject.toml`).
14
+ Manage licensing across your workspace: synchronise `LICENSE` files and source code headers for your own code (`license.source`), and check that every dependency conforms to a license allowlist (`license.dependencies`).
13
15
 
14
16
  ## Usage
15
17
 
@@ -26,15 +28,17 @@ This generator registers a [sync generator](https://nx.dev/concepts/sync-generat
26
28
  The generator will create or update the following files:
27
29
 
28
30
  <FileTree>
29
- - nx.json The lint target is configured to run the license sync generator
30
- - aws-nx-plugin.config.mts Configuration for the license sync generator
31
+ - nx.json The lint target is configured to run the license sync generator and depends on the license-check target
32
+ - aws-nx-plugin.config.mts Configuration for license source sync (`license.source`) and dependency checking (`license.dependencies`)
31
33
  </FileTree>
32
34
 
33
- Some default configuration for license header content and format is added to `aws-nx-plugin.config.mts` to write appropriate headers for a handful of file types. You may wish to customise this further; please see the [configuration section](#configuration) below.
35
+ ## License Headers & Files
36
+
37
+ The generator registers a [sync generator](https://nx.dev/concepts/sync-generators) to execute as part of your `lint` targets which ensures that your source files contain the correct license headers, your projects contain `LICENSE` files, and licensing metadata is set in `package.json` and `pyproject.toml`.
34
38
 
35
- ## Workflow
39
+ ### Workflow
36
40
 
37
- Whenever you build your projects (and a `lint` target runs), the license sync generator will make sure that the licensing in your project matches your configuration (see [license sync behaviour below](#license-sync-behaviour)). If it detects that anything is out of sync, you will receive a message such as:
41
+ Whenever you build your projects (and a `lint` target runs), the license sync generator will make sure that the licensing in your project matches your configuration. If it detects that anything is out of sync, you will receive a message such as:
38
42
 
39
43
  ```bash
40
44
  NX The workspace is out of sync
@@ -67,40 +71,36 @@ Select `Yes` to sync the changes.
67
71
  Make sure you check the changes the license sync generator makes in to version control to ensure that any continuous integration build tasks don't fail due to licenses being out of sync.
68
72
  :::
69
73
 
70
- ## License Sync Behaviour
74
+ ### Sync Behaviour
71
75
 
72
76
  The license sync generator performs three main tasks:
73
77
 
74
- ### 1. Synchronise Source File License Headers
78
+ #### 1. Synchronise Source File License Headers
75
79
 
76
80
  When the sync generator is run, it will ensure that all source code files in your workspace (based on your configuration) contain the appropriate license header. The header is written as the first block comment or consecutive series of line comments in the file (besides the shebang/hashbang if present in a file).
77
81
 
78
- You can update the configuration at any time to change which files should be included or excluded, as well as the content or format of license headers for different file types. For more details, please see the [configuration section](#configuration) below.
79
-
80
- ### 2. Synchronise LICENSE Files
82
+ #### 2. Synchronise LICENSE Files
81
83
 
82
84
  When the sync generator is run, it will ensure that the root `LICENSE` file corresponds to your configured license, as well as ensuring that all subprojects in your workspace also contain the correct `LICENSE` file.
83
85
 
84
- You can exclude projects in the configuration if required. For more details, please see the [configuration section](#configuration) below.
85
-
86
- ### 3. Synchronise licensing information in project files
86
+ #### 3. Synchronise licensing information in project files
87
87
 
88
88
  When the sync generator is run, it will ensure the `license` fields in `package.json` and `pyproject.toml` files are set to your configured license.
89
89
 
90
- You can exclude projects in the configuration if required. For more details, please see the [configuration section](#configuration) below.
91
-
92
- ## Configuration
90
+ ### Header & File Configuration
93
91
 
94
92
  Configuration is defined in the `aws-nx-plugin.config.mts` file in the root of your workspace.
95
93
 
96
- ### SPDX and Copyright Holder
94
+ #### SPDX and Copyright Holder
97
95
 
98
96
  Your chosen license can be updated at any time via the `spdx` configuration property:
99
97
 
100
- ```typescript title="aws-nx-plugin.config.mts" {3}
98
+ ```typescript title="aws-nx-plugin.config.mts" {4}
101
99
  export default {
102
100
  license: {
103
- spdx: 'MIT',
101
+ source: {
102
+ spdx: 'MIT',
103
+ },
104
104
  },
105
105
  } satisfies AwsNxPluginConfig;
106
106
  ```
@@ -109,36 +109,38 @@ When the sync generator runs, all `LICENSE` files, `package.json` and `pyproject
109
109
 
110
110
  You can additionally configure the copyright holder and copyright year, which are included in some `LICENSE` files:
111
111
 
112
- ```typescript title="aws-nx-plugin.config.mts" {4,5}
112
+ ```typescript title="aws-nx-plugin.config.mts" {5,6}
113
113
  export default {
114
114
  license: {
115
- spdx: 'MIT',
116
- copyrightHolder: 'Amazon.com, Inc. or its affiliates',
117
- copyrightYear: 2025,
115
+ source: {
116
+ spdx: 'MIT',
117
+ copyrightHolder: 'Amazon.com, Inc. or its affiliates',
118
+ copyrightYear: 2025,
119
+ },
118
120
  },
119
121
  } satisfies AwsNxPluginConfig;
120
122
  ```
121
123
 
122
- ### License Headers
123
-
124
- #### Content
124
+ #### License Header Content
125
125
 
126
126
  The license header content can be configured in two ways:
127
127
 
128
128
  1. Using inline content:
129
129
 
130
- ```typescript title="aws-nx-plugin.config.mts" {5-9}
130
+ ```typescript title="aws-nx-plugin.config.mts" {6-10}
131
131
  export default {
132
132
  license: {
133
- header: {
134
- content: {
135
- lines: [
136
- 'Copyright: My Company, Incorporated.',
137
- 'Licensed under the MIT License',
138
- 'All rights reserved',
139
- ];
133
+ source: {
134
+ header: {
135
+ content: {
136
+ lines: [
137
+ 'Copyright: My Company, Incorporated.',
138
+ 'Licensed under the MIT License',
139
+ 'All rights reserved',
140
+ ];
141
+ }
142
+ // ... format configuration
140
143
  }
141
- // ... format configuration
142
144
  }
143
145
  }
144
146
  } satisfies AwsNxPluginConfig;
@@ -146,51 +148,55 @@ export default {
146
148
 
147
149
  2. Loading from a file:
148
150
 
149
- ```typescript title="aws-nx-plugin.config.mts" {5}
151
+ ```typescript title="aws-nx-plugin.config.mts" {6}
150
152
  export default {
151
153
  license: {
152
- header: {
153
- content: {
154
- filePath: 'license-header.txt'; // relative to workspace root
154
+ source: {
155
+ header: {
156
+ content: {
157
+ filePath: 'license-header.txt'; // relative to workspace root
158
+ }
159
+ // ... format configuration
155
160
  }
156
- // ... format configuration
157
161
  }
158
162
  }
159
163
  } satisfies AwsNxPluginConfig;
160
164
  ```
161
165
 
162
- #### Format
166
+ #### Header Format
163
167
 
164
168
  You can specify how license headers should be formatted for different file types using glob patterns. The format configuration supports line comments, block comments, or a combination of both:
165
169
 
166
- ```typescript title="aws-nx-plugin.config.mts" {7-29}
170
+ ```typescript title="aws-nx-plugin.config.mts" {8-30}
167
171
  export default {
168
172
  license: {
169
- header: {
170
- content: {
171
- lines: ['Copyright notice here'],
172
- },
173
- format: {
174
- // Line comments
175
- '**/*.ts': {
176
- lineStart: '// ',
177
- },
178
- // Block comments
179
- '**/*.css': {
180
- blockStart: '/*',
181
- blockEnd: '*/',
173
+ source: {
174
+ header: {
175
+ content: {
176
+ lines: ['Copyright notice here'],
182
177
  },
183
- // Block comments with line prefixes
184
- '**/*.java': {
185
- blockStart: '/*',
186
- lineStart: ' * ',
187
- blockEnd: ' */',
188
- },
189
- // Line comments with header/footer
190
- '**/*.py': {
191
- blockStart: '# ------------',
192
- lineStart: '# ',
193
- blockEnd: '# ------------',
178
+ format: {
179
+ // Line comments
180
+ '**/*.ts': {
181
+ lineStart: '// ',
182
+ },
183
+ // Block comments
184
+ '**/*.css': {
185
+ blockStart: '/*',
186
+ blockEnd: '*/',
187
+ },
188
+ // Block comments with line prefixes
189
+ '**/*.java': {
190
+ blockStart: '/*',
191
+ lineStart: ' * ',
192
+ blockEnd: ' */',
193
+ },
194
+ // Line comments with header/footer
195
+ '**/*.py': {
196
+ blockStart: '# ------------',
197
+ lineStart: '# ',
198
+ blockEnd: '# ------------',
199
+ },
194
200
  },
195
201
  },
196
202
  },
@@ -209,27 +215,29 @@ The format configuration supports:
209
215
 
210
216
  For file types that aren't natively supported, you can specify custom comment syntax to tell the sync generator how to identify existing license headers in these file types.
211
217
 
212
- ```typescript title="aws-nx-plugin.config.mts" {12-22}
218
+ ```typescript title="aws-nx-plugin.config.mts" {13-23}
213
219
  export default {
214
220
  license: {
215
- header: {
216
- content: {
217
- lines: ['My license header'],
218
- },
219
- format: {
220
- '**/*.xyz': {
221
- lineStart: '## ',
221
+ source: {
222
+ header: {
223
+ content: {
224
+ lines: ['My license header'],
222
225
  },
223
- },
224
- commentSyntax: {
225
- xyz: {
226
- line: '##', // Define line comment syntax
226
+ format: {
227
+ '**/*.xyz': {
228
+ lineStart: '## ',
229
+ },
227
230
  },
228
- abc: {
229
- block: {
230
- // Define block comment syntax
231
- start: '<!--',
232
- end: '-->',
231
+ commentSyntax: {
232
+ xyz: {
233
+ line: '##', // Define line comment syntax
234
+ },
235
+ abc: {
236
+ block: {
237
+ // Define block comment syntax
238
+ start: '<!--',
239
+ end: '-->',
240
+ },
233
241
  },
234
242
  },
235
243
  },
@@ -238,56 +246,203 @@ export default {
238
246
  } satisfies AwsNxPluginConfig;
239
247
  ```
240
248
 
241
- #### Excluding files
249
+ #### Excluding Files from Header Sync
242
250
 
243
251
  By default, in a git repository, all `.gitignore` files are honored to ensure that only files managed by version control are synchronized. In non-git repositories, all files are considered unless explicitly excluded in configuration.
244
252
 
245
253
  You can exclude additional files from license header synchronization using glob patterns:
246
254
 
247
- ```typescript title="aws-nx-plugin.config.mts" {12-16}
255
+ ```typescript title="aws-nx-plugin.config.mts" {13}
248
256
  export default {
249
257
  license: {
250
- header: {
251
- content: {
252
- lines: ['My license header'],
253
- },
254
- format: {
255
- '**/*.ts': {
256
- lineStart: '// ',
258
+ source: {
259
+ header: {
260
+ content: {
261
+ lines: ['My license header'],
262
+ },
263
+ format: {
264
+ '**/*.ts': {
265
+ lineStart: '// ',
266
+ },
257
267
  },
268
+ exclude: ['**/generated/**', '**/dist/**', 'some-specific-file.ts'],
258
269
  },
259
- exclude: ['**/generated/**', '**/dist/**', 'some-specific-file.ts'],
260
270
  },
261
271
  },
262
272
  } satisfies AwsNxPluginConfig;
263
273
  ```
264
274
 
265
- ### Excluding project files from sync
275
+ #### Excluding Projects from File Sync
266
276
 
267
277
  All `LICENSE` files, `package.json` files and `pyproject.toml` files are synchronised with the configured license by default.
268
278
 
269
279
  You can exclude specific projects or files from synchronization using glob patterns:
270
280
 
271
- ```typescript title="aws-nx-plugin.config.mts" {3-10}
281
+ ```typescript title="aws-nx-plugin.config.mts" {4-11}
272
282
  export default {
273
283
  license: {
274
- files: {
275
- exclude: [
276
- // do not sync LICENSE file, package.json or pyproject.toml
277
- 'packages/excluded-project',
278
- // do not sync LICENSE file, but sync package.json and/or pyproject.toml
279
- 'apps/internal/LICENSE',
280
- ];
284
+ source: {
285
+ files: {
286
+ exclude: [
287
+ // do not sync LICENSE file, package.json or pyproject.toml
288
+ 'packages/excluded-project',
289
+ // do not sync LICENSE file, but sync package.json and/or pyproject.toml
290
+ 'apps/internal/LICENSE',
291
+ ];
292
+ }
281
293
  }
282
294
  }
283
295
  } satisfies AwsNxPluginConfig;
284
296
  ```
285
297
 
286
- ## Disabling license sync
298
+ ### Disabling License Sync
287
299
 
288
- To disable the license sync generator:
300
+ License source sync is enabled by the presence of the `license.source` key in your configuration. To disable it:
289
301
 
290
- 1. Remove the `license` section from your configuration in `aws-nx-plugin.config.mts` (or remove the `aws-nx-plugin.config.mts` file)
291
- 2. Remove the `@aws/nx-plugin:license#sync` generator from `targetDefaults.lint.syncGenerators`
302
+ 1. Remove the `license.source` section from your configuration in `aws-nx-plugin.config.mts` (you can keep `license.dependencies` if you still want dependency license checking)
303
+ 2. If you also want to fully remove the sync generator, remove the `@aws/nx-plugin:license#sync` generator from `targetDefaults.lint.syncGenerators`
292
304
 
293
305
  To re-enable license sync, simply run the `license` generator again.
306
+
307
+ ## Dependency License Checks
308
+
309
+ The `license` generator also configures a `license-check` target that fails when one of your project's dependencies (or any transitive dependency) declares a license that is not in your allowlist.
310
+
311
+ ### How it runs
312
+
313
+ The generator writes a `license-check` target to your root `project.json`:
314
+
315
+ ```json title="project.json"
316
+ {
317
+ "targets": {
318
+ "license-check": {
319
+ "executor": "@aws/nx-plugin:license-check",
320
+ "cache": true,
321
+ "inputs": [
322
+ "{workspaceRoot}/pnpm-lock.yaml",
323
+ "{workspaceRoot}/aws-nx-plugin.config.mts"
324
+ ],
325
+ "options": {}
326
+ }
327
+ }
328
+ }
329
+ ```
330
+
331
+ The `inputs` are computed for your workspace: only lockfiles that are actually present are included, along with `aws-nx-plugin.config.mts`, plus a `{workspaceRoot}/**/uv.lock` glob when Python dependency checking is enabled (i.e. a Python collector is configured).
332
+
333
+ You can run the check directly:
334
+
335
+ <NxCommands commands={['license-check']} />
336
+
337
+ Results are cached against your lockfiles and `aws-nx-plugin.config.mts` — re-runs are instant when nothing has changed.
338
+
339
+ Collectors determine what gets scanned. The `npmCollector` uses [license-checker-rseidelsohn](https://github.com/nicedoc/license-checker-rseidelsohn), and the `pythonCollector` uses [pip-licenses](https://github.com/raimon49/pip-licenses). If no installed dependencies are found, the check passes with nothing to inspect.
340
+
341
+ ### Running as part of lint/build
342
+
343
+ The dependency license check runs automatically whenever you `lint` or `build` any project in your workspace. The `license` generator wires each project's `lint` target to depend on the root `license-check` target, and the project generators (`ts#*` and `py#*`) do the same when they run — so the check is wired up regardless of the order generators are run in.
344
+
345
+ This means you don't need to run the check explicitly, though you can still do so with the `license-check` target:
346
+
347
+ <NxCommands commands={['license-check']} />
348
+
349
+ The wiring is a cross-project `dependsOn` on each project's `lint` target that points at the root `license-check` target. To skip the check during a lint or build, set the `LICENSE_DEPENDENCY_CHECK=skip` environment variable:
350
+
351
+ <PackageManagerShortCommand commands={["LICENSE_DEPENDENCY_CHECK=skip lint"]} />
352
+
353
+ ### Configuration
354
+
355
+ By default the check uses a built-in set of common permissive licenses (MIT, Apache-2.0, BSD, ISC, etc.) exported as `DEFAULT_LICENSE_ALLOWLIST`. You can extend or override this in your config:
356
+
357
+ ```typescript title="aws-nx-plugin.config.mts"
358
+ import { AwsNxPluginConfig } from '@aws/nx-plugin';
359
+ import { DEFAULT_LICENSE_ALLOWLIST } from '@aws/nx-plugin/sdk/license';
360
+
361
+ export default {
362
+ license: {
363
+ // ...
364
+ dependencies: {
365
+ allow: [...DEFAULT_LICENSE_ALLOWLIST, { spdxId: 'LGPL-2.1-or-later', fullName: 'GNU Lesser General Public License v2.1 or later', aliases: [] }],
366
+ exceptions: [
367
+ { package: 'some-package', reason: 'Audited manually — ships MIT text without SPDX field' },
368
+ ],
369
+ },
370
+ },
371
+ } satisfies AwsNxPluginConfig;
372
+ ```
373
+
374
+ <Drawer title="Default License Allowlist" trigger="View the full list of licenses in DEFAULT_LICENSE_ALLOWLIST">
375
+ <LicenseAllowlist />
376
+ </Drawer>
377
+
378
+ #### Customizing the allowlist
379
+
380
+ To restrict the allowlist, replace `DEFAULT_LICENSE_ALLOWLIST` with your own array. To extend it, spread the default and add entries. Entries are matched by SPDX id, full license name, or any of the listed aliases (case-insensitive).
381
+
382
+ #### Per-package exceptions
383
+
384
+ Use `exceptions` for packages that fail the check — either because their license is not in the allowlist, or because they ship without detectable license metadata. The `reason` field is required so reviewers can see why the exception was granted.
385
+
386
+ ```typescript
387
+ exceptions: [
388
+ {
389
+ package: 'union',
390
+ version: '0.5.0',
391
+ reason: 'Package ships verbatim MIT text without declaring license',
392
+ },
393
+ ];
394
+ ```
395
+
396
+ Generators that introduce dependencies with problematic metadata (e.g. the MCP server generator) automatically add the required exceptions to your config when they run.
397
+
398
+ #### Collectors
399
+
400
+ Collectors discover dependencies and extract license metadata. The built-in collectors are `npmCollector()` (scans `node_modules`) and `pythonCollector()` (scans Python virtual environments). The license generator configures `npmCollector()` by default and adds `pythonCollector()` when Python projects are present.
401
+
402
+ To implement a custom collector, conform to the `LicenseCollector` interface:
403
+
404
+ ```typescript
405
+ import type { LicenseCollector } from '@aws/nx-plugin/sdk/license';
406
+
407
+ const myCollector = (): LicenseCollector => ({
408
+ name: 'my-ecosystem',
409
+ traceCommand: 'my-tool why <package>',
410
+ async collect({ workspaceRoot }) {
411
+ return [
412
+ { name: 'some-dep', version: '1.0.0', rawLicense: 'MIT', ecosystem: 'my-ecosystem' },
413
+ ];
414
+ },
415
+ });
416
+ ```
417
+
418
+ #### The onDependency hook
419
+
420
+ `license.dependencies` accepts an optional `onDependency` callback that is invoked once for every discovered dependency, regardless of whether it passes or fails the check. It receives `{ package, spdx }`, where `package` is the package name and `spdx` is the resolved SPDX license expression. An exception's `spdx` takes precedence over the raw declared license, and `spdx` may be an empty string if no license was declared.
421
+
422
+ This is a handy way to print out all of the licenses across your project. Run the `license-check` target to see the output:
423
+
424
+ ```typescript title="aws-nx-plugin.config.mts"
425
+ import { AwsNxPluginConfig } from '@aws/nx-plugin';
426
+ import { DEFAULT_LICENSE_ALLOWLIST } from '@aws/nx-plugin/sdk/license';
427
+
428
+ export default {
429
+ license: {
430
+ dependencies: {
431
+ allow: DEFAULT_LICENSE_ALLOWLIST,
432
+ onDependency: ({ package: pkg, spdx }) => {
433
+ console.log(`${pkg} - ${spdx}`);
434
+ },
435
+ },
436
+ },
437
+ } satisfies AwsNxPluginConfig;
438
+ ```
439
+
440
+ ### Disabling Dependency Checks
441
+
442
+ Dependency license checking is enabled by the presence of the `license.dependencies` key in your configuration.
443
+
444
+ To disable the checks for a single run, set the `LICENSE_DEPENDENCY_CHECK=skip` environment variable:
445
+
446
+ <PackageManagerShortCommand commands={["LICENSE_DEPENDENCY_CHECK=skip lint"]} />
447
+
448
+ To disable permanently, remove the `license.dependencies` key from your configuration in `aws-nx-plugin.config.mts`. You can also re-run the `license` generator with `--dependencyCheck=false` to scaffold without it.
@@ -38,8 +38,8 @@ The generator will create the following project structure in the `<directory>/<n
38
38
  - example.prisma Example model definition
39
39
  - schema.prisma Main Prisma schema (references models)
40
40
  - scripts
41
- - docker-pull.ts Pulls the database Docker image for local development
42
- - docker-start.ts Starts a local database container
41
+ - pull-image.ts Pulls the database container image for local development
42
+ - start-container.ts Starts a local database container
43
43
  - wait-for-db.ts Waits for the local database to be ready
44
44
  - src
45
45
  - index.ts Project entry point
@@ -169,7 +169,7 @@ The client automatically:
169
169
 
170
170
  After adding or updating models under `prisma/models/`, use `migrate dev` to generate migration files and apply them to your local database at the same time.
171
171
 
172
- The generated `prisma` target automatically starts a local database via Docker before running:
172
+ The generated `prisma` target automatically starts a local database container before running:
173
173
 
174
174
  <NxCommands commands={['run <project>:prisma migrate dev']} />
175
175
 
@@ -204,12 +204,26 @@ The generated `prisma` target exposes the Prisma CLI, so you can use it to run a
204
204
 
205
205
  <NxCommands commands={['run <project>:prisma <prisma-command>']} />
206
206
 
207
- ### Prisma Studio
207
+ ### Using Prisma Studio
208
208
 
209
209
  [Prisma Studio](https://www.prisma.io/studio) is a visual editor for your local database. Use it to browse tables, inspect and edit records, filter data, follow relations, and run raw SQL via the built-in SQL console. It is useful for verifying migrations and seeding test data during development. Launch it with:
210
210
 
211
211
  <NxCommands commands={['run <project>:prisma studio']} />
212
212
 
213
+ ### Stopping the Local Database
214
+
215
+ Stopping `serve-local` (e.g. with `Ctrl+C`) automatically removes the local database container, but preserves the named volume so your data persists across restarts.
216
+
217
+ :::caution[Windows]
218
+ Due to limitations with signal handling on Windows, the container is not automatically removed when `serve-local` is stopped. You will need to remove it manually:
219
+
220
+ ```bash
221
+ <engine> rm -f <scope>-<db-name>
222
+ ```
223
+
224
+ Replace `<engine>` with your container engine (`docker` or `finch`), `<scope>` with your Nx workspace scope (e.g. `proj`), and `<db-name>` with your database project name (e.g. `my-db`).
225
+ :::
226
+
213
227
  ## Connecting to the Database
214
228
 
215
229
  In any TypeScript project, import `getPrisma` from your database package and call it to get a type-safe Prisma client:
@@ -524,9 +538,9 @@ module "my_database" {
524
538
 
525
539
  Pin a specific Aurora engine version.
526
540
 
527
- By default, the generated local Docker database image matches the default Aurora engine version. If you change the Aurora engine version, it's recommended to also use a matching local Docker database version for maximum compatibility. See the AWS release notes for [Aurora PostgreSQL versions](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/aurorapostgresql-release-calendar.html) and [Aurora MySQL versions](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.30Updates.html) to identify the corresponding community database version.
541
+ By default, the generated local database container image matches the default Aurora engine version. If you change the Aurora engine version, it's recommended to also use a matching local container image version for maximum compatibility. See the AWS release notes for [Aurora PostgreSQL versions](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraPostgreSQLReleaseNotes/aurorapostgresql-release-calendar.html) and [Aurora MySQL versions](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.Updates.30Updates.html) to identify the corresponding community database version.
528
542
 
529
- The local database image is configured in the generated database project's `serve-local` target in `project.json`. Update the image argument passed to `scripts/docker-start.ts` when you change engine versions.
543
+ The local database image is configured in the generated database project's `serve-local` target in `project.json`. Update the image argument passed to `scripts/start-container.ts` when you change engine versions.
530
544
 
531
545
  <OptionFilter when={{ engine: 'postgres' }}>
532
546
  <Infrastructure>
@@ -11,7 +11,7 @@ import NxCommands from '@components/nx-commands.astro';
11
11
  import PackageManagerShortCommand from '@components/package-manager-short-command.astro';
12
12
  import Link from '@components/link.astro';
13
13
 
14
- The TypeScript project generator can be used to create a modern [TypeScript](https://www.typescriptlang.org/) library or application configured with best practices such as [ECMAScript Modules (ESM)](https://www.typescriptlang.org/docs/handbook/modules/reference.html), TypeScript [project references](https://www.typescriptlang.org/docs/handbook/project-references.html), [Vitest](https://vitest.dev/) for running tests and [ESLint](https://eslint.org/) for static analysis.
14
+ The TypeScript project generator can be used to create a modern [TypeScript](https://www.typescriptlang.org/) library or application configured with best practices such as [ECMAScript Modules (ESM)](https://www.typescriptlang.org/docs/handbook/modules/reference.html), TypeScript [project references](https://www.typescriptlang.org/docs/handbook/project-references.html), [Vitest](https://vitest.dev/) for running tests and [Biome](https://biomejs.dev/) for linting and formatting.
15
15
 
16
16
  ## Usage
17
17
 
@@ -38,7 +38,6 @@ The generator will create the following project structure in the `<directory>/<n
38
38
  - tsconfig.lib.json TypeScript configuration for your library (your runtime or packaged source)
39
39
  - tsconfig.spec.json TypeScript configuration for your tests
40
40
  - vitest.config.mts Configuration for Vitest
41
- - eslint.config.mjs Configuration for ESLint
42
41
 
43
42
  </FileTree>
44
43
 
@@ -198,7 +197,7 @@ If you're building an AWS Lambda function, check out the <Link path="/guides/ts-
198
197
 
199
198
  If you are publishing your TypeScript project to NPM, you must create a `package.json` file for it.
200
199
 
201
- This must declare the dependencies that your project references. Since at build time your project will resolve dependencies installed via the workspace root `package.json`, it's recommended to configure the [Nx Dependency Checks ESLint Plugin](https://nx.dev/nx-api/eslint-plugin/documents/dependency-checks) to ensure that your published project's `package.json` includes all dependencies you use in your project.
200
+ This must declare the dependencies that your project references. Since at build time your project will resolve dependencies installed via the workspace root `package.json`, Biome's `noUndeclaredDependencies` rule will warn you if your project imports a package that isn't listed in its `package.json`.
202
201
 
203
202
  ### Building
204
203
 
@@ -269,11 +268,7 @@ If you are a VSCode user, we recommend installing the [Vitest Runner for VSCode
269
268
 
270
269
  ## Linting
271
270
 
272
- TypeScript projects use [ESLint](https://eslint.org/) for linting, along with [Prettier](https://prettier.io/) for formatting.
273
-
274
- We recommend configuring ESLint in the workspace root `eslint.config.mjs` file, as changes to this will apply to all TypeScript projects in your workspace and ensure consistency.
275
-
276
- Likewise, you can configure Prettier in the root `.prettierrc` file.
271
+ TypeScript projects use [Biome](https://biomejs.dev/) for linting and formatting. Biome is configured in the workspace root `biome.json` file — changes to this apply to all TypeScript projects in your workspace and ensure consistency.
277
272
 
278
273
  ### Running the Linter
279
274
 
@@ -283,7 +278,7 @@ To invoke the linter to check your project, you can run the `lint` target.
283
278
 
284
279
  ### Fixing Lint Issues
285
280
 
286
- The majority of linting or formatting issues can be fixed automatically. You can tell ESLint to fix lint issues by running with the `--configuration=fix` argument.
281
+ The majority of linting or formatting issues can be fixed automatically by running with the `--configuration=fix` argument.
287
282
 
288
283
  <NxCommands commands={["lint <project-name> --configuration=fix"]} />
289
284
 
@@ -303,7 +298,7 @@ To avoid linting issues slowing you down during development (particularly if you
303
298
 
304
299
  <NxCommands commands={["run-many --target build --configuration=skip-lint"]} />
305
300
 
306
- This will still run ESLint as part of the build, but the lint target will always be considered successful.
301
+ This skips the lint target entirely during build.
307
302
 
308
303
  :::tip[Shorthand Command]
309
304
  This has a shorthand command from the root of your workspace:
@@ -134,7 +134,7 @@ This will run the chosen target as well as the targets it depends on.
134
134
 
135
135
  ### Linting
136
136
 
137
- New workspaces are configured with [ESLint](https://eslint.org/) for static analysis and [Prettier](https://prettier.io/) for code formatting. Running `lint` applies both to all projects.
137
+ New workspaces are configured with [Biome](https://biomejs.dev/) for static analysis and code formatting. Running `lint` checks all projects for issues, and `lint --configuration=fix` auto-fixes them.
138
138
 
139
139
  ### Git Secrets
140
140
 
@@ -4,7 +4,7 @@ title: Required Prerequisites
4
4
  - [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
5
5
  - [Node >= 22](https://nodejs.org/en/download) (We recommend using something like [NVM](https://github.com/nvm-sh/nvm) to manage your node versions)
6
6
  - verify by running `node --version`
7
- - [PNPM >= 10](https://pnpm.io/installation#using-npm) (you can also use [Yarn >= 4](https://yarnpkg.com/getting-started/install), [Bun >= 1](https://bun.sh/docs/installation), or [NPM >= 10](https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager) if you prefer)
7
+ - [PNPM >= 11](https://pnpm.io/installation#using-npm) (you can also use [Yarn >= 4](https://yarnpkg.com/getting-started/install), [Bun >= 1](https://bun.sh/docs/installation), or [NPM >= 10](https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager) if you prefer)
8
8
  - verify by running `pnpm --version`, `yarn --version`, `bun --version` or `npm --version`
9
9
  - [UV >= 0.5.29](https://docs.astral.sh/uv/getting-started/installation/)
10
10
  1. install Python 3.14 by running: `uv python install 3.14.0`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin-mcp",
3
- "version": "1.0.0-rc.4",
3
+ "version": "1.0.0-rc.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -17,6 +17,12 @@
17
17
  "description": "The copyright holder, included in the LICENSE file and source file headers by default.",
18
18
  "default": "Amazon.com, Inc. or its affiliates",
19
19
  "x-priority": "important"
20
+ },
21
+ "dependencyCheck": {
22
+ "type": "boolean",
23
+ "description": "Configure a license-check target that fails when dependencies declare licenses outside the configured allowlist.",
24
+ "default": true,
25
+ "x-priority": "important"
20
26
  }
21
27
  },
22
28
  "required": []