comze 0.3.1 → 0.3.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/dist/cli.mjs +159 -26
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -7395,7 +7395,7 @@ var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
|
7395
7395
|
import { resolve } from "path";
|
|
7396
7396
|
|
|
7397
7397
|
// src/fetcher.ts
|
|
7398
|
-
var
|
|
7398
|
+
var import_semver3 = __toESM(require_semver2(), 1);
|
|
7399
7399
|
|
|
7400
7400
|
// src/types.ts
|
|
7401
7401
|
var STABILITY_ORDER = {
|
|
@@ -7570,23 +7570,27 @@ function getCacheDir() {
|
|
|
7570
7570
|
}
|
|
7571
7571
|
return path.join(process.env.XDG_CACHE_HOME || path.join(home, ".cache"), "comze");
|
|
7572
7572
|
}
|
|
7573
|
-
async function getCacheEntry(key) {
|
|
7573
|
+
async function getCacheEntry(key, expectedVersion) {
|
|
7574
7574
|
try {
|
|
7575
7575
|
const cacheDir = getCacheDir();
|
|
7576
7576
|
const filePath = path.join(cacheDir, `${key}.json`);
|
|
7577
7577
|
const content = await fs.readFile(filePath, "utf-8");
|
|
7578
7578
|
const data = JSON.parse(content);
|
|
7579
|
+
if (data.version !== expectedVersion) {
|
|
7580
|
+
return null;
|
|
7581
|
+
}
|
|
7579
7582
|
return data;
|
|
7580
7583
|
} catch {
|
|
7581
7584
|
return null;
|
|
7582
7585
|
}
|
|
7583
7586
|
}
|
|
7584
|
-
async function setCache(key, value, meta = {}) {
|
|
7587
|
+
async function setCache(key, value, version, meta = {}) {
|
|
7585
7588
|
try {
|
|
7586
7589
|
const cacheDir = getCacheDir();
|
|
7587
7590
|
await fs.mkdir(cacheDir, { recursive: true });
|
|
7588
7591
|
const filePath = path.join(cacheDir, `${key}.json`);
|
|
7589
7592
|
const data = {
|
|
7593
|
+
version,
|
|
7590
7594
|
timestamp: Date.now(),
|
|
7591
7595
|
value,
|
|
7592
7596
|
lastModified: meta.lastModified,
|
|
@@ -7595,37 +7599,131 @@ async function setCache(key, value, meta = {}) {
|
|
|
7595
7599
|
await fs.writeFile(filePath, JSON.stringify(data), "utf-8");
|
|
7596
7600
|
} catch {}
|
|
7597
7601
|
}
|
|
7598
|
-
async function touchCache(key) {
|
|
7602
|
+
async function touchCache(key, version) {
|
|
7599
7603
|
try {
|
|
7600
|
-
const entry = await getCacheEntry(key);
|
|
7604
|
+
const entry = await getCacheEntry(key, version);
|
|
7601
7605
|
if (entry) {
|
|
7602
|
-
await setCache(key, entry.value,
|
|
7606
|
+
await setCache(key, entry.value, version, {
|
|
7607
|
+
lastModified: entry.lastModified,
|
|
7608
|
+
etag: entry.etag
|
|
7609
|
+
});
|
|
7603
7610
|
}
|
|
7604
7611
|
} catch {}
|
|
7605
7612
|
}
|
|
7606
7613
|
|
|
7614
|
+
// src/utils/php.ts
|
|
7615
|
+
var import_semver2 = __toESM(require_semver2(), 1);
|
|
7616
|
+
function normalizeComposerConstraint(constraint) {
|
|
7617
|
+
if (!constraint)
|
|
7618
|
+
return "*";
|
|
7619
|
+
let normalized = constraint.trim();
|
|
7620
|
+
normalized = normalized.replace(/\|\|/g, "<<<OR>>>");
|
|
7621
|
+
normalized = normalized.replace(/\|/g, "<<<OR>>>");
|
|
7622
|
+
normalized = normalized.replace(/<<<OR>>>/g, " || ");
|
|
7623
|
+
normalized = normalized.replace(/\s*\|\|\s*/g, " || ");
|
|
7624
|
+
normalized = normalized.replace(/,\s*/g, " ");
|
|
7625
|
+
normalized = normalized.replace(/@(dev|alpha|beta|rc|stable)/gi, "");
|
|
7626
|
+
if (normalized === "*" || normalized.startsWith("ext-")) {
|
|
7627
|
+
return "*";
|
|
7628
|
+
}
|
|
7629
|
+
return normalized;
|
|
7630
|
+
}
|
|
7631
|
+
function extractMinVersion(constraint) {
|
|
7632
|
+
const normalized = normalizeComposerConstraint(constraint);
|
|
7633
|
+
if (normalized === "*")
|
|
7634
|
+
return null;
|
|
7635
|
+
const orParts = normalized.split(/\s*\|\|\s*/);
|
|
7636
|
+
let minVersion = null;
|
|
7637
|
+
for (const part of orParts) {
|
|
7638
|
+
const coerced = import_semver2.default.coerce(part.trim());
|
|
7639
|
+
if (coerced) {
|
|
7640
|
+
if (!minVersion || import_semver2.default.lt(coerced.version, minVersion)) {
|
|
7641
|
+
minVersion = coerced.version;
|
|
7642
|
+
}
|
|
7643
|
+
}
|
|
7644
|
+
}
|
|
7645
|
+
return minVersion;
|
|
7646
|
+
}
|
|
7647
|
+
function extractMaxVersion(constraint) {
|
|
7648
|
+
const normalized = normalizeComposerConstraint(constraint);
|
|
7649
|
+
if (normalized === "*")
|
|
7650
|
+
return null;
|
|
7651
|
+
const upperBoundMatch = normalized.match(/<(=?)\s*(\d+(?:\.\d+)*)/);
|
|
7652
|
+
if (upperBoundMatch) {
|
|
7653
|
+
const coerced = import_semver2.default.coerce(upperBoundMatch[2]);
|
|
7654
|
+
return coerced ? coerced.version : null;
|
|
7655
|
+
}
|
|
7656
|
+
const caretMatch = normalized.match(/\^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
|
|
7657
|
+
if (caretMatch) {
|
|
7658
|
+
const major = parseInt(caretMatch[1], 10);
|
|
7659
|
+
return `${major + 1}.0.0`;
|
|
7660
|
+
}
|
|
7661
|
+
return null;
|
|
7662
|
+
}
|
|
7663
|
+
function checkPhpCompatibility(projectPhp, packagePhp) {
|
|
7664
|
+
if (!packagePhp || packagePhp === "*")
|
|
7665
|
+
return { satisfied: true };
|
|
7666
|
+
if (!projectPhp)
|
|
7667
|
+
return { satisfied: true };
|
|
7668
|
+
const projectMin = extractMinVersion(projectPhp);
|
|
7669
|
+
if (!projectMin)
|
|
7670
|
+
return { satisfied: true };
|
|
7671
|
+
const packageNorm = normalizeComposerConstraint(packagePhp);
|
|
7672
|
+
const packageParts = packageNorm.split(/\s*\|\|\s*/).filter((p) => p.trim());
|
|
7673
|
+
for (const part of packageParts) {
|
|
7674
|
+
const partMax = extractMaxVersion(part);
|
|
7675
|
+
if (partMax && import_semver2.default.gte(projectMin, partMax))
|
|
7676
|
+
continue;
|
|
7677
|
+
try {
|
|
7678
|
+
const range = import_semver2.default.validRange(part.trim());
|
|
7679
|
+
if (range && import_semver2.default.satisfies(projectMin, range))
|
|
7680
|
+
return { satisfied: true };
|
|
7681
|
+
} catch {}
|
|
7682
|
+
const partMin = extractMinVersion(part);
|
|
7683
|
+
if (partMin) {
|
|
7684
|
+
const partMajor = import_semver2.default.major(partMin);
|
|
7685
|
+
const projectMajor = import_semver2.default.major(projectMin);
|
|
7686
|
+
if (part.trim().startsWith("^")) {
|
|
7687
|
+
if (projectMajor === partMajor && import_semver2.default.gte(projectMin, partMin)) {
|
|
7688
|
+
return { satisfied: true };
|
|
7689
|
+
}
|
|
7690
|
+
} else if (import_semver2.default.gte(projectMin, partMin) && !partMax) {
|
|
7691
|
+
return { satisfied: true };
|
|
7692
|
+
}
|
|
7693
|
+
}
|
|
7694
|
+
}
|
|
7695
|
+
return { satisfied: false, reason: `requires php ${packagePhp}` };
|
|
7696
|
+
}
|
|
7697
|
+
|
|
7607
7698
|
// src/fetcher.ts
|
|
7608
7699
|
var PACKAGIST_API = "https://repo.packagist.org/p2";
|
|
7609
|
-
|
|
7700
|
+
var CACHE_VERSION = 1;
|
|
7701
|
+
async function fetchPackage(packageName, minStability = "stable", preferStable = true, currentVersion, allowMajor = true, noCache = false, projectPhp) {
|
|
7610
7702
|
const cacheKey = packageName.replace("/", "_");
|
|
7611
7703
|
let cachedEntry = null;
|
|
7612
7704
|
const headers = {};
|
|
7613
7705
|
if (!noCache) {
|
|
7614
|
-
cachedEntry = await getCacheEntry(cacheKey);
|
|
7706
|
+
cachedEntry = await getCacheEntry(cacheKey, CACHE_VERSION);
|
|
7615
7707
|
if (cachedEntry?.lastModified) {
|
|
7616
7708
|
headers["If-Modified-Since"] = cachedEntry.lastModified;
|
|
7617
7709
|
}
|
|
7618
7710
|
}
|
|
7711
|
+
let data;
|
|
7619
7712
|
try {
|
|
7620
7713
|
const url = `${PACKAGIST_API}/${packageName}.json`;
|
|
7621
7714
|
const response = await fetch(url, { headers });
|
|
7622
7715
|
if (response.status === 304 && cachedEntry) {
|
|
7623
|
-
await touchCache(cacheKey);
|
|
7624
|
-
|
|
7625
|
-
}
|
|
7626
|
-
|
|
7716
|
+
await touchCache(cacheKey, CACHE_VERSION);
|
|
7717
|
+
data = cachedEntry.value;
|
|
7718
|
+
} else if (response.ok) {
|
|
7719
|
+
data = await response.json();
|
|
7720
|
+
if (!noCache) {
|
|
7721
|
+
const lastModified = response.headers.get("Last-Modified") || undefined;
|
|
7722
|
+
await setCache(cacheKey, data, CACHE_VERSION, { lastModified });
|
|
7723
|
+
}
|
|
7724
|
+
} else {
|
|
7627
7725
|
return null;
|
|
7628
|
-
|
|
7726
|
+
}
|
|
7629
7727
|
const versions = data.packages?.[packageName] ?? [];
|
|
7630
7728
|
if (versions.length === 0)
|
|
7631
7729
|
return null;
|
|
@@ -7653,21 +7751,39 @@ async function fetchPackage(packageName, minStability = "stable", preferStable =
|
|
|
7653
7751
|
}
|
|
7654
7752
|
if (!selectedVersion)
|
|
7655
7753
|
return null;
|
|
7754
|
+
let phpIncompatible = false;
|
|
7755
|
+
let skippedVersion;
|
|
7756
|
+
if (projectPhp && selectedVersion.require?.php) {
|
|
7757
|
+
const phpCheck = checkPhpCompatibility(projectPhp, selectedVersion.require.php);
|
|
7758
|
+
if (!phpCheck.satisfied) {
|
|
7759
|
+
phpIncompatible = true;
|
|
7760
|
+
skippedVersion = selectedVersion.version;
|
|
7761
|
+
const versionsToCheck = preferStable ? eligibleVersions.filter((v) => getVersionStability(v.version) === "stable") : eligibleVersions;
|
|
7762
|
+
const compatibleVersion = versionsToCheck.find((v) => {
|
|
7763
|
+
if (!v.require?.php)
|
|
7764
|
+
return true;
|
|
7765
|
+
return checkPhpCompatibility(projectPhp, v.require.php).satisfied;
|
|
7766
|
+
});
|
|
7767
|
+
if (compatibleVersion && compatibleVersion !== selectedVersion) {
|
|
7768
|
+
selectedVersion = compatibleVersion;
|
|
7769
|
+
}
|
|
7770
|
+
}
|
|
7771
|
+
}
|
|
7656
7772
|
const phpRequirement = selectedVersion.require?.php;
|
|
7657
7773
|
let majorDetected;
|
|
7658
7774
|
if (currentVersion) {
|
|
7659
7775
|
const currentNorm = normalizeVersion(currentVersion);
|
|
7660
7776
|
const selectedNorm = normalizeVersion(selectedVersion.version);
|
|
7661
7777
|
if (currentNorm && selectedNorm) {
|
|
7662
|
-
const currentMajor =
|
|
7663
|
-
const selectedMajor =
|
|
7778
|
+
const currentMajor = import_semver3.default.major(currentNorm);
|
|
7779
|
+
const selectedMajor = import_semver3.default.major(selectedNorm);
|
|
7664
7780
|
if (selectedMajor > currentMajor) {
|
|
7665
7781
|
majorDetected = selectedVersion.version;
|
|
7666
7782
|
if (!allowMajor) {
|
|
7667
7783
|
const versionsToCheck = preferStable ? eligibleVersions.filter((v) => getVersionStability(v.version) === "stable") : eligibleVersions;
|
|
7668
7784
|
const sameMajorVersion = versionsToCheck.find((v) => {
|
|
7669
7785
|
const norm = normalizeVersion(v.version);
|
|
7670
|
-
return norm &&
|
|
7786
|
+
return norm && import_semver3.default.major(norm) === currentMajor;
|
|
7671
7787
|
});
|
|
7672
7788
|
if (sameMajorVersion) {
|
|
7673
7789
|
selectedVersion = sameMajorVersion;
|
|
@@ -7689,25 +7805,24 @@ async function fetchPackage(packageName, minStability = "stable", preferStable =
|
|
|
7689
7805
|
phpRequirement: selectedVersion.require?.php ?? phpRequirement,
|
|
7690
7806
|
majorVersion: majorDetected,
|
|
7691
7807
|
deprecated: deprecatedInfo.deprecated,
|
|
7692
|
-
replacement: deprecatedInfo.replacement
|
|
7808
|
+
replacement: deprecatedInfo.replacement,
|
|
7809
|
+
phpIncompatible: phpIncompatible || undefined,
|
|
7810
|
+
skippedVersion,
|
|
7811
|
+
require: selectedVersion.require
|
|
7693
7812
|
};
|
|
7694
|
-
if (!noCache) {
|
|
7695
|
-
const lastModified = response.headers.get("Last-Modified") || undefined;
|
|
7696
|
-
await setCache(cacheKey, result, { lastModified });
|
|
7697
|
-
}
|
|
7698
7813
|
return result;
|
|
7699
7814
|
} catch {
|
|
7700
7815
|
return null;
|
|
7701
7816
|
}
|
|
7702
7817
|
}
|
|
7703
|
-
async function fetchAllPackages(packages, minStability = "stable", preferStable = true, allowMajor = true, noCache = false) {
|
|
7818
|
+
async function fetchAllPackages(packages, minStability = "stable", preferStable = true, allowMajor = true, noCache = false, projectPhp) {
|
|
7704
7819
|
const results = new Map;
|
|
7705
7820
|
const entries = Object.entries(packages);
|
|
7706
7821
|
const CONCURRENCY = 5;
|
|
7707
7822
|
for (let i = 0;i < entries.length; i += CONCURRENCY) {
|
|
7708
7823
|
const batch = entries.slice(i, i + CONCURRENCY);
|
|
7709
7824
|
const promises = batch.map(async ([name, version]) => {
|
|
7710
|
-
const result = await fetchPackage(name, minStability, preferStable, version, allowMajor, noCache);
|
|
7825
|
+
const result = await fetchPackage(name, minStability, preferStable, version, allowMajor, noCache, projectPhp);
|
|
7711
7826
|
if (result)
|
|
7712
7827
|
results.set(name, result);
|
|
7713
7828
|
});
|
|
@@ -7964,6 +8079,9 @@ function renderTable(packages) {
|
|
|
7964
8079
|
if (pkg.phpRequirement) {
|
|
7965
8080
|
extra += import_picocolors.default.gray(` php ${pkg.phpRequirement}`);
|
|
7966
8081
|
}
|
|
8082
|
+
if (pkg.phpIncompatible && pkg.skippedVersion) {
|
|
8083
|
+
extra += import_picocolors.default.yellow(` ${pkg.skippedVersion} skipped (php)`);
|
|
8084
|
+
}
|
|
7967
8085
|
if (pkg.deprecated) {
|
|
7968
8086
|
extra += import_picocolors.default.red(" deprecated");
|
|
7969
8087
|
if (pkg.replacement) {
|
|
@@ -7972,6 +8090,15 @@ function renderTable(packages) {
|
|
|
7972
8090
|
}
|
|
7973
8091
|
console.log(` ${name} ${oldVer} ${arrow} ${coloredNewVer} ${diffLabel} ${age}${extra}`);
|
|
7974
8092
|
}
|
|
8093
|
+
const skippedPackages = packages.filter((p) => p.phpIncompatible && p.skippedVersion);
|
|
8094
|
+
if (skippedPackages.length > 0) {
|
|
8095
|
+
console.log(import_picocolors.default.yellow(`
|
|
8096
|
+
Some versions skipped due to PHP constraints:`));
|
|
8097
|
+
for (const pkg of skippedPackages) {
|
|
8098
|
+
console.log(` ${import_picocolors.default.bold(pkg.name)} ${pkg.skippedVersion} requires higher PHP version`);
|
|
8099
|
+
}
|
|
8100
|
+
console.log(import_picocolors.default.gray(" Update the php constraint in composer.json to use these versions."));
|
|
8101
|
+
}
|
|
7975
8102
|
console.log("");
|
|
7976
8103
|
}
|
|
7977
8104
|
function renderHeader(version) {
|
|
@@ -8012,6 +8139,9 @@ function formatPackageChoice(pkg) {
|
|
|
8012
8139
|
if (pkg.phpRequirement) {
|
|
8013
8140
|
extra += import_picocolors.default.gray(` php ${pkg.phpRequirement}`);
|
|
8014
8141
|
}
|
|
8142
|
+
if (pkg.phpIncompatible && pkg.skippedVersion) {
|
|
8143
|
+
extra += import_picocolors.default.yellow(` ${pkg.skippedVersion} skipped`);
|
|
8144
|
+
}
|
|
8015
8145
|
if (pkg.deprecated) {
|
|
8016
8146
|
extra += import_picocolors.default.red(" deprecated");
|
|
8017
8147
|
if (pkg.replacement) {
|
|
@@ -8057,7 +8187,7 @@ async function selectPackages(packages) {
|
|
|
8057
8187
|
// package.json
|
|
8058
8188
|
var package_default = {
|
|
8059
8189
|
name: "comze",
|
|
8060
|
-
version: "0.3.
|
|
8190
|
+
version: "0.3.2",
|
|
8061
8191
|
description: "A taze-like CLI for updating composer.json dependencies",
|
|
8062
8192
|
author: "qoqn",
|
|
8063
8193
|
license: "MIT",
|
|
@@ -8133,7 +8263,8 @@ async function run(options) {
|
|
|
8133
8263
|
console.log(import_picocolors2.default.gray(` Checking ${Object.keys(filteredPackages).length} packages...`));
|
|
8134
8264
|
console.log(import_picocolors2.default.gray(` Stability: ${minStability}${preferStable ? " (prefer-stable)" : ""}
|
|
8135
8265
|
`));
|
|
8136
|
-
const
|
|
8266
|
+
const projectPhp = allPackages["php"];
|
|
8267
|
+
const results = await fetchAllPackages(filteredPackages, minStability, preferStable, options.major, options.noCache, projectPhp);
|
|
8137
8268
|
const updates = [];
|
|
8138
8269
|
const deprecatedPackages = [];
|
|
8139
8270
|
for (const [name, currentVersion] of Object.entries(filteredPackages)) {
|
|
@@ -8168,7 +8299,9 @@ async function run(options) {
|
|
|
8168
8299
|
majorAvailable,
|
|
8169
8300
|
phpRequirement: result.phpRequirement,
|
|
8170
8301
|
deprecated: result.deprecated,
|
|
8171
|
-
replacement: result.replacement
|
|
8302
|
+
replacement: result.replacement,
|
|
8303
|
+
phpIncompatible: result.phpIncompatible,
|
|
8304
|
+
skippedVersion: result.skippedVersion
|
|
8172
8305
|
});
|
|
8173
8306
|
}
|
|
8174
8307
|
const order = { major: 0, minor: 1, patch: 2 };
|