mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix: say out loud what every sort was already doing
Sonar's S2871 flags a bare .sort(), which orders by UTF-16 code unit rather than by value. All 30 remaining sites turned out to sort ASCII strings — ISO dates, currency and country codes, setting keys, route names, OAuth scopes, zip entry names — where that order is already the intended one. Each says so explicitly now, with a comparator that reproduces it exactly rather than a localeCompare that would quietly reorder things. That mattered more than it sounds. Several of these feed something other than a display: useAtlas joins the sorted codes into the signature that decides whether to rebuild the region layer, daysSlice re-pins sorted dates positionally onto reordered days, and three timeline views pick a day's colour by indexOf into the sorted array. Switching any of them to a locale collator would have been a silent regression. Two smaller ones came with it. The .map(placeBtn) calls in FileManagerAssignModal pass the index as a second argument, which placeBtn declares and uses for its React key — correct already, now written out as .map((p, i) => placeBtn(p, i)). And budgetSlice's optimistic paid-toggle stored the raw boolean behind `paid as unknown as number`, while the schema declares z.number() and both the REST response and the WebSocket event carry 0/1. So the optimistic state and the confirmed state disagreed on type until a refresh. It normalises now, and the two tests that asserted `true` assert the contract. Four `| 0` truncations are listed in sonar-project.properties instead of changed. Two are a djb2 string hash where the 32-bit wrap is the algorithm. The other two look like plain truncation of a row id, but `| 0` is also coercing undefined to 0 there — the settlement flows the API returns carry no user_id, so that is the normal path, and Math.trunc returns NaN and crashes the lookup.
This commit is contained in:
@@ -141,12 +141,12 @@ const manifestAtCommit: NetworkCheck = {
|
||||
if ((m.operatorEgress === true) !== (v.operatorEgress === true)) {
|
||||
p(`manifest operatorEgress ${m.operatorEgress === true} != entry ${v.operatorEgress === true}`);
|
||||
}
|
||||
const normAddons = (a: unknown) => (Array.isArray(a) ? [...a].map(String).sort() : []);
|
||||
const normAddons = (a: unknown) => (Array.isArray(a) ? [...a].map(String).sort((x, y) => (x < y ? -1 : x > y ? 1 : 0)) : []);
|
||||
if (JSON.stringify(normAddons(m.requiredAddons)) !== JSON.stringify(normAddons(v.requiredAddons))) {
|
||||
p('manifest requiredAddons != entry requiredAddons');
|
||||
}
|
||||
const normDeps = (d: unknown) =>
|
||||
(Array.isArray(d) ? d.map((x) => `${(x as { id?: string })?.id}@${(x as { version?: string })?.version}`).sort() : []);
|
||||
(Array.isArray(d) ? d.map((x) => `${(x as { id?: string })?.id}@${(x as { version?: string })?.version}`).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)) : []);
|
||||
if (JSON.stringify(normDeps(m.pluginDependencies)) !== JSON.stringify(normDeps(v.pluginDependencies))) {
|
||||
p('manifest pluginDependencies != entry pluginDependencies');
|
||||
}
|
||||
|
||||
@@ -530,12 +530,12 @@ const releaseEntryParity: OfflineCheck = {
|
||||
problems.push(`• manifest operatorEgress ${m.operatorEgress === true} != entry ${v.operatorEgress === true}`);
|
||||
}
|
||||
|
||||
const normAddons = (a: unknown) => [...arr(a)].sort();
|
||||
const normAddons = (a: unknown) => [...arr(a)].sort((x, y) => (x < y ? -1 : x > y ? 1 : 0));
|
||||
if (JSON.stringify(normAddons(m.requiredAddons)) !== JSON.stringify(normAddons(v.requiredAddons))) {
|
||||
problems.push(`• manifest requiredAddons [${normAddons(m.requiredAddons)}] != entry [${normAddons(v.requiredAddons)}]`);
|
||||
}
|
||||
const normDeps = (d: unknown) =>
|
||||
(Array.isArray(d) ? d.map((x) => `${(x as { id?: string })?.id}@${(x as { version?: string })?.version}`).sort() : []);
|
||||
(Array.isArray(d) ? d.map((x) => `${(x as { id?: string })?.id}@${(x as { version?: string })?.version}`).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)) : []);
|
||||
if (JSON.stringify(normDeps(m.pluginDependencies)) !== JSON.stringify(normDeps(v.pluginDependencies))) {
|
||||
problems.push(`• manifest pluginDependencies [${normDeps(m.pluginDependencies)}] != entry [${normDeps(v.pluginDependencies)}]`);
|
||||
}
|
||||
|
||||
@@ -100,6 +100,6 @@ export function packPluginDir(dir: string, outPath: string): PackResult {
|
||||
artifact: outAbs,
|
||||
sha256: createHash('sha256').update(buf).digest('hex'),
|
||||
size: buf.length,
|
||||
files: filtered.map((f) => f.name).sort(),
|
||||
files: filtered.map((f) => f.name).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user