@badisi/latest-version 8.0.5 → 9.0.0
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/README.md +10 -23
- package/index.cjs +229 -0
- package/index.d.cts +152 -0
- package/index.d.mts +152 -0
- package/index.mjs +201 -0
- package/package.json +20 -14
- package/bin/latest-version +0 -5
- package/cli.d.ts +0 -1
- package/cli.js +0 -239
- package/index.d.ts +0 -146
- package/index.js +0 -248
package/README.md
CHANGED
|
@@ -32,7 +32,11 @@
|
|
|
32
32
|
✅ Check if any `updates` are available<br/>
|
|
33
33
|
✅ Cache support to increase data retrieval performance<br/>
|
|
34
34
|
✅ Support public/private repositories and proxies<br/>
|
|
35
|
-
✅
|
|
35
|
+
✅ Dual build support (CJS/ESM)<br/>
|
|
36
|
+
|
|
37
|
+
🚀 Check out 👉🏻 [@badisi/check-updates][checkupdates]<br/>
|
|
38
|
+
✅ An interactive CLI to scan global or local dependencies and upgrade to wanted or latest versions !
|
|
39
|
+
|
|
36
40
|
|
|
37
41
|
## Installation
|
|
38
42
|
|
|
@@ -50,12 +54,12 @@ __Example__
|
|
|
50
54
|
|
|
51
55
|
```ts
|
|
52
56
|
/** CommonJS */
|
|
53
|
-
// const {
|
|
54
|
-
// const
|
|
57
|
+
// const { latestVersion } = require('@badisi/latest-version');
|
|
58
|
+
// const { readFileSync } = require('node:fs');
|
|
55
59
|
|
|
56
60
|
/** ESM / Typescript */
|
|
57
|
-
import {
|
|
58
|
-
import
|
|
61
|
+
import { latestVersion } from '@badisi/latest-version';
|
|
62
|
+
import { readFileSync } from 'node:fs';
|
|
59
63
|
|
|
60
64
|
(async () => {
|
|
61
65
|
// Single package
|
|
@@ -177,23 +181,6 @@ interface LatestVersionOptions {
|
|
|
177
181
|
```
|
|
178
182
|
|
|
179
183
|
|
|
180
|
-
## Command line tool
|
|
181
|
-
|
|
182
|
-
The CLI utility will help you visualize any available updates for a given *package.json* file, a local *package.json* file or any provided package names.
|
|
183
|
-
|
|
184
|
-
```sh
|
|
185
|
-
$ latest-version <packageJson|packageName...>
|
|
186
|
-
|
|
187
|
-
Examples:
|
|
188
|
-
$ lv
|
|
189
|
-
$ latest-version path/to/package.json
|
|
190
|
-
$ latest-version package1 package2 package3 --skip-missing
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
![CLI utility preview][clipreview]
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
184
|
## Development
|
|
198
185
|
|
|
199
186
|
See the [developer docs][developer].
|
|
@@ -214,7 +201,7 @@ Please read and follow the [Code of Conduct][codeofconduct] and help me keep thi
|
|
|
214
201
|
|
|
215
202
|
|
|
216
203
|
|
|
217
|
-
[
|
|
204
|
+
[checkupdates]: https://github.com/Badisi/check-updates
|
|
218
205
|
[developer]: https://github.com/Badisi/latest-version/blob/main/DEVELOPER.md
|
|
219
206
|
[contributing]: https://github.com/Badisi/latest-version/blob/main/CONTRIBUTING.md
|
|
220
207
|
[codeofconduct]: https://github.com/Badisi/latest-version/blob/main/CODE_OF_CONDUCT.md
|
package/index.cjs
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
let global_dirs = require("global-dirs");
|
|
25
|
+
let node_fs_promises = require("node:fs/promises");
|
|
26
|
+
let node_path = require("node:path");
|
|
27
|
+
let semver_functions_gt_js = require("semver/functions/gt.js");
|
|
28
|
+
semver_functions_gt_js = __toESM(semver_functions_gt_js, 1);
|
|
29
|
+
let semver_ranges_max_satisfying_js = require("semver/ranges/max-satisfying.js");
|
|
30
|
+
semver_ranges_max_satisfying_js = __toESM(semver_ranges_max_satisfying_js, 1);
|
|
31
|
+
let node_fs = require("node:fs");
|
|
32
|
+
let node_os = require("node:os");
|
|
33
|
+
let node_http = require("node:http");
|
|
34
|
+
let node_https = require("node:https");
|
|
35
|
+
let node_url = require("node:url");
|
|
36
|
+
let registry_auth_token = require("registry-auth-token");
|
|
37
|
+
registry_auth_token = __toESM(registry_auth_token, 1);
|
|
38
|
+
let registry_auth_token_registry_url_js = require("registry-auth-token/registry-url.js");
|
|
39
|
+
registry_auth_token_registry_url_js = __toESM(registry_auth_token_registry_url_js, 1);
|
|
40
|
+
//#region src/cache.ts
|
|
41
|
+
const ONE_DAY = 1e3 * 60 * 60 * 24;
|
|
42
|
+
const getCacheDir = (name = "@badisi/latest-version") => {
|
|
43
|
+
const homeDir = (0, node_os.homedir)();
|
|
44
|
+
switch (process.platform) {
|
|
45
|
+
case "darwin": return (0, node_path.join)(homeDir, "Library", "Caches", name);
|
|
46
|
+
case "win32": return (0, node_path.join)(process.env["LOCALAPPDATA"] ?? (0, node_path.join)(homeDir, "AppData", "Local"), name, "Cache");
|
|
47
|
+
default: return (0, node_path.join)(process.env["XDG_CACHE_HOME"] ?? (0, node_path.join)(homeDir, ".cache"), name);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const saveMetadataToCache = (pkg) => {
|
|
51
|
+
const filePath = (0, node_path.join)(getCacheDir(), `${pkg.name}.json`);
|
|
52
|
+
if (!(0, node_fs.existsSync)((0, node_path.dirname)(filePath))) (0, node_fs.mkdirSync)((0, node_path.dirname)(filePath), { recursive: true });
|
|
53
|
+
(0, node_fs.writeFileSync)(filePath, JSON.stringify(pkg));
|
|
54
|
+
};
|
|
55
|
+
const getMetadataFromCache = (pkgName, options) => {
|
|
56
|
+
const maxAge = options?.cacheMaxAge ?? 864e5;
|
|
57
|
+
if (maxAge !== 0) {
|
|
58
|
+
const pkgCacheFilePath = (0, node_path.join)(getCacheDir(), `${pkgName}.json`);
|
|
59
|
+
if ((0, node_fs.existsSync)(pkgCacheFilePath)) {
|
|
60
|
+
const pkg = JSON.parse((0, node_fs.readFileSync)(pkgCacheFilePath).toString());
|
|
61
|
+
if (Date.now() - pkg.lastUpdateDate < maxAge) return pkg;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/metadata.ts
|
|
67
|
+
const downloadMetadata = (pkgName, options) => new Promise((resolve, reject) => {
|
|
68
|
+
const i = pkgName.indexOf("/");
|
|
69
|
+
const pkgScope = i !== -1 ? pkgName.slice(0, i) : "";
|
|
70
|
+
const registryUrl = options?.registryUrl ?? (0, registry_auth_token_registry_url_js.default)(pkgScope);
|
|
71
|
+
const pkgUrl = new node_url.URL(encodeURIComponent(pkgName).replace(/^%40/, "@"), registryUrl);
|
|
72
|
+
let requestOptions = {
|
|
73
|
+
headers: { accept: "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*" },
|
|
74
|
+
host: pkgUrl.hostname,
|
|
75
|
+
path: pkgUrl.pathname,
|
|
76
|
+
port: pkgUrl.port
|
|
77
|
+
};
|
|
78
|
+
const authInfo = (0, registry_auth_token.default)(pkgUrl.toString(), { recursive: true });
|
|
79
|
+
if (authInfo && requestOptions.headers) requestOptions.headers.authorization = `${authInfo.type} ${authInfo.token}`;
|
|
80
|
+
if (options?.requestOptions) requestOptions = {
|
|
81
|
+
...requestOptions,
|
|
82
|
+
...options.requestOptions
|
|
83
|
+
};
|
|
84
|
+
const request = (pkgUrl.protocol === "https:" ? node_https.get : node_http.get)(requestOptions, (res) => {
|
|
85
|
+
if (res.statusCode === 200) {
|
|
86
|
+
let rawData = "";
|
|
87
|
+
res.setEncoding("utf8");
|
|
88
|
+
res.on("data", (chunk) => rawData += chunk);
|
|
89
|
+
res.once("error", (err) => {
|
|
90
|
+
res.removeAllListeners();
|
|
91
|
+
reject(/* @__PURE__ */ new Error(`Request error (${err.message}): ${pkgUrl.toString()}`));
|
|
92
|
+
});
|
|
93
|
+
res.once("end", () => {
|
|
94
|
+
res.removeAllListeners();
|
|
95
|
+
try {
|
|
96
|
+
const pkgMetadata = JSON.parse(rawData);
|
|
97
|
+
resolve({
|
|
98
|
+
name: pkgName,
|
|
99
|
+
lastUpdateDate: Date.now(),
|
|
100
|
+
versions: Object.keys(pkgMetadata["versions"]),
|
|
101
|
+
distTags: pkgMetadata["dist-tags"]
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (typeof error === "string") reject(new Error(error));
|
|
106
|
+
else if (error instanceof Error) reject(error);
|
|
107
|
+
else reject(/* @__PURE__ */ new Error("Metadata extraction error"));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
} else {
|
|
112
|
+
res.removeAllListeners();
|
|
113
|
+
res.resume();
|
|
114
|
+
reject(/* @__PURE__ */ new Error(`Request error (${res.statusCode ?? "unknown"}): ${pkgUrl.toString()}`));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
const abort = (error) => {
|
|
119
|
+
request.destroy();
|
|
120
|
+
reject(typeof error === "string" ? new Error(error) : error);
|
|
121
|
+
};
|
|
122
|
+
request.once("timeout", () => {
|
|
123
|
+
abort(`Request timed out: ${pkgUrl.toString()}`);
|
|
124
|
+
});
|
|
125
|
+
request.once("error", (err) => {
|
|
126
|
+
abort(err);
|
|
127
|
+
});
|
|
128
|
+
request.once("close", () => {
|
|
129
|
+
request.removeAllListeners();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/index.ts
|
|
134
|
+
const isPackageJson = (obj) => obj.dependencies !== void 0 || obj.devDependencies !== void 0 || obj.peerDependencies !== void 0;
|
|
135
|
+
const getRegistryVersions = async (pkgName, tagOrRange, options) => {
|
|
136
|
+
let pkgMetadata;
|
|
137
|
+
if (pkgName.length && options?.useCache) {
|
|
138
|
+
pkgMetadata = getMetadataFromCache(pkgName, options);
|
|
139
|
+
if (!pkgMetadata) {
|
|
140
|
+
pkgMetadata = await downloadMetadata(pkgName, options);
|
|
141
|
+
saveMetadataToCache(pkgMetadata);
|
|
142
|
+
}
|
|
143
|
+
} else if (pkgName.length) pkgMetadata = await downloadMetadata(pkgName, options);
|
|
144
|
+
const versions = {
|
|
145
|
+
latest: pkgMetadata?.distTags["latest"],
|
|
146
|
+
next: pkgMetadata?.distTags["next"]
|
|
147
|
+
};
|
|
148
|
+
if (tagOrRange && pkgMetadata?.distTags[tagOrRange]) versions.wanted = pkgMetadata.distTags[tagOrRange];
|
|
149
|
+
else if (tagOrRange && pkgMetadata?.versions.length) versions.wanted = (0, semver_ranges_max_satisfying_js.default)(pkgMetadata.versions, tagOrRange) ?? void 0;
|
|
150
|
+
return versions;
|
|
151
|
+
};
|
|
152
|
+
const getInstalledVersion = async (pkgName, location = "local") => {
|
|
153
|
+
try {
|
|
154
|
+
const readPackageJson = async (path) => JSON.parse(await (0, node_fs_promises.readFile)(path, "utf8"));
|
|
155
|
+
if (location === "globalNpm") return (await readPackageJson((0, node_path.join)(global_dirs.npm.packages, pkgName, "package.json"))).version;
|
|
156
|
+
else if (location === "globalYarn") {
|
|
157
|
+
if (!(pkgName in (await readPackageJson((0, node_path.resolve)(global_dirs.yarn.packages, "..", "package.json"))).dependencies)) return;
|
|
158
|
+
return (await readPackageJson((0, node_path.join)(global_dirs.yarn.packages, pkgName, "package.json"))).version;
|
|
159
|
+
} else {
|
|
160
|
+
/**
|
|
161
|
+
* Compute the local paths manually as require.resolve() and require.resolve.paths()
|
|
162
|
+
* cannot be trusted anymore.
|
|
163
|
+
* @see https://github.com/nodejs/node/issues/33460
|
|
164
|
+
* @see https://github.com/nodejs/loaders/issues/26
|
|
165
|
+
*/
|
|
166
|
+
const startPath = process.cwd();
|
|
167
|
+
const { root } = (0, node_path.parse)(startPath);
|
|
168
|
+
const findPackageVersion = async (path, rootPath, name) => {
|
|
169
|
+
const pkgPath = (0, node_path.join)(path, "node_modules", name, "package.json");
|
|
170
|
+
try {
|
|
171
|
+
return (await readPackageJson(pkgPath)).version;
|
|
172
|
+
} catch {}
|
|
173
|
+
if (path === rootPath) return;
|
|
174
|
+
return await findPackageVersion((0, node_path.dirname)(path), rootPath, name);
|
|
175
|
+
};
|
|
176
|
+
return await findPackageVersion(startPath, root, pkgName);
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const getInfo = async (pkg, options) => {
|
|
183
|
+
const i = pkg.lastIndexOf("@");
|
|
184
|
+
let pkgInfo = {
|
|
185
|
+
name: i > 1 ? pkg.slice(0, i) : pkg,
|
|
186
|
+
wantedTagOrRange: i > 1 ? pkg.slice(i + 1) : "latest",
|
|
187
|
+
updatesAvailable: false
|
|
188
|
+
};
|
|
189
|
+
try {
|
|
190
|
+
pkgInfo = {
|
|
191
|
+
...pkgInfo,
|
|
192
|
+
local: await getInstalledVersion(pkgInfo.name, "local"),
|
|
193
|
+
globalNpm: await getInstalledVersion(pkgInfo.name, "globalNpm"),
|
|
194
|
+
globalYarn: await getInstalledVersion(pkgInfo.name, "globalYarn"),
|
|
195
|
+
...await getRegistryVersions(pkgInfo.name, pkgInfo.wantedTagOrRange, options)
|
|
196
|
+
};
|
|
197
|
+
const local = pkgInfo.local && pkgInfo.wanted ? (0, semver_functions_gt_js.default)(pkgInfo.wanted, pkgInfo.local) ? pkgInfo.wanted : false : false;
|
|
198
|
+
const globalNpm = pkgInfo.globalNpm && pkgInfo.wanted ? (0, semver_functions_gt_js.default)(pkgInfo.wanted, pkgInfo.globalNpm) ? pkgInfo.wanted : false : false;
|
|
199
|
+
const globalYarn = pkgInfo.globalYarn && pkgInfo.wanted ? (0, semver_functions_gt_js.default)(pkgInfo.wanted, pkgInfo.globalYarn) ? pkgInfo.wanted : false : false;
|
|
200
|
+
pkgInfo.updatesAvailable = local || globalNpm || globalYarn ? {
|
|
201
|
+
local,
|
|
202
|
+
globalNpm,
|
|
203
|
+
globalYarn
|
|
204
|
+
} : false;
|
|
205
|
+
} catch (err) {
|
|
206
|
+
if (typeof err === "string") pkgInfo.error = new Error(err);
|
|
207
|
+
else if (err instanceof Error) pkgInfo.error = err;
|
|
208
|
+
else pkgInfo.error = /* @__PURE__ */ new Error("Unknown error");
|
|
209
|
+
}
|
|
210
|
+
return pkgInfo;
|
|
211
|
+
};
|
|
212
|
+
const latestVersion = async (arg, options) => {
|
|
213
|
+
const pkgs = [];
|
|
214
|
+
if (typeof arg === "string") pkgs.push(arg);
|
|
215
|
+
else if (Array.isArray(arg)) pkgs.push(...arg);
|
|
216
|
+
else if (isPackageJson(arg)) {
|
|
217
|
+
const addDeps = (deps) => {
|
|
218
|
+
if (deps) pkgs.push(...Object.keys(deps).map((key) => `${key}@${deps[key]}`));
|
|
219
|
+
};
|
|
220
|
+
addDeps(arg.dependencies);
|
|
221
|
+
addDeps(arg.devDependencies);
|
|
222
|
+
addDeps(arg.peerDependencies);
|
|
223
|
+
}
|
|
224
|
+
const results = (await Promise.allSettled(pkgs.map((pkg) => getInfo(pkg, options)))).map((jobResult) => jobResult.value);
|
|
225
|
+
return typeof arg === "string" ? results[0] : results;
|
|
226
|
+
};
|
|
227
|
+
//#endregion
|
|
228
|
+
exports.ONE_DAY = ONE_DAY;
|
|
229
|
+
exports.latestVersion = latestVersion;
|
package/index.d.cts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Agent } from "node:http";
|
|
2
|
+
//#region src/cache.d.ts
|
|
3
|
+
declare const ONE_DAY: number;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
interface RegistryVersions {
|
|
7
|
+
/**
|
|
8
|
+
* The latest version of the package found on the registry (if found).
|
|
9
|
+
*/
|
|
10
|
+
latest?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The next version of the package found on the registry (if found).
|
|
13
|
+
*/
|
|
14
|
+
next?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The latest version of the package found on the registry and satisfied by the wanted tag or version range.
|
|
17
|
+
*/
|
|
18
|
+
wanted?: string;
|
|
19
|
+
}
|
|
20
|
+
interface InstalledVersions {
|
|
21
|
+
/**
|
|
22
|
+
* The current local installed version of the package (if installed).
|
|
23
|
+
*/
|
|
24
|
+
local?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The current npm global installed version of the package (if installed).
|
|
27
|
+
*/
|
|
28
|
+
globalNpm?: string;
|
|
29
|
+
/**
|
|
30
|
+
* The current yarn global installed version of the package (if installed).
|
|
31
|
+
*/
|
|
32
|
+
globalYarn?: string;
|
|
33
|
+
}
|
|
34
|
+
interface LatestVersionPackage extends InstalledVersions, RegistryVersions {
|
|
35
|
+
/**
|
|
36
|
+
* The name of the package.
|
|
37
|
+
*/
|
|
38
|
+
name: string;
|
|
39
|
+
/**
|
|
40
|
+
* The tag or version range that was provided (if provided).
|
|
41
|
+
* @default "latest"
|
|
42
|
+
*/
|
|
43
|
+
wantedTagOrRange?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Whether the local or global installed versions (if any) could be upgraded or not, based on the wanted version.
|
|
46
|
+
*/
|
|
47
|
+
updatesAvailable: {
|
|
48
|
+
local: string | false;
|
|
49
|
+
globalNpm: string | false;
|
|
50
|
+
globalYarn: string | false;
|
|
51
|
+
} | false;
|
|
52
|
+
/**
|
|
53
|
+
* Any error that might have occurred during the process.
|
|
54
|
+
*/
|
|
55
|
+
error?: Error;
|
|
56
|
+
}
|
|
57
|
+
interface RequestOptions {
|
|
58
|
+
readonly ca?: string | Buffer | (string | Buffer)[];
|
|
59
|
+
readonly rejectUnauthorized?: boolean;
|
|
60
|
+
readonly agent?: Agent | boolean;
|
|
61
|
+
readonly timeout?: number;
|
|
62
|
+
}
|
|
63
|
+
interface LatestVersionOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Awaiting the api to return might take time, depending on the network, and might impact your package loading performance.
|
|
66
|
+
* You can use the cache mechanism to improve load performance and reduce unnecessary network requests.
|
|
67
|
+
* If `useCache` is not supplied, the api will always check for updates and wait for every requests to return before returning itself.
|
|
68
|
+
* If `useCache` is used, the api will always returned immediately, with either (for each provided packages):
|
|
69
|
+
* 1) a latest/next version available if a cache was found
|
|
70
|
+
* 2) no latest/next version available if no cache was found - in such case updates will be fetched in the background and a cache will
|
|
71
|
+
* be created for each provided packages and made available for the next call to the api.
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
readonly useCache?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* How long the cache for the provided packages should be used before being refreshed (in milliseconds).
|
|
77
|
+
* If `useCache` is not supplied, this option has no effect.
|
|
78
|
+
* If `0` is used, this will force the cache to refresh immediately:
|
|
79
|
+
* 1) The api will returned immediately (without any latest nor next version available for the provided packages)
|
|
80
|
+
* 2) New updates will be fetched in the background
|
|
81
|
+
* 3) The cache for each provided packages will be refreshed and made available for the next call to the api
|
|
82
|
+
* @default ONE_DAY
|
|
83
|
+
*/
|
|
84
|
+
readonly cacheMaxAge?: number;
|
|
85
|
+
/**
|
|
86
|
+
* A JavaScript package registry url that implements the CommonJS Package Registry specification.
|
|
87
|
+
* @default "Looks at any registry urls in the .npmrc file or fallback to the default npm registry instead"
|
|
88
|
+
* @example <caption>.npmrc</caption>
|
|
89
|
+
* registry = 'https://custom-registry.com/'
|
|
90
|
+
* \@pkgscope:registry = 'https://custom-registry.com/'
|
|
91
|
+
*/
|
|
92
|
+
readonly registryUrl?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Set of options to be passed down to Node.js http/https request.
|
|
95
|
+
* @example <caption>Behind a proxy with self-signed certificate</caption>
|
|
96
|
+
* { ca: [ fs.readFileSync('proxy-cert.pem') ] }
|
|
97
|
+
* @example <caption>Bypassing certificate validation</caption>
|
|
98
|
+
* { rejectUnauthorized: false }
|
|
99
|
+
*/
|
|
100
|
+
readonly requestOptions?: RequestOptions;
|
|
101
|
+
}
|
|
102
|
+
interface LatestVersion {
|
|
103
|
+
/**
|
|
104
|
+
* Get latest versions of packages from of a package json like object.
|
|
105
|
+
* @param {PackageJson} item - A package json like object (with dependencies, devDependencies and peerDependencies attributes).
|
|
106
|
+
* @example { dependencies: { 'npm': 'latest' }, devDependencies: { 'npm': '1.3.2' }, peerDependencies: { '@scope/name': '^5.0.2' } }
|
|
107
|
+
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
|
|
108
|
+
* If `useCache` is not supplied, the default of `false` is used.
|
|
109
|
+
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
|
|
110
|
+
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the `npm registry url` instead.
|
|
111
|
+
* @returns {Promise<LatestVersionPackage[]>}
|
|
112
|
+
*/
|
|
113
|
+
(item: PackageJson, options?: LatestVersionOptions): Promise<LatestVersionPackage[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Get latest version of a single package.
|
|
116
|
+
* @param {Package} item - A single package object (represented by a string that should match the following format: `${'@' | ''}${string}@${string}`)
|
|
117
|
+
* @example 'npm', 'npm@1.3.2', '@scope/name@^5.0.2'
|
|
118
|
+
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
|
|
119
|
+
* If `useCache` is not supplied, the default of `false` is used.
|
|
120
|
+
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
|
|
121
|
+
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the npm registry url instead.
|
|
122
|
+
* @returns {Promise<LatestVersionPackage>}
|
|
123
|
+
*/
|
|
124
|
+
(item: Package, options?: LatestVersionOptions): Promise<LatestVersionPackage>;
|
|
125
|
+
/**
|
|
126
|
+
* Get latest versions of a collection of packages.
|
|
127
|
+
* @param {Package[]} items - A collection of package object (represented by a string that should match the following format: `${'@' | ''}${string}@${string}`)
|
|
128
|
+
* @example ['npm', 'npm@1.3.2', '@scope/name@^5.0.2']
|
|
129
|
+
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
|
|
130
|
+
* If `useCache` is not supplied, the default of `false` is used.
|
|
131
|
+
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
|
|
132
|
+
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the npm registry url instead.
|
|
133
|
+
* @returns {Promise<LatestVersionPackage[]>}
|
|
134
|
+
*/
|
|
135
|
+
(items: Package[], options?: LatestVersionOptions): Promise<LatestVersionPackage[]>;
|
|
136
|
+
(item: Package[] | PackageJson, options?: LatestVersionOptions): Promise<LatestVersionPackage[]>;
|
|
137
|
+
}
|
|
138
|
+
type PackageRange = `${"@" | ""}${string}@${string}`;
|
|
139
|
+
type Package = PackageRange | string;
|
|
140
|
+
type PackageJsonDependencies = Record<string, string>;
|
|
141
|
+
type PackageJson = Record<string, unknown> & {
|
|
142
|
+
version?: string;
|
|
143
|
+
} & ({
|
|
144
|
+
dependencies: PackageJsonDependencies;
|
|
145
|
+
} | {
|
|
146
|
+
devDependencies: PackageJsonDependencies;
|
|
147
|
+
} | {
|
|
148
|
+
peerDependencies: PackageJsonDependencies;
|
|
149
|
+
});
|
|
150
|
+
declare const latestVersion: LatestVersion;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { type LatestVersion, type LatestVersionOptions, type LatestVersionPackage, ONE_DAY, type Package, type PackageJson, type PackageJsonDependencies, type PackageRange, type RegistryVersions, type RequestOptions, latestVersion };
|
package/index.d.mts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Agent } from "node:http";
|
|
2
|
+
//#region src/cache.d.ts
|
|
3
|
+
declare const ONE_DAY: number;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
interface RegistryVersions {
|
|
7
|
+
/**
|
|
8
|
+
* The latest version of the package found on the registry (if found).
|
|
9
|
+
*/
|
|
10
|
+
latest?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The next version of the package found on the registry (if found).
|
|
13
|
+
*/
|
|
14
|
+
next?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The latest version of the package found on the registry and satisfied by the wanted tag or version range.
|
|
17
|
+
*/
|
|
18
|
+
wanted?: string;
|
|
19
|
+
}
|
|
20
|
+
interface InstalledVersions {
|
|
21
|
+
/**
|
|
22
|
+
* The current local installed version of the package (if installed).
|
|
23
|
+
*/
|
|
24
|
+
local?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The current npm global installed version of the package (if installed).
|
|
27
|
+
*/
|
|
28
|
+
globalNpm?: string;
|
|
29
|
+
/**
|
|
30
|
+
* The current yarn global installed version of the package (if installed).
|
|
31
|
+
*/
|
|
32
|
+
globalYarn?: string;
|
|
33
|
+
}
|
|
34
|
+
interface LatestVersionPackage extends InstalledVersions, RegistryVersions {
|
|
35
|
+
/**
|
|
36
|
+
* The name of the package.
|
|
37
|
+
*/
|
|
38
|
+
name: string;
|
|
39
|
+
/**
|
|
40
|
+
* The tag or version range that was provided (if provided).
|
|
41
|
+
* @default "latest"
|
|
42
|
+
*/
|
|
43
|
+
wantedTagOrRange?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Whether the local or global installed versions (if any) could be upgraded or not, based on the wanted version.
|
|
46
|
+
*/
|
|
47
|
+
updatesAvailable: {
|
|
48
|
+
local: string | false;
|
|
49
|
+
globalNpm: string | false;
|
|
50
|
+
globalYarn: string | false;
|
|
51
|
+
} | false;
|
|
52
|
+
/**
|
|
53
|
+
* Any error that might have occurred during the process.
|
|
54
|
+
*/
|
|
55
|
+
error?: Error;
|
|
56
|
+
}
|
|
57
|
+
interface RequestOptions {
|
|
58
|
+
readonly ca?: string | Buffer | (string | Buffer)[];
|
|
59
|
+
readonly rejectUnauthorized?: boolean;
|
|
60
|
+
readonly agent?: Agent | boolean;
|
|
61
|
+
readonly timeout?: number;
|
|
62
|
+
}
|
|
63
|
+
interface LatestVersionOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Awaiting the api to return might take time, depending on the network, and might impact your package loading performance.
|
|
66
|
+
* You can use the cache mechanism to improve load performance and reduce unnecessary network requests.
|
|
67
|
+
* If `useCache` is not supplied, the api will always check for updates and wait for every requests to return before returning itself.
|
|
68
|
+
* If `useCache` is used, the api will always returned immediately, with either (for each provided packages):
|
|
69
|
+
* 1) a latest/next version available if a cache was found
|
|
70
|
+
* 2) no latest/next version available if no cache was found - in such case updates will be fetched in the background and a cache will
|
|
71
|
+
* be created for each provided packages and made available for the next call to the api.
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
readonly useCache?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* How long the cache for the provided packages should be used before being refreshed (in milliseconds).
|
|
77
|
+
* If `useCache` is not supplied, this option has no effect.
|
|
78
|
+
* If `0` is used, this will force the cache to refresh immediately:
|
|
79
|
+
* 1) The api will returned immediately (without any latest nor next version available for the provided packages)
|
|
80
|
+
* 2) New updates will be fetched in the background
|
|
81
|
+
* 3) The cache for each provided packages will be refreshed and made available for the next call to the api
|
|
82
|
+
* @default ONE_DAY
|
|
83
|
+
*/
|
|
84
|
+
readonly cacheMaxAge?: number;
|
|
85
|
+
/**
|
|
86
|
+
* A JavaScript package registry url that implements the CommonJS Package Registry specification.
|
|
87
|
+
* @default "Looks at any registry urls in the .npmrc file or fallback to the default npm registry instead"
|
|
88
|
+
* @example <caption>.npmrc</caption>
|
|
89
|
+
* registry = 'https://custom-registry.com/'
|
|
90
|
+
* \@pkgscope:registry = 'https://custom-registry.com/'
|
|
91
|
+
*/
|
|
92
|
+
readonly registryUrl?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Set of options to be passed down to Node.js http/https request.
|
|
95
|
+
* @example <caption>Behind a proxy with self-signed certificate</caption>
|
|
96
|
+
* { ca: [ fs.readFileSync('proxy-cert.pem') ] }
|
|
97
|
+
* @example <caption>Bypassing certificate validation</caption>
|
|
98
|
+
* { rejectUnauthorized: false }
|
|
99
|
+
*/
|
|
100
|
+
readonly requestOptions?: RequestOptions;
|
|
101
|
+
}
|
|
102
|
+
interface LatestVersion {
|
|
103
|
+
/**
|
|
104
|
+
* Get latest versions of packages from of a package json like object.
|
|
105
|
+
* @param {PackageJson} item - A package json like object (with dependencies, devDependencies and peerDependencies attributes).
|
|
106
|
+
* @example { dependencies: { 'npm': 'latest' }, devDependencies: { 'npm': '1.3.2' }, peerDependencies: { '@scope/name': '^5.0.2' } }
|
|
107
|
+
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
|
|
108
|
+
* If `useCache` is not supplied, the default of `false` is used.
|
|
109
|
+
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
|
|
110
|
+
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the `npm registry url` instead.
|
|
111
|
+
* @returns {Promise<LatestVersionPackage[]>}
|
|
112
|
+
*/
|
|
113
|
+
(item: PackageJson, options?: LatestVersionOptions): Promise<LatestVersionPackage[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Get latest version of a single package.
|
|
116
|
+
* @param {Package} item - A single package object (represented by a string that should match the following format: `${'@' | ''}${string}@${string}`)
|
|
117
|
+
* @example 'npm', 'npm@1.3.2', '@scope/name@^5.0.2'
|
|
118
|
+
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
|
|
119
|
+
* If `useCache` is not supplied, the default of `false` is used.
|
|
120
|
+
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
|
|
121
|
+
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the npm registry url instead.
|
|
122
|
+
* @returns {Promise<LatestVersionPackage>}
|
|
123
|
+
*/
|
|
124
|
+
(item: Package, options?: LatestVersionOptions): Promise<LatestVersionPackage>;
|
|
125
|
+
/**
|
|
126
|
+
* Get latest versions of a collection of packages.
|
|
127
|
+
* @param {Package[]} items - A collection of package object (represented by a string that should match the following format: `${'@' | ''}${string}@${string}`)
|
|
128
|
+
* @example ['npm', 'npm@1.3.2', '@scope/name@^5.0.2']
|
|
129
|
+
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
|
|
130
|
+
* If `useCache` is not supplied, the default of `false` is used.
|
|
131
|
+
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
|
|
132
|
+
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the npm registry url instead.
|
|
133
|
+
* @returns {Promise<LatestVersionPackage[]>}
|
|
134
|
+
*/
|
|
135
|
+
(items: Package[], options?: LatestVersionOptions): Promise<LatestVersionPackage[]>;
|
|
136
|
+
(item: Package[] | PackageJson, options?: LatestVersionOptions): Promise<LatestVersionPackage[]>;
|
|
137
|
+
}
|
|
138
|
+
type PackageRange = `${"@" | ""}${string}@${string}`;
|
|
139
|
+
type Package = PackageRange | string;
|
|
140
|
+
type PackageJsonDependencies = Record<string, string>;
|
|
141
|
+
type PackageJson = Record<string, unknown> & {
|
|
142
|
+
version?: string;
|
|
143
|
+
} & ({
|
|
144
|
+
dependencies: PackageJsonDependencies;
|
|
145
|
+
} | {
|
|
146
|
+
devDependencies: PackageJsonDependencies;
|
|
147
|
+
} | {
|
|
148
|
+
peerDependencies: PackageJsonDependencies;
|
|
149
|
+
});
|
|
150
|
+
declare const latestVersion: LatestVersion;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { type LatestVersion, type LatestVersionOptions, type LatestVersionPackage, ONE_DAY, type Package, type PackageJson, type PackageJsonDependencies, type PackageRange, type RegistryVersions, type RequestOptions, latestVersion };
|