@smoothbricks/cli 0.4.0 → 0.4.1
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/dist/lib/run.d.ts +1 -0
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +11 -0
- package/dist/monorepo/nx-sync.d.ts.map +1 -1
- package/dist/monorepo/nx-sync.js +18 -4
- package/dist/monorepo/package-hygiene.d.ts +5 -0
- package/dist/monorepo/package-hygiene.d.ts.map +1 -1
- package/dist/monorepo/package-hygiene.js +18 -4
- package/dist/monorepo/packed-package.js +5 -4
- package/dist/monorepo/packs/index.js +6 -2
- package/package.json +1 -1
- package/src/lib/run.ts +13 -0
- package/src/monorepo/nx-sync.ts +18 -4
- package/src/monorepo/package-hygiene.test.ts +54 -1
- package/src/monorepo/package-hygiene.ts +34 -4
- package/src/monorepo/packed-package.ts +5 -5
- package/src/monorepo/packs/index.ts +6 -2
package/dist/lib/run.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare function runResult(command: string, args: string[], cwd: string,
|
|
|
6
6
|
stdout: string;
|
|
7
7
|
stderr: string;
|
|
8
8
|
}>;
|
|
9
|
+
export declare function printCommandOutput(stdout: string, stderr: string): void;
|
|
9
10
|
export declare function findRepoRoot(): Promise<string>;
|
|
10
11
|
export declare function decode(bytes: Uint8Array): string;
|
|
11
12
|
//# sourceMappingURL=run.d.ts.map
|
package/dist/lib/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/lib/run.ts"],"names":[],"mappings":"AAMA,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnH;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,KAAK,UAAQ,EACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/D;AAuCD,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAMpD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEhD"}
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/lib/run.ts"],"names":[],"mappings":"AAMA,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnH;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,KAAK,UAAQ,EACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAOvE;AAuCD,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAMpD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEhD"}
|
package/dist/lib/run.js
CHANGED
|
@@ -49,6 +49,14 @@ export async function runResult(command, args, cwd, env) {
|
|
|
49
49
|
stderr: decode(result.stderr),
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
export function printCommandOutput(stdout, stderr) {
|
|
53
|
+
if (stdout.length > 0) {
|
|
54
|
+
console.log(trimTrailingNewline(stdout));
|
|
55
|
+
}
|
|
56
|
+
if (stderr.length > 0) {
|
|
57
|
+
console.error(trimTrailingNewline(stderr));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
52
60
|
function mergeEnv(env) {
|
|
53
61
|
const merged = {};
|
|
54
62
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -94,3 +102,6 @@ export async function findRepoRoot() {
|
|
|
94
102
|
export function decode(bytes) {
|
|
95
103
|
return new TextDecoder().decode(bytes);
|
|
96
104
|
}
|
|
105
|
+
function trimTrailingNewline(value) {
|
|
106
|
+
return value.endsWith('\n') ? value.slice(0, -1) : value;
|
|
107
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nx-sync.d.ts","sourceRoot":"","sources":["../../src/monorepo/nx-sync.ts"],"names":[],"mappings":"AAEA,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"nx-sync.d.ts","sourceRoot":"","sources":["../../src/monorepo/nx-sync.ts"],"names":[],"mappings":"AAEA,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAW5E;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAWnF"}
|
package/dist/monorepo/nx-sync.js
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
-
import { runStatus } from '../lib/run.js';
|
|
1
|
+
import { printCommandOutput, runResult, runStatus } from '../lib/run.js';
|
|
2
2
|
export async function fixNxSync(root, verbose = false) {
|
|
3
|
-
const
|
|
3
|
+
const result = verbose
|
|
4
|
+
? { exitCode: await runStatus('nx', ['sync'], root, false), stdout: '', stderr: '' }
|
|
5
|
+
: await runResult('nx', ['sync'], root);
|
|
6
|
+
const status = result.exitCode;
|
|
4
7
|
if (status !== 0) {
|
|
8
|
+
if (!verbose) {
|
|
9
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
10
|
+
}
|
|
5
11
|
throw new Error(`nx sync failed with exit code ${status}`);
|
|
6
12
|
}
|
|
7
13
|
}
|
|
8
14
|
export async function validateNxSync(root, verbose = false) {
|
|
9
|
-
const
|
|
10
|
-
|
|
15
|
+
const result = verbose
|
|
16
|
+
? { exitCode: await runStatus('nx', ['sync:check'], root, false), stdout: '', stderr: '' }
|
|
17
|
+
: await runResult('nx', ['sync:check'], root);
|
|
18
|
+
if (result.exitCode === 0) {
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
if (!verbose) {
|
|
22
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
23
|
+
}
|
|
24
|
+
return 1;
|
|
11
25
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export interface PackageHygieneShell {
|
|
2
2
|
run(command: string, args: string[], cwd: string): Promise<void>;
|
|
3
|
+
runResult?(command: string, args: string[], cwd: string): Promise<{
|
|
4
|
+
exitCode: number;
|
|
5
|
+
stdout: string;
|
|
6
|
+
stderr: string;
|
|
7
|
+
}>;
|
|
3
8
|
runStatus(command: string, args: string[], cwd: string, quiet?: boolean): Promise<number>;
|
|
4
9
|
}
|
|
5
10
|
export declare function fixPackageHygiene(root: string, verboseOrShell?: boolean | PackageHygieneShell, maybeShell?: PackageHygieneShell): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-hygiene.d.ts","sourceRoot":"","sources":["../../src/monorepo/package-hygiene.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3F;AAID,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,OAAO,GAAG,mBAA2B,EACrD,UAAU,GAAE,mBAAkC,GAC7C,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"package-hygiene.d.ts","sourceRoot":"","sources":["../../src/monorepo/package-hygiene.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,SAAS,CAAC,CACR,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC,CAAC;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC3F;AAID,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,OAAO,GAAG,mBAA2B,EACrD,UAAU,GAAE,mBAAkC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,OAAO,GAAG,mBAA2B,EACrD,UAAU,GAAE,mBAAkC,GAC7C,OAAO,CAAC,MAAM,CAAC,CAajB"}
|
|
@@ -1,20 +1,34 @@
|
|
|
1
|
-
import { run, runStatus } from '../lib/run.js';
|
|
2
|
-
const defaultShell = { run, runStatus };
|
|
1
|
+
import { printCommandOutput, run, runResult, runStatus } from '../lib/run.js';
|
|
2
|
+
const defaultShell = { run, runResult, runStatus };
|
|
3
3
|
export async function fixPackageHygiene(root, verboseOrShell = false, maybeShell = defaultShell) {
|
|
4
4
|
const verbose = typeof verboseOrShell === 'boolean' ? verboseOrShell : false;
|
|
5
5
|
const shell = typeof verboseOrShell === 'boolean' ? maybeShell : verboseOrShell;
|
|
6
|
-
const
|
|
6
|
+
const result = await runPackageHygieneCommand(shell, 'sherif', ['-f', '--select', 'highest'], root, verbose);
|
|
7
|
+
const status = result.exitCode;
|
|
7
8
|
if (status !== 0) {
|
|
9
|
+
if (!verbose) {
|
|
10
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
11
|
+
}
|
|
8
12
|
throw new Error(`sherif -f --select highest failed with exit code ${status}`);
|
|
9
13
|
}
|
|
10
14
|
}
|
|
11
15
|
export async function validatePackageHygiene(root, verboseOrShell = false, maybeShell = defaultShell) {
|
|
12
16
|
const verbose = typeof verboseOrShell === 'boolean' ? verboseOrShell : false;
|
|
13
17
|
const shell = typeof verboseOrShell === 'boolean' ? maybeShell : verboseOrShell;
|
|
14
|
-
const
|
|
18
|
+
const result = await runPackageHygieneCommand(shell, 'sherif', ['--fail-on-warnings'], root, verbose);
|
|
19
|
+
const status = result.exitCode;
|
|
15
20
|
if (status !== 0) {
|
|
21
|
+
if (!verbose) {
|
|
22
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
23
|
+
}
|
|
16
24
|
console.error('sherif package hygiene validation failed');
|
|
17
25
|
return 1;
|
|
18
26
|
}
|
|
19
27
|
return 0;
|
|
20
28
|
}
|
|
29
|
+
async function runPackageHygieneCommand(shell, command, args, root, verbose) {
|
|
30
|
+
if (!verbose && shell.runResult) {
|
|
31
|
+
return shell.runResult(command, args, root);
|
|
32
|
+
}
|
|
33
|
+
return { exitCode: await shell.runStatus(command, args, root, !verbose), stdout: '', stderr: '' };
|
|
34
|
+
}
|
|
@@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { publint } from 'publint';
|
|
4
4
|
import { formatMessage } from 'publint/utils';
|
|
5
5
|
import { isRecord } from '../lib/json.js';
|
|
6
|
-
import {
|
|
6
|
+
import { printCommandOutput, runResult } from '../lib/run.js';
|
|
7
7
|
import { listPublicPackages } from '../lib/workspace.js';
|
|
8
8
|
import { readPackedPackageJson, validatePackedWorkspaceDependencies } from './packed-manifest.js';
|
|
9
9
|
export async function validatePackedPublicPackages(root) {
|
|
@@ -116,9 +116,10 @@ async function packPackage(root, pkg) {
|
|
|
116
116
|
const tarballName = `.smoo-${process.pid}-${Date.now()}.tgz`;
|
|
117
117
|
const tarballPath = join(root, tarballName);
|
|
118
118
|
try {
|
|
119
|
-
const
|
|
120
|
-
if (
|
|
121
|
-
|
|
119
|
+
const result = await runResult('bun', ['pm', 'pack', '--filename', tarballName, '--ignore-scripts', '--quiet'], packageDir);
|
|
120
|
+
if (result.exitCode !== 0) {
|
|
121
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
122
|
+
throw new Error(`bun pm pack failed with exit code ${result.exitCode}`);
|
|
122
123
|
}
|
|
123
124
|
const bytes = new Uint8Array(readFileSync(tarballPath));
|
|
124
125
|
return { path: tarballPath, arrayBuffer: bytes.slice().buffer };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { chmodSync, existsSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { runStatus } from '../../lib/run.js';
|
|
3
|
+
import { printCommandOutput, runResult, runStatus } from '../../lib/run.js';
|
|
4
4
|
import { readProjectTargets } from '../../nx/index.js';
|
|
5
5
|
import { syncBunLockfileVersions, validateBunLockfileVersions } from '../lockfile.js';
|
|
6
6
|
import { validateManagedFiles } from '../managed-files.js';
|
|
@@ -221,10 +221,14 @@ async function runBuild(ctx, options = {}) {
|
|
|
221
221
|
if (options.verbose) {
|
|
222
222
|
printCheckHeading('build', true);
|
|
223
223
|
}
|
|
224
|
-
const
|
|
224
|
+
const result = options.verbose
|
|
225
|
+
? { exitCode: await runStatus('nx', ['run-many', '-t', 'build'], ctx.root, false), stdout: '', stderr: '' }
|
|
226
|
+
: await runResult('nx', ['run-many', '-t', 'build'], ctx.root);
|
|
227
|
+
const status = result.exitCode;
|
|
225
228
|
if (status !== 0) {
|
|
226
229
|
if (!options.verbose) {
|
|
227
230
|
printCheckHeading('build', true);
|
|
231
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
228
232
|
}
|
|
229
233
|
console.error('nx run-many -t build failed');
|
|
230
234
|
printCheckStatus('build', 1);
|
package/package.json
CHANGED
package/src/lib/run.ts
CHANGED
|
@@ -70,6 +70,15 @@ export async function runResult(
|
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
export function printCommandOutput(stdout: string, stderr: string): void {
|
|
74
|
+
if (stdout.length > 0) {
|
|
75
|
+
console.log(trimTrailingNewline(stdout));
|
|
76
|
+
}
|
|
77
|
+
if (stderr.length > 0) {
|
|
78
|
+
console.error(trimTrailingNewline(stderr));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
function mergeEnv(env: Record<string, string>): Record<string, string> {
|
|
74
83
|
const merged: Record<string, string> = {};
|
|
75
84
|
for (const [key, value] of Object.entries(process.env)) {
|
|
@@ -118,3 +127,7 @@ export async function findRepoRoot(): Promise<string> {
|
|
|
118
127
|
export function decode(bytes: Uint8Array): string {
|
|
119
128
|
return new TextDecoder().decode(bytes);
|
|
120
129
|
}
|
|
130
|
+
|
|
131
|
+
function trimTrailingNewline(value: string): string {
|
|
132
|
+
return value.endsWith('\n') ? value.slice(0, -1) : value;
|
|
133
|
+
}
|
package/src/monorepo/nx-sync.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
import { runStatus } from '../lib/run.js';
|
|
1
|
+
import { printCommandOutput, runResult, runStatus } from '../lib/run.js';
|
|
2
2
|
|
|
3
3
|
export async function fixNxSync(root: string, verbose = false): Promise<void> {
|
|
4
|
-
const
|
|
4
|
+
const result = verbose
|
|
5
|
+
? { exitCode: await runStatus('nx', ['sync'], root, false), stdout: '', stderr: '' }
|
|
6
|
+
: await runResult('nx', ['sync'], root);
|
|
7
|
+
const status = result.exitCode;
|
|
5
8
|
if (status !== 0) {
|
|
9
|
+
if (!verbose) {
|
|
10
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
11
|
+
}
|
|
6
12
|
throw new Error(`nx sync failed with exit code ${status}`);
|
|
7
13
|
}
|
|
8
14
|
}
|
|
9
15
|
|
|
10
16
|
export async function validateNxSync(root: string, verbose = false): Promise<number> {
|
|
11
|
-
const
|
|
12
|
-
|
|
17
|
+
const result = verbose
|
|
18
|
+
? { exitCode: await runStatus('nx', ['sync:check'], root, false), stdout: '', stderr: '' }
|
|
19
|
+
: await runResult('nx', ['sync:check'], root);
|
|
20
|
+
if (result.exitCode === 0) {
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
if (!verbose) {
|
|
24
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
25
|
+
}
|
|
26
|
+
return 1;
|
|
13
27
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test';
|
|
1
|
+
import { afterEach, describe, expect, it, spyOn } from 'bun:test';
|
|
2
2
|
import { fixPackageHygiene, type PackageHygieneShell, validatePackageHygiene } from './package-hygiene.js';
|
|
3
3
|
|
|
4
4
|
describe('package hygiene', () => {
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
console.log = originalConsoleLog;
|
|
7
|
+
console.error = originalConsoleError;
|
|
8
|
+
});
|
|
9
|
+
|
|
5
10
|
it('runs sherif in autofix mode and selects highest dependency versions', async () => {
|
|
6
11
|
const shell = new RecordingShell();
|
|
7
12
|
|
|
@@ -17,8 +22,39 @@ describe('package hygiene', () => {
|
|
|
17
22
|
|
|
18
23
|
expect(shell.statuses).toEqual([{ command: 'sherif', args: ['--fail-on-warnings'], cwd: '/repo' }]);
|
|
19
24
|
});
|
|
25
|
+
|
|
26
|
+
it('prints captured sherif output when quiet validation fails', async () => {
|
|
27
|
+
const shell = new FailingResultShell('sherif stdout', 'sherif stderr');
|
|
28
|
+
const logs = captureConsoleLogs();
|
|
29
|
+
const errors = captureConsoleErrors();
|
|
30
|
+
|
|
31
|
+
const failures = await validatePackageHygiene('/repo', shell);
|
|
32
|
+
|
|
33
|
+
expect(failures).toBe(1);
|
|
34
|
+
expect(logs).toEqual(['sherif stdout']);
|
|
35
|
+
expect(errors).toEqual(['sherif stderr', 'sherif package hygiene validation failed']);
|
|
36
|
+
});
|
|
20
37
|
});
|
|
21
38
|
|
|
39
|
+
const originalConsoleLog = console.log;
|
|
40
|
+
const originalConsoleError = console.error;
|
|
41
|
+
|
|
42
|
+
function captureConsoleLogs(): string[] {
|
|
43
|
+
const logs: string[] = [];
|
|
44
|
+
spyOn(console, 'log').mockImplementation((...args: unknown[]) => {
|
|
45
|
+
logs.push(args.join(' '));
|
|
46
|
+
});
|
|
47
|
+
return logs;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function captureConsoleErrors(): string[] {
|
|
51
|
+
const errors: string[] = [];
|
|
52
|
+
spyOn(console, 'error').mockImplementation((...args: unknown[]) => {
|
|
53
|
+
errors.push(args.join(' '));
|
|
54
|
+
});
|
|
55
|
+
return errors;
|
|
56
|
+
}
|
|
57
|
+
|
|
22
58
|
class RecordingShell implements PackageHygieneShell {
|
|
23
59
|
readonly runs: { command: string; args: string[]; cwd: string }[] = [];
|
|
24
60
|
readonly statuses: { command: string; args: string[]; cwd: string }[] = [];
|
|
@@ -32,3 +68,20 @@ class RecordingShell implements PackageHygieneShell {
|
|
|
32
68
|
return 0;
|
|
33
69
|
}
|
|
34
70
|
}
|
|
71
|
+
|
|
72
|
+
class FailingResultShell implements PackageHygieneShell {
|
|
73
|
+
constructor(
|
|
74
|
+
private readonly stdout: string,
|
|
75
|
+
private readonly stderr: string,
|
|
76
|
+
) {}
|
|
77
|
+
|
|
78
|
+
async run(): Promise<void> {}
|
|
79
|
+
|
|
80
|
+
async runResult(): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
81
|
+
return { exitCode: 1, stdout: this.stdout, stderr: this.stderr };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async runStatus(): Promise<number> {
|
|
85
|
+
return 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { run, runStatus } from '../lib/run.js';
|
|
1
|
+
import { printCommandOutput, run, runResult, runStatus } from '../lib/run.js';
|
|
2
2
|
|
|
3
3
|
export interface PackageHygieneShell {
|
|
4
4
|
run(command: string, args: string[], cwd: string): Promise<void>;
|
|
5
|
+
runResult?(
|
|
6
|
+
command: string,
|
|
7
|
+
args: string[],
|
|
8
|
+
cwd: string,
|
|
9
|
+
): Promise<{
|
|
10
|
+
exitCode: number;
|
|
11
|
+
stdout: string;
|
|
12
|
+
stderr: string;
|
|
13
|
+
}>;
|
|
5
14
|
runStatus(command: string, args: string[], cwd: string, quiet?: boolean): Promise<number>;
|
|
6
15
|
}
|
|
7
16
|
|
|
8
|
-
const defaultShell: PackageHygieneShell = { run, runStatus };
|
|
17
|
+
const defaultShell: PackageHygieneShell = { run, runResult, runStatus };
|
|
9
18
|
|
|
10
19
|
export async function fixPackageHygiene(
|
|
11
20
|
root: string,
|
|
@@ -14,8 +23,12 @@ export async function fixPackageHygiene(
|
|
|
14
23
|
): Promise<void> {
|
|
15
24
|
const verbose = typeof verboseOrShell === 'boolean' ? verboseOrShell : false;
|
|
16
25
|
const shell = typeof verboseOrShell === 'boolean' ? maybeShell : verboseOrShell;
|
|
17
|
-
const
|
|
26
|
+
const result = await runPackageHygieneCommand(shell, 'sherif', ['-f', '--select', 'highest'], root, verbose);
|
|
27
|
+
const status = result.exitCode;
|
|
18
28
|
if (status !== 0) {
|
|
29
|
+
if (!verbose) {
|
|
30
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
31
|
+
}
|
|
19
32
|
throw new Error(`sherif -f --select highest failed with exit code ${status}`);
|
|
20
33
|
}
|
|
21
34
|
}
|
|
@@ -27,10 +40,27 @@ export async function validatePackageHygiene(
|
|
|
27
40
|
): Promise<number> {
|
|
28
41
|
const verbose = typeof verboseOrShell === 'boolean' ? verboseOrShell : false;
|
|
29
42
|
const shell = typeof verboseOrShell === 'boolean' ? maybeShell : verboseOrShell;
|
|
30
|
-
const
|
|
43
|
+
const result = await runPackageHygieneCommand(shell, 'sherif', ['--fail-on-warnings'], root, verbose);
|
|
44
|
+
const status = result.exitCode;
|
|
31
45
|
if (status !== 0) {
|
|
46
|
+
if (!verbose) {
|
|
47
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
48
|
+
}
|
|
32
49
|
console.error('sherif package hygiene validation failed');
|
|
33
50
|
return 1;
|
|
34
51
|
}
|
|
35
52
|
return 0;
|
|
36
53
|
}
|
|
54
|
+
|
|
55
|
+
async function runPackageHygieneCommand(
|
|
56
|
+
shell: PackageHygieneShell,
|
|
57
|
+
command: string,
|
|
58
|
+
args: string[],
|
|
59
|
+
root: string,
|
|
60
|
+
verbose: boolean,
|
|
61
|
+
): Promise<{ exitCode: number; stdout: string; stderr: string }> {
|
|
62
|
+
if (!verbose && shell.runResult) {
|
|
63
|
+
return shell.runResult(command, args, root);
|
|
64
|
+
}
|
|
65
|
+
return { exitCode: await shell.runStatus(command, args, root, !verbose), stdout: '', stderr: '' };
|
|
66
|
+
}
|
|
@@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { publint } from 'publint';
|
|
4
4
|
import { formatMessage } from 'publint/utils';
|
|
5
5
|
import { isRecord } from '../lib/json.js';
|
|
6
|
-
import {
|
|
6
|
+
import { printCommandOutput, runResult } from '../lib/run.js';
|
|
7
7
|
import type { PackageInfo } from '../lib/workspace.js';
|
|
8
8
|
import { listPublicPackages } from '../lib/workspace.js';
|
|
9
9
|
import { readPackedPackageJson, validatePackedWorkspaceDependencies } from './packed-manifest.js';
|
|
@@ -142,14 +142,14 @@ async function packPackage(root: string, pkg: PackageInfo): Promise<{ path: stri
|
|
|
142
142
|
const tarballName = `.smoo-${process.pid}-${Date.now()}.tgz`;
|
|
143
143
|
const tarballPath = join(root, tarballName);
|
|
144
144
|
try {
|
|
145
|
-
const
|
|
145
|
+
const result = await runResult(
|
|
146
146
|
'bun',
|
|
147
147
|
['pm', 'pack', '--filename', tarballName, '--ignore-scripts', '--quiet'],
|
|
148
148
|
packageDir,
|
|
149
|
-
true,
|
|
150
149
|
);
|
|
151
|
-
if (
|
|
152
|
-
|
|
150
|
+
if (result.exitCode !== 0) {
|
|
151
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
152
|
+
throw new Error(`bun pm pack failed with exit code ${result.exitCode}`);
|
|
153
153
|
}
|
|
154
154
|
const bytes = new Uint8Array(readFileSync(tarballPath));
|
|
155
155
|
return { path: tarballPath, arrayBuffer: bytes.slice().buffer };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { chmodSync, existsSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { runStatus } from '../../lib/run.js';
|
|
3
|
+
import { printCommandOutput, runResult, runStatus } from '../../lib/run.js';
|
|
4
4
|
import { readProjectTargets } from '../../nx/index.js';
|
|
5
5
|
import { syncBunLockfileVersions, validateBunLockfileVersions } from '../lockfile.js';
|
|
6
6
|
import { validateManagedFiles } from '../managed-files.js';
|
|
@@ -315,10 +315,14 @@ async function runBuild(ctx: MonorepoContext, options: ValidatePackOptions = {})
|
|
|
315
315
|
if (options.verbose) {
|
|
316
316
|
printCheckHeading('build', true);
|
|
317
317
|
}
|
|
318
|
-
const
|
|
318
|
+
const result = options.verbose
|
|
319
|
+
? { exitCode: await runStatus('nx', ['run-many', '-t', 'build'], ctx.root, false), stdout: '', stderr: '' }
|
|
320
|
+
: await runResult('nx', ['run-many', '-t', 'build'], ctx.root);
|
|
321
|
+
const status = result.exitCode;
|
|
319
322
|
if (status !== 0) {
|
|
320
323
|
if (!options.verbose) {
|
|
321
324
|
printCheckHeading('build', true);
|
|
325
|
+
printCommandOutput(result.stdout, result.stderr);
|
|
322
326
|
}
|
|
323
327
|
console.error('nx run-many -t build failed');
|
|
324
328
|
printCheckStatus('build', 1);
|