reslop 0.2.5 → 0.2.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/CHANGELOG.md +12 -1
- package/LICENSE +1 -1
- package/README.md +11 -11
- package/bin/reslop.js +3 -8
- package/lib/ansi.js +32 -19
- package/lib/capabilities.js +8 -8
- package/lib/cli.js +40 -74
- package/lib/clipboard.js +39 -47
- package/lib/dashboard/git.js +128 -0
- package/lib/dashboard/model.js +332 -0
- package/lib/dashboard/npm.js +193 -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 +71 -89
- package/lib/git-branches.js +254 -416
- package/lib/git-deps.js +147 -272
- package/lib/git-reword-todo.js +5 -13
- package/lib/git-worktree.js +141 -212
- 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 +49 -82
- 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 +220 -333
- package/lib/render/commits.js +160 -361
- package/lib/render/dash-activity.js +212 -0
- package/lib/render/dash-blocks.js +245 -0
- package/lib/render/dash-table.js +290 -0
- package/lib/render/dashboard.js +62 -0
- package/lib/render/diff.js +123 -258
- package/lib/render/files.js +40 -85
- package/lib/render/frame.js +78 -117
- package/lib/render/notes.js +139 -210
- package/lib/render/npm.js +213 -177
- package/lib/render/present.js +4 -11
- package/lib/render/primitives.js +72 -174
- package/lib/render/render.js +5 -14
- package/lib/render/report.js +43 -0
- package/lib/render/tiles.js +260 -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 +68 -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 +61 -43
- package/lib/session/branches.js +166 -222
- package/lib/session/change-actions.js +49 -119
- package/lib/session/commit.js +274 -355
- package/lib/session/compose.js +556 -714
- package/lib/session/dashboard.js +385 -0
- package/lib/session/dispatch.js +162 -170
- package/lib/session/files-pane.js +76 -44
- package/lib/session/items.js +6 -17
- package/lib/session/lifecycle.js +393 -466
- package/lib/session/load.js +1 -14
- package/lib/session/navigation.js +2 -2
- package/lib/session/npm.js +403 -420
- package/lib/session/ops.js +5 -13
- package/lib/session/pointer.js +16 -14
- package/lib/session/progress.js +39 -30
- package/lib/session/review.js +1 -3
- package/lib/session/tasks.js +276 -235
- package/lib/session/templates.js +51 -59
- package/lib/session/terminal.js +85 -132
- package/lib/session/view.js +47 -81
- package/lib/session/watch.js +196 -212
- package/lib/session.js +81 -161
- package/lib/update.js +44 -111
- package/lib/utilities.js +46 -88
- package/lib/wrap.js +29 -55
- package/package.json +1 -1
package/lib/manifest.js
CHANGED
|
@@ -15,20 +15,17 @@ const SECTION_KEYS = [
|
|
|
15
15
|
'optionalDependencies',
|
|
16
16
|
'peerDependencies',
|
|
17
17
|
];
|
|
18
|
+
const LOCK_PREFIX = 'node_modules/';
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
};
|
|
20
|
+
const isObject = (value) => !!value && typeof value === 'object';
|
|
21
|
+
|
|
22
|
+
const posixRel = (rel) => `${rel ?? ''}`.replaceAll('\\', '/');
|
|
23
23
|
|
|
24
24
|
const depFileMeta = (rel) => {
|
|
25
25
|
const normalized = posixRel(rel);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!kind) return null;
|
|
30
|
-
const dir = path.posix.dirname(normalized);
|
|
31
|
-
return { kind, dir, base, rel: normalized };
|
|
26
|
+
const kind = DEP_KIND[path.posix.basename(normalized)];
|
|
27
|
+
if (!normalized || !kind) return null;
|
|
28
|
+
return { kind, dir: path.posix.dirname(normalized) };
|
|
32
29
|
};
|
|
33
30
|
|
|
34
31
|
const relOf = (dir, name) => (dir === '.' ? name : `${dir}/${name}`);
|
|
@@ -59,28 +56,22 @@ const emptySectionMaps = () => readSections(null);
|
|
|
59
56
|
|
|
60
57
|
const lockRootSections = (lock) => {
|
|
61
58
|
if (!lock) return emptySectionMaps();
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const src = root && typeof root === 'object' ? root : lock;
|
|
65
|
-
return readSections(src);
|
|
59
|
+
const root = isObject(lock.packages) ? lock.packages[''] : null;
|
|
60
|
+
return readSections(isObject(root) ? root : lock);
|
|
66
61
|
};
|
|
67
62
|
|
|
68
63
|
const lockEntries = (lock) => {
|
|
69
64
|
const versions = new Map();
|
|
70
65
|
if (!lock) return versions;
|
|
71
|
-
const packages = lock.packages;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const name = key.slice('node_modules/'.length);
|
|
79
|
-
versions.set(name, entry.version);
|
|
80
|
-
}
|
|
66
|
+
const packages = isObject(lock.packages) ? lock.packages : {};
|
|
67
|
+
for (const key of Object.keys(packages)) {
|
|
68
|
+
const entry = packages[key];
|
|
69
|
+
if (!key.startsWith(LOCK_PREFIX)) continue;
|
|
70
|
+
if (key.includes('/node_modules/')) continue;
|
|
71
|
+
if (!entry || typeof entry.version !== 'string') continue;
|
|
72
|
+
versions.set(key.slice(LOCK_PREFIX.length), entry.version);
|
|
81
73
|
}
|
|
82
|
-
const deps = lock.dependencies;
|
|
83
|
-
if (!deps || typeof deps !== 'object') return versions;
|
|
74
|
+
const deps = isObject(lock.dependencies) ? lock.dependencies : {};
|
|
84
75
|
for (const name of Object.keys(deps)) {
|
|
85
76
|
const entry = deps[name];
|
|
86
77
|
if (versions.has(name)) continue;
|
|
@@ -92,44 +83,31 @@ const lockEntries = (lock) => {
|
|
|
92
83
|
|
|
93
84
|
const lockPackageCount = (lock) => {
|
|
94
85
|
if (!lock) return 0;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
let count = 0;
|
|
98
|
-
for (const key of Object.keys(packages)) {
|
|
99
|
-
if (key !== '') count += 1;
|
|
100
|
-
}
|
|
101
|
-
return count;
|
|
86
|
+
if (isObject(lock.packages)) {
|
|
87
|
+
return Object.keys(lock.packages).filter((key) => key !== '').length;
|
|
102
88
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return Object.keys(deps).length;
|
|
89
|
+
if (!isObject(lock.dependencies)) return 0;
|
|
90
|
+
return Object.keys(lock.dependencies).length;
|
|
106
91
|
};
|
|
107
92
|
|
|
108
93
|
const cloneJson = (value) => JSON.parse(JSON.stringify(value ?? null));
|
|
109
94
|
|
|
110
|
-
const detectIndent = (text) => {
|
|
111
|
-
const match = /\n([ \t]+)"/.exec(text);
|
|
112
|
-
if (!match) return 2;
|
|
113
|
-
return match[1];
|
|
114
|
-
};
|
|
115
|
-
|
|
116
95
|
const stringifyJson = (value, original) => {
|
|
117
|
-
const
|
|
118
|
-
const
|
|
119
|
-
return `${
|
|
96
|
+
const match = /\n([ \t]+)"/.exec(original);
|
|
97
|
+
const indent = match ? match[1] : 2;
|
|
98
|
+
return `${JSON.stringify(value, null, indent)}\n`;
|
|
120
99
|
};
|
|
121
100
|
|
|
122
101
|
const setSectionEntry = (pkg, section, name, version) => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (!map
|
|
126
|
-
|
|
127
|
-
if (!Object.keys(map).length) delete pkg[section];
|
|
102
|
+
const map = pkg[section];
|
|
103
|
+
if (version) {
|
|
104
|
+
if (!isObject(map)) pkg[section] = {};
|
|
105
|
+
pkg[section][name] = version;
|
|
128
106
|
return;
|
|
129
107
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
pkg[section]
|
|
108
|
+
if (!isObject(map)) return;
|
|
109
|
+
delete map[name];
|
|
110
|
+
if (!Object.keys(map).length) delete pkg[section];
|
|
133
111
|
};
|
|
134
112
|
|
|
135
113
|
const dropsEntry = (change, side) => {
|
|
@@ -138,73 +116,41 @@ const dropsEntry = (change, side) => {
|
|
|
138
116
|
};
|
|
139
117
|
|
|
140
118
|
const applyManifestChange = (pkg, change, side) => {
|
|
141
|
-
if (change.section === 'resolved') return
|
|
119
|
+
if (change.section === 'resolved') return;
|
|
142
120
|
const value = side === 'new' ? change.to : change.from;
|
|
143
|
-
if (change.section === 'field') {
|
|
144
|
-
if (value === '') {
|
|
145
|
-
delete pkg[change.name];
|
|
146
|
-
return pkg;
|
|
147
|
-
}
|
|
148
|
-
pkg[change.name] = jsonParse(value ?? '') ?? value;
|
|
149
|
-
return pkg;
|
|
150
|
-
}
|
|
151
121
|
const version = dropsEntry(change, side) ? '' : value;
|
|
152
122
|
setSectionEntry(pkg, change.section, change.name, version);
|
|
153
|
-
return pkg;
|
|
154
123
|
};
|
|
155
124
|
|
|
156
|
-
const
|
|
157
|
-
if (!lock.packages
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
const root = lock.packages[''];
|
|
161
|
-
if (!root || typeof root !== 'object') lock.packages[''] = {};
|
|
125
|
+
const lockRoot = (lock) => {
|
|
126
|
+
if (!isObject(lock.packages)) lock.packages = {};
|
|
127
|
+
if (!isObject(lock.packages[''])) lock.packages[''] = {};
|
|
162
128
|
return lock.packages[''];
|
|
163
129
|
};
|
|
164
130
|
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const srcDeps = src && src.dependencies;
|
|
173
|
-
if (!srcDeps || typeof srcDeps !== 'object') return;
|
|
174
|
-
const entry = srcDeps[change.name];
|
|
175
|
-
if (entry) deps[change.name] = cloneJson(entry);
|
|
131
|
+
const copyLockEntry = (target, source, key, drop) => {
|
|
132
|
+
if (!isObject(target)) return;
|
|
133
|
+
if (drop) return void delete target[key];
|
|
134
|
+
const entry = isObject(source) ? source[key] : null;
|
|
135
|
+
if (entry) target[key] = cloneJson(entry);
|
|
176
136
|
};
|
|
177
137
|
|
|
178
138
|
const applyLockChange = (lock, change, side, oldLock, newLock) => {
|
|
179
|
-
|
|
180
|
-
const
|
|
139
|
+
const src = (side === 'new' ? newLock : oldLock) ?? {};
|
|
140
|
+
const drop = dropsEntry(change, side);
|
|
181
141
|
if (change.section !== 'resolved') {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
applyLegacyLockDep(lock, change, side, src);
|
|
185
|
-
}
|
|
186
|
-
const packages = lock.packages;
|
|
187
|
-
if (!packages || typeof packages !== 'object') return lock;
|
|
188
|
-
const key = `node_modules/${change.name}`;
|
|
189
|
-
if (dropsEntry(change, side)) {
|
|
190
|
-
delete packages[key];
|
|
191
|
-
return lock;
|
|
142
|
+
applyManifestChange(lockRoot(lock), change, side);
|
|
143
|
+
copyLockEntry(lock.dependencies, src.dependencies, change.name, drop);
|
|
192
144
|
}
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
const entry = srcPkgs[key];
|
|
196
|
-
if (entry) packages[key] = cloneJson(entry);
|
|
197
|
-
return lock;
|
|
145
|
+
const key = `${LOCK_PREFIX}${change.name}`;
|
|
146
|
+
copyLockEntry(lock.packages, src.packages, key, drop);
|
|
198
147
|
};
|
|
199
148
|
|
|
200
149
|
const seedManifest = (oldObj, newObj) => {
|
|
201
150
|
const base = cloneJson(oldObj) || {};
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (SECTION_KEYS.includes(key)) continue;
|
|
206
|
-
if (Object.hasOwn(base, key)) continue;
|
|
207
|
-
base[key] = cloneJson(value);
|
|
151
|
+
for (const key of Object.keys(newObj ?? {})) {
|
|
152
|
+
if (SECTION_KEYS.includes(key) || Object.hasOwn(base, key)) continue;
|
|
153
|
+
base[key] = cloneJson(newObj[key]);
|
|
208
154
|
}
|
|
209
155
|
return base;
|
|
210
156
|
};
|
|
@@ -219,8 +165,7 @@ const mergeDepFile = (baseText, oldText, newText, change, side, kind) => {
|
|
|
219
165
|
else base = cloneJson(oldObj) || {};
|
|
220
166
|
if (kind === 'lockfile') applyLockChange(base, change, side, oldObj, newObj);
|
|
221
167
|
else applyManifestChange(base, change, side);
|
|
222
|
-
|
|
223
|
-
return stringifyJson(base, original);
|
|
168
|
+
return stringifyJson(base, baseText || newText || oldText || '');
|
|
224
169
|
};
|
|
225
170
|
|
|
226
171
|
const applyWantedRange = (declared, wanted) => {
|
|
@@ -229,25 +174,26 @@ const applyWantedRange = (declared, wanted) => {
|
|
|
229
174
|
if (/^(file:|git[+@:]|workspace:|https?:|npm:)/.test(declared)) {
|
|
230
175
|
return declared;
|
|
231
176
|
}
|
|
232
|
-
if (
|
|
233
|
-
if (declared.includes('<') || declared.includes('>')) return declared;
|
|
177
|
+
if (/[ |<>]/.test(declared)) return declared;
|
|
234
178
|
const prefix = declared.startsWith('^') || declared.startsWith('~');
|
|
235
179
|
const mark = prefix ? declared[0] : '';
|
|
236
180
|
return `${mark}${wanted}`;
|
|
237
181
|
};
|
|
238
182
|
|
|
183
|
+
const declaredIn = (pkg, section, name) => {
|
|
184
|
+
const map = pkg[section];
|
|
185
|
+
if (!map || typeof map[name] !== 'string') return null;
|
|
186
|
+
return { section, version: map[name] };
|
|
187
|
+
};
|
|
188
|
+
|
|
239
189
|
const findDeclared = (pkg, name, type) => {
|
|
240
190
|
if (type && SECTION_KEYS.includes(type)) {
|
|
241
|
-
const
|
|
242
|
-
if (
|
|
243
|
-
return { section: type, version: map[name] };
|
|
244
|
-
}
|
|
191
|
+
const found = declaredIn(pkg, type, name);
|
|
192
|
+
if (found) return found;
|
|
245
193
|
}
|
|
246
194
|
for (const section of SECTION_KEYS) {
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
249
|
-
return { section, version: map[name] };
|
|
250
|
-
}
|
|
195
|
+
const found = declaredIn(pkg, section, name);
|
|
196
|
+
if (found) return found;
|
|
251
197
|
}
|
|
252
198
|
return null;
|
|
253
199
|
};
|
|
@@ -255,15 +201,12 @@ const findDeclared = (pkg, name, type) => {
|
|
|
255
201
|
const fmtVer = (parts) => `${parts.major}.${parts.minor}.${parts.patch}`;
|
|
256
202
|
|
|
257
203
|
const clauseUpper = (clause) => {
|
|
258
|
-
const pattern = /(<=?)\s*(\d+\.\d+\.\d+)/g;
|
|
259
|
-
const matches = clause.matchAll(pattern);
|
|
260
204
|
let best = null;
|
|
261
|
-
for (const match of
|
|
262
|
-
const op = match[1];
|
|
205
|
+
for (const match of clause.matchAll(/(<=?)\s*(\d+\.\d+\.\d+)/g)) {
|
|
263
206
|
const parsed = parseVersion(match[2]);
|
|
264
207
|
if (!parsed) continue;
|
|
265
208
|
if (best && cmpVersion(parsed, best.ver) >= 0) continue;
|
|
266
|
-
best = { op, ver: parsed };
|
|
209
|
+
best = { op: match[1], ver: parsed };
|
|
267
210
|
}
|
|
268
211
|
return best;
|
|
269
212
|
};
|
|
@@ -272,8 +215,7 @@ const patchedFromRange = (current, range) => {
|
|
|
272
215
|
if (!current || !range) return '';
|
|
273
216
|
const now = parseVersion(current);
|
|
274
217
|
if (!now) return '';
|
|
275
|
-
const
|
|
276
|
-
for (const clause of clauses) {
|
|
218
|
+
for (const clause of `${range}`.split('||')) {
|
|
277
219
|
const upper = clauseUpper(clause);
|
|
278
220
|
if (!upper) continue;
|
|
279
221
|
if (now.major !== upper.ver.major) continue;
|
|
@@ -287,8 +229,7 @@ const patchedFromRange = (current, range) => {
|
|
|
287
229
|
const sameMajor = (from, to) => {
|
|
288
230
|
const left = parseVersion(from);
|
|
289
231
|
const right = parseVersion(to);
|
|
290
|
-
|
|
291
|
-
return left.major === right.major;
|
|
232
|
+
return !!left && !!right && left.major === right.major;
|
|
292
233
|
};
|
|
293
234
|
|
|
294
235
|
const proposedLockVersion = (current, vul) => {
|
|
@@ -297,8 +238,7 @@ const proposedLockVersion = (current, vul) => {
|
|
|
297
238
|
const fix = vul.fix;
|
|
298
239
|
if (fix && sameMajor(current, fix) && fix !== current) return fix;
|
|
299
240
|
const patched = patchedFromRange(current, vul.range);
|
|
300
|
-
|
|
301
|
-
return current;
|
|
241
|
+
return patched || current;
|
|
302
242
|
};
|
|
303
243
|
|
|
304
244
|
const proposedWanted = (out, vul) => {
|
|
@@ -311,6 +251,7 @@ module.exports = {
|
|
|
311
251
|
MANIFEST,
|
|
312
252
|
LOCKFILE,
|
|
313
253
|
SECTION_KEYS,
|
|
254
|
+
isObject,
|
|
314
255
|
depFileMeta,
|
|
315
256
|
relOf,
|
|
316
257
|
listFilePath,
|