@emeryld/manager 0.6.5 → 0.6.6
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/helper-cli/display.js +1 -1
- package/dist/helper-cli/pagination.js +16 -12
- package/dist/helper-cli/prompts.js +1 -1
- package/dist/menu/script-helpers.js +118 -11
- package/dist/menu.js +11 -3
- package/package.json +1 -1
|
@@ -45,5 +45,5 @@ export function printPaginatedScriptList(state, title) {
|
|
|
45
45
|
const display = option.enabled ? label : colors.dim(label);
|
|
46
46
|
console.log(` ${numberLabel} ${icon} ${display}`);
|
|
47
47
|
});
|
|
48
|
-
console.log(colors.dim(`Enter 1-${PAGE_SIZE} to run, ${PREVIOUS_KEY} for previous page, ${NEXT_KEY} for next page, ${BACK_KEY} to go back, or type a name.`));
|
|
48
|
+
console.log(colors.dim(`Enter 1-${PAGE_SIZE} to run, ${PREVIOUS_KEY} for previous page (if shown), ${NEXT_KEY} for next page (if shown), ${BACK_KEY} to go back, or type a name.`));
|
|
49
49
|
}
|
|
@@ -15,18 +15,22 @@ export function buildVisibleOptions(entries, page) {
|
|
|
15
15
|
}));
|
|
16
16
|
const hasPrevious = safePage > 0;
|
|
17
17
|
const hasNext = safePage < pageCount - 1;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
18
|
+
if (hasPrevious) {
|
|
19
|
+
options.push({
|
|
20
|
+
type: 'nav',
|
|
21
|
+
action: 'previous',
|
|
22
|
+
hotkey: PREVIOUS_KEY,
|
|
23
|
+
enabled: true,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (hasNext) {
|
|
27
|
+
options.push({
|
|
28
|
+
type: 'nav',
|
|
29
|
+
action: 'next',
|
|
30
|
+
hotkey: NEXT_KEY,
|
|
31
|
+
enabled: true,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
30
34
|
options.push({
|
|
31
35
|
type: 'nav',
|
|
32
36
|
action: 'back',
|
|
@@ -86,7 +86,7 @@ function formatInteractiveLines(state, selectedIndex, title) {
|
|
|
86
86
|
lines.push(`${pointer}${numberLabel}. ${icon} ${navLabel}`);
|
|
87
87
|
});
|
|
88
88
|
lines.push('');
|
|
89
|
-
lines.push(colors.dim(`Use ↑/↓ (or j/k) to move, 1-${PAGE_SIZE} to run, ${PREVIOUS_KEY} prev page, ${NEXT_KEY} next page, ${BACK_KEY} back, Enter to confirm, Esc/Ctrl+C to exit.`));
|
|
89
|
+
lines.push(colors.dim(`Use ↑/↓ (or j/k) to move, 1-${PAGE_SIZE} to run, ${PREVIOUS_KEY} prev page (when shown), ${NEXT_KEY} next page (when shown), ${BACK_KEY} back, Enter to confirm, Esc/Ctrl+C to exit.`));
|
|
90
90
|
return lines;
|
|
91
91
|
}
|
|
92
92
|
function renderInteractiveList(lines, previousLineCount) {
|
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
import { colors } from "../utils/log.js";
|
|
2
2
|
import { run } from "../utils/run.js";
|
|
3
|
+
const FRONTEND_INDICATORS = [
|
|
4
|
+
{ dep: 'next', label: 'Next' },
|
|
5
|
+
{ dep: 'remix', label: 'Remix' },
|
|
6
|
+
{ dep: '@remix-run/node', label: 'Remix' },
|
|
7
|
+
{ dep: 'expo', label: 'Expo' },
|
|
8
|
+
{ dep: 'react-native', label: 'React Native' },
|
|
9
|
+
{ dep: 'react', label: 'React' },
|
|
10
|
+
{ dep: 'vite', label: 'Vite' },
|
|
11
|
+
{ dep: '@vitejs/plugin-react', label: 'Vite' },
|
|
12
|
+
{ dep: 'svelte', label: 'Svelte' },
|
|
13
|
+
{ dep: '@sveltejs/vite-plugin-svelte', label: 'SvelteKit' },
|
|
14
|
+
{ dep: '@angular/core', label: 'Angular' },
|
|
15
|
+
{ dep: 'vue', label: 'Vue' },
|
|
16
|
+
];
|
|
17
|
+
const BACKEND_INDICATORS = [
|
|
18
|
+
{ dep: 'express', label: 'Express' },
|
|
19
|
+
{ dep: 'fastify', label: 'Fastify' },
|
|
20
|
+
{ dep: 'koa', label: 'Koa' },
|
|
21
|
+
{ dep: 'hono', label: 'Hono' },
|
|
22
|
+
{ dep: '@nestjs/core', label: 'NestJS' },
|
|
23
|
+
{ dep: '@trpc/server', label: 'tRPC' },
|
|
24
|
+
];
|
|
25
|
+
const CLI_INDICATORS = [
|
|
26
|
+
{ dep: '@oclif/core', label: 'OClif' },
|
|
27
|
+
{ dep: '@oclif/command', label: 'OClif' },
|
|
28
|
+
{ dep: 'oclif', label: 'OClif' },
|
|
29
|
+
{ dep: 'commander', label: 'Commander' },
|
|
30
|
+
{ dep: 'yargs', label: 'Yargs' },
|
|
31
|
+
{ dep: 'cac', label: 'CAC' },
|
|
32
|
+
{ dep: 'clipanion', label: 'Clipanion' },
|
|
33
|
+
{ dep: 'caporal', label: 'Caporal' },
|
|
34
|
+
{ dep: 'ink', label: 'Ink' },
|
|
35
|
+
{ dep: 'meow', label: 'Meow' },
|
|
36
|
+
{ dep: 'enquirer', label: 'Enquirer' },
|
|
37
|
+
{ dep: 'zx', label: 'ZX' },
|
|
38
|
+
];
|
|
39
|
+
const CLI_KEYWORDS = new Set(['cli', 'command-line', 'commandline', 'tooling']);
|
|
40
|
+
const KIND_COLOR_MAP = {
|
|
41
|
+
frontend: colors.magenta,
|
|
42
|
+
backend: colors.green,
|
|
43
|
+
library: colors.cyan,
|
|
44
|
+
cli: colors.red,
|
|
45
|
+
};
|
|
3
46
|
export function collectDependencies(pkg) {
|
|
4
47
|
return new Set([
|
|
5
48
|
...Object.keys(pkg.json?.dependencies ?? {}),
|
|
@@ -37,6 +80,7 @@ function resolveFormatScript(pkg, scripts, dependencies) {
|
|
|
37
80
|
description: commandDescription(args),
|
|
38
81
|
args,
|
|
39
82
|
available: true,
|
|
83
|
+
isDefault: true,
|
|
40
84
|
};
|
|
41
85
|
}
|
|
42
86
|
return {
|
|
@@ -56,6 +100,7 @@ function resolveTypecheckScript(pkg, scripts, dependencies) {
|
|
|
56
100
|
description: commandDescription(args),
|
|
57
101
|
args,
|
|
58
102
|
available: true,
|
|
103
|
+
isDefault: true,
|
|
59
104
|
};
|
|
60
105
|
}
|
|
61
106
|
return {
|
|
@@ -75,6 +120,7 @@ function resolveLintScript(pkg, scripts, dependencies) {
|
|
|
75
120
|
description: commandDescription(args),
|
|
76
121
|
args,
|
|
77
122
|
available: true,
|
|
123
|
+
isDefault: true,
|
|
78
124
|
};
|
|
79
125
|
}
|
|
80
126
|
return {
|
|
@@ -86,7 +132,7 @@ function resolveLintScript(pkg, scripts, dependencies) {
|
|
|
86
132
|
function resolveDevScript(pkg, scripts, dependencies, kind) {
|
|
87
133
|
const devCandidates = kind === 'frontend'
|
|
88
134
|
? ['dev', 'start', 'serve']
|
|
89
|
-
: kind === 'backend'
|
|
135
|
+
: kind === 'backend' || kind === 'cli'
|
|
90
136
|
? ['dev', 'start', 'watch', 'serve', 'start:dev']
|
|
91
137
|
: ['dev', 'start'];
|
|
92
138
|
const direct = resolveRunScript(scripts, devCandidates);
|
|
@@ -99,6 +145,7 @@ function resolveDevScript(pkg, scripts, dependencies, kind) {
|
|
|
99
145
|
description: commandDescription(args),
|
|
100
146
|
args,
|
|
101
147
|
available: true,
|
|
148
|
+
isDefault: true,
|
|
102
149
|
};
|
|
103
150
|
}
|
|
104
151
|
if (dependencies.has('vite')) {
|
|
@@ -108,6 +155,7 @@ function resolveDevScript(pkg, scripts, dependencies, kind) {
|
|
|
108
155
|
description: commandDescription(args),
|
|
109
156
|
args,
|
|
110
157
|
available: true,
|
|
158
|
+
isDefault: true,
|
|
111
159
|
};
|
|
112
160
|
}
|
|
113
161
|
if (dependencies.has('expo')) {
|
|
@@ -117,6 +165,7 @@ function resolveDevScript(pkg, scripts, dependencies, kind) {
|
|
|
117
165
|
description: commandDescription(args),
|
|
118
166
|
args,
|
|
119
167
|
available: true,
|
|
168
|
+
isDefault: true,
|
|
120
169
|
};
|
|
121
170
|
}
|
|
122
171
|
return {
|
|
@@ -145,7 +194,9 @@ export function makeBaseScriptEntries(pkg) {
|
|
|
145
194
|
return BASE_SCRIPT_KEYS.map((key) => {
|
|
146
195
|
const resolution = resolveBaseScript(pkg, key, scripts, dependencies, marker.kind);
|
|
147
196
|
const description = resolution.available
|
|
148
|
-
? resolution.
|
|
197
|
+
? resolution.isDefault
|
|
198
|
+
? `${resolution.description} (default)`
|
|
199
|
+
: resolution.description
|
|
149
200
|
: `No ${key} command detected`;
|
|
150
201
|
return {
|
|
151
202
|
name: key,
|
|
@@ -162,17 +213,73 @@ export function makeBaseScriptEntries(pkg) {
|
|
|
162
213
|
});
|
|
163
214
|
}
|
|
164
215
|
export function getPackageMarker(pkg, dependencies = collectDependencies(pkg)) {
|
|
165
|
-
const
|
|
166
|
-
|
|
216
|
+
const normalizedDeps = new Set([...dependencies].map((dep) => String(dep).toLowerCase().trim()));
|
|
217
|
+
function findIndicator(indicators) {
|
|
218
|
+
for (const indicator of indicators) {
|
|
219
|
+
if (normalizedDeps.has(indicator.dep.toLowerCase())) {
|
|
220
|
+
return indicator;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
167
225
|
const pkgType = pkg.json?.type?.toLowerCase();
|
|
168
|
-
|
|
169
|
-
|
|
226
|
+
const keywords = (() => {
|
|
227
|
+
const raw = pkg.json?.keywords;
|
|
228
|
+
if (typeof raw === 'string') {
|
|
229
|
+
return raw
|
|
230
|
+
.split(/\s*,\s*/)
|
|
231
|
+
.map((keyword) => keyword.trim())
|
|
232
|
+
.filter(Boolean);
|
|
233
|
+
}
|
|
234
|
+
if (Array.isArray(raw)) {
|
|
235
|
+
return raw
|
|
236
|
+
.map((keyword) => String(keyword).trim())
|
|
237
|
+
.filter(Boolean);
|
|
238
|
+
}
|
|
239
|
+
return [];
|
|
240
|
+
})();
|
|
241
|
+
const hasCliKeyword = keywords
|
|
242
|
+
.map((keyword) => keyword.toLowerCase())
|
|
243
|
+
.some((keyword) => CLI_KEYWORDS.has(keyword));
|
|
244
|
+
const hasBinField = !!pkg.json?.bin &&
|
|
245
|
+
(typeof pkg.json?.bin === 'string' ||
|
|
246
|
+
typeof pkg.json?.bin === 'object' ||
|
|
247
|
+
Array.isArray(pkg.json?.bin));
|
|
248
|
+
const frontendIndicator = findIndicator(FRONTEND_INDICATORS);
|
|
249
|
+
if (frontendIndicator) {
|
|
250
|
+
return {
|
|
251
|
+
label: frontendIndicator.label ?? frontendIndicator.dep,
|
|
252
|
+
colorize: KIND_COLOR_MAP.frontend,
|
|
253
|
+
kind: 'frontend',
|
|
254
|
+
kindColorize: KIND_COLOR_MAP.frontend,
|
|
255
|
+
};
|
|
170
256
|
}
|
|
171
|
-
|
|
172
|
-
|
|
257
|
+
const backendIndicator = findIndicator(BACKEND_INDICATORS);
|
|
258
|
+
if (backendIndicator) {
|
|
259
|
+
return {
|
|
260
|
+
label: backendIndicator.label ?? backendIndicator.dep,
|
|
261
|
+
colorize: KIND_COLOR_MAP.backend,
|
|
262
|
+
kind: 'backend',
|
|
263
|
+
kindColorize: KIND_COLOR_MAP.backend,
|
|
264
|
+
};
|
|
173
265
|
}
|
|
174
|
-
|
|
175
|
-
|
|
266
|
+
const cliIndicator = findIndicator(CLI_INDICATORS);
|
|
267
|
+
if (cliIndicator || hasCliKeyword || hasBinField) {
|
|
268
|
+
const label = cliIndicator?.label ?? 'CLI';
|
|
269
|
+
return {
|
|
270
|
+
label,
|
|
271
|
+
colorize: KIND_COLOR_MAP.cli,
|
|
272
|
+
kind: 'cli',
|
|
273
|
+
kindColorize: KIND_COLOR_MAP.cli,
|
|
274
|
+
};
|
|
176
275
|
}
|
|
177
|
-
|
|
276
|
+
const isModule = pkgType === 'module';
|
|
277
|
+
const label = isModule ? 'ESM' : 'Node';
|
|
278
|
+
const labelColorizer = isModule ? colors.yellow : colors.cyan;
|
|
279
|
+
return {
|
|
280
|
+
label,
|
|
281
|
+
colorize: labelColorizer,
|
|
282
|
+
kind: 'library',
|
|
283
|
+
kindColorize: KIND_COLOR_MAP.library,
|
|
284
|
+
};
|
|
178
285
|
}
|
package/dist/menu.js
CHANGED
|
@@ -9,6 +9,11 @@ import { ensureWorkingTreeCommitted } from './preflight.js';
|
|
|
9
9
|
import { openDockerHelper } from './docker.js';
|
|
10
10
|
import { run } from './utils/run.js';
|
|
11
11
|
import { makeBaseScriptEntries, getPackageMarker } from './menu/script-helpers.js';
|
|
12
|
+
function formatKindLabel(kind) {
|
|
13
|
+
if (kind === 'cli')
|
|
14
|
+
return 'CLI';
|
|
15
|
+
return `${kind.charAt(0).toUpperCase()}${kind.slice(1)}`;
|
|
16
|
+
}
|
|
12
17
|
function makeManagerStepEntries(targets, packages, state, options) {
|
|
13
18
|
const includeBack = options?.includeBack ?? true;
|
|
14
19
|
return [
|
|
@@ -154,12 +159,15 @@ export function buildPackageSelectionMenu(packages, onStepComplete) {
|
|
|
154
159
|
const entries = ordered.map((pkg) => {
|
|
155
160
|
const marker = getPackageMarker(pkg);
|
|
156
161
|
const pkgColor = pkg.color ?? 'cyan';
|
|
157
|
-
const descriptionMeta = pkg.relativeDir ?? pkg.dirName;
|
|
158
|
-
const
|
|
162
|
+
const descriptionMeta = colors.dim(pkg.relativeDir ?? pkg.dirName);
|
|
163
|
+
const labelBadge = marker.label ? marker.colorize(marker.label) : '';
|
|
164
|
+
const kindLabel = formatKindLabel(marker.kind);
|
|
165
|
+
const kindBadge = marker.kindColorize(kindLabel);
|
|
166
|
+
const badgeMeta = [labelBadge, kindBadge].filter(Boolean).join(' ');
|
|
159
167
|
return {
|
|
160
168
|
name: pkg.name ?? pkg.substitute ?? pkg.dirName,
|
|
161
169
|
emoji: marker.colorize('●'),
|
|
162
|
-
description:
|
|
170
|
+
description: [descriptionMeta, badgeMeta].filter(Boolean).join(' '),
|
|
163
171
|
color: pkgColor,
|
|
164
172
|
handler: async () => {
|
|
165
173
|
const step = await runStepLoop([pkg], packages);
|