@webpieces/code-rules 0.3.159 → 0.3.161
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 +2 -2
- package/src/cli.js +20 -7
- package/src/cli.js.map +1 -1
- package/src/resolve-mode.js +5 -4
- package/src/resolve-mode.js.map +1 -1
- package/src/wp-ci.js +36 -25
- package/src/wp-ci.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webpieces/code-rules",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.161",
|
|
4
4
|
"description": "Standalone code validation rules extracted from architecture-validators, no Nx dependency required",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"directory": "packages/tooling/code-rules"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@webpieces/rules-config": "0.3.
|
|
23
|
+
"@webpieces/rules-config": "0.3.161"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|
package/src/cli.js
CHANGED
|
@@ -5,16 +5,29 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
6
6
|
const from_shared_config_1 = require("./from-shared-config");
|
|
7
7
|
const validate_code_1 = tslib_1.__importDefault(require("./validate-code"));
|
|
8
|
+
// webpieces-disable no-unmanaged-exceptions -- global entry point for code-rules CLI
|
|
8
9
|
async function main() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
try {
|
|
11
|
+
const workspaceRoot = process.cwd();
|
|
12
|
+
const shared = (0, rules_config_1.loadConfig)(workspaceRoot);
|
|
13
|
+
if (!shared.configPath) {
|
|
14
|
+
console.error('webpieces.config.json not found — run wp-setup-ai-hooks to initialize.');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const options = (0, from_shared_config_1.toValidateCodeOptions)(shared);
|
|
18
|
+
const result = await (0, validate_code_1.default)(options, workspaceRoot);
|
|
19
|
+
process.exit(result.success ? 0 : 1);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
const error = (0, rules_config_1.toError)(err);
|
|
23
|
+
if (err instanceof rules_config_1.InformAiError) {
|
|
24
|
+
console.error(error.message);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
console.error(`[code-rules] unexpected error: ${error.message}`);
|
|
28
|
+
}
|
|
13
29
|
process.exit(1);
|
|
14
30
|
}
|
|
15
|
-
const options = (0, from_shared_config_1.toValidateCodeOptions)(shared);
|
|
16
|
-
const result = await (0, validate_code_1.default)(options, workspaceRoot);
|
|
17
|
-
process.exit(result.success ? 0 : 1);
|
|
18
31
|
}
|
|
19
32
|
main();
|
|
20
33
|
//# sourceMappingURL=cli.js.map
|
package/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/cli.ts"],"names":[],"mappings":";;;;AACA,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/cli.ts"],"names":[],"mappings":";;;;AACA,0DAA6E;AAC7E,6DAA6D;AAC7D,4EAA8C;AAE9C,qFAAqF;AACrF,KAAK,UAAU,IAAI;IACf,IAAI,CAAC;QACD,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAA,yBAAU,EAAC,aAAa,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,wEAAwE,CAAC,CAAC;YACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QACD,MAAM,OAAO,GAAG,IAAA,0CAAqB,EAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAe,EAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAA,sBAAO,EAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,GAAG,YAAY,4BAAa,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,KAAK,CAAC,kCAAkC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { loadConfig, InformAiError, toError } from '@webpieces/rules-config';\nimport { toValidateCodeOptions } from './from-shared-config';\nimport runValidateCode from './validate-code';\n\n// webpieces-disable no-unmanaged-exceptions -- global entry point for code-rules CLI\nasync function main(): Promise<void> {\n try {\n const workspaceRoot = process.cwd();\n const shared = loadConfig(workspaceRoot);\n if (!shared.configPath) {\n console.error('webpieces.config.json not found — run wp-setup-ai-hooks to initialize.');\n process.exit(1);\n }\n const options = toValidateCodeOptions(shared);\n const result = await runValidateCode(options, workspaceRoot);\n process.exit(result.success ? 0 : 1);\n } catch (err: unknown) {\n const error = toError(err);\n if (err instanceof InformAiError) {\n console.error(error.message);\n } else {\n console.error(`[code-rules] unexpected error: ${error.message}`);\n }\n process.exit(1);\n }\n}\n\nmain();\n"]}
|
package/src/resolve-mode.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getCurrentBranch = getCurrentBranch;
|
|
4
4
|
exports.shouldSkipRule = shouldSkipRule;
|
|
5
5
|
const child_process_1 = require("child_process");
|
|
6
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
6
7
|
function getCurrentBranch() {
|
|
7
8
|
const envBranch = process.env['BRANCH_NAME'] ||
|
|
8
9
|
process.env['GIT_BRANCH'] ||
|
|
@@ -12,13 +13,13 @@ function getCurrentBranch() {
|
|
|
12
13
|
process.env['CIRCLE_BRANCH'];
|
|
13
14
|
if (envBranch)
|
|
14
15
|
return envBranch;
|
|
15
|
-
//
|
|
16
|
+
// webpieces-disable no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI
|
|
16
17
|
try {
|
|
17
18
|
return (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
|
|
18
|
-
// webpieces-disable catch-error-pattern -- intentional swallow of git command failure; no useful error to surface
|
|
19
19
|
}
|
|
20
|
-
catch {
|
|
21
|
-
|
|
20
|
+
catch (err) {
|
|
21
|
+
const error = (0, rules_config_1.toError)(err);
|
|
22
|
+
throw new rules_config_1.InformAiError(`Failed to determine current git branch: ${error.message}`);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
function shouldSkipRule(epoch, branchPattern) {
|
package/src/resolve-mode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-mode.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/resolve-mode.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"resolve-mode.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/resolve-mode.ts"],"names":[],"mappings":";;AASA,4CAgBC;AAED,wCAkBC;AA7CD,iDAAyC;AAEzC,0DAAiE;AAOjE,SAAgB,gBAAgB;IAC5B,MAAM,SAAS,GACX,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,wHAAwH;IACxH,IAAI,CAAC;QACD,OAAO,IAAA,wBAAQ,EAAC,iCAAiC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpF,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,IAAA,sBAAO,EAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,IAAI,4BAAa,CAAC,2CAA2C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;AACL,CAAC;AAED,SAAgB,cAAc,CAC1B,KAAyB,EACzB,aAAiC;IAEjC,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;YAC5B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,aAAa,GAAG,EAAE,CAAC;QAClE,CAAC;IACL,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QACrC,IAAI,UAAU,GAAG,KAAK,EAAE,CAAC;YACrB,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,6CAA6C,WAAW,EAAE,EAAE,CAAC;QAC9F,CAAC;IACL,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC","sourcesContent":["import { execSync } from 'child_process';\n\nimport { InformAiError, toError } from '@webpieces/rules-config';\n\nexport interface SkipRuleResult {\n skip: boolean;\n reason?: string;\n}\n\nexport function getCurrentBranch(): string {\n const envBranch =\n process.env['BRANCH_NAME'] ||\n process.env['GIT_BRANCH'] ||\n process.env['GITHUB_HEAD_REF'] ||\n process.env['GITHUB_REF_NAME'] ||\n process.env['CI_COMMIT_BRANCH'] ||\n process.env['CIRCLE_BRANCH'];\n if (envBranch) return envBranch;\n // webpieces-disable no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`Failed to determine current git branch: ${error.message}`);\n }\n}\n\nexport function shouldSkipRule(\n epoch: number | undefined,\n branchPattern: string | undefined\n): SkipRuleResult {\n if (branchPattern) {\n const current = getCurrentBranch();\n if (current === branchPattern) {\n return { skip: true, reason: `on branch \"${branchPattern}\"` };\n }\n }\n if (epoch !== undefined) {\n const nowSeconds = Date.now() / 1000;\n if (nowSeconds < epoch) {\n const expiresDate = new Date(epoch * 1000).toISOString().split('T')[0];\n return { skip: true, reason: `ignoreModifiedUntilEpoch active, expires: ${expiresDate}` };\n }\n }\n return { skip: false };\n}\n"]}
|
package/src/wp-ci.js
CHANGED
|
@@ -42,18 +42,16 @@ function pluginEntryMatches(entry) {
|
|
|
42
42
|
return entry.plugin === NX_PLUGIN_NAME;
|
|
43
43
|
}
|
|
44
44
|
function isPluginRegistered(nxJsonPath) {
|
|
45
|
-
|
|
45
|
+
const raw = fs.readFileSync(nxJsonPath, 'utf8');
|
|
46
|
+
// webpieces-disable no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI
|
|
46
47
|
try {
|
|
47
|
-
const raw = fs.readFileSync(nxJsonPath, 'utf8');
|
|
48
48
|
const parsed = JSON.parse(raw);
|
|
49
49
|
const plugins = parsed.plugins ?? [];
|
|
50
50
|
return plugins.some((entry) => pluginEntryMatches(entry));
|
|
51
|
-
// webpieces-disable catch-error-pattern -- malformed nx.json should report as "not registered" with guidance
|
|
52
51
|
}
|
|
53
52
|
catch (err) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return false;
|
|
53
|
+
const error = (0, rules_config_1.toError)(err);
|
|
54
|
+
throw new rules_config_1.InformAiError(`nx.json has invalid JSON — fix the file, then retry.\nParse error: ${error.message}\nFile: ${nxJsonPath}`);
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
function nxBin(root) {
|
|
@@ -83,29 +81,42 @@ function reportPluginMissing() {
|
|
|
83
81
|
console.error(` nx add ${NX_PLUGIN_NAME}\n`);
|
|
84
82
|
console.error(' (or add it manually to the "plugins" array in nx.json).\n');
|
|
85
83
|
}
|
|
84
|
+
// webpieces-disable no-unmanaged-exceptions -- global entry point for wp-ci CLI
|
|
86
85
|
async function main() {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
try {
|
|
87
|
+
const cwd = process.cwd();
|
|
88
|
+
const passthrough = process.argv.slice(2);
|
|
89
|
+
const nxJsonPath = findUp('nx.json', cwd);
|
|
90
|
+
if (!nxJsonPath) {
|
|
91
|
+
const code = await runStandalone(cwd);
|
|
92
|
+
process.exit(code);
|
|
93
|
+
}
|
|
94
|
+
const root = path.dirname(nxJsonPath);
|
|
95
|
+
if (!isPluginRegistered(nxJsonPath)) {
|
|
96
|
+
reportPluginMissing();
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
// Run the architecture + code validators first (this also runs the wiring guard,
|
|
100
|
+
// which fails loudly if nx.json no longer wires validators into the build).
|
|
101
|
+
if (fs.existsSync(path.join(root, 'architecture'))) {
|
|
102
|
+
const validateCode = runNx(root, ['run', 'architecture:validate-complete']);
|
|
103
|
+
if (validateCode !== 0)
|
|
104
|
+
process.exit(validateCode);
|
|
105
|
+
}
|
|
106
|
+
// Then the Gradle-style ci composite (lint + build + test) across affected projects.
|
|
107
|
+
const ciCode = runNx(root, ['affected', '--target=ci', ...passthrough]);
|
|
108
|
+
process.exit(ciCode);
|
|
93
109
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
110
|
+
catch (err) {
|
|
111
|
+
const error = (0, rules_config_1.toError)(err);
|
|
112
|
+
if (err instanceof rules_config_1.InformAiError) {
|
|
113
|
+
console.error(error.message);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.error(`[wp-ci] unexpected error: ${error.message}`);
|
|
117
|
+
}
|
|
97
118
|
process.exit(1);
|
|
98
119
|
}
|
|
99
|
-
// Run the architecture + code validators first (this also runs the wiring guard,
|
|
100
|
-
// which fails loudly if nx.json no longer wires validators into the build).
|
|
101
|
-
if (fs.existsSync(path.join(root, 'architecture'))) {
|
|
102
|
-
const validateCode = runNx(root, ['run', 'architecture:validate-complete']);
|
|
103
|
-
if (validateCode !== 0)
|
|
104
|
-
process.exit(validateCode);
|
|
105
|
-
}
|
|
106
|
-
// Then the Gradle-style ci composite (lint + build + test) across affected projects.
|
|
107
|
-
const ciCode = runNx(root, ['affected', '--target=ci', ...passthrough]);
|
|
108
|
-
process.exit(ciCode);
|
|
109
120
|
}
|
|
110
121
|
void main();
|
|
111
122
|
//# sourceMappingURL=wp-ci.js.map
|
package/src/wp-ci.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wp-ci.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/wp-ci.ts"],"names":[],"mappings":";;AACA;;;;;;;;;;;;;;GAcG;;;AAEH,iDAA0C;AAC1C,+CAAyB;AACzB,mDAA6B;AAE7B,
|
|
1
|
+
{"version":3,"file":"wp-ci.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/wp-ci.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * wp-ci — the universal webpieces CI entrypoint.\n *\n * Works in BOTH an Nx monorepo and a plain (non-Nx) repo, because the detection of\n * \"are we even in Nx?\" cannot live inside an Nx executor (by the time an executor runs,\n * Nx is already running). Dispatch:\n *\n * - no nx.json (non-Nx repo) -> run the standalone code validators, succeed.\n * - nx.json present, plugin NOT in it -> fail with the exact install command.\n * - nx.json present, plugin registered -> run validators (incl. the wiring guard),\n * then `nx affected --target=ci`.\n *\n * Repos reference this as a bin (`\"webpieces:ci\": \"wp-ci\"`) so the logic is versioned in\n * the npm package instead of copy-pasted into each repo's package.json (which drifts).\n */\n\nimport { spawnSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { loadConfig, InformAiError, toError } from '@webpieces/rules-config';\nimport { toValidateCodeOptions } from './from-shared-config';\nimport runValidateCode from './validate-code';\n\nconst NX_PLUGIN_NAME = '@webpieces/nx-webpieces-rules';\n\ninterface NxPluginObject {\n plugin?: string;\n}\n\ntype NxPluginEntry = string | NxPluginObject;\n\ninterface RawNxJson {\n plugins?: NxPluginEntry[];\n}\n\nfunction findUp(filename: string, startDir: string): string | null {\n let dir = startDir;\n while (true) {\n const candidate = path.join(dir, filename);\n if (fs.existsSync(candidate)) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nfunction pluginEntryMatches(entry: NxPluginEntry): boolean {\n if (typeof entry === 'string') return entry === NX_PLUGIN_NAME;\n return entry.plugin === NX_PLUGIN_NAME;\n}\n\nfunction isPluginRegistered(nxJsonPath: string): boolean {\n const raw = fs.readFileSync(nxJsonPath, 'utf8');\n // webpieces-disable no-unmanaged-exceptions -- rethrow as InformAiError so global catch surfaces readable message to AI\n try {\n const parsed = JSON.parse(raw) as RawNxJson;\n const plugins = parsed.plugins ?? [];\n return plugins.some((entry: NxPluginEntry) => pluginEntryMatches(entry));\n } catch (err: unknown) {\n const error = toError(err);\n throw new InformAiError(`nx.json has invalid JSON — fix the file, then retry.\\nParse error: ${error.message}\\nFile: ${nxJsonPath}`);\n }\n}\n\nfunction nxBin(root: string): string {\n const local = path.join(root, 'node_modules', '.bin', 'nx');\n return fs.existsSync(local) ? local : 'nx';\n}\n\nfunction runNx(root: string, args: string[]): number {\n const result = spawnSync(nxBin(root), args, { stdio: 'inherit', cwd: root });\n if (typeof result.status === 'number') return result.status;\n return 1;\n}\n\nasync function runStandalone(cwd: string): Promise<number> {\n const shared = loadConfig(cwd);\n if (!shared.configPath) {\n console.log('ℹ️ Not an Nx repo and no webpieces.config.json found — nothing to validate.');\n return 0;\n }\n console.log('ℹ️ Not an Nx repo — running standalone webpieces code validators.\\n');\n const options = toValidateCodeOptions(shared);\n const result = await runValidateCode(options, cwd);\n return result.success ? 0 : 1;\n}\n\nfunction reportPluginMissing(): void {\n console.error('\\n❌ This is an Nx monorepo but the webpieces Nx plugin is not installed.\\n');\n console.error(' Install it so the validators run during CI:\\n');\n console.error(` nx add ${NX_PLUGIN_NAME}\\n`);\n console.error(' (or add it manually to the \"plugins\" array in nx.json).\\n');\n}\n\n// webpieces-disable no-unmanaged-exceptions -- global entry point for wp-ci CLI\nasync function main(): Promise<void> {\n try {\n const cwd = process.cwd();\n const passthrough = process.argv.slice(2);\n\n const nxJsonPath = findUp('nx.json', cwd);\n if (!nxJsonPath) {\n const code = await runStandalone(cwd);\n process.exit(code);\n }\n\n const root = path.dirname(nxJsonPath);\n if (!isPluginRegistered(nxJsonPath)) {\n reportPluginMissing();\n process.exit(1);\n }\n\n // Run the architecture + code validators first (this also runs the wiring guard,\n // which fails loudly if nx.json no longer wires validators into the build).\n if (fs.existsSync(path.join(root, 'architecture'))) {\n const validateCode = runNx(root, ['run', 'architecture:validate-complete']);\n if (validateCode !== 0) process.exit(validateCode);\n }\n\n // Then the Gradle-style ci composite (lint + build + test) across affected projects.\n const ciCode = runNx(root, ['affected', '--target=ci', ...passthrough]);\n process.exit(ciCode);\n } catch (err: unknown) {\n const error = toError(err);\n if (err instanceof InformAiError) {\n console.error(error.message);\n } else {\n console.error(`[wp-ci] unexpected error: ${error.message}`);\n }\n process.exit(1);\n }\n}\n\nvoid main();\n"]}
|