@emeryld/manager 0.6.3 → 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 +27 -131
- 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 -283
- 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/workspace.js +88 -14
- package/package.json +1 -1
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/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
|
}
|