Skip to content

Commit 2db9a5c

Browse files
authored
test: add debug scripts to tools (#802)
1 parent e0d7e7f commit 2db9a5c

File tree

10 files changed

+539
-0
lines changed

10 files changed

+539
-0
lines changed

nx.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
"releaseTagPattern": "v{version}"
112112
},
113113
"plugins": [
114+
"./tools/src/debug/debug.plugin.ts",
114115
{
115116
"plugin": "./tools/src/npm/npm.plugin.ts",
116117
"options": { "verbose": true }

tools/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const TOOLS_TSCONFIG_PATH = 'tools/tsconfig.tools.json';

tools/src/debug/README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# DEBUG Nx Plugin
2+
3+
A plugin that provides a set of tools to debug your Nx workspace.
4+
5+
## Usage
6+
7+
Register the plugin in your `nx.json`
8+
9+
```jsonc
10+
// nx.json
11+
{
12+
//...
13+
"plugins": ["tools/src/debug/debug.plugin.ts"]
14+
}
15+
```
16+
17+
### Options
18+
19+
You can configure the plugin by providing options object in addition to the plugin path
20+
21+
**Options:**
22+
23+
| Name | Type | Default | Description |
24+
| ---------- | -------- | --------------------------- | ------------------------- |
25+
| `tsconfig` | `string` | `tools/tsconfig.tools.json` | The tsconfig file to use. |
26+
27+
Example:
28+
29+
```jsonc
30+
// nx.json
31+
{
32+
//...
33+
"plugins": [
34+
{
35+
"plugin": "tools/src/debug/debug.plugin.ts",
36+
"options": {
37+
"tsconfig": "tools/tsconfig.tools.json"
38+
}
39+
}
40+
]
41+
}
42+
```
43+
44+
### Targets
45+
46+
#### `list-process`
47+
48+
Lists all the processes running in the workspace.
49+
50+
Options:
51+
52+
| Name | Type | Default | Description |
53+
| --------------- | -------- | ----------- | ---------------------------- |
54+
| `pidFilter` | `number` | `undefined` | Filter processes by PID. |
55+
| `commandFilter` | `string` | `undefined` | Filter processes by command. |
56+
| `slice` | `number` | `undefined` | Slice the list of processes. |
57+
58+
Example:
59+
60+
- `nx run <project-name>:list-process`
61+
- `nx run <project-name>:list-process --pidFilter=1234`
62+
- `nx run <project-name>:list-process --commandFilter=verdaccio`
63+
- `nx run <project-name>:list-process --commandFilter=verdaccio --pidFilter=1234`
64+
- `nx run <project-name>:list-process --commandFilter=verdaccio --slice=5`
65+
66+
#### `kill-process`
67+
68+
Kills a process by its PID or filter
69+
70+
Options:
71+
72+
| Name | Type | Default | Description |
73+
| --------------- | -------- | ----------- | ---------------------------- |
74+
| `pidFilter` | `number` | `undefined` | Filter processes by PID. |
75+
| `commandFilter` | `string` | `undefined` | Filter processes by command. |
76+
77+
Example:
78+
79+
- `nx run <project-name>:kill-process --pidFilter=1234`
80+
- `nx run <project-name>:kill-process --commandFilter=verdaccio`
81+
82+
## Scripts
83+
84+
### `list-process.ts`
85+
86+
Lists all the processes running in the workspace.
87+
88+
Options:
89+
90+
| Name | Type | Default | Description |
91+
| --------------- | -------- | ----------- | ---------------------------- |
92+
| `pidFilter` | `number` | `undefined` | Filter processes by PID. |
93+
| `commandFilter` | `string` | `undefined` | Filter processes by command. |
94+
| `slice` | `number` | `undefined` | Slice the list of processes. |
95+
96+
Example:
97+
98+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/list-process.ts`
99+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/list-process.ts --pidFilter=1234`
100+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/list-process.ts --commandFilter=verdaccio`
101+
102+
### `kill-process.ts`
103+
104+
Kills a process by its PID or command string.
105+
106+
Options:
107+
108+
| Name | Type | Default | Description |
109+
| --------------- | --------- | ----------- | ---------------------------- |
110+
| `pidFilter` | `number` | `undefined` | Filter processes by PID. |
111+
| `commandFilter` | `string` | `undefined` | Filter processes by command. |
112+
| `slice` | `number` | `undefined` | Slice the list of processes. |
113+
| `verbose` | `boolean` | `undefined` | Log the process to kill. |
114+
115+
Example:
116+
117+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/kill-process.ts --pidFilter=1234`
118+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/kill-process.ts --commandFilter=verdaccio --pidFilter=1234`
119+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/kill-process.ts --commandFilter=verdaccio --pidFilter=1234 --verbose`
120+
121+
### `clean-npmrc.ts`
122+
123+
Cleans the `.npmrc` file in the workspace.
124+
125+
Options:
126+
127+
| Name | Type | Default | Description |
128+
| ------------ | ---------------------- | ------- | --------------------------------------------- |
129+
| `userconfig` | `string` | none | The path to the `.npmrc` file. |
130+
| `entryMatch` | `string` \| `string[]` | none | The entries to remove from the `.npmrc` file. |
131+
132+
Example:
133+
134+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/clean-npmrc.ts --entryMatch=secretVerddacioToken`
135+
- `tsx --tsconfig=tools/tsconfig.tools.json tools/src/debug/bin/clean-npmrc.ts --userconfig=.npmrc --entryMatch=secretVerddacioToken`
136+
137+
Log npm config settings:
138+
139+
- `npm config list`
140+
- `npm config list -l`
141+
- `npm config list -l --location=global`
142+
- `npm config list -l --userconfig=path/to/file.npmrc`

tools/src/debug/bin/clean-npmrc.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import yargs, { Options } from 'yargs';
2+
import { hideBin } from 'yargs/helpers';
3+
import { cleanNpmrc } from '../utils';
4+
import { CleanNpmrcBinOptions } from './types';
5+
6+
const argv = yargs(hideBin(process.argv))
7+
.version(false)
8+
.options({
9+
userconfig: { type: 'string' },
10+
entryMatch: { type: 'array' },
11+
verbose: { type: 'boolean' },
12+
force: { type: 'boolean' },
13+
} satisfies Record<keyof CleanNpmrcBinOptions, Options>)
14+
.coerce('entriesToRemove', entriesToRemove =>
15+
Array.isArray(entriesToRemove) ? entriesToRemove : [entriesToRemove],
16+
).argv;
17+
18+
const { userconfig, entryMatch = [] } = argv as CleanNpmrcBinOptions;
19+
20+
if (entryMatch.length === 0) {
21+
throw new Error(
22+
'This would remove all entries. Please provide a entry filter --entryMatch. (or pass --force if you really want to remove ALL entries)',
23+
);
24+
}
25+
26+
cleanNpmrc({
27+
...(userconfig ? { userconfig } : {}),
28+
entryMatch,
29+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import yargs from 'yargs';
2+
import { hideBin } from 'yargs/helpers';
3+
import { PID, killProcesses } from '../utils';
4+
import { KillProcessesBinOptions } from './types';
5+
6+
const { commandMatch, pid, verbose, force } = yargs(hideBin(process.argv))
7+
.version(false)
8+
.options({
9+
force: { type: 'boolean', default: false },
10+
verbose: { type: 'boolean' },
11+
pid: { type: 'string', array: true, default: [] },
12+
commandMatch: { type: 'string', array: true, default: [] },
13+
})
14+
.coerce('commandMatch', (commandMatch: string[]) =>
15+
commandMatch.flatMap(p => p.split(',')).filter(p => p !== ''),
16+
)
17+
.coerce('pid', (pid: string[]) =>
18+
pid.flatMap(p => p.split(',')).filter(p => p !== ''),
19+
).argv as Omit<KillProcessesBinOptions, 'pid' | 'commandMatch'> & {
20+
pid: PID[];
21+
commandMatch: string[];
22+
};
23+
if (verbose && commandMatch.length > 0) {
24+
console.log(`Command Filter: ${commandMatch.join(', ')}`);
25+
}
26+
if (verbose && pid.length > 0) {
27+
console.log(`PID Filter: ${pid.join(', ')}`);
28+
}
29+
30+
if (pid.length === 0 && commandMatch.length === 0 && !force) {
31+
throw new Error(
32+
'This would kill all processes. Please provide a PID or a command filter and a PID filter. (or pass --force if you really want to kill ALL processes)',
33+
);
34+
}
35+
36+
killProcesses({ commandMatch, pid, verbose });
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import yargs from 'yargs';
2+
import { hideBin } from 'yargs/helpers';
3+
import { PID, listProcess } from '../utils';
4+
import { ListProcessesBinOptions } from './types';
5+
6+
const { commandMatch, pid, verbose, slice } = yargs(hideBin(process.argv))
7+
.version(false)
8+
.options({
9+
verbose: { type: 'boolean' },
10+
commandMatch: { type: 'string', array: true, default: [] },
11+
pid: { type: 'string', array: true, default: [] },
12+
slice: { type: 'number', default: 9 },
13+
})
14+
.coerce('commandMatch', (commandMatch: string[]) =>
15+
commandMatch.flatMap(p => p.split(',')).filter(p => p !== ''),
16+
)
17+
.coerce('pid', (pid: string[]) =>
18+
pid.flatMap(p => p.split(',')).filter(p => p !== ''),
19+
).argv as Omit<ListProcessesBinOptions, 'pid' | 'commandMatch' | 'slice'> & {
20+
pid: PID[];
21+
commandMatch: string[];
22+
} & {
23+
slice: number;
24+
};
25+
26+
if (verbose && commandMatch.length > 0) {
27+
console.log(`Command Match: ${commandMatch.join(', ')}`);
28+
}
29+
if (verbose && pid.length > 0) {
30+
console.log(`Command Match: ${pid.join(', ')}`);
31+
}
32+
33+
const processesToLog = listProcess({ commandMatch, pid }).slice(-slice); // show only last N processes
34+
35+
if (processesToLog.length === 0) {
36+
console.info(
37+
`No processes found. Filter: ${JSON.stringify(
38+
{ commandMatch, pid },
39+
null,
40+
2,
41+
)}`,
42+
);
43+
}
44+
45+
processesToLog.forEach(({ pid, command }) => {
46+
console.log(`${pid}: ${command}`);
47+
});

tools/src/debug/bin/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// options for `bin/list-processes`
2+
import { CleanNpmrcOptions, ProcessListOption } from '../utils';
3+
4+
export type ListProcessesBinOptions = ProcessListOption & {
5+
slice?: number;
6+
};
7+
8+
export type KillProcessesBinOptions = ProcessListOption & {
9+
force: boolean;
10+
};
11+
12+
export type CleanNpmrcBinOptions = CleanNpmrcOptions & {
13+
force: boolean;
14+
verbose: boolean;
15+
};

tools/src/debug/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const LIST_PROCESS_BIN = 'tools/src/debug/bin/list-process.ts';
2+
export const KILL_PROCESS_BIN = 'tools/src/debug/bin/kill-process.ts';

tools/src/debug/debug.plugin.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { type CreateNodes, type CreateNodesContext } from '@nx/devkit';
2+
import { dirname } from 'node:path';
3+
import { objectToCliArgs } from '../../../packages/nx-plugin/src/executors/internal/cli';
4+
import { TOOLS_TSCONFIG_PATH } from '../constants';
5+
import { KILL_PROCESS_BIN, LIST_PROCESS_BIN } from './constants';
6+
7+
type CreateNodesOptions = {
8+
tsconfig?: string;
9+
listProcessBin?: string;
10+
killProcessBin?: string;
11+
verbose?: boolean;
12+
};
13+
14+
export const createNodes: CreateNodes = [
15+
'**/project.json',
16+
(
17+
projectConfigurationFile: string,
18+
opts: undefined | unknown,
19+
context: CreateNodesContext,
20+
) => {
21+
const root = dirname(projectConfigurationFile);
22+
23+
if (root !== '.') {
24+
return {};
25+
}
26+
27+
const {
28+
tsconfig = TOOLS_TSCONFIG_PATH,
29+
listProcessBin = LIST_PROCESS_BIN,
30+
killProcessBin = KILL_PROCESS_BIN,
31+
verbose = false,
32+
} = (opts ?? {}) as CreateNodesOptions;
33+
34+
return {
35+
projects: {
36+
[root]: {
37+
targets: {
38+
'clean-npmrc': {
39+
command: `tsx --tsconfig={args.tsconfig} tools/src/debug/bin/clean-npmrc.ts ${objectToCliArgs(
40+
{
41+
verbose: '{args.verbose}',
42+
userconfig: '{args.userconfig}',
43+
entryMatch: '{args.entryMatch}',
44+
},
45+
).join(' ')}`,
46+
options: {
47+
tsconfig,
48+
verbose,
49+
},
50+
},
51+
'list-process': {
52+
command: `tsx --tsconfig={args.tsconfig} ${listProcessBin} ${objectToCliArgs(
53+
{
54+
verbose: '{args.verbose}',
55+
slice: '{args.slice}',
56+
pid: '{args.pid}',
57+
commandMatch: '{args.commandMatch}',
58+
},
59+
).join(' ')}`,
60+
options: {
61+
tsconfig,
62+
slice: 9,
63+
},
64+
},
65+
'kill-process': {
66+
command: `tsx --tsconfig={args.tsconfig} ${killProcessBin} ${objectToCliArgs(
67+
{
68+
verbose: '{args.verbose}',
69+
force: '{args.force}',
70+
pid: '{args.pid}',
71+
commandMatch: '{args.commandMatch}',
72+
},
73+
).join(' ')}`,
74+
options: {
75+
tsconfig,
76+
},
77+
},
78+
},
79+
},
80+
},
81+
};
82+
},
83+
];

0 commit comments

Comments
 (0)