@mxpicture/build-api 0.2.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/dist/barrel/Barrel.d.ts +15 -0
- package/dist/barrel/Barrel.js +136 -0
- package/dist/barrel/index.d.ts +1 -0
- package/dist/barrel/index.js +2 -0
- package/dist/cleanup/Cleanup.d.ts +24 -0
- package/dist/cleanup/Cleanup.js +83 -0
- package/dist/cleanup/index.d.ts +1 -0
- package/dist/cleanup/index.js +2 -0
- package/dist/deps/FixWorkspaceDeps.d.ts +30 -0
- package/dist/deps/FixWorkspaceDeps.js +121 -0
- package/dist/deps/index.d.ts +1 -0
- package/dist/deps/index.js +2 -0
- package/dist/osInfo/index.d.ts +1 -0
- package/dist/osInfo/index.js +2 -0
- package/dist/osInfo/osInfo.common.d.ts +4 -0
- package/dist/osInfo/osInfo.common.js +56 -0
- package/dist/pkg/Pkg.d.ts +7 -0
- package/dist/pkg/Pkg.js +13 -0
- package/dist/pkg/index.d.ts +2 -0
- package/dist/pkg/index.js +3 -0
- package/dist/pkg/pkg.common.d.ts +5 -0
- package/dist/pkg/pkg.common.js +41 -0
- package/dist/scripts/fix-workspace-deps.d.ts +2 -0
- package/dist/scripts/fix-workspace-deps.js +16 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.js +8 -0
- package/dist/types/types.barrel.d.ts +11 -0
- package/dist/types/types.barrel.js +1 -0
- package/dist/types/types.cleanup.d.ts +8 -0
- package/dist/types/types.cleanup.js +1 -0
- package/dist/types/types.common.d.ts +25 -0
- package/dist/types/types.common.js +1 -0
- package/dist/types/types.deps.d.ts +8 -0
- package/dist/types/types.deps.js +10 -0
- package/dist/types/types.os.d.ts +7 -0
- package/dist/types/types.os.js +1 -0
- package/dist/types/types.package.d.ts +27 -0
- package/dist/types/types.package.js +1 -0
- package/dist/types/types.vscode.d.ts +36 -0
- package/dist/types/types.vscode.js +1 -0
- package/dist/types/types.workspace.d.ts +27 -0
- package/dist/types/types.workspace.js +6 -0
- package/dist/vscode/OSUser.d.ts +9 -0
- package/dist/vscode/OSUser.js +62 -0
- package/dist/vscode/VSCodeSettings.d.ts +10 -0
- package/dist/vscode/VSCodeSettings.js +41 -0
- package/dist/vscode/VSCodeWorkspace.d.ts +9 -0
- package/dist/vscode/VSCodeWorkspace.js +29 -0
- package/dist/vscode/common.vscode.d.ts +21 -0
- package/dist/vscode/common.vscode.js +65 -0
- package/dist/vscode/config.vscode.d.ts +2 -0
- package/dist/vscode/config.vscode.js +4 -0
- package/dist/vscode/index.d.ts +5 -0
- package/dist/vscode/index.js +6 -0
- package/dist/vscode/profiles.vscode.d.ts +5 -0
- package/dist/vscode/profiles.vscode.js +29 -0
- package/dist/vscode/storage.vscode.d.ts +3 -0
- package/dist/vscode/storage.vscode.js +15 -0
- package/dist/vscode/types.vscode.d.ts +37 -0
- package/dist/vscode/types.vscode.js +6 -0
- package/dist/vscode/vscode.config.d.ts +2 -0
- package/dist/vscode/vscode.config.js +4 -0
- package/dist/vscode/vscode.profiles.d.ts +5 -0
- package/dist/vscode/vscode.profiles.js +30 -0
- package/dist/vscode/vscode.settings.d.ts +3 -0
- package/dist/vscode/vscode.settings.js +26 -0
- package/dist/vscode/vscode.storage.d.ts +3 -0
- package/dist/vscode/vscode.storage.js +15 -0
- package/dist/vscode/vscode.workspace.d.ts +3 -0
- package/dist/vscode/vscode.workspace.js +14 -0
- package/dist/vscode/workspace.vscode.d.ts +11 -0
- package/dist/vscode/workspace.vscode.js +149 -0
- package/dist/workspace/IFixWorkspaceDeps.d.ts +22 -0
- package/dist/workspace/IFixWorkspaceDeps.js +118 -0
- package/dist/workspace/WorkspacePaths.d.ts +7 -0
- package/dist/workspace/WorkspacePaths.js +30 -0
- package/dist/workspace/fixWorkspaceDeps.d.ts +22 -0
- package/dist/workspace/fixWorkspaceDeps.js +118 -0
- package/dist/workspace/index.d.ts +2 -0
- package/dist/workspace/index.js +3 -0
- package/dist/workspace/workspace.common.d.ts +13 -0
- package/dist/workspace/workspace.common.js +152 -0
- package/dist/zod/index.d.ts +1 -0
- package/dist/zod/index.js +2 -0
- package/dist/zod/zod.package.d.ts +9 -0
- package/dist/zod/zod.package.js +8 -0
- package/package.json +45 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BarrelGroup, BarrelResult } from "../types/types.barrel.js";
|
|
2
|
+
export declare const DEFAULT_EXCLUDED_PATTERNS: RegExp[];
|
|
3
|
+
export declare const DEFAULT_HEADER = "// This file is auto-generated. Do not edit manually.\n";
|
|
4
|
+
export declare class Barrel {
|
|
5
|
+
readonly packagesDir: string;
|
|
6
|
+
protected readonly excludes: RegExp[];
|
|
7
|
+
protected readonly fileHeader: string;
|
|
8
|
+
constructor(packagesDir: string, excludes?: RegExp[], fileHeader?: string);
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
protected isExcluded(fileName: string): boolean;
|
|
11
|
+
protected persistBarrel(group: BarrelGroup): Promise<BarrelGroup>;
|
|
12
|
+
protected updatePackageExports(packageDir: string, packageJsonPath: string, exports: Record<string, string>): Promise<void>;
|
|
13
|
+
protected hasExportsChanged(a: Record<string, string> | undefined, b: Record<string, string> | undefined): boolean;
|
|
14
|
+
protected extractExports(result: BarrelResult): Record<string, string>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { basename, dirname, join, relative } from "node:path";
|
|
2
|
+
import { readdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { Pkg } from "../pkg/Pkg.js";
|
|
4
|
+
// /** File patterns to exclude from barrel exports */
|
|
5
|
+
export const DEFAULT_EXCLUDED_PATTERNS = [
|
|
6
|
+
/\.test\.ts$/,
|
|
7
|
+
/\.spec\.ts$/,
|
|
8
|
+
/\.d\.ts$/,
|
|
9
|
+
/index\.ts$/,
|
|
10
|
+
/(.+\/|^)src\/(.+\/|)scripts?\/.+\.m?ts$/,
|
|
11
|
+
/\/4testing(\/|$)/,
|
|
12
|
+
];
|
|
13
|
+
// /** Header comment added to every generated barrel file */
|
|
14
|
+
export const DEFAULT_HEADER = "// This file is auto-generated. Do not edit manually.\n";
|
|
15
|
+
export class Barrel {
|
|
16
|
+
packagesDir;
|
|
17
|
+
excludes;
|
|
18
|
+
fileHeader;
|
|
19
|
+
constructor(packagesDir, excludes, fileHeader) {
|
|
20
|
+
this.packagesDir = packagesDir;
|
|
21
|
+
this.excludes = excludes ?? DEFAULT_EXCLUDED_PATTERNS;
|
|
22
|
+
this.fileHeader = fileHeader ?? DEFAULT_HEADER;
|
|
23
|
+
}
|
|
24
|
+
async run() {
|
|
25
|
+
const packageDirs = (await readdir(this.packagesDir)).map((p) => join(this.packagesDir, p));
|
|
26
|
+
const promises = [];
|
|
27
|
+
for (const packageDir of packageDirs) {
|
|
28
|
+
try {
|
|
29
|
+
const srcDirPath = join(packageDir, "src");
|
|
30
|
+
const packageJsonPath = join(packageDir, "package.json");
|
|
31
|
+
const items = (await readdir(srcDirPath, { recursive: true })).sort();
|
|
32
|
+
let currentGroup;
|
|
33
|
+
for (const item of items) {
|
|
34
|
+
const filename = basename(item);
|
|
35
|
+
const dirPath = join(srcDirPath, dirname(item));
|
|
36
|
+
const filePath = join(dirPath, filename);
|
|
37
|
+
if (dirPath !== currentGroup?.dirPath) {
|
|
38
|
+
if (currentGroup)
|
|
39
|
+
promises.push(this.persistBarrel({ ...currentGroup }));
|
|
40
|
+
currentGroup = {
|
|
41
|
+
dirPath,
|
|
42
|
+
files: [],
|
|
43
|
+
packageDir,
|
|
44
|
+
packageJsonPath,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (this.isExcluded(filePath) ||
|
|
48
|
+
(!filename.endsWith(".ts") && !filename.endsWith(".mts")))
|
|
49
|
+
continue;
|
|
50
|
+
currentGroup.files.push(filename);
|
|
51
|
+
}
|
|
52
|
+
if (currentGroup)
|
|
53
|
+
promises.push(this.persistBarrel({ ...currentGroup }));
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const barrelGroups = (await Promise.all(promises)).filter((prom) => prom.files.length > 0);
|
|
60
|
+
const results = [];
|
|
61
|
+
for (const barrelGroup of barrelGroups) {
|
|
62
|
+
let found = results.find((res) => barrelGroup.packageDir === res.packageDir);
|
|
63
|
+
if (!found) {
|
|
64
|
+
found = {
|
|
65
|
+
barrelDirs: [],
|
|
66
|
+
packageDir: barrelGroup.packageDir,
|
|
67
|
+
packageJsonPath: barrelGroup.packageJsonPath,
|
|
68
|
+
};
|
|
69
|
+
results.push(found);
|
|
70
|
+
}
|
|
71
|
+
found.barrelDirs.push(barrelGroup.dirPath);
|
|
72
|
+
}
|
|
73
|
+
await Promise.all(results.map(async (res) => this.updatePackageExports(res.packageDir, res.packageJsonPath, this.extractExports(res))));
|
|
74
|
+
}
|
|
75
|
+
isExcluded(fileName) {
|
|
76
|
+
return this.excludes.some((pattern) => pattern.test(fileName));
|
|
77
|
+
}
|
|
78
|
+
async persistBarrel(group) {
|
|
79
|
+
const barrelPath = join(group.dirPath, "index.ts");
|
|
80
|
+
// no files --> skip/delete index.ts
|
|
81
|
+
if (group.files.length === 0) {
|
|
82
|
+
await rm(barrelPath, { recursive: true, force: true });
|
|
83
|
+
return group;
|
|
84
|
+
}
|
|
85
|
+
const content = `${this.fileHeader}${group.files
|
|
86
|
+
.sort()
|
|
87
|
+
.map((f) => `export * from "./${basename(f, ".ts")}.js";`)
|
|
88
|
+
.join("\n")}\n`;
|
|
89
|
+
await writeFile(barrelPath, content);
|
|
90
|
+
return group;
|
|
91
|
+
}
|
|
92
|
+
async updatePackageExports(packageDir, packageJsonPath, exports) {
|
|
93
|
+
try {
|
|
94
|
+
const pkgJson = new Pkg(packageJsonPath);
|
|
95
|
+
const pkgName = relative(this.packagesDir, packageDir);
|
|
96
|
+
console.log(`📦 updating ${pkgName} package.json ...`);
|
|
97
|
+
const pkg = await pkgJson.readJson();
|
|
98
|
+
if (!this.hasExportsChanged(exports, pkg.exports)) {
|
|
99
|
+
console.log(`🧹 No changes in ${pkgName}, nothing to do`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
pkg.exports = { ...exports };
|
|
103
|
+
await pkgJson.writeJson(pkg);
|
|
104
|
+
console.log(`✅ ${pkgName} update successful`);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
console.log(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
hasExportsChanged(a, b) {
|
|
111
|
+
if (!a)
|
|
112
|
+
a = {};
|
|
113
|
+
if (!b)
|
|
114
|
+
b = {};
|
|
115
|
+
if (Object.keys(a).length !== Object.keys(b).length)
|
|
116
|
+
return true;
|
|
117
|
+
if (!a && !b)
|
|
118
|
+
return false;
|
|
119
|
+
if (!a || !b)
|
|
120
|
+
return true;
|
|
121
|
+
for (const entryA of Object.entries(a)) {
|
|
122
|
+
if (b[entryA[0]] !== entryA[1])
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
extractExports(result) {
|
|
128
|
+
const record = {};
|
|
129
|
+
for (const barrelDir of result.barrelDirs) {
|
|
130
|
+
const ex = relative(join(result.packageDir, "src"), barrelDir);
|
|
131
|
+
record[`./${ex}`] = `./dist/${ex}/index.js`;
|
|
132
|
+
}
|
|
133
|
+
record["./package.json"] = "./package.json";
|
|
134
|
+
return record;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Barrel.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ToBeDeleted, ToCleanup } from "../types/types.cleanup.js";
|
|
2
|
+
import { WorkspacePaths } from "../workspace/WorkspacePaths.js";
|
|
3
|
+
import { Logger } from "../types/types.workspace.js";
|
|
4
|
+
export interface CleanupParams {
|
|
5
|
+
repoRoot: string;
|
|
6
|
+
workspacesName?: string;
|
|
7
|
+
logger?: Logger;
|
|
8
|
+
toBeDeleted?: ToBeDeleted[];
|
|
9
|
+
}
|
|
10
|
+
export declare const runCleanup: (params: CleanupParams) => Promise<void>;
|
|
11
|
+
export declare class Cleanup {
|
|
12
|
+
protected readonly paths: WorkspacePaths;
|
|
13
|
+
protected readonly log: Logger;
|
|
14
|
+
protected readonly toBeDeleted: ToBeDeleted[];
|
|
15
|
+
constructor(paths: WorkspacePaths, log: Logger, toBeDeleted: ToBeDeleted[]);
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
read(): Promise<ToCleanup[]>;
|
|
18
|
+
cleanup(toCleanups: ToCleanup[]): Promise<void>;
|
|
19
|
+
cleanupSingle(toCleanup: ToCleanup): Promise<void>;
|
|
20
|
+
protected readDir(dir: string): Promise<ToCleanup[]>;
|
|
21
|
+
protected buildRemovePaths(basePath: string): ToCleanup[];
|
|
22
|
+
protected move(toCleanup: ToCleanup): Promise<void>;
|
|
23
|
+
protected remove(toCleanup: ToCleanup): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { readdir, rename, rm } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { WorkspacePaths } from "../workspace/WorkspacePaths.js";
|
|
4
|
+
// moveSuffix: e.g. mv node_modules node_modules_tmp && rm -rf node_modules_tmp (async)
|
|
5
|
+
const DEFAULT_TO_BE_DELETED = [
|
|
6
|
+
{ name: "node_modules", moveSuffix: "_tmp" },
|
|
7
|
+
{ name: "dist", moveSuffix: "_tmp" },
|
|
8
|
+
{ name: "tsconfig.tsbuildinfo" },
|
|
9
|
+
{ name: ".tsbuildinfo" },
|
|
10
|
+
];
|
|
11
|
+
export const runCleanup = async (params) => new Cleanup(WorkspacePaths.instance(params.repoRoot, params.workspacesName), params.logger ?? (() => { }), params.toBeDeleted ?? DEFAULT_TO_BE_DELETED).run();
|
|
12
|
+
export class Cleanup {
|
|
13
|
+
paths;
|
|
14
|
+
log;
|
|
15
|
+
toBeDeleted;
|
|
16
|
+
constructor(paths, log, toBeDeleted) {
|
|
17
|
+
this.paths = paths;
|
|
18
|
+
this.log = log;
|
|
19
|
+
this.toBeDeleted = toBeDeleted;
|
|
20
|
+
}
|
|
21
|
+
async run() {
|
|
22
|
+
const items = await this.read();
|
|
23
|
+
return this.cleanup(items);
|
|
24
|
+
}
|
|
25
|
+
async read() {
|
|
26
|
+
const dirs = await readdir(this.paths.workspacesDir);
|
|
27
|
+
const toCleanupsTmp = await Promise.all(dirs.map((dir) => this.readDir(dir)));
|
|
28
|
+
const toCleanups = this.buildRemovePaths(this.paths.repoRoot);
|
|
29
|
+
for (const tmp of toCleanupsTmp)
|
|
30
|
+
toCleanups.push(...tmp);
|
|
31
|
+
return toCleanups;
|
|
32
|
+
}
|
|
33
|
+
async cleanup(toCleanups) {
|
|
34
|
+
await Promise.all(toCleanups.map(async (x) => this.cleanupSingle(x)));
|
|
35
|
+
}
|
|
36
|
+
async cleanupSingle(toCleanup) {
|
|
37
|
+
this.log(`🧹 Cleanup started ${toCleanup.name} ...`);
|
|
38
|
+
try {
|
|
39
|
+
if (!toCleanup.moveTo) {
|
|
40
|
+
await this.remove(toCleanup);
|
|
41
|
+
this.log(`✅ ${toCleanup.name} removed sucessfully`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
this.log(`📦 Moving ${toCleanup.name} to ${toCleanup.name}${toCleanup.moveSuffix}`);
|
|
45
|
+
await this.move(toCleanup);
|
|
46
|
+
this.log(`📦 Start async removing ${toCleanup.name} (${toCleanup.name}${toCleanup.moveSuffix})`);
|
|
47
|
+
this.remove(toCleanup)
|
|
48
|
+
.then(() => this.log(`✅ ${toCleanup.name} (async) removed sucessfully`))
|
|
49
|
+
.catch((e) => {
|
|
50
|
+
this.log(`❌ Removing ${toCleanup.name} (async) failed ${e}`);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
this.log(`❌ Removing ${toCleanup.name} failed ${error}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async readDir(dir) {
|
|
58
|
+
const packgeDir = join(this.paths.workspacesDir, dir);
|
|
59
|
+
if (!(await this.paths.workspaceByPath(packgeDir)))
|
|
60
|
+
return [];
|
|
61
|
+
return this.buildRemovePaths(packgeDir);
|
|
62
|
+
}
|
|
63
|
+
buildRemovePaths(basePath) {
|
|
64
|
+
return this.toBeDeleted.map((d) => {
|
|
65
|
+
const path = join(basePath, d.name);
|
|
66
|
+
return {
|
|
67
|
+
...d,
|
|
68
|
+
path,
|
|
69
|
+
moveTo: d.moveSuffix ? `${path}${d.moveSuffix}` : undefined,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async move(toCleanup) {
|
|
74
|
+
if (toCleanup.moveTo)
|
|
75
|
+
return rename(toCleanup.path, toCleanup.moveTo);
|
|
76
|
+
}
|
|
77
|
+
async remove(toCleanup) {
|
|
78
|
+
return rm(toCleanup.moveTo ?? toCleanup.path, {
|
|
79
|
+
force: true,
|
|
80
|
+
recursive: true,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Cleanup.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DepsProcessMode, DepsReplacementMode } from "../types/types.deps.js";
|
|
2
|
+
import { FixWorkspaceDepsMain, FixWorkspaceDepsParams } from "../types/types.workspace.js";
|
|
3
|
+
export declare const runFixDeps: (p: {
|
|
4
|
+
repoRoot: string;
|
|
5
|
+
mode: DepsProcessMode;
|
|
6
|
+
replacement: DepsReplacementMode;
|
|
7
|
+
}) => Promise<void>;
|
|
8
|
+
export declare const instanceFixDeps: (p: {
|
|
9
|
+
repoRoot: string;
|
|
10
|
+
mode: DepsProcessMode;
|
|
11
|
+
replacement: DepsReplacementMode;
|
|
12
|
+
}) => FixWorkspaceDepsVersion | FixWorkspaceDepsFile;
|
|
13
|
+
export declare abstract class IFixWorkspaceDeps {
|
|
14
|
+
readonly repoRoot: string;
|
|
15
|
+
readonly mode: DepsProcessMode;
|
|
16
|
+
constructor(repoRoot: string, mode: DepsProcessMode);
|
|
17
|
+
protected abstract fixVersion(p: FixWorkspaceDepsParams): string | null;
|
|
18
|
+
protected abstract restoreVersion(p: FixWorkspaceDepsParams): string | null;
|
|
19
|
+
run(): Promise<void>;
|
|
20
|
+
protected handleDependencies(deps: Record<string, string> | undefined, p: FixWorkspaceDepsMain): boolean;
|
|
21
|
+
protected runSingle(p: FixWorkspaceDepsMain): boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare class FixWorkspaceDepsVersion extends IFixWorkspaceDeps {
|
|
24
|
+
protected fixVersion(p: FixWorkspaceDepsParams): string | null;
|
|
25
|
+
protected restoreVersion(p: FixWorkspaceDepsParams): string | null;
|
|
26
|
+
}
|
|
27
|
+
export declare class FixWorkspaceDepsFile extends IFixWorkspaceDeps {
|
|
28
|
+
protected fixVersion(p: FixWorkspaceDepsParams): string | null;
|
|
29
|
+
protected restoreVersion(p: FixWorkspaceDepsParams): string | null;
|
|
30
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { DepsReplacementMode } from "../types/types.deps.js";
|
|
2
|
+
import { buildMapEntries, readPackageJsons, writePackageJsons, } from "../workspace/workspace.common.js";
|
|
3
|
+
export const runFixDeps = async (p) => instanceFixDeps(p).run();
|
|
4
|
+
export const instanceFixDeps = (p) => p.replacement === DepsReplacementMode.version
|
|
5
|
+
? new FixWorkspaceDepsVersion(p.repoRoot, p.mode)
|
|
6
|
+
: new FixWorkspaceDepsFile(p.repoRoot, p.mode);
|
|
7
|
+
export class IFixWorkspaceDeps {
|
|
8
|
+
repoRoot;
|
|
9
|
+
mode;
|
|
10
|
+
constructor(repoRoot, mode) {
|
|
11
|
+
this.repoRoot = repoRoot;
|
|
12
|
+
this.mode = mode;
|
|
13
|
+
}
|
|
14
|
+
async run() {
|
|
15
|
+
if (this.mode === "fix")
|
|
16
|
+
console.log("🔧 Fixing workspace dependencies...\n");
|
|
17
|
+
else
|
|
18
|
+
console.log("🔧 Restoring workspace dependencies...\n");
|
|
19
|
+
const pkgs = await readPackageJsons(this.repoRoot);
|
|
20
|
+
const mapEntries = buildMapEntries(pkgs);
|
|
21
|
+
const versionMap = new Map();
|
|
22
|
+
const workspacePackages = new Set();
|
|
23
|
+
for (const pkg of pkgs) {
|
|
24
|
+
versionMap.set(pkg.content.name, pkg.content.version);
|
|
25
|
+
workspacePackages.add(pkg.content.name);
|
|
26
|
+
}
|
|
27
|
+
console.log("📋 Version map:");
|
|
28
|
+
for (const map of mapEntries)
|
|
29
|
+
console.log(` ${map.fromPkg.content.name} --> ${map.toPkg.content.name}: ${map.relPath}`);
|
|
30
|
+
console.log();
|
|
31
|
+
for (const consumingPkg of pkgs) {
|
|
32
|
+
console.log(`📦 Processing ${consumingPkg.content.name}...`);
|
|
33
|
+
try {
|
|
34
|
+
consumingPkg.modified = this.runSingle({
|
|
35
|
+
consumingPkg,
|
|
36
|
+
mapEntries,
|
|
37
|
+
versionMap,
|
|
38
|
+
workspacePackages,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
console.error(`\nError processing ${consumingPkg.content.name}:`, err);
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
await writePackageJsons(pkgs);
|
|
47
|
+
if (this.mode === "fix")
|
|
48
|
+
console.log("✅ Done fixing workspace dependencies!");
|
|
49
|
+
else
|
|
50
|
+
console.log("✅ Done restoring workspace dependencies!");
|
|
51
|
+
}
|
|
52
|
+
// Replace workspace:* with file:...
|
|
53
|
+
handleDependencies(deps, p) {
|
|
54
|
+
if (!deps)
|
|
55
|
+
return false;
|
|
56
|
+
const handler = this.mode === "fix" ? this.fixVersion : this.restoreVersion;
|
|
57
|
+
let modified = false;
|
|
58
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
59
|
+
const newVersion = handler({ ...p, pkg: name, version });
|
|
60
|
+
if (!newVersion)
|
|
61
|
+
continue;
|
|
62
|
+
console.log(` ✓ Replaced ${name}: ${version} → ${newVersion}`);
|
|
63
|
+
deps[name] = newVersion;
|
|
64
|
+
modified = true;
|
|
65
|
+
}
|
|
66
|
+
return modified;
|
|
67
|
+
}
|
|
68
|
+
runSingle(p) {
|
|
69
|
+
let modified = false;
|
|
70
|
+
modified =
|
|
71
|
+
this.handleDependencies(p.consumingPkg.content.dependencies, p) ||
|
|
72
|
+
modified;
|
|
73
|
+
modified =
|
|
74
|
+
this.handleDependencies(p.consumingPkg.content.devDependencies, p) ||
|
|
75
|
+
modified;
|
|
76
|
+
modified =
|
|
77
|
+
this.handleDependencies(p.consumingPkg.content.peerDependencies, p) ||
|
|
78
|
+
modified;
|
|
79
|
+
return modified;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class FixWorkspaceDepsVersion extends IFixWorkspaceDeps {
|
|
83
|
+
fixVersion(p) {
|
|
84
|
+
if (p.version !== "workspace:*")
|
|
85
|
+
return null;
|
|
86
|
+
const actualVersion = p.versionMap.get(p.pkg);
|
|
87
|
+
if (!actualVersion) {
|
|
88
|
+
console.error(` ERROR: Could not find version for workspace dependency ${p.pkg}`);
|
|
89
|
+
throw new Error(`Cannot resolve workspace dependency: ${p.pkg}`);
|
|
90
|
+
}
|
|
91
|
+
return `^${actualVersion}`;
|
|
92
|
+
}
|
|
93
|
+
restoreVersion(p) {
|
|
94
|
+
if (p.workspacePackages.has(p.pkg) && p.version.startsWith("^")) {
|
|
95
|
+
// Verify the version matches what fix script would have created
|
|
96
|
+
const actualVersion = p.versionMap.get(p.pkg);
|
|
97
|
+
if (actualVersion && p.version === `^${actualVersion}`) {
|
|
98
|
+
return "workspace:*";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export class FixWorkspaceDepsFile extends IFixWorkspaceDeps {
|
|
105
|
+
fixVersion(p) {
|
|
106
|
+
if (p.version !== "workspace:*")
|
|
107
|
+
return null;
|
|
108
|
+
const mapEntry = p.mapEntries.find((mapEntry) => mapEntry.fromPkg.content.name === p.consumingPkg.content.name &&
|
|
109
|
+
mapEntry.toPkg.content.name === p.pkg);
|
|
110
|
+
if (!mapEntry) {
|
|
111
|
+
console.error(` ERROR: Could not find version for workspace dependency ${p.pkg}`);
|
|
112
|
+
throw new Error(`Cannot resolve workspace dependency: ${p.pkg}`);
|
|
113
|
+
}
|
|
114
|
+
return `file:${mapEntry.relPath}`;
|
|
115
|
+
}
|
|
116
|
+
restoreVersion(p) {
|
|
117
|
+
if (!p.version.startsWith("file:"))
|
|
118
|
+
return null;
|
|
119
|
+
return "workspace:*";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./FixWorkspaceDeps.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./osInfo.common.js";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { join, sep } from "path";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
let __info = null;
|
|
5
|
+
export const osInfo = () => {
|
|
6
|
+
if (!__info) {
|
|
7
|
+
const isWSL = os.release().toLowerCase().includes("microsoft");
|
|
8
|
+
__info = isWSL ? wslInfo() : defaultInfo();
|
|
9
|
+
if (!__info)
|
|
10
|
+
throw new Error("Load OS info failed");
|
|
11
|
+
}
|
|
12
|
+
return __info;
|
|
13
|
+
};
|
|
14
|
+
export const defaultInfo = () => {
|
|
15
|
+
const platform = process.platform;
|
|
16
|
+
const homedir = os.homedir();
|
|
17
|
+
const configDirParts = [];
|
|
18
|
+
if (platform === "win32") {
|
|
19
|
+
if (process.env.APPDATA)
|
|
20
|
+
configDirParts.push(process.env.APPDATA);
|
|
21
|
+
}
|
|
22
|
+
else if (platform === "darwin") {
|
|
23
|
+
configDirParts.push(homedir, "Library", "Application Support");
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
configDirParts.push(homedir, ".config");
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
username: os.userInfo().username,
|
|
30
|
+
homedir,
|
|
31
|
+
platform,
|
|
32
|
+
configDir: join(...configDirParts),
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export const wslInfo = () => {
|
|
36
|
+
const whoamiParts = execSync("whoami.exe").toString().split(sep);
|
|
37
|
+
if (whoamiParts.length === 0)
|
|
38
|
+
throw new Error("Windows user could not be determined");
|
|
39
|
+
// const winUser = process.env["WINUSER"] || process.env["USER"];
|
|
40
|
+
const platform = process.platform;
|
|
41
|
+
let username = whoamiParts[whoamiParts.length - 1];
|
|
42
|
+
// remove AD group
|
|
43
|
+
const userParts = username.split("\\");
|
|
44
|
+
username = userParts[userParts.length - 1];
|
|
45
|
+
username = username.replace("\r", "").replace("\n", "");
|
|
46
|
+
const parts = ["/mnt", "c", "Users", username];
|
|
47
|
+
const homedir = join(...parts);
|
|
48
|
+
const configDir = join(homedir, "AppData", "Roaming");
|
|
49
|
+
return {
|
|
50
|
+
username,
|
|
51
|
+
homedir,
|
|
52
|
+
configDir,
|
|
53
|
+
platform,
|
|
54
|
+
isWSL: true,
|
|
55
|
+
};
|
|
56
|
+
};
|
package/dist/pkg/Pkg.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
export class Pkg {
|
|
3
|
+
packageJsonPath;
|
|
4
|
+
constructor(packageJsonPath) {
|
|
5
|
+
this.packageJsonPath = packageJsonPath;
|
|
6
|
+
}
|
|
7
|
+
async readJson() {
|
|
8
|
+
return JSON.parse(await readFile(this.packageJsonPath, "utf8"));
|
|
9
|
+
}
|
|
10
|
+
async writeJson(pkg) {
|
|
11
|
+
return writeFile(this.packageJsonPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { PackageVersion } from "../types/types.package.js";
|
|
2
|
+
export declare const splitVersion: (version: string) => PackageVersion;
|
|
3
|
+
export declare const concatVersion: (version: PackageVersion) => string;
|
|
4
|
+
export declare const compareVersions: (a: PackageVersion | string, b: PackageVersion | string) => number;
|
|
5
|
+
export declare const compareVersionsGT: (a: PackageVersion | string, b: PackageVersion | string) => boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export const splitVersion = (version) => {
|
|
2
|
+
const parts = version.split(".");
|
|
3
|
+
let major = parts.shift();
|
|
4
|
+
const prefix = major.startsWith("v") ? "v" : null;
|
|
5
|
+
if (major.startsWith("v"))
|
|
6
|
+
major = major.substring(1);
|
|
7
|
+
const minor = parts.shift();
|
|
8
|
+
const patch = parts.shift();
|
|
9
|
+
return {
|
|
10
|
+
major: Number(major),
|
|
11
|
+
minor: minor ? Number(minor) : null,
|
|
12
|
+
patch: patch ? Number(patch) : null,
|
|
13
|
+
prefix,
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export const concatVersion = (version) => {
|
|
17
|
+
let result = version.major.toString();
|
|
18
|
+
if (version.prefix)
|
|
19
|
+
result = version.prefix + result;
|
|
20
|
+
if (version.minor)
|
|
21
|
+
result += "." + version.minor.toString();
|
|
22
|
+
if (version.patch)
|
|
23
|
+
result += "." + version.patch.toString();
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
export const compareVersions = (a, b) => {
|
|
27
|
+
a = typeof a === "string" ? splitVersion(a) : a;
|
|
28
|
+
b = typeof b === "string" ? splitVersion(b) : b;
|
|
29
|
+
if (a.major !== b.major)
|
|
30
|
+
return a.major - b.major;
|
|
31
|
+
if (a.minor === null || b.minor === null)
|
|
32
|
+
return 0;
|
|
33
|
+
if (a.minor !== b.minor)
|
|
34
|
+
return a.minor - b.minor;
|
|
35
|
+
if (a.patch === null || b.patch === null)
|
|
36
|
+
return 0;
|
|
37
|
+
if (a.patch !== b.patch)
|
|
38
|
+
return a.patch - b.patch;
|
|
39
|
+
return 0;
|
|
40
|
+
};
|
|
41
|
+
export const compareVersionsGT = (a, b) => compareVersions(a, b) > 0;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
import { Argument, program } from "@commander-js/extra-typings";
|
|
3
|
+
import { argv, cwd } from "node:process";
|
|
4
|
+
import { isAbsolute, join } from "node:path";
|
|
5
|
+
import { runFixDepsByVersion } from "../deps/FixWorkspaceDeps.js";
|
|
6
|
+
// todo integrate into cli and use it --> thats fine because it only gets executed after build
|
|
7
|
+
program
|
|
8
|
+
.version("1.0.0")
|
|
9
|
+
.description("Fix/restore workspace dependencies CLI")
|
|
10
|
+
.addArgument(new Argument("<mode>", "fix / restore").choices(["fix", "restore"]))
|
|
11
|
+
.addArgument(new Argument("<repoRoot>", "Repos root path"))
|
|
12
|
+
.action(async (mode, repoRoot) => {
|
|
13
|
+
const root = isAbsolute(repoRoot) ? repoRoot : join(cwd(), repoRoot);
|
|
14
|
+
await runFixDepsByVersion(root, mode);
|
|
15
|
+
});
|
|
16
|
+
program.parse(argv);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// This file is auto-generated. Do not edit manually.
|
|
2
|
+
export * from "./types.barrel.js";
|
|
3
|
+
export * from "./types.cleanup.js";
|
|
4
|
+
export * from "./types.deps.js";
|
|
5
|
+
export * from "./types.os.js";
|
|
6
|
+
export * from "./types.package.js";
|
|
7
|
+
export * from "./types.vscode.js";
|
|
8
|
+
export * from "./types.workspace.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|