@somewhatabstract/x 0.0.1 → 0.1.0
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/.github/dependabot.yml +28 -0
- package/.github/workflows/codeql-analysis.yml +29 -29
- package/.github/workflows/dependabot-pr-approval.yml +36 -0
- package/.github/workflows/nodejs.yml +84 -86
- package/.github/workflows/release.yml +4 -7
- package/.vscode/settings.json +19 -0
- package/CHANGELOG.md +23 -0
- package/CONTRIBUTING.md +3 -3
- package/README.md +132 -1
- package/biome.json +39 -0
- package/dist/x.mjs +278 -3
- package/package.json +14 -4
- package/src/__tests__/build-environment.test.ts +285 -0
- package/src/__tests__/discover-packages.test.ts +196 -0
- package/src/__tests__/errors.test.ts +59 -0
- package/src/__tests__/execute-script.test.ts +1042 -0
- package/src/__tests__/find-matching-bins.test.ts +506 -0
- package/src/__tests__/find-workspace-root.test.ts +73 -0
- package/src/__tests__/is-node-executable.test.ts +125 -0
- package/src/__tests__/resolve-bin-path.test.ts +344 -0
- package/src/__tests__/x-impl.test.ts +306 -7
- package/src/__tests__/x.test.ts +236 -0
- package/src/bin/x.ts +55 -1
- package/src/build-environment.ts +98 -0
- package/src/discover-packages.ts +35 -0
- package/src/errors.ts +10 -0
- package/src/execute-script.ts +56 -0
- package/src/find-matching-bins.ts +72 -0
- package/src/find-workspace-root.ts +24 -0
- package/src/is-node-executable.ts +16 -0
- package/src/resolve-bin-path.ts +48 -0
- package/src/x-impl.ts +95 -4
- package/tsconfig-types.json +2 -4
- package/tsconfig.json +5 -13
- package/tsdown.config.ts +1 -1
- package/vitest.config.ts +1 -0
package/src/x-impl.ts
CHANGED
|
@@ -1,5 +1,96 @@
|
|
|
1
|
+
import {discoverPackages} from "./discover-packages";
|
|
2
|
+
import {HandledError} from "./errors";
|
|
3
|
+
import {executeScript} from "./execute-script";
|
|
4
|
+
import {findMatchingBins} from "./find-matching-bins";
|
|
5
|
+
import {findWorkspaceRoot} from "./find-workspace-root";
|
|
1
6
|
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
export interface XOptions {
|
|
8
|
+
dryRun?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface XResult {
|
|
12
|
+
exitCode: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Main implementation of the x command.
|
|
17
|
+
* Finds and executes a bin script from any package in the workspace.
|
|
18
|
+
*
|
|
19
|
+
* @param scriptName - Name of the bin script to execute
|
|
20
|
+
* @param args - Arguments to pass to the script
|
|
21
|
+
* @param options - Additional options
|
|
22
|
+
* @returns Result object with exit code
|
|
23
|
+
*/
|
|
24
|
+
export async function xImpl(
|
|
25
|
+
scriptName: string,
|
|
26
|
+
args: string[] = [],
|
|
27
|
+
options: XOptions = {},
|
|
28
|
+
): Promise<XResult> {
|
|
29
|
+
try {
|
|
30
|
+
if (!scriptName || !scriptName.trim()) {
|
|
31
|
+
throw new HandledError("Script name cannot be empty");
|
|
32
|
+
}
|
|
33
|
+
if (scriptName.includes("/") || scriptName.includes("\\")) {
|
|
34
|
+
throw new HandledError(
|
|
35
|
+
"Script name cannot contain path separators",
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Find workspace root
|
|
40
|
+
const workspaceRoot = await findWorkspaceRoot();
|
|
41
|
+
|
|
42
|
+
// Discover all packages
|
|
43
|
+
const packages = await discoverPackages(workspaceRoot);
|
|
44
|
+
|
|
45
|
+
if (packages.length === 0) {
|
|
46
|
+
throw new HandledError(
|
|
47
|
+
"No packages found in workspace. Is this a valid monorepo?",
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Find matching bins
|
|
52
|
+
const matchingBins = await findMatchingBins(packages, scriptName);
|
|
53
|
+
|
|
54
|
+
if (matchingBins.length === 0) {
|
|
55
|
+
throw new HandledError(
|
|
56
|
+
`No bin script named "${scriptName}" found in any workspace package.`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (matchingBins.length > 1) {
|
|
61
|
+
console.error(
|
|
62
|
+
`Multiple packages provide bin "${scriptName}". Please be more specific.`,
|
|
63
|
+
);
|
|
64
|
+
console.error("\nMatching packages:");
|
|
65
|
+
matchingBins.forEach((bin) => {
|
|
66
|
+
console.error(` - ${bin.packageName} (${bin.packagePath})`);
|
|
67
|
+
});
|
|
68
|
+
throw new HandledError(
|
|
69
|
+
`Ambiguous bin name "${scriptName}". Found ${matchingBins.length} matches.`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const bin = matchingBins[0];
|
|
74
|
+
|
|
75
|
+
// Dry run mode - just show what would be executed
|
|
76
|
+
if (options.dryRun) {
|
|
77
|
+
console.log(
|
|
78
|
+
`Would execute: ${bin.binName} from ${bin.packageName}`,
|
|
79
|
+
);
|
|
80
|
+
console.log(` Binary: ${bin.binPath}`);
|
|
81
|
+
console.log(` Arguments: ${args.join(" ")}`);
|
|
82
|
+
return {exitCode: 0};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Execute the script
|
|
86
|
+
const exitCode = await executeScript(bin, args, workspaceRoot);
|
|
87
|
+
|
|
88
|
+
return {exitCode};
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof HandledError) {
|
|
91
|
+
console.error(`Error: ${error.message}`);
|
|
92
|
+
return {exitCode: 1};
|
|
93
|
+
}
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
package/tsconfig-types.json
CHANGED
package/tsconfig.json
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "esnext",
|
|
4
|
-
"lib": [
|
|
5
|
-
"es2023"
|
|
6
|
-
],
|
|
4
|
+
"lib": ["es2023"],
|
|
7
5
|
"moduleDetection": "force",
|
|
8
6
|
"module": "preserve",
|
|
9
7
|
"moduleResolution": "bundler",
|
|
10
8
|
"resolveJsonModule": true,
|
|
11
|
-
"types": [
|
|
12
|
-
|
|
13
|
-
],
|
|
14
|
-
"typeRoots": [
|
|
15
|
-
"./node_modules/@types"
|
|
16
|
-
],
|
|
9
|
+
"types": ["node"],
|
|
10
|
+
"typeRoots": ["./node_modules/@types"],
|
|
17
11
|
"strict": true,
|
|
18
12
|
"noUnusedLocals": true,
|
|
19
13
|
"declaration": true,
|
|
@@ -23,7 +17,5 @@
|
|
|
23
17
|
"verbatimModuleSyntax": true,
|
|
24
18
|
"skipLibCheck": true
|
|
25
19
|
},
|
|
26
|
-
"include": [
|
|
27
|
-
|
|
28
|
-
]
|
|
29
|
-
}
|
|
20
|
+
"include": ["src"]
|
|
21
|
+
}
|
package/tsdown.config.ts
CHANGED