@webpieces/nx-webpieces-rules 0.4.820 → 0.4.821
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/nx-webpieces-rules",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.821",
|
|
4
4
|
"description": "Nx-specific webpieces validation rules and graph tooling. Bundles all @webpieces rule packages with Nx graph validators and an inference plugin.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@webpieces/ai-hook-rules": "0.4.
|
|
22
|
-
"@webpieces/api-doc-model": "0.4.
|
|
23
|
-
"@webpieces/code-rules": "0.4.
|
|
24
|
-
"@webpieces/core-util": "0.4.
|
|
25
|
-
"@webpieces/eslint-rules": "0.4.
|
|
26
|
-
"@webpieces/pr-gate": "0.4.
|
|
27
|
-
"@webpieces/rules-config": "0.4.
|
|
21
|
+
"@webpieces/ai-hook-rules": "0.4.821",
|
|
22
|
+
"@webpieces/api-doc-model": "0.4.821",
|
|
23
|
+
"@webpieces/code-rules": "0.4.821",
|
|
24
|
+
"@webpieces/core-util": "0.4.821",
|
|
25
|
+
"@webpieces/eslint-rules": "0.4.821",
|
|
26
|
+
"@webpieces/pr-gate": "0.4.821",
|
|
27
|
+
"@webpieces/rules-config": "0.4.821",
|
|
28
28
|
"madge": "8.0.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
@@ -18,7 +18,7 @@ import { TargetConfiguration } from '@nx/devkit';
|
|
|
18
18
|
* measured ~3.2x contention cost
|
|
19
19
|
* is what that buys you). Scoped to the rule-running targets, `build`/`test`/`lint` keep sharing.
|
|
20
20
|
*
|
|
21
|
-
* The two vars are the same pair `
|
|
21
|
+
* The two vars are the same pair `BranchIdentity.current()` reads, in the same order, so the hash keys off
|
|
22
22
|
* exactly the values the skip decision keys off. A plain `git rev-parse` is deliberately NOT used: nx
|
|
23
23
|
* inputs must be cheap and pure, and on the CI checkout the vars are the authoritative answer anyway.
|
|
24
24
|
*
|
|
@@ -20,7 +20,7 @@ exports.BRANCH_IDENTITY_INPUTS = void 0;
|
|
|
20
20
|
* measured ~3.2x contention cost
|
|
21
21
|
* is what that buys you). Scoped to the rule-running targets, `build`/`test`/`lint` keep sharing.
|
|
22
22
|
*
|
|
23
|
-
* The two vars are the same pair `
|
|
23
|
+
* The two vars are the same pair `BranchIdentity.current()` reads, in the same order, so the hash keys off
|
|
24
24
|
* exactly the values the skip decision keys off. A plain `git rev-parse` is deliberately NOT used: nx
|
|
25
25
|
* inputs must be cheap and pure, and on the CI checkout the vars are the authoritative answer anyway.
|
|
26
26
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch-identity-inputs.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/branch-identity-inputs.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACU,QAAA,sBAAsB,GAA+C;IAC9E,EAAE,GAAG,EAAE,iBAAiB,EAAE;IAC1B,EAAE,GAAG,EAAE,kBAAkB,EAAE;CAC9B,CAAC","sourcesContent":["import { TargetConfiguration } from '@nx/devkit';\n\n/**\n * The BRANCH IDENTITY, as nx task-hash inputs. Append these to any CACHED target that can be turned off by\n * `turnOffRuleWhileOnBranch`.\n *\n * WHY A CACHED RULE TARGET NEEDS THEM: the branch hatch makes a rule's verdict depend on which branch you\n * are on, and nothing about the branch is otherwise in the hash. So a hatched branch runs `<project>:ci`\n * green and caches it under hash H; a later, UNRELATED PR that did not touch that project's files hashes to\n * the same H and REPLAYS the hatched green — the relaxation escapes the one branch that opted into it,\n * which is the single property the hatch is supposed to guarantee.\n *\n * `{workspaceRoot}/webpieces.config.json` in `sharedGlobals` (nx.json) is the other half and neither half\n * is sufficient alone: the config file makes EDITING a hatch bust the cache, but two branches sharing one\n * unedited config file still hash identically — which is exactly the leak above.\n *\n * DELIBERATELY NOT IN `sharedGlobals`. Putting a branch-varying value there would make EVERY task hash\n * branch-unique and destroy cross-branch cache reuse fleet-wide (`.claude/rules/build-verification.md`'s\n * measured ~3.2x contention cost\n * is what that buys you). Scoped to the rule-running targets, `build`/`test`/`lint` keep sharing.\n *\n * The two vars are the same pair `
|
|
1
|
+
{"version":3,"file":"branch-identity-inputs.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/branch-identity-inputs.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACU,QAAA,sBAAsB,GAA+C;IAC9E,EAAE,GAAG,EAAE,iBAAiB,EAAE;IAC1B,EAAE,GAAG,EAAE,kBAAkB,EAAE;CAC9B,CAAC","sourcesContent":["import { TargetConfiguration } from '@nx/devkit';\n\n/**\n * The BRANCH IDENTITY, as nx task-hash inputs. Append these to any CACHED target that can be turned off by\n * `turnOffRuleWhileOnBranch`.\n *\n * WHY A CACHED RULE TARGET NEEDS THEM: the branch hatch makes a rule's verdict depend on which branch you\n * are on, and nothing about the branch is otherwise in the hash. So a hatched branch runs `<project>:ci`\n * green and caches it under hash H; a later, UNRELATED PR that did not touch that project's files hashes to\n * the same H and REPLAYS the hatched green — the relaxation escapes the one branch that opted into it,\n * which is the single property the hatch is supposed to guarantee.\n *\n * `{workspaceRoot}/webpieces.config.json` in `sharedGlobals` (nx.json) is the other half and neither half\n * is sufficient alone: the config file makes EDITING a hatch bust the cache, but two branches sharing one\n * unedited config file still hash identically — which is exactly the leak above.\n *\n * DELIBERATELY NOT IN `sharedGlobals`. Putting a branch-varying value there would make EVERY task hash\n * branch-unique and destroy cross-branch cache reuse fleet-wide (`.claude/rules/build-verification.md`'s\n * measured ~3.2x contention cost\n * is what that buys you). Scoped to the rule-running targets, `build`/`test`/`lint` keep sharing.\n *\n * The two vars are the same pair `BranchIdentity.current()` reads, in the same order, so the hash keys off\n * exactly the values the skip decision keys off. A plain `git rev-parse` is deliberately NOT used: nx\n * inputs must be cheap and pure, and on the CI checkout the vars are the authoritative answer anyway.\n *\n * These are object literals because that is the nx INPUT DSL, not a webpieces data structure — the same\n * form the `{'runtime': ...}` inputs in validation-targets.ts already use.\n */\nexport const BRANCH_IDENTITY_INPUTS: NonNullable<TargetConfiguration['inputs']> = [\n { env: 'GITHUB_HEAD_REF' },\n { env: 'WEBPIECES_BRANCH' },\n];\n"]}
|
package/src/plugin.d.ts
CHANGED
|
@@ -100,6 +100,8 @@ export declare const createNodesV2: CreateNodesV2<ArchitecturePluginOptions>;
|
|
|
100
100
|
* NOTE: Type checking is done by the build target (@nx/js:tsc) during compilation.
|
|
101
101
|
*/
|
|
102
102
|
export declare function createCiTarget(perProjectValidation: string[], architectureEnabled: boolean): TargetConfiguration;
|
|
103
|
+
/** Emergency profile: retain compilation/typechecking and tests, schedule no lint or policy target. */
|
|
104
|
+
export declare function createHotfixCiTarget(): TargetConfiguration;
|
|
103
105
|
/**
|
|
104
106
|
* Export plugin as default for Nx
|
|
105
107
|
*/
|
package/src/plugin.js
CHANGED
|
@@ -22,6 +22,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
22
22
|
exports.createNodesV2 = void 0;
|
|
23
23
|
exports.isInsideNestedGitRepo = isInsideNestedGitRepo;
|
|
24
24
|
exports.createCiTarget = createCiTarget;
|
|
25
|
+
exports.createHotfixCiTarget = createHotfixCiTarget;
|
|
25
26
|
const path_1 = require("path");
|
|
26
27
|
const fs_1 = require("fs");
|
|
27
28
|
const runtime_targets_1 = require("./runtime-targets");
|
|
@@ -181,6 +182,7 @@ function addPerProjectTargets(results, projectFiles, opts, context) {
|
|
|
181
182
|
* Build the target map for one project. Most targets are project.json-only
|
|
182
183
|
* (package.json-only projects may not have TypeScript source); `ci` goes on all.
|
|
183
184
|
*/
|
|
185
|
+
// webpieces-disable no-function-outside-class -- Nx requires its inference callback and target-map assembly at module scope; this existing functional plugin is invoked by Nx, not DI.
|
|
184
186
|
function buildPerProjectTargets(isProjectJson, projectRoot, opts, architectureEnabled, rawProject) {
|
|
185
187
|
const targets = {};
|
|
186
188
|
// Per-project validation gates that `ci` must depend on. Collected as they are added
|
|
@@ -219,6 +221,7 @@ function buildPerProjectTargets(isProjectJson, projectRoot, opts, architectureEn
|
|
|
219
221
|
// lint + build + test + the validation gates that formerly rode on the compile
|
|
220
222
|
// executor's targetDefaults, so a bare `build` stays a fast compile-only step.
|
|
221
223
|
targets['ci'] = createCiTarget(validationTargets, architectureEnabled);
|
|
224
|
+
targets['hotfix-ci'] = createHotfixCiTarget();
|
|
222
225
|
return targets;
|
|
223
226
|
}
|
|
224
227
|
/**
|
|
@@ -449,6 +452,20 @@ function createCiTarget(perProjectValidation, architectureEnabled) {
|
|
|
449
452
|
},
|
|
450
453
|
};
|
|
451
454
|
}
|
|
455
|
+
/** Emergency profile: retain compilation/typechecking and tests, schedule no lint or policy target. */
|
|
456
|
+
// webpieces-disable no-function-outside-class -- Nx inference target factory, matching createCiTarget and invoked by the module-scope plugin callback.
|
|
457
|
+
function createHotfixCiTarget() {
|
|
458
|
+
return {
|
|
459
|
+
executor: 'nx:noop',
|
|
460
|
+
cache: true,
|
|
461
|
+
inputs: ['default', ...branch_identity_inputs_1.BRANCH_IDENTITY_INPUTS],
|
|
462
|
+
dependsOn: ['build', 'test'],
|
|
463
|
+
metadata: {
|
|
464
|
+
technologies: ['nx'],
|
|
465
|
+
description: 'Hotfix CI: compilation/typechecking and tests only; lint and Webpieces validators bypassed',
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
}
|
|
452
469
|
function createHelpTarget() {
|
|
453
470
|
return {
|
|
454
471
|
executor: '@webpieces/nx-webpieces-rules:help',
|
package/src/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/plugin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unified Nx Inference Plugin for @webpieces/nx-webpieces-rules\n *\n * This plugin automatically creates targets for:\n * 1. Workspace-level architecture validation (generate, visualize, validate-*)\n * 2. Per-project circular dependency checking\n * 3. Per-project API documents, opted into with a TAG: `generate:openapi` infers `openapi-generate`,\n * `generate:docs-site` infers `openapi-generate` + `docs-generate` (see generate-targets.ts)\n *\n * Install with: nx add @webpieces/nx-webpieces-rules\n *\n * Usage:\n * Add to nx.json plugins array:\n * {\n * \"plugins\": [\"@webpieces/nx-webpieces-rules\"]\n * }\n *\n * Then all targets appear automatically without manual project.json configuration.\n */\n\nimport { dirname, join } from 'path';\nimport { existsSync } from 'fs';\nimport type {\n CreateNodesV2,\n CreateNodesContextV2,\n CreateNodesResultV2,\n CreateNodesResult,\n TargetConfiguration,\n} from '@nx/devkit';\nimport {\n createVisualizeRuntimeTarget,\n createValidateRuntimeArchitectureTarget,\n} from './runtime-targets';\nimport { BRANCH_IDENTITY_INPUTS } from './branch-identity-inputs';\nimport { ValidationTargets } from './validation-targets';\nimport { createDiGraphGenerateTarget } from './di-graph-targets';\nimport { GenerateTargets, RawProjectJson, RawProjectJsonReader } from './generate-targets';\n\n/**\n * Circular dependency checking options\n */\nexport interface CircularDepsOptions {\n enabled?: boolean;\n targetName?: string;\n excludePatterns?: string[];\n}\n\n/**\n * Validation options for architecture checks\n */\nexport interface ValidationOptions {\n noCycles?: boolean;\n architectureUnchanged?: boolean;\n validatePackageJson?: boolean;\n validateNewMethods?: boolean;\n validateModifiedMethods?: boolean;\n validateModifiedFiles?: boolean;\n validateVersionsLocked?: boolean;\n validateTsInSrc?: boolean;\n validateNxWiring?: boolean;\n runtimeArchitecture?: boolean;\n validateApiRelations?: boolean;\n validateApiLibTag?: boolean;\n diGraph?: boolean;\n newMethodsMaxLines?: number;\n modifiedAndNewMethodsMaxLines?: number;\n modifiedFilesMaxLines?: number;\n /**\n * Validation mode for method/file size limits:\n * - STRICT: All limits enforced, disable comments ignored\n * - NORMAL: Limits enforced, disable comments with dates work\n * - OFF: Skip size validations entirely (for fast iteration)\n */\n validationMode?: 'STRICT' | 'NORMAL' | 'OFF';\n}\n\n/**\n * Feature flags for workspace targets\n */\nexport interface FeatureOptions {\n generate?: boolean;\n visualize?: boolean;\n visualizeRuntime?: boolean;\n}\n\n/**\n * Workspace-level configuration options\n */\nexport interface WorkspaceOptions {\n enabled?: boolean;\n targetPrefix?: string;\n graphPath?: string;\n validations?: ValidationOptions;\n features?: FeatureOptions;\n}\n\n/**\n * Configuration for @webpieces/nx-webpieces-rules Nx plugin\n */\nexport interface ArchitecturePluginOptions {\n circularDeps?: CircularDepsOptions;\n workspace?: WorkspaceOptions;\n}\n\nconst DEFAULT_OPTIONS: Required<ArchitecturePluginOptions> = {\n circularDeps: {\n enabled: true,\n targetName: 'validate-no-file-import-cycles',\n excludePatterns: [],\n },\n workspace: {\n enabled: true,\n targetPrefix: 'arch:',\n graphPath: 'architecture/dependencies.json',\n validations: {\n noCycles: true,\n architectureUnchanged: true,\n validatePackageJson: true,\n validateNewMethods: true,\n validateModifiedMethods: true,\n validateModifiedFiles: true,\n validateVersionsLocked: true,\n validateTsInSrc: true,\n validateNxWiring: true,\n runtimeArchitecture: true,\n validateApiRelations: true,\n validateApiLibTag: true,\n diGraph: true,\n newMethodsMaxLines: 30,\n modifiedAndNewMethodsMaxLines: 80,\n modifiedFilesMaxLines: 900,\n validationMode: 'NORMAL',\n },\n features: {\n generate: true,\n visualize: true,\n visualizeRuntime: true,\n },\n },\n};\n\nfunction normalizeOptions(\n options: ArchitecturePluginOptions | undefined,\n): Required<ArchitecturePluginOptions> {\n const circularDeps = {\n ...DEFAULT_OPTIONS.circularDeps,\n ...options?.circularDeps,\n };\n\n const workspace = {\n ...DEFAULT_OPTIONS.workspace,\n ...options?.workspace,\n validations: {\n ...DEFAULT_OPTIONS.workspace.validations,\n ...options?.workspace?.validations,\n },\n features: {\n ...DEFAULT_OPTIONS.workspace.features,\n ...options?.workspace?.features,\n },\n };\n\n return {\n circularDeps,\n workspace,\n } as Required<ArchitecturePluginOptions>;\n}\n\nasync function createNodesFunction(\n projectFiles: readonly string[],\n options: ArchitecturePluginOptions | undefined,\n context: CreateNodesContextV2,\n): Promise<CreateNodesResultV2> {\n const opts = normalizeOptions(options);\n const results: CreateNodesResultV2 = [];\n\n // Add workspace-level architecture targets\n addArchitectureProject(results, projectFiles, opts, context);\n\n // Add per-project targets (circular-deps, ci, di-graph)\n addPerProjectTargets(results, projectFiles, opts, context);\n\n return results;\n}\n\nfunction addArchitectureProject(\n results: CreateNodesResultV2,\n projectFiles: readonly string[],\n opts: Required<ArchitecturePluginOptions>,\n context: CreateNodesContextV2,\n): void {\n if (!opts.workspace.enabled) return;\n\n const archDirPath = join(context.workspaceRoot, 'architecture');\n if (!existsSync(archDirPath)) return;\n\n const workspaceTargets = createWorkspaceTargetsWithoutPrefix(opts);\n if (Object.keys(workspaceTargets).length === 0) return;\n\n const result: CreateNodesResult = {\n projects: {\n architecture: {\n name: 'architecture',\n root: 'architecture',\n targets: workspaceTargets,\n },\n },\n };\n\n const firstProjectFile = projectFiles[0];\n if (firstProjectFile) {\n results.push([firstProjectFile, result] as const);\n }\n}\n\n\n// A project sits inside a NESTED git repo (e.g. a clone under repositories/) when any of its\n// ancestor dirs — up to but NOT including the workspace root — contains a `.git`. Such projects are\n// separate repos, not part of THIS workspace's graph, so they must not get inferred targets (that is\n// what drags foreign clones into `nx affected`). Same repo-boundary signal the AI guards use.\nexport function isInsideNestedGitRepo(workspaceRoot: string, projectRoot: string): boolean {\n let dir = projectRoot;\n while (dir && dir !== '.' && dir !== '/') {\n if (existsSync(join(workspaceRoot, dir, '.git'))) return true;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\n}\n\nfunction addPerProjectTargets(\n results: CreateNodesResultV2,\n projectFiles: readonly string[],\n opts: Required<ArchitecturePluginOptions>,\n context: CreateNodesContextV2,\n): void {\n // Track processed project roots to avoid duplicates when both files exist\n const processedRoots = new Set<string>();\n\n for (const projectFile of projectFiles) {\n const isProjectJson = projectFile.endsWith('project.json');\n const isPackageJson = projectFile.endsWith('package.json');\n\n if (!isProjectJson && !isPackageJson) continue;\n\n const projectRoot = dirname(projectFile);\n\n // Skip root (workspace manifest, not a project)\n if (projectRoot === '.') continue;\n\n // Skip projects inside a nested git repo (vendored clones under repositories/): they are\n // separate repos and must not be swept into this workspace's `nx affected` graph.\n if (isInsideNestedGitRepo(context.workspaceRoot, projectRoot)) continue;\n\n // Skip if we've already processed this project root\n if (processedRoots.has(projectRoot)) continue;\n\n // For package.json, skip if project.json also exists in same directory\n // (prefer project.json - it will be processed separately)\n if (isPackageJson) {\n const projectJsonPath = join(context.workspaceRoot, projectRoot, 'project.json');\n if (existsSync(projectJsonPath)) continue;\n }\n\n processedRoots.add(projectRoot);\n\n const architectureEnabled =\n opts.workspace.enabled === true &&\n existsSync(join(context.workspaceRoot, 'architecture'));\n const targets = buildPerProjectTargets(\n isProjectJson,\n projectRoot,\n opts,\n architectureEnabled,\n isProjectJson ? new RawProjectJsonReader().read(context.workspaceRoot, projectFile, projectRoot) : undefined,\n );\n\n if (Object.keys(targets).length === 0) continue;\n\n const result: CreateNodesResult = {\n projects: {\n [projectRoot]: {\n targets,\n },\n },\n };\n\n results.push([projectFile, result] as const);\n }\n}\n\n/**\n * Build the target map for one project. Most targets are project.json-only\n * (package.json-only projects may not have TypeScript source); `ci` goes on all.\n */\nfunction buildPerProjectTargets(\n isProjectJson: boolean,\n projectRoot: string,\n opts: Required<ArchitecturePluginOptions>,\n architectureEnabled: boolean,\n rawProject: RawProjectJson | undefined,\n): Record<string, TargetConfiguration> {\n const targets: Record<string, TargetConfiguration> = {};\n\n // Per-project validation gates that `ci` must depend on. Collected as they are added\n // so `ci` references only gates that actually exist on THIS project (a package.json-only\n // project has none).\n const validationTargets: string[] = [];\n\n // Add circular-deps target ONLY for project.json projects\n if (isProjectJson && opts.circularDeps.enabled) {\n if (!isExcluded(projectRoot, opts.circularDeps.excludePatterns!)) {\n const targetName = opts.circularDeps.targetName!;\n targets[targetName] = createCircularDepsTarget(projectRoot, targetName);\n validationTargets.push(targetName);\n }\n }\n\n // Per-project DI design DAG: regenerate design.json/design.md/design.html on every build.\n //\n // `di-graph-generate` is itself pushed onto validationTargets so `ci` still RUNS it — it used to ride\n // in only as the `dependsOn` of the deleted `validate-di-graph-unchanged` gate. There is no staleness\n // gate here any more: \"the regenerated design files are committed\" is now one repo-wide check in\n // `wp-review-upsert-pr` (see di-graph-targets.ts for why the per-project gate could not work).\n if (isProjectJson && opts.workspace.validations!.diGraph) {\n targets['di-graph-generate'] = createDiGraphGenerateTarget();\n validationTargets.push('di-graph-generate');\n }\n\n // API documents, opted into with a TAG (generate:openapi / generate:docs-site). An untagged project\n // costs this one in-memory tag check. They ride ci like every other build step — generation is\n // ordinary BUILD work, not a side channel (#1021).\n if (rawProject !== undefined) {\n const generated = new GenerateTargets(projectRoot, rawProject).infer();\n for (const [name, target] of Object.entries(generated)) {\n targets[name] = target;\n validationTargets.push(name);\n }\n }\n\n // Add ci target to ALL projects (both project.json and package.json). ci aggregates\n // lint + build + test + the validation gates that formerly rode on the compile\n // executor's targetDefaults, so a bare `build` stays a fast compile-only step.\n targets['ci'] = createCiTarget(validationTargets, architectureEnabled);\n\n return targets;\n}\n\n/**\n * Nx V2 Inference Plugin\n * Matches project.json and package.json files to create targets\n */\nexport const createNodesV2: CreateNodesV2<ArchitecturePluginOptions> = [\n // Pattern to match project.json and package.json files\n '**/{project,package}.json',\n\n // Inference function\n createNodesFunction,\n];\n\n/**\n * Build list of enabled validation target names for validate-complete dependency chain\n */\nfunction buildValidationTargetsList(\n validations: Required<ArchitecturePluginOptions>['workspace']['validations'],\n): string[] {\n const targets: string[] = [];\n if (validations!.noCycles) targets.push('validate-no-architecture-cycles');\n if (validations!.architectureUnchanged) targets.push('validate-architecture-unchanged');\n if (validations!.validatePackageJson) targets.push('validate-packagejson');\n // Use combined validate-code instead of 3 separate targets\n if (\n validations!.validateNewMethods ||\n validations!.validateModifiedMethods ||\n validations!.validateModifiedFiles\n ) {\n targets.push('validate-code');\n }\n if (validations!.validateVersionsLocked) targets.push('validate-versions-locked');\n if (validations!.validateTsInSrc) targets.push('validate-ts-in-src');\n if (validations!.validateNxWiring) targets.push('validate-nx-wiring');\n if (validations!.runtimeArchitecture) targets.push('validate-runtime-architecture');\n if (validations!.validateApiRelations) targets.push('validate-api-relations');\n if (validations!.validateApiLibTag) targets.push('validate-api-lib-tag');\n return targets;\n}\n\n/**\n * Create workspace-level architecture validation targets WITHOUT prefix\n * Used for virtual 'architecture' project\n */\nfunction createWorkspaceTargetsWithoutPrefix(\n opts: Required<ArchitecturePluginOptions>,\n): Record<string, TargetConfiguration> {\n const targets: Record<string, TargetConfiguration> = {};\n const graphPath = opts.workspace.graphPath!;\n const validations = opts.workspace.validations!;\n // One ValidationTargets instance, injected below to build each target config.\n const targetFactory = new ValidationTargets();\n\n // Add help target (always available)\n targets['help'] = createHelpTarget();\n\n if (opts.workspace.features!.generate) {\n targets['generate'] = createGenerateTarget(graphPath);\n }\n if (opts.workspace.features!.visualize) {\n targets['visualize'] = createVisualizeTargetWithoutPrefix(graphPath);\n }\n if (opts.workspace.features!.visualizeRuntime) {\n targets['visualize-runtime'] = createVisualizeRuntimeTarget();\n }\n if (validations.noCycles) {\n targets['validate-no-architecture-cycles'] = targetFactory.noCycles();\n }\n if (validations.architectureUnchanged) {\n targets['validate-architecture-unchanged'] = createValidateUnchangedTarget(graphPath);\n }\n if (validations.validatePackageJson) {\n targets['validate-packagejson'] = targetFactory.packageJson();\n }\n // Always available (cheap; success when a repo has no checklists). Kept out of the validate-complete /\n // ci aggregate so it does not change existing gate behavior — consumers point a required check at it.\n targets['validate-checklist-docs'] = targetFactory.checklistDocs();\n // Use combined validate-code instead of 3 separate targets\n // Options come from webpieces.config.json at the workspace root\n // (loaded via @webpieces/rules-config; same source of truth as @webpieces/ai-hook-rules)\n if (\n validations.validateNewMethods ||\n validations.validateModifiedMethods ||\n validations.validateModifiedFiles\n ) {\n targets['validate-code'] = targetFactory.code();\n }\n if (validations.validateVersionsLocked) {\n targets['validate-versions-locked'] = targetFactory.versionsLocked();\n }\n if (validations.validateTsInSrc) {\n targets['validate-ts-in-src'] = targetFactory.tsInSrc();\n }\n if (validations.validateNxWiring) {\n targets['validate-nx-wiring'] = targetFactory.nxWiring();\n }\n if (validations.runtimeArchitecture) {\n targets['validate-runtime-architecture'] = createValidateRuntimeArchitectureTarget();\n }\n if (validations.validateApiRelations) {\n targets['validate-api-relations'] = targetFactory.apiRelations();\n }\n if (validations.validateApiLibTag) {\n targets['validate-api-lib-tag'] = targetFactory.apiLibTag();\n }\n\n // Add validate-complete target that runs all enabled validations\n const validationTargets = buildValidationTargetsList(validations);\n if (validationTargets.length > 0) {\n targets['validate-complete'] = createValidateCompleteTarget(validationTargets);\n }\n\n return targets;\n}\n\nfunction createGenerateTarget(graphPath: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:generate',\n cache: false,\n outputs: [\n '{workspaceRoot}/architecture/dependencies.json',\n '{workspaceRoot}/architecture/dependencies.html',\n '{workspaceRoot}/architecture/apis',\n '{workspaceRoot}/architecture/runtime-dependencies.json',\n ],\n options: { graphPath },\n metadata: {\n technologies: ['nx'],\n description:\n 'Generate the architecture dependency graph (+ clickable dependencies.html) and the runtime microservice graph',\n },\n };\n}\n\nfunction createVisualizeTargetWithoutPrefix(graphPath: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:visualize',\n dependsOn: ['generate'],\n options: { graphPath },\n metadata: {\n technologies: ['nx'],\n description: 'Generate visual representations of the architecture graph',\n },\n };\n}\n\nfunction createValidateUnchangedTarget(graphPath: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-architecture-unchanged',\n cache: false,\n inputs: ['default', '{workspaceRoot}/architecture/dependencies.json'],\n options: { graphPath },\n metadata: {\n technologies: ['nx'],\n description: 'Validate the architecture matches the saved blessed graph',\n },\n };\n}\n\nfunction createValidateNewMethodsTarget(\n maxLines: number,\n mode: 'STRICT' | 'NORMAL' | 'OFF',\n): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-new-methods',\n cache: false, // Don't cache - depends on git state\n inputs: ['default'],\n options: { max: maxLines, mode },\n metadata: {\n technologies: ['nx'],\n description: `Validate new methods do not exceed ${maxLines} lines (only runs in affected mode)`,\n },\n };\n}\n\nfunction createValidateModifiedMethodsTarget(\n maxLines: number,\n mode: 'STRICT' | 'NORMAL' | 'OFF',\n): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-modified-methods',\n cache: false, // Don't cache - depends on git state\n inputs: ['default'],\n options: { max: maxLines, mode },\n metadata: {\n technologies: ['nx'],\n description: `Validate new and modified methods do not exceed ${maxLines} lines (encourages gradual cleanup)`,\n },\n };\n}\n\nfunction createValidateModifiedFilesTarget(\n maxLines: number,\n mode: 'STRICT' | 'NORMAL' | 'OFF',\n): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-modified-files',\n cache: false, // Don't cache - depends on git state\n inputs: ['default'],\n options: { max: maxLines, mode },\n metadata: {\n technologies: ['nx'],\n description: `Validate modified files do not exceed ${maxLines} lines (encourages keeping files small)`,\n },\n };\n}\n\nfunction createValidateCompleteTarget(validationTargets: string[]): TargetConfiguration {\n return {\n executor: 'nx:noop',\n cache: true,\n dependsOn: validationTargets,\n metadata: {\n technologies: ['nx'],\n description: 'Run all architecture validations (cycles, unchanged, package.json, code rules)',\n },\n };\n}\n\n/**\n * Create per-project ci target - Gradle-style composite target\n * Composite CI target: runs lint, build, test, and every validation gate.\n *\n * Validation (architecture graph completeness, per-project file-import cycles, DI-graph\n * unchanged) lives HERE, not on the build/compile target. That keeps `nx build` a fast\n * compile-only step for local iteration while `nx ci` is the full gate the PR check runs.\n *\n * The per-project gates are passed in because they exist only on project.json projects;\n * `architecture:validate-complete` is a cross-project dep added only when the workspace\n * `architecture` project exists.\n *\n * NOTE: Type checking is done by the build target (@nx/js:tsc) during compilation.\n */\n// webpieces-disable no-function-outside-class -- Nx inference plugin: createNodes invokes these as module-scope target factories; the entire plugin is intentionally functional (matching the surrounding 18 factories), a DI class is not how the Nx plugin API is called.\nexport function createCiTarget(\n perProjectValidation: string[],\n architectureEnabled: boolean,\n): TargetConfiguration {\n const dependsOn: string[] = ['lint', 'build', 'test', ...perProjectValidation];\n if (architectureEnabled) {\n dependsOn.push('architecture:validate-complete');\n }\n return {\n executor: 'nx:noop',\n cache: true,\n // The branch is part of what `ci` asserts, because the rules it aggregates can be switched off by\n // turnOffRuleWhileOnBranch. Its own cache entry is a noop, but a `ci` hash that ignores the branch\n // is a green claim about a branch that was never checked. See branch-identity-inputs.ts.\n inputs: ['default', ...BRANCH_IDENTITY_INPUTS],\n dependsOn,\n metadata: {\n technologies: ['nx'],\n description:\n 'Run all CI checks: lint, build, test, and validation (Gradle-style composite target)',\n },\n };\n}\n\nfunction createHelpTarget(): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:help',\n cache: false, // Never cache - always show help output\n metadata: {\n technologies: ['nx'],\n description: 'Display help for @webpieces/nx-webpieces-rules commands and targets',\n },\n };\n}\n\n/**\n * Create per-project circular dependency checking target.\n *\n * Uses the `validate-no-file-import-cycles` executor (which bundles madge as a\n * dependency) rather than a runtime `npx madge` fetch. The executor reads\n * webpieces.config.json so the gate can be turned on/off (`mode`) and\n * time-boxed (`turnOffRuleUntilEpoch`) like every other webpieces rule.\n *\n * Note `projectRoot` is intentionally unused now — the executor derives the\n * project root from the Nx context — but the param is kept for call-site\n * symmetry with the rest of the per-project target factories.\n */\nfunction createCircularDepsTarget(_projectRoot: string, _targetName: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-no-file-import-cycles',\n cache: true,\n // BRANCH_IDENTITY_INPUTS: this gate honors turnOffRuleWhileOnBranch, and it is CACHED, so without\n // the branch in its hash a hatched green replays onto branches the hatch never covered.\n inputs: ['default', ...BRANCH_IDENTITY_INPUTS],\n outputs: [] as string[],\n metadata: {\n technologies: ['madge'],\n description: 'Check for circular file-import dependencies using madge',\n },\n };\n}\n\n/**\n * Check if a project should be excluded based on patterns\n */\nfunction isExcluded(projectRoot: string, excludePatterns: string[]): boolean {\n if (excludePatterns.length === 0) {\n return false;\n }\n\n // Simple glob matching (could be enhanced with minimatch if needed)\n return excludePatterns.some((pattern) => {\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\*\\*/g, '.*') // ** matches any path\n .replace(/\\*/g, '[^/]*'); // * matches any string except /\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(projectRoot);\n });\n}\n\n/**\n * Export plugin as default for Nx\n */\nexport default { createNodesV2 };\n"]}
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../../../packages/tooling/nx-webpieces-rules/src/plugin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unified Nx Inference Plugin for @webpieces/nx-webpieces-rules\n *\n * This plugin automatically creates targets for:\n * 1. Workspace-level architecture validation (generate, visualize, validate-*)\n * 2. Per-project circular dependency checking\n * 3. Per-project API documents, opted into with a TAG: `generate:openapi` infers `openapi-generate`,\n * `generate:docs-site` infers `openapi-generate` + `docs-generate` (see generate-targets.ts)\n *\n * Install with: nx add @webpieces/nx-webpieces-rules\n *\n * Usage:\n * Add to nx.json plugins array:\n * {\n * \"plugins\": [\"@webpieces/nx-webpieces-rules\"]\n * }\n *\n * Then all targets appear automatically without manual project.json configuration.\n */\n\nimport { dirname, join } from 'path';\nimport { existsSync } from 'fs';\nimport type {\n CreateNodesV2,\n CreateNodesContextV2,\n CreateNodesResultV2,\n CreateNodesResult,\n TargetConfiguration,\n} from '@nx/devkit';\nimport {\n createVisualizeRuntimeTarget,\n createValidateRuntimeArchitectureTarget,\n} from './runtime-targets';\nimport { BRANCH_IDENTITY_INPUTS } from './branch-identity-inputs';\nimport { ValidationTargets } from './validation-targets';\nimport { createDiGraphGenerateTarget } from './di-graph-targets';\nimport { GenerateTargets, RawProjectJson, RawProjectJsonReader } from './generate-targets';\n\n/**\n * Circular dependency checking options\n */\nexport interface CircularDepsOptions {\n enabled?: boolean;\n targetName?: string;\n excludePatterns?: string[];\n}\n\n/**\n * Validation options for architecture checks\n */\nexport interface ValidationOptions {\n noCycles?: boolean;\n architectureUnchanged?: boolean;\n validatePackageJson?: boolean;\n validateNewMethods?: boolean;\n validateModifiedMethods?: boolean;\n validateModifiedFiles?: boolean;\n validateVersionsLocked?: boolean;\n validateTsInSrc?: boolean;\n validateNxWiring?: boolean;\n runtimeArchitecture?: boolean;\n validateApiRelations?: boolean;\n validateApiLibTag?: boolean;\n diGraph?: boolean;\n newMethodsMaxLines?: number;\n modifiedAndNewMethodsMaxLines?: number;\n modifiedFilesMaxLines?: number;\n /**\n * Validation mode for method/file size limits:\n * - STRICT: All limits enforced, disable comments ignored\n * - NORMAL: Limits enforced, disable comments with dates work\n * - OFF: Skip size validations entirely (for fast iteration)\n */\n validationMode?: 'STRICT' | 'NORMAL' | 'OFF';\n}\n\n/**\n * Feature flags for workspace targets\n */\nexport interface FeatureOptions {\n generate?: boolean;\n visualize?: boolean;\n visualizeRuntime?: boolean;\n}\n\n/**\n * Workspace-level configuration options\n */\nexport interface WorkspaceOptions {\n enabled?: boolean;\n targetPrefix?: string;\n graphPath?: string;\n validations?: ValidationOptions;\n features?: FeatureOptions;\n}\n\n/**\n * Configuration for @webpieces/nx-webpieces-rules Nx plugin\n */\nexport interface ArchitecturePluginOptions {\n circularDeps?: CircularDepsOptions;\n workspace?: WorkspaceOptions;\n}\n\nconst DEFAULT_OPTIONS: Required<ArchitecturePluginOptions> = {\n circularDeps: {\n enabled: true,\n targetName: 'validate-no-file-import-cycles',\n excludePatterns: [],\n },\n workspace: {\n enabled: true,\n targetPrefix: 'arch:',\n graphPath: 'architecture/dependencies.json',\n validations: {\n noCycles: true,\n architectureUnchanged: true,\n validatePackageJson: true,\n validateNewMethods: true,\n validateModifiedMethods: true,\n validateModifiedFiles: true,\n validateVersionsLocked: true,\n validateTsInSrc: true,\n validateNxWiring: true,\n runtimeArchitecture: true,\n validateApiRelations: true,\n validateApiLibTag: true,\n diGraph: true,\n newMethodsMaxLines: 30,\n modifiedAndNewMethodsMaxLines: 80,\n modifiedFilesMaxLines: 900,\n validationMode: 'NORMAL',\n },\n features: {\n generate: true,\n visualize: true,\n visualizeRuntime: true,\n },\n },\n};\n\nfunction normalizeOptions(\n options: ArchitecturePluginOptions | undefined,\n): Required<ArchitecturePluginOptions> {\n const circularDeps = {\n ...DEFAULT_OPTIONS.circularDeps,\n ...options?.circularDeps,\n };\n\n const workspace = {\n ...DEFAULT_OPTIONS.workspace,\n ...options?.workspace,\n validations: {\n ...DEFAULT_OPTIONS.workspace.validations,\n ...options?.workspace?.validations,\n },\n features: {\n ...DEFAULT_OPTIONS.workspace.features,\n ...options?.workspace?.features,\n },\n };\n\n return {\n circularDeps,\n workspace,\n } as Required<ArchitecturePluginOptions>;\n}\n\nasync function createNodesFunction(\n projectFiles: readonly string[],\n options: ArchitecturePluginOptions | undefined,\n context: CreateNodesContextV2,\n): Promise<CreateNodesResultV2> {\n const opts = normalizeOptions(options);\n const results: CreateNodesResultV2 = [];\n\n // Add workspace-level architecture targets\n addArchitectureProject(results, projectFiles, opts, context);\n\n // Add per-project targets (circular-deps, ci, di-graph)\n addPerProjectTargets(results, projectFiles, opts, context);\n\n return results;\n}\n\nfunction addArchitectureProject(\n results: CreateNodesResultV2,\n projectFiles: readonly string[],\n opts: Required<ArchitecturePluginOptions>,\n context: CreateNodesContextV2,\n): void {\n if (!opts.workspace.enabled) return;\n\n const archDirPath = join(context.workspaceRoot, 'architecture');\n if (!existsSync(archDirPath)) return;\n\n const workspaceTargets = createWorkspaceTargetsWithoutPrefix(opts);\n if (Object.keys(workspaceTargets).length === 0) return;\n\n const result: CreateNodesResult = {\n projects: {\n architecture: {\n name: 'architecture',\n root: 'architecture',\n targets: workspaceTargets,\n },\n },\n };\n\n const firstProjectFile = projectFiles[0];\n if (firstProjectFile) {\n results.push([firstProjectFile, result] as const);\n }\n}\n\n\n// A project sits inside a NESTED git repo (e.g. a clone under repositories/) when any of its\n// ancestor dirs — up to but NOT including the workspace root — contains a `.git`. Such projects are\n// separate repos, not part of THIS workspace's graph, so they must not get inferred targets (that is\n// what drags foreign clones into `nx affected`). Same repo-boundary signal the AI guards use.\nexport function isInsideNestedGitRepo(workspaceRoot: string, projectRoot: string): boolean {\n let dir = projectRoot;\n while (dir && dir !== '.' && dir !== '/') {\n if (existsSync(join(workspaceRoot, dir, '.git'))) return true;\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return false;\n}\n\nfunction addPerProjectTargets(\n results: CreateNodesResultV2,\n projectFiles: readonly string[],\n opts: Required<ArchitecturePluginOptions>,\n context: CreateNodesContextV2,\n): void {\n // Track processed project roots to avoid duplicates when both files exist\n const processedRoots = new Set<string>();\n\n for (const projectFile of projectFiles) {\n const isProjectJson = projectFile.endsWith('project.json');\n const isPackageJson = projectFile.endsWith('package.json');\n\n if (!isProjectJson && !isPackageJson) continue;\n\n const projectRoot = dirname(projectFile);\n\n // Skip root (workspace manifest, not a project)\n if (projectRoot === '.') continue;\n\n // Skip projects inside a nested git repo (vendored clones under repositories/): they are\n // separate repos and must not be swept into this workspace's `nx affected` graph.\n if (isInsideNestedGitRepo(context.workspaceRoot, projectRoot)) continue;\n\n // Skip if we've already processed this project root\n if (processedRoots.has(projectRoot)) continue;\n\n // For package.json, skip if project.json also exists in same directory\n // (prefer project.json - it will be processed separately)\n if (isPackageJson) {\n const projectJsonPath = join(context.workspaceRoot, projectRoot, 'project.json');\n if (existsSync(projectJsonPath)) continue;\n }\n\n processedRoots.add(projectRoot);\n\n const architectureEnabled =\n opts.workspace.enabled === true &&\n existsSync(join(context.workspaceRoot, 'architecture'));\n const targets = buildPerProjectTargets(\n isProjectJson,\n projectRoot,\n opts,\n architectureEnabled,\n isProjectJson ? new RawProjectJsonReader().read(context.workspaceRoot, projectFile, projectRoot) : undefined,\n );\n\n if (Object.keys(targets).length === 0) continue;\n\n const result: CreateNodesResult = {\n projects: {\n [projectRoot]: {\n targets,\n },\n },\n };\n\n results.push([projectFile, result] as const);\n }\n}\n\n/**\n * Build the target map for one project. Most targets are project.json-only\n * (package.json-only projects may not have TypeScript source); `ci` goes on all.\n */\n// webpieces-disable no-function-outside-class -- Nx requires its inference callback and target-map assembly at module scope; this existing functional plugin is invoked by Nx, not DI.\nfunction buildPerProjectTargets(\n isProjectJson: boolean,\n projectRoot: string,\n opts: Required<ArchitecturePluginOptions>,\n architectureEnabled: boolean,\n rawProject: RawProjectJson | undefined,\n): Record<string, TargetConfiguration> {\n const targets: Record<string, TargetConfiguration> = {};\n\n // Per-project validation gates that `ci` must depend on. Collected as they are added\n // so `ci` references only gates that actually exist on THIS project (a package.json-only\n // project has none).\n const validationTargets: string[] = [];\n\n // Add circular-deps target ONLY for project.json projects\n if (isProjectJson && opts.circularDeps.enabled) {\n if (!isExcluded(projectRoot, opts.circularDeps.excludePatterns!)) {\n const targetName = opts.circularDeps.targetName!;\n targets[targetName] = createCircularDepsTarget(projectRoot, targetName);\n validationTargets.push(targetName);\n }\n }\n\n // Per-project DI design DAG: regenerate design.json/design.md/design.html on every build.\n //\n // `di-graph-generate` is itself pushed onto validationTargets so `ci` still RUNS it — it used to ride\n // in only as the `dependsOn` of the deleted `validate-di-graph-unchanged` gate. There is no staleness\n // gate here any more: \"the regenerated design files are committed\" is now one repo-wide check in\n // `wp-review-upsert-pr` (see di-graph-targets.ts for why the per-project gate could not work).\n if (isProjectJson && opts.workspace.validations!.diGraph) {\n targets['di-graph-generate'] = createDiGraphGenerateTarget();\n validationTargets.push('di-graph-generate');\n }\n\n // API documents, opted into with a TAG (generate:openapi / generate:docs-site). An untagged project\n // costs this one in-memory tag check. They ride ci like every other build step — generation is\n // ordinary BUILD work, not a side channel (#1021).\n if (rawProject !== undefined) {\n const generated = new GenerateTargets(projectRoot, rawProject).infer();\n for (const [name, target] of Object.entries(generated)) {\n targets[name] = target;\n validationTargets.push(name);\n }\n }\n\n // Add ci target to ALL projects (both project.json and package.json). ci aggregates\n // lint + build + test + the validation gates that formerly rode on the compile\n // executor's targetDefaults, so a bare `build` stays a fast compile-only step.\n targets['ci'] = createCiTarget(validationTargets, architectureEnabled);\n targets['hotfix-ci'] = createHotfixCiTarget();\n\n return targets;\n}\n\n/**\n * Nx V2 Inference Plugin\n * Matches project.json and package.json files to create targets\n */\nexport const createNodesV2: CreateNodesV2<ArchitecturePluginOptions> = [\n // Pattern to match project.json and package.json files\n '**/{project,package}.json',\n\n // Inference function\n createNodesFunction,\n];\n\n/**\n * Build list of enabled validation target names for validate-complete dependency chain\n */\nfunction buildValidationTargetsList(\n validations: Required<ArchitecturePluginOptions>['workspace']['validations'],\n): string[] {\n const targets: string[] = [];\n if (validations!.noCycles) targets.push('validate-no-architecture-cycles');\n if (validations!.architectureUnchanged) targets.push('validate-architecture-unchanged');\n if (validations!.validatePackageJson) targets.push('validate-packagejson');\n // Use combined validate-code instead of 3 separate targets\n if (\n validations!.validateNewMethods ||\n validations!.validateModifiedMethods ||\n validations!.validateModifiedFiles\n ) {\n targets.push('validate-code');\n }\n if (validations!.validateVersionsLocked) targets.push('validate-versions-locked');\n if (validations!.validateTsInSrc) targets.push('validate-ts-in-src');\n if (validations!.validateNxWiring) targets.push('validate-nx-wiring');\n if (validations!.runtimeArchitecture) targets.push('validate-runtime-architecture');\n if (validations!.validateApiRelations) targets.push('validate-api-relations');\n if (validations!.validateApiLibTag) targets.push('validate-api-lib-tag');\n return targets;\n}\n\n/**\n * Create workspace-level architecture validation targets WITHOUT prefix\n * Used for virtual 'architecture' project\n */\nfunction createWorkspaceTargetsWithoutPrefix(\n opts: Required<ArchitecturePluginOptions>,\n): Record<string, TargetConfiguration> {\n const targets: Record<string, TargetConfiguration> = {};\n const graphPath = opts.workspace.graphPath!;\n const validations = opts.workspace.validations!;\n // One ValidationTargets instance, injected below to build each target config.\n const targetFactory = new ValidationTargets();\n\n // Add help target (always available)\n targets['help'] = createHelpTarget();\n\n if (opts.workspace.features!.generate) {\n targets['generate'] = createGenerateTarget(graphPath);\n }\n if (opts.workspace.features!.visualize) {\n targets['visualize'] = createVisualizeTargetWithoutPrefix(graphPath);\n }\n if (opts.workspace.features!.visualizeRuntime) {\n targets['visualize-runtime'] = createVisualizeRuntimeTarget();\n }\n if (validations.noCycles) {\n targets['validate-no-architecture-cycles'] = targetFactory.noCycles();\n }\n if (validations.architectureUnchanged) {\n targets['validate-architecture-unchanged'] = createValidateUnchangedTarget(graphPath);\n }\n if (validations.validatePackageJson) {\n targets['validate-packagejson'] = targetFactory.packageJson();\n }\n // Always available (cheap; success when a repo has no checklists). Kept out of the validate-complete /\n // ci aggregate so it does not change existing gate behavior — consumers point a required check at it.\n targets['validate-checklist-docs'] = targetFactory.checklistDocs();\n // Use combined validate-code instead of 3 separate targets\n // Options come from webpieces.config.json at the workspace root\n // (loaded via @webpieces/rules-config; same source of truth as @webpieces/ai-hook-rules)\n if (\n validations.validateNewMethods ||\n validations.validateModifiedMethods ||\n validations.validateModifiedFiles\n ) {\n targets['validate-code'] = targetFactory.code();\n }\n if (validations.validateVersionsLocked) {\n targets['validate-versions-locked'] = targetFactory.versionsLocked();\n }\n if (validations.validateTsInSrc) {\n targets['validate-ts-in-src'] = targetFactory.tsInSrc();\n }\n if (validations.validateNxWiring) {\n targets['validate-nx-wiring'] = targetFactory.nxWiring();\n }\n if (validations.runtimeArchitecture) {\n targets['validate-runtime-architecture'] = createValidateRuntimeArchitectureTarget();\n }\n if (validations.validateApiRelations) {\n targets['validate-api-relations'] = targetFactory.apiRelations();\n }\n if (validations.validateApiLibTag) {\n targets['validate-api-lib-tag'] = targetFactory.apiLibTag();\n }\n\n // Add validate-complete target that runs all enabled validations\n const validationTargets = buildValidationTargetsList(validations);\n if (validationTargets.length > 0) {\n targets['validate-complete'] = createValidateCompleteTarget(validationTargets);\n }\n\n return targets;\n}\n\nfunction createGenerateTarget(graphPath: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:generate',\n cache: false,\n outputs: [\n '{workspaceRoot}/architecture/dependencies.json',\n '{workspaceRoot}/architecture/dependencies.html',\n '{workspaceRoot}/architecture/apis',\n '{workspaceRoot}/architecture/runtime-dependencies.json',\n ],\n options: { graphPath },\n metadata: {\n technologies: ['nx'],\n description:\n 'Generate the architecture dependency graph (+ clickable dependencies.html) and the runtime microservice graph',\n },\n };\n}\n\nfunction createVisualizeTargetWithoutPrefix(graphPath: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:visualize',\n dependsOn: ['generate'],\n options: { graphPath },\n metadata: {\n technologies: ['nx'],\n description: 'Generate visual representations of the architecture graph',\n },\n };\n}\n\nfunction createValidateUnchangedTarget(graphPath: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-architecture-unchanged',\n cache: false,\n inputs: ['default', '{workspaceRoot}/architecture/dependencies.json'],\n options: { graphPath },\n metadata: {\n technologies: ['nx'],\n description: 'Validate the architecture matches the saved blessed graph',\n },\n };\n}\n\nfunction createValidateNewMethodsTarget(\n maxLines: number,\n mode: 'STRICT' | 'NORMAL' | 'OFF',\n): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-new-methods',\n cache: false, // Don't cache - depends on git state\n inputs: ['default'],\n options: { max: maxLines, mode },\n metadata: {\n technologies: ['nx'],\n description: `Validate new methods do not exceed ${maxLines} lines (only runs in affected mode)`,\n },\n };\n}\n\nfunction createValidateModifiedMethodsTarget(\n maxLines: number,\n mode: 'STRICT' | 'NORMAL' | 'OFF',\n): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-modified-methods',\n cache: false, // Don't cache - depends on git state\n inputs: ['default'],\n options: { max: maxLines, mode },\n metadata: {\n technologies: ['nx'],\n description: `Validate new and modified methods do not exceed ${maxLines} lines (encourages gradual cleanup)`,\n },\n };\n}\n\nfunction createValidateModifiedFilesTarget(\n maxLines: number,\n mode: 'STRICT' | 'NORMAL' | 'OFF',\n): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-modified-files',\n cache: false, // Don't cache - depends on git state\n inputs: ['default'],\n options: { max: maxLines, mode },\n metadata: {\n technologies: ['nx'],\n description: `Validate modified files do not exceed ${maxLines} lines (encourages keeping files small)`,\n },\n };\n}\n\nfunction createValidateCompleteTarget(validationTargets: string[]): TargetConfiguration {\n return {\n executor: 'nx:noop',\n cache: true,\n dependsOn: validationTargets,\n metadata: {\n technologies: ['nx'],\n description: 'Run all architecture validations (cycles, unchanged, package.json, code rules)',\n },\n };\n}\n\n/**\n * Create per-project ci target - Gradle-style composite target\n * Composite CI target: runs lint, build, test, and every validation gate.\n *\n * Validation (architecture graph completeness, per-project file-import cycles, DI-graph\n * unchanged) lives HERE, not on the build/compile target. That keeps `nx build` a fast\n * compile-only step for local iteration while `nx ci` is the full gate the PR check runs.\n *\n * The per-project gates are passed in because they exist only on project.json projects;\n * `architecture:validate-complete` is a cross-project dep added only when the workspace\n * `architecture` project exists.\n *\n * NOTE: Type checking is done by the build target (@nx/js:tsc) during compilation.\n */\n// webpieces-disable no-function-outside-class -- Nx inference plugin: createNodes invokes these as module-scope target factories; the entire plugin is intentionally functional (matching the surrounding 18 factories), a DI class is not how the Nx plugin API is called.\nexport function createCiTarget(\n perProjectValidation: string[],\n architectureEnabled: boolean,\n): TargetConfiguration {\n const dependsOn: string[] = ['lint', 'build', 'test', ...perProjectValidation];\n if (architectureEnabled) {\n dependsOn.push('architecture:validate-complete');\n }\n return {\n executor: 'nx:noop',\n cache: true,\n // The branch is part of what `ci` asserts, because the rules it aggregates can be switched off by\n // turnOffRuleWhileOnBranch. Its own cache entry is a noop, but a `ci` hash that ignores the branch\n // is a green claim about a branch that was never checked. See branch-identity-inputs.ts.\n inputs: ['default', ...BRANCH_IDENTITY_INPUTS],\n dependsOn,\n metadata: {\n technologies: ['nx'],\n description:\n 'Run all CI checks: lint, build, test, and validation (Gradle-style composite target)',\n },\n };\n}\n\n/** Emergency profile: retain compilation/typechecking and tests, schedule no lint or policy target. */\n// webpieces-disable no-function-outside-class -- Nx inference target factory, matching createCiTarget and invoked by the module-scope plugin callback.\nexport function createHotfixCiTarget(): TargetConfiguration {\n return {\n executor: 'nx:noop',\n cache: true,\n inputs: ['default', ...BRANCH_IDENTITY_INPUTS],\n dependsOn: ['build', 'test'],\n metadata: {\n technologies: ['nx'],\n description: 'Hotfix CI: compilation/typechecking and tests only; lint and Webpieces validators bypassed',\n },\n };\n}\n\nfunction createHelpTarget(): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:help',\n cache: false, // Never cache - always show help output\n metadata: {\n technologies: ['nx'],\n description: 'Display help for @webpieces/nx-webpieces-rules commands and targets',\n },\n };\n}\n\n/**\n * Create per-project circular dependency checking target.\n *\n * Uses the `validate-no-file-import-cycles` executor (which bundles madge as a\n * dependency) rather than a runtime `npx madge` fetch. The executor reads\n * webpieces.config.json so the gate can be turned on/off (`mode`) and\n * time-boxed (`turnOffRuleUntilEpoch`) like every other webpieces rule.\n *\n * Note `projectRoot` is intentionally unused now — the executor derives the\n * project root from the Nx context — but the param is kept for call-site\n * symmetry with the rest of the per-project target factories.\n */\nfunction createCircularDepsTarget(_projectRoot: string, _targetName: string): TargetConfiguration {\n return {\n executor: '@webpieces/nx-webpieces-rules:validate-no-file-import-cycles',\n cache: true,\n // BRANCH_IDENTITY_INPUTS: this gate honors turnOffRuleWhileOnBranch, and it is CACHED, so without\n // the branch in its hash a hatched green replays onto branches the hatch never covered.\n inputs: ['default', ...BRANCH_IDENTITY_INPUTS],\n outputs: [] as string[],\n metadata: {\n technologies: ['madge'],\n description: 'Check for circular file-import dependencies using madge',\n },\n };\n}\n\n/**\n * Check if a project should be excluded based on patterns\n */\nfunction isExcluded(projectRoot: string, excludePatterns: string[]): boolean {\n if (excludePatterns.length === 0) {\n return false;\n }\n\n // Simple glob matching (could be enhanced with minimatch if needed)\n return excludePatterns.some((pattern: string) => {\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\*\\*/g, '.*') // ** matches any path\n .replace(/\\*/g, '[^/]*'); // * matches any string except /\n\n const regex = new RegExp(`^${regexPattern}$`);\n return regex.test(projectRoot);\n });\n}\n\n/**\n * Export plugin as default for Nx\n */\nexport default { createNodesV2 };\n"]}
|