{"version":3,"sources":["../src/prisma.ts","../src/prisma/extension.ts","../src/lib/decimal-binary.ts","../src/lib/decimal-string.ts","../src/lib/errors.ts","../src/lib/fractional-indexing-binary.ts","../src/lib/fractional-indexing-string.ts","../src/lib/utils.ts","../src/factory.ts","../src/prisma/common.ts","../src/prisma/constants.ts","../src/prisma/schema.ts"],"sourcesContent":["/**\n * The Prisma ORM integration for the fraci library.\n *\n * @module fraci/prisma\n */\n\nexport * from \"./prisma/index.js\";\n","// Import `@prisma/client/extension.js` instead of `@prisma/client` to prevent types in `PrismaClient` from being extracted in the return type of the `prismaFraci` function.\n// In `@prisma/client/extension.js`, `PrismaClient` is exported as `any`, which is not usable by users, so the import destination is modified to `@prisma/client` in post-processing.\nimport { Prisma } from \"@prisma/client/extension.js\";\nimport {\n  createFraciCache,\n  DEFAULT_MAX_LENGTH,\n  DEFAULT_MAX_RETRIES,\n  fraciBinary,\n  fraciString,\n  type AnyFraci,\n  type Fraci,\n} from \"../factory.js\";\nimport { FraciError } from \"../lib/errors.js\";\nimport type { AnyFractionalIndex, FractionalIndex } from \"../lib/types.js\";\nimport type { FraciOf } from \"../types.js\";\nimport {\n  isIndexConflictError,\n  type PrismaClientConflictError,\n} from \"./common.js\";\nimport { EXTENSION_NAME } from \"./constants.js\";\nimport type {\n  AllModelFieldName,\n  AnyPrismaClient,\n  BinaryModelFieldName,\n  ModelKey,\n  ModelScalarPayload,\n  QueryArgs,\n  StringModelFieldName,\n} from \"./prisma-types.js\";\nimport type { PrismaFraciFieldOptions, PrismaFraciOptions } from \"./schema.js\";\n\n/**\n * A brand for Prisma models and fields.\n *\n * @template Model - The model name\n * @template Field - The field name\n */\ntype PrismaBrand<Model extends string, Field extends string> = {\n  readonly __prisma__: { model: Model; field: Field };\n};\n\n/**\n * A tuple of two fractional indices, used for generating a new index between them.\n *\n * @template FI - The fractional index type\n */\ntype Indices<FI extends AnyFractionalIndex> = [a: FI | null, b: FI | null];\n\n/**\n * Type representing the enhanced fractional indexing utility for Prisma ORM.\n * This type extends the base fractional indexing utility with additional methods for retrieving indices.\n *\n * This is an internal type used to define the methods for the Prisma extension.\n *\n * @template Model - The model name\n * @template Where - The type of the required fields for the `where` argument of the `findMany` method\n * @template FI - The fractional index type\n *\n * @see {@link Fraci} - The base fractional indexing utility type\n */\ntype FraciForPrismaInternal<\n  Model extends ModelKey,\n  Where,\n  FI extends AnyFractionalIndex,\n> = FraciOf<FI> & {\n  /**\n   * Checks if the error is a conflict error for the fractional index.\n   *\n   * @param error - The error to check.\n   * @returns `true` if the error is a conflict error for the fractional index, or `false` otherwise.\n   */\n  isIndexConflictError(error: unknown): error is PrismaClientConflictError;\n  /**\n   * Retrieves the existing indices to generate a new fractional index for the item after the specified item.\n   *\n   * @param where - The `where` argument of the `findMany` method. Must have the fields specified in the {@link PrismaFraciFieldOptions.group group} property of the field options.\n   * @param cursor - The cursor (selector) of the item. If `null`, this method returns the indices to generate a new fractional index for the first item.\n   * @param client - The Prisma client to use. Should be specified when using transactions. If not specified, the client used to create the extension is used.\n   * @returns The indices to generate a new fractional index for the item after the specified item, or `undefined` if the item specified by the `cursor` does not exist.\n   */\n  indicesForAfter: {\n    (\n      where: Where & QueryArgs<Model>[\"where\"],\n      cursor: QueryArgs<Model>[\"cursor\"],\n      client?: AnyPrismaClient,\n    ): Promise<Indices<FI> | undefined>;\n    (\n      where: Where & QueryArgs<Model>[\"where\"],\n      cursor: null,\n      client?: AnyPrismaClient,\n    ): Promise<Indices<FI>>;\n  };\n  /**\n   * Retrieves the existing indices to generate a new fractional index for the item before the specified item.\n   *\n   * @param where - The `where` argument of the `findMany` method. Must have the fields specified in the {@link PrismaFraciFieldOptions.group group} property of the field options.\n   * @param cursor - The cursor (selector) of the item. If `null`, this method returns the indices to generate a new fractional index for the last item.\n   * @param client - The Prisma client to use. Should be specified when using transactions. If not specified, the client used to create the extension is used.\n   * @returns The indices to generate a new fractional index for the item before the specified item, or `undefined` if the item specified by the `cursor` does not exist.\n   */\n  indicesForBefore: {\n    (\n      where: Where & QueryArgs<Model>[\"where\"],\n      cursor: QueryArgs<Model>[\"cursor\"],\n      client?: AnyPrismaClient,\n    ): Promise<Indices<FI> | undefined>;\n    (\n      where: Where & QueryArgs<Model>[\"where\"],\n      cursor: null,\n      client?: AnyPrismaClient,\n    ): Promise<Indices<FI>>;\n  };\n  /**\n   * Retrieves the existing indices to generate a new fractional index for the first item.\n   * Equivalent to {@link FraciForPrismaInternal.indicesForAfter `indicesForAfter(where, null, client)`}.\n   *\n   * @param where - The `where` argument of the `findMany` method. Must have the fields specified in the {@link PrismaFraciOptions.group group} property of the field options.\n   * @param client - The Prisma client to use. Should be specified when using transactions. If not specified, the client used to create the extension is used.\n   * @returns The indices to generate a new fractional index for the first item.\n   */\n  indicesForFirst(\n    where: Where & QueryArgs<Model>[\"where\"],\n    client?: AnyPrismaClient,\n  ): Promise<Indices<FI>>;\n  /**\n   * Retrieves the existing indices to generate a new fractional index for the last item.\n   * Equivalent to {@link FraciForPrismaInternal.indicesForBefore `indicesForBefore(where, null, client)`}.\n   *\n   * @param where - The `where` argument of the `findMany` method. Must have the fields specified in the {@link PrismaFraciOptions.group group} property of the field options.\n   * @param client - The Prisma client to use. Should be specified when using transactions. If not specified, the client used to create the extension is used.\n   * @returns The indices to generate a new fractional index for the last item.\n   */\n  indicesForLast(\n    where: Where & QueryArgs<Model>[\"where\"],\n    client?: AnyPrismaClient,\n  ): Promise<Indices<FI>>;\n};\n\n/**\n * Type representing the enhanced fractional indexing utility for Prisma ORM.\n * This type extends the base fractional indexing utility with additional methods for retrieving indices.\n *\n * @template Options - The field options type\n * @template Model - The model name\n * @template Field - The field name\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n */\ntype FraciForPrismaByFieldOptions<\n  Options extends PrismaFraciFieldOptions,\n  Model extends ModelKey,\n  Field extends BinaryModelFieldName<Model> | StringModelFieldName<Model>,\n> = FraciForPrismaInternal<\n  Model,\n  Pick<\n    ModelScalarPayload<Model>,\n    Extract<Options[\"group\"][number], AllModelFieldName<Model>>\n  >,\n  Field extends BinaryModelFieldName<Model>\n    ? Options extends { readonly type: \"binary\" }\n      ? FractionalIndex<Options, PrismaBrand<Model, Field>>\n      : never\n    : Options extends {\n          readonly lengthBase: string;\n          readonly digitBase: string;\n        }\n      ? FractionalIndex<\n          {\n            readonly type: \"string\";\n            readonly lengthBase: Options[\"lengthBase\"];\n            readonly digitBase: Options[\"digitBase\"];\n          },\n          PrismaBrand<Model, Field>\n        >\n      : never\n>;\n\n/**\n * Type representing the enhanced fractional indexing utility for Prisma ORM.\n * This type extends the base fractional indexing utility with additional methods for retrieving indices.\n *\n * @template Options - The options type\n * @template QualifiedField - The qualified field name\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n */\nexport type FraciForPrisma<\n  Options extends PrismaFraciOptions,\n  QualifiedField extends keyof Options[\"fields\"],\n> = Options[\"fields\"][QualifiedField] extends PrismaFraciFieldOptions\n  ? QualifiedField extends `${infer M}.${infer F}`\n    ? FraciForPrismaByFieldOptions<Options[\"fields\"][QualifiedField], M, F>\n    : never\n  : never;\n\n/**\n * A union of the pairs of the key and value of the {@link PrismaFraciOptions.fields fields} property of the options.\n *\n * @template Options - The options type\n *\n * @example [\"article.fi\", { group: [\"userId\"], lengthBase: \"0123456789\", digitBase: \"0123456789\" }] | [\"photo.fi\", { group: [\"userId\"], lengthBase: \"0123456789\", digitBase: \"0123456789\" }] | ...\n */\ntype FieldsUnion<Options extends PrismaFraciOptions> = {\n  [K in keyof Options[\"fields\"]]: [K, Options[\"fields\"][K]];\n}[keyof Options[\"fields\"]];\n\n/**\n * The field information for each model.\n *\n * @template Options - The options type\n */\ntype PerModelFieldInfo<Options extends PrismaFraciOptions> = {\n  [M in ModelKey]: {\n    [F in\n      | BinaryModelFieldName<M>\n      | StringModelFieldName<M> as `${M}.${F}` extends FieldsUnion<Options>[0]\n      ? F\n      : never]: {\n      readonly helper: Options[\"fields\"][`${M}.${F}`] extends PrismaFraciFieldOptions\n        ? FraciForPrismaByFieldOptions<Options[\"fields\"][`${M}.${F}`], M, F>\n        : never;\n    };\n  };\n};\n\n/**\n * [model component](https://www.prisma.io/docs/orm/prisma-client/client-extensions/model) of the Prisma extension.\n *\n * @template Options - The options type\n */\ntype PrismaFraciExtensionModel<Options extends PrismaFraciOptions> = {\n  [M in keyof PerModelFieldInfo<Options>]: {\n    fraci<F extends keyof PerModelFieldInfo<Options>[M]>(\n      field: F,\n    ): PerModelFieldInfo<Options>[M][F][\"helper\"];\n  };\n};\n\n/**\n * The type of our Prisma extension.\n *\n * @template Options - The options type\n */\nexport type PrismaFraciExtension<Options extends PrismaFraciOptions> = {\n  name: typeof EXTENSION_NAME;\n  model: PrismaFraciExtensionModel<Options>;\n};\n\n/**\n * {@link AnyFraci} for Prisma.\n */\ntype AnyFraciForPrisma = FraciForPrismaInternal<\n  string,\n  any,\n  AnyFractionalIndex\n>;\n\n/**\n * Creates a Prisma extension for fractional indexing.\n *\n * @template Options - The options type\n *\n * @param options - The options for the fractional indexing extension\n * @returns The Prisma extension.\n * @throws {FraciError} Throws a {@link FraciError} when field information for a specified model.field cannot be retrieved\n * @throws {FraciError} Throws a {@link FraciError} when the digit or length base strings are invalid\n *\n * @see {@link FraciForPrisma} - The enhanced fractional indexing utility for Prisma ORM\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nexport function prismaFraci<const Options extends PrismaFraciOptions>({\n  fields,\n  maxLength = DEFAULT_MAX_LENGTH,\n  maxRetries = DEFAULT_MAX_RETRIES,\n}: Options) {\n  return Prisma.defineExtension((client) => {\n    // Create a shared cache for better performance across multiple fields\n    const cache = createFraciCache();\n\n    // Map to store helper instances for each model.field combination\n    const helperMap = new Map<string, AnyFraciForPrisma>();\n\n    // Process each field configuration from the options\n    for (const [modelAndField, config] of Object.entries(fields) as [\n      string,\n      PrismaFraciFieldOptions,\n    ][]) {\n      // Split the \"model.field\" string into separate parts\n      const [model, field] = modelAndField.split(\".\", 2) as [ModelKey, string];\n\n      // Get the actual model name from Prisma metadata\n      const { modelName } = (client as any)[model]?.fields?.[field] ?? {};\n      if (!modelName) {\n        if (globalThis.__DEV__) {\n          console.error(`FraciError: [INITIALIZATION_FAILED] Could not get field information for ${model}.${field}.\nMake sure that\n- The model and field names are correct and exist in the Prisma schema\n- The Prisma client is generated with the correct schema\n- The Prisma version is compatible with the extension`);\n        }\n\n        throw new FraciError(\n          \"INITIALIZATION_FAILED\",\n          `Could not get field information for ${model}.${field}`,\n        );\n      }\n\n      // Create the base fractional indexing helper\n      const helper =\n        config.type === \"binary\"\n          ? fraciBinary({\n              maxLength,\n              maxRetries,\n            })\n          : fraciString(\n              {\n                ...config,\n                maxLength,\n                maxRetries,\n              },\n              cache,\n            );\n\n      /**\n       * Internal function to retrieve indices for positioning items.\n       * This function queries the database to find the appropriate indices\n       * for inserting an item before or after a specified cursor position.\n       *\n       * @param where - The where clause to filter items by group\n       * @param cursor - The cursor position, or null for first/last position\n       * @param direction - The direction to search for indices (asc/desc)\n       * @param tuple - A function to create a tuple from two indices\n       * @param pClient - The Prisma client to use\n       * @returns A tuple of indices, or undefined if the cursor doesn't exist\n       */\n      const indicesFor = async (\n        where: any,\n        cursor: any,\n        direction: \"asc\" | \"desc\",\n        tuple: <T>(a: T, b: T) => [T, T],\n        pClient: AnyPrismaClient = client,\n      ): Promise<any> => {\n        // Case 1: No cursor provided - get the first/last item in the group\n        if (!cursor) {\n          const item = await pClient[model].findFirst({\n            where, // Filter by group conditions\n            select: { [field]: true }, // Only select the fractional index field\n            orderBy: { [field]: direction }, // Order by the fractional index in appropriate direction\n          });\n\n          // We should always return a tuple of two indices if `cursor` is `null`.\n          // For after: [null, firstItem]\n          // For before: [lastItem, null]\n          return tuple(null, item?.[field] ?? null);\n        }\n\n        // Case 2: Cursor provided - find items adjacent to the cursor\n        const items = await pClient[model].findMany({\n          cursor, // Start from the cursor position\n          where, // Filter by group conditions\n          select: { [field]: true }, // Only select the fractional index field\n          orderBy: { [field]: direction }, // Order by the fractional index in appropriate direction\n          take: 2, // Get the cursor item and the adjacent item\n        });\n\n        return items.length < 1\n          ? // Return undefined if cursor not found\n            undefined\n          : // Return the indices in the appropriate order based on direction\n            tuple(items[0][field], items[1]?.[field] ?? null);\n      };\n\n      // Function to find indices for inserting an item after a specified cursor\n      const indicesForAfter = (\n        where: any,\n        cursor: any,\n        pClient?: AnyPrismaClient,\n      ): Promise<any> =>\n        indicesFor(where, cursor, \"asc\", (a, b) => [a, b], pClient);\n\n      // Function to find indices for inserting an item before a specified cursor\n      const indicesForBefore = (\n        where: any,\n        cursor: any,\n        pClient?: AnyPrismaClient,\n      ): Promise<any> =>\n        indicesFor(where, cursor, \"desc\", (a, b) => [b, a], pClient);\n\n      // Create an enhanced helper with Prisma-specific methods\n      const helperEx: AnyFraciForPrisma = {\n        ...(helper as AnyFraci), // Include all methods from the base fraci helper\n        isIndexConflictError: (\n          error: unknown,\n        ): error is PrismaClientConflictError =>\n          isIndexConflictError(error, modelName, field),\n        indicesForAfter,\n        indicesForBefore,\n        indicesForFirst: (where: any, pClient?: AnyPrismaClient) =>\n          indicesForAfter(where, null, pClient),\n        indicesForLast: (where: any, pClient?: AnyPrismaClient) =>\n          indicesForBefore(where, null, pClient),\n      };\n\n      // Store the helper in the map with a unique key combining model and field\n      helperMap.set(`${model}\\0${field}`, helperEx);\n    }\n\n    // Create the extension model object that will be attached to each Prisma model\n    const extensionModel = Object.create(null) as Record<ModelKey, unknown>;\n\n    // Iterate through all models in the Prisma client\n    for (const model of Object.keys(client) as ModelKey[]) {\n      // Skip internal Prisma properties that start with $ or _\n      if (model.startsWith(\"$\") || model.startsWith(\"_\")) {\n        continue;\n      }\n\n      // Add the fraci method to each model\n      extensionModel[model] = {\n        // This method retrieves the appropriate helper for the specified field\n        fraci(field: string) {\n          return helperMap.get(`${model}\\0${field}`)!;\n        },\n      };\n    }\n\n    // Register the extension with Prisma\n    return client.$extends({\n      name: EXTENSION_NAME,\n      model: extensionModel,\n    } as unknown as PrismaFraciExtension<Options>);\n  });\n}\n","export const INTEGER_ZERO = new Uint8Array([128, 0]);\n\nexport const INTEGER_MINUS_ONE = new Uint8Array([127, 255]);\n\n/**\n * Compares two Uint8Arrays.\n *\n * @param a - The first array\n * @param b - The second array\n * @returns A number indicating the comparison result\n *   - Negative if a < b\n *   - Zero if a == b\n *   - Positive if a > b\n */\nexport function compare(a: Uint8Array, b: Uint8Array): number {\n  const len = Math.min(a.length, b.length);\n  let r = 0;\n  for (let i = 0; !r && i < len; i++) {\n    r = a[i] - b[i];\n  }\n  return r || a.length - b.length;\n}\n\n/**\n * Concatenates two Uint8Arrays.\n *\n * @param a - The first array\n * @param b - The second array\n * @returns The concatenated array\n */\nexport function concat(a: Uint8Array, b: Uint8Array): Uint8Array {\n  const result = new Uint8Array(a.length + b.length);\n  result.set(a);\n  result.set(b, a.length);\n  return result;\n}\n\n/**\n * Gets the signed length of the integer part from a binary fractional index.\n * This function extracts the length information encoded in the first byte of the index string.\n *\n * @param index - The fractional index binary\n * @returns The signed length of the integer part, or NaN if the first character is invalid\n */\nexport function getIntegerLengthSigned(index: Uint8Array): number {\n  const [value] = index;\n  return value - (value >= 128 ? 127 : 128);\n}\n\n/**\n * Gets the byte representing the length of the integer part.\n * Reverse operation of {@link getIntegerLengthSigned}.\n *\n * @param signedLength - The signed length of the integer part\n * @returns The byte representing the length of the integer part\n */\nexport function getIntegerLengthByte(signedLength: number): number {\n  return signedLength + (signedLength < 0 ? 128 : 127);\n}\n\n/**\n * Checks if a binary fractional index represents the smallest possible integer.\n *\n * @param index - The fractional index binary to check\n * @returns A boolean indicating if the index represents the smallest integer\n */\nexport function isSmallestInteger(index: Uint8Array): boolean {\n  return index.length === 129 && index.every((v) => v === 0);\n}\n\n/**\n * Splits a fractional index binary into its integer and fractional parts.\n * This function uses the length information encoded in the first character\n * to determine where to split the binary.\n *\n * @param index - The fractional index binary to split\n * @returns A tuple containing the integer and fractional parts, or undefined if the index is invalid\n */\nexport function splitParts(\n  index: Uint8Array,\n): [integer: Uint8Array, fractional: Uint8Array] | undefined {\n  // Get the encoded length from the first character and convert to absolute value\n  // Add 1 because the length includes the length character itself\n  const intLength = Math.abs(getIntegerLengthSigned(index)) + 1;\n\n  // Validation: ensure the length is valid and the binary is long enough\n  if (Number.isNaN(intLength) || index.length < intLength) {\n    // Invalid length or binary too short\n    return;\n  }\n\n  // Split the string into integer and fractional parts\n  // The integer part includes the length character and the digits\n  // The fractional part is everything after the integer part\n  return [index.subarray(0, intLength), index.subarray(intLength)];\n}\n\n/**\n * Increments the integer part of a fractional index.\n * This function handles carrying and length changes when incrementing the integer.\n *\n * @param index - The fractional index binary whose integer part should be incremented\n * @returns\n *   - A new binary with the incremented integer part\n *   - null if the integer cannot be incremented (reached maximum value)\n *   - undefined if the input is invalid\n */\nexport function incrementInteger(\n  index: Uint8Array,\n): Uint8Array | null | undefined {\n  if (!index.length) {\n    return;\n  }\n\n  const intLengthSigned = getIntegerLengthSigned(index);\n\n  // Extract the length character and the actual digits from the integer part\n  const digits = index.slice(0, Math.abs(intLengthSigned) + 1);\n\n  // Try to increment the rightmost digit first, with carrying if needed\n  // This is similar to adding 1 to a number in the custom base system\n  for (let i = digits.length - 1; i >= 1; i--) {\n    // Increment the digit and check for overflow\n    // Note that Uint8Array wraps around on overflow, which is what we want\n    if (digits[i]++ < 255) {\n      // The digit is not 255 before increment, meaning no overflow will occur\n      // This is the common case for most increments\n      return digits;\n    }\n\n    // Overflow occurred - carry to the next digit to the left\n  }\n\n  // Special case: transitioning from negative to zero\n  // This is like going from -1 to 0 in decimal, which requires special handling\n  if (intLengthSigned === -1) {\n    // The integer is -1. We need to return 0.\n    // This requires changing the length encoding character to represent positive length\n    return INTEGER_ZERO.slice();\n  }\n\n  // If we get here, we've carried through all digits (like 999 + 1 = 1000)\n  // We need to increase the length of the integer representation\n  const newLenSigned = intLengthSigned + 1;\n  if (newLenSigned > 128) {\n    // Reached the limit of representable integers\n    // This is an edge case where we can't represent a larger integer\n    return null;\n  }\n\n  // Create a new integer with increased length (all digits are smallest digit)\n  const newBinary = new Uint8Array(Math.abs(newLenSigned) + 1);\n  newBinary[0] = getIntegerLengthByte(newLenSigned);\n  return newBinary;\n}\n\n/**\n * Decrements the integer part of a fractional index.\n * This function handles borrowing and length changes when decrementing the integer.\n *\n * @param index - The fractional index string whose integer part should be decremented\n * @returns\n *   - A new binary with the decremented integer part\n *   - null if the integer cannot be decremented (reached minimum value)\n *   - undefined if the input is invalid\n */\nexport function decrementInteger(\n  index: Uint8Array,\n): Uint8Array | null | undefined {\n  const intLengthSigned = getIntegerLengthSigned(index);\n  if (Number.isNaN(intLengthSigned)) {\n    return;\n  }\n\n  // Extract the length character and the actual digits from the integer part\n  const digits = index.slice(0, Math.abs(intLengthSigned) + 1);\n\n  // Try to decrement the rightmost digit first, with borrowing if needed\n  // This is similar to subtracting 1 from a number in the custom base system\n  for (let i = digits.length - 1; i >= 1; i--) {\n    // Decrement the digit and check for underflow\n    // Note that Uint8Array wraps around on underflow, which is what we want\n    if (digits[i]--) {\n      // The digit is non-zero before decrement, meaning no underflow will occur\n      return digits;\n    }\n\n    // Underflow occurred - borrow from the next digit to the left\n  }\n\n  // Special case: transitioning from zero to negative integers\n  // This is like going from 0 to -1 in decimal, which requires special handling\n  if (intLengthSigned === 1) {\n    // The integer is 0. We need to return -1.\n    // This requires changing the length encoding character to represent negative length\n    return INTEGER_MINUS_ONE.slice();\n  }\n\n  // If we get here, we've borrowed through all digits (like 1000 - 1 = 999)\n  // We need to decrease the length of the integer representation\n  const newLenSigned = intLengthSigned - 1;\n  if (newLenSigned < -128) {\n    // Reached the limit of representable integers\n    // This is an edge case where we can't represent a smaller integer\n    return null;\n  }\n\n  // Create a new integer with decreased length (all digits are largest digit)\n  const newBinary = new Uint8Array(Math.abs(newLenSigned) + 1).fill(255);\n  newBinary[0] = getIntegerLengthByte(newLenSigned);\n  return newBinary;\n}\n\n/**\n * Calculates the midpoint between two fractional parts.\n * This function recursively finds a string that sorts between two fractional parts.\n * It handles various cases including when one of the inputs is null.\n *\n * @param a - The lower bound fractional part, or empty binary if there is no lower bound\n * @param b - The upper bound fractional part, or null if there is no upper bound\n * @returns A binary that sorts between a and b, or undefined if inputs are invalid\n */\nexport function getMidpointFractional(\n  a: Uint8Array,\n  b: Uint8Array | null,\n): Uint8Array | undefined {\n  if (b != null && compare(a, b) >= 0) {\n    // Precondition failed.\n    return;\n  }\n\n  // Optimization: If a and b share a common prefix, preserve it\n  if (b) {\n    // Find the first position where a and b differ\n    const prefixLength = b.findIndex((value, i) => value !== (a[i] ?? 0));\n\n    // If they share a prefix, keep it and recursively find midpoint of the differing parts\n    if (prefixLength > 0) {\n      const suffix = getMidpointFractional(\n        a.subarray(prefixLength),\n        b.subarray(prefixLength),\n      );\n      if (!suffix) {\n        return;\n      }\n\n      return concat(b.subarray(0, prefixLength), suffix);\n    }\n  }\n\n  // At this point, we're handling the first differing digits\n  const aDigit = a[0] ?? 0;\n  const bDigit = b ? b[0] : 256;\n  if (bDigit == null) {\n    return;\n  }\n\n  // Case 1: Non-consecutive digits - we can simply use their average\n  if (aDigit + 1 !== bDigit) {\n    const mid = (aDigit + bDigit) >> 1; // Fast integer division by 2\n    return new Uint8Array([mid]);\n  }\n\n  // Case 2: Consecutive digits with b having two or more digits\n  if (b && b.length > 1) {\n    // We can just use b's first digit (which is one more than a's first digit)\n    return new Uint8Array([b[0]]);\n  }\n\n  // Case 3: Consecutive digits with b having length 1 or null\n  // This is the most complex case requiring recursive construction\n  // Example: midpoint('49', '5') becomes '495'\n  // We take a's first digit, then recursively find midpoint of a's remainder and null\n  const suffix = getMidpointFractional(a.subarray(1), null);\n  if (!suffix) {\n    return;\n  }\n\n  const result = new Uint8Array(1 + suffix.length);\n  result[0] = aDigit;\n  result.set(suffix, 1);\n  return result;\n}\n","/**\n * Gets the signed length of the integer part from a fractional index.\n * This function extracts the length information encoded in the first character\n * of the index string.\n *\n * @param index - The fractional index string\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @returns The signed length of the integer part, or undefined if the first character is invalid\n */\nexport function getIntegerLengthSigned(\n  index: string,\n  lenBaseReverse: ReadonlyMap<string, number>,\n): number | undefined {\n  return lenBaseReverse.get(index[0]);\n}\n\n/**\n * Splits a fractional index string into its integer and fractional parts.\n * This function uses the length information encoded in the first character\n * to determine where to split the string.\n *\n * @param index - The fractional index string to split\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @returns A tuple containing the integer and fractional parts, or undefined if the index is invalid\n */\nexport function splitParts(\n  index: string,\n  lenBaseReverse: ReadonlyMap<string, number>,\n): [integer: string, fractional: string] | undefined {\n  // Get the encoded length from the first character and convert to absolute value\n  // Add 1 because the length includes the length character itself\n  const intLength =\n    Math.abs(getIntegerLengthSigned(index, lenBaseReverse) ?? 0) + 1;\n\n  // Validation: ensure the length is valid and the string is long enough\n  if (intLength < 2 || index.length < intLength) {\n    // Invalid length or string too short\n    return;\n  }\n\n  // Split the string into integer and fractional parts\n  // The integer part includes the length character and the digits\n  // The fractional part is everything after the integer part\n  return [index.slice(0, intLength), index.slice(intLength)];\n}\n\n/**\n * Generates a string representation of the integer zero.\n * This function creates a string that represents the integer zero\n * in the specified digit base and length encoding.\n *\n * @param digBaseForward - Array mapping digit positions to characters\n * @param lenBaseForward - Map of length values to their encoding characters\n * @returns A string representation of the integer zero\n */\nexport function getIntegerZero(\n  digBaseForward: readonly string[],\n  lenBaseForward: ReadonlyMap<number, string>,\n): string {\n  return lenBaseForward.get(1)! + digBaseForward[0];\n}\n\n/**\n * Generates a string representation of the smallest possible integer.\n * This function finds the smallest length value in the length encoding map\n * and creates a string representing the smallest possible integer.\n *\n * @param digBaseForward - Array mapping digit positions to characters\n * @param lenBaseForward - Map of length values to their encoding characters\n * @returns A string representation of the smallest possible integer\n */\nexport function getSmallestInteger(\n  digBaseForward: readonly string[],\n  lenBaseForward: ReadonlyMap<number, string>,\n): string {\n  // Find the smallest length value in the length encoding map\n  // This will be the most negative value, representing the smallest possible integer\n  const minKey = Math.min(...Array.from(lenBaseForward.keys()));\n\n  // Get the character that encodes this smallest length\n  const minLenChar = lenBaseForward.get(minKey)!;\n\n  // Create a string with the length character followed by the smallest digit repeated\n  // The number of repetitions is the absolute value of the length\n  return `${minLenChar}${digBaseForward[0].repeat(Math.abs(minKey))}`;\n}\n\n/**\n * Increments the integer part of a fractional index.\n * This function handles carrying and length changes when incrementing the integer.\n *\n * @param index - The fractional index string whose integer part should be incremented\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @param lenBaseForward - Map of length values to their encoding characters\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @returns\n *   - A new string with the incremented integer part\n *   - null if the integer cannot be incremented (reached maximum value)\n *   - undefined if the input is invalid\n */\nexport function incrementInteger(\n  index: string,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n  lenBaseForward: ReadonlyMap<number, string>,\n  lenBaseReverse: ReadonlyMap<string, number>,\n): string | null | undefined {\n  const intLengthSigned = getIntegerLengthSigned(index, lenBaseReverse);\n  if (!intLengthSigned) {\n    return;\n  }\n\n  const smallestDigit = digBaseForward[0];\n\n  // Extract the length character and the actual digits from the integer part\n  const [lenChar, ...digits] = index.slice(0, Math.abs(intLengthSigned) + 1);\n\n  // Try to increment the rightmost digit first, with carrying if needed\n  // This is similar to adding 1 to a number in the custom base system\n  for (let i = digits.length - 1; i >= 0; i--) {\n    const value = digBaseReverse.get(digits[i]);\n    if (value == null) {\n      // Invalid digit\n      return;\n    }\n\n    if (value < digBaseForward.length - 1) {\n      // No carrying needed - we can increment this digit and return\n      // This is the common case for most increments\n      digits[i] = digBaseForward[value + 1];\n      return `${lenChar}${digits.join(\"\")}`;\n    }\n\n    // This digit is at max value (9 in decimal), set to smallest (0) and continue carrying\n    // We need to carry to the next digit to the left\n    digits[i] = smallestDigit;\n  }\n\n  // Special case: transitioning from negative integers to zero\n  // This is like going from -1 to 0 in decimal, which requires special handling\n  if (intLengthSigned === -1) {\n    // The integer is -1. We need to return 0.\n    // This requires changing the length encoding character\n    return `${lenBaseForward.get(1)!}${smallestDigit}`;\n  }\n\n  // If we get here, we've carried through all digits (like 999 + 1 = 1000)\n  // We need to increase the length of the integer representation\n  const newLenSigned = intLengthSigned + 1;\n  const newLenChar = lenBaseForward.get(newLenSigned);\n  if (!newLenChar) {\n    // Reached the limit of representable integers\n    // This is an edge case where we can't represent a larger integer\n    return null;\n  }\n\n  // Create a new integer with increased length (all digits are smallest digit)\n  // For example, in decimal: 999 + 1 = 1000 (all zeros with a 1 at the start)\n  // But in our system, we encode the length separately\n  return `${newLenChar}${smallestDigit.repeat(Math.abs(newLenSigned))}`;\n}\n\n/**\n * Decrements the integer part of a fractional index.\n * This function handles borrowing and length changes when decrementing the integer.\n *\n * @param index - The fractional index string whose integer part should be decremented\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @param lenBaseForward - Map of length values to their encoding characters\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @returns\n *   - A new string with the decremented integer part\n *   - null if the integer cannot be decremented (reached minimum value)\n *   - undefined if the input is invalid\n */\nexport function decrementInteger(\n  index: string,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n  lenBaseForward: ReadonlyMap<number, string>,\n  lenBaseReverse: ReadonlyMap<string, number>,\n): string | null | undefined {\n  const intLengthSigned = getIntegerLengthSigned(index, lenBaseReverse);\n  if (!intLengthSigned) {\n    return;\n  }\n\n  const largestDigit = digBaseForward[digBaseForward.length - 1];\n\n  // Extract the length character and the actual digits from the integer part\n  const [lenChar, ...digits] = index.slice(0, Math.abs(intLengthSigned) + 1);\n\n  // Try to decrement the rightmost digit first, with borrowing if needed\n  // This is similar to subtracting 1 from a number in the custom base system\n  for (let i = digits.length - 1; i >= 0; i--) {\n    const value = digBaseReverse.get(digits[i]);\n    if (value == null) {\n      // Invalid digit\n      return;\n    }\n\n    if (value > 0) {\n      // No borrowing needed - we can decrement this digit and return\n      // This is the common case for most decrements\n      digits[i] = digBaseForward[value - 1];\n      return `${lenChar}${digits.join(\"\")}`;\n    }\n\n    // This digit is at min value (0 in decimal), set to largest (9) and continue borrowing\n    // We need to borrow from the next digit to the left\n    digits[i] = largestDigit;\n  }\n\n  // Special case: transitioning from zero to negative integers\n  // This is like going from 0 to -1 in decimal, which requires special handling\n  if (intLengthSigned === 1) {\n    // The integer is 0. We need to return -1.\n    // This requires changing the length encoding character to represent negative length\n    return `${lenBaseForward.get(-1)!}${largestDigit}`;\n  }\n\n  // If we get here, we've borrowed through all digits (like 1000 - 1 = 999)\n  // We need to decrease the length of the integer representation\n  const newLenSigned = intLengthSigned - 1;\n  const newLenChar = lenBaseForward.get(newLenSigned);\n  if (!newLenChar) {\n    // Reached the limit of representable integers\n    // This is an edge case where we can't represent a smaller integer\n    return null;\n  }\n\n  // Create a new integer with decreased length (all digits are largest digit)\n  // For example, in decimal: 1000 - 1 = 999 (all nines)\n  // But in our system, we encode the length separately\n  return `${newLenChar}${largestDigit.repeat(Math.abs(newLenSigned))}`;\n}\n\n/**\n * Calculates the midpoint between two fractional parts.\n * This function recursively finds a string that sorts between two fractional parts.\n * It handles various cases including when one of the inputs is null.\n *\n * @param a - The lower bound fractional part, or empty string if there is no lower bound\n * @param b - The upper bound fractional part, or null if there is no upper bound\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @returns A string that sorts between a and b, or undefined if inputs are invalid\n */\nexport function getMidpointFractional(\n  a: string,\n  b: string | null,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n): string | undefined {\n  if (b != null && b <= a) {\n    // Precondition failed.\n    return;\n  }\n\n  // Optimization: If a and b share a common prefix, preserve it\n  if (b) {\n    // Pad a with zeros to match b's length for comparison\n    const aPadded = a.padEnd(b.length, digBaseForward[0]);\n\n    // Find the first position where a and b differ\n    const prefixLength = Array.prototype.findIndex.call(\n      b,\n      (char, i) => char !== aPadded[i],\n    );\n\n    // If they share a prefix, keep it and recursively find midpoint of the differing parts\n    if (prefixLength > 0) {\n      return `${b.slice(0, prefixLength)}${getMidpointFractional(\n        a.slice(prefixLength),\n        b.slice(prefixLength),\n        digBaseForward,\n        digBaseReverse,\n      )}`;\n    }\n  }\n\n  // At this point, we're handling the first differing digits\n  const aDigit = a ? digBaseReverse.get(a[0]) : 0;\n  const bDigit = b ? digBaseReverse.get(b[0]) : digBaseForward.length;\n  if (aDigit == null || bDigit == null) {\n    // Invalid digit.\n    return;\n  }\n\n  // Case 1: Non-consecutive digits - we can simply use their average\n  if (aDigit + 1 !== bDigit) {\n    const mid = (aDigit + bDigit) >> 1; // Fast integer division by 2\n    return digBaseForward[mid];\n  }\n\n  // Case 2: Consecutive digits with b having two or more digits\n  if (b && b.length > 1) {\n    // We can just use b's first digit (which is one more than a's first digit)\n    return b[0];\n  }\n\n  // Case 3: Consecutive digits with b having length 1 or null\n  // This is the most complex case requiring recursive construction\n  // Example: midpoint('49', '5') becomes '495'\n  // We take a's first digit, then recursively find midpoint of a's remainder and null\n  return `${digBaseForward[aDigit]}${getMidpointFractional(\n    a.slice(1),\n    null,\n    digBaseForward,\n    digBaseReverse,\n  )}`;\n}\n","/**\n * Error codes for the Fraci library.\n *\n * These codes help identify specific error conditions that may occur during library operations.\n *\n * - `INITIALIZATION_FAILED`: Indicates that the library failed to initialize.\n *   Currently seen when the base string does not meet the requirements, or when the specified model or field does not exist in the generated Prisma client.\n * - `INTERNAL_ERROR`: Indicates an internal error in the library. Please file an issue if you see this.\n * - `INVALID_FRACTIONAL_INDEX`: Indicates that an invalid fractional index was provided to `generateKeyBetween` or `generateNKeysBetween` functions.\n * - `MAX_LENGTH_EXCEEDED`: Indicates that the maximum length of the generated key was exceeded.\n * - `MAX_RETRIES_EXCEEDED`: Indicates that the maximum number of retries was exceeded when generating a key.\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nexport type FraciErrorCode =\n  | \"INITIALIZATION_FAILED\"\n  | \"INTERNAL_ERROR\"\n  | \"INVALID_FRACTIONAL_INDEX\"\n  | \"MAX_LENGTH_EXCEEDED\"\n  | \"MAX_RETRIES_EXCEEDED\";\n\n/**\n * Custom error class for the Fraci library.\n *\n * This class encapsulates errors that occur during fractional indexing operations,\n * providing structured error information through error codes and descriptive messages.\n * Use the utility functions {@link isFraciError} and {@link getFraciErrorCode} to safely work with these errors.\n *\n * @see {@link FraciErrorCode} - The error codes for the Fraci library\n * @see {@link isFraciError} - Type guard to check if an error is a FraciError\n * @see {@link getFraciErrorCode} - Function to extract the error code from a FraciError\n */\nexport class FraciError extends Error {\n  readonly name: \"FraciError\";\n\n  constructor(\n    /**\n     * The specific error code identifying the type of error.\n     */\n    readonly code: FraciErrorCode,\n    /**\n     * A descriptive message providing details about the error condition.\n     */\n    readonly message: string,\n  ) {\n    super(`[${code}] ${message}`);\n\n    this.name = \"FraciError\";\n  }\n}\n\n/**\n * Type guard that checks if the given error is an instance of {@link FraciError}.\n *\n * This is useful in error handling blocks to determine if an error originated from the Fraci library.\n *\n * @param error - The error to check\n * @returns `true` if the error is a {@link FraciError}, `false` otherwise\n *\n * @example\n * ```typescript\n * try {\n *   // Some Fraci operation\n * } catch (error) {\n *   if (isFraciError(error)) {\n *     // Handle Fraci-specific error\n *   } else {\n *     // Handle other types of errors\n *   }\n * }\n * ```\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n * @see {@link getFraciErrorCode} - Function to extract the error code from a {@link FraciError}\n */\nexport function isFraciError(error: unknown): error is FraciError {\n  return error instanceof FraciError;\n}\n\n/**\n * Extracts the error code from a {@link FraciError}.\n *\n * This function safely extracts the error code without requiring type checking first.\n * If the error is not a {@link FraciError}, it returns `undefined`.\n *\n * @param error - The error to extract the code from\n * @returns The {@link FraciErrorCode} if the error is a {@link FraciError}, `undefined` otherwise\n *\n * @example\n * ```typescript\n * try {\n *   // Some Fraci operation\n * } catch (error) {\n *   switch (getFraciErrorCode(error)) {\n *     case \"MAX_LENGTH_EXCEEDED\":\n *     case \"MAX_RETRIES_EXCEEDED\":\n *       // Handle specific error case\n *       break;\n *\n *     default:\n *       // Handle other cases, including unknown errors\n *       // or Fraci errors that are not handled above\n *       break;\n *   }\n * }\n * ```\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n * @see {@link FraciErrorCode} - The error codes for the Fraci library\n * @see {@link isFraciError} - Type guard to check if an error is a {@link FraciError}\n */\nexport function getFraciErrorCode(error: unknown): FraciErrorCode | undefined {\n  return error instanceof FraciError ? error.code : undefined;\n}\n","import {\n  INTEGER_ZERO,\n  compare,\n  concat,\n  decrementInteger,\n  getMidpointFractional,\n  incrementInteger,\n  isSmallestInteger,\n  splitParts,\n} from \"./decimal-binary.js\";\nimport { FraciError } from \"./errors.js\";\n\n/**\n * Converts a Node.js Buffer to a Uint8Array if necessary.\n * Our library is not compatible with Node.js Buffers due to [the difference of the `slice` method](https://nodejs.org/api/buffer.html#bufslicestart-end).\n *\n * @param value - The value to convert to a Uint8Array\n * @returns The original value as a Uint8Array, or null if the value is null\n */\nfunction forceUint8Array(value: Uint8Array | null): Uint8Array | null {\n  return value?.constructor.name === \"Buffer\"\n    ? new Uint8Array(value.buffer, value.byteOffset, value.length)\n    : value;\n}\n\n/**\n * Validates if a binary is a valid fractional index.\n * A valid fractional index must:\n * - Not be empty or equal to the smallest integer\n * - Have a valid integer part with valid digits\n * - Not have trailing zeros in the fractional part\n * - Contain only valid digits in both integer and fractional parts\n *\n * @param index - The string to validate as a fractional index\n * @returns True if the string is a valid fractional index, false otherwise\n */\nexport function isValidFractionalIndex(index: Uint8Array): boolean {\n  if (!index.length || isSmallestInteger(index)) {\n    // The smallest integer is not a valid fractional index. It must have a fractional part.\n    return false;\n  }\n\n  const parts = splitParts(index);\n  if (!parts) {\n    // Invalid integer length character or the integer part is too short.\n    return false;\n  }\n\n  const [, fractional] = parts;\n  if (fractional?.at(-1) === 0) {\n    // Trailing zeros are not allowed in the fractional part.\n    return false;\n  }\n\n  // All bytes in a Uint8Array are valid by definition (0-255),\n  // so we don't need to check each byte like in the string version\n\n  return true;\n}\n\n/**\n * Ensures a value is not undefined, throwing an error if it is.\n * This is a utility function used to handle unexpected undefined values\n * that should have been validated earlier in the code.\n *\n * @param value - The value to check\n * @returns The original value if it's not undefined\n * @throws {FraciError} Throws a {@link FraciError} when the value is undefined (internal error)\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nfunction ensureNotUndefined<T>(value: T | undefined): T {\n  if (value === undefined) {\n    // This should not happen as we should have validated the value before.\n    if (globalThis.__DEV__) {\n      console.error(\n        \"FraciError: [INTERNAL_ERROR] Unexpected undefined. Please file an issue to report this error.\",\n      );\n    }\n\n    throw new FraciError(\"INTERNAL_ERROR\", \"Unexpected undefined\");\n  }\n  return value;\n}\n\n/**\n * Generates a key between two existing keys without validation.\n * This internal function handles the core algorithm for creating a fractional index\n * between two existing indices. It assumes inputs are valid and doesn't perform validation.\n *\n * The function handles several cases:\n * - When both a and b are null (first key)\n * - When only a is null (key before b)\n * - When only b is null (key after a)\n * - When both a and b are provided (key between a and b)\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @returns A new key that sorts between a and b\n */\nfunction generateKeyBetweenUnsafe(\n  a: Uint8Array | null,\n  b: Uint8Array | null,\n): Uint8Array {\n  // Strategy: Handle different cases based on bounds\n  if (!a) {\n    if (!b) {\n      // Case: First key (no bounds)\n      return INTEGER_ZERO.slice();\n    }\n\n    // Case: Key before first key\n    const [bInt, bFrac] = ensureNotUndefined(splitParts(b));\n    if (isSmallestInteger(bInt)) {\n      // Edge case: b is already at the smallest possible integer\n      // We can't decrement the integer part further, so we need to use a fractional part\n      // that sorts before b's fractional part\n      return concat(\n        bInt,\n        ensureNotUndefined(getMidpointFractional(new Uint8Array(), bFrac)),\n      );\n    }\n\n    if (bFrac.length) {\n      // Optimization: If b has a fractional part, we can use just its integer part\n      // This creates a shorter key that still sorts correctly before b\n      return bInt.slice();\n    }\n\n    // Standard case: Decrement the integer part of b\n    const decremented = ensureNotUndefined(\n      decrementInteger(bInt),\n    ) as Uint8Array;\n    if (!isSmallestInteger(decremented)) {\n      return decremented;\n    }\n\n    // Edge case: If we hit the smallest integer, add the largest digit as fractional part\n    // This ensures we still have a valid key that sorts before b\n    const result = new Uint8Array(decremented.length + 1);\n    result.set(decremented);\n    result[decremented.length] = 255;\n    return result;\n  }\n\n  if (!b) {\n    // Case: Key after last key\n    const aParts = ensureNotUndefined(splitParts(a));\n    const [aInt, aFrac] = aParts;\n\n    // Try to increment the integer part first (most efficient)\n    const incremented = ensureNotUndefined(incrementInteger(aInt));\n    if (incremented) {\n      // If we can increment the integer part, use that result\n      // This creates a shorter key than using fractional parts\n      return incremented;\n    }\n\n    // Edge case: We've reached the largest possible integer representation\n    // We need to use the fractional part method instead\n    // Calculate a fractional part that sorts after a's fractional part\n    return concat(aInt, ensureNotUndefined(getMidpointFractional(aFrac, null)));\n  }\n\n  // Case: Key between two existing keys\n  const [aInt, aFrac] = ensureNotUndefined(splitParts(a));\n  const [bInt, bFrac] = ensureNotUndefined(splitParts(b));\n\n  // If both keys have the same integer part, we need to find a fractional part between them\n  if (!compare(aInt, bInt)) {\n    // Calculate the midpoint between the two fractional parts\n    return concat(\n      aInt,\n      ensureNotUndefined(getMidpointFractional(aFrac, bFrac)),\n    );\n  }\n\n  // Try to increment a's integer part\n  const cInt = ensureNotUndefined(incrementInteger(aInt));\n\n  // Two possible outcomes:\n  return cInt && compare(cInt, bInt)\n    ? // 1. If incrementing a's integer doesn't reach b's integer,\n      // we can use the incremented value (shorter key)\n      cInt\n    : // 2. If incrementing a's integer equals b's integer or we can't increment,\n      // we need to use a's integer with a fractional part that sorts after a's fractional part\n      concat(aInt, ensureNotUndefined(getMidpointFractional(aFrac, null)));\n}\n\n/**\n * Generates a key between two existing keys with validation.\n * This function validates the input keys before generating a new key between them.\n * It returns undefined if either key is invalid or if b is less than or equal to a.\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @returns A new key that sorts between a and b, or undefined if inputs are invalid\n */\nexport function generateKeyBetween(\n  a: Uint8Array | null,\n  b: Uint8Array | null,\n): Uint8Array | undefined {\n  return (a != null && !isValidFractionalIndex(a)) ||\n    (b != null && !isValidFractionalIndex(b)) ||\n    (a != null && b != null && compare(a, b) >= 0)\n    ? undefined\n    : generateKeyBetweenUnsafe(forceUint8Array(a), forceUint8Array(b));\n}\n\n/**\n * Generates multiple keys between two existing keys without validation.\n * This internal function creates n evenly distributed keys between a and b.\n * It uses a recursive divide-and-conquer approach for more even distribution.\n *\n * The function handles several cases:\n * - When n < 1 (returns empty array)\n * - When n = 1 (returns a single key between a and b)\n * - When b is null (generates n keys after a)\n * - When a is null (generates n keys before b)\n * - When both a and b are provided (generates n keys between a and b)\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @param n - Number of keys to generate\n * @returns An array of n new keys that sort between a and b\n */\nfunction generateNKeysBetweenUnsafe(\n  a: Uint8Array | null,\n  b: Uint8Array | null,\n  n: number,\n): Uint8Array[] {\n  if (n < 1) {\n    return [];\n  }\n\n  if (n === 1) {\n    return [generateKeyBetweenUnsafe(a, b)];\n  }\n\n  // Special case: Generate n keys after a (no upper bound)\n  if (b == null) {\n    let c = a;\n    // Sequential generation - each new key is after the previous one\n    return Array.from(\n      { length: n },\n      () => (c = generateKeyBetweenUnsafe(c, b)),\n    );\n  }\n\n  // Special case: Generate n keys before b (no lower bound)\n  if (a == null) {\n    let c = b;\n    // Sequential generation in reverse - each new key is before the previous one\n    // Then reverse the array to get ascending order\n    return Array.from(\n      { length: n },\n      () => (c = generateKeyBetweenUnsafe(a, c)),\n    ).reverse();\n  }\n\n  // Divide-and-conquer approach for better distribution of keys\n  const mid = n >> 1; // Fast integer division by 2\n\n  // Find a midpoint key between a and b\n  const c = generateKeyBetweenUnsafe(a, b);\n\n  // Recursively generate keys in both halves and combine them\n  // This creates a more balanced distribution than sequential generation\n  return [\n    ...generateNKeysBetweenUnsafe(a, c, mid),\n    c,\n    ...generateNKeysBetweenUnsafe(c, b, n - mid - 1),\n  ];\n}\n\n/**\n * Generates multiple keys between two existing keys with validation.\n * This function validates the input keys before generating new keys between them.\n * It returns undefined if either key is invalid or if b is less than or equal to a.\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @param n - Number of keys to generate\n * @returns An array of n new keys that sort between a and b, or undefined if inputs are invalid\n */\nexport function generateNKeysBetween(\n  a: Uint8Array | null,\n  b: Uint8Array | null,\n  n: number,\n): Uint8Array[] | undefined {\n  return (a != null && !isValidFractionalIndex(a)) ||\n    (b != null && !isValidFractionalIndex(b)) ||\n    (a != null && b != null && compare(a, b) >= 0)\n    ? undefined\n    : generateNKeysBetweenUnsafe(forceUint8Array(a), forceUint8Array(b), n);\n}\n\n/**\n * Generates a suffix to avoid conflicts between fractional indices.\n * This function creates a unique suffix based on the count value,\n * converting it to the specified digit base. The suffix is used to\n * ensure uniqueness when multiple indices need to be generated between\n * the same bounds.\n *\n * @param count - The count value to convert to a suffix\n * @returns A binary suffix in the specified digit base\n */\nexport function avoidConflictSuffix(count: number): Uint8Array {\n  const additionalFrac: number[] = [];\n\n  // Convert a number to a binary representation\n  // This works like converting to a different number base,\n  // but we write the digits in reverse order.\n  //\n  // For example, in binary:\n  // - The number 3 would become [3]\n  // - The number 256 would become [0, 1]\n  // - The number 1234 would become bytes representing 1234 in little-endian\n  //\n  // We do this reversed ordering to ensure the array doesn't end with zeros,\n  // which we need to avoid in fractional indices.\n  while (count > 0) {\n    // Add the byte for the current remainder\n    additionalFrac.push(count & 255);\n    // Integer division to get the next byte\n    count >>= 8;\n  }\n\n  // The result is a unique suffix for each count value\n  return new Uint8Array(additionalFrac);\n}\n","import {\n  decrementInteger,\n  getIntegerZero,\n  getMidpointFractional,\n  incrementInteger,\n  splitParts,\n} from \"./decimal-string.js\";\nimport { FraciError } from \"./errors.js\";\n\n/**\n * Validates if a string is a valid fractional index.\n * A valid fractional index must:\n * - Not be empty or equal to the smallest integer\n * - Have a valid integer part with valid digits\n * - Not have trailing zeros in the fractional part\n * - Contain only valid digits in both integer and fractional parts\n *\n * @param index - The string to validate as a fractional index\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @param smallestInteger - The smallest possible integer representation\n * @returns True if the string is a valid fractional index, false otherwise\n */\nexport function isValidFractionalIndex(\n  index: string,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n  lenBaseReverse: ReadonlyMap<string, number>,\n  smallestInteger: string,\n): boolean {\n  if (!index || index === smallestInteger) {\n    // The smallest integer is not a valid fractional index. It must have a fractional part.\n    return false;\n  }\n\n  const parts = splitParts(index, lenBaseReverse);\n  if (!parts) {\n    // Invalid integer length character or the integer part is too short.\n    return false;\n  }\n\n  const [integer, fractional] = parts;\n  if (fractional.endsWith(digBaseForward[0])) {\n    // Trailing zeros are not allowed in the fractional part.\n    return false;\n  }\n\n  for (const char of integer.slice(1)) {\n    if (!digBaseReverse.has(char)) {\n      return false;\n    }\n  }\n\n  for (const char of fractional) {\n    if (!digBaseReverse.has(char)) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n/**\n * Ensures a value is not undefined, throwing an error if it is.\n * This is a utility function used to handle unexpected undefined values\n * that should have been validated earlier in the code.\n *\n * @param value - The value to check\n * @returns The original value if it's not undefined\n * @throws {FraciError} Throws a {@link FraciError} when the value is undefined (internal error)\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nfunction ensureNotUndefined<T>(value: T | undefined): T {\n  if (value === undefined) {\n    // This should not happen as we should have validated the value before.\n    if (globalThis.__DEV__) {\n      console.error(\n        \"FraciError: [INTERNAL_ERROR] Unexpected undefined. Please file an issue to report this error.\",\n      );\n    }\n\n    throw new FraciError(\"INTERNAL_ERROR\", \"Unexpected undefined\");\n  }\n  return value;\n}\n\n/**\n * Generates a key between two existing keys without validation.\n * This internal function handles the core algorithm for creating a fractional index\n * between two existing indices. It assumes inputs are valid and doesn't perform validation.\n *\n * The function handles several cases:\n * - When both a and b are null (first key)\n * - When only a is null (key before b)\n * - When only b is null (key after a)\n * - When both a and b are provided (key between a and b)\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @param lenBaseForward - Map of length values to their encoding characters\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @param smallestInteger - The smallest possible integer representation\n * @returns A new key that sorts between a and b\n */\nfunction generateKeyBetweenUnsafe(\n  a: string | null,\n  b: string | null,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n  lenBaseForward: ReadonlyMap<number, string>,\n  lenBaseReverse: ReadonlyMap<string, number>,\n  smallestInteger: string,\n): string {\n  // Strategy: Handle different cases based on bounds\n  if (!a) {\n    if (!b) {\n      // Case: First key (no bounds)\n      return getIntegerZero(digBaseForward, lenBaseForward);\n    }\n\n    // Case: Key before first key\n    const [bInt, bFrac] = ensureNotUndefined(splitParts(b, lenBaseReverse));\n    if (bInt === smallestInteger) {\n      // Edge case: b is already at the smallest possible integer\n      // We can't decrement the integer part further, so we need to use a fractional part\n      // that sorts before b's fractional part\n      return `${bInt}${ensureNotUndefined(\n        getMidpointFractional(\"\", bFrac, digBaseForward, digBaseReverse),\n      )}`;\n    }\n\n    if (bFrac) {\n      // Optimization: If b has a fractional part, we can use just its integer part\n      // This creates a shorter key that still sorts correctly before b\n      return bInt;\n    }\n\n    // Standard case: Decrement the integer part of b\n    const decremented = ensureNotUndefined(\n      decrementInteger(\n        bInt,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseForward,\n        lenBaseReverse,\n      ),\n    ) as string;\n\n    // Edge case: If we hit the smallest integer, add the largest digit as fractional part\n    // This ensures we still have a valid key that sorts before b\n    return decremented === smallestInteger\n      ? `${decremented}${digBaseForward[digBaseForward.length - 1]}`\n      : decremented;\n  }\n\n  if (!b) {\n    // Case: Key after last key\n    const aParts = ensureNotUndefined(splitParts(a, lenBaseReverse));\n    const [aInt, aFrac] = aParts;\n\n    // Try to increment the integer part first (most efficient)\n    const incremented = ensureNotUndefined(\n      incrementInteger(\n        aInt,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseForward,\n        lenBaseReverse,\n      ),\n    );\n\n    if (incremented !== null) {\n      // If we can increment the integer part, use that result\n      // This creates a shorter key than using fractional parts\n      return incremented;\n    }\n\n    // Edge case: We've reached the largest possible integer representation\n    // We need to use the fractional part method instead\n    // Calculate a fractional part that sorts after a's fractional part\n    return `${aInt}${ensureNotUndefined(\n      getMidpointFractional(aFrac, null, digBaseForward, digBaseReverse),\n    )}`;\n  }\n\n  // Case: Key between two existing keys\n  const aParts = ensureNotUndefined(splitParts(a, lenBaseReverse));\n  const bParts = ensureNotUndefined(splitParts(b, lenBaseReverse));\n  const [aInt, aFrac] = aParts;\n  const [bInt, bFrac] = bParts;\n\n  // If both keys have the same integer part, we need to find a fractional part between them\n  if (aInt === bInt) {\n    // Calculate the midpoint between the two fractional parts\n    return `${aInt}${ensureNotUndefined(\n      getMidpointFractional(aFrac, bFrac, digBaseForward, digBaseReverse),\n    )}`;\n  }\n\n  // Try to increment a's integer part\n  const cInt = ensureNotUndefined(\n    incrementInteger(\n      aInt,\n      digBaseForward,\n      digBaseReverse,\n      lenBaseForward,\n      lenBaseReverse,\n    ),\n  );\n\n  // Two possible outcomes:\n  return cInt !== null && cInt !== bInt\n    ? // 1. If incrementing a's integer doesn't reach b's integer,\n      // we can use the incremented value (shorter key)\n      cInt\n    : // 2. If incrementing a's integer equals b's integer or we can't increment,\n      // we need to use a's integer with a fractional part that sorts after a's fractional part\n      `${aInt}${ensureNotUndefined(\n        getMidpointFractional(aFrac, null, digBaseForward, digBaseReverse),\n      )}`;\n}\n\n/**\n * Generates a key between two existing keys with validation.\n * This function validates the input keys before generating a new key between them.\n * It returns undefined if either key is invalid or if b is less than or equal to a.\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @param lenBaseForward - Map of length values to their encoding characters\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @param smallestInteger - The smallest possible integer representation\n * @returns A new key that sorts between a and b, or undefined if inputs are invalid\n */\nexport function generateKeyBetween(\n  a: string | null,\n  b: string | null,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n  lenBaseForward: ReadonlyMap<number, string>,\n  lenBaseReverse: ReadonlyMap<string, number>,\n  smallestInteger: string,\n): string | undefined {\n  return (a != null &&\n    !isValidFractionalIndex(\n      a,\n      digBaseForward,\n      digBaseReverse,\n      lenBaseReverse,\n      smallestInteger,\n    )) ||\n    (b != null &&\n      !isValidFractionalIndex(\n        b,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseReverse,\n        smallestInteger,\n      )) ||\n    (a != null && b != null && b <= a)\n    ? undefined\n    : generateKeyBetweenUnsafe(\n        a,\n        b,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseForward,\n        lenBaseReverse,\n        smallestInteger,\n      );\n}\n\n/**\n * Generates multiple keys between two existing keys without validation.\n * This internal function creates n evenly distributed keys between a and b.\n * It uses a recursive divide-and-conquer approach for more even distribution.\n *\n * The function handles several cases:\n * - When n < 1 (returns empty array)\n * - When n = 1 (returns a single key between a and b)\n * - When b is null (generates n keys after a)\n * - When a is null (generates n keys before b)\n * - When both a and b are provided (generates n keys between a and b)\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @param n - Number of keys to generate\n * @param args - Array containing the base maps and smallest integer value\n * @returns An array of n new keys that sort between a and b\n */\nfunction generateNKeysBetweenUnsafe(\n  a: string | null,\n  b: string | null,\n  n: number,\n  ...args: [\n    readonly string[],\n    ReadonlyMap<string, number>,\n    ReadonlyMap<number, string>,\n    ReadonlyMap<string, number>,\n    string,\n  ]\n): string[] {\n  if (n < 1) {\n    return [];\n  }\n\n  if (n === 1) {\n    return [generateKeyBetweenUnsafe(a, b, ...args)];\n  }\n\n  // Special case: Generate n keys after a (no upper bound)\n  if (b == null) {\n    let c = a;\n    // Sequential generation - each new key is after the previous one\n    return Array.from(\n      { length: n },\n      () => (c = generateKeyBetweenUnsafe(c, b, ...args)),\n    );\n  }\n\n  // Special case: Generate n keys before b (no lower bound)\n  if (a == null) {\n    let c = b;\n    // Sequential generation in reverse - each new key is before the previous one\n    // Then reverse the array to get ascending order\n    return Array.from(\n      { length: n },\n      () => (c = generateKeyBetweenUnsafe(a, c, ...args)),\n    ).reverse();\n  }\n\n  // Divide-and-conquer approach for better distribution of keys\n  const mid = n >> 1; // Fast integer division by 2\n\n  // Find a midpoint key between a and b\n  const c = generateKeyBetweenUnsafe(a, b, ...args);\n\n  // Recursively generate keys in both halves and combine them\n  // This creates a more balanced distribution than sequential generation\n  return [\n    ...generateNKeysBetweenUnsafe(a, c, mid, ...args),\n    c,\n    ...generateNKeysBetweenUnsafe(c, b, n - mid - 1, ...args),\n  ];\n}\n\n/**\n * Generates multiple keys between two existing keys with validation.\n * This function validates the input keys before generating new keys between them.\n * It returns undefined if either key is invalid or if b is less than or equal to a.\n *\n * @param a - The lower bound key, or null if there is no lower bound\n * @param b - The upper bound key, or null if there is no upper bound\n * @param n - Number of keys to generate\n * @param digBaseForward - Array mapping digit positions to characters\n * @param digBaseReverse - Map of digit characters to their numeric values\n * @param lenBaseForward - Map of length values to their encoding characters\n * @param lenBaseReverse - Map of length encoding characters to their numeric values\n * @param smallestInteger - The smallest possible integer representation\n * @returns An array of n new keys that sort between a and b, or undefined if inputs are invalid\n */\nexport function generateNKeysBetween(\n  a: string | null,\n  b: string | null,\n  n: number,\n  digBaseForward: readonly string[],\n  digBaseReverse: ReadonlyMap<string, number>,\n  lenBaseForward: ReadonlyMap<number, string>,\n  lenBaseReverse: ReadonlyMap<string, number>,\n  smallestInteger: string,\n): string[] | undefined {\n  return (a != null &&\n    !isValidFractionalIndex(\n      a,\n      digBaseForward,\n      digBaseReverse,\n      lenBaseReverse,\n      smallestInteger,\n    )) ||\n    (b != null &&\n      !isValidFractionalIndex(\n        b,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseReverse,\n        smallestInteger,\n      )) ||\n    (a != null && b != null && b <= a)\n    ? undefined\n    : generateNKeysBetweenUnsafe(\n        a,\n        b,\n        n,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseForward,\n        lenBaseReverse,\n        smallestInteger,\n      );\n}\n\n/**\n * Generates a suffix to avoid conflicts between fractional indices.\n * This function creates a unique suffix based on the count value,\n * converting it to the specified digit base. The suffix is used to\n * ensure uniqueness when multiple indices need to be generated between\n * the same bounds.\n *\n * @param count - The count value to convert to a suffix\n * @param digBaseForward - Array mapping digit positions to characters\n * @returns A string suffix in the specified digit base\n */\nexport function avoidConflictSuffix(\n  count: number,\n  digBaseForward: readonly string[],\n): string {\n  // Use the digit base length as the radix for conversion\n  const radix = digBaseForward.length;\n  let additionalFrac = \"\";\n\n  // Convert a number to a string representation using our custom digit base\n  // This works like converting to a different number base (like base-10 or base-16),\n  // but we write the digits in reverse order.\n  //\n  // For example, with digit base \"0123456789\":\n  // - The number 3 would become \"3\"\n  // - The number 10 would become \"01\"\n  // - The number 1234 would become \"4321\"\n  //\n  // We do this reversed ordering to ensure the string doesn't end with zeros,\n  // which we need to avoid in fractional indices.\n  while (count > 0) {\n    // Add the digit for the current remainder\n    additionalFrac += digBaseForward[count % radix];\n    // Integer division to get the next digit\n    count = Math.floor(count / radix);\n  }\n\n  // The result is a unique suffix for each count value\n  return additionalFrac;\n}\n","import { FraciError, type FraciErrorCode } from \"./errors.js\";\n\nconst ERROR_CODE_INITIALIZATION_FAILED =\n  \"INITIALIZATION_FAILED\" satisfies FraciErrorCode;\n\n/**\n * Splits a base string into an array of characters and validates it.\n * This function ensures the base string meets the requirements:\n * - Has at least 4 unique characters\n * - Characters are in ascending order (by character code)\n *\n * @param base - The base string to split and validate\n * @returns An array of characters from the base string\n * @throws {FraciError} Throws a {@link FraciError} when the base string has fewer than 4 unique characters\n * @throws {FraciError} Throws a {@link FraciError} when the base string characters are not unique or not in ascending order\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nfunction splitBase(base: string): string[] {\n  // Intentionally not using a spread operator to ensure consistent splitting behavior.\n  // That means we don't support strings with surrogate pairs.\n  const forward = base.split(\"\");\n\n  if (forward.length < 4) {\n    // Minimum length requirement ensures the system has enough distinct characters:\n    // - We need at least 2 characters to represent +1 and -1 in integer length bases.\n    // - We need at least 3 characters to calculate the middle of fractional parts.\n    // - An extra character provides additional flexibility.\n    throw new FraciError(\n      ERROR_CODE_INITIALIZATION_FAILED,\n      \"Base string must have at least 4 unique characters\",\n    );\n  }\n\n  // Validate that characters are in strictly ascending order\n  // This is essential for correct sorting behavior in the fractional indexing system\n  let lastCode = -1;\n  for (const char of forward) {\n    const code = char.charCodeAt(0);\n    if (code <= lastCode) {\n      throw new FraciError(\n        ERROR_CODE_INITIALIZATION_FAILED,\n        \"Base string characters must be unique and in ascending order\",\n      );\n    }\n    lastCode = code;\n  }\n\n  return forward;\n}\n\n/**\n * Creates forward and reverse mappings for a digit base.\n * This function converts a base string into a pair of data structures:\n * 1. An array mapping positions to characters\n * 2. A map from characters to their positions\n *\n * @param base - The base string containing unique characters in ascending order\n * @returns A tuple containing the forward array and reverse map\n * @throws {FraciError} Throws a {@link FraciError} when the base string has fewer than 4 unique characters (via {@link splitBase})\n * @throws {FraciError} Throws a {@link FraciError} when the base string characters are not unique or not in ascending order (via {@link splitBase})\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nexport function createDigitBaseMap(\n  base: string,\n): [forward: readonly string[], reverse: ReadonlyMap<string, number>] {\n  // We always convert characters to an array first to ensure consistent splitting behavior.\n  const forward = splitBase(base);\n\n  return [forward, new Map(forward.map((char, index) => [char, index]))];\n}\n\n/**\n * Creates forward and reverse mappings for integer length encoding.\n * This function converts a base string into a pair of maps:\n * 1. A map from integer lengths to their encoding characters\n * 2. A map from encoding characters to their integer lengths\n *\n * The characters are distributed to represent both positive and negative lengths,\n * with the first half of characters representing negative lengths and the second\n * half representing positive lengths (skipping 0).\n *\n * @param base - The base string containing unique characters in ascending order\n * @returns A tuple containing the forward map (length → char) and reverse map (char → length)\n * @throws {FraciError} Throws a {@link FraciError} when the base string has fewer than 4 unique characters (via {@link splitBase})\n * @throws {FraciError} Throws a {@link FraciError} when the base string characters are not unique or not in ascending order (via {@link splitBase})\n *\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nexport function createIntegerLengthBaseMap(\n  base: string,\n): [\n  forward: ReadonlyMap<number, string>,\n  reverse: ReadonlyMap<string, number>,\n] {\n  // We always convert characters to an array first to ensure consistent splitting behavior.\n  const forward = splitBase(base);\n\n  // Divide the character set in half to represent negative and positive lengths\n  // This is a key design decision that allows representing both positive and negative integers\n  const positiveBegin = forward.length >> 1; // Fast integer division by 2\n\n  // Map each character to a signed integer length value\n  // The first half of characters map to negative lengths, the second half to positive\n  // Important: We deliberately skip 0 as a length value to simplify the algorithm\n  const forwardEntries = forward.map(\n    (char, index) =>\n      [\n        index < positiveBegin\n          ? // For characters in the first half, assign negative values starting from -1\n            index - positiveBegin // This maps to -1, -2, -3, etc.\n          : // For characters in the second half, assign positive values starting from 1\n            index - positiveBegin + 1, // This maps to 1, 2, 3, etc. (skipping 0)\n        char,\n      ] as const,\n  );\n\n  // Create both forward (length → char) and reverse (char → length) maps\n  // This allows efficient lookups in both directions\n  return [\n    new Map(forwardEntries),\n    new Map(forwardEntries.map(([value, char]) => [char, value])),\n  ];\n}\n","import type {\n  BASE10,\n  BASE16L,\n  BASE16U,\n  BASE26L,\n  BASE26U,\n  BASE36L,\n  BASE36U,\n  BASE52,\n  BASE62,\n  BASE64URL,\n  BASE88,\n  BASE95,\n} from \"./bases.js\";\nimport { concat } from \"./lib/decimal-binary.js\";\nimport { getSmallestInteger } from \"./lib/decimal-string.js\";\nimport { FraciError, type FraciErrorCode } from \"./lib/errors.js\";\nimport {\n  avoidConflictSuffix as avoidConflictSuffixBinary,\n  generateKeyBetween as generateKeyBetweenBinary,\n  generateNKeysBetween as generateNKeysBetweenBinary,\n} from \"./lib/fractional-indexing-binary.js\";\nimport {\n  avoidConflictSuffix,\n  generateKeyBetween,\n  generateNKeysBetween,\n} from \"./lib/fractional-indexing-string.js\";\nimport type {\n  AnyBinaryFractionalIndexBase,\n  AnyStringFractionalIndexBase,\n  FractionalIndex,\n  FractionalIndexBase,\n} from \"./lib/types.js\";\nimport { createDigitBaseMap, createIntegerLengthBaseMap } from \"./lib/utils.js\";\n\n/**\n * Default maximum length for fractional index keys.\n */\nexport const DEFAULT_MAX_LENGTH = 50;\n\n/**\n * Default maximum number of retry attempts when generating keys.\n */\nexport const DEFAULT_MAX_RETRIES = 5;\n\nconst ERROR_CODE_INVALID_INPUT =\n  \"INVALID_FRACTIONAL_INDEX\" satisfies FraciErrorCode;\nconst ERROR_MESSAGE_INVALID_INPUT = \"Invalid indices provided\";\n\nconst ERROR_CODE_EXCEEDED_MAX_LENGTH =\n  \"MAX_LENGTH_EXCEEDED\" satisfies FraciErrorCode;\nconst ERROR_MESSAGE_EXCEEDED_MAX_LENGTH = \"Exceeded maximum length\";\n\nconst ERROR_CODE_EXCEEDED_MAX_RETRIES =\n  \"MAX_RETRIES_EXCEEDED\" satisfies FraciErrorCode;\nconst ERROR_MESSAGE_EXCEEDED_MAX_RETRIES = \"Exceeded maximum retries\";\n\ntype IndexPairs<T> =\n  | [T | null, T | null]\n  | [T | null, T]\n  | [T | null, null]\n  | [T, T | null]\n  | [T, T]\n  | [T, null]\n  | [null, T | null]\n  | [null, T]\n  | [null, null];\n\n/**\n * Fractional indexing utility that provides methods for generating ordered keys.\n *\n * @template B - The base configuration defining the encoding strategy\n * @template X - The brand type for the fractional index\n *\n * @see {@link fraci} - The unified factory function for creating fractional indexing utilities\n * @see {@link fraciBinary} - The factory function for creating binary-based fractional indexing utilities\n * @see {@link fraciString} - The factory function for creating string-based fractional indexing utilities\n */\nexport interface Fraci<B extends FractionalIndexBase, X> {\n  /**\n   * The character sets used for representing digits in the fractional index.\n   */\n  readonly base: B;\n\n  /**\n   * The brand type for the fractional index. Does not exist at runtime.\n   *\n   * @internal\n   */\n  readonly brand?: X | undefined;\n\n  /**\n   * Generates a key between two existing keys.\n   * Returns a generator that yields new unique keys between the provided bounds.\n   *\n   * @param a - The lower bound key, or null if there is no lower bound\n   * @param b - The upper bound key, or null if there is no upper bound\n   * @param skip - Number of conflict avoidance iterations to skip (default: 0)\n   * @returns A generator yielding fractional index keys\n   * @throws {FraciError} Throws a {@link FraciError} when invalid input is provided\n   * @throws {FraciError} Throws a {@link FraciError} when the generated key exceeds the maximum length\n   *\n   * @see {@link FraciError} - The custom error class for the Fraci library\n   */\n  generateKeyBetween(\n    a: FractionalIndex<B, X> | null,\n    b: FractionalIndex<B, X> | null,\n    skip?: number,\n  ): Generator<FractionalIndex<B, X>, never, unknown>;\n\n  /**\n   * Generates a key between two existing keys.\n   * Returns a generator that yields new unique keys between the provided bounds.\n   *\n   * This is an overload to make the spread operator work with conditional tuples.\n   *\n   * @param a - The lower bound key, or null if there is no lower bound\n   * @param b - The upper bound key, or null if there is no upper bound\n   * @param skip - Number of conflict avoidance iterations to skip (default: 0)\n   * @returns A generator yielding fractional index keys\n   * @throws {FraciError} Throws a {@link FraciError} when invalid input is provided\n   * @throws {FraciError} Throws a {@link FraciError} when the generated key exceeds the maximum length\n   *\n   * @see {@link FraciError} - The custom error class for the Fraci library\n   *\n   * @ignore Documentation should be ignored for this overload but should not affect functionality and Intellisense\n   */\n  generateKeyBetween(\n    ...[a, b, skip]:\n      | [...IndexPairs<FractionalIndex<B, X>>]\n      | [...IndexPairs<FractionalIndex<B, X>>, number]\n  ): Generator<FractionalIndex<B, X>, never, unknown>;\n\n  /**\n   * Generates multiple keys evenly distributed between two existing keys.\n   * Returns a generator that yields arrays of new unique keys.\n   *\n   * @param a - The lower bound key, or null if there is no lower bound\n   * @param b - The upper bound key, or null if there is no upper bound\n   * @param n - Number of keys to generate\n   * @param skip - Number of conflict avoidance iterations to skip (default: 0)\n   * @returns A generator yielding arrays of fractional index keys\n   * @throws {FraciError} Throws a {@link FraciError} when invalid input is provided\n   * @throws {FraciError} Throws a {@link FraciError} when the generated keys would exceed the maximum length\n   *\n   * @see {@link FraciError} - The custom error class for the Fraci library\n   */\n  generateNKeysBetween(\n    a: FractionalIndex<B, X> | null,\n    b: FractionalIndex<B, X> | null,\n    n: number,\n    skip?: number,\n  ): Generator<FractionalIndex<B, X>[], never, unknown>;\n\n  /**\n   * Generates multiple keys evenly distributed between two existing keys.\n   * Returns a generator that yields arrays of new unique keys.\n   *\n   * This is an overload to make the spread operator work with conditional tuples.\n   *\n   * @param a - The lower bound key, or null if there is no lower bound\n   * @param b - The upper bound key, or null if there is no upper bound\n   * @param n - Number of keys to generate\n   * @param skip - Number of conflict avoidance iterations to skip (default: 0)\n   * @returns A generator yielding arrays of fractional index keys\n   * @throws {FraciError} Throws a {@link FraciError} when invalid input is provided\n   * @throws {FraciError} Throws a {@link FraciError} when the generated keys would exceed the maximum length\n   *\n   * @ignore Documentation should be ignored for this overload but should not affect functionality and Intellisense\n   *\n   * @see {@link FraciError} - The custom error class for the Fraci library\n   */\n  generateNKeysBetween(\n    ...[a, b, n, skip]:\n      | [...IndexPairs<FractionalIndex<B, X>>, number]\n      | [...IndexPairs<FractionalIndex<B, X>>, number, number]\n  ): Generator<FractionalIndex<B, X>[], never, unknown>;\n}\n\n/**\n * Type alias for any {@link Fraci} instance with a binary digit base.\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n * @see {@link AnyFraci} - A union type of all fractional index types\n * @see {@link AnyStringFraci} - The type of all string fractional index types\n */\nexport type AnyBinaryFraci = Fraci<AnyBinaryFractionalIndexBase, any>;\n\n/**\n * Type alias for any {@link Fraci} instance with a string digit base.\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n * @see {@link AnyFraci} - A union type of all fractional index types\n * @see {@link AnyBinaryFraci} - The type of all binary fractional index types\n */\nexport type AnyStringFraci = Fraci<AnyStringFractionalIndexBase, any>;\n\n/**\n * Type alias for any {@link Fraci} instance with any digit base, length base, and brand.\n * This is useful for cases where the specific parameters don't matter.\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n * @see {@link AnyBinaryFraci} - The type of all binary fractional index types\n * @see {@link AnyStringFraci} - The type of all string fractional index types\n */\nexport type AnyFraci = AnyBinaryFraci | AnyStringFraci;\n\n/**\n * Base options for fractional indexing.\n *\n * This type serves as the base type for the `B` template parameter in the {@link Fraci} type,\n * defining the encoding strategy used by the index.\n *\n * @see {@link FraciOptions} - The main configuration options for fractional indexing\n * @see {@link FraciOptionsBaseToBase} - The type alias for converting options to a more specific type\n */\nexport type FraciOptionsBase =\n  | {\n      /**\n       * The type discriminator identifying this as a string fractional index configuration.\n       *\n       * Must be \"string\" or `undefined` for string fractional indices.\n       */\n      readonly type?: \"string\" | undefined;\n\n      /**\n       * The character set used for encoding the length of the integer part.\n       *\n       * This determines what characters are used to represent the length of the integer\n       * portion of the fractional index. Characters must be in ascending lexicographic order.\n       *\n       * The first character of a fractional index comes from this character set.\n       *\n       * @see {@link BASE10}, {@link BASE16L}, {@link BASE16U}, {@link BASE26L}, {@link BASE26U}, {@link BASE36L}, {@link BASE36U}, {@link BASE52}, {@link BASE62}, {@link BASE64URL}, {@link BASE88}, {@link BASE95}\n       */\n      readonly lengthBase: string;\n\n      /**\n       * The character set used for representing digits in the fractional index.\n       *\n       * These characters form the ordered set used to encode the actual index values,\n       * and must be in ascending lexicographic order.\n       *\n       * The second and all subsequent characters of a fractional index come from this character set.\n       *\n       * @see {@link BASE10}, {@link BASE16L}, {@link BASE16U}, {@link BASE26L}, {@link BASE26U}, {@link BASE36L}, {@link BASE36U}, {@link BASE52}, {@link BASE62}, {@link BASE64URL}, {@link BASE88}, {@link BASE95}\n       */\n      readonly digitBase: string;\n    }\n  | {\n      /**\n       * The type discriminator identifying this as a binary fractional index configuration.\n       *\n       * Must be \"binary\" for binary fractional indices.\n       */\n      readonly type: \"binary\";\n    };\n\n/**\n * Type alias for converting the options to a more specific type.\n *\n * @template B - The base configuration defining the encoding strategy\n *\n * @see {@link FraciOptionsBase} - The base options for fractional indexing\n * @see {@link FractionalIndexBase} - The base configuration for fractional indices\n */\nexport type FraciOptionsBaseToBase<B extends FraciOptionsBase> = B extends {\n  readonly lengthBase: string;\n  readonly digitBase: string;\n}\n  ? {\n      /**\n       * The type discriminator identifying this as a string fractional index configuration.\n       */\n      readonly type: \"string\";\n\n      /**\n       * The character set used for encoding the length of the integer part.\n       *\n       * This determines what characters are used to represent the length of the integer\n       * portion of the fractional index. Characters must be in ascending lexicographic order.\n       *\n       * The first character of a fractional index comes from this character set.\n       *\n       * @see {@link BASE10}, {@link BASE16L}, {@link BASE16U}, {@link BASE26L}, {@link BASE26U}, {@link BASE36L}, {@link BASE36U}, {@link BASE52}, {@link BASE62}, {@link BASE64URL}, {@link BASE88}, {@link BASE95}\n       */\n      readonly lengthBase: B[\"lengthBase\"];\n\n      /**\n       * The character set used for representing digits in the fractional index.\n       *\n       * These characters form the ordered set used to encode the actual index values,\n       * and must be in ascending lexicographic order.\n       *\n       * The second and all subsequent characters of a fractional index come from this character set.\n       *\n       * @see {@link BASE10}, {@link BASE16L}, {@link BASE16U}, {@link BASE26L}, {@link BASE26U}, {@link BASE36L}, {@link BASE36U}, {@link BASE52}, {@link BASE62}, {@link BASE64URL}, {@link BASE88}, {@link BASE95}\n       */\n      readonly digitBase: B[\"digitBase\"];\n    }\n  : {\n      /**\n       * The type discriminator identifying this as a binary fractional index configuration.\n       */\n      readonly type: \"binary\";\n    };\n\n/**\n * Configuration options for creating fractional indexing utilities.\n *\n * @template B - The base configuration defining the encoding strategy\n *\n * @see {@link fraci} - The unified factory function for creating fractional indexing utilities\n * @see {@link FraciOptionsBase} - The base options for fractional indexing\n * @see {@link BinaryFraciOptions} - The options for binary fractional indexing\n * @see {@link StringFraciOptions} - The options for string fractional indexing\n */\nexport type FraciOptions<B extends FraciOptionsBase> = B & {\n  /**\n   * Maximum allowed length for generated keys.\n   * @default DEFAULT_MAX_LENGTH (50)\n   */\n  readonly maxLength?: number | undefined;\n\n  /**\n   * Maximum number of retry attempts when generating keys.\n   * @default DEFAULT_MAX_RETRIES (5)\n   */\n  readonly maxRetries?: number | undefined;\n};\n\n/**\n * Base configuration for creating string-based fractional indexing utilities.\n *\n * Defines the configuration for fractional indices represented using binary encoding,\n * where indices are stored as byte arrays (`Uint8Array`).\n *\n * Binary indices generally provide more compact storage and efficient comparison operations\n * compared to string-based alternatives.\n *\n * @see {@link FraciOptions} - The main configuration options for fractional indexing\n * @see {@link StringFraciOptions} - The options for string fractional indexing\n */\nexport type BinaryFraciOptions = FraciOptions<{\n  /**\n   * The type discriminator identifying this as a binary fractional index configuration.\n   */\n  readonly type: \"binary\";\n}>;\n\n/**\n * Base configuration for creating string-based fractional indexing utilities.\n *\n * Defines the configuration for fractional indices represented using string encoding,\n * where indices are stored as human-readable strings using specified character sets.\n *\n * String indices are useful when human readability or sortability in standard string\n * contexts (like databases) is required.\n *\n * @see {@link FraciOptions} - The main configuration options for fractional indexing\n * @see {@link BinaryFraciOptions} - The options for binary fractional indexing\n */\nexport type StringFraciOptions = FraciOptions<{\n  /**\n   * The type discriminator identifying this as a string fractional index configuration.\n   */\n  readonly type?: \"string\" | undefined;\n\n  /**\n   * The character set used for encoding the length of the integer part.\n   *\n   * This determines what characters are used to represent the length of the integer\n   * portion of the fractional index. Characters must be in ascending lexicographic order.\n   *\n   * The first character of a fractional index comes from this character set.\n   *\n   * @see {@link BASE10}, {@link BASE16L}, {@link BASE16U}, {@link BASE26L}, {@link BASE26U}, {@link BASE36L}, {@link BASE36U}, {@link BASE52}, {@link BASE62}, {@link BASE64URL}, {@link BASE88}, {@link BASE95}\n   */\n  readonly lengthBase: string;\n\n  /**\n   * The character set used for representing digits in the fractional index.\n   *\n   * These characters form the ordered set used to encode the actual index values,\n   * and must be in ascending lexicographic order.\n   *\n   * The second and all subsequent characters of a fractional index come from this character set.\n   *\n   * @see {@link BASE10}, {@link BASE16L}, {@link BASE16U}, {@link BASE26L}, {@link BASE26U}, {@link BASE36L}, {@link BASE36U}, {@link BASE52}, {@link BASE62}, {@link BASE64URL}, {@link BASE88}, {@link BASE95}\n   */\n  readonly digitBase: string;\n}>;\n\n/**\n * Type alias to represent options that can be branded.\n *\n * @template T - The base options type\n * @template X - The brand type\n */\ntype BrandableOptions<T, X> = T & {\n  /**\n   * The brand type for the fractional index.\n   */\n  readonly brand?: X | undefined;\n};\n\n/**\n * Cache for storing computed values to improve performance.\n * Uses a branded type pattern to prevent accidental misuse.\n *\n * @see {@link createFraciCache} - Function to create a new cache\n */\nexport type FraciCache = Map<string, unknown> & { readonly __fraci__: never };\n\n/**\n * Creates a new empty {@link FraciCache} for storing computed values in string-based fractional indexing operations.\n * Using a cache can improve initialization performance when repeatedly using the same base configurations.\n *\n * @returns A new empty FraciCache instance\n *\n * @example\n * ```typescript\n * const cache = createFraciCache();\n * const fraci1 = fraciString({ brand: \"a\", lengthBase: \"abcdefghij\", digitBase: \"0123456789\" }, cache);\n * const fraci2 = fraciString({ brand: \"b\", lengthBase: \"abcdefghij\", digitBase: \"0123456789\" }, cache);\n * // Both instances will share cached computations\n * ```\n */\nexport function createFraciCache(): FraciCache {\n  return new Map() as FraciCache;\n}\n\n/**\n * Retrieves a value from cache or computes it if not present.\n *\n * @template T - The type of the value to cache\n *\n * @param cache - The cache to use, or undefined to bypass caching\n * @param key - The cache key to look up\n * @param fn - Function to execute if the value is not in the cache\n * @returns The cached or newly computed value\n */\nfunction withCache<T>(\n  cache: FraciCache | undefined,\n  key: string,\n  fn: () => T,\n): T {\n  // If no cache is provided, just compute the value directly\n  if (!cache) {\n    return fn();\n  }\n\n  // Try to get the value from the cache\n  let value = cache.get(key) as T | undefined;\n  if (value === undefined) {\n    // Value not found in cache, compute it\n    value = fn();\n    // Store in cache for future use\n    cache.set(key, value);\n  }\n\n  return value;\n}\n\nfunction logInvalidInputError(\n  a: string | Uint8Array | null,\n  b: string | Uint8Array | null,\n  skip: number,\n): void {\n  if (globalThis.__DEV__) {\n    console.error(\n      `FraciError: [INVALID_FRACTIONAL_INDEX] ${ERROR_MESSAGE_INVALID_INPUT}. a = ${a}, b = ${b}, skip = ${skip}\nMake sure that\n- Fractional indices generated by the same fraci instance with the same configuration are being used as-is\n- Indices in different groups have not been mixed up\n- a (the first argument item) comes before b (the second argument item) in the group\nFile an issue if you use the library correctly and still encounter this error.`,\n    );\n  }\n}\n\n/**\n * Creates a binary-based fractional indexing utility with the specified configuration.\n *\n * @template X - The brand type for the fractional index\n *\n * @param options - Configuration options for the fractional indexing utility\n * @returns A binary-based fractional indexing utility instance\n *\n * @example\n * ```typescript\n * // Create a binary-based fractional indexing utility\n * const binaryFraci = fraciBinary({ brand: \"exampleIndex\" });\n *\n * // Generate a key between null and null (first key)\n * const [key1] = binaryFraci.generateKeyBetween(null, null);\n * // Generate a key between key1 and null (key after key1)\n * const [key2] = binaryFraci.generateKeyBetween(key1, null);\n * // Generate a key between key1 and key2\n * const [key3] = binaryFraci.generateKeyBetween(key1, key2);\n * ```\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n * @see {@link BinaryFraciOptions} - The options for the binary fractional indexing utility\n * @see {@link fraci} - The unified factory function for creating fractional indexing utilities\n * @see {@link fraciString} - The factory function for creating string-based fractional indexing utilities\n */\nexport function fraciBinary<const X = unknown>({\n  maxLength = DEFAULT_MAX_LENGTH,\n  maxRetries = DEFAULT_MAX_RETRIES,\n}: BrandableOptions<\n  Omit<BinaryFraciOptions, \"type\"> & { readonly type?: \"binary\" | undefined },\n  X\n> = {}): Fraci<AnyBinaryFractionalIndexBase, X> {\n  type F = FractionalIndex<AnyBinaryFractionalIndexBase, X>;\n\n  return {\n    base: { type: \"binary\" },\n    *generateKeyBetween(a: F | null, b: F | null, skip = 0) {\n      // Generate the base key between a and b (without conflict avoidance)\n      const base = generateKeyBetweenBinary(a, b);\n      if (!base) {\n        // Logic Error. Should not happen if a and b are valid (i.e. generated by this library with same lengthBase and digitBase).\n        if (globalThis.__DEV__) {\n          logInvalidInputError(a, b, skip);\n        }\n        throw new FraciError(\n          ERROR_CODE_INVALID_INPUT,\n          ERROR_MESSAGE_INVALID_INPUT,\n        );\n      }\n\n      // Generate multiple possible keys with conflict avoidance suffixes\n      // This allows the caller to try multiple keys if earlier ones conflict\n      for (let i = 0; i < maxRetries; i++) {\n        const value = concat(base, avoidConflictSuffixBinary(i + skip));\n        if (value.length > maxLength) {\n          throw new FraciError(\n            ERROR_CODE_EXCEEDED_MAX_LENGTH,\n            ERROR_MESSAGE_EXCEEDED_MAX_LENGTH,\n          );\n        }\n        yield value as F;\n      }\n\n      // If we reach here, it means we exceeded the maximum retries\n      throw new FraciError(\n        ERROR_CODE_EXCEEDED_MAX_RETRIES,\n        ERROR_MESSAGE_EXCEEDED_MAX_RETRIES,\n      );\n    },\n    *generateNKeysBetween(a: F | null, b: F | null, n: number, skip = 0) {\n      // Generate n base keys between a and b (without conflict avoidance)\n      const base = generateNKeysBetweenBinary(a, b, n);\n      if (!base) {\n        // Logic Error. Should not happen if a and b are valid (i.e. generated by this library with same lengthBase and digitBase).\n        if (globalThis.__DEV__) {\n          logInvalidInputError(a, b, skip);\n        }\n        throw new FraciError(\n          ERROR_CODE_INVALID_INPUT,\n          ERROR_MESSAGE_INVALID_INPUT,\n        );\n      }\n\n      // Find the longest key to ensure we don't exceed maxLength when adding suffixes\n      const longest = base.reduce((acc, v) => Math.max(acc, v.length), 0);\n\n      // Generate multiple sets of keys with conflict avoidance suffixes\n      // Each set has the same suffix applied to all keys to maintain relative ordering\n      for (let i = 0; i < maxRetries; i++) {\n        const suffix = avoidConflictSuffixBinary(i + skip);\n        if (longest + suffix.length > maxLength) {\n          throw new FraciError(\n            ERROR_CODE_EXCEEDED_MAX_LENGTH,\n            ERROR_MESSAGE_EXCEEDED_MAX_LENGTH,\n          );\n        }\n        yield base.map((v) => concat(v, suffix) as F);\n      }\n\n      // If we reach here, it means we exceeded the maximum retries\n      throw new FraciError(\n        ERROR_CODE_EXCEEDED_MAX_RETRIES,\n        ERROR_MESSAGE_EXCEEDED_MAX_RETRIES,\n      );\n    },\n  };\n}\n\n/**\n * Creates a string-based fractional indexing utility with the specified configuration.\n *\n * @template B - The base configuration defining the character sets\n * @template X - The brand type for the fractional index\n *\n * @param options - Configuration options for the fractional indexing utility\n * @param cache - Optional cache to improve performance by reusing computed values\n * @returns A string-based fractional indexing utility instance\n * @throws {FraciError} Throws a {@link FraciError} when the digit or length base strings are invalid\n *\n * @example\n * ```typescript\n * // Create a decimal-based fractional indexing utility\n * const decimalFraci = fraciString({\n *   brand: \"exampleIndex\",\n *   lengthBase: \"abcdefghij\",\n *   digitBase: \"0123456789\",\n * });\n *\n * // Generate a key between null and null (first key)\n * const [key1] = decimalFraci.generateKeyBetween(null, null);\n * // Generate a key between key1 and null (key after key1)\n * const [key2] = decimalFraci.generateKeyBetween(key1, null);\n * // Generate a key between key1 and key2\n * const [key3] = decimalFraci.generateKeyBetween(key1, key2);\n * ```\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n * @see {@link StringFraciOptions} - The options for the string fractional indexing utility\n * @see {@link FraciCache} - The cache for storing computed values\n * @see {@link fraci} - The unified factory function for creating fractional indexing utilities\n * @see {@link fraciBinary} - The factory function for creating binary-based fractional indexing utilities\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nexport function fraciString<\n  const B extends StringFraciOptions,\n  const X = unknown,\n>(\n  {\n    lengthBase,\n    digitBase,\n    maxLength = DEFAULT_MAX_LENGTH,\n    maxRetries = DEFAULT_MAX_RETRIES,\n  }: BrandableOptions<B, X>,\n  cache?: FraciCache,\n): Fraci<FraciOptionsBaseToBase<B>, X> {\n  type F = FractionalIndex<FraciOptionsBaseToBase<B>, X>;\n\n  // Create and potentially cache the digit and length base maps\n  // This optimization avoids recreating these maps when using the same bases multiple times\n  const [lenBaseForward, lenBaseReverse] = withCache(\n    cache,\n    `L${lengthBase}`,\n    createIntegerLengthBaseMap.bind(null, lengthBase),\n  );\n  const [digBaseForward, digBaseReverse] = withCache(\n    cache,\n    `D${digitBase}`,\n    createDigitBaseMap.bind(null, digitBase),\n  );\n  const smallestInteger = getSmallestInteger(digBaseForward, lenBaseForward);\n\n  return {\n    base: {\n      type: \"string\",\n      lengthBase,\n      digitBase,\n    } as FraciOptionsBaseToBase<B>,\n    *generateKeyBetween(a: F | null, b: F | null, skip = 0) {\n      // Generate the base key between a and b (without conflict avoidance)\n      const base = generateKeyBetween(\n        a,\n        b,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseForward,\n        lenBaseReverse,\n        smallestInteger,\n      );\n      if (!base) {\n        // Logic Error. Should not happen if a and b are valid (i.e. generated by this library with same lengthBase and digitBase).\n        if (globalThis.__DEV__) {\n          logInvalidInputError(a, b, skip);\n        }\n        throw new FraciError(\n          ERROR_CODE_INVALID_INPUT,\n          ERROR_MESSAGE_INVALID_INPUT,\n        );\n      }\n\n      // Generate multiple possible keys with conflict avoidance suffixes\n      // This allows the caller to try multiple keys if earlier ones conflict\n      for (let i = 0; i < maxRetries; i++) {\n        const value = `${base}${avoidConflictSuffix(i + skip, digBaseForward)}`;\n        if (value.length > maxLength) {\n          throw new FraciError(\n            ERROR_CODE_EXCEEDED_MAX_LENGTH,\n            ERROR_MESSAGE_EXCEEDED_MAX_LENGTH,\n          );\n        }\n        yield value as F;\n      }\n\n      // If we reach here, it means we exceeded the maximum retries\n      throw new FraciError(\n        ERROR_CODE_EXCEEDED_MAX_RETRIES,\n        ERROR_MESSAGE_EXCEEDED_MAX_RETRIES,\n      );\n    },\n    *generateNKeysBetween(a: F | null, b: F | null, n: number, skip = 0) {\n      // Generate n base keys between a and b (without conflict avoidance)\n      const base = generateNKeysBetween(\n        a,\n        b,\n        n,\n        digBaseForward,\n        digBaseReverse,\n        lenBaseForward,\n        lenBaseReverse,\n        smallestInteger,\n      );\n      if (!base) {\n        // Logic Error. Should not happen if a and b are valid (i.e. generated by this library with same lengthBase and digitBase).\n        if (globalThis.__DEV__) {\n          logInvalidInputError(a, b, skip);\n        }\n        throw new FraciError(\n          ERROR_CODE_INVALID_INPUT,\n          ERROR_MESSAGE_INVALID_INPUT,\n        );\n      }\n\n      // Find the longest key to ensure we don't exceed maxLength when adding suffixes\n      const longest = base.reduce((acc, v) => Math.max(acc, v.length), 0);\n\n      // Generate multiple sets of keys with conflict avoidance suffixes\n      // Each set has the same suffix applied to all keys to maintain relative ordering\n      for (let i = 0; i < maxRetries; i++) {\n        const suffix = avoidConflictSuffix(i + skip, digBaseForward);\n        if (longest + suffix.length > maxLength) {\n          throw new FraciError(\n            ERROR_CODE_EXCEEDED_MAX_LENGTH,\n            ERROR_MESSAGE_EXCEEDED_MAX_LENGTH,\n          );\n        }\n        yield base.map((v) => `${v}${suffix}` as F);\n      }\n\n      // If we reach here, it means we exceeded the maximum retries\n      throw new FraciError(\n        ERROR_CODE_EXCEEDED_MAX_RETRIES,\n        ERROR_MESSAGE_EXCEEDED_MAX_RETRIES,\n      );\n    },\n  };\n}\n\n/**\n * **We recommend using {@link fraciBinary} or {@link fraciString} directly to reduce bundle size whenever possible.**\n *\n * Creates a fractional indexing utility with the specified configuration.\n * This is the main factory function for creating a {@link Fraci} instance that can generate\n * fractional indices between existing values.\n *\n * @template B - The base configuration defining the encoding strategy\n * @template X - The brand type for the fractional index\n *\n * @param options - Configuration options for the fractional indexing utility\n * @param cache - Optional cache to improve performance by reusing computed values\n * @returns A fractional indexing utility instance\n * @throws {FraciError} Throws a {@link FraciError} when the digit or length base strings are invalid\n *\n * @example\n * ```typescript\n * // Create a decimal-based fractional indexing utility\n * const decimalFraci = fraci({\n *   brand: \"exampleIndex\",\n *   lengthBase: \"abcdefghij\",\n *   digitBase: \"0123456789\",\n * });\n *\n * // Generate a key between null and null (first key)\n * const [key1] = decimalFraci.generateKeyBetween(null, null);\n * // Generate a key between key1 and null (key after key1)\n * const [key2] = decimalFraci.generateKeyBetween(key1, null);\n * // Generate a key between key1 and key2\n * const [key3] = decimalFraci.generateKeyBetween(key1, key2);\n * ```\n *\n * @see {@link Fraci} - The main fractional indexing utility type\n * @see {@link fraciBinary} - The factory function for creating binary-based fractional indexing utilities\n * @see {@link fraciString} - The factory function for creating string-based fractional indexing utilities\n * @see {@link FraciError} - The custom error class for the Fraci library\n */\nexport function fraci<const B extends FraciOptionsBase, const X = unknown>(\n  options: FraciOptions<B> | (FraciOptions<B> & { readonly brand: X }),\n  cache?: FraciCache,\n): Fraci<FraciOptionsBaseToBase<B>, X> {\n  if (options.type === \"binary\") {\n    if (globalThis.__DEV__) {\n      if (cache) {\n        console.warn(\"Fraci: Cache is not used for binary base\");\n      }\n    }\n    return fraciBinary(options) as Fraci<FraciOptionsBaseToBase<B>, X>;\n  }\n\n  return fraciString(options, cache) as Fraci<FraciOptionsBaseToBase<B>, X>;\n}\n","import type { PrismaClientKnownRequestError } from \"@prisma/client/runtime/library.js\";\n\n/**\n * The Prisma conflict error code.\n */\nconst PRISMA_CONFLICT_CODE = \"P2002\";\n\n/**\n * {@link PrismaClientKnownRequestError} of the conflict error.\n */\nexport type PrismaClientConflictError = PrismaClientKnownRequestError & {\n  code: typeof PRISMA_CONFLICT_CODE;\n  meta: { modelName: string; target: string[] };\n};\n\n/**\n * Checks if the error is a conflict error for the fractional index.\n *\n * This is important for handling unique constraint violations when inserting items\n * with the same fractional index, which can happen in concurrent environments.\n *\n * @param error - The error object to check.\n * @param modelName - The model name.\n * @param field - The field name of the fractional index.\n * @returns `true` if the error is a conflict error for the fractional index, or `false` otherwise.\n */\nexport function isIndexConflictError(\n  error: unknown,\n  modelName: string,\n  field: string,\n): error is PrismaClientConflictError {\n  return (\n    error instanceof Error &&\n    error.name === \"PrismaClientKnownRequestError\" &&\n    (error as PrismaClientKnownRequestError).code === PRISMA_CONFLICT_CODE && // P2002 is the Prisma code for unique constraint violations\n    (error as any).meta?.modelName === modelName && // Check if the error is for the correct model\n    Array.isArray((error as any).meta?.target) && // Check if the target field is specified\n    (error as any).meta.target.includes(field) // Check if the target includes our fractional index field\n  );\n}\n","/**\n * The extension name for the Prisma fractional indexing extension.\n */\nexport const EXTENSION_NAME = \"fraci\";\n","import type { QualifiedFields } from \"./prisma-types.js\";\n\n/**\n * The options for the binary fractional index fields.\n *\n * @template Group - The type of the name of the group fields\n *\n * @example { type: \"binary\", group: [\"userId\"] }\n *\n * @see {@link PrismaFraciFieldOptions} - The unified type for fractional index field options\n * @see {@link PrismaFraciFieldOptionsString} - The string fractional index field options\n * @see {@link PrismaFraciOptions} - The options for the fractional indexing extension\n */\nexport interface PrismaFraciFieldOptionsBinary<Group extends string = string> {\n  /**\n   * The type of the fractional index.\n   * Must be \"binary\" for binary fractional indices.\n   */\n  readonly type: \"binary\";\n\n  /**\n   * The fields that define the grouping context for the fractional index.\n   * This is an array of field names.\n   */\n  readonly group: readonly Group[];\n}\n\n/**\n * The options for the string fractional index fields.\n *\n * @template Group - The type of the name of the group fields\n *\n * @example { group: [\"userId\"], lengthBase: \"0123456789\", digitBase: \"0123456789\" }\n *\n * @see {@link PrismaFraciFieldOptions} - The unified type for fractional index field options\n * @see {@link PrismaFraciFieldOptionsBinary} - The binary fractional index field options\n * @see {@link PrismaFraciOptions} - The options for the fractional indexing extension\n */\nexport interface PrismaFraciFieldOptionsString<Group extends string = string> {\n  /**\n   * The type of the fractional index.\n   * Must be \"string\" or `undefined` for string fractional indices.\n   */\n  readonly type?: \"string\" | undefined;\n\n  /**\n   * The fields that define the grouping context for the fractional index.\n   * This is an array of field names.\n   */\n  readonly group: readonly Group[];\n\n  /**\n   * The character set used for encoding the length of the integer part.\n   */\n  readonly lengthBase: string;\n\n  /**\n   * The character set used for representing digits in the fractional index.\n   */\n  readonly digitBase: string;\n}\n\n/**\n * The options for the fractional index fields.\n *\n * @template Group - The type of the name of the group fields\n *\n * @example { group: [\"userId\", \"title\"], lengthBase: \"0123456789\", digitBase: \"0123456789\" }\n *\n * @see {@link PrismaFraciFieldOptionsBinary} - The binary fractional index field options\n * @see {@link PrismaFraciFieldOptionsString} - The string fractional index field options\n * @see {@link PrismaFraciOptions} - The options for the fractional indexing extension\n */\nexport type PrismaFraciFieldOptions<\n  Group extends string = string,\n  Mode extends \"binary\" | \"string\" = \"binary\" | \"string\",\n> = {\n  readonly binary: PrismaFraciFieldOptionsBinary<Group>;\n  readonly string: PrismaFraciFieldOptionsString<Group>;\n}[Mode];\n\n/**\n * The record of the fractional index fields.\n *\n * @example { \"article.fi\": { group: [\"userId\"], lengthBase: \"0123456789\", digitBase: \"0123456789\" } }\n *\n * @see {@link PrismaFraciFieldOptions} - The unified type for fractional index field options\n * @see {@link PrismaFraciOptions} - The options for the fractional indexing extension\n */\nexport type PrismaFraciFieldOptionsRecord = {\n  readonly [Q in QualifiedFields[0]]?:\n    | PrismaFraciFieldOptions<\n        Extract<QualifiedFields, [Q, any, any]>[1],\n        Extract<QualifiedFields, [Q, any, any]>[2]\n      >\n    | undefined;\n};\n\n/**\n * The options for the fractional indexing extension.\n */\nexport interface PrismaFraciOptions {\n  /**\n   * The maximum number of retries to generate a fractional index.\n   *\n   * @default 5\n   */\n  readonly maxRetries?: number | undefined;\n\n  /**\n   * The maximum length of the fractional index.\n   *\n   * @default 50\n   */\n  readonly maxLength?: number | undefined;\n\n  /**\n   * The fractional index fields.\n   */\n  readonly fields: PrismaFraciFieldOptionsRecord;\n}\n\n/**\n * Creates a Prisma extension for fractional indexing.\n * This function defines the options for integrating fractional indexing\n * into a Prisma schema, including field configurations and performance settings.\n *\n * @template Options - The options type\n *\n * @param options - The options for the fractional indexing extension\n * @returns The options object with default values applied\n */\nexport function definePrismaFraci<const Options extends PrismaFraciOptions>(\n  options: Options,\n): Options {\n  return options;\n}\n"],"mappings":"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","names":["prisma_exports","__export","definePrismaFraci","prismaFraci","__toCommonJS","import_extension","INTEGER_ZERO","INTEGER_MINUS_ONE","compare","a","b","len","r","i","concat","result","getIntegerLengthSigned","index","value","getIntegerLengthByte","signedLength","isSmallestInteger","v","splitParts","intLength","incrementInteger","intLengthSigned","digits","newLenSigned","newBinary","decrementInteger","getMidpointFractional","prefixLength","suffix","aDigit","bDigit","mid","getIntegerLengthSigned","index","lenBaseReverse","splitParts","intLength","getIntegerZero","digBaseForward","lenBaseForward","getSmallestInteger","minKey","incrementInteger","digBaseReverse","intLengthSigned","smallestDigit","lenChar","digits","i","value","newLenSigned","newLenChar","decrementInteger","largestDigit","getMidpointFractional","a","b","aPadded","prefixLength","char","aDigit","bDigit","mid","FraciError","code","message","forceUint8Array","value","isValidFractionalIndex","index","isSmallestInteger","parts","splitParts","fractional","ensureNotUndefined","FraciError","generateKeyBetweenUnsafe","a","b","INTEGER_ZERO","bInt","bFrac","concat","getMidpointFractional","decremented","decrementInteger","result","aParts","aInt","aFrac","incremented","incrementInteger","compare","cInt","generateKeyBetween","generateNKeysBetweenUnsafe","n","c","mid","generateNKeysBetween","avoidConflictSuffix","count","additionalFrac","isValidFractionalIndex","index","digBaseForward","digBaseReverse","lenBaseReverse","smallestInteger","parts","splitParts","integer","fractional","char","ensureNotUndefined","value","FraciError","generateKeyBetweenUnsafe","a","b","lenBaseForward","getIntegerZero","bInt","bFrac","getMidpointFractional","decremented","decrementInteger","aParts","aInt","aFrac","incremented","incrementInteger","bParts","cInt","generateKeyBetween","generateNKeysBetweenUnsafe","n","args","c","mid","generateNKeysBetween","avoidConflictSuffix","count","radix","additionalFrac","ERROR_CODE_INITIALIZATION_FAILED","splitBase","base","forward","FraciError","lastCode","char","code","createDigitBaseMap","index","createIntegerLengthBaseMap","positiveBegin","forwardEntries","value","DEFAULT_MAX_LENGTH","DEFAULT_MAX_RETRIES","ERROR_CODE_INVALID_INPUT","ERROR_MESSAGE_INVALID_INPUT","ERROR_CODE_EXCEEDED_MAX_LENGTH","ERROR_MESSAGE_EXCEEDED_MAX_LENGTH","ERROR_CODE_EXCEEDED_MAX_RETRIES","ERROR_MESSAGE_EXCEEDED_MAX_RETRIES","createFraciCache","withCache","cache","key","fn","value","fraciBinary","maxLength","DEFAULT_MAX_LENGTH","maxRetries","DEFAULT_MAX_RETRIES","a","b","skip","base","generateKeyBetween","FraciError","ERROR_CODE_INVALID_INPUT","ERROR_MESSAGE_INVALID_INPUT","i","value","concat","avoidConflictSuffix","ERROR_CODE_EXCEEDED_MAX_LENGTH","ERROR_MESSAGE_EXCEEDED_MAX_LENGTH","ERROR_CODE_EXCEEDED_MAX_RETRIES","ERROR_MESSAGE_EXCEEDED_MAX_RETRIES","n","generateNKeysBetween","longest","acc","v","suffix","fraciString","lengthBase","digitBase","cache","lenBaseForward","lenBaseReverse","withCache","createIntegerLengthBaseMap","digBaseForward","digBaseReverse","createDigitBaseMap","smallestInteger","getSmallestInteger","PRISMA_CONFLICT_CODE","isIndexConflictError","error","modelName","field","EXTENSION_NAME","prismaFraci","fields","maxLength","DEFAULT_MAX_LENGTH","maxRetries","DEFAULT_MAX_RETRIES","client","cache","createFraciCache","helperMap","modelAndField","config","model","field","modelName","FraciError","helper","fraciBinary","fraciString","indicesFor","where","cursor","direction","tuple","pClient","item","items","indicesForAfter","a","b","indicesForBefore","helperEx","error","isIndexConflictError","extensionModel","EXTENSION_NAME","definePrismaFraci","options"]}