@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
71 lines • 3.03 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
/**
* Order two strings by Unicode code point, the way Python's `sorted` does.
*
* JavaScript's default comparator compares UTF-16 code *units*. Astral
* characters (U+10000 and up) are stored as a surrogate pair in
* 0xD800-0xDFFF, so they sort before every BMP character from U+E000 up —
* while Python puts them after. A directory holding `\u{1F600}.txt` and a
* U+E000 name therefore lists in opposite orders across the two trees, and
* any listing compared against a shared integ truth file diverges. See
* issue #370.
*
* There is no Python counterpart because `sorted()` is already code-point
* ordered; this is the module that makes TypeScript agree with it. Use it
* for anything a user can see the order of. eslint bans the zero-argument
* default comparator outright so it cannot creep back.
*/
export function compareCodePoints(a, b) {
if (a === b)
return 0;
let i = 0;
let j = 0;
while (i < a.length && j < b.length) {
const aPoint = a.codePointAt(i) ?? 0;
const bPoint = b.codePointAt(j) ?? 0;
if (aPoint !== bPoint)
return aPoint - bPoint;
i += aPoint > 0xffff ? 2 : 1;
j += bPoint > 0xffff ? 2 : 1;
}
return a.length - i - (b.length - j);
}
/**
* Order two `/`-separated paths component by component, each compared by
* code point, so a path sorts right after its parent the way Python's
* `sorted(key=lambda p: p.split("/"))` and a sorted readdir walk put it.
*/
export function compareComponents(a, b) {
const ca = a.split('/');
const cb = b.split('/');
const n = Math.min(ca.length, cb.length);
for (let i = 0; i < n; i += 1) {
const order = compareCodePoints(ca[i] ?? '', cb[i] ?? '');
if (order !== 0)
return order;
}
return ca.length - cb.length;
}
/**
* JSON with each object's keys in code-point order, the key order of
* Python's `json.dumps(value, sort_keys=True)`, so an encoded checkpoint does
* not depend on the order its maps were filled in.
*/
export function sortedJson(value) {
return JSON.stringify(value, (_key, item) => item !== null && typeof item === 'object' && !Array.isArray(item)
? Object.fromEntries(Object.entries(item).sort(([a], [b]) => compareCodePoints(a, b)))
: item);
}
//# sourceMappingURL=sort.js.map