reslop 0.2.5 → 0.2.7
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/CHANGELOG.md +22 -1
- package/LICENSE +1 -1
- package/README.md +11 -11
- package/bin/reslop.js +3 -8
- package/lib/ansi.js +72 -19
- package/lib/api.js +1 -1
- package/lib/capabilities.js +8 -8
- package/lib/cli.js +61 -75
- package/lib/clipboard.js +39 -47
- package/lib/dashboard/git.js +128 -0
- package/lib/dashboard/model.js +357 -0
- package/lib/dashboard/npm.js +290 -0
- package/lib/dashboard/tree.js +278 -0
- package/lib/deps-diff.js +197 -402
- package/lib/deps.js +113 -240
- package/lib/detect.js +8 -18
- package/lib/diff/align.js +41 -113
- package/lib/diff/diff.js +12 -43
- package/lib/diff/display.js +25 -36
- package/lib/diff/edit.js +6 -20
- package/lib/diff/inline.js +76 -144
- package/lib/diff/items.js +33 -47
- package/lib/diff/parse.js +28 -56
- package/lib/diff/patch.js +12 -33
- package/lib/diff/unit.js +79 -178
- package/lib/editor.js +52 -69
- package/lib/files.js +79 -91
- package/lib/find.js +61 -0
- package/lib/git-branches.js +254 -416
- package/lib/git-deps.js +148 -272
- package/lib/git-reword-todo.js +5 -13
- package/lib/git-worktree.js +161 -214
- package/lib/git.js +21 -49
- package/lib/github.js +67 -181
- package/lib/gitlab.js +40 -90
- package/lib/highlight/bash.js +55 -177
- package/lib/highlight/core.js +155 -141
- package/lib/highlight/css.js +25 -58
- package/lib/highlight/csv.js +19 -37
- package/lib/highlight/dart.js +72 -213
- package/lib/highlight/dot.js +14 -14
- package/lib/highlight/html.js +42 -63
- package/lib/highlight/js.js +177 -506
- package/lib/highlight/json.js +17 -37
- package/lib/highlight/log.js +19 -25
- package/lib/highlight/txt.js +7 -10
- package/lib/highlight.js +17 -46
- package/lib/keys.js +75 -83
- package/lib/manifest.js +67 -126
- package/lib/npm-commands.js +120 -169
- package/lib/remote.js +140 -190
- package/lib/render/branches.js +63 -61
- package/lib/render/chrome.js +412 -347
- package/lib/render/commits.js +160 -361
- package/lib/render/dash-activity.js +212 -0
- package/lib/render/dash-blocks.js +496 -0
- package/lib/render/dash-table.js +295 -0
- package/lib/render/dashboard.js +62 -0
- package/lib/render/diff.js +123 -258
- package/lib/render/files.js +60 -86
- package/lib/render/frame.js +82 -117
- package/lib/render/notes.js +150 -210
- package/lib/render/npm.js +213 -177
- package/lib/render/packages.js +93 -0
- package/lib/render/present.js +4 -11
- package/lib/render/primitives.js +77 -172
- package/lib/render/render.js +5 -14
- package/lib/render/report.js +43 -0
- package/lib/render/repos.js +226 -0
- package/lib/render/search.js +25 -0
- package/lib/render/tiles.js +355 -0
- package/lib/render/unit.js +15 -31
- package/lib/report-model.js +110 -33
- package/lib/report-parse.js +56 -37
- package/lib/report-render.js +102 -59
- package/lib/report-run.js +87 -77
- package/lib/report-test.js +221 -99
- package/lib/report-tools.js +96 -154
- package/lib/review-merge.js +33 -41
- package/lib/review.js +69 -129
- package/lib/runs.js +225 -0
- package/lib/select.js +53 -91
- package/lib/session/accessors.js +14 -21
- package/lib/session/actions.js +189 -65
- package/lib/session/branches.js +164 -222
- package/lib/session/change-actions.js +49 -119
- package/lib/session/commit.js +298 -352
- package/lib/session/compose.js +572 -715
- package/lib/session/dashboard.js +530 -0
- package/lib/session/dispatch.js +197 -171
- package/lib/session/files-pane.js +92 -45
- package/lib/session/find.js +94 -0
- package/lib/session/items.js +6 -17
- package/lib/session/lifecycle.js +420 -466
- package/lib/session/load.js +1 -14
- package/lib/session/navigation.js +4 -2
- package/lib/session/npm.js +403 -420
- package/lib/session/ops.js +5 -13
- package/lib/session/packages.js +143 -0
- package/lib/session/pointer.js +30 -14
- package/lib/session/progress.js +39 -30
- package/lib/session/review.js +1 -3
- package/lib/session/tasks.js +277 -236
- package/lib/session/templates.js +51 -59
- package/lib/session/terminal.js +85 -132
- package/lib/session/view.js +59 -80
- package/lib/session/watch.js +201 -212
- package/lib/session/workspace.js +455 -0
- package/lib/session.js +95 -161
- package/lib/update.js +44 -111
- package/lib/utilities.js +46 -88
- package/lib/workspace.js +166 -0
- package/lib/wrap.js +29 -55
- package/package.json +1 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const worktree = require('../git-worktree.js');
|
|
7
|
+
const { runGitAsync } = worktree;
|
|
8
|
+
|
|
9
|
+
const UNIT = '\x1f';
|
|
10
|
+
const RECENT_COUNT = 8;
|
|
11
|
+
const BRANCH_FORMAT = [
|
|
12
|
+
'%(HEAD)',
|
|
13
|
+
'%(refname:short)',
|
|
14
|
+
'%(objectname:short)',
|
|
15
|
+
'%(committerdate:unix)',
|
|
16
|
+
'%(upstream:short)',
|
|
17
|
+
'%(upstream:track)',
|
|
18
|
+
'%(subject)',
|
|
19
|
+
].join('%09');
|
|
20
|
+
const LAST_FORMAT = ['%H', '%h', '%ct', '%s'].join('%x1f');
|
|
21
|
+
const PROBES = {
|
|
22
|
+
total: ['rev-list', '--count', 'HEAD'],
|
|
23
|
+
recent: ['log', `--max-count=${RECENT_COUNT}`, `--format=${LAST_FORMAT}`],
|
|
24
|
+
refs: ['for-each-ref', `--format=${BRANCH_FORMAT}`, 'refs/heads'],
|
|
25
|
+
dir: ['rev-parse', '--absolute-git-dir'],
|
|
26
|
+
};
|
|
27
|
+
const TRACK_AHEAD = /ahead (\d+)/;
|
|
28
|
+
const TRACK_BEHIND = /behind (\d+)/;
|
|
29
|
+
|
|
30
|
+
const gitText = async (top, args) => {
|
|
31
|
+
try {
|
|
32
|
+
const result = await runGitAsync(args, top);
|
|
33
|
+
return result.status === 0 ? result.stdout.trim() : '';
|
|
34
|
+
} catch {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const countOf = (text) => {
|
|
40
|
+
const value = parseInt(text, 10);
|
|
41
|
+
return Number.isFinite(value) ? value : 0;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const msOf = (seconds) => (Number.isFinite(seconds) ? seconds * 1000 : 0);
|
|
45
|
+
|
|
46
|
+
const parseLines = (text, parse) => text.split('\n').map(parse).filter(Boolean);
|
|
47
|
+
|
|
48
|
+
const parseTrack = (text) => {
|
|
49
|
+
const raw = `${text ?? ''}`;
|
|
50
|
+
const ahead = TRACK_AHEAD.exec(raw);
|
|
51
|
+
const behind = TRACK_BEHIND.exec(raw);
|
|
52
|
+
return {
|
|
53
|
+
ahead: ahead ? Number(ahead[1]) : 0,
|
|
54
|
+
behind: behind ? Number(behind[1]) : 0,
|
|
55
|
+
gone: raw.includes('gone'),
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const parseBranch = (line) => {
|
|
60
|
+
const parts = line.split('\t');
|
|
61
|
+
const name = (parts[1] ?? '').trim();
|
|
62
|
+
if (!name) return null;
|
|
63
|
+
return {
|
|
64
|
+
name,
|
|
65
|
+
current: parts[0].includes('*'),
|
|
66
|
+
sha: (parts[2] ?? '').trim(),
|
|
67
|
+
at: msOf(Number(parts[3])),
|
|
68
|
+
upstream: (parts[4] ?? '').trim(),
|
|
69
|
+
...parseTrack(parts[5]),
|
|
70
|
+
subject: parts.slice(6).join('\t').trim(),
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const parseCommit = (line) => {
|
|
75
|
+
const parts = line.split(UNIT);
|
|
76
|
+
if (parts.length < 4 || !parts[0]) return null;
|
|
77
|
+
return {
|
|
78
|
+
sha: parts[0],
|
|
79
|
+
short: parts[1],
|
|
80
|
+
at: msOf(Number(parts[2])),
|
|
81
|
+
subject: parts.slice(3).join(UNIT).trim(),
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const readNumber = (file) => {
|
|
86
|
+
try {
|
|
87
|
+
return countOf(fs.readFileSync(file, 'utf8'));
|
|
88
|
+
} catch {
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const readStep = (dir, step, total) => ({
|
|
94
|
+
step: readNumber(path.join(dir, step)),
|
|
95
|
+
total: readNumber(path.join(dir, total)),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const rebaseState = (gitDir) => {
|
|
99
|
+
if (!gitDir) return null;
|
|
100
|
+
const merge = path.join(gitDir, 'rebase-merge');
|
|
101
|
+
if (fs.existsSync(merge)) return readStep(merge, 'msgnum', 'end');
|
|
102
|
+
const apply = path.join(gitDir, 'rebase-apply');
|
|
103
|
+
if (fs.existsSync(apply)) return readStep(apply, 'next', 'last');
|
|
104
|
+
return null;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const readGitSummary = async (top) => {
|
|
108
|
+
const names = Object.keys(PROBES);
|
|
109
|
+
const read = (name) => gitText(top, PROBES[name]);
|
|
110
|
+
const texts = await Promise.all(names.map(read));
|
|
111
|
+
const probes = {};
|
|
112
|
+
for (let i = 0; i < names.length; i++) probes[names[i]] = texts[i];
|
|
113
|
+
const branches = parseLines(probes.refs, parseBranch);
|
|
114
|
+
const current = branches.find((entry) => entry.current);
|
|
115
|
+
const recent = parseLines(probes.recent, parseCommit);
|
|
116
|
+
return {
|
|
117
|
+
branch: current ? current.name : '',
|
|
118
|
+
rebase: rebaseState(probes.dir),
|
|
119
|
+
commits: {
|
|
120
|
+
total: countOf(probes.total),
|
|
121
|
+
last: recent[0] ?? null,
|
|
122
|
+
recent,
|
|
123
|
+
},
|
|
124
|
+
branches,
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
module.exports = { readGitSummary, parseTrack };
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const tree = require('./tree.js');
|
|
4
|
+
const { folderOf, extOf } = tree;
|
|
5
|
+
const files = require('../files.js');
|
|
6
|
+
const { TASK_KINDS, taskKind } = files;
|
|
7
|
+
|
|
8
|
+
const MINUTE_MS = 60_000;
|
|
9
|
+
const RUNS_SHOWN = 6;
|
|
10
|
+
const CHAIN_GAP_MS = 2000;
|
|
11
|
+
const NPM_NAMED = /^npm (?:run|exec)(?:\s+-s)?\s+(\S+)/;
|
|
12
|
+
const NPM_ALIAS = /^npm (test|start|stop|restart)(?:\s|$)/;
|
|
13
|
+
const AGE_TEXT = /^(\d+)\s+(second|minute|hour|day|week|month|year)s?\s+ago$/i;
|
|
14
|
+
const AGE_SEC = {
|
|
15
|
+
second: 1,
|
|
16
|
+
minute: 60,
|
|
17
|
+
hour: 3600,
|
|
18
|
+
day: 86400,
|
|
19
|
+
week: 604800,
|
|
20
|
+
month: 2592000,
|
|
21
|
+
year: 31536000,
|
|
22
|
+
};
|
|
23
|
+
const STATUS_RANK = { running: 3, failed: 2, aborted: 1, passed: 0 };
|
|
24
|
+
|
|
25
|
+
const namedScript = (command) => {
|
|
26
|
+
const text = `${command ?? ''}`.trim();
|
|
27
|
+
const named = NPM_NAMED.exec(text);
|
|
28
|
+
if (named) return named[1];
|
|
29
|
+
const alias = NPM_ALIAS.exec(text);
|
|
30
|
+
return alias ? alias[1] : '';
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const scriptName = (command) => {
|
|
34
|
+
const named = namedScript(command);
|
|
35
|
+
if (named) return named;
|
|
36
|
+
const text = `${command ?? ''}`.trim();
|
|
37
|
+
const token = text.split(/\s+/)[0];
|
|
38
|
+
const slash = Math.max(token.lastIndexOf('/'), token.lastIndexOf('\\'));
|
|
39
|
+
return token.slice(slash + 1) || text;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const runName = (record) => {
|
|
43
|
+
const command = `${record.command ?? ''}`.trim();
|
|
44
|
+
const script = `${record.script ?? ''}`.trim();
|
|
45
|
+
return namedScript(command) || script || command;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const ageSeconds = (text) => {
|
|
49
|
+
const raw = `${text ?? ''}`.trim();
|
|
50
|
+
if (/^yesterday$/i.test(raw)) return AGE_SEC.day;
|
|
51
|
+
const match = AGE_TEXT.exec(raw);
|
|
52
|
+
if (!match) return Number.POSITIVE_INFINITY;
|
|
53
|
+
return Number(match[1]) * AGE_SEC[match[2].toLowerCase()];
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const newerDate = (current, next) => {
|
|
57
|
+
if (!next) return current;
|
|
58
|
+
if (!current || ageSeconds(next) < ageSeconds(current)) return next;
|
|
59
|
+
return current;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const groupOf = (map, key) => {
|
|
63
|
+
let group = map.get(key);
|
|
64
|
+
if (!group) {
|
|
65
|
+
group = {
|
|
66
|
+
key,
|
|
67
|
+
added: 0,
|
|
68
|
+
removed: 0,
|
|
69
|
+
stagedAdded: 0,
|
|
70
|
+
stagedRemoved: 0,
|
|
71
|
+
staged: 0,
|
|
72
|
+
remaining: 0,
|
|
73
|
+
date: '',
|
|
74
|
+
};
|
|
75
|
+
map.set(key, group);
|
|
76
|
+
}
|
|
77
|
+
return group;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const byChange = (left, right) => {
|
|
81
|
+
const lhs = left.added + left.removed;
|
|
82
|
+
const rhs = right.added + right.removed;
|
|
83
|
+
return rhs - lhs || left.key.localeCompare(right.key, 'en');
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const groupChanges = (entries) => {
|
|
87
|
+
const dirs = new Map();
|
|
88
|
+
const exts = new Map();
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
const groups = [
|
|
91
|
+
groupOf(dirs, folderOf(entry.path)),
|
|
92
|
+
groupOf(exts, extOf(entry.path)),
|
|
93
|
+
];
|
|
94
|
+
for (const group of groups) {
|
|
95
|
+
group.added += entry.added ?? 0;
|
|
96
|
+
group.removed += entry.removed ?? 0;
|
|
97
|
+
group.stagedAdded += entry.stagedAdded ?? 0;
|
|
98
|
+
group.stagedRemoved += entry.stagedRemoved ?? 0;
|
|
99
|
+
group.staged += entry.staged ?? 0;
|
|
100
|
+
group.remaining += entry.remaining ?? 0;
|
|
101
|
+
group.date = newerDate(group.date, entry.date);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
dirs: [...dirs.values()].sort(byChange),
|
|
106
|
+
exts: [...exts.values()].sort(byChange),
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const npmRunStatus = (run) => {
|
|
111
|
+
if (run.running) return 'running';
|
|
112
|
+
if (run.exit === 0) return 'passed';
|
|
113
|
+
if (run.exit === '' || run.exit === null) return 'aborted';
|
|
114
|
+
return 'failed';
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const externalRun = (record) => {
|
|
118
|
+
const progress = record.progress ?? {};
|
|
119
|
+
return {
|
|
120
|
+
source: 'reslop t',
|
|
121
|
+
name: runName(record),
|
|
122
|
+
status: record.status,
|
|
123
|
+
exit: record.exit,
|
|
124
|
+
startedAt: record.startedAt,
|
|
125
|
+
endedAt: record.endedAt,
|
|
126
|
+
done: progress.done ?? 0,
|
|
127
|
+
failed: progress.failed ?? 0,
|
|
128
|
+
expected: progress.expected ?? 0,
|
|
129
|
+
result: record.result ?? null,
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const internalRun = (run) => ({
|
|
134
|
+
source: 'reslop',
|
|
135
|
+
name: scriptName(run.label),
|
|
136
|
+
status: npmRunStatus(run),
|
|
137
|
+
exit: run.exit,
|
|
138
|
+
startedAt: run.startedAt,
|
|
139
|
+
endedAt: run.endedAt,
|
|
140
|
+
done: 0,
|
|
141
|
+
failed: 0,
|
|
142
|
+
expected: 0,
|
|
143
|
+
result: null,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const rankOf = (status) => STATUS_RANK[status] ?? 0;
|
|
147
|
+
|
|
148
|
+
const isOpen = (run) => run.status === 'running' || !run.endedAt;
|
|
149
|
+
|
|
150
|
+
const addNum = (left, right) => {
|
|
151
|
+
if (typeof left !== 'number') return typeof right === 'number' ? right : null;
|
|
152
|
+
return typeof right === 'number' ? left + right : left;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const mergeResult = (left, right) => {
|
|
156
|
+
if (!left || !right) return left || right;
|
|
157
|
+
const tools = new Set(left.tools);
|
|
158
|
+
for (const tool of right.tools ?? []) tools.add(tool);
|
|
159
|
+
return {
|
|
160
|
+
tools: [...tools],
|
|
161
|
+
tests: addNum(left.tests, right.tests),
|
|
162
|
+
passed: addNum(left.passed, right.passed),
|
|
163
|
+
failed: addNum(left.failed, right.failed),
|
|
164
|
+
skipped: addNum(left.skipped, right.skipped),
|
|
165
|
+
errors: addNum(left.errors, right.errors),
|
|
166
|
+
warnings: addNum(left.warnings, right.warnings),
|
|
167
|
+
duration: left.duration || right.duration || '',
|
|
168
|
+
problems: addNum(left.problems, right.problems),
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const continuesRun = (prev, next) => {
|
|
173
|
+
if (prev.name !== next.name) return false;
|
|
174
|
+
if (isOpen(prev)) return next.startedAt >= prev.startedAt;
|
|
175
|
+
return next.startedAt <= prev.endedAt + CHAIN_GAP_MS;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const absorbRun = (prev, next) => {
|
|
179
|
+
const open = isOpen(prev) || isOpen(next);
|
|
180
|
+
if (rankOf(next.status) >= rankOf(prev.status)) {
|
|
181
|
+
prev.exit = next.exit;
|
|
182
|
+
prev.status = next.status;
|
|
183
|
+
}
|
|
184
|
+
prev.endedAt = open ? 0 : Math.max(prev.endedAt, next.endedAt);
|
|
185
|
+
prev.done += next.done;
|
|
186
|
+
prev.failed += next.failed;
|
|
187
|
+
prev.expected = Math.max(prev.expected, next.expected);
|
|
188
|
+
prev.result = mergeResult(prev.result, next.result);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const collapseRuns = (list) => {
|
|
192
|
+
const ordered = [...list].sort(
|
|
193
|
+
(left, right) => left.startedAt - right.startedAt,
|
|
194
|
+
);
|
|
195
|
+
const groups = [];
|
|
196
|
+
for (const run of ordered) {
|
|
197
|
+
const prev = groups.at(-1);
|
|
198
|
+
if (prev && continuesRun(prev, run)) absorbRun(prev, run);
|
|
199
|
+
else groups.push({ ...run });
|
|
200
|
+
}
|
|
201
|
+
return groups.sort((left, right) => right.startedAt - left.startedAt);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const mergeRuns = (records, npmRun) => {
|
|
205
|
+
const list = records.map(externalRun);
|
|
206
|
+
if (npmRun) list.push(internalRun(npmRun));
|
|
207
|
+
return collapseRuns(list).slice(0, RUNS_SHOWN);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const taskKindCounts = (store) => {
|
|
211
|
+
const kinds = TASK_KINDS.map((kind) => ({
|
|
212
|
+
id: kind.id,
|
|
213
|
+
title: kind.title,
|
|
214
|
+
done: 0,
|
|
215
|
+
total: 0,
|
|
216
|
+
}));
|
|
217
|
+
const byId = new Map(kinds.map((row) => [row.id, row]));
|
|
218
|
+
let done = 0;
|
|
219
|
+
let total = 0;
|
|
220
|
+
if (!store) return { kinds, done, total };
|
|
221
|
+
for (const task of store.tasks) {
|
|
222
|
+
if (!`${task.text ?? ''}`.trim()) continue;
|
|
223
|
+
const row = byId.get(taskKind(task));
|
|
224
|
+
row.total += 1;
|
|
225
|
+
total += 1;
|
|
226
|
+
if (!task.done) continue;
|
|
227
|
+
row.done += 1;
|
|
228
|
+
done += 1;
|
|
229
|
+
}
|
|
230
|
+
return { kinds, done, total };
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const versionFields = (pkg, outdatedMap) => {
|
|
234
|
+
const hit = outdatedMap ? outdatedMap.get(pkg.name) : null;
|
|
235
|
+
const current = (hit && hit.current) || pkg.version;
|
|
236
|
+
if (!outdatedMap) return { current, wanted: '', latest: '' };
|
|
237
|
+
if (!hit) return { current, wanted: current, latest: current };
|
|
238
|
+
return { current, wanted: hit.wanted, latest: hit.latest };
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const auditFields = (pkg, auditMap) => {
|
|
242
|
+
const finding = auditMap ? auditMap.get(pkg.name) : null;
|
|
243
|
+
return {
|
|
244
|
+
audit: Boolean(finding),
|
|
245
|
+
fix: finding && finding.fix ? finding.fix : '',
|
|
246
|
+
range: finding && finding.range ? finding.range : '',
|
|
247
|
+
severity: finding && finding.severity ? finding.severity : '',
|
|
248
|
+
title: finding && finding.title ? finding.title : '',
|
|
249
|
+
};
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const modulesModel = (modules, auditMap, outdatedMap) => {
|
|
253
|
+
const packages = modules.packages.map((pkg) => ({
|
|
254
|
+
name: pkg.name,
|
|
255
|
+
bytes: pkg.bytes,
|
|
256
|
+
dev: pkg.dev,
|
|
257
|
+
transitive: Boolean(pkg.transitive),
|
|
258
|
+
chain: pkg.chain || '',
|
|
259
|
+
...auditFields(pkg, auditMap),
|
|
260
|
+
...versionFields(pkg, outdatedMap),
|
|
261
|
+
}));
|
|
262
|
+
return { ...modules, packages };
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const npmModel = (input) => {
|
|
266
|
+
const info = input.npm;
|
|
267
|
+
const extras = input.npmExtras;
|
|
268
|
+
const auditMap = extras ? extras.auditMap : null;
|
|
269
|
+
const outdatedMap = extras ? extras.outdatedMap : null;
|
|
270
|
+
const npmRun = input.npmRun;
|
|
271
|
+
return {
|
|
272
|
+
ready: Boolean(info),
|
|
273
|
+
hasManifest: info ? info.hasManifest : false,
|
|
274
|
+
deps: info ? info.deps : 0,
|
|
275
|
+
dev: info ? info.dev : 0,
|
|
276
|
+
modules: info ? modulesModel(info.modules, auditMap, outdatedMap) : null,
|
|
277
|
+
audit: auditMap ? auditMap.size : null,
|
|
278
|
+
outdated: outdatedMap ? outdatedMap.size : null,
|
|
279
|
+
running: npmRun && npmRun.running ? npmRun.label : '',
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const minuteOf = (at) => Math.floor((at || 0) / MINUTE_MS);
|
|
284
|
+
|
|
285
|
+
const filesModel = (input) => {
|
|
286
|
+
const index = input.index;
|
|
287
|
+
const ready = Boolean(index && index.ready);
|
|
288
|
+
const summary = ready ? index.summary() : null;
|
|
289
|
+
const cold = { dirs: new Set(), exts: new Set() };
|
|
290
|
+
return {
|
|
291
|
+
ready,
|
|
292
|
+
total: summary ? summary.total : { files: 0, bytes: 0, lines: 0 },
|
|
293
|
+
dirs: summary ? summary.dirs : [],
|
|
294
|
+
exts: summary ? summary.exts : [],
|
|
295
|
+
hot: index ? index.hot(input.now) : cold,
|
|
296
|
+
delta: input.fileDelta,
|
|
297
|
+
};
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const diffsModel = (input) => {
|
|
301
|
+
const groups = groupChanges(input.entries);
|
|
302
|
+
return {
|
|
303
|
+
totals: input.totals,
|
|
304
|
+
dirs: groups.dirs,
|
|
305
|
+
exts: groups.exts,
|
|
306
|
+
files: input.entries.length,
|
|
307
|
+
activity: input.activity ?? { minutes: [], live: false },
|
|
308
|
+
delta: input.diffDelta,
|
|
309
|
+
};
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const commitsModel = (input) => {
|
|
313
|
+
const git = input.git;
|
|
314
|
+
return {
|
|
315
|
+
ready: Boolean(git),
|
|
316
|
+
rebase: git ? git.rebase : null,
|
|
317
|
+
info: git ? git.commits : null,
|
|
318
|
+
changedAt: input.marks.commit,
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const branchesModel = (input) => {
|
|
323
|
+
const git = input.git;
|
|
324
|
+
return {
|
|
325
|
+
ready: Boolean(git),
|
|
326
|
+
list: git ? git.branches : [],
|
|
327
|
+
rebase: git ? git.rebase : null,
|
|
328
|
+
switches: input.switches,
|
|
329
|
+
hot: input.branchAt,
|
|
330
|
+
};
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const tasksModel = (input) => taskKindCounts(input.store);
|
|
334
|
+
|
|
335
|
+
const buildModel = (input) => ({
|
|
336
|
+
now: input.now,
|
|
337
|
+
frame: input.frame,
|
|
338
|
+
busy: input.busy,
|
|
339
|
+
files: filesModel(input),
|
|
340
|
+
diffs: diffsModel(input),
|
|
341
|
+
commits: commitsModel(input),
|
|
342
|
+
branches: branchesModel(input),
|
|
343
|
+
npm: npmModel(input),
|
|
344
|
+
runs: mergeRuns(input.runs, input.npmRun),
|
|
345
|
+
tasks: tasksModel(input),
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
module.exports = {
|
|
349
|
+
MINUTE_MS,
|
|
350
|
+
minuteOf,
|
|
351
|
+
groupChanges,
|
|
352
|
+
mergeRuns,
|
|
353
|
+
scriptName,
|
|
354
|
+
runName,
|
|
355
|
+
npmModel,
|
|
356
|
+
buildModel,
|
|
357
|
+
};
|