UNPKG

alinea

Version:

[![npm](https://img.shields.io/npm/v/alinea.svg)](https://npmjs.org/package/alinea) [![install size](https://packagephobia.com/badge?p=alinea)](https://packagephobia.com/result?p=alinea)

228 lines (226 loc) 5.7 kB
import "../../chunks/chunk-U5RRZUYZ.js"; // src/core/util/FractionalIndexing.ts var BASE_62_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var SMALLEST_INTEGER = "A00000000000000000000000000"; var INTEGER_ZERO = "a0"; function midpoint(a, b, digits) { if (b !== null && a >= b) { throw new Error(a + " >= " + b); } if (a.slice(-1) === "0" || b && b.slice(-1) === "0") { throw new Error("trailing zero"); } if (b) { let n = 0; while ((a[n] || "0") === b[n]) { n++; } if (n > 0) { return b.slice(0, n) + midpoint(a.slice(n), b.slice(n), digits); } } const digitA = a ? digits.indexOf(a[0]) : 0; const digitB = b !== null ? digits.indexOf(b[0]) : digits.length; if (digitB - digitA > 1) { const midDigit = Math.round(0.5 * (digitA + digitB)); return digits[midDigit]; } else { if (b && b.length > 1) { return b.slice(0, 1); } else { return digits[digitA] + midpoint(a.slice(1), null, digits); } } } function validateInteger(int) { if (int.length !== getIntegerLength(int[0])) { throw new Error("invalid integer part of order key: " + int); } } function getIntegerLength(head) { if (head >= "a" && head <= "z") { return head.charCodeAt(0) - "a".charCodeAt(0) + 2; } else if (head >= "A" && head <= "Z") { return "Z".charCodeAt(0) - head.charCodeAt(0) + 2; } else { throw new Error("invalid order key head: " + head); } } function getIntegerPart(key) { const integerPartLength = getIntegerLength(key[0]); if (integerPartLength > key.length) { throw new Error("invalid order key: " + key); } return key.slice(0, integerPartLength); } function validateOrderKey(key) { if (key === SMALLEST_INTEGER) { throw new Error("invalid order key: " + key); } const i = getIntegerPart(key); const f = key.slice(i.length); if (f.slice(-1) === "0") { throw new Error("invalid order key: " + key); } } function isValidOrderKey(key) { try { validateOrderKey(key); return true; } catch (e) { return false; } } function incrementInteger(x, digits) { validateInteger(x); const [head, ...digs] = x.split(""); let carry = true; for (let i = digs.length - 1; carry && i >= 0; i--) { const d = digits.indexOf(digs[i]) + 1; if (d === digits.length) { digs[i] = "0"; } else { digs[i] = digits[d]; carry = false; } } if (carry) { if (head === "Z") { return "a0"; } if (head === "z") { return null; } const h = String.fromCharCode(head.charCodeAt(0) + 1); if (h > "a") { digs.push("0"); } else { digs.pop(); } return h + digs.join(""); } else { return head + digs.join(""); } } function decrementInteger(x, digits) { validateInteger(x); const [head, ...digs] = x.split(""); let borrow = true; for (let i = digs.length - 1; borrow && i >= 0; i--) { const d = digits.indexOf(digs[i]) - 1; if (d === -1) { digs[i] = digits.slice(-1); } else { digs[i] = digits[d]; borrow = false; } } if (borrow) { if (head === "a") { return "Z" + digits.slice(-1); } if (head === "A") { return null; } const h = String.fromCharCode(head.charCodeAt(0) - 1); if (h < "Z") { digs.push(digits.slice(-1)); } else { digs.pop(); } return h + digs.join(""); } else { return head + digs.join(""); } } function generateKeyBetween(a, b, digits = BASE_62_DIGITS) { if (a !== null) { validateOrderKey(a); } if (b !== null) { validateOrderKey(b); } if (a !== null && b !== null && a >= b) { throw new Error(a + " >= " + b); } if (a === null) { if (b === null) { return INTEGER_ZERO; } const ib2 = getIntegerPart(b); const fb2 = b.slice(ib2.length); if (ib2 === SMALLEST_INTEGER) { return ib2 + midpoint("", fb2, digits); } if (ib2 < b) { return ib2; } const res = decrementInteger(ib2, digits); if (res === null) { throw new Error("cannot decrement any more"); } return res; } if (b === null) { const ia2 = getIntegerPart(a); const fa2 = a.slice(ia2.length); const i2 = incrementInteger(ia2, digits); return i2 === null ? ia2 + midpoint(fa2, null, digits) : i2; } const ia = getIntegerPart(a); const fa = a.slice(ia.length); const ib = getIntegerPart(b); const fb = b.slice(ib.length); if (ia === ib) { return ia + midpoint(fa, fb, digits); } const i = incrementInteger(ia, digits); if (i === null) { throw new Error("cannot increment any more"); } if (i < b) { return i; } return ia + midpoint(fa, null, digits); } function generateNKeysBetween(a, b, n, digits = BASE_62_DIGITS) { if (n === 0) { return []; } if (n === 1) { return [generateKeyBetween(a, b, digits)]; } if (b === null) { let c2 = generateKeyBetween(a, b, digits); const result = [c2]; for (let i = 0; i < n - 1; i++) { c2 = generateKeyBetween(c2, b, digits); result.push(c2); } return result; } if (a === null) { let c2 = generateKeyBetween(a, b, digits); const result = [c2]; for (let i = 0; i < n - 1; i++) { c2 = generateKeyBetween(a, c2, digits); result.push(c2); } result.reverse(); return result; } const mid = Math.floor(n / 2); const c = generateKeyBetween(a, b, digits); return [ ...generateNKeysBetween(a, c, mid, digits), c, ...generateNKeysBetween(c, b, n - mid - 1, digits) ]; } export { BASE_62_DIGITS, generateKeyBetween, generateNKeysBetween, isValidOrderKey, validateOrderKey };