@fuman/build 0.0.13 → 0.0.14
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/cli/commands/_utils.d.ts +0 -1
- package/cli/commands/_utils.js +2 -3
- package/cli/commands/bump-version.d.ts +2 -4
- package/cli/commands/bump-version.js +2 -6
- package/cli/commands/find-changed-packages.d.ts +0 -2
- package/cli/commands/find-changed-packages.js +0 -2
- package/cli/commands/gen-changelog.d.ts +0 -2
- package/cli/commands/gen-changelog.js +0 -2
- package/cli/commands/lint/config.d.ts +30 -0
- package/cli/commands/lint/index.d.ts +8 -0
- package/cli/commands/lint/index.js +47 -0
- package/cli/commands/lint/validate-workspace-deps.d.ts +41 -0
- package/cli/commands/lint/validate-workspace-deps.js +94 -0
- package/cli/commands/release.d.ts +2 -2
- package/cli/commands/release.js +25 -16
- package/cli/index.d.ts +1 -1
- package/config.d.ts +3 -0
- package/fuman-build.js +2 -2
- package/git/utils.d.ts +3 -1
- package/git/utils.js +10 -2
- package/index.js +1 -1
- package/misc/_config.d.ts +1 -1
- package/misc/_config.js +4 -3
- package/package-json/types.d.ts +10 -1
- package/package-json/types.js +1 -0
- package/package.json +5 -5
- package/versioning/bump-version.d.ts +3 -1
- package/versioning/bump-version.js +28 -5
- package/versioning/types.d.ts +15 -0
- package/cli/commands/validate-workspace-deps.d.ts +0 -50
- package/cli/commands/validate-workspace-deps.js +0 -87
package/cli/commands/_utils.d.ts
CHANGED
package/cli/commands/_utils.js
CHANGED
|
@@ -3,12 +3,11 @@ import { loadBuildConfig } from "../../misc/_config.js";
|
|
|
3
3
|
async function loadConfig(params) {
|
|
4
4
|
const {
|
|
5
5
|
workspaceRoot,
|
|
6
|
-
configPath = "build.config.js",
|
|
7
6
|
require: require2 = true
|
|
8
7
|
} = params;
|
|
9
|
-
const config = await loadBuildConfig(workspaceRoot
|
|
8
|
+
const config = await loadBuildConfig(workspaceRoot);
|
|
10
9
|
if (!config && require2) {
|
|
11
|
-
throw new Error(`Config not found
|
|
10
|
+
throw new Error(`Config not found at ${workspaceRoot}`);
|
|
12
11
|
}
|
|
13
12
|
return config ?? null;
|
|
14
13
|
}
|
|
@@ -3,15 +3,13 @@ import { bc } from './_utils.js';
|
|
|
3
3
|
export declare function formatBumpVersionResult(result: BumpVersionResult, withReleaseType: boolean): string;
|
|
4
4
|
export declare const bumpVersionCli: bc.Command<{
|
|
5
5
|
root: string | undefined;
|
|
6
|
-
|
|
7
|
-
type: "auto" | "major" | "minor" | "patch";
|
|
6
|
+
type: "major" | "minor" | "patch" | "auto";
|
|
8
7
|
since: string | undefined;
|
|
9
8
|
dryRun: boolean | undefined;
|
|
10
9
|
quiet: boolean | undefined;
|
|
11
10
|
}, {
|
|
12
11
|
root: string | undefined;
|
|
13
|
-
|
|
14
|
-
type: "auto" | "major" | "minor" | "patch";
|
|
12
|
+
type: "major" | "minor" | "patch" | "auto";
|
|
15
13
|
since: string | undefined;
|
|
16
14
|
dryRun: boolean | undefined;
|
|
17
15
|
quiet: boolean | undefined;
|
|
@@ -13,8 +13,6 @@ function formatBumpVersionResult(result, withReleaseType) {
|
|
|
13
13
|
lines.push(` has new features: ${result.hasFeatures}`);
|
|
14
14
|
lines.push("");
|
|
15
15
|
}
|
|
16
|
-
lines.push(`next version: ${result.nextVersion}`);
|
|
17
|
-
lines.push("");
|
|
18
16
|
lines.push("list of changed packages:");
|
|
19
17
|
for (const { package: pkg, because, prevVersion } of result.changedPackages) {
|
|
20
18
|
let versionStr = prevVersion;
|
|
@@ -30,7 +28,6 @@ const bumpVersionCli = bc.command({
|
|
|
30
28
|
desc: "bump the version of changed packages",
|
|
31
29
|
options: {
|
|
32
30
|
root: bc.string().desc("path to the root of the workspace (default: process.cwd())"),
|
|
33
|
-
config: bc.string().desc("path to the build.config.js file"),
|
|
34
31
|
type: bc.string().desc("override type of release (major, minor, patch) (default: auto-detect)").enum("major", "minor", "patch", "auto").default("auto"),
|
|
35
32
|
since: bc.string().desc("starting point for the changelog (default: latest tag)"),
|
|
36
33
|
dryRun: bc.boolean("dry-run").desc("whether to only print the detected changes without actually modifying anything"),
|
|
@@ -42,7 +39,6 @@ const bumpVersionCli = bc.command({
|
|
|
42
39
|
const workspace = await collectPackageJsons(root);
|
|
43
40
|
const config = await loadConfig({
|
|
44
41
|
workspaceRoot: root,
|
|
45
|
-
configPath: args.config,
|
|
46
42
|
require: false
|
|
47
43
|
});
|
|
48
44
|
const since = args.since ?? await getLatestTag(root);
|
|
@@ -58,12 +54,12 @@ const bumpVersionCli = bc.command({
|
|
|
58
54
|
dryRun: args.dryRun
|
|
59
55
|
});
|
|
60
56
|
if (args.quiet) {
|
|
61
|
-
console.log(result.
|
|
57
|
+
console.log(JSON.stringify(result.nextVersions));
|
|
62
58
|
} else {
|
|
63
59
|
console.log(formatBumpVersionResult(result, releaseType == null));
|
|
64
60
|
}
|
|
65
61
|
if (isRunningInGithubActions()) {
|
|
66
|
-
writeGithubActionsOutput("
|
|
62
|
+
writeGithubActionsOutput("versions", JSON.stringify(result.nextVersions));
|
|
67
63
|
writeGithubActionsOutput("hasBreakingChanges", String(result.hasBreakingChanges));
|
|
68
64
|
writeGithubActionsOutput("hasFeatures", String(result.hasFeatures));
|
|
69
65
|
writeGithubActionsOutput("changedPackages", result.changedPackages.map((it) => it.package.json.name).join(","));
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { bc } from './_utils.js';
|
|
2
2
|
export declare const findChangedPackagesCli: bc.Command<{
|
|
3
3
|
root: string | undefined;
|
|
4
|
-
config: string | undefined;
|
|
5
4
|
since: string | undefined;
|
|
6
5
|
until: string | undefined;
|
|
7
6
|
}, {
|
|
8
7
|
root: string | undefined;
|
|
9
|
-
config: string | undefined;
|
|
10
8
|
since: string | undefined;
|
|
11
9
|
until: string | undefined;
|
|
12
10
|
}>;
|
|
@@ -9,7 +9,6 @@ const findChangedPackagesCli = bc.command({
|
|
|
9
9
|
desc: "find changed packages between two commits, and output a comma-separated list of package names",
|
|
10
10
|
options: {
|
|
11
11
|
root: bc.string().desc("path to the root of the workspace (default: process.cwd())"),
|
|
12
|
-
config: bc.string("config").desc("path to the build.config.js file"),
|
|
13
12
|
since: bc.string().desc("starting point for the changelog (default: latest tag)"),
|
|
14
13
|
until: bc.string().desc("ending point for the changelog (default: HEAD)")
|
|
15
14
|
},
|
|
@@ -17,7 +16,6 @@ const findChangedPackagesCli = bc.command({
|
|
|
17
16
|
const root = args.root ?? process.cwd();
|
|
18
17
|
const config = await loadConfig({
|
|
19
18
|
workspaceRoot: root,
|
|
20
|
-
configPath: args.config,
|
|
21
19
|
require: false
|
|
22
20
|
});
|
|
23
21
|
const since = args.since ?? await getLatestTag(root);
|
|
@@ -2,11 +2,9 @@ import { bc } from './_utils.js';
|
|
|
2
2
|
export declare const generateChangelogCli: bc.Command<{
|
|
3
3
|
only: string | undefined;
|
|
4
4
|
root: string | undefined;
|
|
5
|
-
config: string | undefined;
|
|
6
5
|
since: string | undefined;
|
|
7
6
|
}, {
|
|
8
7
|
only: string | undefined;
|
|
9
8
|
root: string | undefined;
|
|
10
|
-
config: string | undefined;
|
|
11
9
|
since: string | undefined;
|
|
12
10
|
}>;
|
|
@@ -11,14 +11,12 @@ const generateChangelogCli = bc.command({
|
|
|
11
11
|
options: {
|
|
12
12
|
only: bc.string().desc("comma-separated list of packages to include"),
|
|
13
13
|
root: bc.string().desc("path to the root of the workspace (default: process.cwd())"),
|
|
14
|
-
config: bc.string("config").desc("path to the build.config.js file"),
|
|
15
14
|
since: bc.string().desc("starting point for the changelog (default: latest tag)")
|
|
16
15
|
},
|
|
17
16
|
handler: async (args) => {
|
|
18
17
|
const root = args.root ?? process.cwd();
|
|
19
18
|
const config = await loadConfig({
|
|
20
19
|
workspaceRoot: root,
|
|
21
|
-
configPath: args.config,
|
|
22
20
|
require: false
|
|
23
21
|
});
|
|
24
22
|
let workspacePackages = await collectPackageJsons(root, false);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { WorkspacePackage } from '../../../package-json/collect-package-jsons.js';
|
|
2
|
+
export interface LintConfig {
|
|
3
|
+
/**
|
|
4
|
+
* whether to also validate the root package.json
|
|
5
|
+
*
|
|
6
|
+
* @default false
|
|
7
|
+
*/
|
|
8
|
+
includeRoot?: boolean;
|
|
9
|
+
/** validation of external dependencies */
|
|
10
|
+
externalDependencies?: {
|
|
11
|
+
/** @default true */
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* whether to skip validating peer dependencies
|
|
15
|
+
*
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
skipPeerDependencies?: boolean;
|
|
19
|
+
shouldSkip?: (ctx: {
|
|
20
|
+
/** package currently being validated */
|
|
21
|
+
package: WorkspacePackage;
|
|
22
|
+
/** name of the dependency */
|
|
23
|
+
dependency: string;
|
|
24
|
+
/** version of the dependency */
|
|
25
|
+
version: string;
|
|
26
|
+
/** field in which the dependency is declared */
|
|
27
|
+
field: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies';
|
|
28
|
+
}) => boolean;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { loadConfig } from "../_utils.js";
|
|
3
|
+
import { validateWorkspaceDeps } from "./validate-workspace-deps.js";
|
|
4
|
+
import * as bc from "@drizzle-team/brocli";
|
|
5
|
+
const INTERNAL_MESSAGES = {
|
|
6
|
+
not_workspace_proto: "internal dependencies must be linked with workspace: protocol",
|
|
7
|
+
standalone_dep: "non-standalone packages cannot depend on standalone packages with workspace: protocol",
|
|
8
|
+
not_workspace_dep: "workspace: protocol is used to link to a package not found in the workspace"
|
|
9
|
+
};
|
|
10
|
+
const lintCli = bc.command({
|
|
11
|
+
name: "lint",
|
|
12
|
+
desc: "check the workspace for any issues",
|
|
13
|
+
options: {
|
|
14
|
+
workspace: bc.string().desc("path to the workspace root (default: cwd)"),
|
|
15
|
+
noErrorCode: bc.boolean("no-error-code").desc("whether to always exit with a zero code").default(false)
|
|
16
|
+
},
|
|
17
|
+
handler: async (args) => {
|
|
18
|
+
const workspaceRoot = args.workspace ?? process.cwd();
|
|
19
|
+
const config = (await loadConfig({ workspaceRoot }))?.lint;
|
|
20
|
+
const errors = await validateWorkspaceDeps({
|
|
21
|
+
workspaceRoot,
|
|
22
|
+
config
|
|
23
|
+
});
|
|
24
|
+
if (errors.length > 0) {
|
|
25
|
+
const externalErrors = errors.filter((it) => it.type === "external");
|
|
26
|
+
const internalErrors = errors.filter((it) => it.type === "internal");
|
|
27
|
+
if (externalErrors.length > 0) {
|
|
28
|
+
console.error("⚠️ Found external dependencies mismatch:");
|
|
29
|
+
for (const error of externalErrors) {
|
|
30
|
+
console.error(` - at ${error.package}: ${error.at} has ${error.dependency}@${error.version}, but ${error.otherPackage} has @${error.otherVersion}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (internalErrors.length > 0) {
|
|
34
|
+
console.error("⚠️ Found issues with internal dependencies:");
|
|
35
|
+
for (const error of internalErrors) {
|
|
36
|
+
console.error(` - at ${error.package}, dependency ${error.dependency}: ${INTERNAL_MESSAGES[error.subtype]}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!args.noErrorCode) {
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
export {
|
|
46
|
+
lintCli
|
|
47
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { WorkspacePackage } from '../../../package-json/collect-package-jsons.js';
|
|
2
|
+
import { LintConfig } from './config.js';
|
|
3
|
+
/** information about a mismatch between a package and its dependencies */
|
|
4
|
+
export interface ExternalDepsError {
|
|
5
|
+
type: 'external';
|
|
6
|
+
/** package name where the mismatch occurred */
|
|
7
|
+
package: string;
|
|
8
|
+
/** name of the mismatched dependency */
|
|
9
|
+
dependency: string;
|
|
10
|
+
/** version of the mismatched dependency */
|
|
11
|
+
version: string;
|
|
12
|
+
/** type of dependency (`dependencies`, `devDependencies`, etc) */
|
|
13
|
+
at: string;
|
|
14
|
+
/** package name where the dependency was originally declared */
|
|
15
|
+
otherPackage: string;
|
|
16
|
+
/** original version of the dependency */
|
|
17
|
+
otherVersion: string;
|
|
18
|
+
}
|
|
19
|
+
export interface InternalDepsError {
|
|
20
|
+
type: 'internal';
|
|
21
|
+
/** package name where the mismatch occurred */
|
|
22
|
+
package: string;
|
|
23
|
+
/** name of the mismatched dependency */
|
|
24
|
+
dependency: string;
|
|
25
|
+
/**
|
|
26
|
+
* sub-type of the error
|
|
27
|
+
* - not_workspace_proto: internal dependencies must be linked with workspace: protocol
|
|
28
|
+
* - standalone_dep: non-standalone packages cannot depend on standalone packages
|
|
29
|
+
* - not_workspace_dep: `workspace:` protocol is used to link to a package not found in the workspace
|
|
30
|
+
*/
|
|
31
|
+
subtype: 'not_workspace_proto' | 'standalone_dep' | 'not_workspace_dep';
|
|
32
|
+
}
|
|
33
|
+
export type WorkspaceDepsError = ExternalDepsError | InternalDepsError;
|
|
34
|
+
/**
|
|
35
|
+
* validate the external dependencies of a workspace
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateWorkspaceDeps(params: {
|
|
38
|
+
workspaceRoot: string | URL;
|
|
39
|
+
packages?: WorkspacePackage[];
|
|
40
|
+
config?: LintConfig;
|
|
41
|
+
}): Promise<WorkspaceDepsError[]>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { valid, satisfies, validRange, subset } from "semver";
|
|
2
|
+
import { collectPackageJsons } from "../../../package-json/collect-package-jsons.js";
|
|
3
|
+
async function validateWorkspaceDeps(params) {
|
|
4
|
+
const {
|
|
5
|
+
workspaceRoot,
|
|
6
|
+
config: {
|
|
7
|
+
includeRoot,
|
|
8
|
+
externalDependencies: {
|
|
9
|
+
enabled: externalDependenciesEnabled = true,
|
|
10
|
+
skipPeerDependencies: externalDependenciesSkipPeerDependencies = false,
|
|
11
|
+
shouldSkip: externalDependenciesShouldSkip
|
|
12
|
+
} = {}
|
|
13
|
+
} = {}
|
|
14
|
+
} = params;
|
|
15
|
+
const packages = params.packages ?? await collectPackageJsons(workspaceRoot, includeRoot);
|
|
16
|
+
const packagesMap = new Map(packages.map((pj) => [pj.json.name, pj]));
|
|
17
|
+
const versions = {};
|
|
18
|
+
const errors = [];
|
|
19
|
+
for (const pkg of packages) {
|
|
20
|
+
const pj = pkg.json;
|
|
21
|
+
if (pj.name === void 0) {
|
|
22
|
+
throw new Error("package.json without name is not supported");
|
|
23
|
+
}
|
|
24
|
+
for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
25
|
+
const deps = pj[field];
|
|
26
|
+
if (!deps) continue;
|
|
27
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
28
|
+
if (packagesMap.has(name)) {
|
|
29
|
+
const otherPkg = packagesMap.get(name);
|
|
30
|
+
const otherPkgStandalone = Boolean(otherPkg?.json.fuman?.standalone);
|
|
31
|
+
if (!otherPkgStandalone && !version.startsWith("workspace:")) {
|
|
32
|
+
errors.push({
|
|
33
|
+
type: "internal",
|
|
34
|
+
package: pj.name,
|
|
35
|
+
dependency: name,
|
|
36
|
+
subtype: "not_workspace_proto"
|
|
37
|
+
});
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (!pj.fuman?.standalone && otherPkgStandalone && version.startsWith("workspace:")) {
|
|
41
|
+
errors.push({
|
|
42
|
+
type: "internal",
|
|
43
|
+
package: pj.name,
|
|
44
|
+
dependency: name,
|
|
45
|
+
subtype: "standalone_dep"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (version.startsWith("workspace:")) {
|
|
51
|
+
errors.push({
|
|
52
|
+
type: "internal",
|
|
53
|
+
package: pj.name,
|
|
54
|
+
dependency: name,
|
|
55
|
+
subtype: "not_workspace_dep"
|
|
56
|
+
});
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (!externalDependenciesEnabled) continue;
|
|
60
|
+
if (field === "peerDependencies" && externalDependenciesSkipPeerDependencies) continue;
|
|
61
|
+
if (externalDependenciesShouldSkip?.({ package: pkg, dependency: name, version, field })) continue;
|
|
62
|
+
if (versions[name] === void 0) {
|
|
63
|
+
versions[name] = {};
|
|
64
|
+
}
|
|
65
|
+
for (const [pkgName, pkgDepVersions] of Object.entries(versions[name])) {
|
|
66
|
+
let ok = true;
|
|
67
|
+
if (pkgDepVersions.match(/^(?:https?:\/\/|catalog:)/)) {
|
|
68
|
+
ok = version === pkgDepVersions;
|
|
69
|
+
} else if (valid(version) != null) {
|
|
70
|
+
ok = satisfies(version, pkgDepVersions);
|
|
71
|
+
} else if (validRange(version) != null) {
|
|
72
|
+
ok = subset(pkgDepVersions, version);
|
|
73
|
+
}
|
|
74
|
+
if (!ok) {
|
|
75
|
+
errors.push({
|
|
76
|
+
type: "external",
|
|
77
|
+
package: pj.name,
|
|
78
|
+
dependency: name,
|
|
79
|
+
version,
|
|
80
|
+
at: field,
|
|
81
|
+
otherPackage: pkgName,
|
|
82
|
+
otherVersion: pkgDepVersions
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
versions[name][pj.name] = version;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return errors;
|
|
91
|
+
}
|
|
92
|
+
export {
|
|
93
|
+
validateWorkspaceDeps
|
|
94
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { bc } from './_utils.js';
|
|
2
2
|
export declare const releaseCli: bc.Command<{
|
|
3
|
-
kind: "
|
|
3
|
+
kind: "major" | "minor" | "patch" | "auto";
|
|
4
4
|
withGithubRelease: boolean;
|
|
5
5
|
gitExtraOrigins: string | undefined;
|
|
6
6
|
githubToken: string | undefined;
|
|
@@ -18,7 +18,7 @@ export declare const releaseCli: bc.Command<{
|
|
|
18
18
|
npmRegistry: string | undefined;
|
|
19
19
|
dryRun: boolean | undefined;
|
|
20
20
|
}, {
|
|
21
|
-
kind: "
|
|
21
|
+
kind: "major" | "minor" | "patch" | "auto";
|
|
22
22
|
withGithubRelease: boolean;
|
|
23
23
|
gitExtraOrigins: string | undefined;
|
|
24
24
|
githubToken: string | undefined;
|
package/cli/commands/release.js
CHANGED
|
@@ -42,7 +42,6 @@ const releaseCli = bc.command({
|
|
|
42
42
|
const root = process.cwd();
|
|
43
43
|
const config = await loadConfig({
|
|
44
44
|
workspaceRoot: root,
|
|
45
|
-
configPath: "build.config.js",
|
|
46
45
|
require: false
|
|
47
46
|
});
|
|
48
47
|
const workspaceWithRoot = await collectPackageJsons(root, true);
|
|
@@ -79,28 +78,38 @@ const releaseCli = bc.command({
|
|
|
79
78
|
} else {
|
|
80
79
|
changedPackages = workspace;
|
|
81
80
|
}
|
|
81
|
+
const taggingSchema = config?.versioning?.taggingSchema ?? "semver";
|
|
82
82
|
let tagName;
|
|
83
|
-
if (
|
|
83
|
+
if (taggingSchema === "semver") {
|
|
84
84
|
const versions = sort(workspace.map((pkg) => asNonNull(pkg.json.version)));
|
|
85
85
|
tagName = `v${versions[versions.length - 1]}`;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (!args.dryRun) {
|
|
93
|
-
process.exit(1);
|
|
86
|
+
if (await gitTagExists(tagName, root)) {
|
|
87
|
+
console.log(`❗ tag ${tagName} already exists. did the previous release complete successfully?`);
|
|
88
|
+
console.log("❗ if so, please verify versions in package.json and try again");
|
|
89
|
+
if (!args.dryRun) {
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
94
92
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
93
|
+
if (!changedPackages.some((pkg) => pkg.json.version === tagName.replace(/^v/, ""))) {
|
|
94
|
+
console.log(`❗ tag ${tagName} does not match any of the package versions. did the previous release complete successfully?`);
|
|
95
|
+
console.log("❗ if so, please verify versions in package.json, tag the commit release and try again");
|
|
96
|
+
if (!args.dryRun) {
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
101
99
|
}
|
|
100
|
+
} else if (taggingSchema === "date") {
|
|
101
|
+
const date = /* @__PURE__ */ new Date();
|
|
102
|
+
const tagNamePrefix = `v${date.getFullYear()}.${(date.getMonth() + 1).toString().padStart(2, "0")}.${date.getDate().toString().padStart(2, "0")}`;
|
|
103
|
+
let currentLetter = "a";
|
|
104
|
+
do {
|
|
105
|
+
tagName = `${tagNamePrefix}${currentLetter}`;
|
|
106
|
+
currentLetter = String.fromCharCode(currentLetter.charCodeAt(0) + 1);
|
|
107
|
+
} while (await gitTagExists(tagName, root));
|
|
108
|
+
} else {
|
|
109
|
+
throw new Error(`Unknown tagging schema: ${taggingSchema}`);
|
|
102
110
|
}
|
|
103
111
|
console.log("");
|
|
112
|
+
console.log("🚀 next tag:", tagName);
|
|
104
113
|
console.log("📝 generating changelog...");
|
|
105
114
|
const changelog = prevTag != null ? await generateChangelog({
|
|
106
115
|
workspace: changedPackages,
|
package/cli/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { buildPackage } from './commands/build.js';
|
|
2
2
|
export { generateDocs } from './commands/docs.js';
|
|
3
3
|
export { generateDepsGraph } from './commands/gen-deps-graph.js';
|
|
4
|
-
export { validateWorkspaceDeps, type WorkspaceDepsError } from './commands/validate-workspace-deps.js';
|
|
4
|
+
export { validateWorkspaceDeps, type WorkspaceDepsError } from './commands/lint/validate-workspace-deps.js';
|
package/config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AnyToNever } from '@fuman/utils';
|
|
2
2
|
import { TypeDocOptions } from 'typedoc';
|
|
3
|
+
import { LintConfig } from './cli/commands/lint/config.js';
|
|
3
4
|
import { JsrConfig } from './jsr/config.js';
|
|
4
5
|
import { PackageJson } from './package-json/types.js';
|
|
5
6
|
import { VersioningOptions } from './versioning/types.js';
|
|
@@ -49,6 +50,8 @@ export interface RootConfigObject {
|
|
|
49
50
|
*/
|
|
50
51
|
excludePackages?: string[];
|
|
51
52
|
}>;
|
|
53
|
+
/** `lint` command configuration */
|
|
54
|
+
lint?: LintConfig;
|
|
52
55
|
}
|
|
53
56
|
/** root configuration (either an object or a function that returns an object) */
|
|
54
57
|
export type RootConfig = RootConfigObject | (() => RootConfigObject);
|
package/fuman-build.js
CHANGED
|
@@ -9,11 +9,11 @@ import { findChangedPackagesCli } from "./cli/commands/find-changed-packages.js"
|
|
|
9
9
|
import { generateChangelogCli } from "./cli/commands/gen-changelog.js";
|
|
10
10
|
import { generateDepsGraphCli } from "./cli/commands/gen-deps-graph.js";
|
|
11
11
|
import { jsrCli } from "./cli/commands/jsr.js";
|
|
12
|
+
import { lintCli } from "./cli/commands/lint/index.js";
|
|
12
13
|
import { publishPackagesCli } from "./cli/commands/publish.js";
|
|
13
14
|
import { releaseCli } from "./cli/commands/release.js";
|
|
14
|
-
import { validateWorkspaceDepsCli } from "./cli/commands/validate-workspace-deps.js";
|
|
15
15
|
await bc.run([
|
|
16
|
-
|
|
16
|
+
lintCli,
|
|
17
17
|
generateDepsGraphCli,
|
|
18
18
|
buildPackageCli,
|
|
19
19
|
jsrCli,
|
package/git/utils.d.ts
CHANGED
|
@@ -70,7 +70,9 @@ export interface CommitInfo {
|
|
|
70
70
|
*/
|
|
71
71
|
export declare function getCommitsBetween(params: {
|
|
72
72
|
/** starting point for the diff */
|
|
73
|
-
since
|
|
73
|
+
since?: string;
|
|
74
|
+
/** only include commits that modified these files */
|
|
75
|
+
files?: string[];
|
|
74
76
|
/**
|
|
75
77
|
* ending point for the diff
|
|
76
78
|
* @default 'HEAD'
|
package/git/utils.js
CHANGED
|
@@ -50,13 +50,21 @@ async function findChangedFiles(params) {
|
|
|
50
50
|
return files;
|
|
51
51
|
}
|
|
52
52
|
async function getCommitsBetween(params) {
|
|
53
|
-
const { since, until = "HEAD", cwd } = params;
|
|
53
|
+
const { since, until = "HEAD", cwd, files } = params;
|
|
54
54
|
const delim = `---${randomUUID()}---`;
|
|
55
|
-
const res = await exec([
|
|
55
|
+
const res = await exec([
|
|
56
|
+
"git",
|
|
57
|
+
"log",
|
|
58
|
+
`--pretty=format:%H %s%n%an%n%ae%n%aI%n%cn%n%ce%n%cI%n%b%n${delim}`,
|
|
59
|
+
since != null ? `${since}..${until}` : until,
|
|
60
|
+
// eslint-disable-next-line ts/strict-boolean-expressions
|
|
61
|
+
...files?.length ? ["--", ...files] : []
|
|
62
|
+
], {
|
|
56
63
|
cwd,
|
|
57
64
|
throwOnError: true
|
|
58
65
|
});
|
|
59
66
|
const lines = res.stdout.trim().split("\n");
|
|
67
|
+
if (lines.length === 1 && lines[0] === "") return [];
|
|
60
68
|
const items = [];
|
|
61
69
|
let current = null;
|
|
62
70
|
for (let i = 0; i < lines.length; i++) {
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { getGithubActionsInput, isRunningInGithubActions, writeGithubActionsOutp
|
|
|
2
2
|
import { buildPackage } from "./cli/commands/build.js";
|
|
3
3
|
import { generateDocs } from "./cli/commands/docs.js";
|
|
4
4
|
import { generateDepsGraph } from "./cli/commands/gen-deps-graph.js";
|
|
5
|
-
import { validateWorkspaceDeps } from "./cli/commands/validate-workspace-deps.js";
|
|
5
|
+
import { validateWorkspaceDeps } from "./cli/commands/lint/validate-workspace-deps.js";
|
|
6
6
|
import { findChangedFiles, getCommitsBetween, getCurrentBranch, getCurrentCommit, getFirstCommit, getLatestTag, gitTagExists, parseConventionalCommit } from "./git/utils.js";
|
|
7
7
|
import { ExecError, exec } from "./misc/exec.js";
|
|
8
8
|
import { normalizeFilePath } from "./misc/path.js";
|
package/misc/_config.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function loadBuildConfig<T>(packageRoot: string
|
|
1
|
+
export declare function loadBuildConfig<T>(packageRoot: string): Promise<T | undefined>;
|
package/misc/_config.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
|
|
2
|
+
const CONFIG_NAME = "build.config.js";
|
|
3
|
+
async function loadBuildConfig(packageRoot) {
|
|
3
4
|
try {
|
|
4
|
-
const mod = (await import(join(packageRoot,
|
|
5
|
+
const mod = (await import(join(packageRoot, CONFIG_NAME))).default;
|
|
5
6
|
if (typeof mod === "function") {
|
|
6
7
|
return mod();
|
|
7
8
|
} else {
|
|
@@ -9,7 +10,7 @@ async function loadBuildConfig(packageRoot, configName = "build.config.js") {
|
|
|
9
10
|
}
|
|
10
11
|
} catch (e) {
|
|
11
12
|
if (!(e instanceof Error && e.code === "ERR_MODULE_NOT_FOUND")) {
|
|
12
|
-
throw new Error(`Could not load ${
|
|
13
|
+
throw new Error(`Could not load ${CONFIG_NAME}`, { cause: e });
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
}
|
package/package-json/types.d.ts
CHANGED
|
@@ -45,12 +45,21 @@ export interface PackageJson {
|
|
|
45
45
|
*/
|
|
46
46
|
distOnlyFields?: Record<string, unknown>;
|
|
47
47
|
/**
|
|
48
|
-
* whether this package has its own versioning scheme
|
|
48
|
+
* whether this package has its own versioning scheme, not managed by @fuman/build
|
|
49
49
|
* (be careful with this option! this might break cross-release semver compatibility)
|
|
50
50
|
*/
|
|
51
51
|
ownVersioning?: boolean;
|
|
52
52
|
/** whether this package should not be published */
|
|
53
53
|
private?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* whether this is a "standalone" package
|
|
56
|
+
*
|
|
57
|
+
* standalone packages have a few differences from normal ones:
|
|
58
|
+
* - (bump-version) each standalone package has independent versioning
|
|
59
|
+
* - (lint) normal packages can't depend on standalone packages
|
|
60
|
+
* - (lint) unlike normal packages, standalone packages are allowed to depend on older versions of workspace packages
|
|
61
|
+
*/
|
|
62
|
+
standalone?: boolean;
|
|
54
63
|
};
|
|
55
64
|
[key: string]: any;
|
|
56
65
|
}
|
package/package-json/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuman/build",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.14",
|
|
5
5
|
"description": "utils for building packages and managing monorepos",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {},
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@drizzle-team/brocli": "^0.10.2",
|
|
10
|
-
"@fuman/fetch": "
|
|
11
|
-
"@fuman/io": "^0.0.
|
|
12
|
-
"@fuman/node": "^0.0.
|
|
13
|
-
"@fuman/utils": "^0.0.
|
|
10
|
+
"@fuman/fetch": "0.0.13",
|
|
11
|
+
"@fuman/io": "^0.0.14",
|
|
12
|
+
"@fuman/node": "^0.0.14",
|
|
13
|
+
"@fuman/utils": "^0.0.14",
|
|
14
14
|
"cross-spawn": "^7.0.5",
|
|
15
15
|
"detect-indent": "^7.0.1",
|
|
16
16
|
"js-yaml": "^4.1.0",
|
|
@@ -17,7 +17,7 @@ export interface BumpVersionResult {
|
|
|
17
17
|
/** max version of all packages */
|
|
18
18
|
maxVersion: string;
|
|
19
19
|
/** next version */
|
|
20
|
-
|
|
20
|
+
nextVersions: Record<string, string>;
|
|
21
21
|
/** changed packages which will be bumped to `nextVersion` */
|
|
22
22
|
changedPackages: BumpVersionPackage[];
|
|
23
23
|
/** detected release type */
|
|
@@ -36,6 +36,8 @@ export interface BumpVersionResult {
|
|
|
36
36
|
export declare function bumpVersion(params: {
|
|
37
37
|
/** packages for which to generate the changelog */
|
|
38
38
|
workspace: WorkspacePackage[];
|
|
39
|
+
/** previous tag */
|
|
40
|
+
prevTag?: string | null;
|
|
39
41
|
/** whether to bump version of all packages, not just changed ones */
|
|
40
42
|
all?: boolean;
|
|
41
43
|
type?: ReleaseType;
|
|
@@ -4,7 +4,7 @@ import process from "node:process";
|
|
|
4
4
|
import { asNonNull } from "@fuman/utils";
|
|
5
5
|
import detectIndent from "detect-indent";
|
|
6
6
|
import { parse, inc, satisfies, gt } from "semver";
|
|
7
|
-
import { getCommitsBetween, parseConventionalCommit } from "../git/utils.js";
|
|
7
|
+
import { getCommitsBetween, parseConventionalCommit, getLatestTag } from "../git/utils.js";
|
|
8
8
|
import { collectVersions, findRootPackage } from "../package-json/utils.js";
|
|
9
9
|
import { findProjectChangedPackages } from "./collect-files.js";
|
|
10
10
|
async function bumpVersion(params) {
|
|
@@ -21,7 +21,7 @@ async function bumpVersion(params) {
|
|
|
21
21
|
for (const pkg of workspaceWithoutRoot) {
|
|
22
22
|
if (pkg.root) continue;
|
|
23
23
|
const version = asNonNull(pkg.json.version);
|
|
24
|
-
if (pkg.json.fuman?.ownVersioning) {
|
|
24
|
+
if (pkg.json.fuman?.ownVersioning || pkg.json.fuman?.standalone) {
|
|
25
25
|
continue;
|
|
26
26
|
}
|
|
27
27
|
if (maxVersion == null || gt(version, maxVersion)) {
|
|
@@ -89,6 +89,9 @@ async function bumpVersion(params) {
|
|
|
89
89
|
if (obj == null) continue;
|
|
90
90
|
if (obj[pkgName] == null || typeof obj[pkgName] !== "string") continue;
|
|
91
91
|
let expandedVersion = obj[pkgName];
|
|
92
|
+
if (!expandedVersion.startsWith("workspace:") && otherPkg.json.fuman?.standalone) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
92
95
|
if (expandedVersion === "workspace:^") expandedVersion = `^${workspaceVersions[pkgName]}`;
|
|
93
96
|
if (expandedVersion === "workspace:*") expandedVersion = workspaceVersions[pkgName];
|
|
94
97
|
if (!satisfies(nextVersion, expandedVersion)) {
|
|
@@ -115,22 +118,42 @@ async function bumpVersion(params) {
|
|
|
115
118
|
if (withRoot) {
|
|
116
119
|
packagesToBump.push(findRootPackage(workspace));
|
|
117
120
|
}
|
|
121
|
+
const nextVersions = {};
|
|
122
|
+
let prevTag = params.prevTag;
|
|
118
123
|
for (const pkg of packagesToBump) {
|
|
119
124
|
if (pkg.json.fuman?.ownVersioning) continue;
|
|
125
|
+
let newVersion = nextVersion;
|
|
126
|
+
if (pkg.json.fuman?.standalone) {
|
|
127
|
+
newVersion = asNonNull(pkg.json.version);
|
|
128
|
+
if (prevTag === void 0) {
|
|
129
|
+
prevTag = await getLatestTag(pkg.path);
|
|
130
|
+
}
|
|
131
|
+
if (prevTag != null) {
|
|
132
|
+
const commits = await getCommitsBetween({
|
|
133
|
+
until: prevTag,
|
|
134
|
+
cwd,
|
|
135
|
+
files: [join(pkg.path, "package.json")]
|
|
136
|
+
});
|
|
137
|
+
if (commits.length > 0) {
|
|
138
|
+
newVersion = asNonNull(inc(newVersion, type));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
120
142
|
if (!dryRun) {
|
|
121
143
|
const pkgJsonPath = join(pkg.path, "package.json");
|
|
122
144
|
const pkgJsonText = await fsp.readFile(pkgJsonPath, "utf8");
|
|
123
145
|
const indent = detectIndent(pkgJsonText).indent || " ";
|
|
124
146
|
const pkgJson = JSON.parse(pkgJsonText);
|
|
125
|
-
pkgJson.version =
|
|
147
|
+
pkgJson.version = newVersion;
|
|
126
148
|
await fsp.writeFile(pkgJsonPath, `${JSON.stringify(pkgJson, null, indent)}
|
|
127
149
|
`);
|
|
128
150
|
}
|
|
129
|
-
pkg.json.version =
|
|
151
|
+
pkg.json.version = newVersion;
|
|
152
|
+
nextVersions[asNonNull(pkg.json.name)] = newVersion;
|
|
130
153
|
}
|
|
131
154
|
return {
|
|
132
155
|
maxVersion,
|
|
133
|
-
|
|
156
|
+
nextVersions,
|
|
134
157
|
changedPackages: result,
|
|
135
158
|
releaseType: type,
|
|
136
159
|
hasBreakingChanges,
|
package/versioning/types.d.ts
CHANGED
|
@@ -12,6 +12,21 @@ export interface ChangelogGeneratorParams {
|
|
|
12
12
|
}
|
|
13
13
|
/** settings for versioning manager */
|
|
14
14
|
export interface VersioningOptions {
|
|
15
|
+
/**
|
|
16
|
+
* schema to use when tagging commits
|
|
17
|
+
* - `semver`: semver-compatible schema (e.g. `v1.2.3`), based on the max. version of the workspace
|
|
18
|
+
* - `date`: date-based schema (e.g. `v2023.01.01`), based on the date of the release
|
|
19
|
+
*
|
|
20
|
+
* unless your monorepo has standalone packages, you should probably use `semver` schema.
|
|
21
|
+
* `date` schema is primarily useful for repos where different packages have separate release cycles,
|
|
22
|
+
* to avoid conflicts when bumping versions.
|
|
23
|
+
*
|
|
24
|
+
* > note: this is **only** used for the `release` command, when tagging commits.
|
|
25
|
+
* > this does **not** affect the versioning of the packages themselves, they always use semver.
|
|
26
|
+
*
|
|
27
|
+
* @default 'semver'
|
|
28
|
+
*/
|
|
29
|
+
taggingSchema?: 'semver' | 'date';
|
|
15
30
|
/**
|
|
16
31
|
* globs of files changes to which to white-list (relative to package root)
|
|
17
32
|
*
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { bc } from './_utils.js';
|
|
2
|
-
/** information about a mismatch between a package and its dependencies */
|
|
3
|
-
export interface WorkspaceDepsError {
|
|
4
|
-
/** package name where the mismatch occurred */
|
|
5
|
-
package: string;
|
|
6
|
-
/** name of the mismatched dependency */
|
|
7
|
-
dependency: string;
|
|
8
|
-
/** version of the mismatched dependency */
|
|
9
|
-
version: string;
|
|
10
|
-
/** type of dependency (`dependencies`, `devDependencies`, etc) */
|
|
11
|
-
at: string;
|
|
12
|
-
/** package name where the dependency was originally declared */
|
|
13
|
-
otherPackage: string;
|
|
14
|
-
/** original version of the dependency */
|
|
15
|
-
otherVersion: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* validate the external dependencies of a workspace
|
|
19
|
-
*/
|
|
20
|
-
export declare function validateWorkspaceDeps(params: {
|
|
21
|
-
/** path to the workspace root */
|
|
22
|
-
workspaceRoot: string | URL;
|
|
23
|
-
/**
|
|
24
|
-
* whether to also validate the root package.json
|
|
25
|
-
*
|
|
26
|
-
* @default true
|
|
27
|
-
*/
|
|
28
|
-
includeRoot?: boolean;
|
|
29
|
-
/**
|
|
30
|
-
* whether to skip validating dependencies of other workspace packages
|
|
31
|
-
*
|
|
32
|
-
* @default true
|
|
33
|
-
*/
|
|
34
|
-
skipWorkspaceDeps?: boolean;
|
|
35
|
-
/** whether to skip validating peer dependencies */
|
|
36
|
-
skipPeerDeps?: boolean;
|
|
37
|
-
}): Promise<WorkspaceDepsError[]>;
|
|
38
|
-
export declare const validateWorkspaceDepsCli: bc.Command<{
|
|
39
|
-
includeRoot: boolean;
|
|
40
|
-
noSkipWorkspaceDeps: boolean | undefined;
|
|
41
|
-
root: string | undefined;
|
|
42
|
-
withErrorCode: boolean | undefined;
|
|
43
|
-
skipPeerDeps: boolean | undefined;
|
|
44
|
-
}, {
|
|
45
|
-
includeRoot: boolean;
|
|
46
|
-
noSkipWorkspaceDeps: boolean | undefined;
|
|
47
|
-
root: string | undefined;
|
|
48
|
-
withErrorCode: boolean | undefined;
|
|
49
|
-
skipPeerDeps: boolean | undefined;
|
|
50
|
-
}>;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import process from "node:process";
|
|
2
|
-
import { satisfies } from "semver";
|
|
3
|
-
import { collectPackageJsons } from "../../package-json/collect-package-jsons.js";
|
|
4
|
-
import * as bc from "@drizzle-team/brocli";
|
|
5
|
-
async function validateWorkspaceDeps(params) {
|
|
6
|
-
const {
|
|
7
|
-
workspaceRoot,
|
|
8
|
-
includeRoot = true,
|
|
9
|
-
skipWorkspaceDeps = true,
|
|
10
|
-
skipPeerDeps = true
|
|
11
|
-
} = params;
|
|
12
|
-
const pjs = await collectPackageJsons(workspaceRoot, includeRoot);
|
|
13
|
-
const workspacePackages = new Set(skipWorkspaceDeps ? pjs.map((pj) => pj.json.name) : []);
|
|
14
|
-
const versions = {};
|
|
15
|
-
const errors = [];
|
|
16
|
-
for (const { json: pj } of pjs) {
|
|
17
|
-
if (pj.name === void 0) {
|
|
18
|
-
throw new Error("package.json without name is not supported");
|
|
19
|
-
}
|
|
20
|
-
for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
|
|
21
|
-
const deps = pj[field];
|
|
22
|
-
if (!deps) continue;
|
|
23
|
-
if (field === "peerDependencies" && skipPeerDeps) continue;
|
|
24
|
-
for (const [name, version] of Object.entries(deps)) {
|
|
25
|
-
if (workspacePackages.has(name)) continue;
|
|
26
|
-
if (version.startsWith("workspace:")) continue;
|
|
27
|
-
if (versions[name] === void 0) {
|
|
28
|
-
versions[name] = {};
|
|
29
|
-
}
|
|
30
|
-
for (const [pkgName, pkgDepVersions] of Object.entries(versions[name])) {
|
|
31
|
-
let ok = true;
|
|
32
|
-
if (pkgDepVersions.match(/^(?:https?:\/\/|catalog:)/)) {
|
|
33
|
-
ok = version === pkgDepVersions;
|
|
34
|
-
} else {
|
|
35
|
-
ok = satisfies(version, pkgDepVersions);
|
|
36
|
-
}
|
|
37
|
-
if (!ok) {
|
|
38
|
-
errors.push({
|
|
39
|
-
package: pj.name,
|
|
40
|
-
dependency: name,
|
|
41
|
-
version,
|
|
42
|
-
at: field,
|
|
43
|
-
otherPackage: pkgName,
|
|
44
|
-
otherVersion: pkgDepVersions
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
versions[name][pj.name] = version;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return errors;
|
|
53
|
-
}
|
|
54
|
-
const validateWorkspaceDepsCli = bc.command({
|
|
55
|
-
name: "validate-workspace-deps",
|
|
56
|
-
desc: "validate the external dependencies of a workspace",
|
|
57
|
-
options: {
|
|
58
|
-
includeRoot: bc.boolean("include-root").desc("whether to also validate the root package.json").default(false),
|
|
59
|
-
noSkipWorkspaceDeps: bc.boolean("no-skip-workspace-deps").desc("whether to not skip validating dependencies of other workspace packages"),
|
|
60
|
-
root: bc.string().desc("path to the root of the workspace (default: cwd)"),
|
|
61
|
-
withErrorCode: bc.boolean("with-error-code").desc("whether to exit with a non-zero code if there are mismatches"),
|
|
62
|
-
skipPeerDeps: bc.boolean("skip-peer-deps").desc("whether to skip validating peer dependencies")
|
|
63
|
-
},
|
|
64
|
-
handler: async (args) => {
|
|
65
|
-
const errors = await validateWorkspaceDeps({
|
|
66
|
-
workspaceRoot: args.root ?? process.cwd(),
|
|
67
|
-
includeRoot: args.includeRoot,
|
|
68
|
-
skipWorkspaceDeps: !args.noSkipWorkspaceDeps,
|
|
69
|
-
skipPeerDeps: args.skipPeerDeps
|
|
70
|
-
});
|
|
71
|
-
if (errors.length > 0) {
|
|
72
|
-
console.error("⚠️ Found external dependencies mismatch:");
|
|
73
|
-
for (const error of errors) {
|
|
74
|
-
console.error(` - at ${error.package}: ${error.at} has ${error.dependency}@${error.version}, but ${error.otherPackage} has @${error.otherVersion}`);
|
|
75
|
-
}
|
|
76
|
-
if (args.withErrorCode) {
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
console.log("✅ All external dependencies match!");
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
export {
|
|
85
|
-
validateWorkspaceDeps,
|
|
86
|
-
validateWorkspaceDepsCli
|
|
87
|
-
};
|