@emeryld/manager 0.6.2 → 0.6.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/create-package/index.js +28 -132
- package/dist/create-package/shared.js +1 -0
- package/dist/create-package/variants/contract.js +1 -1
- package/dist/create-package/variants/fullstack.js +2 -2
- package/dist/helper-cli/colors.js +7 -0
- package/dist/helper-cli/display.js +49 -0
- package/dist/helper-cli/env.js +14 -0
- package/dist/helper-cli/pagination.js +41 -0
- package/dist/helper-cli/prompts.js +229 -0
- package/dist/helper-cli/runner.js +59 -0
- package/dist/helper-cli/scripts.js +47 -0
- package/dist/helper-cli/ts-node.js +10 -0
- package/dist/helper-cli/types.js +1 -0
- package/dist/helper-cli.js +9 -268
- package/dist/menu/script-helpers.js +178 -0
- package/dist/menu.js +78 -19
- package/dist/packages.js +6 -150
- package/dist/utils/colors.js +1 -10
- package/dist/utils/run.js +4 -4
- package/dist/workspace.js +88 -14
- package/package.json +1 -1
package/dist/menu.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
// src/menu.js
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { colors, globalEmoji } from './utils/log.js';
|
|
4
|
-
import { updateDependencies, testAll, testSingle, buildAll, buildSingle, } from './workspace.js';
|
|
4
|
+
import { updateDependencies, testAll, testSingle, buildAll, buildSingle, cleanPackages, rebuildPackages, } from './workspace.js';
|
|
5
5
|
import { releaseMultiple, releaseSingle } from './release.js';
|
|
6
6
|
import { getOrderedPackages } from './packages.js';
|
|
7
7
|
import { runHelperCli } from './helper-cli.js';
|
|
8
8
|
import { ensureWorkingTreeCommitted } from './preflight.js';
|
|
9
9
|
import { openDockerHelper } from './docker.js';
|
|
10
10
|
import { run } from './utils/run.js';
|
|
11
|
+
import { makeBaseScriptEntries, getPackageMarker } from './menu/script-helpers.js';
|
|
11
12
|
function makeManagerStepEntries(targets, packages, state, options) {
|
|
12
13
|
const includeBack = options?.includeBack ?? true;
|
|
13
14
|
return [
|
|
@@ -20,6 +21,24 @@ function makeManagerStepEntries(targets, packages, state, options) {
|
|
|
20
21
|
state.lastStep = 'update';
|
|
21
22
|
},
|
|
22
23
|
},
|
|
24
|
+
{
|
|
25
|
+
name: 'clean',
|
|
26
|
+
emoji: '🧹',
|
|
27
|
+
description: 'Remove node_modules, dist, and caches',
|
|
28
|
+
handler: async () => {
|
|
29
|
+
await cleanPackages(targets);
|
|
30
|
+
state.lastStep = 'clean';
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'rebuild',
|
|
35
|
+
emoji: '🔁',
|
|
36
|
+
description: 'Clean then build',
|
|
37
|
+
handler: async () => {
|
|
38
|
+
await rebuildPackages(targets);
|
|
39
|
+
state.lastStep = 'rebuild';
|
|
40
|
+
},
|
|
41
|
+
},
|
|
23
42
|
{
|
|
24
43
|
name: 'test',
|
|
25
44
|
emoji: '🧪',
|
|
@@ -93,25 +112,32 @@ function makeManagerStepEntries(targets, packages, state, options) {
|
|
|
93
112
|
: []),
|
|
94
113
|
];
|
|
95
114
|
}
|
|
96
|
-
function
|
|
97
|
-
const scripts = pkg.json?.scripts ?? {};
|
|
98
|
-
const entries = [];
|
|
115
|
+
function makeDockerEntry(pkg) {
|
|
99
116
|
if (pkg.dockerfilePath) {
|
|
100
117
|
const dockerLabel = path
|
|
101
118
|
.relative(process.cwd(), pkg.dockerfilePath)
|
|
102
119
|
.replace(/\\/g, '/');
|
|
103
|
-
|
|
120
|
+
return {
|
|
104
121
|
name: `Dockerfile (${dockerLabel})`,
|
|
105
122
|
emoji: '🐳',
|
|
106
123
|
description: 'manager -> opens the docker cli',
|
|
107
124
|
handler: async () => {
|
|
108
125
|
await openDockerHelper(pkg);
|
|
109
126
|
},
|
|
110
|
-
}
|
|
127
|
+
};
|
|
111
128
|
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
function makePackageScriptEntries(pkg) {
|
|
132
|
+
const scripts = pkg.json?.scripts ?? {};
|
|
133
|
+
const baseEntries = makeBaseScriptEntries(pkg);
|
|
134
|
+
const baseNames = new Set(baseEntries.map((entry) => entry.name));
|
|
135
|
+
const entries = [];
|
|
112
136
|
Object.entries(scripts)
|
|
113
137
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
114
138
|
.forEach(([name, command]) => {
|
|
139
|
+
if (baseNames.has(name))
|
|
140
|
+
return;
|
|
115
141
|
entries.push({
|
|
116
142
|
name,
|
|
117
143
|
emoji: '▶️',
|
|
@@ -121,23 +147,31 @@ function makePackageScriptEntries(pkg) {
|
|
|
121
147
|
},
|
|
122
148
|
});
|
|
123
149
|
});
|
|
124
|
-
return entries;
|
|
150
|
+
return [...baseEntries, ...entries];
|
|
125
151
|
}
|
|
126
152
|
export function buildPackageSelectionMenu(packages, onStepComplete) {
|
|
127
153
|
const ordered = getOrderedPackages(packages);
|
|
128
|
-
const entries = ordered.map((pkg) =>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
154
|
+
const entries = ordered.map((pkg) => {
|
|
155
|
+
const marker = getPackageMarker(pkg);
|
|
156
|
+
const pkgColor = pkg.color ?? 'cyan';
|
|
157
|
+
const descriptionMeta = pkg.relativeDir ?? pkg.dirName;
|
|
158
|
+
const markerHint = marker.label ? ` · ${marker.label}` : '';
|
|
159
|
+
return {
|
|
160
|
+
name: pkg.name ?? pkg.substitute ?? pkg.dirName,
|
|
161
|
+
emoji: marker.colorize('●'),
|
|
162
|
+
description: `${descriptionMeta}${colors.dim(markerHint)}`,
|
|
163
|
+
color: pkgColor,
|
|
164
|
+
handler: async () => {
|
|
165
|
+
const step = await runStepLoop([pkg], packages);
|
|
166
|
+
onStepComplete?.(step);
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
});
|
|
137
170
|
if (ordered.length === 0)
|
|
138
171
|
return entries;
|
|
139
172
|
entries.push({
|
|
140
173
|
name: 'All packages',
|
|
174
|
+
color: 'gray',
|
|
141
175
|
emoji: globalEmoji,
|
|
142
176
|
description: 'Select all packages',
|
|
143
177
|
handler: async () => {
|
|
@@ -154,10 +188,12 @@ export async function runStepLoop(targets, packages) {
|
|
|
154
188
|
// Single package: show combined menu (manager actions + package.json scripts)
|
|
155
189
|
if (targets.length === 1) {
|
|
156
190
|
const pkg = targets[0];
|
|
191
|
+
const dockerEntry = makeDockerEntry(pkg);
|
|
157
192
|
// eslint-disable-next-line no-constant-condition
|
|
158
193
|
while (true) {
|
|
159
194
|
const scriptEntries = makePackageScriptEntries(pkg);
|
|
160
195
|
const entries = [
|
|
196
|
+
...(dockerEntry ? [dockerEntry] : []),
|
|
161
197
|
{
|
|
162
198
|
name: 'manager actions',
|
|
163
199
|
emoji: globalEmoji,
|
|
@@ -170,9 +206,8 @@ export async function runStepLoop(targets, packages) {
|
|
|
170
206
|
{
|
|
171
207
|
name: 'back',
|
|
172
208
|
emoji: '↩️',
|
|
173
|
-
description: 'Return to package
|
|
209
|
+
description: 'Return to package menu',
|
|
174
210
|
handler: () => {
|
|
175
|
-
// no state change; just exit to the package scripts menu
|
|
176
211
|
state.lastStep = undefined;
|
|
177
212
|
},
|
|
178
213
|
},
|
|
@@ -184,7 +219,31 @@ export async function runStepLoop(targets, packages) {
|
|
|
184
219
|
});
|
|
185
220
|
},
|
|
186
221
|
},
|
|
187
|
-
|
|
222
|
+
{
|
|
223
|
+
name: 'package scripts',
|
|
224
|
+
emoji: '📜',
|
|
225
|
+
description: 'Run package.json scripts',
|
|
226
|
+
handler: async () => {
|
|
227
|
+
if (scriptEntries.length === 0) {
|
|
228
|
+
console.log(colors.yellow(`No package.json scripts found for ${pkg.name}.`));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const scriptsMenu = [
|
|
232
|
+
...scriptEntries,
|
|
233
|
+
{
|
|
234
|
+
name: 'back',
|
|
235
|
+
emoji: '↩️',
|
|
236
|
+
description: 'Return to package menu',
|
|
237
|
+
handler: () => { },
|
|
238
|
+
},
|
|
239
|
+
];
|
|
240
|
+
await runHelperCli({
|
|
241
|
+
title: `${pkg.name} scripts`,
|
|
242
|
+
scripts: scriptsMenu,
|
|
243
|
+
argv: [],
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
},
|
|
188
247
|
{
|
|
189
248
|
name: 'back',
|
|
190
249
|
emoji: '↩️',
|
package/dist/packages.js
CHANGED
|
@@ -1,161 +1,17 @@
|
|
|
1
1
|
// src/packages.js
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
4
|
+
import { colorFromSeed, deriveSubstitute, inferManifestFromWorkspace, loadWorkspaceManifest, mergeManifestEntries, normalizeManifestPath, } from './packages/manifest-utils.js';
|
|
5
5
|
const rootDir = process.cwd();
|
|
6
|
-
const ignoredDirs = new Set([
|
|
7
|
-
'node_modules',
|
|
8
|
-
'.git',
|
|
9
|
-
'.turbo',
|
|
10
|
-
'.next',
|
|
11
|
-
'dist',
|
|
12
|
-
'build',
|
|
13
|
-
'.cache',
|
|
14
|
-
'coverage',
|
|
15
|
-
]);
|
|
16
|
-
const colorPalette = ['cyan', 'green', 'yellow', 'magenta', 'red'];
|
|
17
6
|
let manifestState;
|
|
18
|
-
function manifestFilePath() {
|
|
19
|
-
return path.join(rootDir, 'scripts', 'packages.mjs');
|
|
20
|
-
}
|
|
21
|
-
function isManifestMissing(error) {
|
|
22
|
-
if (typeof error !== 'object' || error === null)
|
|
23
|
-
return false;
|
|
24
|
-
const code = error.code;
|
|
25
|
-
return code === 'ERR_MODULE_NOT_FOUND' || code === 'ENOENT';
|
|
26
|
-
}
|
|
27
|
-
function normalizeManifestPath(value) {
|
|
28
|
-
const absolute = path.resolve(rootDir, value || '');
|
|
29
|
-
let relative = path.relative(rootDir, absolute);
|
|
30
|
-
if (!relative)
|
|
31
|
-
return '.';
|
|
32
|
-
relative = relative.replace(/\\/g, '/');
|
|
33
|
-
return relative.replace(/^(?:\.\/)+/, '');
|
|
34
|
-
}
|
|
35
|
-
function colorFromSeed(seed) {
|
|
36
|
-
const normalized = `${seed}`.trim() || 'package';
|
|
37
|
-
let hash = 0;
|
|
38
|
-
for (let i = 0; i < normalized.length; i++) {
|
|
39
|
-
hash = (hash * 31 + normalized.charCodeAt(i)) >>> 0;
|
|
40
|
-
}
|
|
41
|
-
return colorPalette[hash % colorPalette.length];
|
|
42
|
-
}
|
|
43
|
-
function deriveSubstitute(name) {
|
|
44
|
-
const trimmed = (name || '').trim();
|
|
45
|
-
if (!trimmed)
|
|
46
|
-
return '';
|
|
47
|
-
const segments = trimmed.split(/[@\/\-]/).filter(Boolean);
|
|
48
|
-
const transformed = segments
|
|
49
|
-
.map((segment) => segment)
|
|
50
|
-
.filter(Boolean)
|
|
51
|
-
.join(' ');
|
|
52
|
-
return transformed || trimmed;
|
|
53
|
-
}
|
|
54
|
-
async function findPackageJsonFiles(baseDir) {
|
|
55
|
-
const results = new Set();
|
|
56
|
-
const queue = [baseDir];
|
|
57
|
-
while (queue.length) {
|
|
58
|
-
const current = queue.shift();
|
|
59
|
-
let entries;
|
|
60
|
-
try {
|
|
61
|
-
entries = await readdir(current, { withFileTypes: true });
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
for (const entry of entries) {
|
|
67
|
-
if (entry.isFile() && entry.name === 'package.json') {
|
|
68
|
-
results.add(path.join(current, entry.name));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
for (const entry of entries) {
|
|
72
|
-
if (!entry.isDirectory())
|
|
73
|
-
continue;
|
|
74
|
-
if (entry.isSymbolicLink())
|
|
75
|
-
continue;
|
|
76
|
-
if (ignoredDirs.has(entry.name))
|
|
77
|
-
continue;
|
|
78
|
-
queue.push(path.join(current, entry.name));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return [...results].sort();
|
|
82
|
-
}
|
|
83
|
-
async function loadWorkspaceManifest() {
|
|
84
|
-
const manifestPath = manifestFilePath();
|
|
85
|
-
try {
|
|
86
|
-
const manifestModule = await import(pathToFileURL(manifestPath).href);
|
|
87
|
-
if (Array.isArray(manifestModule?.PACKAGE_MANIFEST)) {
|
|
88
|
-
return manifestModule.PACKAGE_MANIFEST;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
if (isManifestMissing(error))
|
|
93
|
-
return undefined;
|
|
94
|
-
throw error;
|
|
95
|
-
}
|
|
96
|
-
return undefined;
|
|
97
|
-
}
|
|
98
|
-
async function inferManifestFromWorkspace() {
|
|
99
|
-
const manifest = [];
|
|
100
|
-
const pkgJsonPaths = await findPackageJsonFiles(rootDir);
|
|
101
|
-
for (const pkgJsonPath of pkgJsonPaths) {
|
|
102
|
-
try {
|
|
103
|
-
const raw = await readFile(pkgJsonPath, 'utf8');
|
|
104
|
-
const json = JSON.parse(raw);
|
|
105
|
-
const pkgDir = path.dirname(pkgJsonPath);
|
|
106
|
-
const pkgName = json.name?.trim() || path.basename(pkgDir) || 'package';
|
|
107
|
-
manifest.push({
|
|
108
|
-
name: pkgName,
|
|
109
|
-
path: normalizeManifestPath(path.relative(rootDir, pkgDir)),
|
|
110
|
-
color: colorFromSeed(pkgName),
|
|
111
|
-
substitute: deriveSubstitute(pkgName),
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return manifest;
|
|
119
|
-
}
|
|
120
|
-
function mergeManifestEntries(inferred, overrides) {
|
|
121
|
-
const normalizedOverrides = new Map();
|
|
122
|
-
overrides?.forEach((entry) => {
|
|
123
|
-
const normalized = normalizeManifestPath(entry.path);
|
|
124
|
-
if (!normalized)
|
|
125
|
-
return;
|
|
126
|
-
normalizedOverrides.set(normalized, { ...entry, path: normalized });
|
|
127
|
-
});
|
|
128
|
-
const merged = [];
|
|
129
|
-
for (const baseEntry of inferred) {
|
|
130
|
-
const normalized = normalizeManifestPath(baseEntry.path);
|
|
131
|
-
const override = normalizedOverrides.get(normalized);
|
|
132
|
-
if (override) {
|
|
133
|
-
normalizedOverrides.delete(normalized);
|
|
134
|
-
const name = override.name || baseEntry.name;
|
|
135
|
-
const color = override.color ?? baseEntry.color ?? colorFromSeed(name);
|
|
136
|
-
const substitute = override.substitute ?? baseEntry.substitute ?? deriveSubstitute(name) ?? name;
|
|
137
|
-
merged.push({ name, path: normalized, color, substitute });
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
merged.push({ ...baseEntry, path: normalized });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
normalizedOverrides.forEach((entry) => {
|
|
144
|
-
const name = entry.name || path.basename(entry.path) || 'package';
|
|
145
|
-
const color = entry.color ?? colorFromSeed(name);
|
|
146
|
-
const substitute = entry.substitute ?? deriveSubstitute(name) ?? name;
|
|
147
|
-
merged.push({ name, path: entry.path, color, substitute });
|
|
148
|
-
});
|
|
149
|
-
return merged;
|
|
150
|
-
}
|
|
151
7
|
async function ensureManifestState(forceReload = false) {
|
|
152
8
|
if (manifestState && !forceReload)
|
|
153
9
|
return manifestState;
|
|
154
10
|
const [workspaceManifest, inferred] = await Promise.all([
|
|
155
|
-
loadWorkspaceManifest(),
|
|
156
|
-
inferManifestFromWorkspace(),
|
|
11
|
+
loadWorkspaceManifest(rootDir),
|
|
12
|
+
inferManifestFromWorkspace(rootDir),
|
|
157
13
|
]);
|
|
158
|
-
const entries = mergeManifestEntries(inferred, workspaceManifest);
|
|
14
|
+
const entries = mergeManifestEntries(rootDir, inferred, workspaceManifest);
|
|
159
15
|
const byName = new Map(entries.map((pkg) => [pkg.name.toLowerCase(), pkg]));
|
|
160
16
|
const byPath = new Map(entries.map((pkg) => [pkg.path.toLowerCase(), pkg]));
|
|
161
17
|
manifestState = {
|
|
@@ -180,7 +36,7 @@ export async function loadPackages() {
|
|
|
180
36
|
const meta = byPath.get(relativePath.toLowerCase()) ??
|
|
181
37
|
byName.get((pkgName ?? '').toLowerCase());
|
|
182
38
|
const substitute = meta?.substitute ?? deriveSubstitute(pkgName) ?? path.basename(pkgDir);
|
|
183
|
-
const color = meta?.color ?? colorFromSeed(pkgName);
|
|
39
|
+
const color = (meta?.color ?? colorFromSeed(pkgName));
|
|
184
40
|
let dockerfilePath;
|
|
185
41
|
try {
|
|
186
42
|
const candidate = path.join(pkgDir, 'Dockerfile');
|
package/dist/utils/colors.js
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
1
|
// src/utils/colors.js
|
|
2
|
-
|
|
3
|
-
export const colors = {
|
|
4
|
-
cyan: ansi(36),
|
|
5
|
-
green: ansi(32),
|
|
6
|
-
yellow: ansi(33),
|
|
7
|
-
magenta: ansi(35),
|
|
8
|
-
red: ansi(31),
|
|
9
|
-
bold: ansi(1),
|
|
10
|
-
dim: ansi(2),
|
|
11
|
-
};
|
|
2
|
+
export { colors } from '../colors-shared.js';
|
package/dist/utils/run.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/utils/run.js
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export const rootDir =
|
|
3
|
+
// Always execute commands from the workspace where the CLI is invoked.
|
|
4
|
+
// This makes installs from node_modules behave correctly instead of
|
|
5
|
+
// running in the package's own directory.
|
|
6
|
+
export const rootDir = process.cwd();
|
|
7
7
|
export function run(command, args, options = {}) {
|
|
8
8
|
return new Promise((resolve, reject) => {
|
|
9
9
|
const child = spawn(command, args, {
|
package/dist/workspace.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/workspace.js
|
|
2
2
|
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { rm } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
3
5
|
import { run, rootDir } from './utils/run.js';
|
|
4
6
|
import { logGlobal, logPkg, colors } from './utils/log.js';
|
|
5
7
|
import { collectGitStatus, gitAdd, gitCommit } from './git.js';
|
|
@@ -191,12 +193,83 @@ function packageFilterArg(pkg) {
|
|
|
191
193
|
return '.';
|
|
192
194
|
return `./${pkg.relativeDir}`;
|
|
193
195
|
}
|
|
196
|
+
async function runLifecycleScenario(pkg, scenario) {
|
|
197
|
+
if (pkg) {
|
|
198
|
+
logPkg(pkg, scenario.singleMessage);
|
|
199
|
+
await run('pnpm', scenario.singleArgs(pkg));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
logGlobal(scenario.allMessage, colors.cyan);
|
|
203
|
+
await run('pnpm', scenario.allArgs);
|
|
204
|
+
}
|
|
205
|
+
const TYPECHECK_SCENARIO = {
|
|
206
|
+
allArgs: ['typecheck'],
|
|
207
|
+
allMessage: 'Running typecheck for all packages…',
|
|
208
|
+
singleArgs: (pkg) => ['run', '--filter', packageFilterArg(pkg), 'typecheck'],
|
|
209
|
+
singleMessage: 'Running typecheck…',
|
|
210
|
+
};
|
|
211
|
+
const BUILD_SCENARIO = {
|
|
212
|
+
allArgs: ['build'],
|
|
213
|
+
allMessage: 'Running build for all packages…',
|
|
214
|
+
singleArgs: (pkg) => ['run', '--filter', packageFilterArg(pkg), 'build'],
|
|
215
|
+
singleMessage: 'Running build…',
|
|
216
|
+
};
|
|
217
|
+
const TEST_SCENARIO = {
|
|
218
|
+
allArgs: ['test'],
|
|
219
|
+
allMessage: 'Running tests for all packages…',
|
|
220
|
+
singleArgs: (pkg) => [
|
|
221
|
+
'test',
|
|
222
|
+
'--',
|
|
223
|
+
pkg.relativeDir === '.' ? '.' : pkg.relativeDir,
|
|
224
|
+
],
|
|
225
|
+
singleMessage: 'Running tests…',
|
|
226
|
+
};
|
|
194
227
|
export async function runCleanInstall() {
|
|
195
228
|
logGlobal('Cleaning workspace…', colors.cyan);
|
|
196
229
|
await run('pnpm', ['run', 'clean']);
|
|
197
230
|
logGlobal('Reinstalling dependencies…', colors.cyan);
|
|
198
231
|
await run('pnpm', ['install']);
|
|
199
232
|
}
|
|
233
|
+
const CLEAN_TARGETS = [
|
|
234
|
+
'node_modules',
|
|
235
|
+
'dist',
|
|
236
|
+
'build',
|
|
237
|
+
'.turbo',
|
|
238
|
+
'.next',
|
|
239
|
+
'.expo',
|
|
240
|
+
'.parcel-cache',
|
|
241
|
+
'.cache',
|
|
242
|
+
'coverage',
|
|
243
|
+
'tmp',
|
|
244
|
+
'.tmp',
|
|
245
|
+
];
|
|
246
|
+
async function removePath(target) {
|
|
247
|
+
try {
|
|
248
|
+
await rm(target, { recursive: true, force: true });
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
console.warn(colors.yellow(` failed to remove ${target}: ${String(error)}`));
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
export async function cleanPackages(targets) {
|
|
257
|
+
for (const pkg of targets) {
|
|
258
|
+
logPkg(pkg, 'Cleaning build artifacts and caches…');
|
|
259
|
+
const results = await Promise.all(CLEAN_TARGETS.map(async (name) => {
|
|
260
|
+
const target = path.join(pkg.path, name);
|
|
261
|
+
const removed = await removePath(target);
|
|
262
|
+
return { name, removed };
|
|
263
|
+
}));
|
|
264
|
+
const removed = results.filter((r) => r.removed).map((r) => r.name);
|
|
265
|
+
if (removed.length === 0) {
|
|
266
|
+
console.log(colors.dim(' nothing to clean'));
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
console.log(colors.dim(` removed ${removed.join(', ')}`));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
200
273
|
export async function updateDependencies(targets) {
|
|
201
274
|
const preStatus = await collectGitStatus();
|
|
202
275
|
if (targets.length === 1) {
|
|
@@ -231,32 +304,33 @@ export async function updateDependencies(targets) {
|
|
|
231
304
|
logGlobal('Push complete.', colors.green);
|
|
232
305
|
}
|
|
233
306
|
export async function typecheckAll() {
|
|
234
|
-
|
|
235
|
-
await run('pnpm', ['typecheck']);
|
|
307
|
+
await runLifecycleScenario(undefined, TYPECHECK_SCENARIO);
|
|
236
308
|
}
|
|
237
309
|
export async function typecheckSingle(pkg) {
|
|
238
|
-
|
|
239
|
-
logPkg(pkg, `Running typecheck…`);
|
|
240
|
-
await run('pnpm', ['run', '--filter', filterArg, 'typecheck']);
|
|
310
|
+
await runLifecycleScenario(pkg, TYPECHECK_SCENARIO);
|
|
241
311
|
}
|
|
242
312
|
export async function buildAll() {
|
|
243
|
-
|
|
244
|
-
await run('pnpm', ['build']);
|
|
313
|
+
await runLifecycleScenario(undefined, BUILD_SCENARIO);
|
|
245
314
|
}
|
|
246
315
|
export async function buildSingle(pkg) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
316
|
+
await runLifecycleScenario(pkg, BUILD_SCENARIO);
|
|
317
|
+
}
|
|
318
|
+
export async function rebuildPackages(targets) {
|
|
319
|
+
await cleanPackages(targets);
|
|
320
|
+
if (targets.length === 1) {
|
|
321
|
+
await buildSingle(targets[0]);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
await buildAll();
|
|
325
|
+
}
|
|
250
326
|
}
|
|
251
327
|
export async function buildPackageLocally(pkg) {
|
|
252
328
|
logPkg(pkg, 'Building local dist before publish…');
|
|
253
329
|
await run('pnpm', ['run', 'build'], { cwd: pkg.path });
|
|
254
330
|
}
|
|
255
331
|
export async function testAll() {
|
|
256
|
-
|
|
257
|
-
await run('pnpm', ['test']);
|
|
332
|
+
await runLifecycleScenario(undefined, TEST_SCENARIO);
|
|
258
333
|
}
|
|
259
334
|
export async function testSingle(pkg) {
|
|
260
|
-
|
|
261
|
-
await run('pnpm', ['test', '--', pkg.relativeDir === '.' ? '.' : pkg.relativeDir]);
|
|
335
|
+
await runLifecycleScenario(pkg, TEST_SCENARIO);
|
|
262
336
|
}
|