fraci
Version:
Fractional indexing that's robust, performant, and secure, with first-class support for Drizzle ORM and Prisma ORM.
656 lines (649 loc) • 13 kB
JavaScript
// src/lib/errors.ts
var c = class extends Error {
constructor(e, t) {
super(`[${e}] ${t}`);
this.code = e;
this.message = t;
this.name = "FraciError";
}
name;
};
function pn(n) {
return n instanceof c;
}
function En(n) {
return n instanceof c ? n.code : void 0;
}
// src/lib/decimal-binary.ts
var K = new Uint8Array([128, 0]), gn = new Uint8Array([127, 255]);
function b(n, r) {
let e = Math.min(n.length, r.length), t = 0;
for (let a = 0; !t && a < e; a++)
t = n[a] - r[a];
return t || n.length - r.length;
}
function I(n, r) {
let e = new Uint8Array(n.length + r.length);
return e.set(n), e.set(r, n.length), e;
}
function k(n) {
let [r] = n;
return r - (r >= 128 ? 127 : 128);
}
function q(n) {
return n + (n < 0 ? 128 : 127);
}
function U(n) {
return n.length === 129 && n.every((r) => r === 0);
}
function B(n) {
let r = Math.abs(k(n)) + 1;
if (!(Number.isNaN(r) || n.length < r))
return [n.subarray(0, r), n.subarray(r)];
}
function P(n) {
if (!n.length)
return;
let r = k(n), e = n.slice(0, Math.abs(r) + 1);
for (let i = e.length - 1; i >= 1; i--)
if (e[i]++ < 255)
return e;
if (r === -1)
return K.slice();
let t = r + 1;
if (t > 128)
return null;
let a = new Uint8Array(Math.abs(t) + 1);
return a[0] = q(t), a;
}
function W(n) {
let r = k(n);
if (Number.isNaN(r))
return;
let e = n.slice(0, Math.abs(r) + 1);
for (let i = e.length - 1; i >= 1; i--)
if (e[i]--)
return e;
if (r === 1)
return gn.slice();
let t = r - 1;
if (t < -128)
return null;
let a = new Uint8Array(Math.abs(t) + 1).fill(255);
return a[0] = q(t), a;
}
function _(n, r) {
if (r != null && b(n, r) >= 0)
return;
if (r) {
let o = r.findIndex((l, s) => l !== (n[s] ?? 0));
if (o > 0) {
let l = _(
n.subarray(o),
r.subarray(o)
);
return l ? I(r.subarray(0, o), l) : void 0;
}
}
let e = n[0] ?? 0, t = r ? r[0] : 256;
if (t == null)
return;
if (e + 1 !== t) {
let o = e + t >> 1;
return new Uint8Array([o]);
}
if (r && r.length > 1)
return new Uint8Array([r[0]]);
let a = _(n.subarray(1), null);
if (!a)
return;
let i = new Uint8Array(1 + a.length);
return i[0] = e, i.set(a, 1), i;
}
// src/lib/decimal-string.ts
function G(n, r) {
return r.get(n[0]);
}
function M(n, r) {
let e = Math.abs(G(n, r) ?? 0) + 1;
if (!(e < 2 || n.length < e))
return [n.slice(0, e), n.slice(e)];
}
function z(n, r) {
return r.get(1) + n[0];
}
function J(n, r) {
let e = Math.min(...Array.from(r.keys()));
return `${r.get(e)}${n[0].repeat(Math.abs(e))}`;
}
function V(n, r, e, t, a) {
let i = G(n, a);
if (!i)
return;
let o = r[0], [l, ...s] = n.slice(0, Math.abs(i) + 1);
for (let g = s.length - 1; g >= 0; g--) {
let d = e.get(s[g]);
if (d == null)
return;
if (d < r.length - 1)
return s[g] = r[d + 1], `${l}${s.join("")}`;
s[g] = o;
}
if (i === -1)
return `${t.get(1)}${o}`;
let u = i + 1, f = t.get(u);
return f ? `${f}${o.repeat(Math.abs(u))}` : null;
}
function Q(n, r, e, t, a) {
let i = G(n, a);
if (!i)
return;
let o = r[r.length - 1], [l, ...s] = n.slice(0, Math.abs(i) + 1);
for (let g = s.length - 1; g >= 0; g--) {
let d = e.get(s[g]);
if (d == null)
return;
if (d > 0)
return s[g] = r[d - 1], `${l}${s.join("")}`;
s[g] = o;
}
if (i === 1)
return `${t.get(-1)}${o}`;
let u = i - 1, f = t.get(u);
return f ? `${f}${o.repeat(Math.abs(u))}` : null;
}
function x(n, r, e, t) {
if (r != null && r <= n)
return;
if (r) {
let o = n.padEnd(r.length, e[0]), l = Array.prototype.findIndex.call(
r,
(s, u) => s !== o[u]
);
if (l > 0)
return `${r.slice(0, l)}${x(
n.slice(l),
r.slice(l),
e,
t
)}`;
}
let a = n ? t.get(n[0]) : 0, i = r ? t.get(r[0]) : e.length;
if (!(a == null || i == null)) {
if (a + 1 !== i) {
let o = a + i >> 1;
return e[o];
}
return r && r.length > 1 ? r[0] : `${e[a]}${x(
n.slice(1),
null,
e,
t
)}`;
}
}
// src/lib/fractional-indexing-binary.ts
function R(n) {
return n?.constructor.name === "Buffer" ? new Uint8Array(n.buffer, n.byteOffset, n.length) : n;
}
function N(n) {
if (!n.length || U(n))
return !1;
let r = B(n);
if (!r)
return !1;
let [, e] = r;
return e?.at(-1) !== 0;
}
function E(n) {
if (n === void 0)
throw new c("INTERNAL_ERROR", "Unexpected undefined");
return n;
}
function w(n, r) {
if (!n) {
if (!r)
return K.slice();
let [l, s] = E(B(r));
if (U(l))
return I(
l,
E(_(new Uint8Array(), s))
);
if (s.length)
return l.slice();
let u = E(
W(l)
);
if (!U(u))
return u;
let f = new Uint8Array(u.length + 1);
return f.set(u), f[u.length] = 255, f;
}
if (!r) {
let l = E(B(n)), [s, u] = l, f = E(P(s));
return f || I(s, E(_(u, null)));
}
let [e, t] = E(B(n)), [a, i] = E(B(r));
if (!b(e, a))
return I(
e,
E(_(t, i))
);
let o = E(P(e));
return o && b(o, a) ? (
// 1. If incrementing a's integer doesn't reach b's integer,
// we can use the incremented value (shorter key)
o
) : (
// 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(e, E(_(t, null)))
);
}
function Y(n, r) {
return n != null && !N(n) || r != null && !N(r) || n != null && r != null && b(n, r) >= 0 ? void 0 : w(R(n), R(r));
}
function Z(n, r, e) {
if (e < 1)
return [];
if (e === 1)
return [w(n, r)];
if (r == null) {
let i = n;
return Array.from(
{ length: e },
() => i = w(i, r)
);
}
if (n == null) {
let i = r;
return Array.from(
{ length: e },
() => i = w(n, i)
).reverse();
}
let t = e >> 1, a = w(n, r);
return [
...Z(n, a, t),
a,
...Z(a, r, e - t - 1)
];
}
function nn(n, r, e) {
return n != null && !N(n) || r != null && !N(r) || n != null && r != null && b(n, r) >= 0 ? void 0 : Z(R(n), R(r), e);
}
function H(n) {
let r = [];
for (; n > 0; )
r.push(n & 255), n >>= 8;
return new Uint8Array(r);
}
// src/lib/fractional-indexing-string.ts
function S(n, r, e, t, a) {
if (!n || n === a)
return !1;
let i = M(n, t);
if (!i)
return !1;
let [o, l] = i;
if (l.endsWith(r[0]))
return !1;
for (let s of o.slice(1))
if (!e.has(s))
return !1;
for (let s of l)
if (!e.has(s))
return !1;
return !0;
}
function h(n) {
if (n === void 0)
throw new c("INTERNAL_ERROR", "Unexpected undefined");
return n;
}
function T(n, r, e, t, a, i, o) {
if (!n) {
if (!r)
return z(e, a);
let [y, m] = h(M(r, i));
if (y === o)
return `${y}${h(
x("", m, e, t)
)}`;
if (m)
return y;
let p = h(
Q(
y,
e,
t,
a,
i
)
);
return p === o ? `${p}${e[e.length - 1]}` : p;
}
if (!r) {
let y = h(M(n, i)), [m, p] = y, F = h(
V(
m,
e,
t,
a,
i
)
);
return F !== null ? F : `${m}${h(
x(p, null, e, t)
)}`;
}
let l = h(M(n, i)), s = h(M(r, i)), [u, f] = l, [g, d] = s;
if (u === g)
return `${u}${h(
x(f, d, e, t)
)}`;
let A = h(
V(
u,
e,
t,
a,
i
)
);
return A !== null && A !== g ? (
// 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}${h(
x(f, null, e, t)
)}`
);
}
function rn(n, r, e, t, a, i, o) {
return n != null && !S(
n,
e,
t,
i,
o
) || r != null && !S(
r,
e,
t,
i,
o
) || n != null && r != null && r <= n ? void 0 : T(
n,
r,
e,
t,
a,
i,
o
);
}
function j(n, r, e, ...t) {
if (e < 1)
return [];
if (e === 1)
return [T(n, r, ...t)];
if (r == null) {
let o = n;
return Array.from(
{ length: e },
() => o = T(o, r, ...t)
);
}
if (n == null) {
let o = r;
return Array.from(
{ length: e },
() => o = T(n, o, ...t)
).reverse();
}
let a = e >> 1, i = T(n, r, ...t);
return [
...j(n, i, a, ...t),
i,
...j(i, r, e - a - 1, ...t)
];
}
function en(n, r, e, t, a, i, o, l) {
return n != null && !S(
n,
t,
a,
o,
l
) || r != null && !S(
r,
t,
a,
o,
l
) || n != null && r != null && r <= n ? void 0 : j(
n,
r,
e,
t,
a,
i,
o,
l
);
}
function v(n, r) {
let e = r.length, t = "";
for (; n > 0; )
t += r[n % e], n = Math.floor(n / e);
return t;
}
// src/lib/utils.ts
var tn = "INITIALIZATION_FAILED";
function an(n) {
let r = n.split("");
if (r.length < 4)
throw new c(
tn,
"Base string must have at least 4 unique characters"
);
let e = -1;
for (let t of r) {
let a = t.charCodeAt(0);
if (a <= e)
throw new c(
tn,
"Base string characters must be unique and in ascending order"
);
e = a;
}
return r;
}
function on(n) {
let r = an(n);
return [r, new Map(r.map((e, t) => [e, t]))];
}
function ln(n) {
let r = an(n), e = r.length >> 1, t = r.map(
(a, i) => [
i < e ? (
// For characters in the first half, assign negative values starting from -1
i - e
) : (
// For characters in the second half, assign positive values starting from 1
i - e + 1
),
// This maps to 1, 2, 3, etc. (skipping 0)
a
]
);
return [
new Map(t),
new Map(t.map(([a, i]) => [i, a]))
];
}
// src/factory.ts
var un = 50, cn = 5, D = "INVALID_FRACTIONAL_INDEX", L = "Invalid indices provided", O = "MAX_LENGTH_EXCEEDED", X = "Exceeded maximum length", C = "MAX_RETRIES_EXCEEDED", $ = "Exceeded maximum retries";
function Ln() {
return /* @__PURE__ */ new Map();
}
function sn(n, r, e) {
if (!n)
return e();
let t = n.get(r);
return t === void 0 && (t = e(), n.set(r, t)), t;
}
function yn({
maxLength: n = un,
maxRetries: r = cn
} = {}) {
return {
base: { type: "binary" },
*generateKeyBetween(e, t, a = 0) {
let i = Y(e, t);
if (!i)
throw new c(
D,
L
);
for (let o = 0; o < r; o++) {
let l = I(i, H(o + a));
if (l.length > n)
throw new c(
O,
X
);
yield l;
}
throw new c(
C,
$
);
},
*generateNKeysBetween(e, t, a, i = 0) {
let o = nn(e, t, a);
if (!o)
throw new c(
D,
L
);
let l = o.reduce((s, u) => Math.max(s, u.length), 0);
for (let s = 0; s < r; s++) {
let u = H(s + i);
if (l + u.length > n)
throw new c(
O,
X
);
yield o.map((f) => I(f, u));
}
throw new c(
C,
$
);
}
};
}
function dn({
lengthBase: n,
digitBase: r,
maxLength: e = un,
maxRetries: t = cn
}, a) {
let [i, o] = sn(
a,
`L${n}`,
ln.bind(null, n)
), [l, s] = sn(
a,
`D${r}`,
on.bind(null, r)
), u = J(l, i);
return {
base: {
type: "string",
lengthBase: n,
digitBase: r
},
*generateKeyBetween(f, g, d = 0) {
let A = rn(
f,
g,
l,
s,
i,
o,
u
);
if (!A)
throw new c(
D,
L
);
for (let y = 0; y < t; y++) {
let m = `${A}${v(y + d, l)}`;
if (m.length > e)
throw new c(
O,
X
);
yield m;
}
throw new c(
C,
$
);
},
*generateNKeysBetween(f, g, d, A = 0) {
let y = en(
f,
g,
d,
l,
s,
i,
o,
u
);
if (!y)
throw new c(
D,
L
);
let m = y.reduce((p, F) => Math.max(p, F.length), 0);
for (let p = 0; p < t; p++) {
let F = v(p + A, l);
if (m + F.length > e)
throw new c(
O,
X
);
yield y.map((fn) => `${fn}${F}`);
}
throw new c(
C,
$
);
}
};
}
function On(n, r) {
return n.type === "binary" ? yn(n) : dn(n, r);
}
export {
c as a,
pn as b,
En as c,
un as d,
cn as e,
Ln as f,
yn as g,
dn as h,
On as i
};
//# sourceMappingURL=chunk-H7E2WV2H.js.map