@webpieces/nx-webpieces-rules 0.4.930 → 0.4.932
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/package.json +7 -7
- package/src/configs/tag-truth-configs.d.ts +8 -2
- package/src/configs/tag-truth-configs.js +9 -2
- package/src/configs/tag-truth-configs.js.map +1 -1
- package/src/lib/tag-truth.d.ts +24 -6
- package/src/lib/tag-truth.js +40 -9
- package/src/lib/tag-truth.js.map +1 -1
- package/src/rule-settings.js +2 -1
- package/src/rule-settings.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/nx-webpieces-rules",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.932",
|
|
4
4
|
"description": "Nx-specific webpieces validation rules, graph tooling, executors, and inference plugin.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@webpieces/api-doc-model": "0.4.
|
|
24
|
-
"@webpieces/core-util": "0.4.
|
|
25
|
-
"@webpieces/eslint-rules": "0.4.
|
|
26
|
-
"@webpieces/rules-config": "0.4.
|
|
23
|
+
"@webpieces/api-doc-model": "0.4.932",
|
|
24
|
+
"@webpieces/core-util": "0.4.932",
|
|
25
|
+
"@webpieces/eslint-rules": "0.4.932",
|
|
26
|
+
"@webpieces/rules-config": "0.4.932",
|
|
27
27
|
"madge": "8.0.0",
|
|
28
|
-
"@webpieces/rules-sdk": "0.4.
|
|
28
|
+
"@webpieces/rules-sdk": "0.4.932"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@nx/devkit": ">=18.0.0"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@webpieces/tooling-testkit": "0.4.
|
|
44
|
+
"@webpieces/tooling-testkit": "0.4.932"
|
|
45
45
|
},
|
|
46
46
|
"types": "./src/index.d.ts",
|
|
47
47
|
"bin": {
|
|
@@ -15,15 +15,21 @@ export declare class ApiClientPackagesEntry {
|
|
|
15
15
|
*
|
|
16
16
|
* - `mode` — OFF | RUN_EVERY_TIME (a graph rule: it reads every project, every run).
|
|
17
17
|
* - `apiLibPackages` — required; may be empty (an api library then imports nothing from outside), e.g.
|
|
18
|
-
* `["@webpieces/core-util", "tslib"]`.
|
|
19
|
-
*
|
|
18
|
+
* `["@webpieces/core-util", "tslib"]`. OUTSIDE packages only: a package an api library's wire contract
|
|
19
|
+
* may pull into every consumer. A WORKSPACE project is never allowed through this list.
|
|
20
20
|
* - `apiClients` — required; one entry per `role:api-client` project. A `role:api-client` with no
|
|
21
21
|
* entry is itself a violation: what it may talk to is stated, never inferred.
|
|
22
|
+
* - `allowedWorkspaceProjects` — required; may be empty (#1287). The WORKSPACE projects (not role:api-lib)
|
|
23
|
+
* any api-lib / api-client may depend on: a generator that builds its OpenAPI documents, or a shared
|
|
24
|
+
* util library the repo deliberately lets every contract use. Matched by nx project name or
|
|
25
|
+
* package.json name, globs allowed, e.g. `["@my/openapi-docs-site", "core-util"]`. An entry that
|
|
26
|
+
* matches no workspace project is itself a violation, so the list cannot rot.
|
|
22
27
|
*/
|
|
23
28
|
export declare class ApiLibDependenciesConfig extends BaseRuleConfig {
|
|
24
29
|
mode?: StructuralMode;
|
|
25
30
|
apiLibPackages: string[];
|
|
26
31
|
apiClients: ApiClientPackagesEntry[];
|
|
32
|
+
allowedWorkspaceProjects: string[];
|
|
27
33
|
static readonly SCHEMA: SchemaShape<ApiLibDependenciesConfig>;
|
|
28
34
|
}
|
|
29
35
|
/**
|
|
@@ -22,18 +22,25 @@ exports.ApiClientPackagesEntry = ApiClientPackagesEntry;
|
|
|
22
22
|
*
|
|
23
23
|
* - `mode` — OFF | RUN_EVERY_TIME (a graph rule: it reads every project, every run).
|
|
24
24
|
* - `apiLibPackages` — required; may be empty (an api library then imports nothing from outside), e.g.
|
|
25
|
-
* `["@webpieces/core-util", "tslib"]`.
|
|
26
|
-
*
|
|
25
|
+
* `["@webpieces/core-util", "tslib"]`. OUTSIDE packages only: a package an api library's wire contract
|
|
26
|
+
* may pull into every consumer. A WORKSPACE project is never allowed through this list.
|
|
27
27
|
* - `apiClients` — required; one entry per `role:api-client` project. A `role:api-client` with no
|
|
28
28
|
* entry is itself a violation: what it may talk to is stated, never inferred.
|
|
29
|
+
* - `allowedWorkspaceProjects` — required; may be empty (#1287). The WORKSPACE projects (not role:api-lib)
|
|
30
|
+
* any api-lib / api-client may depend on: a generator that builds its OpenAPI documents, or a shared
|
|
31
|
+
* util library the repo deliberately lets every contract use. Matched by nx project name or
|
|
32
|
+
* package.json name, globs allowed, e.g. `["@my/openapi-docs-site", "core-util"]`. An entry that
|
|
33
|
+
* matches no workspace project is itself a violation, so the list cannot rot.
|
|
29
34
|
*/
|
|
30
35
|
class ApiLibDependenciesConfig extends rules_sdk_1.BaseRuleConfig {
|
|
31
36
|
apiLibPackages;
|
|
32
37
|
apiClients;
|
|
38
|
+
allowedWorkspaceProjects;
|
|
33
39
|
static SCHEMA = {
|
|
34
40
|
mode: new rules_sdk_1.FieldDef('string', rule_configs_1.STRUCTURAL_MODES),
|
|
35
41
|
apiLibPackages: new rules_sdk_1.FieldDef('string[]'),
|
|
36
42
|
apiClients: rules_sdk_1.FieldDef.objects(ApiClientPackagesEntry.SCHEMA),
|
|
43
|
+
allowedWorkspaceProjects: new rules_sdk_1.FieldDef('string[]'),
|
|
37
44
|
};
|
|
38
45
|
}
|
|
39
46
|
exports.ApiLibDependenciesConfig = ApiLibDependenciesConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-truth-configs.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/configs/tag-truth-configs.ts"],"names":[],"mappings":";;;AAAA,oDAA6E;AAC7E,iDAAkE;AAClE,+GAA+G;AAC/G,MAAa,sBAAsB;IAC/B,iFAAiF;IACjF,OAAO,CAAU;IACjB,mGAAmG;IACnG,QAAQ,CAAY;IAEpB,MAAM,CAAU,MAAM,GAAwC;QAC1D,OAAO,EAAE,IAAI,oBAAQ,CAAC,QAAQ,CAAC;QAC/B,QAAQ,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;KACrC,CAAC;;AATN,wDAUC;AAED;;;;;;;;;;;GAWG;AACH,MAAa,wBAAyB,SAAQ,0BAAc;IAExD,cAAc,CAAY;IAC1B,UAAU,CAA4B;IAEtC,MAAM,CAAU,MAAM,GAA0C;QAC5D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,cAAc,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;QACxC,UAAU,EAAE,oBAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC;KAC9D,CAAC;;AATN,4DAUC;AAED;;;;;;GAMG;AACH,MAAa,gBAAiB,SAAQ,0BAAc;IAEhD,KAAK,CAAY;IAEjB,MAAM,CAAU,MAAM,GAAkC;QACpD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;KACpC,CAAC;;AAPN,4CAQC;AAED;;;;;;GAMG;AACH,MAAa,oBAAoB;IAC7B,8EAA8E;IAC9E,KAAK,CAAY;IACjB,qGAAqG;IACrG,aAAa,CAAY;IACzB,qEAAqE;IACrE,KAAK,CAAY;IAEjB,MAAM,CAAU,MAAM,GAAsC;QACxD,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;QACjC,aAAa,EAAE,oBAAQ,CAAC,eAAe,EAAE;QACzC,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;KACpC,CAAC;;AAZN,oDAaC;AAED;;;;;;;;;;GAUG;AACH,MAAa,qBAAsB,SAAQ,0BAAc;IAErD,OAAO,CAA0B;IAEjC,MAAM,CAAU,MAAM,GAAuC;QACzD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,OAAO,EAAE,oBAAQ,CAAC,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC;KACjE,CAAC;;AAPN,sDAQC;AAED;;;GAGG;AACH,MAAa,sBAAsB;IAC/B,wGAAwG;IACxG,IAAI,CAAU;IACd;;;OAGG;IACH,iBAAiB,CAAY;IAE7B,MAAM,CAAU,MAAM,GAAwC;QAC1D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,CAAC;QAC5B,iBAAiB,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;KAC9C,CAAC;;AAZN,wDAaC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,iBAAkB,SAAQ,0BAAc;IAEjD,KAAK,CAAY;IACjB,mBAAmB,CAA4B;IAE/C,MAAM,CAAU,MAAM,GAAmC;QACrD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;QACjC,mBAAmB,EAAE,oBAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC;KACvE,CAAC;;AATN,8CAUC","sourcesContent":["import { FieldDef, SchemaShape, BaseRuleConfig } from \"@webpieces/rules-sdk\";\nimport { StructuralMode, STRUCTURAL_MODES } from \"./rule-configs\";\n/** One `role:api-client` project and the outside packages it may import (its SDK, inversify, …). Data-only. */\nexport class ApiClientPackagesEntry {\n /** The nx project name of the `role:api-client` library, e.g. `gmail-client`. */\n project!: string;\n /** Package names (globs allowed, e.g. `@google-cloud/*`) it may import beyond `apiLibPackages`. */\n packages!: string[];\n\n static readonly SCHEMA: SchemaShape<ApiClientPackagesEntry> = {\n project: new FieldDef('string'),\n packages: new FieldDef('string[]'),\n };\n}\n\n/**\n * `api-lib-dependencies` (D2) — a `role:api-lib` may depend only on other `role:api-lib` projects plus\n * the outside packages in `apiLibPackages`; a `role:api-client` may ALSO import the packages its own\n * `apiClients` entry names (its SDK, `inversify`, `@webpieces/core-context`, …).\n *\n * - `mode` — OFF | RUN_EVERY_TIME (a graph rule: it reads every project, every run).\n * - `apiLibPackages` — required; may be empty (an api library then imports nothing from outside), e.g.\n * `[\"@webpieces/core-util\", \"tslib\"]`. A workspace project whose name or package name is listed here\n * is allowed too, so a repo whose `core-util` is a workspace project states it the same way.\n * - `apiClients` — required; one entry per `role:api-client` project. A `role:api-client` with no\n * entry is itself a violation: what it may talk to is stated, never inferred.\n */\nexport class ApiLibDependenciesConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n apiLibPackages!: string[];\n apiClients!: ApiClientPackagesEntry[];\n\n static readonly SCHEMA: SchemaShape<ApiLibDependenciesConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n apiLibPackages: new FieldDef('string[]'),\n apiClients: FieldDef.objects(ApiClientPackagesEntry.SCHEMA),\n };\n}\n\n/**\n * `api-lib-path` (D10) — both directions: every `role:api-lib` / `role:api-client` project lives under\n * one of `paths`, and every project under `paths` carries one of those two roles.\n *\n * - `mode` — OFF | RUN_EVERY_TIME.\n * - `paths` — required, non-empty globs over project ROOTS, e.g. `[\"libraries/apis/**\"]`.\n */\nexport class ApiLibPathConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n paths!: string[];\n\n static readonly SCHEMA: SchemaShape<ApiLibPathConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n paths: FieldDef.nonEmptyStrings(),\n };\n}\n\n/**\n * One folder of the runtime layout: the project roots it covers, the framework SETS a project there may\n * carry, and the roles it may have. Data-only.\n *\n * A framework set is written as its tags joined by `+`, in any order: `\"browser+node+react-native\"`.\n * Listing two sets means EITHER — `[\"node\", \"express\"]` is a node library or an express one.\n */\nexport class FrameworkFolderEntry {\n /** Globs over project ROOTS, e.g. `[\"libraries/universal/**\"]`. Non-empty. */\n paths!: string[];\n /** The accepted framework sets, each `+`-joined, e.g. `[\"browser+node+react-native\"]`. Non-empty. */\n frameworkSets!: string[];\n /** The accepted roles, e.g. `[\"lib\", \"designed-lib\"]`. Non-empty. */\n roles!: string[];\n\n static readonly SCHEMA: SchemaShape<FrameworkFolderEntry> = {\n paths: FieldDef.nonEmptyStrings(),\n frameworkSets: FieldDef.nonEmptyStrings(),\n roles: FieldDef.nonEmptyStrings(),\n };\n}\n\n/**\n * `framework-folder` (D9) — the folder a library lives in and the tags it carries say the same thing,\n * both directions:\n * - a project under an entry's `paths` (the FIRST entry whose glob matches, in `entries` order) must\n * carry one of that entry's `frameworkSets`, exactly, and one of its `roles`;\n * - a LIBRARY (any role but server/app/client/bundle) carrying a framework set and role that some entry\n * lists must live under one of the entries that list them.\n *\n * - `mode` — OFF | RUN_EVERY_TIME.\n * - `entries` — required, non-empty. The recommended layout is in `.claude/rules/framework-tags.md`.\n */\nexport class FrameworkFolderConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n entries!: FrameworkFolderEntry[];\n\n static readonly SCHEMA: SchemaShape<FrameworkFolderConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n entries: FieldDef.nonEmptyObjects(FrameworkFolderEntry.SCHEMA),\n };\n}\n\n/**\n * One row of the product dependency matrix (#1204): the OTHER products a product may depend on.\n * Data-only.\n */\nexport class ProductDependencyEntry {\n /** The product this row is about — the name after `product:` in some project's tags, e.g. `example`. */\n name!: string;\n /**\n * The other products a project of `name` may depend on, e.g. `[\"platform\", \"openapi\"]`. A product\n * may always depend on itself, so it is never listed; `[]` states that it depends on no other.\n */\n allowedToDependOn!: string[];\n\n static readonly SCHEMA: SchemaShape<ProductDependencyEntry> = {\n name: new FieldDef('string'),\n allowedToDependOn: new FieldDef('string[]'),\n };\n}\n\n/**\n * `product-tags` (#1179, #1204) — two halves behind ONE switch:\n * - every project whose role is in `roles` carries at least one well-formed `product:<name>` nx tag\n * (lowercase kebab, several allowed). The product filter and the Product color mode of\n * `arch:visualize` / `arch:visualize-runtime` seed a product's membership from exactly those tags,\n * so an untagged server, client or app silently drops out of every product view;\n * - every edge of the DEPENDENCY graph respects `productDependencies`: an edge A -> B is legal when,\n * for EVERY product p of A, B carries p or a product p's entry allows. Membership is the resolved\n * one (a project's own tags are final; an untagged project inherits). The runtime graph is not\n * checked.\n *\n * - `mode` — OFF | RUN_EVERY_TIME (a graph rule: it reads every project, every run). OFF turns off\n * both halves.\n * - `roles` — required, non-empty: WHICH roles are refused without a tag, e.g.\n * `[\"server\", \"client\", \"app\"]`. It decides which projects fail, so it is behaviour, never a default.\n * - `productDependencies` — required; `[]` is valid and means no product may depend on another. One\n * entry per product that DOES depend on others, e.g.\n * `[{ \"name\": \"example\", \"allowedToDependOn\": [\"platform\", \"openapi\"] }]`. A product with no entry\n * may depend only on itself. A `name` or `allowedToDependOn` value that no `product:` tag uses, and a\n * duplicate `name`, fail generation naming it — a typo can never silently allow or forbid nothing.\n */\nexport class ProductTagsConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n roles!: string[];\n productDependencies!: ProductDependencyEntry[];\n\n static readonly SCHEMA: SchemaShape<ProductTagsConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n roles: FieldDef.nonEmptyStrings(),\n productDependencies: FieldDef.objects(ProductDependencyEntry.SCHEMA),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tag-truth-configs.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/configs/tag-truth-configs.ts"],"names":[],"mappings":";;;AAAA,oDAA6E;AAC7E,iDAAkE;AAClE,+GAA+G;AAC/G,MAAa,sBAAsB;IAC/B,iFAAiF;IACjF,OAAO,CAAU;IACjB,mGAAmG;IACnG,QAAQ,CAAY;IAEpB,MAAM,CAAU,MAAM,GAAwC;QAC1D,OAAO,EAAE,IAAI,oBAAQ,CAAC,QAAQ,CAAC;QAC/B,QAAQ,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;KACrC,CAAC;;AATN,wDAUC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAa,wBAAyB,SAAQ,0BAAc;IAExD,cAAc,CAAY;IAC1B,UAAU,CAA4B;IACtC,wBAAwB,CAAY;IAEpC,MAAM,CAAU,MAAM,GAA0C;QAC5D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,cAAc,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;QACxC,UAAU,EAAE,oBAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC;QAC3D,wBAAwB,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;KACrD,CAAC;;AAXN,4DAYC;AAED;;;;;;GAMG;AACH,MAAa,gBAAiB,SAAQ,0BAAc;IAEhD,KAAK,CAAY;IAEjB,MAAM,CAAU,MAAM,GAAkC;QACpD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;KACpC,CAAC;;AAPN,4CAQC;AAED;;;;;;GAMG;AACH,MAAa,oBAAoB;IAC7B,8EAA8E;IAC9E,KAAK,CAAY;IACjB,qGAAqG;IACrG,aAAa,CAAY;IACzB,qEAAqE;IACrE,KAAK,CAAY;IAEjB,MAAM,CAAU,MAAM,GAAsC;QACxD,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;QACjC,aAAa,EAAE,oBAAQ,CAAC,eAAe,EAAE;QACzC,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;KACpC,CAAC;;AAZN,oDAaC;AAED;;;;;;;;;;GAUG;AACH,MAAa,qBAAsB,SAAQ,0BAAc;IAErD,OAAO,CAA0B;IAEjC,MAAM,CAAU,MAAM,GAAuC;QACzD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,OAAO,EAAE,oBAAQ,CAAC,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC;KACjE,CAAC;;AAPN,sDAQC;AAED;;;GAGG;AACH,MAAa,sBAAsB;IAC/B,wGAAwG;IACxG,IAAI,CAAU;IACd;;;OAGG;IACH,iBAAiB,CAAY;IAE7B,MAAM,CAAU,MAAM,GAAwC;QAC1D,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,CAAC;QAC5B,iBAAiB,EAAE,IAAI,oBAAQ,CAAC,UAAU,CAAC;KAC9C,CAAC;;AAZN,wDAaC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,iBAAkB,SAAQ,0BAAc;IAEjD,KAAK,CAAY;IACjB,mBAAmB,CAA4B;IAE/C,MAAM,CAAU,MAAM,GAAmC;QACrD,IAAI,EAAE,IAAI,oBAAQ,CAAC,QAAQ,EAAE,+BAAgB,CAAC;QAC9C,KAAK,EAAE,oBAAQ,CAAC,eAAe,EAAE;QACjC,mBAAmB,EAAE,oBAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC;KACvE,CAAC;;AATN,8CAUC","sourcesContent":["import { FieldDef, SchemaShape, BaseRuleConfig } from \"@webpieces/rules-sdk\";\nimport { StructuralMode, STRUCTURAL_MODES } from \"./rule-configs\";\n/** One `role:api-client` project and the outside packages it may import (its SDK, inversify, …). Data-only. */\nexport class ApiClientPackagesEntry {\n /** The nx project name of the `role:api-client` library, e.g. `gmail-client`. */\n project!: string;\n /** Package names (globs allowed, e.g. `@google-cloud/*`) it may import beyond `apiLibPackages`. */\n packages!: string[];\n\n static readonly SCHEMA: SchemaShape<ApiClientPackagesEntry> = {\n project: new FieldDef('string'),\n packages: new FieldDef('string[]'),\n };\n}\n\n/**\n * `api-lib-dependencies` (D2) — a `role:api-lib` may depend only on other `role:api-lib` projects plus\n * the outside packages in `apiLibPackages`; a `role:api-client` may ALSO import the packages its own\n * `apiClients` entry names (its SDK, `inversify`, `@webpieces/core-context`, …).\n *\n * - `mode` — OFF | RUN_EVERY_TIME (a graph rule: it reads every project, every run).\n * - `apiLibPackages` — required; may be empty (an api library then imports nothing from outside), e.g.\n * `[\"@webpieces/core-util\", \"tslib\"]`. OUTSIDE packages only: a package an api library's wire contract\n * may pull into every consumer. A WORKSPACE project is never allowed through this list.\n * - `apiClients` — required; one entry per `role:api-client` project. A `role:api-client` with no\n * entry is itself a violation: what it may talk to is stated, never inferred.\n * - `allowedWorkspaceProjects` — required; may be empty (#1287). The WORKSPACE projects (not role:api-lib)\n * any api-lib / api-client may depend on: a generator that builds its OpenAPI documents, or a shared\n * util library the repo deliberately lets every contract use. Matched by nx project name or\n * package.json name, globs allowed, e.g. `[\"@my/openapi-docs-site\", \"core-util\"]`. An entry that\n * matches no workspace project is itself a violation, so the list cannot rot.\n */\nexport class ApiLibDependenciesConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n apiLibPackages!: string[];\n apiClients!: ApiClientPackagesEntry[];\n allowedWorkspaceProjects!: string[];\n\n static readonly SCHEMA: SchemaShape<ApiLibDependenciesConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n apiLibPackages: new FieldDef('string[]'),\n apiClients: FieldDef.objects(ApiClientPackagesEntry.SCHEMA),\n allowedWorkspaceProjects: new FieldDef('string[]'),\n };\n}\n\n/**\n * `api-lib-path` (D10) — both directions: every `role:api-lib` / `role:api-client` project lives under\n * one of `paths`, and every project under `paths` carries one of those two roles.\n *\n * - `mode` — OFF | RUN_EVERY_TIME.\n * - `paths` — required, non-empty globs over project ROOTS, e.g. `[\"libraries/apis/**\"]`.\n */\nexport class ApiLibPathConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n paths!: string[];\n\n static readonly SCHEMA: SchemaShape<ApiLibPathConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n paths: FieldDef.nonEmptyStrings(),\n };\n}\n\n/**\n * One folder of the runtime layout: the project roots it covers, the framework SETS a project there may\n * carry, and the roles it may have. Data-only.\n *\n * A framework set is written as its tags joined by `+`, in any order: `\"browser+node+react-native\"`.\n * Listing two sets means EITHER — `[\"node\", \"express\"]` is a node library or an express one.\n */\nexport class FrameworkFolderEntry {\n /** Globs over project ROOTS, e.g. `[\"libraries/universal/**\"]`. Non-empty. */\n paths!: string[];\n /** The accepted framework sets, each `+`-joined, e.g. `[\"browser+node+react-native\"]`. Non-empty. */\n frameworkSets!: string[];\n /** The accepted roles, e.g. `[\"lib\", \"designed-lib\"]`. Non-empty. */\n roles!: string[];\n\n static readonly SCHEMA: SchemaShape<FrameworkFolderEntry> = {\n paths: FieldDef.nonEmptyStrings(),\n frameworkSets: FieldDef.nonEmptyStrings(),\n roles: FieldDef.nonEmptyStrings(),\n };\n}\n\n/**\n * `framework-folder` (D9) — the folder a library lives in and the tags it carries say the same thing,\n * both directions:\n * - a project under an entry's `paths` (the FIRST entry whose glob matches, in `entries` order) must\n * carry one of that entry's `frameworkSets`, exactly, and one of its `roles`;\n * - a LIBRARY (any role but server/app/client/bundle) carrying a framework set and role that some entry\n * lists must live under one of the entries that list them.\n *\n * - `mode` — OFF | RUN_EVERY_TIME.\n * - `entries` — required, non-empty. The recommended layout is in `.claude/rules/framework-tags.md`.\n */\nexport class FrameworkFolderConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n entries!: FrameworkFolderEntry[];\n\n static readonly SCHEMA: SchemaShape<FrameworkFolderConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n entries: FieldDef.nonEmptyObjects(FrameworkFolderEntry.SCHEMA),\n };\n}\n\n/**\n * One row of the product dependency matrix (#1204): the OTHER products a product may depend on.\n * Data-only.\n */\nexport class ProductDependencyEntry {\n /** The product this row is about — the name after `product:` in some project's tags, e.g. `example`. */\n name!: string;\n /**\n * The other products a project of `name` may depend on, e.g. `[\"platform\", \"openapi\"]`. A product\n * may always depend on itself, so it is never listed; `[]` states that it depends on no other.\n */\n allowedToDependOn!: string[];\n\n static readonly SCHEMA: SchemaShape<ProductDependencyEntry> = {\n name: new FieldDef('string'),\n allowedToDependOn: new FieldDef('string[]'),\n };\n}\n\n/**\n * `product-tags` (#1179, #1204) — two halves behind ONE switch:\n * - every project whose role is in `roles` carries at least one well-formed `product:<name>` nx tag\n * (lowercase kebab, several allowed). The product filter and the Product color mode of\n * `arch:visualize` / `arch:visualize-runtime` seed a product's membership from exactly those tags,\n * so an untagged server, client or app silently drops out of every product view;\n * - every edge of the DEPENDENCY graph respects `productDependencies`: an edge A -> B is legal when,\n * for EVERY product p of A, B carries p or a product p's entry allows. Membership is the resolved\n * one (a project's own tags are final; an untagged project inherits). The runtime graph is not\n * checked.\n *\n * - `mode` — OFF | RUN_EVERY_TIME (a graph rule: it reads every project, every run). OFF turns off\n * both halves.\n * - `roles` — required, non-empty: WHICH roles are refused without a tag, e.g.\n * `[\"server\", \"client\", \"app\"]`. It decides which projects fail, so it is behaviour, never a default.\n * - `productDependencies` — required; `[]` is valid and means no product may depend on another. One\n * entry per product that DOES depend on others, e.g.\n * `[{ \"name\": \"example\", \"allowedToDependOn\": [\"platform\", \"openapi\"] }]`. A product with no entry\n * may depend only on itself. A `name` or `allowedToDependOn` value that no `product:` tag uses, and a\n * duplicate `name`, fail generation naming it — a typo can never silently allow or forbid nothing.\n */\nexport class ProductTagsConfig extends BaseRuleConfig {\n declare mode?: StructuralMode;\n roles!: string[];\n productDependencies!: ProductDependencyEntry[];\n\n static readonly SCHEMA: SchemaShape<ProductTagsConfig> = {\n mode: new FieldDef('string', STRUCTURAL_MODES),\n roles: FieldDef.nonEmptyStrings(),\n productDependencies: FieldDef.objects(ProductDependencyEntry.SCHEMA),\n };\n}\n"]}
|
package/src/lib/tag-truth.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Tag truth — the four GRAPH rules that make an nx `role:*` / `framework:*` / `product:*` tag true
|
|
3
3
|
* (#1064, #1179):
|
|
4
4
|
*
|
|
5
|
-
* api-lib-dependencies (D2) — a `role:api-lib` depends only on other `role:api-lib` projects
|
|
5
|
+
* api-lib-dependencies (D2) — a `role:api-lib` depends only on other `role:api-lib` projects, the
|
|
6
|
+
* stated workspace projects (`allowedWorkspaceProjects`, #1287) and a
|
|
6
7
|
* stated list of outside packages; a `role:api-client` may also import
|
|
7
8
|
* the packages its own config entry names (its SDK, inversify, …).
|
|
8
9
|
* api-lib-path (D10) — every api-lib / api-client lives under the configured api globs, and
|
|
@@ -32,15 +33,27 @@ export declare const API_LIB_ROLE = "api-lib";
|
|
|
32
33
|
export declare const API_CLIENT_ROLE = "api-client";
|
|
33
34
|
/** `api-lib-dependencies`, resolved: what an api library may import from outside the api-lib set. */
|
|
34
35
|
export declare class ApiLibDependenciesRule {
|
|
35
|
-
/**
|
|
36
|
+
/** OUTSIDE package names (globs allowed) every api-lib and api-client may import. */
|
|
36
37
|
readonly apiLibPackages: readonly string[];
|
|
37
|
-
/** `role:api-client` project → the extra packages it may
|
|
38
|
+
/** `role:api-client` project → the extra outside packages it may import. */
|
|
38
39
|
readonly apiClientPackages: ReadonlyMap<string, readonly string[]>;
|
|
40
|
+
/**
|
|
41
|
+
* WORKSPACE projects (nx name or package.json name, globs allowed) every api-lib and api-client may
|
|
42
|
+
* depend on — a generator, or a deliberately shared util library (#1287). Each entry must match
|
|
43
|
+
* some workspace project.
|
|
44
|
+
*/
|
|
45
|
+
readonly allowedWorkspaceProjects: readonly string[];
|
|
39
46
|
constructor(
|
|
40
|
-
/**
|
|
47
|
+
/** OUTSIDE package names (globs allowed) every api-lib and api-client may import. */
|
|
41
48
|
apiLibPackages: readonly string[],
|
|
42
|
-
/** `role:api-client` project → the extra packages it may
|
|
43
|
-
apiClientPackages: ReadonlyMap<string, readonly string[]
|
|
49
|
+
/** `role:api-client` project → the extra outside packages it may import. */
|
|
50
|
+
apiClientPackages: ReadonlyMap<string, readonly string[]>,
|
|
51
|
+
/**
|
|
52
|
+
* WORKSPACE projects (nx name or package.json name, globs allowed) every api-lib and api-client may
|
|
53
|
+
* depend on — a generator, or a deliberately shared util library (#1287). Each entry must match
|
|
54
|
+
* some workspace project.
|
|
55
|
+
*/
|
|
56
|
+
allowedWorkspaceProjects: readonly string[]);
|
|
44
57
|
}
|
|
45
58
|
/** `api-lib-path`, resolved: the globs every api project — and only api projects — lives under. */
|
|
46
59
|
export declare class ApiLibPathRule {
|
|
@@ -105,6 +118,11 @@ export declare class TagTruthValidator {
|
|
|
105
118
|
private readonly rules;
|
|
106
119
|
constructor(rules: TagTruthRules);
|
|
107
120
|
problems(graph: EnhancedGraph, infos: Map<string, ProjectInfo>, imports: ReadonlyMap<string, ProjectImports>): string[];
|
|
121
|
+
/**
|
|
122
|
+
* #1287 — an `allowedWorkspaceProjects` entry that matches no workspace project (by nx name or
|
|
123
|
+
* package.json name) is refused, so the list cannot rot into allowances for projects long gone.
|
|
124
|
+
*/
|
|
125
|
+
private deadWorkspaceEntries;
|
|
108
126
|
/** Every product some project's `product:` tag names — what a matrix entry may refer to. */
|
|
109
127
|
private declaredProducts;
|
|
110
128
|
/**
|
package/src/lib/tag-truth.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Tag truth — the four GRAPH rules that make an nx `role:*` / `framework:*` / `product:*` tag true
|
|
4
4
|
* (#1064, #1179):
|
|
5
5
|
*
|
|
6
|
-
* api-lib-dependencies (D2) — a `role:api-lib` depends only on other `role:api-lib` projects
|
|
6
|
+
* api-lib-dependencies (D2) — a `role:api-lib` depends only on other `role:api-lib` projects, the
|
|
7
|
+
* stated workspace projects (`allowedWorkspaceProjects`, #1287) and a
|
|
7
8
|
* stated list of outside packages; a `role:api-client` may also import
|
|
8
9
|
* the packages its own config entry names (its SDK, inversify, …).
|
|
9
10
|
* api-lib-path (D10) — every api-lib / api-client lives under the configured api globs, and
|
|
@@ -44,13 +45,21 @@ const API_ROLES = [exports.API_LIB_ROLE, exports.API_CLIENT_ROLE];
|
|
|
44
45
|
class ApiLibDependenciesRule {
|
|
45
46
|
apiLibPackages;
|
|
46
47
|
apiClientPackages;
|
|
48
|
+
allowedWorkspaceProjects;
|
|
47
49
|
constructor(
|
|
48
|
-
/**
|
|
50
|
+
/** OUTSIDE package names (globs allowed) every api-lib and api-client may import. */
|
|
49
51
|
apiLibPackages,
|
|
50
|
-
/** `role:api-client` project → the extra packages it may
|
|
51
|
-
apiClientPackages
|
|
52
|
+
/** `role:api-client` project → the extra outside packages it may import. */
|
|
53
|
+
apiClientPackages,
|
|
54
|
+
/**
|
|
55
|
+
* WORKSPACE projects (nx name or package.json name, globs allowed) every api-lib and api-client may
|
|
56
|
+
* depend on — a generator, or a deliberately shared util library (#1287). Each entry must match
|
|
57
|
+
* some workspace project.
|
|
58
|
+
*/
|
|
59
|
+
allowedWorkspaceProjects) {
|
|
52
60
|
this.apiLibPackages = apiLibPackages;
|
|
53
61
|
this.apiClientPackages = apiClientPackages;
|
|
62
|
+
this.allowedWorkspaceProjects = allowedWorkspaceProjects;
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
exports.ApiLibDependenciesRule = ApiLibDependenciesRule;
|
|
@@ -154,7 +163,7 @@ class TagTruthRules {
|
|
|
154
163
|
const clients = new Map();
|
|
155
164
|
for (const entry of options['apiClients'])
|
|
156
165
|
clients.set(entry.project, entry.packages);
|
|
157
|
-
return new ApiLibDependenciesRule(options['apiLibPackages'], clients);
|
|
166
|
+
return new ApiLibDependenciesRule(options['apiLibPackages'], clients, options['allowedWorkspaceProjects']);
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
169
|
exports.TagTruthRules = TagTruthRules;
|
|
@@ -199,11 +208,30 @@ class TagTruthValidator {
|
|
|
199
208
|
problems.push(...this.productTagProblems(info, root, entry, this.rules.productTags));
|
|
200
209
|
}
|
|
201
210
|
}
|
|
211
|
+
if (this.rules.apiLibDependencies !== null) {
|
|
212
|
+
problems.push(...this.deadWorkspaceEntries(graph, imports, this.rules.apiLibDependencies));
|
|
213
|
+
}
|
|
202
214
|
if (this.rules.productTags !== null) {
|
|
203
215
|
problems.push(...this.rules.productTags.dependencies.problems(graph, this.declaredProducts(infos)));
|
|
204
216
|
}
|
|
205
217
|
return problems;
|
|
206
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* #1287 — an `allowedWorkspaceProjects` entry that matches no workspace project (by nx name or
|
|
221
|
+
* package.json name) is refused, so the list cannot rot into allowances for projects long gone.
|
|
222
|
+
*/
|
|
223
|
+
deadWorkspaceEntries(graph, imports, rule) {
|
|
224
|
+
const names = [...Object.keys(graph), ...imports.keys()];
|
|
225
|
+
for (const each of imports.values())
|
|
226
|
+
if (each.packageName)
|
|
227
|
+
names.push(each.packageName);
|
|
228
|
+
return rule.allowedWorkspaceProjects
|
|
229
|
+
.filter((entry) => !names.some((name) => (0, rules_config_1.matchesAnyGlob)(name, [entry])))
|
|
230
|
+
.map((entry) => `${"api-lib-dependencies"}: allowedWorkspaceProjects entry '${entry}' matches no workspace ` +
|
|
231
|
+
`project (by nx project name or package.json name) — an allowance for a project that is not ` +
|
|
232
|
+
`there controls nothing. Delete '${entry}' from ${"api-lib-dependencies"}.allowedWorkspaceProjects ` +
|
|
233
|
+
`in webpieces.config.json.`);
|
|
234
|
+
}
|
|
207
235
|
/** Every product some project's `product:` tag names — what a matrix entry may refer to. */
|
|
208
236
|
declaredProducts(infos) {
|
|
209
237
|
const resolver = new product_resolver_1.ProductResolver();
|
|
@@ -250,6 +278,7 @@ class TagTruthValidator {
|
|
|
250
278
|
}
|
|
251
279
|
const allowed = [...rule.apiLibPackages, ...(clientPackages ?? [])];
|
|
252
280
|
const listName = role === exports.API_CLIENT_ROLE ? `apiLibPackages or its apiClients entry` : 'apiLibPackages';
|
|
281
|
+
const workspaceList = `${"api-lib-dependencies"}.allowedWorkspaceProjects`;
|
|
253
282
|
const problems = [];
|
|
254
283
|
const workspaceNames = new Set();
|
|
255
284
|
for (const dep of entry.dependsOn) {
|
|
@@ -259,13 +288,15 @@ class TagTruthValidator {
|
|
|
259
288
|
const depRole = graph[dep]?.role;
|
|
260
289
|
if (depRole === exports.API_LIB_ROLE)
|
|
261
290
|
continue;
|
|
262
|
-
if ((0, rules_config_1.matchesAnyGlob)(dep,
|
|
291
|
+
if ((0, rules_config_1.matchesAnyGlob)(dep, rule.allowedWorkspaceProjects))
|
|
263
292
|
continue;
|
|
264
|
-
if (depImports?.packageName && (0, rules_config_1.matchesAnyGlob)(depImports.packageName,
|
|
293
|
+
if (depImports?.packageName && (0, rules_config_1.matchesAnyGlob)(depImports.packageName, rule.allowedWorkspaceProjects))
|
|
265
294
|
continue;
|
|
266
295
|
problems.push(`${rulePrefix} must not depend on '${dep}' (role:${depRole ?? 'none'}) — an api library depends ` +
|
|
267
|
-
`only on role:api-lib projects and the
|
|
268
|
-
`role:api-lib project, or
|
|
296
|
+
`only on role:api-lib projects and the workspace projects ${workspaceList} lists. Move what ` +
|
|
297
|
+
`it needs into a role:api-lib project, or — when '${dep}' is a generator or a workspace ` +
|
|
298
|
+
`library every api library may deliberately share — add '${depImports?.packageName ?? dep}' ` +
|
|
299
|
+
`to ${workspaceList} in webpieces.config.json.`);
|
|
269
300
|
}
|
|
270
301
|
const own = imports.get(name);
|
|
271
302
|
for (const pkg of [...(own?.prodPackages ?? [])].sort()) {
|
package/src/lib/tag-truth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tag-truth.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/tag-truth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tag truth — the four GRAPH rules that make an nx `role:*` / `framework:*` / `product:*` tag true\n * (#1064, #1179):\n *\n * api-lib-dependencies (D2) — a `role:api-lib` depends only on other `role:api-lib` projects plus a\n * stated list of outside packages; a `role:api-client` may also import\n * the packages its own config entry names (its SDK, inversify, …).\n * api-lib-path (D10) — every api-lib / api-client lives under the configured api globs, and\n * everything under them carries one of those two roles.\n * framework-folder (D9) — the folder a library lives in and its framework set + role agree,\n * both directions.\n * product-tags (#1179) — every project whose role is listed (seed: server, client, app)\n * carries a well-formed `product:<name>` tag, the seed the product\n * filter and Product color mode derive membership from; and (#1204)\n * every dependency edge respects the product dependency matrix\n * (product-dependencies.ts), read on the RESOLVED membership.\n *\n * They run beside `library-types-match-client` and `role-dependency` (graph-metadata.ts), in\n * `architecture:generate` and `validate-architecture-unchanged`, AFTER enrichGraph has resolved every\n * project's framework set and role — so a tag is read exactly one way. Every problem across every\n * project is collected and thrown as one MetadataValidationError, before anything is written.\n *\n * There is NO default (`.claude/rules/no-rule-defaults.md`): each rule's fields come from\n * webpieces.config.json, which must state them or fail to load. `TagTruthRules.none()` is what a unit\n * test or a caller that configured nothing asked for — not a default.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { loadAndValidate, matchesAnyGlob, RuleOptions } from \"@webpieces/rules-config\";\nimport { ApiClientPackagesEntry, FrameworkFolderEntry, ProductDependencyEntry } from \"../configs/tag-truth-configs\";\nimport type { EnhancedGraph, GraphEntry } from './graph-sorter';\nimport { APP_ROLES, MetadataValidationError } from './graph-metadata';\nimport { ProjectInfo } from './project-info';\nimport { ProductResolver } from './product-resolver';\nimport { ProductDependencyMatrix } from './product-dependencies';\nimport { RuleGate } from './rule-gate';\nimport { DepUsageScanner } from './dep-usage-scanner';\nimport { toError } from '../toError';\n\n/** The only field of a package.json this check reads. */\ntype RawPackageJson = { name?: string };\n\nexport const API_LIB_ROLE = 'api-lib';\nexport const API_CLIENT_ROLE = 'api-client';\nconst API_ROLES: readonly string[] = [API_LIB_ROLE, API_CLIENT_ROLE];\n\n/** `api-lib-dependencies`, resolved: what an api library may import from outside the api-lib set. */\nexport class ApiLibDependenciesRule {\n constructor(\n /** Package / project names (globs allowed) every api-lib and api-client may depend on. */\n public readonly apiLibPackages: readonly string[],\n /** `role:api-client` project → the extra packages it may depend on. */\n public readonly apiClientPackages: ReadonlyMap<string, readonly string[]>,\n ) {}\n}\n\n/** `api-lib-path`, resolved: the globs every api project — and only api projects — lives under. */\nexport class ApiLibPathRule {\n constructor(public readonly paths: readonly string[]) {}\n}\n\n/** One `framework-folder` entry with its framework sets canonicalised (`a+b`, tokens sorted). */\nexport class FrameworkFolder {\n constructor(\n public readonly paths: readonly string[],\n public readonly frameworkSets: readonly string[],\n public readonly roles: readonly string[],\n ) {}\n\n /** A framework set written in any order, canonicalised: `node+browser` → `browser+node`. */\n // webpieces-disable no-function-outside-class -- static helper of this class\n static canonical(frameworks: readonly string[]): string {\n return [...new Set(frameworks.map((each: string) => each.trim()).filter((each: string) => each !== ''))]\n .sort()\n .join('+');\n }\n\n // webpieces-disable no-function-outside-class -- static factory of this class\n static fromEntry(entry: FrameworkFolderEntry): FrameworkFolder {\n return new FrameworkFolder(\n entry.paths,\n entry.frameworkSets.map((set: string) => FrameworkFolder.canonical(set.split('+'))),\n entry.roles,\n );\n }\n}\n\n/** `framework-folder`, resolved. Entry ORDER matters: the first entry whose glob matches governs. */\nexport class FrameworkFolderRule {\n constructor(public readonly folders: readonly FrameworkFolder[]) {}\n}\n\n/**\n * `product-tags`, resolved: the roles whose every project must declare a `product:<name>` tag, and the\n * product dependency matrix every dependency edge must respect (#1204).\n */\nexport class ProductTagsRule {\n constructor(\n public readonly roles: readonly string[],\n public readonly dependencies: ProductDependencyMatrix,\n ) {}\n}\n\n/**\n * The four rules' switches, read from webpieces.config.json once. A rule that is OFF (or time-boxed /\n * branch-scoped off) is `null`.\n */\nexport class TagTruthRules {\n constructor(\n public readonly apiLibDependencies: ApiLibDependenciesRule | null,\n public readonly apiLibPath: ApiLibPathRule | null,\n public readonly frameworkFolder: FrameworkFolderRule | null,\n public readonly productTags: ProductTagsRule | null,\n ) {}\n\n /** Every rule off — what a caller that configured nothing asked for. */\n // webpieces-disable no-function-outside-class -- static factory of this class\n static none(): TagTruthRules {\n return new TagTruthRules(null, null, null, null);\n }\n\n anyEnabled(): boolean {\n return (\n this.apiLibDependencies !== null ||\n this.apiLibPath !== null ||\n this.frameworkFolder !== null ||\n this.productTags !== null\n );\n }\n\n /** `mode: OFF` and both escape hatches come from RuleGate, so there is ONE reading of them. */\n // webpieces-disable no-function-outside-class -- static factory of this class\n static fromConfig(workspaceRoot: string): TagTruthRules {\n const gate = new RuleGate();\n const rules = loadAndValidate(workspaceRoot).resolved.rules;\n // webpieces-disable no-any-unknown -- a validated rule entry is still opaque JSON in the option bag\n const optionsOf = (name: string): RuleOptions | null =>\n gate.isDisabled(workspaceRoot, name, true) ? null : (rules.get(name)?.options ?? null);\n\n const deps = optionsOf(\"api-lib-dependencies\");\n const where = optionsOf(\"api-lib-path\");\n const folder = optionsOf(\"framework-folder\");\n const products = optionsOf(\"product-tags\");\n return new TagTruthRules(\n deps === null ? null : TagTruthRules.dependenciesRule(deps),\n where === null ? null : new ApiLibPathRule(where['paths'] as string[]),\n folder === null\n ? null\n : new FrameworkFolderRule((folder['entries'] as FrameworkFolderEntry[]).map(FrameworkFolder.fromEntry)),\n products === null\n ? null\n : new ProductTagsRule(\n products['roles'] as string[],\n new ProductDependencyMatrix(products['productDependencies'] as ProductDependencyEntry[]),\n ),\n );\n }\n\n // webpieces-disable no-function-outside-class -- private static reader of this class\n private static dependenciesRule(options: RuleOptions): ApiLibDependenciesRule {\n const clients = new Map<string, readonly string[]>();\n for (const entry of options['apiClients'] as ApiClientPackagesEntry[]) clients.set(entry.project, entry.packages);\n return new ApiLibDependenciesRule(options['apiLibPackages'] as string[], clients);\n }\n}\n\n/** What ONE project imports from production source, and the package name others import it by. */\nexport class ProjectImports {\n constructor(\n /** The project's own `package.json` name, or null when it has none. */\n public readonly packageName: string | null,\n /** Bare package names its production (non-test) source imports. */\n public readonly prodPackages: ReadonlySet<string>,\n ) {}\n}\n\n/** The pure check: every tag-truth problem in a graph whose framework sets and roles are resolved. */\nexport class TagTruthValidator {\n constructor(private readonly rules: TagTruthRules) {}\n\n problems(\n graph: EnhancedGraph,\n infos: Map<string, ProjectInfo>,\n imports: ReadonlyMap<string, ProjectImports>,\n ): string[] {\n const problems: string[] = [];\n for (const name of Object.keys(graph).sort()) {\n const entry = graph[name];\n const info = infos.get(name);\n if (info === undefined || info.root === '' || info.root === '.') continue;\n const root = info.root.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n if (this.rules.apiLibDependencies !== null) {\n problems.push(...this.dependencyProblems(name, entry, graph, imports, this.rules.apiLibDependencies));\n }\n if (this.rules.apiLibPath !== null) {\n problems.push(...this.pathProblems(name, root, entry, this.rules.apiLibPath));\n }\n if (this.rules.frameworkFolder !== null) {\n problems.push(...this.folderProblems(name, root, entry, this.rules.frameworkFolder));\n }\n if (this.rules.productTags !== null) {\n problems.push(...this.productTagProblems(info, root, entry, this.rules.productTags));\n }\n }\n if (this.rules.productTags !== null) {\n problems.push(...this.rules.productTags.dependencies.problems(graph, this.declaredProducts(infos)));\n }\n return problems;\n }\n\n /** Every product some project's `product:` tag names — what a matrix entry may refer to. */\n private declaredProducts(infos: Map<string, ProjectInfo>): Set<string> {\n const resolver = new ProductResolver();\n const declared = new Set<string>();\n for (const info of infos.values()) {\n for (const product of resolver.resolve(info).products) declared.add(product);\n }\n return declared;\n }\n\n /**\n * #1179 — a project whose role the rule lists declares at least one well-formed `product:<name>`.\n * The DECLARED tags are read straight from the project's tags, not from the graph's `products`\n * field, so this check does not depend on enrichment order. A malformed tag is not counted here\n * because enrichGraph already fails on it, naming the tag.\n */\n private productTagProblems(info: ProjectInfo, root: string, entry: GraphEntry, rule: ProductTagsRule): string[] {\n const role = entry.role;\n if (role === undefined || !rule.roles.includes(role)) return [];\n if (new ProductResolver().resolve(info).products.length > 0) return [];\n return [\n `${\"product-tags\"}: '${info.name}' is role:${role} but carries no product tag — every ` +\n `${rule.roles.map((each: string) => `role:${each}`).join(' / ')} must name the product(s) it belongs ` +\n `to, so the architecture graphs can show one product. Add \"product:<name>\" (lowercase kebab, ` +\n `several allowed) to the \"tags\" in ${root}/project.json, e.g. \"tags\": [..., \"product:<name>\"].`,\n ];\n }\n\n /** D2 — the workspace edges and the outside packages of ONE api-lib / api-client. */\n private dependencyProblems(\n name: string,\n entry: GraphEntry,\n graph: EnhancedGraph,\n imports: ReadonlyMap<string, ProjectImports>,\n rule: ApiLibDependenciesRule,\n ): string[] {\n const role = entry.role;\n if (role === undefined || !API_ROLES.includes(role)) return [];\n const rulePrefix = `${\"api-lib-dependencies\"}: '${name}' (role:${role})`;\n const clientPackages = rule.apiClientPackages.get(name);\n if (role === API_CLIENT_ROLE && clientPackages === undefined) {\n return [\n `${rulePrefix} has no apiClients entry — what an api-client talks to is stated, never inferred. ` +\n `Add { \"project\": \"${name}\", \"packages\": [<its SDK, inversify, …>] } to ` +\n `${\"api-lib-dependencies\"}.apiClients in webpieces.config.json, or retag it role:api-lib ` +\n 'if it bundles no implementation.',\n ];\n }\n const allowed = [...rule.apiLibPackages, ...(clientPackages ?? [])];\n const listName =\n role === API_CLIENT_ROLE ? `apiLibPackages or its apiClients entry` : 'apiLibPackages';\n const problems: string[] = [];\n const workspaceNames = new Set<string>();\n for (const dep of entry.dependsOn) {\n const depImports = imports.get(dep);\n if (depImports?.packageName) workspaceNames.add(depImports.packageName);\n const depRole = graph[dep]?.role;\n if (depRole === API_LIB_ROLE) continue;\n if (matchesAnyGlob(dep, allowed)) continue;\n if (depImports?.packageName && matchesAnyGlob(depImports.packageName, allowed)) continue;\n problems.push(\n `${rulePrefix} must not depend on '${dep}' (role:${depRole ?? 'none'}) — an api library depends ` +\n `only on role:api-lib projects and the packages ${listName} lists. Move what it needs into a ` +\n `role:api-lib project, or add '${depImports?.packageName ?? dep}' to ${listName}.`,\n );\n }\n const own = imports.get(name);\n for (const pkg of [...(own?.prodPackages ?? [])].sort()) {\n if (pkg === own?.packageName || workspaceNames.has(pkg) || this.isWorkspacePackage(pkg, imports)) continue;\n if (matchesAnyGlob(pkg, allowed)) continue;\n problems.push(\n `${rulePrefix} imports '${pkg}', which ${listName} does not list — an api library's wire contract ` +\n `must not drag an outside runtime into every consumer. Remove the import, or add '${pkg}' ` +\n `to ${\"api-lib-dependencies\"}.${role === API_CLIENT_ROLE ? `apiClients[\"${name}\"].packages` : 'apiLibPackages'}.`,\n );\n }\n return problems;\n }\n\n /** A package some workspace project publishes — its edge is judged as a workspace dependency above. */\n private isWorkspacePackage(pkg: string, imports: ReadonlyMap<string, ProjectImports>): boolean {\n for (const each of imports.values()) if (each.packageName === pkg) return true;\n return false;\n }\n\n /** D10 — an api project lives under the api globs, and everything there is an api project. */\n private pathProblems(name: string, root: string, entry: GraphEntry, rule: ApiLibPathRule): string[] {\n const isApi = entry.role !== undefined && API_ROLES.includes(entry.role);\n const inPath = matchesAnyGlob(root, rule.paths);\n const globs = `[${rule.paths.join(', ')}]`;\n if (isApi && !inPath) {\n return [\n `${\"api-lib-path\"}: '${name}' is role:${entry.role} but lives at '${root}', outside ` +\n `${\"api-lib-path\"}.paths ${globs} — move it under one of them ` +\n '(nx g @nx/workspace:move), so every contract in the repo is found in one place.',\n ];\n }\n if (inPath && !isApi) {\n return [\n `${\"api-lib-path\"}: '${name}' lives at '${root}', under ${\"api-lib-path\"}.paths ` +\n `${globs}, but is role:${entry.role ?? 'none'} — everything there is a contract. Retag it ` +\n 'role:api-lib (a contract and/or its DTOs) or role:api-client (a contract plus its SDK ' +\n 'adapter), or move it out of the api tree.',\n ];\n }\n return [];\n }\n\n /** D9 — the folder and the tags agree, both directions. */\n private folderProblems(name: string, root: string, entry: GraphEntry, rule: FrameworkFolderRule): string[] {\n if (entry.framework === undefined || entry.role === undefined) return [];\n const set = FrameworkFolder.canonical(entry.framework);\n const role = entry.role;\n const governing = rule.folders.find((folder: FrameworkFolder) => matchesAnyGlob(root, folder.paths));\n const prefix = `${\"framework-folder\"}: '${name}' at '${root}'`;\n if (governing !== undefined) {\n const problems: string[] = [];\n const glob = governing.paths.join(', ');\n if (!governing.frameworkSets.includes(set)) {\n problems.push(\n `${prefix} carries framework set [${set}], but the folder ${glob} holds ` +\n `[${governing.frameworkSets.join(' | ')}] — retag it to the folder's set, or move it to ` +\n 'the folder that holds its set.',\n );\n }\n if (!governing.roles.includes(role)) {\n problems.push(\n `${prefix} is role:${role}, but the folder ${glob} holds role ` +\n `${governing.roles.map((each: string) => `role:${each}`).join(' | ')} — retag it, or move it.`,\n );\n }\n return problems;\n }\n if (APP_ROLES.includes(role) || role === 'bundle') return [];\n const homes = rule.folders.filter(\n (folder: FrameworkFolder) => folder.frameworkSets.includes(set) && folder.roles.includes(role),\n );\n if (homes.length === 0) return [];\n const globs = homes.map((folder: FrameworkFolder) => folder.paths.join(', ')).join(' | ');\n return [\n `${prefix} is a role:${role} carrying [${set}], which ${\"framework-folder\"} places under ` +\n `${globs} — move it there (nx g @nx/workspace:move), so the folder tells a reader what runs where.`,\n ];\n }\n}\n\n/** The executor-facing entry point: read the config and the imports, check, and throw before any write. */\nexport class TagTruthCheck {\n assertTrue(graph: EnhancedGraph, infos: Map<string, ProjectInfo>, workspaceRoot: string): void {\n const rules = TagTruthRules.fromConfig(workspaceRoot);\n if (!rules.anyEnabled()) return;\n const imports = rules.apiLibDependencies === null ? new Map<string, ProjectImports>() : this.importsOf(infos, workspaceRoot);\n const problems = new TagTruthValidator(rules).problems(graph, infos, imports);\n if (problems.length > 0) throw new MetadataValidationError(problems);\n }\n\n /** Every project's production imports and package name, read from its source and package.json. */\n importsOf(infos: Map<string, ProjectInfo>, workspaceRoot: string): Map<string, ProjectImports> {\n const scanner = new DepUsageScanner();\n const found = new Map<string, ProjectImports>();\n for (const info of infos.values()) {\n if (info.root === '' || info.root === '.') continue;\n const abs = path.resolve(workspaceRoot, info.root);\n found.set(info.name, new ProjectImports(this.packageNameOf(abs), scanner.scan(abs).prodPackages));\n }\n return found;\n }\n\n private packageNameOf(projectDir: string): string | null {\n const file = path.join(projectDir, 'package.json');\n if (!fs.existsSync(file)) return null;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const parsed = JSON.parse(fs.readFileSync(file, 'utf-8')) as RawPackageJson;\n return typeof parsed.name === 'string' ? parsed.name : null;\n } catch (err: unknown) {\n const error = toError(err);\n throw new Error(`Failed to parse ${file} while reading the package name tag-truth checks against`, {\n cause: error,\n });\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tag-truth.js","sourceRoot":"","sources":["../../../../../../packages/tooling/nx-webpieces-rules/src/lib/tag-truth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Tag truth — the four GRAPH rules that make an nx `role:*` / `framework:*` / `product:*` tag true\n * (#1064, #1179):\n *\n * api-lib-dependencies (D2) — a `role:api-lib` depends only on other `role:api-lib` projects, the\n * stated workspace projects (`allowedWorkspaceProjects`, #1287) and a\n * stated list of outside packages; a `role:api-client` may also import\n * the packages its own config entry names (its SDK, inversify, …).\n * api-lib-path (D10) — every api-lib / api-client lives under the configured api globs, and\n * everything under them carries one of those two roles.\n * framework-folder (D9) — the folder a library lives in and its framework set + role agree,\n * both directions.\n * product-tags (#1179) — every project whose role is listed (seed: server, client, app)\n * carries a well-formed `product:<name>` tag, the seed the product\n * filter and Product color mode derive membership from; and (#1204)\n * every dependency edge respects the product dependency matrix\n * (product-dependencies.ts), read on the RESOLVED membership.\n *\n * They run beside `library-types-match-client` and `role-dependency` (graph-metadata.ts), in\n * `architecture:generate` and `validate-architecture-unchanged`, AFTER enrichGraph has resolved every\n * project's framework set and role — so a tag is read exactly one way. Every problem across every\n * project is collected and thrown as one MetadataValidationError, before anything is written.\n *\n * There is NO default (`.claude/rules/no-rule-defaults.md`): each rule's fields come from\n * webpieces.config.json, which must state them or fail to load. `TagTruthRules.none()` is what a unit\n * test or a caller that configured nothing asked for — not a default.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { loadAndValidate, matchesAnyGlob, RuleOptions } from \"@webpieces/rules-config\";\nimport { ApiClientPackagesEntry, FrameworkFolderEntry, ProductDependencyEntry } from \"../configs/tag-truth-configs\";\nimport type { EnhancedGraph, GraphEntry } from './graph-sorter';\nimport { APP_ROLES, MetadataValidationError } from './graph-metadata';\nimport { ProjectInfo } from './project-info';\nimport { ProductResolver } from './product-resolver';\nimport { ProductDependencyMatrix } from './product-dependencies';\nimport { RuleGate } from './rule-gate';\nimport { DepUsageScanner } from './dep-usage-scanner';\nimport { toError } from '../toError';\n\n/** The only field of a package.json this check reads. */\ntype RawPackageJson = { name?: string };\n\nexport const API_LIB_ROLE = 'api-lib';\nexport const API_CLIENT_ROLE = 'api-client';\nconst API_ROLES: readonly string[] = [API_LIB_ROLE, API_CLIENT_ROLE];\n\n/** `api-lib-dependencies`, resolved: what an api library may import from outside the api-lib set. */\nexport class ApiLibDependenciesRule {\n constructor(\n /** OUTSIDE package names (globs allowed) every api-lib and api-client may import. */\n public readonly apiLibPackages: readonly string[],\n /** `role:api-client` project → the extra outside packages it may import. */\n public readonly apiClientPackages: ReadonlyMap<string, readonly string[]>,\n /**\n * WORKSPACE projects (nx name or package.json name, globs allowed) every api-lib and api-client may\n * depend on — a generator, or a deliberately shared util library (#1287). Each entry must match\n * some workspace project.\n */\n public readonly allowedWorkspaceProjects: readonly string[],\n ) {}\n}\n\n/** `api-lib-path`, resolved: the globs every api project — and only api projects — lives under. */\nexport class ApiLibPathRule {\n constructor(public readonly paths: readonly string[]) {}\n}\n\n/** One `framework-folder` entry with its framework sets canonicalised (`a+b`, tokens sorted). */\nexport class FrameworkFolder {\n constructor(\n public readonly paths: readonly string[],\n public readonly frameworkSets: readonly string[],\n public readonly roles: readonly string[],\n ) {}\n\n /** A framework set written in any order, canonicalised: `node+browser` → `browser+node`. */\n // webpieces-disable no-function-outside-class -- static helper of this class\n static canonical(frameworks: readonly string[]): string {\n return [...new Set(frameworks.map((each: string) => each.trim()).filter((each: string) => each !== ''))]\n .sort()\n .join('+');\n }\n\n // webpieces-disable no-function-outside-class -- static factory of this class\n static fromEntry(entry: FrameworkFolderEntry): FrameworkFolder {\n return new FrameworkFolder(\n entry.paths,\n entry.frameworkSets.map((set: string) => FrameworkFolder.canonical(set.split('+'))),\n entry.roles,\n );\n }\n}\n\n/** `framework-folder`, resolved. Entry ORDER matters: the first entry whose glob matches governs. */\nexport class FrameworkFolderRule {\n constructor(public readonly folders: readonly FrameworkFolder[]) {}\n}\n\n/**\n * `product-tags`, resolved: the roles whose every project must declare a `product:<name>` tag, and the\n * product dependency matrix every dependency edge must respect (#1204).\n */\nexport class ProductTagsRule {\n constructor(\n public readonly roles: readonly string[],\n public readonly dependencies: ProductDependencyMatrix,\n ) {}\n}\n\n/**\n * The four rules' switches, read from webpieces.config.json once. A rule that is OFF (or time-boxed /\n * branch-scoped off) is `null`.\n */\nexport class TagTruthRules {\n constructor(\n public readonly apiLibDependencies: ApiLibDependenciesRule | null,\n public readonly apiLibPath: ApiLibPathRule | null,\n public readonly frameworkFolder: FrameworkFolderRule | null,\n public readonly productTags: ProductTagsRule | null,\n ) {}\n\n /** Every rule off — what a caller that configured nothing asked for. */\n // webpieces-disable no-function-outside-class -- static factory of this class\n static none(): TagTruthRules {\n return new TagTruthRules(null, null, null, null);\n }\n\n anyEnabled(): boolean {\n return (\n this.apiLibDependencies !== null ||\n this.apiLibPath !== null ||\n this.frameworkFolder !== null ||\n this.productTags !== null\n );\n }\n\n /** `mode: OFF` and both escape hatches come from RuleGate, so there is ONE reading of them. */\n // webpieces-disable no-function-outside-class -- static factory of this class\n static fromConfig(workspaceRoot: string): TagTruthRules {\n const gate = new RuleGate();\n const rules = loadAndValidate(workspaceRoot).resolved.rules;\n // webpieces-disable no-any-unknown -- a validated rule entry is still opaque JSON in the option bag\n const optionsOf = (name: string): RuleOptions | null =>\n gate.isDisabled(workspaceRoot, name, true) ? null : (rules.get(name)?.options ?? null);\n\n const deps = optionsOf(\"api-lib-dependencies\");\n const where = optionsOf(\"api-lib-path\");\n const folder = optionsOf(\"framework-folder\");\n const products = optionsOf(\"product-tags\");\n return new TagTruthRules(\n deps === null ? null : TagTruthRules.dependenciesRule(deps),\n where === null ? null : new ApiLibPathRule(where['paths'] as string[]),\n folder === null\n ? null\n : new FrameworkFolderRule((folder['entries'] as FrameworkFolderEntry[]).map(FrameworkFolder.fromEntry)),\n products === null\n ? null\n : new ProductTagsRule(\n products['roles'] as string[],\n new ProductDependencyMatrix(products['productDependencies'] as ProductDependencyEntry[]),\n ),\n );\n }\n\n // webpieces-disable no-function-outside-class -- private static reader of this class\n private static dependenciesRule(options: RuleOptions): ApiLibDependenciesRule {\n const clients = new Map<string, readonly string[]>();\n for (const entry of options['apiClients'] as ApiClientPackagesEntry[]) clients.set(entry.project, entry.packages);\n return new ApiLibDependenciesRule(\n options['apiLibPackages'] as string[],\n clients,\n options['allowedWorkspaceProjects'] as string[],\n );\n }\n}\n\n/** What ONE project imports from production source, and the package name others import it by. */\nexport class ProjectImports {\n constructor(\n /** The project's own `package.json` name, or null when it has none. */\n public readonly packageName: string | null,\n /** Bare package names its production (non-test) source imports. */\n public readonly prodPackages: ReadonlySet<string>,\n ) {}\n}\n\n/** The pure check: every tag-truth problem in a graph whose framework sets and roles are resolved. */\nexport class TagTruthValidator {\n constructor(private readonly rules: TagTruthRules) {}\n\n problems(\n graph: EnhancedGraph,\n infos: Map<string, ProjectInfo>,\n imports: ReadonlyMap<string, ProjectImports>,\n ): string[] {\n const problems: string[] = [];\n for (const name of Object.keys(graph).sort()) {\n const entry = graph[name];\n const info = infos.get(name);\n if (info === undefined || info.root === '' || info.root === '.') continue;\n const root = info.root.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n if (this.rules.apiLibDependencies !== null) {\n problems.push(...this.dependencyProblems(name, entry, graph, imports, this.rules.apiLibDependencies));\n }\n if (this.rules.apiLibPath !== null) {\n problems.push(...this.pathProblems(name, root, entry, this.rules.apiLibPath));\n }\n if (this.rules.frameworkFolder !== null) {\n problems.push(...this.folderProblems(name, root, entry, this.rules.frameworkFolder));\n }\n if (this.rules.productTags !== null) {\n problems.push(...this.productTagProblems(info, root, entry, this.rules.productTags));\n }\n }\n if (this.rules.apiLibDependencies !== null) {\n problems.push(...this.deadWorkspaceEntries(graph, imports, this.rules.apiLibDependencies));\n }\n if (this.rules.productTags !== null) {\n problems.push(...this.rules.productTags.dependencies.problems(graph, this.declaredProducts(infos)));\n }\n return problems;\n }\n\n /**\n * #1287 — an `allowedWorkspaceProjects` entry that matches no workspace project (by nx name or\n * package.json name) is refused, so the list cannot rot into allowances for projects long gone.\n */\n private deadWorkspaceEntries(\n graph: EnhancedGraph,\n imports: ReadonlyMap<string, ProjectImports>,\n rule: ApiLibDependenciesRule,\n ): string[] {\n const names: string[] = [...Object.keys(graph), ...imports.keys()];\n for (const each of imports.values()) if (each.packageName) names.push(each.packageName);\n return rule.allowedWorkspaceProjects\n .filter((entry: string) => !names.some((name: string) => matchesAnyGlob(name, [entry])))\n .map(\n (entry: string) =>\n `${\"api-lib-dependencies\"}: allowedWorkspaceProjects entry '${entry}' matches no workspace ` +\n `project (by nx project name or package.json name) — an allowance for a project that is not ` +\n `there controls nothing. Delete '${entry}' from ${\"api-lib-dependencies\"}.allowedWorkspaceProjects ` +\n `in webpieces.config.json.`,\n );\n }\n\n /** Every product some project's `product:` tag names — what a matrix entry may refer to. */\n private declaredProducts(infos: Map<string, ProjectInfo>): Set<string> {\n const resolver = new ProductResolver();\n const declared = new Set<string>();\n for (const info of infos.values()) {\n for (const product of resolver.resolve(info).products) declared.add(product);\n }\n return declared;\n }\n\n /**\n * #1179 — a project whose role the rule lists declares at least one well-formed `product:<name>`.\n * The DECLARED tags are read straight from the project's tags, not from the graph's `products`\n * field, so this check does not depend on enrichment order. A malformed tag is not counted here\n * because enrichGraph already fails on it, naming the tag.\n */\n private productTagProblems(info: ProjectInfo, root: string, entry: GraphEntry, rule: ProductTagsRule): string[] {\n const role = entry.role;\n if (role === undefined || !rule.roles.includes(role)) return [];\n if (new ProductResolver().resolve(info).products.length > 0) return [];\n return [\n `${\"product-tags\"}: '${info.name}' is role:${role} but carries no product tag — every ` +\n `${rule.roles.map((each: string) => `role:${each}`).join(' / ')} must name the product(s) it belongs ` +\n `to, so the architecture graphs can show one product. Add \"product:<name>\" (lowercase kebab, ` +\n `several allowed) to the \"tags\" in ${root}/project.json, e.g. \"tags\": [..., \"product:<name>\"].`,\n ];\n }\n\n /** D2 — the workspace edges and the outside packages of ONE api-lib / api-client. */\n private dependencyProblems(\n name: string,\n entry: GraphEntry,\n graph: EnhancedGraph,\n imports: ReadonlyMap<string, ProjectImports>,\n rule: ApiLibDependenciesRule,\n ): string[] {\n const role = entry.role;\n if (role === undefined || !API_ROLES.includes(role)) return [];\n const rulePrefix = `${\"api-lib-dependencies\"}: '${name}' (role:${role})`;\n const clientPackages = rule.apiClientPackages.get(name);\n if (role === API_CLIENT_ROLE && clientPackages === undefined) {\n return [\n `${rulePrefix} has no apiClients entry — what an api-client talks to is stated, never inferred. ` +\n `Add { \"project\": \"${name}\", \"packages\": [<its SDK, inversify, …>] } to ` +\n `${\"api-lib-dependencies\"}.apiClients in webpieces.config.json, or retag it role:api-lib ` +\n 'if it bundles no implementation.',\n ];\n }\n const allowed = [...rule.apiLibPackages, ...(clientPackages ?? [])];\n const listName =\n role === API_CLIENT_ROLE ? `apiLibPackages or its apiClients entry` : 'apiLibPackages';\n const workspaceList = `${\"api-lib-dependencies\"}.allowedWorkspaceProjects`;\n const problems: string[] = [];\n const workspaceNames = new Set<string>();\n for (const dep of entry.dependsOn) {\n const depImports = imports.get(dep);\n if (depImports?.packageName) workspaceNames.add(depImports.packageName);\n const depRole = graph[dep]?.role;\n if (depRole === API_LIB_ROLE) continue;\n if (matchesAnyGlob(dep, rule.allowedWorkspaceProjects)) continue;\n if (depImports?.packageName && matchesAnyGlob(depImports.packageName, rule.allowedWorkspaceProjects)) continue;\n problems.push(\n `${rulePrefix} must not depend on '${dep}' (role:${depRole ?? 'none'}) — an api library depends ` +\n `only on role:api-lib projects and the workspace projects ${workspaceList} lists. Move what ` +\n `it needs into a role:api-lib project, or — when '${dep}' is a generator or a workspace ` +\n `library every api library may deliberately share — add '${depImports?.packageName ?? dep}' ` +\n `to ${workspaceList} in webpieces.config.json.`,\n );\n }\n const own = imports.get(name);\n for (const pkg of [...(own?.prodPackages ?? [])].sort()) {\n if (pkg === own?.packageName || workspaceNames.has(pkg) || this.isWorkspacePackage(pkg, imports)) continue;\n if (matchesAnyGlob(pkg, allowed)) continue;\n problems.push(\n `${rulePrefix} imports '${pkg}', which ${listName} does not list — an api library's wire contract ` +\n `must not drag an outside runtime into every consumer. Remove the import, or add '${pkg}' ` +\n `to ${\"api-lib-dependencies\"}.${role === API_CLIENT_ROLE ? `apiClients[\"${name}\"].packages` : 'apiLibPackages'}.`,\n );\n }\n return problems;\n }\n\n /** A package some workspace project publishes — its edge is judged as a workspace dependency above. */\n private isWorkspacePackage(pkg: string, imports: ReadonlyMap<string, ProjectImports>): boolean {\n for (const each of imports.values()) if (each.packageName === pkg) return true;\n return false;\n }\n\n /** D10 — an api project lives under the api globs, and everything there is an api project. */\n private pathProblems(name: string, root: string, entry: GraphEntry, rule: ApiLibPathRule): string[] {\n const isApi = entry.role !== undefined && API_ROLES.includes(entry.role);\n const inPath = matchesAnyGlob(root, rule.paths);\n const globs = `[${rule.paths.join(', ')}]`;\n if (isApi && !inPath) {\n return [\n `${\"api-lib-path\"}: '${name}' is role:${entry.role} but lives at '${root}', outside ` +\n `${\"api-lib-path\"}.paths ${globs} — move it under one of them ` +\n '(nx g @nx/workspace:move), so every contract in the repo is found in one place.',\n ];\n }\n if (inPath && !isApi) {\n return [\n `${\"api-lib-path\"}: '${name}' lives at '${root}', under ${\"api-lib-path\"}.paths ` +\n `${globs}, but is role:${entry.role ?? 'none'} — everything there is a contract. Retag it ` +\n 'role:api-lib (a contract and/or its DTOs) or role:api-client (a contract plus its SDK ' +\n 'adapter), or move it out of the api tree.',\n ];\n }\n return [];\n }\n\n /** D9 — the folder and the tags agree, both directions. */\n private folderProblems(name: string, root: string, entry: GraphEntry, rule: FrameworkFolderRule): string[] {\n if (entry.framework === undefined || entry.role === undefined) return [];\n const set = FrameworkFolder.canonical(entry.framework);\n const role = entry.role;\n const governing = rule.folders.find((folder: FrameworkFolder) => matchesAnyGlob(root, folder.paths));\n const prefix = `${\"framework-folder\"}: '${name}' at '${root}'`;\n if (governing !== undefined) {\n const problems: string[] = [];\n const glob = governing.paths.join(', ');\n if (!governing.frameworkSets.includes(set)) {\n problems.push(\n `${prefix} carries framework set [${set}], but the folder ${glob} holds ` +\n `[${governing.frameworkSets.join(' | ')}] — retag it to the folder's set, or move it to ` +\n 'the folder that holds its set.',\n );\n }\n if (!governing.roles.includes(role)) {\n problems.push(\n `${prefix} is role:${role}, but the folder ${glob} holds role ` +\n `${governing.roles.map((each: string) => `role:${each}`).join(' | ')} — retag it, or move it.`,\n );\n }\n return problems;\n }\n if (APP_ROLES.includes(role) || role === 'bundle') return [];\n const homes = rule.folders.filter(\n (folder: FrameworkFolder) => folder.frameworkSets.includes(set) && folder.roles.includes(role),\n );\n if (homes.length === 0) return [];\n const globs = homes.map((folder: FrameworkFolder) => folder.paths.join(', ')).join(' | ');\n return [\n `${prefix} is a role:${role} carrying [${set}], which ${\"framework-folder\"} places under ` +\n `${globs} — move it there (nx g @nx/workspace:move), so the folder tells a reader what runs where.`,\n ];\n }\n}\n\n/** The executor-facing entry point: read the config and the imports, check, and throw before any write. */\nexport class TagTruthCheck {\n assertTrue(graph: EnhancedGraph, infos: Map<string, ProjectInfo>, workspaceRoot: string): void {\n const rules = TagTruthRules.fromConfig(workspaceRoot);\n if (!rules.anyEnabled()) return;\n const imports = rules.apiLibDependencies === null ? new Map<string, ProjectImports>() : this.importsOf(infos, workspaceRoot);\n const problems = new TagTruthValidator(rules).problems(graph, infos, imports);\n if (problems.length > 0) throw new MetadataValidationError(problems);\n }\n\n /** Every project's production imports and package name, read from its source and package.json. */\n importsOf(infos: Map<string, ProjectInfo>, workspaceRoot: string): Map<string, ProjectImports> {\n const scanner = new DepUsageScanner();\n const found = new Map<string, ProjectImports>();\n for (const info of infos.values()) {\n if (info.root === '' || info.root === '.') continue;\n const abs = path.resolve(workspaceRoot, info.root);\n found.set(info.name, new ProjectImports(this.packageNameOf(abs), scanner.scan(abs).prodPackages));\n }\n return found;\n }\n\n private packageNameOf(projectDir: string): string | null {\n const file = path.join(projectDir, 'package.json');\n if (!fs.existsSync(file)) return null;\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const parsed = JSON.parse(fs.readFileSync(file, 'utf-8')) as RawPackageJson;\n return typeof parsed.name === 'string' ? parsed.name : null;\n } catch (err: unknown) {\n const error = toError(err);\n throw new Error(`Failed to parse ${file} while reading the package name tag-truth checks against`, {\n cause: error,\n });\n }\n }\n}\n"]}
|
package/src/rule-settings.js
CHANGED
package/src/rule-settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-settings.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/rule-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigObject } from '@webpieces/rules-sdk';\n\n/** Optional knobs only. Required behaviour is always supplied by the repository. */\nexport const optionalTuning: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {},\n \"no-file-import-cycles\": {},\n \"runtime-architecture\": {},\n \"nx-wiring\": {},\n \"di-graph\": {},\n \"missing-design-annotation\": {},\n \"validate-architecture-unchanged\": {},\n \"validate-no-architecture-cycles\": {},\n \"validate-packagejson\": {},\n \"validate-versions-locked\": {},\n \"validate-eslint-sync\": {},\n \"no-root-union-api-type\": {},\n \"api-rules-for-openapi\": {},\n \"api-rules-for-mcp\": {},\n \"api-lib-dependencies\": {},\n \"api-lib-path\": {},\n \"framework-folder\": {},\n \"product-tags\": {}\n};\n\n/** Written for review by setup/sync; never used as a loader fallback. */\nexport const recommendedSeeds: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"maxLines\": 400,\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-file-import-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"runtime-architecture\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"nx-wiring\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"di-graph\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"missing-design-annotation\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-architecture-unchanged\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-no-architecture-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-packagejson\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-versions-locked\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-eslint-sync\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-root-union-api-type\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-openapi\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-mcp\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-lib-dependencies\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"apiLibPackages\": [\n \"@webpieces/core-util\",\n \"tslib\"\n ],\n \"apiClients\": []\n },\n \"api-lib-path\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"paths\": [\n \"libraries/apis/**\"\n ]\n },\n \"framework-folder\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"entries\": [\n {\n \"paths\": [\n \"libraries/angular/**\"\n ],\n \"frameworkSets\": [\n \"angular\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/node/**\"\n ],\n \"frameworkSets\": [\n \"node\",\n \"express\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/universal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/react-native/**\"\n ],\n \"frameworkSets\": [\n \"react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/internal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-node/**\"\n ],\n \"frameworkSets\": [\n \"node\"\n ],\n \"roles\": [\n \"api-client\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n }\n ]\n },\n \"product-tags\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"roles\": [\n \"server\",\n \"client\",\n \"app\"\n ],\n \"productDependencies\": [],\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"rule-settings.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/rule-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigObject } from '@webpieces/rules-sdk';\n\n/** Optional knobs only. Required behaviour is always supplied by the repository. */\nexport const optionalTuning: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {},\n \"no-file-import-cycles\": {},\n \"runtime-architecture\": {},\n \"nx-wiring\": {},\n \"di-graph\": {},\n \"missing-design-annotation\": {},\n \"validate-architecture-unchanged\": {},\n \"validate-no-architecture-cycles\": {},\n \"validate-packagejson\": {},\n \"validate-versions-locked\": {},\n \"validate-eslint-sync\": {},\n \"no-root-union-api-type\": {},\n \"api-rules-for-openapi\": {},\n \"api-rules-for-mcp\": {},\n \"api-lib-dependencies\": {},\n \"api-lib-path\": {},\n \"framework-folder\": {},\n \"product-tags\": {}\n};\n\n/** Written for review by setup/sync; never used as a loader fallback. */\nexport const recommendedSeeds: Readonly<Record<string, ConfigObject>> = {\n \"wiring-format\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"maxLines\": 400,\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-file-import-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"runtime-architecture\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"nx-wiring\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"di-graph\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"missing-design-annotation\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-architecture-unchanged\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-no-architecture-cycles\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-packagejson\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-versions-locked\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"validate-eslint-sync\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"no-root-union-api-type\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-openapi\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-rules-for-mcp\": {\n \"mode\": \"AFFECTED_PROJECT\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n },\n \"api-lib-dependencies\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"apiLibPackages\": [\n \"@webpieces/core-util\",\n \"tslib\"\n ],\n \"apiClients\": [],\n \"allowedWorkspaceProjects\": []\n },\n \"api-lib-path\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"paths\": [\n \"libraries/apis/**\"\n ]\n },\n \"framework-folder\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null,\n \"entries\": [\n {\n \"paths\": [\n \"libraries/angular/**\"\n ],\n \"frameworkSets\": [\n \"angular\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/node/**\"\n ],\n \"frameworkSets\": [\n \"node\",\n \"express\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/universal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/react-native/**\"\n ],\n \"frameworkSets\": [\n \"react-native\"\n ],\n \"roles\": [\n \"lib\",\n \"designed-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/internal/**\"\n ],\n \"frameworkSets\": [\n \"browser+node+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-node/**\"\n ],\n \"frameworkSets\": [\n \"node\"\n ],\n \"roles\": [\n \"api-client\"\n ]\n },\n {\n \"paths\": [\n \"libraries/apis/external-rn-browser/**\"\n ],\n \"frameworkSets\": [\n \"browser+react-native\"\n ],\n \"roles\": [\n \"api-lib\"\n ]\n }\n ]\n },\n \"product-tags\": {\n \"mode\": \"RUN_EVERY_TIME\",\n \"roles\": [\n \"server\",\n \"client\",\n \"app\"\n ],\n \"productDependencies\": [],\n \"turnOffRuleUntilEpoch\": 0,\n \"turnOffRuleWhileOnBranch\": null\n }\n};\n"]}
|