@illumine/npm-diff 0.0.1
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/LICENSE +21 -0
- package/lib/index.cjs +193 -0
- package/lib/index.js +187 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 unbyte <i@shangyes.net>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/lib/index.cjs
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var extraTypings = require('@commander-js/extra-typings');
|
|
5
|
+
var zx = require('zx');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
var semver = require('semver');
|
|
8
|
+
var tar = require('tar');
|
|
9
|
+
var prompts = require('@inquirer/prompts');
|
|
10
|
+
var promises = require('fs/promises');
|
|
11
|
+
var unminify = require('@illumine/unminify');
|
|
12
|
+
var oxfmt = require('oxfmt');
|
|
13
|
+
|
|
14
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
|
|
16
|
+
var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
17
|
+
|
|
18
|
+
// src/error.ts
|
|
19
|
+
var CliError = class extends Error {
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// src/registry.ts
|
|
23
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
24
|
+
var ABBREVIATED = "application/vnd.npm.install-v1+json";
|
|
25
|
+
async function fetchPackument(pkg, registry) {
|
|
26
|
+
const url = `${registry.replace(/\/+$/, "")}/${pkg.replace("/", "%2F")}`;
|
|
27
|
+
let res;
|
|
28
|
+
try {
|
|
29
|
+
res = await fetch(url, { headers: { accept: ABBREVIATED } });
|
|
30
|
+
} catch (cause) {
|
|
31
|
+
throw new CliError(`Could not reach the npm registry: ${cause.message}`);
|
|
32
|
+
}
|
|
33
|
+
if (res.status === 404) {
|
|
34
|
+
throw new CliError(`Package '${pkg}' was not found on the npm registry.`);
|
|
35
|
+
}
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
throw new CliError(`The npm registry returned HTTP ${res.status} for '${pkg}'.`);
|
|
38
|
+
}
|
|
39
|
+
return await res.json();
|
|
40
|
+
}
|
|
41
|
+
function pickVersion(versions, message, exclude) {
|
|
42
|
+
const pool = exclude ? versions.filter((version) => version !== exclude) : versions;
|
|
43
|
+
return prompts.search({
|
|
44
|
+
message,
|
|
45
|
+
pageSize: 15,
|
|
46
|
+
source: async (term) => {
|
|
47
|
+
const matched = term ? pool.filter((version) => version.includes(term)) : pool;
|
|
48
|
+
return matched.map((version) => ({ name: version, value: version }));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function sortVersions(a, b) {
|
|
53
|
+
return semver__default.default.lt(a, b) ? [a, b] : [b, a];
|
|
54
|
+
}
|
|
55
|
+
var JS_FILES = "**/*.{js,cjs,mjs}";
|
|
56
|
+
var FORMATTABLE_FILES = "**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,css,html,htm,yaml,yml,json,jsonc,json5}";
|
|
57
|
+
async function unminifyTree(dir) {
|
|
58
|
+
for (const file of await zx.glob(JS_FILES, { cwd: dir, absolute: true, dot: true })) {
|
|
59
|
+
const code = await promises.readFile(file, "utf8");
|
|
60
|
+
try {
|
|
61
|
+
await promises.writeFile(file, await unminify.unminify(code, { filename: path.basename(file) }));
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function formatTree(dir) {
|
|
67
|
+
for (const file of await zx.glob(FORMATTABLE_FILES, { cwd: dir, absolute: true, dot: true })) {
|
|
68
|
+
const code = await promises.readFile(file, "utf8");
|
|
69
|
+
try {
|
|
70
|
+
const { code: formatted } = await oxfmt.format(path.basename(file), code, {
|
|
71
|
+
tabWidth: 2,
|
|
72
|
+
printWidth: 120
|
|
73
|
+
});
|
|
74
|
+
await promises.writeFile(file, formatted);
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
var EXTENSION_ID = "moshfeu.compare-folders";
|
|
80
|
+
async function ensureVscode() {
|
|
81
|
+
const code = await zx.which("code", { nothrow: true });
|
|
82
|
+
if (!code) {
|
|
83
|
+
throw new CliError(
|
|
84
|
+
"The VS Code CLI ('code') was not found on your PATH.\nInstall VS Code, then run the 'Shell Command: Install \\'code\\' command in PATH' command from its Command Palette."
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
const { stdout } = await zx.$`code --list-extensions`;
|
|
88
|
+
const installed = stdout.split("\n").map((line) => line.trim().toLowerCase());
|
|
89
|
+
if (installed.includes(EXTENSION_ID)) return;
|
|
90
|
+
const install = await prompts.confirm({
|
|
91
|
+
message: `The '${EXTENSION_ID}' extension is required but not installed. Install it now?`,
|
|
92
|
+
default: true
|
|
93
|
+
});
|
|
94
|
+
if (!install) {
|
|
95
|
+
throw new CliError(`Cannot continue without the '${EXTENSION_ID}' extension.`);
|
|
96
|
+
}
|
|
97
|
+
await zx.$({ stdio: "inherit" })`code --install-extension ${EXTENSION_ID}`;
|
|
98
|
+
}
|
|
99
|
+
async function launchDiff(left, right) {
|
|
100
|
+
await zx.$({
|
|
101
|
+
env: { ...process.env, COMPARE_FOLDERS: "DIFF" },
|
|
102
|
+
stdio: "inherit"
|
|
103
|
+
})`code --new-window --wait ${left} ${right}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/npm-diff.ts
|
|
107
|
+
var NpmDiff = class {
|
|
108
|
+
constructor(pkg, registry = DEFAULT_REGISTRY) {
|
|
109
|
+
this.pkg = pkg;
|
|
110
|
+
this.registry = registry;
|
|
111
|
+
}
|
|
112
|
+
pkg;
|
|
113
|
+
registry;
|
|
114
|
+
packument;
|
|
115
|
+
workdir = zx.tmpdir("npmdiff-");
|
|
116
|
+
async run(specA, specB) {
|
|
117
|
+
await ensureVscode();
|
|
118
|
+
this.packument = await zx.spinner(
|
|
119
|
+
`Fetching '${this.pkg}' from npm\u2026`,
|
|
120
|
+
() => fetchPackument(this.pkg, this.registry)
|
|
121
|
+
);
|
|
122
|
+
const [left, right] = specA && specB ? sortVersions(this.resolve(specA), this.resolve(specB)) : await this.pickVersions(specA);
|
|
123
|
+
if (left === right) {
|
|
124
|
+
throw new CliError(`Both specs resolve to ${left} \u2014 there is nothing to diff.`);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
await this.prepare(left);
|
|
128
|
+
await this.prepare(right);
|
|
129
|
+
console.log(zx.chalk.green(`Opening VS Code to diff ${this.pkg} ${left} \u2194 ${right}`));
|
|
130
|
+
await launchDiff(path.join(this.workdir, left), path.join(this.workdir, right));
|
|
131
|
+
console.log(zx.chalk.dim("VS Code closed \u2014 cleaning up temporary files."));
|
|
132
|
+
} finally {
|
|
133
|
+
await zx.fs.remove(this.workdir);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Resolve a version or dist-tag into a concrete published version. */
|
|
137
|
+
resolve(spec) {
|
|
138
|
+
const { versions, "dist-tags": tags } = this.packument;
|
|
139
|
+
const resolved = tags[spec] ?? (versions[spec] ? spec : void 0);
|
|
140
|
+
if (!resolved) {
|
|
141
|
+
throw new CliError(`'${spec}' is not a published version or dist-tag of this package.`);
|
|
142
|
+
}
|
|
143
|
+
return resolved;
|
|
144
|
+
}
|
|
145
|
+
async pickVersions(existing) {
|
|
146
|
+
const versions = Object.keys(this.packument.versions).sort(semver__default.default.rcompare);
|
|
147
|
+
if (existing) {
|
|
148
|
+
const version = this.resolve(existing);
|
|
149
|
+
return sortVersions(
|
|
150
|
+
version,
|
|
151
|
+
await pickVersion(versions, `Compare ${version} against`, version)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
const first = await pickVersion(versions, "Select the first version");
|
|
155
|
+
const second = await pickVersion(versions, "Select the second version", first);
|
|
156
|
+
return sortVersions(first, second);
|
|
157
|
+
}
|
|
158
|
+
async prepare(version) {
|
|
159
|
+
const label = `${this.pkg}@${version}`;
|
|
160
|
+
const dir = path.join(this.workdir, version);
|
|
161
|
+
await zx.fs.mkdirp(dir);
|
|
162
|
+
const tarball = await zx.spinner(`Downloading ${label}`, () => this.download(version, dir));
|
|
163
|
+
await zx.spinner(`Unpacking ${label}`, () => this.unpack(tarball, dir));
|
|
164
|
+
await zx.spinner(`Unminifying ${label}`, () => unminifyTree(dir));
|
|
165
|
+
await zx.spinner(`Formatting ${label}`, () => formatTree(dir));
|
|
166
|
+
}
|
|
167
|
+
async download(version, dir) {
|
|
168
|
+
const { stdout } = await zx.$`npm pack ${this.pkg}@${version} --registry ${this.registry} --pack-destination ${dir} --json`;
|
|
169
|
+
const [{ filename }] = JSON.parse(stdout);
|
|
170
|
+
return path.join(dir, filename);
|
|
171
|
+
}
|
|
172
|
+
async unpack(tarball, dir) {
|
|
173
|
+
await tar.extract({ file: tarball, cwd: dir, strip: 1 });
|
|
174
|
+
await zx.fs.remove(tarball);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/index.ts
|
|
179
|
+
zx.$.verbose = false;
|
|
180
|
+
var program = new extraTypings.Command();
|
|
181
|
+
program.name("npmdiff").description("Diff two versions of an npm package in VS Code, unminified and formatted").argument("<pkgname>", "npm package name (scoped names supported)").argument("[spec-a]", "a version or dist-tag").argument("[spec-b]", "a version or dist-tag").option("--registry <url>", "npm registry to query", DEFAULT_REGISTRY).action(
|
|
182
|
+
(pkgname, specA, specB, options) => new NpmDiff(pkgname, options.registry).run(specA, specB)
|
|
183
|
+
);
|
|
184
|
+
program.parseAsync().catch((error) => {
|
|
185
|
+
if (error instanceof CliError) {
|
|
186
|
+
console.error(zx.chalk.red(error.message));
|
|
187
|
+
} else if (error instanceof Error && error.name === "ExitPromptError") {
|
|
188
|
+
console.error(zx.chalk.yellow("Aborted."));
|
|
189
|
+
} else {
|
|
190
|
+
console.error(error);
|
|
191
|
+
}
|
|
192
|
+
process.exit(1);
|
|
193
|
+
});
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from '@commander-js/extra-typings';
|
|
3
|
+
import { $, chalk, tmpdir, spinner, fs, which, glob } from 'zx';
|
|
4
|
+
import { join, basename } from 'path';
|
|
5
|
+
import semver from 'semver';
|
|
6
|
+
import { extract } from 'tar';
|
|
7
|
+
import { confirm, search } from '@inquirer/prompts';
|
|
8
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
9
|
+
import { unminify } from '@illumine/unminify';
|
|
10
|
+
import { format } from 'oxfmt';
|
|
11
|
+
|
|
12
|
+
// src/error.ts
|
|
13
|
+
var CliError = class extends Error {
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/registry.ts
|
|
17
|
+
var DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
18
|
+
var ABBREVIATED = "application/vnd.npm.install-v1+json";
|
|
19
|
+
async function fetchPackument(pkg, registry) {
|
|
20
|
+
const url = `${registry.replace(/\/+$/, "")}/${pkg.replace("/", "%2F")}`;
|
|
21
|
+
let res;
|
|
22
|
+
try {
|
|
23
|
+
res = await fetch(url, { headers: { accept: ABBREVIATED } });
|
|
24
|
+
} catch (cause) {
|
|
25
|
+
throw new CliError(`Could not reach the npm registry: ${cause.message}`);
|
|
26
|
+
}
|
|
27
|
+
if (res.status === 404) {
|
|
28
|
+
throw new CliError(`Package '${pkg}' was not found on the npm registry.`);
|
|
29
|
+
}
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
throw new CliError(`The npm registry returned HTTP ${res.status} for '${pkg}'.`);
|
|
32
|
+
}
|
|
33
|
+
return await res.json();
|
|
34
|
+
}
|
|
35
|
+
function pickVersion(versions, message, exclude) {
|
|
36
|
+
const pool = exclude ? versions.filter((version) => version !== exclude) : versions;
|
|
37
|
+
return search({
|
|
38
|
+
message,
|
|
39
|
+
pageSize: 15,
|
|
40
|
+
source: async (term) => {
|
|
41
|
+
const matched = term ? pool.filter((version) => version.includes(term)) : pool;
|
|
42
|
+
return matched.map((version) => ({ name: version, value: version }));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function sortVersions(a, b) {
|
|
47
|
+
return semver.lt(a, b) ? [a, b] : [b, a];
|
|
48
|
+
}
|
|
49
|
+
var JS_FILES = "**/*.{js,cjs,mjs}";
|
|
50
|
+
var FORMATTABLE_FILES = "**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,css,html,htm,yaml,yml,json,jsonc,json5}";
|
|
51
|
+
async function unminifyTree(dir) {
|
|
52
|
+
for (const file of await glob(JS_FILES, { cwd: dir, absolute: true, dot: true })) {
|
|
53
|
+
const code = await readFile(file, "utf8");
|
|
54
|
+
try {
|
|
55
|
+
await writeFile(file, await unminify(code, { filename: basename(file) }));
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function formatTree(dir) {
|
|
61
|
+
for (const file of await glob(FORMATTABLE_FILES, { cwd: dir, absolute: true, dot: true })) {
|
|
62
|
+
const code = await readFile(file, "utf8");
|
|
63
|
+
try {
|
|
64
|
+
const { code: formatted } = await format(basename(file), code, {
|
|
65
|
+
tabWidth: 2,
|
|
66
|
+
printWidth: 120
|
|
67
|
+
});
|
|
68
|
+
await writeFile(file, formatted);
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
var EXTENSION_ID = "moshfeu.compare-folders";
|
|
74
|
+
async function ensureVscode() {
|
|
75
|
+
const code = await which("code", { nothrow: true });
|
|
76
|
+
if (!code) {
|
|
77
|
+
throw new CliError(
|
|
78
|
+
"The VS Code CLI ('code') was not found on your PATH.\nInstall VS Code, then run the 'Shell Command: Install \\'code\\' command in PATH' command from its Command Palette."
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const { stdout } = await $`code --list-extensions`;
|
|
82
|
+
const installed = stdout.split("\n").map((line) => line.trim().toLowerCase());
|
|
83
|
+
if (installed.includes(EXTENSION_ID)) return;
|
|
84
|
+
const install = await confirm({
|
|
85
|
+
message: `The '${EXTENSION_ID}' extension is required but not installed. Install it now?`,
|
|
86
|
+
default: true
|
|
87
|
+
});
|
|
88
|
+
if (!install) {
|
|
89
|
+
throw new CliError(`Cannot continue without the '${EXTENSION_ID}' extension.`);
|
|
90
|
+
}
|
|
91
|
+
await $({ stdio: "inherit" })`code --install-extension ${EXTENSION_ID}`;
|
|
92
|
+
}
|
|
93
|
+
async function launchDiff(left, right) {
|
|
94
|
+
await $({
|
|
95
|
+
env: { ...process.env, COMPARE_FOLDERS: "DIFF" },
|
|
96
|
+
stdio: "inherit"
|
|
97
|
+
})`code --new-window --wait ${left} ${right}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/npm-diff.ts
|
|
101
|
+
var NpmDiff = class {
|
|
102
|
+
constructor(pkg, registry = DEFAULT_REGISTRY) {
|
|
103
|
+
this.pkg = pkg;
|
|
104
|
+
this.registry = registry;
|
|
105
|
+
}
|
|
106
|
+
pkg;
|
|
107
|
+
registry;
|
|
108
|
+
packument;
|
|
109
|
+
workdir = tmpdir("npmdiff-");
|
|
110
|
+
async run(specA, specB) {
|
|
111
|
+
await ensureVscode();
|
|
112
|
+
this.packument = await spinner(
|
|
113
|
+
`Fetching '${this.pkg}' from npm\u2026`,
|
|
114
|
+
() => fetchPackument(this.pkg, this.registry)
|
|
115
|
+
);
|
|
116
|
+
const [left, right] = specA && specB ? sortVersions(this.resolve(specA), this.resolve(specB)) : await this.pickVersions(specA);
|
|
117
|
+
if (left === right) {
|
|
118
|
+
throw new CliError(`Both specs resolve to ${left} \u2014 there is nothing to diff.`);
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
await this.prepare(left);
|
|
122
|
+
await this.prepare(right);
|
|
123
|
+
console.log(chalk.green(`Opening VS Code to diff ${this.pkg} ${left} \u2194 ${right}`));
|
|
124
|
+
await launchDiff(join(this.workdir, left), join(this.workdir, right));
|
|
125
|
+
console.log(chalk.dim("VS Code closed \u2014 cleaning up temporary files."));
|
|
126
|
+
} finally {
|
|
127
|
+
await fs.remove(this.workdir);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/** Resolve a version or dist-tag into a concrete published version. */
|
|
131
|
+
resolve(spec) {
|
|
132
|
+
const { versions, "dist-tags": tags } = this.packument;
|
|
133
|
+
const resolved = tags[spec] ?? (versions[spec] ? spec : void 0);
|
|
134
|
+
if (!resolved) {
|
|
135
|
+
throw new CliError(`'${spec}' is not a published version or dist-tag of this package.`);
|
|
136
|
+
}
|
|
137
|
+
return resolved;
|
|
138
|
+
}
|
|
139
|
+
async pickVersions(existing) {
|
|
140
|
+
const versions = Object.keys(this.packument.versions).sort(semver.rcompare);
|
|
141
|
+
if (existing) {
|
|
142
|
+
const version = this.resolve(existing);
|
|
143
|
+
return sortVersions(
|
|
144
|
+
version,
|
|
145
|
+
await pickVersion(versions, `Compare ${version} against`, version)
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const first = await pickVersion(versions, "Select the first version");
|
|
149
|
+
const second = await pickVersion(versions, "Select the second version", first);
|
|
150
|
+
return sortVersions(first, second);
|
|
151
|
+
}
|
|
152
|
+
async prepare(version) {
|
|
153
|
+
const label = `${this.pkg}@${version}`;
|
|
154
|
+
const dir = join(this.workdir, version);
|
|
155
|
+
await fs.mkdirp(dir);
|
|
156
|
+
const tarball = await spinner(`Downloading ${label}`, () => this.download(version, dir));
|
|
157
|
+
await spinner(`Unpacking ${label}`, () => this.unpack(tarball, dir));
|
|
158
|
+
await spinner(`Unminifying ${label}`, () => unminifyTree(dir));
|
|
159
|
+
await spinner(`Formatting ${label}`, () => formatTree(dir));
|
|
160
|
+
}
|
|
161
|
+
async download(version, dir) {
|
|
162
|
+
const { stdout } = await $`npm pack ${this.pkg}@${version} --registry ${this.registry} --pack-destination ${dir} --json`;
|
|
163
|
+
const [{ filename }] = JSON.parse(stdout);
|
|
164
|
+
return join(dir, filename);
|
|
165
|
+
}
|
|
166
|
+
async unpack(tarball, dir) {
|
|
167
|
+
await extract({ file: tarball, cwd: dir, strip: 1 });
|
|
168
|
+
await fs.remove(tarball);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// src/index.ts
|
|
173
|
+
$.verbose = false;
|
|
174
|
+
var program = new Command();
|
|
175
|
+
program.name("npmdiff").description("Diff two versions of an npm package in VS Code, unminified and formatted").argument("<pkgname>", "npm package name (scoped names supported)").argument("[spec-a]", "a version or dist-tag").argument("[spec-b]", "a version or dist-tag").option("--registry <url>", "npm registry to query", DEFAULT_REGISTRY).action(
|
|
176
|
+
(pkgname, specA, specB, options) => new NpmDiff(pkgname, options.registry).run(specA, specB)
|
|
177
|
+
);
|
|
178
|
+
program.parseAsync().catch((error) => {
|
|
179
|
+
if (error instanceof CliError) {
|
|
180
|
+
console.error(chalk.red(error.message));
|
|
181
|
+
} else if (error instanceof Error && error.name === "ExitPromptError") {
|
|
182
|
+
console.error(chalk.yellow("Aborted."));
|
|
183
|
+
} else {
|
|
184
|
+
console.error(error);
|
|
185
|
+
}
|
|
186
|
+
process.exit(1);
|
|
187
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@illumine/npm-diff",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Diff two versions of an npm package in VS Code, unminified and formatted",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"npmdiff": "./lib/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"lib"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"npm",
|
|
14
|
+
"diff",
|
|
15
|
+
"unminify",
|
|
16
|
+
"version",
|
|
17
|
+
"compare",
|
|
18
|
+
"vscode"
|
|
19
|
+
],
|
|
20
|
+
"homepage": "https://github.com/unbyte/illumine/tree/main/packages/npm-diff#readme",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/unbyte/illumine.git",
|
|
24
|
+
"directory": "packages/npm-diff"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/unbyte/illumine/issues"
|
|
28
|
+
},
|
|
29
|
+
"author": {
|
|
30
|
+
"name": "unbyte",
|
|
31
|
+
"url": "https://github.com/unbyte"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@inquirer/prompts": "^8.5.2",
|
|
36
|
+
"@commander-js/extra-typings": "^15.0.0",
|
|
37
|
+
"commander": "^15.0.0",
|
|
38
|
+
"oxfmt": "~0.53.0",
|
|
39
|
+
"semver": "^7.8.5",
|
|
40
|
+
"tar": "^7.5.19",
|
|
41
|
+
"zx": "^8.8.5",
|
|
42
|
+
"@illumine/unminify": "0.0.1"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsup"
|
|
49
|
+
}
|
|
50
|
+
}
|