@smoothbricks/cli 0.3.2 → 0.3.3
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/monorepo/lockfile.d.ts.map +1 -1
- package/dist/monorepo/lockfile.js +40 -6
- package/dist/monorepo/packed-manifest.d.ts.map +1 -1
- package/dist/monorepo/packed-manifest.js +36 -3
- package/package.json +2 -2
- package/src/monorepo/lockfile.ts +41 -6
- package/src/monorepo/packed-manifest.ts +36 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../src/monorepo/lockfile.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../../src/monorepo/lockfile.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,8BAA8B;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAWD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,8BAAmC,GAAG,MAAM,CAkD1G;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiChE"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
1
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { escapeRegex, getWorkspacePackages } from '../lib/workspace.js';
|
|
@@ -20,6 +21,12 @@ export function syncBunLockfileVersions(root, options = {}) {
|
|
|
20
21
|
let lockfile = readFileSync(lockfilePath, 'utf8');
|
|
21
22
|
let updated = 0;
|
|
22
23
|
for (const pkg of packages) {
|
|
24
|
+
// If the package.json version is a prerelease (e.g. 0.2.2-next.0) it may
|
|
25
|
+
// never have been published. Use the latest stable git tag version so
|
|
26
|
+
// that `bun pm pack` writes an installable dependency range for consumers.
|
|
27
|
+
const targetVersion = pkg.version.includes('-')
|
|
28
|
+
? (latestStableTagVersion(root, pkg.projectName) ?? pkg.version)
|
|
29
|
+
: pkg.version;
|
|
23
30
|
const relativePath = pkg.path.replaceAll('\\', '/');
|
|
24
31
|
const escaped = escapeRegex(relativePath);
|
|
25
32
|
const pattern = new RegExp(`("${escaped}":\\s*\\{[^}]*"version":\\s*")([^"]+)(")`);
|
|
@@ -31,15 +38,16 @@ export function syncBunLockfileVersions(root, options = {}) {
|
|
|
31
38
|
continue;
|
|
32
39
|
}
|
|
33
40
|
const lockVersion = match[2];
|
|
34
|
-
if (lockVersion ===
|
|
41
|
+
if (lockVersion === targetVersion) {
|
|
35
42
|
if (log) {
|
|
36
|
-
console.log(`ok: ${relativePath} = ${
|
|
43
|
+
console.log(`ok: ${relativePath} = ${targetVersion}`);
|
|
37
44
|
}
|
|
38
45
|
continue;
|
|
39
46
|
}
|
|
40
|
-
lockfile = lockfile.replace(pattern, `$1${
|
|
47
|
+
lockfile = lockfile.replace(pattern, `$1${targetVersion}$3`);
|
|
41
48
|
if (log) {
|
|
42
|
-
|
|
49
|
+
const suffix = targetVersion !== pkg.version ? ` (latest stable tag; package.json has ${pkg.version})` : '';
|
|
50
|
+
console.log(`fix: ${relativePath}: ${lockVersion} -> ${targetVersion}${suffix}`);
|
|
43
51
|
}
|
|
44
52
|
updated++;
|
|
45
53
|
}
|
|
@@ -61,6 +69,9 @@ export function validateBunLockfileVersions(root) {
|
|
|
61
69
|
const lockfile = readFileSync(lockfilePath, 'utf8');
|
|
62
70
|
let failures = 0;
|
|
63
71
|
for (const pkg of packages) {
|
|
72
|
+
const targetVersion = pkg.version.includes('-')
|
|
73
|
+
? (latestStableTagVersion(root, pkg.projectName) ?? pkg.version)
|
|
74
|
+
: pkg.version;
|
|
64
75
|
const relativePath = pkg.path.replaceAll('\\', '/');
|
|
65
76
|
const escaped = escapeRegex(relativePath);
|
|
66
77
|
const pattern = new RegExp(`("${escaped}":\\s*\\{[^}]*"version":\\s*")([^"]+)(")`);
|
|
@@ -71,8 +82,8 @@ export function validateBunLockfileVersions(root) {
|
|
|
71
82
|
continue;
|
|
72
83
|
}
|
|
73
84
|
const lockVersion = match[2];
|
|
74
|
-
if (lockVersion !==
|
|
75
|
-
console.error(`${relativePath}: bun.lock workspace version must be ${
|
|
85
|
+
if (lockVersion !== targetVersion) {
|
|
86
|
+
console.error(`${relativePath}: bun.lock workspace version must be ${targetVersion}, got ${lockVersion}`);
|
|
76
87
|
failures++;
|
|
77
88
|
}
|
|
78
89
|
}
|
|
@@ -81,3 +92,26 @@ export function validateBunLockfileVersions(root) {
|
|
|
81
92
|
}
|
|
82
93
|
return failures;
|
|
83
94
|
}
|
|
95
|
+
function latestStableTagVersion(root, projectName) {
|
|
96
|
+
try {
|
|
97
|
+
const output = execSync(`git tag --list '${projectName}@*' --sort=-v:refname`, {
|
|
98
|
+
cwd: root,
|
|
99
|
+
encoding: 'utf8',
|
|
100
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
101
|
+
});
|
|
102
|
+
const prefix = `${projectName}@`;
|
|
103
|
+
for (const line of output.split('\n')) {
|
|
104
|
+
const tag = line.trim();
|
|
105
|
+
if (!tag.startsWith(prefix))
|
|
106
|
+
continue;
|
|
107
|
+
const version = tag.slice(prefix.length);
|
|
108
|
+
if (version && !version.includes('-')) {
|
|
109
|
+
return version;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packed-manifest.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"packed-manifest.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAUlC;AAED,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,WAAW,EAC1B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,MAAM,EAAE,CA8CV"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
1
2
|
import { $ } from 'bun';
|
|
2
3
|
import { isRecord, recordProperty } from '../lib/json.js';
|
|
3
4
|
import { decode } from '../lib/run.js';
|
|
@@ -14,7 +15,9 @@ export async function readPackedPackageJson(root, tarball, packageName) {
|
|
|
14
15
|
return parsed;
|
|
15
16
|
}
|
|
16
17
|
export function validatePackedWorkspaceDependencies(root, sourcePackage, packedPackage) {
|
|
17
|
-
const
|
|
18
|
+
const workspacePackages = getWorkspacePackages(root);
|
|
19
|
+
const workspaceVersions = new Map(workspacePackages.map((pkg) => [pkg.name, pkg.version]));
|
|
20
|
+
const projectNameByPackage = new Map(workspacePackages.map((pkg) => [pkg.name, pkg.projectName]));
|
|
18
21
|
const failures = [];
|
|
19
22
|
for (const field of workspaceDependencyFields) {
|
|
20
23
|
const sourceDependencies = recordProperty(sourcePackage.json, field);
|
|
@@ -39,8 +42,15 @@ export function validatePackedWorkspaceDependencies(root, sourcePackage, packedP
|
|
|
39
42
|
if (sourceRange !== 'workspace:*') {
|
|
40
43
|
failures.push(`${sourcePackage.path}: source ${field}.${name} must use workspace:*`);
|
|
41
44
|
}
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
// When the workspace dep is at a prerelease version that was never
|
|
46
|
+
// published, the lockfile sync rewrites it to the latest stable tag
|
|
47
|
+
// version. Accept that version as valid.
|
|
48
|
+
const projectName = projectNameByPackage.get(name);
|
|
49
|
+
const expectedVersion = workspaceVersion.includes('-') && projectName
|
|
50
|
+
? (latestStableTagVersion(root, projectName) ?? workspaceVersion)
|
|
51
|
+
: workspaceVersion;
|
|
52
|
+
if (packedRange !== expectedVersion) {
|
|
53
|
+
failures.push(`${sourcePackage.path}: packed ${field}.${name} must be ${expectedVersion}, got ${formatRange(packedRange)}`);
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
}
|
|
@@ -49,3 +59,26 @@ export function validatePackedWorkspaceDependencies(root, sourcePackage, packedP
|
|
|
49
59
|
function formatRange(value) {
|
|
50
60
|
return typeof value === 'string' ? value : '<missing>';
|
|
51
61
|
}
|
|
62
|
+
function latestStableTagVersion(root, projectName) {
|
|
63
|
+
try {
|
|
64
|
+
const output = execSync(`git tag --list '${projectName}@*' --sort=-v:refname`, {
|
|
65
|
+
cwd: root,
|
|
66
|
+
encoding: 'utf8',
|
|
67
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
68
|
+
});
|
|
69
|
+
const prefix = `${projectName}@`;
|
|
70
|
+
for (const line of output.split('\n')) {
|
|
71
|
+
const tag = line.trim();
|
|
72
|
+
if (!tag.startsWith(prefix))
|
|
73
|
+
continue;
|
|
74
|
+
const version = tag.slice(prefix.length);
|
|
75
|
+
if (version && !version.includes('-')) {
|
|
76
|
+
return version;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smoothbricks/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SmoothBricks monorepo automation CLI",
|
|
6
6
|
"bin": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
48
|
-
"@smoothbricks/nx-plugin": "0.2.2
|
|
48
|
+
"@smoothbricks/nx-plugin": "0.2.2",
|
|
49
49
|
"@smoothbricks/validation": "0.1.1",
|
|
50
50
|
"commander": "^14.0.3",
|
|
51
51
|
"publint": "^0.3.18",
|
package/src/monorepo/lockfile.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
1
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { escapeRegex, getWorkspacePackages } from '../lib/workspace.js';
|
|
@@ -25,6 +26,13 @@ export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVe
|
|
|
25
26
|
let lockfile = readFileSync(lockfilePath, 'utf8');
|
|
26
27
|
let updated = 0;
|
|
27
28
|
for (const pkg of packages) {
|
|
29
|
+
// If the package.json version is a prerelease (e.g. 0.2.2-next.0) it may
|
|
30
|
+
// never have been published. Use the latest stable git tag version so
|
|
31
|
+
// that `bun pm pack` writes an installable dependency range for consumers.
|
|
32
|
+
const targetVersion = pkg.version.includes('-')
|
|
33
|
+
? (latestStableTagVersion(root, pkg.projectName) ?? pkg.version)
|
|
34
|
+
: pkg.version;
|
|
35
|
+
|
|
28
36
|
const relativePath = pkg.path.replaceAll('\\', '/');
|
|
29
37
|
const escaped = escapeRegex(relativePath);
|
|
30
38
|
const pattern = new RegExp(`("${escaped}":\\s*\\{[^}]*"version":\\s*")([^"]+)(")`);
|
|
@@ -36,15 +44,16 @@ export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVe
|
|
|
36
44
|
continue;
|
|
37
45
|
}
|
|
38
46
|
const lockVersion = match[2];
|
|
39
|
-
if (lockVersion ===
|
|
47
|
+
if (lockVersion === targetVersion) {
|
|
40
48
|
if (log) {
|
|
41
|
-
console.log(`ok: ${relativePath} = ${
|
|
49
|
+
console.log(`ok: ${relativePath} = ${targetVersion}`);
|
|
42
50
|
}
|
|
43
51
|
continue;
|
|
44
52
|
}
|
|
45
|
-
lockfile = lockfile.replace(pattern, `$1${
|
|
53
|
+
lockfile = lockfile.replace(pattern, `$1${targetVersion}$3`);
|
|
46
54
|
if (log) {
|
|
47
|
-
|
|
55
|
+
const suffix = targetVersion !== pkg.version ? ` (latest stable tag; package.json has ${pkg.version})` : '';
|
|
56
|
+
console.log(`fix: ${relativePath}: ${lockVersion} -> ${targetVersion}${suffix}`);
|
|
48
57
|
}
|
|
49
58
|
updated++;
|
|
50
59
|
}
|
|
@@ -69,6 +78,10 @@ export function validateBunLockfileVersions(root: string): number {
|
|
|
69
78
|
const lockfile = readFileSync(lockfilePath, 'utf8');
|
|
70
79
|
let failures = 0;
|
|
71
80
|
for (const pkg of packages) {
|
|
81
|
+
const targetVersion = pkg.version.includes('-')
|
|
82
|
+
? (latestStableTagVersion(root, pkg.projectName) ?? pkg.version)
|
|
83
|
+
: pkg.version;
|
|
84
|
+
|
|
72
85
|
const relativePath = pkg.path.replaceAll('\\', '/');
|
|
73
86
|
const escaped = escapeRegex(relativePath);
|
|
74
87
|
const pattern = new RegExp(`("${escaped}":\\s*\\{[^}]*"version":\\s*")([^"]+)(")`);
|
|
@@ -79,8 +92,8 @@ export function validateBunLockfileVersions(root: string): number {
|
|
|
79
92
|
continue;
|
|
80
93
|
}
|
|
81
94
|
const lockVersion = match[2];
|
|
82
|
-
if (lockVersion !==
|
|
83
|
-
console.error(`${relativePath}: bun.lock workspace version must be ${
|
|
95
|
+
if (lockVersion !== targetVersion) {
|
|
96
|
+
console.error(`${relativePath}: bun.lock workspace version must be ${targetVersion}, got ${lockVersion}`);
|
|
84
97
|
failures++;
|
|
85
98
|
}
|
|
86
99
|
}
|
|
@@ -89,3 +102,25 @@ export function validateBunLockfileVersions(root: string): number {
|
|
|
89
102
|
}
|
|
90
103
|
return failures;
|
|
91
104
|
}
|
|
105
|
+
|
|
106
|
+
function latestStableTagVersion(root: string, projectName: string): string | null {
|
|
107
|
+
try {
|
|
108
|
+
const output = execSync(`git tag --list '${projectName}@*' --sort=-v:refname`, {
|
|
109
|
+
cwd: root,
|
|
110
|
+
encoding: 'utf8',
|
|
111
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
112
|
+
});
|
|
113
|
+
const prefix = `${projectName}@`;
|
|
114
|
+
for (const line of output.split('\n')) {
|
|
115
|
+
const tag = line.trim();
|
|
116
|
+
if (!tag.startsWith(prefix)) continue;
|
|
117
|
+
const version = tag.slice(prefix.length);
|
|
118
|
+
if (version && !version.includes('-')) {
|
|
119
|
+
return version;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
1
2
|
import { $ } from 'bun';
|
|
2
3
|
import { isRecord, recordProperty } from '../lib/json.js';
|
|
3
4
|
import { decode } from '../lib/run.js';
|
|
@@ -25,7 +26,9 @@ export function validatePackedWorkspaceDependencies(
|
|
|
25
26
|
sourcePackage: PackageInfo,
|
|
26
27
|
packedPackage: Record<string, unknown>,
|
|
27
28
|
): string[] {
|
|
28
|
-
const
|
|
29
|
+
const workspacePackages = getWorkspacePackages(root);
|
|
30
|
+
const workspaceVersions = new Map(workspacePackages.map((pkg) => [pkg.name, pkg.version]));
|
|
31
|
+
const projectNameByPackage = new Map(workspacePackages.map((pkg) => [pkg.name, pkg.projectName]));
|
|
29
32
|
const failures: string[] = [];
|
|
30
33
|
for (const field of workspaceDependencyFields) {
|
|
31
34
|
const sourceDependencies = recordProperty(sourcePackage.json, field);
|
|
@@ -52,9 +55,17 @@ export function validatePackedWorkspaceDependencies(
|
|
|
52
55
|
if (sourceRange !== 'workspace:*') {
|
|
53
56
|
failures.push(`${sourcePackage.path}: source ${field}.${name} must use workspace:*`);
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
// When the workspace dep is at a prerelease version that was never
|
|
59
|
+
// published, the lockfile sync rewrites it to the latest stable tag
|
|
60
|
+
// version. Accept that version as valid.
|
|
61
|
+
const projectName = projectNameByPackage.get(name);
|
|
62
|
+
const expectedVersion =
|
|
63
|
+
workspaceVersion.includes('-') && projectName
|
|
64
|
+
? (latestStableTagVersion(root, projectName) ?? workspaceVersion)
|
|
65
|
+
: workspaceVersion;
|
|
66
|
+
if (packedRange !== expectedVersion) {
|
|
56
67
|
failures.push(
|
|
57
|
-
`${sourcePackage.path}: packed ${field}.${name} must be ${
|
|
68
|
+
`${sourcePackage.path}: packed ${field}.${name} must be ${expectedVersion}, got ${formatRange(packedRange)}`,
|
|
58
69
|
);
|
|
59
70
|
}
|
|
60
71
|
}
|
|
@@ -65,3 +76,25 @@ export function validatePackedWorkspaceDependencies(
|
|
|
65
76
|
function formatRange(value: unknown): string {
|
|
66
77
|
return typeof value === 'string' ? value : '<missing>';
|
|
67
78
|
}
|
|
79
|
+
|
|
80
|
+
function latestStableTagVersion(root: string, projectName: string): string | null {
|
|
81
|
+
try {
|
|
82
|
+
const output = execSync(`git tag --list '${projectName}@*' --sort=-v:refname`, {
|
|
83
|
+
cwd: root,
|
|
84
|
+
encoding: 'utf8',
|
|
85
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
86
|
+
});
|
|
87
|
+
const prefix = `${projectName}@`;
|
|
88
|
+
for (const line of output.split('\n')) {
|
|
89
|
+
const tag = line.trim();
|
|
90
|
+
if (!tag.startsWith(prefix)) continue;
|
|
91
|
+
const version = tag.slice(prefix.length);
|
|
92
|
+
if (version && !version.includes('-')) {
|
|
93
|
+
return version;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|