1 | import { constants, filter, fs, loadSettings, log, semver, formatModuleName, } from '../common';
|
2 | export const name = 'ls';
|
3 | export const alias = 'l';
|
4 | export const description = 'Lists modules in dependency order.';
|
5 | export const args = {
|
6 | '-D': 'Show all module dependencies (omit for local only).',
|
7 | '-i': 'Include ignored modules.',
|
8 | '-p': 'Show path to module.',
|
9 | '-n': 'Retrieve registry details from NPM.',
|
10 | '--no-formatting': 'Simple list without table formatting.',
|
11 | };
|
12 | export async function cmd(args) {
|
13 | const options = (args && args.options) || {};
|
14 | await ls({
|
15 | dependencies: options.D ? 'all' : 'local',
|
16 | includeIgnored: options.i,
|
17 | showPath: options.p,
|
18 | npm: options.n,
|
19 | formatting: options.formatting,
|
20 | });
|
21 | }
|
22 | export async function ls(options = {}) {
|
23 | const { includeIgnored = false, npm = false } = options;
|
24 | const formatting = options.formatting === false ? false : true;
|
25 | const settings = await loadSettings({ npm, spinner: npm });
|
26 | if (!settings) {
|
27 | log.warn.yellow(constants.CONFIG_NOT_FOUND_ERROR);
|
28 | return;
|
29 | }
|
30 | const modules = settings.modules.filter((pkg) => filter.includeIgnored(pkg, includeIgnored));
|
31 | if (formatting) {
|
32 | printTable(modules, Object.assign(Object.assign({}, options), { basePath: fs.dirname(settings.path), columns: options.columns }));
|
33 | log.info();
|
34 | }
|
35 | else {
|
36 | log.info();
|
37 | modules.forEach((pkg) => log.info(pkg.name));
|
38 | log.info();
|
39 | }
|
40 | return {
|
41 | modules,
|
42 | settings: settings,
|
43 | };
|
44 | }
|
45 | export function printTable(modules, options = {}) {
|
46 | const { dependencies = 'none', includeIgnored = false, showPath = false, dependants, basePath, columns = [], } = options;
|
47 | const showAllDependencies = dependencies === 'all';
|
48 | const showDependants = dependants !== undefined;
|
49 | const listDependences = (pkg, modules) => pkg.dependencies
|
50 | .filter((dep) => (showAllDependencies ? true : dep.isLocal))
|
51 | .filter((dep) => (dep.package ? filter.includeIgnored(dep.package, includeIgnored) : true))
|
52 | .map((dep) => {
|
53 | const isIgnored = dep.package && dep.package.isIgnored;
|
54 | const name = isIgnored
|
55 | ? log.gray(dep.name)
|
56 | : dep.isLocal
|
57 | ? log.cyan(dep.name)
|
58 | : log.gray(dep.name);
|
59 | return `${name} ${log.gray(dep.version)}`;
|
60 | })
|
61 | .join('\n');
|
62 | const listDependants = (dependants) => {
|
63 | if (!dependants || dependants.length === 0) {
|
64 | return log.yellow('dependant');
|
65 | }
|
66 | return dependants
|
67 | .filter((pkg) => filter.includeIgnored(pkg, includeIgnored))
|
68 | .map((pkg) => {
|
69 | const name = pkg.isIgnored ? log.gray(pkg.name) : formatModuleName(pkg.name);
|
70 | return `${name} ${log.gray(pkg.version)}`;
|
71 | })
|
72 | .join('\n');
|
73 | };
|
74 | const column = {
|
75 | module: {
|
76 | head: 'module',
|
77 | render: (pkg) => {
|
78 | const text = formatModuleName(pkg.name);
|
79 | return ` ${text}`;
|
80 | },
|
81 | },
|
82 | version: {
|
83 | head: 'version ',
|
84 | render: (pkg) => {
|
85 | const npmVersion = pkg.npm && pkg.npm.latest;
|
86 | const format = (args) => {
|
87 | const { from, to } = args;
|
88 | const max = Math.max(from.text.length, 12);
|
89 | const left = `${from.text} `.substring(0, max);
|
90 | const right = to.color(`← NPM ${to.text}`);
|
91 | return `${from.color(left)} ${right}`;
|
92 | };
|
93 | if (npmVersion && semver.gt(pkg.version, npmVersion)) {
|
94 | return format({
|
95 | from: { text: pkg.version, color: log.yellow },
|
96 | to: { text: npmVersion, color: log.gray },
|
97 | });
|
98 | }
|
99 | else if (npmVersion && semver.lt(pkg.version, npmVersion)) {
|
100 | return format({
|
101 | from: { text: pkg.version, color: log.gray },
|
102 | to: { text: npmVersion, color: log.magenta },
|
103 | });
|
104 | }
|
105 | else {
|
106 | return log.magenta(pkg.version);
|
107 | }
|
108 | },
|
109 | },
|
110 | dependencies: {
|
111 | head: 'dependencies',
|
112 | render: (pkg) => listDependences(pkg, modules),
|
113 | },
|
114 | dependants: {
|
115 | head: 'dependants',
|
116 | render: (pkg) => listDependants(dependants || []),
|
117 | },
|
118 | path: {
|
119 | head: 'path',
|
120 | render: (pkg) => {
|
121 | const path = basePath && pkg.dir.startsWith(basePath)
|
122 | ? pkg.dir.substring(basePath.length, pkg.dir.length)
|
123 | : pkg.dir;
|
124 | return log.gray(path);
|
125 | },
|
126 | },
|
127 | };
|
128 | const logModules = (modules) => {
|
129 | const cols = [];
|
130 | const addColumn = (col, include = true) => {
|
131 | if (include) {
|
132 | cols.push(col);
|
133 | }
|
134 | };
|
135 | addColumn(column.module);
|
136 | addColumn(column.version);
|
137 | addColumn(column.dependencies, dependencies !== 'none');
|
138 | addColumn(column.dependants, showDependants);
|
139 | addColumn(column.path, showPath);
|
140 | (columns || []).forEach((col) => addColumn(col));
|
141 | const head = cols.map((col) => log.gray(col.head));
|
142 | const builder = log.table({ head, border: false });
|
143 | modules.forEach((pkg) => {
|
144 | const row = [];
|
145 | cols.forEach((col) => row.push(`${col.render(pkg)} `));
|
146 | builder.add(row);
|
147 | });
|
148 | builder.log();
|
149 | };
|
150 | if (modules.length > 0) {
|
151 | logModules(modules);
|
152 | }
|
153 | }
|