inup 1.5.6 → 1.6.2
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 +30 -1
- package/dist/cli.js +42 -11
- package/dist/config/constants.js +6 -7
- package/dist/config/project-config.js +5 -0
- package/dist/core/package-detector.js +49 -1
- package/dist/core/upgrade-runner.js +9 -0
- package/dist/core/upgrader.js +9 -3
- package/dist/features/changelog/services/package-metadata-service.js +2 -13
- package/dist/features/changelog/services/release-notes-service.js +0 -27
- package/dist/features/debug/index.js +1 -0
- package/dist/features/debug/renderer/performance-modal.js +17 -1
- package/dist/features/debug/services/perf-logger.js +129 -0
- package/dist/features/debug/services/performance-tracker.js +15 -3
- package/dist/features/headless/headless-runner.js +69 -0
- package/dist/features/headless/index.js +27 -0
- package/dist/features/headless/report.js +64 -0
- package/dist/features/headless/types.js +6 -0
- package/dist/features/headless/vulnerability-audit.js +106 -0
- package/dist/interactive-ui.js +4 -2
- package/dist/services/http/adaptive-controller.js +153 -0
- package/dist/services/http/etag-store.js +91 -0
- package/dist/services/http/resizable-semaphore.js +71 -0
- package/dist/services/http/retry.js +23 -1
- package/dist/services/index.js +0 -1
- package/dist/services/npm-registry.js +198 -97
- package/dist/services/package-manager-detector.js +6 -3
- package/dist/ui/modal/package-info-sections/sections.js +24 -0
- package/dist/ui/presenters/health.js +24 -0
- package/dist/ui/renderer/package-list/rows.js +8 -3
- package/dist/ui/session/selection-state-builder.js +7 -2
- package/dist/ui/themes-colors.js +12 -3
- package/dist/ui/utils/cursor.js +9 -3
- package/dist/utils/color.js +38 -0
- package/dist/utils/debug-logger.js +8 -1
- package/dist/utils/engines.js +63 -0
- package/dist/utils/filesystem/io.js +16 -0
- package/dist/utils/filesystem/scan.js +82 -7
- package/dist/utils/index.js +4 -0
- package/dist/utils/local-env.js +81 -0
- package/dist/utils/manifest.js +35 -0
- package/dist/utils/version.js +9 -2
- package/package.json +8 -8
- package/dist/services/cache-manager.js +0 -95
- package/dist/services/jsdelivr/client.js +0 -191
- package/dist/services/jsdelivr/manifest.js +0 -136
- package/dist/services/jsdelivr-registry.js +0 -9
- package/dist/services/persistent-cache.js +0 -237
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.jsdelivrPool = exports.RETRY_TIMEOUTS = void 0;
|
|
4
|
-
exports.fetchPackageManifestFromJsdelivr = fetchPackageManifestFromJsdelivr;
|
|
5
|
-
exports.fetchPackageManifestFromNpmRegistry = fetchPackageManifestFromNpmRegistry;
|
|
6
|
-
const undici_1 = require("undici");
|
|
7
|
-
const config_1 = require("../../config");
|
|
8
|
-
const utils_1 = require("../../utils");
|
|
9
|
-
const retry_1 = require("../http/retry");
|
|
10
|
-
const DEFAULT_JSDELIVR_RETRY_TIMEOUT_MS = 2000;
|
|
11
|
-
const DEFAULT_JSDELIVR_POOL_TIMEOUT_MS = 60000;
|
|
12
|
-
const MIN_JSDELIVR_CONNECT_TIMEOUT_MS = 500;
|
|
13
|
-
const toPositiveInteger = (value) => {
|
|
14
|
-
if (!Number.isFinite(value) || value <= 0) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
const normalized = Math.floor(value);
|
|
18
|
-
return normalized > 0 ? normalized : null;
|
|
19
|
-
};
|
|
20
|
-
exports.RETRY_TIMEOUTS = (() => {
|
|
21
|
-
const configured = Array.from(new Set(config_1.JSDELIVR_RETRY_TIMEOUTS.map(toPositiveInteger).filter((value) => value !== null))).sort((a, b) => a - b);
|
|
22
|
-
return configured.length > 0 ? configured : [DEFAULT_JSDELIVR_RETRY_TIMEOUT_MS];
|
|
23
|
-
})();
|
|
24
|
-
const RETRY_DELAYS = config_1.JSDELIVR_RETRY_DELAYS.map(toPositiveInteger).filter((value) => value !== null);
|
|
25
|
-
const MAX_RETRY_AFTER_DELAY_MS = exports.RETRY_TIMEOUTS[exports.RETRY_TIMEOUTS.length - 1];
|
|
26
|
-
const RETRY_AFTER_HEADER = 'retry-after';
|
|
27
|
-
const parseRetryAfterMs = (value) => {
|
|
28
|
-
const trimmed = value.trim();
|
|
29
|
-
if (!trimmed) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
const seconds = Number(trimmed);
|
|
33
|
-
if (Number.isFinite(seconds)) {
|
|
34
|
-
if (seconds <= 0) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
const delayMs = Math.floor(seconds * 1000);
|
|
38
|
-
return delayMs > 0 ? delayMs : null;
|
|
39
|
-
}
|
|
40
|
-
const dateMs = Date.parse(trimmed);
|
|
41
|
-
if (Number.isNaN(dateMs)) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
const delayMs = dateMs - Date.now();
|
|
45
|
-
return delayMs > 0 ? delayMs : null;
|
|
46
|
-
};
|
|
47
|
-
const getHeaderValue = (headers, name) => {
|
|
48
|
-
if (!headers) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
const direct = headers[name];
|
|
52
|
-
if (typeof direct === 'string') {
|
|
53
|
-
return direct;
|
|
54
|
-
}
|
|
55
|
-
if (Array.isArray(direct)) {
|
|
56
|
-
return direct.find((value) => typeof value === 'string') ?? null;
|
|
57
|
-
}
|
|
58
|
-
const headerEntry = Object.entries(headers).find(([headerName]) => headerName.toLowerCase() === name);
|
|
59
|
-
if (!headerEntry) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
const [, rawValue] = headerEntry;
|
|
63
|
-
if (typeof rawValue === 'string') {
|
|
64
|
-
return rawValue;
|
|
65
|
-
}
|
|
66
|
-
if (Array.isArray(rawValue)) {
|
|
67
|
-
return rawValue.find((value) => typeof value === 'string') ?? null;
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
};
|
|
71
|
-
const getRetryAfterDelay = (headers) => {
|
|
72
|
-
const retryAfterValue = getHeaderValue(headers, RETRY_AFTER_HEADER);
|
|
73
|
-
if (!retryAfterValue) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
const parsedDelay = parseRetryAfterMs(retryAfterValue);
|
|
77
|
-
if (parsedDelay === null) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
return Math.min(parsedDelay, MAX_RETRY_AFTER_DELAY_MS);
|
|
81
|
-
};
|
|
82
|
-
const getRetryDelay = (attempt, headers) => {
|
|
83
|
-
const configuredDelay = RETRY_DELAYS.length === 0 ? 0 : RETRY_DELAYS[Math.min(attempt, RETRY_DELAYS.length - 1)];
|
|
84
|
-
const retryAfterDelay = getRetryAfterDelay(headers);
|
|
85
|
-
return retryAfterDelay === null ? configuredDelay : Math.max(configuredDelay, retryAfterDelay);
|
|
86
|
-
};
|
|
87
|
-
// Keep connection setup bounded by retry budget so fallback stays responsive.
|
|
88
|
-
const JSDELIVR_CONNECT_TIMEOUT_MS = Math.max(exports.RETRY_TIMEOUTS[0], MIN_JSDELIVR_CONNECT_TIMEOUT_MS);
|
|
89
|
-
const JSDELIVR_POOL_TIMEOUT_MS = toPositiveInteger(config_1.JSDELIVR_POOL_TIMEOUT) ?? DEFAULT_JSDELIVR_POOL_TIMEOUT_MS;
|
|
90
|
-
const JSDELIVR_CONNECTIONS = toPositiveInteger(config_1.MAX_CONCURRENT_REQUESTS) ?? 1;
|
|
91
|
-
// Create a persistent connection pool for jsDelivr CDN with optimal settings
|
|
92
|
-
// This enables connection reuse and HTTP/1.1 keep-alive for blazing fast requests
|
|
93
|
-
exports.jsdelivrPool = new undici_1.Pool('https://cdn.jsdelivr.net', {
|
|
94
|
-
connections: JSDELIVR_CONNECTIONS,
|
|
95
|
-
pipelining: 10,
|
|
96
|
-
keepAliveTimeout: JSDELIVR_POOL_TIMEOUT_MS,
|
|
97
|
-
keepAliveMaxTimeout: JSDELIVR_POOL_TIMEOUT_MS,
|
|
98
|
-
connectTimeout: JSDELIVR_CONNECT_TIMEOUT_MS,
|
|
99
|
-
});
|
|
100
|
-
const consumeBodySafely = async (body) => {
|
|
101
|
-
try {
|
|
102
|
-
await body.text();
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
// Ignore body read errors on non-200 responses because request will be retried/fallback.
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
async function fetchPackageManifestFromJsdelivr(packageName, versionTag) {
|
|
109
|
-
const url = `${config_1.JSDELIVR_CDN_URL}/${encodeURIComponent(packageName)}@${versionTag}/package.json`;
|
|
110
|
-
for (let attempt = 0; attempt < exports.RETRY_TIMEOUTS.length; attempt++) {
|
|
111
|
-
const timeout = exports.RETRY_TIMEOUTS[attempt];
|
|
112
|
-
const tReq = Date.now();
|
|
113
|
-
try {
|
|
114
|
-
const { statusCode, headers, body } = await (0, undici_1.request)(url, {
|
|
115
|
-
dispatcher: exports.jsdelivrPool,
|
|
116
|
-
method: 'GET',
|
|
117
|
-
headers: {
|
|
118
|
-
accept: 'application/json',
|
|
119
|
-
},
|
|
120
|
-
headersTimeout: timeout,
|
|
121
|
-
bodyTimeout: timeout,
|
|
122
|
-
});
|
|
123
|
-
if (statusCode !== 200) {
|
|
124
|
-
// Consume body to prevent memory leaks
|
|
125
|
-
await consumeBodySafely(body);
|
|
126
|
-
if ((0, retry_1.isRetryableStatus)(statusCode) && attempt < exports.RETRY_TIMEOUTS.length - 1) {
|
|
127
|
-
const delay = getRetryDelay(attempt, headers);
|
|
128
|
-
utils_1.debugLog.warn('jsdelivr', `${packageName}@${versionTag} HTTP ${statusCode}, retry ${attempt + 1} in ${delay}ms`);
|
|
129
|
-
if (delay > 0) {
|
|
130
|
-
await (0, retry_1.sleep)(delay);
|
|
131
|
-
}
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
utils_1.debugLog.warn('jsdelivr', `${packageName}@${versionTag} HTTP ${statusCode}, no more retries`);
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
const text = await body.text();
|
|
138
|
-
const data = JSON.parse(text);
|
|
139
|
-
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
utils_1.debugLog.perf('jsdelivr', `fetch manifest ${packageName}@${versionTag}`, tReq);
|
|
143
|
-
return data;
|
|
144
|
-
}
|
|
145
|
-
catch (error) {
|
|
146
|
-
if ((0, retry_1.isTransientNetworkError)(error) && attempt < exports.RETRY_TIMEOUTS.length - 1) {
|
|
147
|
-
const delay = getRetryDelay(attempt);
|
|
148
|
-
utils_1.debugLog.warn('jsdelivr', `${packageName}@${versionTag} transient error on attempt ${attempt + 1}, retry in ${delay}ms`, error);
|
|
149
|
-
if (delay > 0) {
|
|
150
|
-
await (0, retry_1.sleep)(delay);
|
|
151
|
-
}
|
|
152
|
-
continue;
|
|
153
|
-
}
|
|
154
|
-
if (!(0, retry_1.isTransientNetworkError)(error)) {
|
|
155
|
-
// Unexpected errors are logged for observability.
|
|
156
|
-
console.error(`jsDelivr fetch failed for ${packageName}@${versionTag} on attempt ${attempt + 1}/${exports.RETRY_TIMEOUTS.length}`, error);
|
|
157
|
-
utils_1.debugLog.error('jsdelivr', `unexpected error for ${packageName}@${versionTag} attempt ${attempt + 1}`, error);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
utils_1.debugLog.warn('jsdelivr', `${packageName}@${versionTag} exhausted retries`, error);
|
|
161
|
-
}
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
async function fetchPackageManifestFromNpmRegistry(packageName, version) {
|
|
168
|
-
const controller = new AbortController();
|
|
169
|
-
const timeoutId = setTimeout(() => controller.abort(), config_1.REQUEST_TIMEOUT);
|
|
170
|
-
try {
|
|
171
|
-
const response = await fetch(`${config_1.NPM_REGISTRY_URL}/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}`, {
|
|
172
|
-
method: 'GET',
|
|
173
|
-
headers: {
|
|
174
|
-
accept: 'application/json',
|
|
175
|
-
},
|
|
176
|
-
signal: controller.signal,
|
|
177
|
-
});
|
|
178
|
-
if (!response.ok) {
|
|
179
|
-
return null;
|
|
180
|
-
}
|
|
181
|
-
return (await response.json());
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
utils_1.debugLog.warn('npm-registry', `exact manifest fallback failed for ${packageName}@${version}`, error);
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
finally {
|
|
188
|
-
clearTimeout(timeoutId);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.fetchExactPackageManifest = fetchExactPackageManifest;
|
|
37
|
-
exports.getAllPackageDataFromJsdelivr = getAllPackageDataFromJsdelivr;
|
|
38
|
-
exports.closeJsdelivrPool = closeJsdelivrPool;
|
|
39
|
-
exports.clearExactManifestCache = clearExactManifestCache;
|
|
40
|
-
const semver = __importStar(require("semver"));
|
|
41
|
-
const utils_1 = require("../../utils");
|
|
42
|
-
const version_1 = require("../../utils/version");
|
|
43
|
-
const inflight_1 = require("../http/inflight");
|
|
44
|
-
const client_1 = require("./client");
|
|
45
|
-
const EXACT_VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
46
|
-
const sortVersionsDescending = (versions) => {
|
|
47
|
-
const uniqueVersions = [];
|
|
48
|
-
const seenVersions = new Set();
|
|
49
|
-
for (const version of versions) {
|
|
50
|
-
const identity = (0, version_1.versionIdentity)(version);
|
|
51
|
-
if (!seenVersions.has(identity)) {
|
|
52
|
-
seenVersions.add(identity);
|
|
53
|
-
uniqueVersions.push(version);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return uniqueVersions.sort((a, b) => {
|
|
57
|
-
const comparableA = (0, version_1.toComparableVersion)(a);
|
|
58
|
-
const comparableB = (0, version_1.toComparableVersion)(b);
|
|
59
|
-
if (comparableA && comparableB) {
|
|
60
|
-
return semver.rcompare(comparableA, comparableB);
|
|
61
|
-
}
|
|
62
|
-
if (comparableA) {
|
|
63
|
-
return -1;
|
|
64
|
-
}
|
|
65
|
-
if (comparableB) {
|
|
66
|
-
return 1;
|
|
67
|
-
}
|
|
68
|
-
return b.localeCompare(a);
|
|
69
|
-
});
|
|
70
|
-
};
|
|
71
|
-
const inFlightManifests = new inflight_1.InflightMap();
|
|
72
|
-
async function fetchExactPackageManifest(packageName, version) {
|
|
73
|
-
const normalizedVersion = version.trim();
|
|
74
|
-
if (!EXACT_VERSION_PATTERN.test(normalizedVersion) || !semver.valid(normalizedVersion)) {
|
|
75
|
-
utils_1.debugLog.warn('jsdelivr', `skipping non-exact version lookup for ${packageName}@${version}`);
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
const cacheKey = `${packageName}@${normalizedVersion}`;
|
|
79
|
-
return inFlightManifests.dedupe(cacheKey, async () => {
|
|
80
|
-
const jsdelivrManifest = await (0, client_1.fetchPackageManifestFromJsdelivr)(packageName, normalizedVersion);
|
|
81
|
-
if (jsdelivrManifest) {
|
|
82
|
-
return jsdelivrManifest;
|
|
83
|
-
}
|
|
84
|
-
return await (0, client_1.fetchPackageManifestFromNpmRegistry)(packageName, normalizedVersion);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
async function getAllPackageDataFromJsdelivr(packageNames, currentVersions, onProgress) {
|
|
88
|
-
const packageData = new Map();
|
|
89
|
-
if (packageNames.length === 0) {
|
|
90
|
-
return packageData;
|
|
91
|
-
}
|
|
92
|
-
const total = packageNames.length;
|
|
93
|
-
let completedCount = 0;
|
|
94
|
-
const inFlightLookups = new inflight_1.InflightMap();
|
|
95
|
-
const fetchPackageData = async (packageName, currentVersion) => {
|
|
96
|
-
const latestManifest = await (0, client_1.fetchPackageManifestFromJsdelivr)(packageName, 'latest');
|
|
97
|
-
const latestVersion = typeof latestManifest?.version === 'string' ? latestManifest.version.trim() : '';
|
|
98
|
-
if (!latestVersion) {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
const majorVersion = (0, version_1.extractMajorVersion)(currentVersion);
|
|
102
|
-
const latestMajorVersion = (0, version_1.extractMajorVersion)(latestVersion);
|
|
103
|
-
const shouldFetchMajorVersion = Boolean(majorVersion && (latestMajorVersion === null || latestMajorVersion !== majorVersion));
|
|
104
|
-
const majorManifest = shouldFetchMajorVersion
|
|
105
|
-
? await (0, client_1.fetchPackageManifestFromJsdelivr)(packageName, majorVersion)
|
|
106
|
-
: null;
|
|
107
|
-
const majorResolvedVersion = typeof majorManifest?.version === 'string' ? majorManifest.version.trim() : '';
|
|
108
|
-
const sortedVersions = sortVersionsDescending([latestVersion, majorResolvedVersion].filter(Boolean));
|
|
109
|
-
const allVersions = sortedVersions[0] === latestVersion
|
|
110
|
-
? sortedVersions
|
|
111
|
-
: [latestVersion, ...sortedVersions.filter((version) => version !== latestVersion)];
|
|
112
|
-
return { latestVersion, allVersions };
|
|
113
|
-
};
|
|
114
|
-
const getPackageData = (packageName, currentVersion) => inFlightLookups.dedupe(packageName, () => fetchPackageData(packageName, currentVersion));
|
|
115
|
-
await Promise.all(packageNames.map(async (packageName) => {
|
|
116
|
-
try {
|
|
117
|
-
const result = await getPackageData(packageName, currentVersions?.get(packageName));
|
|
118
|
-
if (result) {
|
|
119
|
-
packageData.set(packageName, result);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
finally {
|
|
123
|
-
completedCount++;
|
|
124
|
-
onProgress?.(packageName, completedCount, total);
|
|
125
|
-
}
|
|
126
|
-
}));
|
|
127
|
-
return packageData;
|
|
128
|
-
}
|
|
129
|
-
async function closeJsdelivrPool() {
|
|
130
|
-
const { jsdelivrPool } = await Promise.resolve().then(() => __importStar(require('./client')));
|
|
131
|
-
await jsdelivrPool.close();
|
|
132
|
-
}
|
|
133
|
-
function clearExactManifestCache() {
|
|
134
|
-
inFlightManifests.clear();
|
|
135
|
-
}
|
|
136
|
-
//# sourceMappingURL=manifest.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.clearExactManifestCache = exports.closeJsdelivrPool = exports.getAllPackageDataFromJsdelivr = exports.fetchExactPackageManifest = void 0;
|
|
4
|
-
var manifest_1 = require("./jsdelivr/manifest");
|
|
5
|
-
Object.defineProperty(exports, "fetchExactPackageManifest", { enumerable: true, get: function () { return manifest_1.fetchExactPackageManifest; } });
|
|
6
|
-
Object.defineProperty(exports, "getAllPackageDataFromJsdelivr", { enumerable: true, get: function () { return manifest_1.getAllPackageDataFromJsdelivr; } });
|
|
7
|
-
Object.defineProperty(exports, "closeJsdelivrPool", { enumerable: true, get: function () { return manifest_1.closeJsdelivrPool; } });
|
|
8
|
-
Object.defineProperty(exports, "clearExactManifestCache", { enumerable: true, get: function () { return manifest_1.clearExactManifestCache; } });
|
|
9
|
-
//# sourceMappingURL=jsdelivr-registry.js.map
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.persistentCache = void 0;
|
|
7
|
-
const fs_1 = require("fs");
|
|
8
|
-
const path_1 = require("path");
|
|
9
|
-
const env_paths_1 = __importDefault(require("env-paths"));
|
|
10
|
-
const config_1 = require("../config");
|
|
11
|
-
// Maximum cache size (number of packages)
|
|
12
|
-
const MAX_CACHE_ENTRIES = 5000;
|
|
13
|
-
// Cache file format version (increment when structure changes)
|
|
14
|
-
const CACHE_VERSION = 2;
|
|
15
|
-
/**
|
|
16
|
-
* Persistent cache manager for package registry data.
|
|
17
|
-
* Stores cache on disk for fast repeated runs across CLI invocations.
|
|
18
|
-
*/
|
|
19
|
-
class PersistentCacheManager {
|
|
20
|
-
cacheDir;
|
|
21
|
-
indexPath;
|
|
22
|
-
index = null;
|
|
23
|
-
dirty = false;
|
|
24
|
-
constructor() {
|
|
25
|
-
const paths = (0, env_paths_1.default)(config_1.PACKAGE_NAME);
|
|
26
|
-
this.cacheDir = (0, path_1.join)(paths.cache, 'registry');
|
|
27
|
-
this.indexPath = (0, path_1.join)(this.cacheDir, 'index.json');
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Ensure cache directory exists
|
|
31
|
-
*/
|
|
32
|
-
ensureCacheDir() {
|
|
33
|
-
if (!(0, fs_1.existsSync)(this.cacheDir)) {
|
|
34
|
-
(0, fs_1.mkdirSync)(this.cacheDir, { recursive: true });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Load cache index from disk
|
|
39
|
-
*/
|
|
40
|
-
loadIndex() {
|
|
41
|
-
if (this.index) {
|
|
42
|
-
return this.index;
|
|
43
|
-
}
|
|
44
|
-
try {
|
|
45
|
-
if ((0, fs_1.existsSync)(this.indexPath)) {
|
|
46
|
-
const content = (0, fs_1.readFileSync)(this.indexPath, 'utf-8');
|
|
47
|
-
const parsed = JSON.parse(content);
|
|
48
|
-
// Check cache version - invalidate if outdated
|
|
49
|
-
if (parsed.version !== CACHE_VERSION) {
|
|
50
|
-
this.clearCache();
|
|
51
|
-
this.index = { version: CACHE_VERSION, entries: {} };
|
|
52
|
-
return this.index;
|
|
53
|
-
}
|
|
54
|
-
this.index = parsed;
|
|
55
|
-
return this.index;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
// Corrupted index, start fresh
|
|
60
|
-
}
|
|
61
|
-
this.index = { version: CACHE_VERSION, entries: {} };
|
|
62
|
-
return this.index;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Save cache index to disk
|
|
66
|
-
*/
|
|
67
|
-
saveIndex() {
|
|
68
|
-
if (!this.dirty || !this.index) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
this.ensureCacheDir();
|
|
73
|
-
(0, fs_1.writeFileSync)(this.indexPath, JSON.stringify(this.index), 'utf-8');
|
|
74
|
-
this.dirty = false;
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
// Silently fail - cache is not critical
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Generate a safe filename for a package name
|
|
82
|
-
*/
|
|
83
|
-
getFilename(packageName) {
|
|
84
|
-
// Handle scoped packages: @scope/name -> scope__name
|
|
85
|
-
const safeName = packageName.replace(/^@/, '').replace(/\//g, '__');
|
|
86
|
-
return `${safeName}.json`;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Get cached data for a package
|
|
90
|
-
*/
|
|
91
|
-
get(packageName) {
|
|
92
|
-
const index = this.loadIndex();
|
|
93
|
-
const entry = index.entries[packageName];
|
|
94
|
-
if (!entry) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
// Read the actual cache file
|
|
98
|
-
try {
|
|
99
|
-
const filePath = (0, path_1.join)(this.cacheDir, entry.file);
|
|
100
|
-
if (!(0, fs_1.existsSync)(filePath)) {
|
|
101
|
-
delete index.entries[packageName];
|
|
102
|
-
this.dirty = true;
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
const content = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
106
|
-
const cached = JSON.parse(content);
|
|
107
|
-
return {
|
|
108
|
-
latestVersion: cached.latestVersion,
|
|
109
|
-
allVersions: cached.allVersions,
|
|
110
|
-
timestamp: entry.timestamp,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
// Corrupted cache file, remove from index
|
|
115
|
-
delete index.entries[packageName];
|
|
116
|
-
this.dirty = true;
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Store data for a package
|
|
122
|
-
*/
|
|
123
|
-
set(packageName, data) {
|
|
124
|
-
const index = this.loadIndex();
|
|
125
|
-
// Evict old entries if cache is too large
|
|
126
|
-
const entryCount = Object.keys(index.entries).length;
|
|
127
|
-
if (entryCount >= MAX_CACHE_ENTRIES) {
|
|
128
|
-
this.evictOldest(Math.floor(MAX_CACHE_ENTRIES * 0.1)); // Evict 10%
|
|
129
|
-
}
|
|
130
|
-
const filename = this.getFilename(packageName);
|
|
131
|
-
const entry = {
|
|
132
|
-
...data,
|
|
133
|
-
timestamp: Date.now(),
|
|
134
|
-
};
|
|
135
|
-
try {
|
|
136
|
-
this.ensureCacheDir();
|
|
137
|
-
const filePath = (0, path_1.join)(this.cacheDir, filename);
|
|
138
|
-
(0, fs_1.writeFileSync)(filePath, JSON.stringify(entry), 'utf-8');
|
|
139
|
-
index.entries[packageName] = {
|
|
140
|
-
file: filename,
|
|
141
|
-
timestamp: Date.now(),
|
|
142
|
-
};
|
|
143
|
-
this.dirty = true;
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
// Silently fail - cache is not critical
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Batch get multiple packages (returns map of found entries)
|
|
151
|
-
*/
|
|
152
|
-
getMany(packageNames) {
|
|
153
|
-
const results = new Map();
|
|
154
|
-
for (const name of packageNames) {
|
|
155
|
-
const cached = this.get(name);
|
|
156
|
-
if (cached) {
|
|
157
|
-
results.set(name, cached);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return results;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Batch set multiple packages
|
|
164
|
-
*/
|
|
165
|
-
setMany(entries) {
|
|
166
|
-
for (const [name, data] of entries) {
|
|
167
|
-
this.set(name, data);
|
|
168
|
-
}
|
|
169
|
-
this.flush();
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Evict oldest cache entries
|
|
173
|
-
*/
|
|
174
|
-
evictOldest(count) {
|
|
175
|
-
const index = this.loadIndex();
|
|
176
|
-
const entries = Object.entries(index.entries);
|
|
177
|
-
// Sort by timestamp (oldest first)
|
|
178
|
-
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
179
|
-
// Remove oldest entries
|
|
180
|
-
const toRemove = entries.slice(0, count);
|
|
181
|
-
for (const [packageName, entry] of toRemove) {
|
|
182
|
-
try {
|
|
183
|
-
const filePath = (0, path_1.join)(this.cacheDir, entry.file);
|
|
184
|
-
if ((0, fs_1.existsSync)(filePath)) {
|
|
185
|
-
(0, fs_1.unlinkSync)(filePath);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
catch {
|
|
189
|
-
// Ignore deletion errors
|
|
190
|
-
}
|
|
191
|
-
delete index.entries[packageName];
|
|
192
|
-
}
|
|
193
|
-
this.dirty = true;
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Clear all cache
|
|
197
|
-
*/
|
|
198
|
-
clearCache() {
|
|
199
|
-
try {
|
|
200
|
-
if ((0, fs_1.existsSync)(this.cacheDir)) {
|
|
201
|
-
const files = (0, fs_1.readdirSync)(this.cacheDir);
|
|
202
|
-
for (const file of files) {
|
|
203
|
-
try {
|
|
204
|
-
(0, fs_1.unlinkSync)((0, path_1.join)(this.cacheDir, file));
|
|
205
|
-
}
|
|
206
|
-
catch {
|
|
207
|
-
// Ignore
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
// Ignore
|
|
214
|
-
}
|
|
215
|
-
this.index = { version: CACHE_VERSION, entries: {} };
|
|
216
|
-
this.dirty = true;
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Flush pending changes to disk
|
|
220
|
-
*/
|
|
221
|
-
flush() {
|
|
222
|
-
this.saveIndex();
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Get cache statistics
|
|
226
|
-
*/
|
|
227
|
-
getStats() {
|
|
228
|
-
const index = this.loadIndex();
|
|
229
|
-
return {
|
|
230
|
-
entries: Object.keys(index.entries).length,
|
|
231
|
-
cacheDir: this.cacheDir,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Export singleton instance
|
|
236
|
-
exports.persistentCache = new PersistentCacheManager();
|
|
237
|
-
//# sourceMappingURL=persistent-cache.js.map
|