@fuman/build 0.0.2 → 0.0.4
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/ci/github-actions.d.ts +3 -0
- package/cli/commands/build.d.ts +12 -0
- package/cli/commands/cr.d.ts +6 -0
- package/cli/commands/cr.js +60 -5
- package/cli/commands/docs.d.ts +11 -0
- package/cli/commands/docs.js +132 -0
- package/cli/commands/gen-deps-graph.d.ts +4 -0
- package/cli/commands/release.d.ts +2 -0
- package/cli/commands/release.js +20 -13
- package/cli/commands/validate-workspace-deps.d.ts +7 -1
- package/cli/commands/validate-workspace-deps.js +8 -3
- package/cli/index.d.ts +2 -1
- package/config.d.ts +22 -0
- package/fuman-build.js +3 -1
- package/git/github.d.ts +1 -0
- package/git/github.js +1 -1
- package/git/utils.d.ts +58 -2
- package/git/utils.js +8 -0
- package/index.d.ts +1 -0
- package/index.js +11 -1
- package/jsr/build-jsr.js +2 -1
- package/jsr/generate-workspace.js +2 -1
- package/misc/exec.d.ts +14 -0
- package/misc/exec.js +13 -3
- package/misc/path.d.ts +2 -1
- package/misc/path.js +2 -2
- package/misc/publish-order.d.ts +9 -0
- package/misc/tsconfig.d.ts +4 -0
- package/package-json/collect-package-jsons.d.ts +9 -0
- package/package-json/parse.d.ts +3 -0
- package/package-json/parse.js +13 -4
- package/package-json/process-package-json.d.ts +1 -0
- package/package-json/process-package-json.js +69 -58
- package/package-json/types.d.ts +1 -0
- package/package.json +13 -7
- package/versioning/collect-files.d.ts +2 -0
- package/versioning/collect-files.js +1 -4
- package/versioning/index.d.ts +4 -0
- package/versioning/types.d.ts +1 -0
- package/vite/build-plugin.js +2 -1
- package/vite/config.d.ts +4 -1
package/ci/github-actions.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/** are we running in github actions? */
|
|
1
2
|
export declare function isRunningInGithubActions(): boolean;
|
|
3
|
+
/** get the value of a github actions input */
|
|
2
4
|
export declare function getGithubActionsInput(name: string): string | undefined;
|
|
5
|
+
/** set the value of a github actions output */
|
|
3
6
|
export declare function writeGithubActionsOutput(name: string, value: string): void;
|
package/cli/commands/build.d.ts
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { WorkspacePackage } from '../../package-json/collect-package-jsons.js';
|
|
2
2
|
import { bc } from './_utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* build a single package using vite
|
|
5
|
+
*
|
|
6
|
+
* tiny wrapper on top of `vite build`
|
|
7
|
+
*/
|
|
3
8
|
export declare function buildPackage(params: {
|
|
9
|
+
/** path to the workspace root */
|
|
4
10
|
workspaceRoot: string;
|
|
11
|
+
/**
|
|
12
|
+
* list of workspace packages **including root**
|
|
13
|
+
*/
|
|
5
14
|
workspace?: WorkspacePackage[];
|
|
15
|
+
/** name of the package to build */
|
|
6
16
|
packageName: string;
|
|
17
|
+
/** path to the `build.config.js` file */
|
|
7
18
|
configPath?: string;
|
|
19
|
+
/** "fixed" version to use when building the package */
|
|
8
20
|
fixedVersion?: string;
|
|
9
21
|
}): Promise<void>;
|
|
10
22
|
export declare const buildPackageCli: bc.Command<{
|
package/cli/commands/cr.d.ts
CHANGED
|
@@ -5,13 +5,19 @@ export declare function runContinuousRelease(params: {
|
|
|
5
5
|
workspace?: WorkspacePackage[];
|
|
6
6
|
distDir?: string;
|
|
7
7
|
extraArgs?: string[];
|
|
8
|
+
onlyChanged?: boolean;
|
|
9
|
+
onlyChangedSince?: string;
|
|
8
10
|
}): Promise<void>;
|
|
9
11
|
export declare const runContinuousReleaseCli: bc.Command<{
|
|
10
12
|
root: string | undefined;
|
|
11
13
|
distDir: string | undefined;
|
|
12
14
|
extraArgs: string | undefined;
|
|
15
|
+
onlyChanged: boolean;
|
|
16
|
+
onlyChangedSince: string | undefined;
|
|
13
17
|
}, {
|
|
14
18
|
extraArgs: string[] | undefined;
|
|
15
19
|
root: string | undefined;
|
|
16
20
|
distDir: string | undefined;
|
|
21
|
+
onlyChanged: boolean;
|
|
22
|
+
onlyChangedSince: string | undefined;
|
|
17
23
|
}>;
|
package/cli/commands/cr.js
CHANGED
|
@@ -2,24 +2,77 @@ import { join } from "node:path";
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { asNonNull } from "@fuman/utils";
|
|
4
4
|
import { isRunningInGithubActions } from "../../ci/github-actions.js";
|
|
5
|
+
import { getLatestTag } from "../../git/utils.js";
|
|
5
6
|
import { exec } from "../../misc/exec.js";
|
|
6
7
|
import { collectPackageJsons, filterPackageJsonsForPublish } from "../../package-json/collect-package-jsons.js";
|
|
7
|
-
import
|
|
8
|
+
import { findProjectChangedPackages } from "../../versioning/collect-files.js";
|
|
9
|
+
import { loadConfig } from "./_utils.js";
|
|
8
10
|
import { buildPackage } from "./build.js";
|
|
11
|
+
import * as bc from "@drizzle-team/brocli";
|
|
9
12
|
async function runContinuousRelease(params) {
|
|
10
13
|
const {
|
|
11
14
|
workspaceRoot = process.cwd(),
|
|
12
15
|
workspace = await collectPackageJsons(workspaceRoot, true),
|
|
13
16
|
distDir = "dist",
|
|
14
|
-
extraArgs = []
|
|
17
|
+
extraArgs = [],
|
|
18
|
+
onlyChanged = false,
|
|
19
|
+
onlyChangedSince
|
|
15
20
|
} = params;
|
|
16
21
|
const workspaceWithoutRoot = workspace.filter((pkg) => !pkg.root);
|
|
17
|
-
|
|
22
|
+
let packages = filterPackageJsonsForPublish(workspaceWithoutRoot, "npm");
|
|
23
|
+
if (onlyChanged) {
|
|
24
|
+
const config = await loadConfig({
|
|
25
|
+
workspaceRoot,
|
|
26
|
+
require: false
|
|
27
|
+
});
|
|
28
|
+
const since = onlyChangedSince ?? await getLatestTag(workspaceRoot);
|
|
29
|
+
if (since == null) {
|
|
30
|
+
throw new Error("no previous tag found, cannot determine changeset");
|
|
31
|
+
}
|
|
32
|
+
const changedPackages = await findProjectChangedPackages({
|
|
33
|
+
params: config?.versioning,
|
|
34
|
+
workspace: workspaceWithoutRoot,
|
|
35
|
+
root: workspaceRoot,
|
|
36
|
+
since
|
|
37
|
+
});
|
|
38
|
+
if (!changedPackages.length) {
|
|
39
|
+
console.log(`🤔 no packages changed since ${since}, nothing to do`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const changedPackagesNames = /* @__PURE__ */ new Set();
|
|
43
|
+
for (const pkg of changedPackages) {
|
|
44
|
+
changedPackagesNames.add(asNonNull(pkg.json.name));
|
|
45
|
+
}
|
|
46
|
+
let hadChanges = true;
|
|
47
|
+
while (hadChanges) {
|
|
48
|
+
hadChanges = false;
|
|
49
|
+
for (const pkg of packages) {
|
|
50
|
+
const pkgName = asNonNull(pkg.json.name);
|
|
51
|
+
for (const field of ["dependencies", "peerDependencies"]) {
|
|
52
|
+
const deps = pkg.json[field];
|
|
53
|
+
if (deps == null) continue;
|
|
54
|
+
for (const name of Object.keys(deps)) {
|
|
55
|
+
if (changedPackagesNames.has(name) && !changedPackagesNames.has(pkgName)) {
|
|
56
|
+
hadChanges = true;
|
|
57
|
+
changedPackages.push(pkg);
|
|
58
|
+
changedPackagesNames.add(pkgName);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
packages = changedPackages;
|
|
66
|
+
console.log(`📝 only publishing changed packages since ${since}:`);
|
|
67
|
+
for (const pkg of packages) {
|
|
68
|
+
console.log(` - ${pkg.json.name}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
18
71
|
if (!isRunningInGithubActions()) {
|
|
19
72
|
throw new Error("cr command is only supported in github actions");
|
|
20
73
|
}
|
|
21
74
|
const distPaths = [];
|
|
22
|
-
for (const pkg of
|
|
75
|
+
for (const pkg of packages) {
|
|
23
76
|
if (pkg.json.scripts?.build !== void 0) {
|
|
24
77
|
await exec([
|
|
25
78
|
"npm",
|
|
@@ -60,7 +113,9 @@ const runContinuousReleaseCli = bc.command({
|
|
|
60
113
|
options: {
|
|
61
114
|
root: bc.string().desc("path to the root of the workspace (default: cwd)"),
|
|
62
115
|
distDir: bc.string("dist-dir").desc("directory to publish from, relative to package root (default: dist)"),
|
|
63
|
-
extraArgs: bc.string("extra-args").desc("extra arguments to pass to pkg-pr-new")
|
|
116
|
+
extraArgs: bc.string("extra-args").desc("extra arguments to pass to pkg-pr-new"),
|
|
117
|
+
onlyChanged: bc.boolean("only-changed").desc("whether to only publish packages changed since the last release.").default(false),
|
|
118
|
+
onlyChangedSince: bc.string("only-changed-since").desc("starting point for the changelog (defaults to latest tag)")
|
|
64
119
|
},
|
|
65
120
|
transform: (args) => {
|
|
66
121
|
return {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { bc } from './_utils.js';
|
|
2
|
+
/** generate documentation using typedoc for the workspace */
|
|
3
|
+
export declare function generateDocs(params: {
|
|
4
|
+
/** path to the workspace root */
|
|
5
|
+
workspaceRoot: string;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
export declare const generateDocsCli: bc.Command<{
|
|
8
|
+
root: string | undefined;
|
|
9
|
+
}, {
|
|
10
|
+
root: string | undefined;
|
|
11
|
+
}>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { asNonNull } from "@fuman/utils";
|
|
3
|
+
import * as td from "typedoc";
|
|
4
|
+
import { loadBuildConfig } from "../../misc/_config.js";
|
|
5
|
+
import { collectPackageJsons } from "../../package-json/collect-package-jsons.js";
|
|
6
|
+
import { processPackageJson } from "../../package-json/process-package-json.js";
|
|
7
|
+
import * as bc from "@drizzle-team/brocli";
|
|
8
|
+
const CUSTOM_ROOT_FIELDS = [
|
|
9
|
+
"includePackages",
|
|
10
|
+
"excludePackages"
|
|
11
|
+
];
|
|
12
|
+
const DEFAULT_CONFIG = {
|
|
13
|
+
includeVersion: true,
|
|
14
|
+
validation: {
|
|
15
|
+
notExported: true,
|
|
16
|
+
invalidLink: true,
|
|
17
|
+
notDocumented: false
|
|
18
|
+
},
|
|
19
|
+
excludePrivate: true,
|
|
20
|
+
excludeExternals: true,
|
|
21
|
+
excludeInternal: true,
|
|
22
|
+
exclude: [
|
|
23
|
+
"**/*/node_modules",
|
|
24
|
+
"**/*.test.ts",
|
|
25
|
+
"**/*.test-utils.ts"
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
class FumanTypedocReader {
|
|
29
|
+
constructor(workspaceRoot) {
|
|
30
|
+
this.workspaceRoot = workspaceRoot;
|
|
31
|
+
}
|
|
32
|
+
name = "@fuman/build";
|
|
33
|
+
order = 0;
|
|
34
|
+
// before any other readers
|
|
35
|
+
supportsPackages = true;
|
|
36
|
+
_workspace;
|
|
37
|
+
_rootConfig;
|
|
38
|
+
_forwardOptions(options, config, cwd) {
|
|
39
|
+
for (const [key, val] of Object.entries(config)) {
|
|
40
|
+
if (CUSTOM_ROOT_FIELDS.includes(key)) continue;
|
|
41
|
+
options.setValue(key, val, cwd);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async read(options, logger, cwd) {
|
|
45
|
+
if (cwd === this.workspaceRoot) {
|
|
46
|
+
const config = await loadBuildConfig(cwd);
|
|
47
|
+
this._rootConfig = config;
|
|
48
|
+
const data2 = config?.typedoc;
|
|
49
|
+
if (data2 != null) this._forwardOptions(options, data2, cwd);
|
|
50
|
+
options.setValue("entryPointStrategy", "packages");
|
|
51
|
+
this._workspace = await collectPackageJsons(cwd);
|
|
52
|
+
const entrypoints2 = [];
|
|
53
|
+
for (const pkg2 of this._workspace) {
|
|
54
|
+
const pkgName = asNonNull(pkg2.json.name);
|
|
55
|
+
if (data2?.includePackages && !data2.includePackages.includes(pkgName)) continue;
|
|
56
|
+
if (data2?.excludePackages?.includes(pkgName)) continue;
|
|
57
|
+
if (pkg2.json.exports != null && !data2?.includePackages?.includes(pkgName)) continue;
|
|
58
|
+
entrypoints2.push(pkg2.path);
|
|
59
|
+
}
|
|
60
|
+
options.setValue("entryPoints", entrypoints2, cwd);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const rootConfig = asNonNull(this._rootConfig);
|
|
64
|
+
if (rootConfig.typedoc != null) this._forwardOptions(options, rootConfig.typedoc, cwd);
|
|
65
|
+
const pkg = asNonNull(this._workspace?.find((pkg2) => pkg2.path.replace(/\/$/, "") === cwd.replace(/\/$/, "")));
|
|
66
|
+
const pkgConfig = await loadBuildConfig(cwd);
|
|
67
|
+
const hookContext = {
|
|
68
|
+
outDir: "",
|
|
69
|
+
packageDir: pkg.path,
|
|
70
|
+
packageName: asNonNull(pkg.json.name),
|
|
71
|
+
packageJson: pkg.json,
|
|
72
|
+
jsr: false,
|
|
73
|
+
typedoc: true
|
|
74
|
+
};
|
|
75
|
+
pkgConfig?.preparePackageJson?.(hookContext);
|
|
76
|
+
const { entrypoints } = processPackageJson({ packageJson: pkg.json, onlyEntrypoints: true });
|
|
77
|
+
options.setValue("entryPoints", Object.values(entrypoints), cwd);
|
|
78
|
+
if (!pkgConfig?.typedoc) return;
|
|
79
|
+
let data = pkgConfig.typedoc;
|
|
80
|
+
if (typeof data === "function") {
|
|
81
|
+
data = data(options.getRawValues());
|
|
82
|
+
}
|
|
83
|
+
this._forwardOptions(options, data, cwd);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function generateDocs(params) {
|
|
87
|
+
const app = await td.Application.bootstrapWithPlugins(DEFAULT_CONFIG, [
|
|
88
|
+
new FumanTypedocReader(params.workspaceRoot),
|
|
89
|
+
new td.TSConfigReader(),
|
|
90
|
+
new td.TypeDocReader()
|
|
91
|
+
]);
|
|
92
|
+
const project = await app.convert();
|
|
93
|
+
if (!project) {
|
|
94
|
+
throw new Error("Could not convert to typedoc project");
|
|
95
|
+
}
|
|
96
|
+
if (app.options.getValue("treatWarningsAsErrors") && app.logger.hasWarnings()) {
|
|
97
|
+
throw new Error("There were warnings while converting the project");
|
|
98
|
+
}
|
|
99
|
+
const preValidationWarnCount = app.logger.warningCount;
|
|
100
|
+
app.validate(project);
|
|
101
|
+
const hadValidationWarnings = app.logger.warningCount !== preValidationWarnCount;
|
|
102
|
+
if (app.logger.hasErrors()) {
|
|
103
|
+
throw new Error("There were errors while validating the project");
|
|
104
|
+
}
|
|
105
|
+
if (hadValidationWarnings && (app.options.getValue("treatWarningsAsErrors") || app.options.getValue("treatValidationWarningsAsErrors"))) {
|
|
106
|
+
throw new Error("There were warnings while validating the project");
|
|
107
|
+
}
|
|
108
|
+
if (app.options.getValue("emit") === "none") return;
|
|
109
|
+
await app.generateOutputs(project);
|
|
110
|
+
if (app.logger.hasErrors()) {
|
|
111
|
+
throw new Error("There were errors while generating the outputs");
|
|
112
|
+
}
|
|
113
|
+
if (app.options.getValue("treatWarningsAsErrors") && app.logger.hasWarnings()) {
|
|
114
|
+
throw new Error("There were warnings while generating the outputs");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const generateDocsCli = bc.command({
|
|
118
|
+
name: "typedoc",
|
|
119
|
+
desc: "generate docs using typedoc",
|
|
120
|
+
options: {
|
|
121
|
+
root: bc.string().desc("path to the root of the workspace (default: cwd)")
|
|
122
|
+
},
|
|
123
|
+
handler: async (args) => {
|
|
124
|
+
await generateDocs({
|
|
125
|
+
workspaceRoot: args.root ?? process.cwd()
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
export {
|
|
130
|
+
generateDocs,
|
|
131
|
+
generateDocsCli
|
|
132
|
+
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { bc } from './_utils.js';
|
|
2
|
+
/** generate a graphviz dot file of the workspace dependencies */
|
|
2
3
|
export declare function generateDepsGraph(params: {
|
|
4
|
+
/** path to the workspace root */
|
|
3
5
|
workspaceRoot: string | URL;
|
|
6
|
+
/** whether to include the root package.json in the graph */
|
|
4
7
|
includeRoot?: boolean;
|
|
8
|
+
/** whether to include external dependencies in the graph */
|
|
5
9
|
includeExternal?: boolean;
|
|
6
10
|
}): Promise<string>;
|
|
7
11
|
export declare const generateDepsGraphCli: bc.Command<{
|
|
@@ -4,6 +4,7 @@ export declare const releaseCli: bc.Command<{
|
|
|
4
4
|
withGithubRelease: boolean;
|
|
5
5
|
githubToken: string | undefined;
|
|
6
6
|
githubRepo: string | undefined;
|
|
7
|
+
githubApiUrl: string | undefined;
|
|
7
8
|
withJsr: boolean;
|
|
8
9
|
jsrRegistry: string | undefined;
|
|
9
10
|
jsrToken: string | undefined;
|
|
@@ -20,6 +21,7 @@ export declare const releaseCli: bc.Command<{
|
|
|
20
21
|
withGithubRelease: boolean;
|
|
21
22
|
githubToken: string | undefined;
|
|
22
23
|
githubRepo: string | undefined;
|
|
24
|
+
githubApiUrl: string | undefined;
|
|
23
25
|
withJsr: boolean;
|
|
24
26
|
jsrRegistry: string | undefined;
|
|
25
27
|
jsrToken: string | undefined;
|
package/cli/commands/release.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { basename } from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import {
|
|
5
|
-
import { asNonNull, notImplemented } from "@fuman/utils";
|
|
4
|
+
import { asNonNull, notImplemented, parallelMap } from "@fuman/utils";
|
|
6
5
|
import { sort } from "semver";
|
|
7
6
|
import { createGithubRelease } from "../../git/github.js";
|
|
8
|
-
import { getLatestTag, getFirstCommit } from "../../git/utils.js";
|
|
7
|
+
import { getLatestTag, getFirstCommit, gitTagExists } from "../../git/utils.js";
|
|
9
8
|
import { jsrCreatePackages } from "../../jsr/create-packages.js";
|
|
10
9
|
import { generateDenoWorkspace } from "../../jsr/generate-workspace.js";
|
|
11
10
|
import { exec } from "../../misc/exec.js";
|
|
@@ -24,6 +23,7 @@ const releaseCli = bc.command({
|
|
|
24
23
|
withGithubRelease: bc.boolean("with-github-release").desc("whether to create a github release (requires GITHUB_TOKEN env var). if false, will only create a commit with the release notes").default(false),
|
|
25
24
|
githubToken: bc.string("github-token").desc("github token to use for creating a release (defaults to GITHUB_TOKEN env var)"),
|
|
26
25
|
githubRepo: bc.string("github-repo").desc("github repo to create a release for (defaults to GITHUB_REPOSITORY env var)"),
|
|
26
|
+
githubApiUrl: bc.string("github-api-url").desc("github api url to use for creating a release (for github-compatible apis)"),
|
|
27
27
|
withJsr: bc.boolean("with-jsr").desc("whether to publish to jsr").default(false),
|
|
28
28
|
jsrRegistry: bc.string("jsr-registry").desc("URL of the jsr registry to publish to"),
|
|
29
29
|
jsrToken: bc.string("jsr-token").desc("jsr token to use for publishing"),
|
|
@@ -75,6 +75,20 @@ const releaseCli = bc.command({
|
|
|
75
75
|
} else {
|
|
76
76
|
changedPackages = workspace;
|
|
77
77
|
}
|
|
78
|
+
let tagName;
|
|
79
|
+
if (!bumpVersionResult) {
|
|
80
|
+
const versions = sort(workspace.map((pkg) => asNonNull(pkg.json.version)));
|
|
81
|
+
tagName = `v${versions[versions.length - 1]}`;
|
|
82
|
+
} else {
|
|
83
|
+
tagName = `v${bumpVersionResult.nextVersion}`;
|
|
84
|
+
}
|
|
85
|
+
if (await gitTagExists(tagName, root)) {
|
|
86
|
+
console.log(`❗ tag ${tagName} already exists. did the previous release complete successfully?`);
|
|
87
|
+
console.log("❗ if so, please verify versions in package.json and try again");
|
|
88
|
+
if (!args.dryRun) {
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
78
92
|
console.log("");
|
|
79
93
|
console.log("📝 generating changelog...");
|
|
80
94
|
const changelog = prevTag != null ? await generateChangelog({
|
|
@@ -158,13 +172,6 @@ const releaseCli = bc.command({
|
|
|
158
172
|
});
|
|
159
173
|
console.log("\x1B[;32m✅ published to jsr\x1B[;0m");
|
|
160
174
|
}
|
|
161
|
-
let tagName;
|
|
162
|
-
if (!bumpVersionResult) {
|
|
163
|
-
const versions = sort(workspace.map((pkg) => asNonNull(pkg.json.version)));
|
|
164
|
-
tagName = `v${versions[versions.length - 1]}`;
|
|
165
|
-
} else {
|
|
166
|
-
tagName = `v${bumpVersionResult.nextVersion}`;
|
|
167
|
-
}
|
|
168
175
|
if (args.dryRun) {
|
|
169
176
|
console.log("dry run, skipping release commit and tag");
|
|
170
177
|
} else {
|
|
@@ -205,10 +212,10 @@ ${changelog}`;
|
|
|
205
212
|
tag: tagName,
|
|
206
213
|
name: tagName,
|
|
207
214
|
body: changelog,
|
|
208
|
-
artifacts: tarballs
|
|
215
|
+
artifacts: await parallelMap(tarballs, async (file) => ({
|
|
209
216
|
name: basename(file),
|
|
210
217
|
type: "application/gzip",
|
|
211
|
-
body:
|
|
218
|
+
body: await readFile(file)
|
|
212
219
|
}))
|
|
213
220
|
});
|
|
214
221
|
console.log(`\x1B[;32m✅github release created: https://github.com/${repo}/releases/tag/${tagName}\x1B[;0m`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { bc } from './_utils.js';
|
|
2
|
+
/** information about a mismatch between a package and its dependencies */
|
|
2
3
|
export interface WorkspaceDepsError {
|
|
3
4
|
/** package name where the mismatch occurred */
|
|
4
5
|
package: string;
|
|
@@ -13,7 +14,12 @@ export interface WorkspaceDepsError {
|
|
|
13
14
|
/** original version of the dependency */
|
|
14
15
|
otherVersion: string;
|
|
15
16
|
}
|
|
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;
|
|
17
23
|
/**
|
|
18
24
|
* whether to also validate the root package.json
|
|
19
25
|
*
|
|
@@ -2,8 +2,12 @@ import process from "node:process";
|
|
|
2
2
|
import { satisfies } from "semver";
|
|
3
3
|
import { collectPackageJsons } from "../../package-json/collect-package-jsons.js";
|
|
4
4
|
import * as bc from "@drizzle-team/brocli";
|
|
5
|
-
async function validateWorkspaceDeps(
|
|
6
|
-
const {
|
|
5
|
+
async function validateWorkspaceDeps(params) {
|
|
6
|
+
const {
|
|
7
|
+
workspaceRoot,
|
|
8
|
+
includeRoot = true,
|
|
9
|
+
skipWorkspaceDeps = true
|
|
10
|
+
} = params;
|
|
7
11
|
const pjs = await collectPackageJsons(workspaceRoot, includeRoot);
|
|
8
12
|
const workspacePackages = new Set(skipWorkspaceDeps ? pjs.map((pj) => pj.json.name) : []);
|
|
9
13
|
const versions = {};
|
|
@@ -48,7 +52,8 @@ const validateWorkspaceDepsCli = bc.command({
|
|
|
48
52
|
root: bc.string().desc("path to the root of the workspace (default: cwd)")
|
|
49
53
|
},
|
|
50
54
|
handler: async (args) => {
|
|
51
|
-
const errors = await validateWorkspaceDeps(
|
|
55
|
+
const errors = await validateWorkspaceDeps({
|
|
56
|
+
workspaceRoot: args.root ?? process.cwd(),
|
|
52
57
|
includeRoot: args.includeRoot,
|
|
53
58
|
skipWorkspaceDeps: !args.noSkipWorkspaceDeps
|
|
54
59
|
});
|
package/cli/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { buildPackage } from './commands/build.js';
|
|
2
|
+
export { generateDocs } from './commands/docs.js';
|
|
2
3
|
export { generateDepsGraph } from './commands/gen-deps-graph.js';
|
|
3
|
-
export { validateWorkspaceDeps } from './commands/validate-workspace-deps.js';
|
|
4
|
+
export { validateWorkspaceDeps, type WorkspaceDepsError } from './commands/validate-workspace-deps.js';
|
package/config.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { AnyToNever } from '@fuman/utils';
|
|
2
|
+
import { TypeDocOptions } from 'typedoc';
|
|
1
3
|
import { JsrConfig } from './jsr/config.js';
|
|
2
4
|
import { PackageJson } from './package-json/types.js';
|
|
3
5
|
import { VersioningOptions } from './versioning/types.js';
|
|
6
|
+
/** context object that is passed to each build hook */
|
|
4
7
|
export interface BuildHookContext {
|
|
5
8
|
/** full path to the output directory */
|
|
6
9
|
outDir: string;
|
|
@@ -15,7 +18,10 @@ export interface BuildHookContext {
|
|
|
15
18
|
packageJson: PackageJson;
|
|
16
19
|
/** whether this is a jsr build */
|
|
17
20
|
jsr: boolean;
|
|
21
|
+
/** whether this is a documentation build */
|
|
22
|
+
typedoc: boolean;
|
|
18
23
|
}
|
|
24
|
+
/** root configuration object */
|
|
19
25
|
export interface RootConfigObject {
|
|
20
26
|
/**
|
|
21
27
|
* path to vite config to use when building using fuman-build cli,
|
|
@@ -28,5 +34,21 @@ export interface RootConfigObject {
|
|
|
28
34
|
jsr?: JsrConfig;
|
|
29
35
|
/** configuration for the changelog generator */
|
|
30
36
|
versioning?: VersioningOptions;
|
|
37
|
+
/** base configuration for typedoc */
|
|
38
|
+
typedoc?: AnyToNever<Omit<Partial<TypeDocOptions>, 'entryPoints' | 'entryPointStrategy' | 'extends'> & {
|
|
39
|
+
/**
|
|
40
|
+
* **note**: fuman-specific option
|
|
41
|
+
*
|
|
42
|
+
* if passed, docs will be generated for the specified packages only
|
|
43
|
+
*/
|
|
44
|
+
includePackages?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* **note**: fuman-specific option
|
|
47
|
+
*
|
|
48
|
+
* list of packages for which the docs should *not* be generated
|
|
49
|
+
*/
|
|
50
|
+
excludePackages?: string[];
|
|
51
|
+
}>;
|
|
31
52
|
}
|
|
53
|
+
/** root configuration (either an object or a function that returns an object) */
|
|
32
54
|
export type RootConfig = RootConfigObject | (() => RootConfigObject);
|
package/fuman-build.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as bc from "@drizzle-team/brocli";
|
|
|
4
4
|
import { buildPackageCli } from "./cli/commands/build.js";
|
|
5
5
|
import { bumpVersionCli } from "./cli/commands/bump-version.js";
|
|
6
6
|
import { runContinuousReleaseCli } from "./cli/commands/cr.js";
|
|
7
|
+
import { generateDocsCli } from "./cli/commands/docs.js";
|
|
7
8
|
import { findChangedPackagesCli } from "./cli/commands/find-changed-packages.js";
|
|
8
9
|
import { generateChangelogCli } from "./cli/commands/gen-changelog.js";
|
|
9
10
|
import { generateDepsGraphCli } from "./cli/commands/gen-deps-graph.js";
|
|
@@ -21,7 +22,8 @@ await bc.run([
|
|
|
21
22
|
bumpVersionCli,
|
|
22
23
|
publishPackagesCli,
|
|
23
24
|
releaseCli,
|
|
24
|
-
runContinuousReleaseCli
|
|
25
|
+
runContinuousReleaseCli,
|
|
26
|
+
generateDocsCli
|
|
25
27
|
], {
|
|
26
28
|
theme: (event) => {
|
|
27
29
|
if (event.type === "error" && event.violation === "unknown_error") {
|
package/git/github.d.ts
CHANGED
package/git/github.js
CHANGED
|
@@ -4,7 +4,7 @@ import { asyncPool } from "@fuman/utils";
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
async function createGithubRelease(params) {
|
|
6
6
|
const ffetch = ffetchBase.extend({
|
|
7
|
-
baseUrl: "https://api.github.com",
|
|
7
|
+
baseUrl: params.apiUrl ?? "https://api.github.com",
|
|
8
8
|
addons: [
|
|
9
9
|
ffetchAddons.retry(),
|
|
10
10
|
ffetchAddons.parser(ffetchZodAdapter())
|
package/git/utils.d.ts
CHANGED
|
@@ -1,38 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* get the latest tag in the repository
|
|
3
|
+
* @param cwd override the current working directory
|
|
4
|
+
*/
|
|
1
5
|
export declare function getLatestTag(cwd?: string | URL): Promise<string | null>;
|
|
6
|
+
/**
|
|
7
|
+
* get hash of the first commit in the repository
|
|
8
|
+
* @param cwd override the current working directory
|
|
9
|
+
*/
|
|
2
10
|
export declare function getFirstCommit(cwd?: string | URL): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* get hash of the current commit
|
|
13
|
+
* @param cwd override the current working directory
|
|
14
|
+
*/
|
|
3
15
|
export declare function getCurrentCommit(cwd?: string | URL): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* get name of the current branch
|
|
18
|
+
* @param cwd override the current working directory
|
|
19
|
+
*/
|
|
4
20
|
export declare function getCurrentBranch(cwd?: string | URL): Promise<string>;
|
|
21
|
+
export declare function gitTagExists(tag: string, cwd?: string | URL): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* find changed files between two commits
|
|
24
|
+
*
|
|
25
|
+
* @returns list of changed files, relative to the repository root
|
|
26
|
+
*/
|
|
5
27
|
export declare function findChangedFiles(params: {
|
|
28
|
+
/** starting point for the diff */
|
|
6
29
|
since: string;
|
|
7
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* ending point for the diff
|
|
32
|
+
*
|
|
33
|
+
* @default 'HEAD'
|
|
34
|
+
*/
|
|
8
35
|
until?: string;
|
|
36
|
+
/** override the current working directory */
|
|
9
37
|
cwd?: string | URL;
|
|
10
38
|
}): Promise<string[]>;
|
|
39
|
+
/** information about a commit */
|
|
11
40
|
export interface CommitInfo {
|
|
41
|
+
/** full hash of the commit */
|
|
12
42
|
hash: string;
|
|
43
|
+
/** author of the commit */
|
|
13
44
|
author: {
|
|
45
|
+
/** name of the author */
|
|
14
46
|
name: string;
|
|
47
|
+
/** email of the author */
|
|
15
48
|
email: string;
|
|
49
|
+
/** date of the commit */
|
|
16
50
|
date: Date;
|
|
17
51
|
};
|
|
52
|
+
/** committer of the commit */
|
|
18
53
|
committer: {
|
|
54
|
+
/** name of the committer */
|
|
19
55
|
name: string;
|
|
56
|
+
/** email of the committer */
|
|
20
57
|
email: string;
|
|
58
|
+
/** date of the commit */
|
|
21
59
|
date: Date;
|
|
22
60
|
};
|
|
61
|
+
/** commit message */
|
|
23
62
|
message: string;
|
|
63
|
+
/** commit description */
|
|
24
64
|
description: string;
|
|
25
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* get information about commits between two commits (both ends inclusive)
|
|
68
|
+
*
|
|
69
|
+
* @returns list of commits, in reverse chronological order
|
|
70
|
+
*/
|
|
26
71
|
export declare function getCommitsBetween(params: {
|
|
72
|
+
/** starting point for the diff */
|
|
27
73
|
since: string;
|
|
28
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* ending point for the diff
|
|
76
|
+
* @default 'HEAD'
|
|
77
|
+
*/
|
|
29
78
|
until?: string;
|
|
79
|
+
/** override the current working directory */
|
|
30
80
|
cwd?: string | URL;
|
|
31
81
|
}): Promise<CommitInfo[]>;
|
|
82
|
+
/** information about a conventional commit */
|
|
32
83
|
export interface ConventionalCommit {
|
|
84
|
+
/** type of the commit (e.g. `feat`, `fix`, etc) */
|
|
33
85
|
type: string;
|
|
86
|
+
/** scope of the commit (i.e. "scope" in `feat(scope): subject`) */
|
|
34
87
|
scope?: string;
|
|
88
|
+
/** whether the commit is marked as breaking with an exclamation mark */
|
|
35
89
|
breaking: boolean;
|
|
90
|
+
/** subject of the commit */
|
|
36
91
|
subject: string;
|
|
37
92
|
}
|
|
93
|
+
/** parse a conventional commit message */
|
|
38
94
|
export declare function parseConventionalCommit(msg: string): ConventionalCommit | null;
|
package/git/utils.js
CHANGED
|
@@ -30,6 +30,13 @@ async function getCurrentBranch(cwd) {
|
|
|
30
30
|
});
|
|
31
31
|
return res.stdout.trim();
|
|
32
32
|
}
|
|
33
|
+
async function gitTagExists(tag, cwd) {
|
|
34
|
+
const res = await exec(["git", "tag", "--list", tag], {
|
|
35
|
+
cwd,
|
|
36
|
+
throwOnError: true
|
|
37
|
+
});
|
|
38
|
+
return res.stdout.trim() !== "";
|
|
39
|
+
}
|
|
33
40
|
async function findChangedFiles(params) {
|
|
34
41
|
const { since, until = "HEAD", cwd } = params;
|
|
35
42
|
const res = await exec(["git", "diff", "--name-only", since, until], {
|
|
@@ -106,5 +113,6 @@ export {
|
|
|
106
113
|
getCurrentCommit,
|
|
107
114
|
getFirstCommit,
|
|
108
115
|
getLatestTag,
|
|
116
|
+
gitTagExists,
|
|
109
117
|
parseConventionalCommit
|
|
110
118
|
};
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { getGithubActionsInput, isRunningInGithubActions, writeGithubActionsOutput } from "./ci/github-actions.js";
|
|
2
2
|
import { buildPackage } from "./cli/commands/build.js";
|
|
3
|
+
import { generateDocs } from "./cli/commands/docs.js";
|
|
3
4
|
import { generateDepsGraph } from "./cli/commands/gen-deps-graph.js";
|
|
4
5
|
import { validateWorkspaceDeps } from "./cli/commands/validate-workspace-deps.js";
|
|
5
|
-
import { findChangedFiles, getCommitsBetween, getCurrentBranch, getCurrentCommit, getFirstCommit, getLatestTag, parseConventionalCommit } from "./git/utils.js";
|
|
6
|
+
import { findChangedFiles, getCommitsBetween, getCurrentBranch, getCurrentCommit, getFirstCommit, getLatestTag, gitTagExists, parseConventionalCommit } from "./git/utils.js";
|
|
6
7
|
import { exec } from "./misc/exec.js";
|
|
7
8
|
import { normalizeFilePath } from "./misc/path.js";
|
|
8
9
|
import { determinePublishOrder, sortWorkspaceByPublishOrder } from "./misc/publish-order.js";
|
|
@@ -13,17 +14,25 @@ import { findPackageJson } from "./package-json/find-package-json.js";
|
|
|
13
14
|
import { parsePackageJson, parsePackageJsonFile, parseWorkspaceRootPackageJson } from "./package-json/parse.js";
|
|
14
15
|
import { processPackageJson } from "./package-json/process-package-json.js";
|
|
15
16
|
import { PackageJsonSchema } from "./package-json/types.js";
|
|
17
|
+
import { bumpVersion } from "./versioning/bump-version.js";
|
|
18
|
+
import { findProjectChangedFiles, findProjectChangedPackages } from "./versioning/collect-files.js";
|
|
19
|
+
import { generateChangelog } from "./versioning/generate-changelog.js";
|
|
16
20
|
export {
|
|
17
21
|
NPM_PACKAGE_NAME_REGEX,
|
|
18
22
|
PackageJsonSchema,
|
|
19
23
|
buildPackage,
|
|
24
|
+
bumpVersion,
|
|
20
25
|
collectPackageJsons,
|
|
21
26
|
determinePublishOrder,
|
|
22
27
|
exec,
|
|
23
28
|
filterPackageJsonsForPublish,
|
|
24
29
|
findChangedFiles,
|
|
25
30
|
findPackageJson,
|
|
31
|
+
findProjectChangedFiles,
|
|
32
|
+
findProjectChangedPackages,
|
|
33
|
+
generateChangelog,
|
|
26
34
|
generateDepsGraph,
|
|
35
|
+
generateDocs,
|
|
27
36
|
getCommitsBetween,
|
|
28
37
|
getCurrentBranch,
|
|
29
38
|
getCurrentCommit,
|
|
@@ -32,6 +41,7 @@ export {
|
|
|
32
41
|
getLatestTag,
|
|
33
42
|
getTsconfigFiles,
|
|
34
43
|
getTsconfigFor,
|
|
44
|
+
gitTagExists,
|
|
35
45
|
isRunningInGithubActions,
|
|
36
46
|
normalizeFilePath,
|
|
37
47
|
npmCheckVersion,
|
package/jsr/build-jsr.js
CHANGED
|
@@ -103,7 +103,8 @@ ${badImports.join("\n")}`);
|
|
|
103
103
|
packageDir: ourPackage.path,
|
|
104
104
|
packageName: asNonNull(ourPackage.json.name),
|
|
105
105
|
packageJson: ourPackage.json,
|
|
106
|
-
jsr: true
|
|
106
|
+
jsr: true,
|
|
107
|
+
typedoc: false
|
|
107
108
|
};
|
|
108
109
|
packageConfig?.preparePackageJson?.(hookContext);
|
|
109
110
|
const workspaceVersions = collectVersions(workspacePackages);
|
|
@@ -125,7 +125,8 @@ async function generateDenoWorkspace(params) {
|
|
|
125
125
|
packageDir: packageOutRoot,
|
|
126
126
|
packageName: pkg.json.name,
|
|
127
127
|
packageJson: pkg.json,
|
|
128
|
-
jsr: true
|
|
128
|
+
jsr: true,
|
|
129
|
+
typedoc: false
|
|
129
130
|
};
|
|
130
131
|
packageConfig?.preparePackageJson?.(hookContext);
|
|
131
132
|
const workspaceVersions = collectVersions(workspacePackages);
|
package/misc/exec.d.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { SpawnOptions } from 'node:child_process';
|
|
2
|
+
/** result of {@link exec} */
|
|
2
3
|
export interface ExecResult {
|
|
4
|
+
/** stdout of the command */
|
|
3
5
|
stdout: string;
|
|
6
|
+
/** stderr of the command */
|
|
4
7
|
stderr: string;
|
|
8
|
+
/** exit code of the command */
|
|
5
9
|
exitCode: number;
|
|
6
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* execute a command and return its result
|
|
13
|
+
*
|
|
14
|
+
* **differences from node's `child_process.exec()`**:
|
|
15
|
+
* - if `options.stdio` is set to `'inherit'`, the command will be printed to the console (unless `options.quiet` is set to `true`)
|
|
16
|
+
* - on non-zero exit code, the promise will be rejected with an error if `options.throwOnError` is set to `true`
|
|
17
|
+
*
|
|
18
|
+
* @param cmd command to execute (first element is the command itself, the rest are arguments to it)
|
|
19
|
+
*/
|
|
7
20
|
export declare function exec(cmd: string[], options?: SpawnOptions & {
|
|
8
21
|
throwOnError?: boolean;
|
|
22
|
+
quiet?: boolean;
|
|
9
23
|
}): Promise<ExecResult>;
|
package/misc/exec.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path__default from "node:path";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { spawn } from "cross-spawn";
|
|
4
|
+
import { normalizeFilePath } from "./path.js";
|
|
2
5
|
function exec(cmd, options) {
|
|
3
6
|
return new Promise((resolve, reject) => {
|
|
4
|
-
if (options?.stdio === "inherit") {
|
|
5
|
-
|
|
7
|
+
if (options?.stdio === "inherit" && !options.quiet) {
|
|
8
|
+
const cmdStr = cmd.map((it) => it.includes(" ") ? `"${it.replace(/"/g, '\\"')}"` : it).join(" ");
|
|
9
|
+
let cwdStr = "";
|
|
10
|
+
if (options?.cwd != null) {
|
|
11
|
+
const normCwd = path__default.resolve(normalizeFilePath(options.cwd));
|
|
12
|
+
const showCwd = normCwd !== process.cwd();
|
|
13
|
+
cwdStr = showCwd ? `\x1B[;3m${path__default.relative(process.cwd(), normCwd)}\x1B[;23m ` : "";
|
|
14
|
+
}
|
|
15
|
+
console.log(`${cwdStr}\x1B[;34m$\x1B[;0m ${cmdStr}`);
|
|
6
16
|
}
|
|
7
17
|
const proc = spawn(cmd[0], cmd.slice(1), {
|
|
8
18
|
stdio: "pipe",
|
package/misc/path.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { URL as NodeURL } from 'node:url';
|
|
2
|
+
export declare function normalizeFilePath(filePath: string | URL | NodeURL): string;
|
package/misc/path.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { fileURLToPath } from "node:url";
|
|
1
|
+
import { URL as URL$1, fileURLToPath } from "node:url";
|
|
2
2
|
function normalizeFilePath(filePath) {
|
|
3
|
-
if (filePath instanceof URL) {
|
|
3
|
+
if (filePath instanceof URL || filePath instanceof URL$1) {
|
|
4
4
|
return fileURLToPath(filePath);
|
|
5
5
|
} else if (filePath.startsWith("file://")) {
|
|
6
6
|
return fileURLToPath(new URL(filePath));
|
package/misc/publish-order.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import { WorkspacePackage } from '../package-json/collect-package-jsons.js';
|
|
2
|
+
/** sort a workspace by the publish order (i.e. dependencies first, then dependants) */
|
|
2
3
|
export declare function sortWorkspaceByPublishOrder(packages: WorkspacePackage[]): WorkspacePackage[];
|
|
4
|
+
/**
|
|
5
|
+
* determine the publish order of a workspace
|
|
6
|
+
*
|
|
7
|
+
* publish order is determined by the dependencies of the packages,
|
|
8
|
+
* so that for each package, all its dependencies are to be published before it
|
|
9
|
+
*
|
|
10
|
+
* @throws if there's a cycle in the dependencies
|
|
11
|
+
*/
|
|
3
12
|
export declare function determinePublishOrder(dependencies: Record<string, string[]>): string[];
|
package/misc/tsconfig.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
/** get a full tsconfig for the given directory */
|
|
1
2
|
export declare function getTsconfigFor(cwd: string): Promise<unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* get the list of files that are included in the tsconfig
|
|
5
|
+
*/
|
|
2
6
|
export declare function getTsconfigFiles(cwd: string): Promise<string[]>;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { PackageJson } from './types.js';
|
|
2
|
+
/** information about a package in a workspace */
|
|
2
3
|
export interface WorkspacePackage {
|
|
4
|
+
/** path to the package root */
|
|
3
5
|
path: string;
|
|
6
|
+
/** whether this is the root package */
|
|
4
7
|
root: boolean;
|
|
8
|
+
/** package.json of the package */
|
|
5
9
|
json: PackageJson;
|
|
6
10
|
}
|
|
11
|
+
/** collect package.jsons from a workspace */
|
|
7
12
|
export declare function collectPackageJsons(workspaceRoot: string | URL, includeRoot?: boolean): Promise<WorkspacePackage[]>;
|
|
13
|
+
/**
|
|
14
|
+
* filter packages to only include the ones that are to be published
|
|
15
|
+
* to the given registry
|
|
16
|
+
*/
|
|
8
17
|
export declare function filterPackageJsonsForPublish(packages: WorkspacePackage[], registry: 'jsr' | 'npm'): WorkspacePackage[];
|
package/package-json/parse.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { PackageJson } from './types.js';
|
|
2
|
+
/** parse a package.json from string */
|
|
2
3
|
export declare function parsePackageJson(packageJson: string): PackageJson;
|
|
4
|
+
/** parse a package.json file */
|
|
3
5
|
export declare function parsePackageJsonFile(packageJsonPath: string | URL): Promise<PackageJson>;
|
|
6
|
+
/** parse the package.json file at the root of the workspace */
|
|
4
7
|
export declare function parseWorkspaceRootPackageJson(workspaceRoot: string | URL): Promise<PackageJson>;
|
package/package-json/parse.js
CHANGED
|
@@ -26,10 +26,19 @@ async function parseWorkspaceRootPackageJson(workspaceRoot) {
|
|
|
26
26
|
if (!workspace.packages) {
|
|
27
27
|
throw new Error("No packages found in pnpm-workspace.yaml");
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
if (workspace.catalog || workspace.catalogs) {
|
|
30
|
+
const catalogs = {};
|
|
31
|
+
if (workspace.catalog) {
|
|
32
|
+
catalogs[""] = workspace.catalog;
|
|
33
|
+
}
|
|
34
|
+
if (workspace.catalogs) {
|
|
35
|
+
for (const [name, catalog] of Object.entries(workspace.catalogs)) {
|
|
36
|
+
catalogs[name] = catalog;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
parsed.catalogs = catalogs;
|
|
40
|
+
}
|
|
41
|
+
parsed.workspaces = workspace.packages;
|
|
33
42
|
}
|
|
34
43
|
return parsed;
|
|
35
44
|
}
|
|
@@ -2,6 +2,7 @@ const DEFAULT_FIELDS_TO_COPY_ROOT = ["license", "author", "contributors", "homep
|
|
|
2
2
|
function processPackageJson(params) {
|
|
3
3
|
const {
|
|
4
4
|
packageJson: packageJsonOrig,
|
|
5
|
+
onlyEntrypoints = false,
|
|
5
6
|
workspaceVersions,
|
|
6
7
|
rootPackageJson,
|
|
7
8
|
rootFieldsToCopy = DEFAULT_FIELDS_TO_COPY_ROOT,
|
|
@@ -10,71 +11,81 @@ function processPackageJson(params) {
|
|
|
10
11
|
} = params;
|
|
11
12
|
const packageJson = structuredClone(packageJsonOrig);
|
|
12
13
|
const entrypoints = {};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
packageJson[field]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
delete packageJson.devDependencies;
|
|
29
|
-
delete packageJson.private;
|
|
30
|
-
if (packageJson.fuman?.distOnlyFields) {
|
|
31
|
-
Object.assign(packageJson, packageJson.fuman.distOnlyFields);
|
|
32
|
-
delete packageJson.distOnlyFields;
|
|
33
|
-
}
|
|
34
|
-
function replaceWorkspaceDependencies(field) {
|
|
35
|
-
if (packageJson[field] == null) return;
|
|
36
|
-
const dependencies = packageJson[field];
|
|
37
|
-
for (const name of Object.keys(dependencies)) {
|
|
38
|
-
const value = dependencies[name];
|
|
39
|
-
if (value.startsWith("workspace:")) {
|
|
40
|
-
if (bundledWorkspaceDeps) {
|
|
41
|
-
let found = false;
|
|
42
|
-
for (const dep of bundledWorkspaceDeps) {
|
|
43
|
-
if (dep.test(name)) {
|
|
44
|
-
delete dependencies[name];
|
|
45
|
-
found = true;
|
|
46
|
-
break;
|
|
14
|
+
if (!onlyEntrypoints) {
|
|
15
|
+
let replaceCustomDependencies = function(field) {
|
|
16
|
+
if (packageJson[field] == null) return;
|
|
17
|
+
const dependencies = packageJson[field];
|
|
18
|
+
for (const name of Object.keys(dependencies)) {
|
|
19
|
+
const value = dependencies[name];
|
|
20
|
+
if (value.startsWith("workspace:")) {
|
|
21
|
+
if (bundledWorkspaceDeps) {
|
|
22
|
+
let found = false;
|
|
23
|
+
for (const dep of bundledWorkspaceDeps) {
|
|
24
|
+
if (dep.test(name)) {
|
|
25
|
+
delete dependencies[name];
|
|
26
|
+
found = true;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
47
29
|
}
|
|
30
|
+
if (found) continue;
|
|
48
31
|
}
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
32
|
+
if (value !== "workspace:^" && value !== "workspace:*") {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Cannot replace workspace dependency ${name} with ${value} - only workspace:^ and * are supported`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (workspaceVersions?.[name] == null) {
|
|
38
|
+
throw new Error(`Cannot replace workspace: dependency ${name} not found in workspace`);
|
|
39
|
+
}
|
|
40
|
+
if (fixedVersion != null) {
|
|
41
|
+
dependencies[name] = fixedVersion;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const workspaceVersion = workspaceVersions?.[name];
|
|
45
|
+
const depVersion = value === "workspace:*" ? workspaceVersion : `^${workspaceVersion}`;
|
|
46
|
+
dependencies[name] = depVersion;
|
|
58
47
|
}
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
if (value.startsWith("catalog:")) {
|
|
49
|
+
if (!rootPackageJson?.catalogs) throw new Error("catalogs are not available in the workspace root");
|
|
50
|
+
const catalogName = value.slice("catalog:".length);
|
|
51
|
+
const catalog = rootPackageJson.catalogs[catalogName];
|
|
52
|
+
if (catalog == null) throw new Error(`catalog ${catalogName} not found in the workspace root`);
|
|
53
|
+
if (catalog[name] == null) throw new Error(`catalog ${catalogName} does not contain ${name}`);
|
|
54
|
+
dependencies[name] = catalog[name];
|
|
62
55
|
}
|
|
63
|
-
const workspaceVersion = workspaceVersions?.[name];
|
|
64
|
-
const depVersion = value === "workspace:*" ? workspaceVersion : `^${workspaceVersion}`;
|
|
65
|
-
dependencies[name] = depVersion;
|
|
66
56
|
}
|
|
57
|
+
};
|
|
58
|
+
for (const field of rootFieldsToCopy) {
|
|
59
|
+
if (rootPackageJson?.[field] != null && packageJson[field] == null) {
|
|
60
|
+
packageJson[field] = rootPackageJson[field];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const newScripts = {};
|
|
64
|
+
if (packageJson.scripts && Array.isArray(packageJson.fuman?.keepScripts)) {
|
|
65
|
+
for (const script of packageJson.fuman.keepScripts) {
|
|
66
|
+
if (typeof script !== "string") continue;
|
|
67
|
+
if (script in packageJson.scripts) continue;
|
|
68
|
+
newScripts[script] = packageJson.scripts[script];
|
|
69
|
+
}
|
|
70
|
+
delete packageJson.keepScripts;
|
|
71
|
+
}
|
|
72
|
+
packageJson.scripts = newScripts;
|
|
73
|
+
delete packageJson.devDependencies;
|
|
74
|
+
delete packageJson.private;
|
|
75
|
+
if (packageJson.fuman?.distOnlyFields) {
|
|
76
|
+
Object.assign(packageJson, packageJson.fuman.distOnlyFields);
|
|
77
|
+
delete packageJson.distOnlyFields;
|
|
67
78
|
}
|
|
79
|
+
replaceCustomDependencies("dependencies");
|
|
80
|
+
replaceCustomDependencies("devDependencies");
|
|
81
|
+
replaceCustomDependencies("peerDependencies");
|
|
82
|
+
replaceCustomDependencies("optionalDependencies");
|
|
83
|
+
delete packageJson.typedoc;
|
|
84
|
+
delete packageJson.eslintConfig;
|
|
85
|
+
delete packageJson.eslintIgnore;
|
|
86
|
+
delete packageJson.prettier;
|
|
87
|
+
delete packageJson.fuman;
|
|
68
88
|
}
|
|
69
|
-
replaceWorkspaceDependencies("dependencies");
|
|
70
|
-
replaceWorkspaceDependencies("devDependencies");
|
|
71
|
-
replaceWorkspaceDependencies("peerDependencies");
|
|
72
|
-
replaceWorkspaceDependencies("optionalDependencies");
|
|
73
|
-
delete packageJson.typedoc;
|
|
74
|
-
delete packageJson.eslintConfig;
|
|
75
|
-
delete packageJson.eslintIgnore;
|
|
76
|
-
delete packageJson.prettier;
|
|
77
|
-
delete packageJson.fuman;
|
|
78
89
|
if (packageJson.exports != null) {
|
|
79
90
|
let exports = packageJson.exports;
|
|
80
91
|
if (typeof exports === "string") {
|
package/package-json/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuman/build",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
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": "^0.0.
|
|
11
|
-
"@fuman/io": "^0.0.
|
|
12
|
-
"@fuman/node": "^0.0.
|
|
13
|
-
"@fuman/utils": "^0.0.
|
|
10
|
+
"@fuman/fetch": "^0.0.4",
|
|
11
|
+
"@fuman/io": "^0.0.4",
|
|
12
|
+
"@fuman/node": "^0.0.4",
|
|
13
|
+
"@fuman/utils": "^0.0.4",
|
|
14
14
|
"cross-spawn": "^7.0.5",
|
|
15
15
|
"detect-indent": "^7.0.1",
|
|
16
16
|
"js-yaml": "^4.1.0",
|
|
17
17
|
"picomatch": "^4.0.2",
|
|
18
18
|
"semver": "^7.6.3",
|
|
19
19
|
"tinyglobby": "^0.2.6",
|
|
20
|
-
"zod": "^3.
|
|
20
|
+
"zod": "^3.0.0"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
+
"typedoc": ">=0.24.0",
|
|
23
24
|
"typescript": "^5.2.2",
|
|
24
|
-
"vite": "^5.4.0"
|
|
25
|
+
"vite": "^5.4.0 || ^6.0.0"
|
|
25
26
|
},
|
|
26
27
|
"exports": {
|
|
27
28
|
".": {
|
|
@@ -59,6 +60,11 @@
|
|
|
59
60
|
"bin": {
|
|
60
61
|
"fuman-build": "fuman-build.js"
|
|
61
62
|
},
|
|
63
|
+
"peerDependenciesMeta": {
|
|
64
|
+
"typedoc": {
|
|
65
|
+
"optional": true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
62
68
|
"author": "",
|
|
63
69
|
"repository": {
|
|
64
70
|
"type": "git",
|
|
@@ -10,12 +10,14 @@ export interface ProjectChangedFile {
|
|
|
10
10
|
}
|
|
11
11
|
export declare function findProjectChangedFiles(params: {
|
|
12
12
|
params?: VersioningOptions;
|
|
13
|
+
workspace?: WorkspacePackage[];
|
|
13
14
|
root?: string | URL;
|
|
14
15
|
since: string;
|
|
15
16
|
until?: string;
|
|
16
17
|
}): Promise<ProjectChangedFile[]>;
|
|
17
18
|
export declare function findProjectChangedPackages(params: {
|
|
18
19
|
params?: VersioningOptions;
|
|
20
|
+
workspace?: WorkspacePackage[];
|
|
19
21
|
root?: string | URL;
|
|
20
22
|
since: string;
|
|
21
23
|
until?: string;
|
|
@@ -29,10 +29,7 @@ async function findProjectChangedFiles(params) {
|
|
|
29
29
|
cwd: root
|
|
30
30
|
});
|
|
31
31
|
if (!changed.length) return [];
|
|
32
|
-
const packages = await collectPackageJsons(root);
|
|
33
|
-
for (const pkg of packages) {
|
|
34
|
-
pkg.path = relative(root, pkg.path);
|
|
35
|
-
}
|
|
32
|
+
const packages = (params.workspace ?? await collectPackageJsons(root)).map((pkg) => ({ ...pkg, path: relative(root, pkg.path) }));
|
|
36
33
|
const files = [];
|
|
37
34
|
const includeGlobs = include == null ? null : picomatch(include);
|
|
38
35
|
const excludeGlobs = exclude == null ? null : picomatch(exclude);
|
package/versioning/types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface ChangelogGeneratorParams {
|
|
|
9
9
|
commitFormatter?: (commit: CommitInfo, parsed: ConventionalCommit, files: string[]) => string;
|
|
10
10
|
packageCommitsFormatter?: (packageName: string, commits: Record<string, string>) => string;
|
|
11
11
|
}
|
|
12
|
+
/** settings for versioning manager */
|
|
12
13
|
export interface VersioningOptions {
|
|
13
14
|
/**
|
|
14
15
|
* globs of files changes to which to white-list (relative to package root)
|
package/vite/build-plugin.js
CHANGED
|
@@ -52,7 +52,8 @@ async function fumanBuild(params) {
|
|
|
52
52
|
packageDir: packageRoot,
|
|
53
53
|
packageName: asNonNull(ourPackageJson.name),
|
|
54
54
|
packageJson: ourPackageJson,
|
|
55
|
-
jsr: false
|
|
55
|
+
jsr: false,
|
|
56
|
+
typedoc: false
|
|
56
57
|
};
|
|
57
58
|
params.preparePackageJson?.(hookContext);
|
|
58
59
|
packageConfig?.preparePackageJson?.(hookContext);
|
package/vite/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { MaybePromise } from '@fuman/utils';
|
|
1
|
+
import { AnyToNever, MaybePromise } from '@fuman/utils';
|
|
2
|
+
import { TypeDocOptions } from 'typedoc';
|
|
2
3
|
import { Plugin, UserConfig } from 'vite';
|
|
3
4
|
import { BuildHookContext } from '../config.js';
|
|
4
5
|
import { JsrConfig } from '../jsr/config.js';
|
|
@@ -30,5 +31,7 @@ export interface CustomBuildConfigObject {
|
|
|
30
31
|
* time to do any final modifications to the package contents
|
|
31
32
|
*/
|
|
32
33
|
finalize?: (ctx: BuildHookContext) => MaybePromise<void>;
|
|
34
|
+
/** package-specific configuration for typedoc */
|
|
35
|
+
typedoc?: AnyToNever<Partial<TypeDocOptions>> | ((current: AnyToNever<Partial<TypeDocOptions>>) => AnyToNever<Partial<TypeDocOptions>>);
|
|
33
36
|
}
|
|
34
37
|
export type CustomBuildConfig = CustomBuildConfigObject | (() => CustomBuildConfigObject);
|