UNPKG

fraci

Version:

Fractional indexing that's robust, performant, and secure, with first-class support for Drizzle ORM and Prisma ORM.

728 lines (719 loc) 15.8 kB
"use strict"; var P = Object.defineProperty; var En = Object.getOwnPropertyDescriptor; var mn = Object.getOwnPropertyNames; var hn = Object.prototype.hasOwnProperty; var An = (n, e) => { for (var r in e) P(n, r, { get: e[r], enumerable: !0 }); }, In = (n, e, r, t) => { if (e && typeof e == "object" || typeof e == "function") for (let o of mn(e)) !hn.call(n, o) && o !== r && P(n, o, { get: () => e[o], enumerable: !(t = En(e, o)) || t.enumerable }); return n; }; var xn = (n) => In(P({}, "__esModule", { value: !0 }), n); // src/index.ts var Kn = {}; An(Kn, { BASE10: () => Fn, BASE16L: () => Bn, BASE16U: () => _n, BASE26L: () => bn, BASE26U: () => wn, BASE36L: () => Mn, BASE36U: () => Un, BASE52: () => Tn, BASE62: () => Rn, BASE64URL: () => Sn, BASE88: () => Nn, BASE95: () => Ln, DEFAULT_MAX_LENGTH: () => z, DEFAULT_MAX_RETRIES: () => J, FraciError: () => c, createFraciCache: () => Cn, fraci: () => $n, fraciBinary: () => gn, fraciString: () => dn, getFraciErrorCode: () => On, isFraciError: () => Dn }); module.exports = xn(Kn); // src/bases.ts var Fn = "0123456789", Bn = "0123456789abcdef", _n = "0123456789ABCDEF", bn = "abcdefghijklmnopqrstuvwxyz", wn = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", Mn = "0123456789abcdefghijklmnopqrstuvwxyz", Un = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", Tn = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", Rn = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", Sn = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz", Nn = "!#$%()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~", Ln = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; // src/lib/errors.ts var c = class extends Error { constructor(r, t) { super(`[${r}] ${t}`); this.code = r; this.message = t; this.name = "FraciError"; } name; }; function Dn(n) { return n instanceof c; } function On(n) { return n instanceof c ? n.code : void 0; } // src/lib/decimal-binary.ts var G = new Uint8Array([128, 0]), Xn = new Uint8Array([127, 255]); function _(n, e) { let r = Math.min(n.length, e.length), t = 0; for (let o = 0; !t && o < r; o++) t = n[o] - e[o]; return t || n.length - e.length; } function I(n, e) { let r = new Uint8Array(n.length + e.length); return r.set(n), r.set(e, n.length), r; } function V(n) { let [e] = n; return e - (e >= 128 ? 127 : 128); } function Q(n) { return n + (n < 0 ? 128 : 127); } function R(n) { return n.length === 129 && n.every((e) => e === 0); } function b(n) { let e = Math.abs(V(n)) + 1; if (!(Number.isNaN(e) || n.length < e)) return [n.subarray(0, e), n.subarray(e)]; } function k(n) { if (!n.length) return; let e = V(n), r = n.slice(0, Math.abs(e) + 1); for (let i = r.length - 1; i >= 1; i--) if (r[i]++ < 255) return r; if (e === -1) return G.slice(); let t = e + 1; if (t > 128) return null; let o = new Uint8Array(Math.abs(t) + 1); return o[0] = Q(t), o; } function Y(n) { let e = V(n); if (Number.isNaN(e)) return; let r = n.slice(0, Math.abs(e) + 1); for (let i = r.length - 1; i >= 1; i--) if (r[i]--) return r; if (e === 1) return Xn.slice(); let t = e - 1; if (t < -128) return null; let o = new Uint8Array(Math.abs(t) + 1).fill(255); return o[0] = Q(t), o; } function F(n, e) { if (e != null && _(n, e) >= 0) return; if (e) { let a = e.findIndex((l, s) => l !== (n[s] ?? 0)); if (a > 0) { let l = F( n.subarray(a), e.subarray(a) ); return l ? I(e.subarray(0, a), l) : void 0; } } let r = n[0] ?? 0, t = e ? e[0] : 256; if (t == null) return; if (r + 1 !== t) { let a = r + t >> 1; return new Uint8Array([a]); } if (e && e.length > 1) return new Uint8Array([e[0]]); let o = F(n.subarray(1), null); if (!o) return; let i = new Uint8Array(1 + o.length); return i[0] = r, i.set(o, 1), i; } // src/lib/decimal-string.ts function Z(n, e) { return e.get(n[0]); } function w(n, e) { let r = Math.abs(Z(n, e) ?? 0) + 1; if (!(r < 2 || n.length < r)) return [n.slice(0, r), n.slice(r)]; } function nn(n, e) { return e.get(1) + n[0]; } function en(n, e) { let r = Math.min(...Array.from(e.keys())); return `${e.get(r)}${n[0].repeat(Math.abs(r))}`; } function j(n, e, r, t, o) { let i = Z(n, o); if (!i) return; let a = e[0], [l, ...s] = n.slice(0, Math.abs(i) + 1); for (let y = s.length - 1; y >= 0; y--) { let g = r.get(s[y]); if (g == null) return; if (g < e.length - 1) return s[y] = e[g + 1], `${l}${s.join("")}`; s[y] = a; } if (i === -1) return `${t.get(1)}${a}`; let u = i + 1, f = t.get(u); return f ? `${f}${a.repeat(Math.abs(u))}` : null; } function rn(n, e, r, t, o) { let i = Z(n, o); if (!i) return; let a = e[e.length - 1], [l, ...s] = n.slice(0, Math.abs(i) + 1); for (let y = s.length - 1; y >= 0; y--) { let g = r.get(s[y]); if (g == null) return; if (g > 0) return s[y] = e[g - 1], `${l}${s.join("")}`; s[y] = a; } if (i === 1) return `${t.get(-1)}${a}`; let u = i - 1, f = t.get(u); return f ? `${f}${a.repeat(Math.abs(u))}` : null; } function B(n, e, r, t) { if (e != null && e <= n) return; if (e) { let a = n.padEnd(e.length, r[0]), l = Array.prototype.findIndex.call( e, (s, u) => s !== a[u] ); if (l > 0) return `${e.slice(0, l)}${B( n.slice(l), e.slice(l), r, t )}`; } let o = n ? t.get(n[0]) : 0, i = e ? t.get(e[0]) : r.length; if (!(o == null || i == null)) { if (o + 1 !== i) { let a = o + i >> 1; return r[a]; } return e && e.length > 1 ? e[0] : `${r[o]}${B( n.slice(1), null, r, t )}`; } } // src/lib/fractional-indexing-binary.ts function S(n) { return n?.constructor.name === "Buffer" ? new Uint8Array(n.buffer, n.byteOffset, n.length) : n; } function N(n) { if (!n.length || R(n)) return !1; let e = b(n); if (!e) return !1; let [, r] = e; return r?.at(-1) !== 0; } function E(n) { if (n === void 0) throw console.error( "FraciError: [INTERNAL_ERROR] Unexpected undefined. Please file an issue to report this error." ), new c("INTERNAL_ERROR", "Unexpected undefined"); return n; } function M(n, e) { if (!n) { if (!e) return G.slice(); let [l, s] = E(b(e)); if (R(l)) return I( l, E(F(new Uint8Array(), s)) ); if (s.length) return l.slice(); let u = E( Y(l) ); if (!R(u)) return u; let f = new Uint8Array(u.length + 1); return f.set(u), f[u.length] = 255, f; } if (!e) { let l = E(b(n)), [s, u] = l, f = E(k(s)); return f || I(s, E(F(u, null))); } let [r, t] = E(b(n)), [o, i] = E(b(e)); if (!_(r, o)) return I( r, E(F(t, i)) ); let a = E(k(r)); return a && _(a, o) ? ( // 1. If incrementing a's integer doesn't reach b's integer, // we can use the incremented value (shorter key) a ) : ( // 2. If incrementing a's integer equals b's integer or we can't increment, // we need to use a's integer with a fractional part that sorts after a's fractional part I(r, E(F(t, null))) ); } function tn(n, e) { return n != null && !N(n) || e != null && !N(e) || n != null && e != null && _(n, e) >= 0 ? void 0 : M(S(n), S(e)); } function H(n, e, r) { if (r < 1) return []; if (r === 1) return [M(n, e)]; if (e == null) { let i = n; return Array.from( { length: r }, () => i = M(i, e) ); } if (n == null) { let i = e; return Array.from( { length: r }, () => i = M(n, i) ).reverse(); } let t = r >> 1, o = M(n, e); return [ ...H(n, o, t), o, ...H(o, e, r - t - 1) ]; } function on(n, e, r) { return n != null && !N(n) || e != null && !N(e) || n != null && e != null && _(n, e) >= 0 ? void 0 : H(S(n), S(e), r); } function q(n) { let e = []; for (; n > 0; ) e.push(n & 255), n >>= 8; return new Uint8Array(e); } // src/lib/fractional-indexing-string.ts function L(n, e, r, t, o) { if (!n || n === o) return !1; let i = w(n, t); if (!i) return !1; let [a, l] = i; if (l.endsWith(e[0])) return !1; for (let s of a.slice(1)) if (!r.has(s)) return !1; for (let s of l) if (!r.has(s)) return !1; return !0; } function m(n) { if (n === void 0) throw console.error( "FraciError: [INTERNAL_ERROR] Unexpected undefined. Please file an issue to report this error." ), new c("INTERNAL_ERROR", "Unexpected undefined"); return n; } function U(n, e, r, t, o, i, a) { if (!n) { if (!e) return nn(r, o); let [d, h] = m(w(e, i)); if (d === a) return `${d}${m( B("", h, r, t) )}`; if (h) return d; let p = m( rn( d, r, t, o, i ) ); return p === a ? `${p}${r[r.length - 1]}` : p; } if (!e) { let d = m(w(n, i)), [h, p] = d, x = m( j( h, r, t, o, i ) ); return x !== null ? x : `${h}${m( B(p, null, r, t) )}`; } let l = m(w(n, i)), s = m(w(e, i)), [u, f] = l, [y, g] = s; if (u === y) return `${u}${m( B(f, g, r, t) )}`; let A = m( j( u, r, t, o, i ) ); return A !== null && A !== y ? ( // 1. If incrementing a's integer doesn't reach b's integer, // we can use the incremented value (shorter key) A ) : ( // 2. If incrementing a's integer equals b's integer or we can't increment, // we need to use a's integer with a fractional part that sorts after a's fractional part `${u}${m( B(f, null, r, t) )}` ); } function an(n, e, r, t, o, i, a) { return n != null && !L( n, r, t, i, a ) || e != null && !L( e, r, t, i, a ) || n != null && e != null && e <= n ? void 0 : U( n, e, r, t, o, i, a ); } function W(n, e, r, ...t) { if (r < 1) return []; if (r === 1) return [U(n, e, ...t)]; if (e == null) { let a = n; return Array.from( { length: r }, () => a = U(a, e, ...t) ); } if (n == null) { let a = e; return Array.from( { length: r }, () => a = U(n, a, ...t) ).reverse(); } let o = r >> 1, i = U(n, e, ...t); return [ ...W(n, i, o, ...t), i, ...W(i, e, r - o - 1, ...t) ]; } function ln(n, e, r, t, o, i, a, l) { return n != null && !L( n, t, o, a, l ) || e != null && !L( e, t, o, a, l ) || n != null && e != null && e <= n ? void 0 : W( n, e, r, t, o, i, a, l ); } function v(n, e) { let r = e.length, t = ""; for (; n > 0; ) t += e[n % r], n = Math.floor(n / r); return t; } // src/lib/utils.ts var sn = "INITIALIZATION_FAILED"; function un(n) { let e = n.split(""); if (e.length < 4) throw new c( sn, "Base string must have at least 4 unique characters" ); let r = -1; for (let t of e) { let o = t.charCodeAt(0); if (o <= r) throw new c( sn, "Base string characters must be unique and in ascending order" ); r = o; } return e; } function cn(n) { let e = un(n); return [e, new Map(e.map((r, t) => [r, t]))]; } function fn(n) { let e = un(n), r = e.length >> 1, t = e.map( (o, i) => [ i < r ? ( // For characters in the first half, assign negative values starting from -1 i - r ) : ( // For characters in the second half, assign positive values starting from 1 i - r + 1 ), // This maps to 1, 2, 3, etc. (skipping 0) o ] ); return [ new Map(t), new Map(t.map(([o, i]) => [i, o])) ]; } // src/factory.ts var z = 50, J = 5, D = "INVALID_FRACTIONAL_INDEX", T = "Invalid indices provided", O = "MAX_LENGTH_EXCEEDED", X = "Exceeded maximum length", C = "MAX_RETRIES_EXCEEDED", $ = "Exceeded maximum retries"; function Cn() { return /* @__PURE__ */ new Map(); } function yn(n, e, r) { if (!n) return r(); let t = n.get(e); return t === void 0 && (t = r(), n.set(e, t)), t; } function K(n, e, r) { console.error( `FraciError: [INVALID_FRACTIONAL_INDEX] ${T}. a = ${n}, b = ${e}, skip = ${r} Make sure that - Fractional indices generated by the same fraci instance with the same configuration are being used as-is - Indices in different groups have not been mixed up - a (the first argument item) comes before b (the second argument item) in the group File an issue if you use the library correctly and still encounter this error.` ); } function gn({ maxLength: n = z, maxRetries: e = J } = {}) { return { base: { type: "binary" }, *generateKeyBetween(r, t, o = 0) { let i = tn(r, t); if (!i) throw K(r, t, o), new c( D, T ); for (let a = 0; a < e; a++) { let l = I(i, q(a + o)); if (l.length > n) throw new c( O, X ); yield l; } throw new c( C, $ ); }, *generateNKeysBetween(r, t, o, i = 0) { let a = on(r, t, o); if (!a) throw K(r, t, i), new c( D, T ); let l = a.reduce((s, u) => Math.max(s, u.length), 0); for (let s = 0; s < e; s++) { let u = q(s + i); if (l + u.length > n) throw new c( O, X ); yield a.map((f) => I(f, u)); } throw new c( C, $ ); } }; } function dn({ lengthBase: n, digitBase: e, maxLength: r = z, maxRetries: t = J }, o) { let [i, a] = yn( o, `L${n}`, fn.bind(null, n) ), [l, s] = yn( o, `D${e}`, cn.bind(null, e) ), u = en(l, i); return { base: { type: "string", lengthBase: n, digitBase: e }, *generateKeyBetween(f, y, g = 0) { let A = an( f, y, l, s, i, a, u ); if (!A) throw K(f, y, g), new c( D, T ); for (let d = 0; d < t; d++) { let h = `${A}${v(d + g, l)}`; if (h.length > r) throw new c( O, X ); yield h; } throw new c( C, $ ); }, *generateNKeysBetween(f, y, g, A = 0) { let d = ln( f, y, g, l, s, i, a, u ); if (!d) throw K(f, y, A), new c( D, T ); let h = d.reduce((p, x) => Math.max(p, x.length), 0); for (let p = 0; p < t; p++) { let x = v(p + A, l); if (h + x.length > r) throw new c( O, X ); yield d.map((pn) => `${pn}${x}`); } throw new c( C, $ ); } }; } function $n(n, e) { return n.type === "binary" ? (e && console.warn("Fraci: Cache is not used for binary base"), gn(n)) : dn(n, e); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BASE10, BASE16L, BASE16U, BASE26L, BASE26U, BASE36L, BASE36U, BASE52, BASE62, BASE64URL, BASE88, BASE95, DEFAULT_MAX_LENGTH, DEFAULT_MAX_RETRIES, FraciError, createFraciCache, fraci, fraciBinary, fraciString, getFraciErrorCode, isFraciError }); //# sourceMappingURL=index.cjs.map