fraci
Version:
Fractional indexing that's robust, performant, and secure, with first-class support for Drizzle ORM and Prisma ORM.
1 lines • 32.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/drizzle.ts","../src/drizzle/runtime-sync.ts","../src/drizzle/common.ts","../src/drizzle/runtime.ts","../src/drizzle/schema.ts"],"sourcesContent":["/**\n * The Drizzle ORM integration for the fraci library.\n *\n * @module fraci/drizzle\n */\n\nexport * from \"./drizzle/index.js\";\n","import { and, sql } from \"drizzle-orm\";\nimport type { BaseSQLiteDatabase } from \"drizzle-orm/sqlite-core\";\nimport type { Fraci } from \"../factory.js\";\nimport type { AnyFractionalIndex as AFI } from \"../lib/types.js\";\nimport { equity, OPERATORS } from \"./common.js\";\nimport type { drizzleFraci, FraciForDrizzle } from \"./runtime.js\";\nimport type {\n DrizzleFraciConfig,\n DrizzleFraciCursor,\n DrizzleFraciGroup,\n DrizzleFractionalIndex,\n} from \"./types.js\";\n\n/**\n * Type representing supported synchronous Drizzle database clients.\n * This is specifically for Bun SQLite, which is the only synchronous database engine currently available.\n */\nexport type SupportedDrizzleDatabaseSync = BaseSQLiteDatabase<\"sync\", any, any>;\n\n/**\n * Internal function to retrieve indices for positioning items.\n * This function queries the database synchronously to find the appropriate indices\n * for inserting an item before or after a specified cursor position.\n *\n * @param client - The synchronous Drizzle database client\n * @param config - The fractional indexing configuration\n * @param group - The group context for the indices\n * @param cursor - The cursor position, or null for first/last position\n * @param reverse - Whether to retrieve indices in reverse order\n * @returns A tuple of indices, or undefined if the cursor doesn't exist\n */\nfunction indicesFor(\n client: SupportedDrizzleDatabaseSync,\n {\n group: groupConfig,\n cursor: cursorConfig,\n column,\n table,\n }: DrizzleFraciConfig,\n group: DrizzleFraciGroup<DrizzleFraciConfig>,\n cursor: DrizzleFraciCursor<DrizzleFraciConfig> | null,\n reverse: boolean,\n): [AFI | null, AFI | null] | undefined {\n const [order, compare, tuple] = OPERATORS[Number(reverse)];\n const fiSelector = { v: sql<AFI>`${column}` };\n\n // SECURITY: Always use config for `Object.entries` so that all fields are included\n const groupConditions = Object.entries(groupConfig).map(([key, column]) =>\n equity(column, group[key]),\n );\n\n // Case 1: No cursor provided - get the first/last item in the group\n // This is used for indicesForFirst and indicesForLast operations\n if (!cursor) {\n const item = client\n .select(fiSelector)\n .from(table)\n .where(and(...groupConditions))\n .limit(1)\n .orderBy(order(column))\n .all();\n\n // Return [null, firstItem] or [lastItem, null] depending on direction\n return tuple(null, item[0]?.v ?? null);\n }\n\n // Case 2: Cursor provided - build condition to find the exact cursor item\n // This combines group conditions with cursor-specific conditions\n const cursorCondition = and(\n ...groupConditions,\n // SECURITY: Always use config for `Object.entries` so that all fields are included\n // This ensures we don't miss any cursor fields that should be matched\n ...Object.entries(cursorConfig).map(\n ([key, column]) => equity(column, cursor[key]), // Use equity to safely handle null/undefined\n ),\n );\n\n // Performance optimization: Use a subquery to get the fractional index of the cursor item\n // This avoids having to fetch the cursor item separately and then do another query\n const subQueryFIOfCursor = client\n .select(fiSelector)\n .from(table)\n .where(cursorCondition)\n .limit(1);\n\n // Find an item adjacent to the cursor item in a single query\n // This is the main query that finds the items we need for generating a new index\n const items = client\n .select(fiSelector)\n .from(table)\n .where(\n and(\n ...groupConditions, // Stay within the same group\n compare(column, subQueryFIOfCursor), // Use gte/lte based on direction\n ),\n )\n .limit(2) // We need at most 2 items (the cursor item and one adjacent item)\n .orderBy(order(column)) // Sort in the appropriate direction\n .all();\n\n // Process the results\n return items.length < 1\n ? undefined // Cursor item not found in the group\n : tuple(items[0].v, items[1]?.v ?? null); // Reorder based on direction\n}\n\n/**\n * Retrieves indices for positioning an item after a specified cursor.\n * This is a wrapper around the {@link indicesFor} function with `reverse` set to false.\n *\n * @param client - The synchronous Drizzle database client\n * @param config - The fractional indexing configuration\n * @param group - The group context for the indices\n * @param cursor - The cursor position, or null for the first position\n * @returns A tuple of indices, or undefined if the cursor doesn't exist\n */\nfunction indicesForAfter(\n client: SupportedDrizzleDatabaseSync,\n config: DrizzleFraciConfig,\n group: DrizzleFraciGroup<DrizzleFraciConfig>,\n cursor: DrizzleFraciCursor<DrizzleFraciConfig> | null,\n): [AFI | null, AFI | null] | undefined {\n return indicesFor(client, config, group, cursor, false);\n}\n\n/**\n * Retrieves indices for positioning an item before a specified cursor.\n * This is a wrapper around the {@link indicesFor} function with `reverse` set to true.\n *\n * @param client - The synchronous Drizzle database client\n * @param config - The fractional indexing configuration\n * @param group - The group context for the indices\n * @param cursor - The cursor position, or null for the last position\n * @returns A tuple of indices, or undefined if the cursor doesn't exist\n */\nfunction indicesForBefore(\n client: SupportedDrizzleDatabaseSync,\n config: DrizzleFraciConfig,\n group: DrizzleFraciGroup<DrizzleFraciConfig>,\n cursor: DrizzleFraciCursor<DrizzleFraciConfig> | null,\n): [AFI | null, AFI | null] | undefined {\n return indicesFor(client, config, group, cursor, true);\n}\n\n/**\n * Type representing the enhanced fractional indexing utility for Drizzle ORM with synchronous database engine.\n * This type extends the base fractional indexing utility with additional\n * methods for retrieving indices based on synchronous database queries.\n *\n * This is the synchronous counterpart to the {@link FraciForDrizzle} type.\n *\n * @template Config - The type of the fractional indexing configuration\n *\n * @see {@link Fraci} - The base fractional indexing utility type\n * @see {@link drizzleFraciSync} - The main function to create an instance of this type\n * @see {@link FraciForDrizzle} - The asynchronous version of this type\n */\nexport type FraciForDrizzleSync<Config extends DrizzleFraciConfig> =\n Config[\"fraci\"] & {\n /**\n * Returns the indices to calculate the new index of the item to be inserted after the cursor.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @param cursor - A record of the cursor row columns that uniquely identifies the item within a group. If `null`, this function returns the indices to calculate the new index of the first item in the group.\n * @returns The indices to calculate the new index of the item to be inserted after the cursor.\n */\n readonly indicesForAfter: {\n (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config>,\n ):\n | [\n DrizzleFractionalIndex<Config>,\n DrizzleFractionalIndex<Config> | null,\n ]\n | undefined;\n (\n group: DrizzleFraciGroup<Config>,\n cursor: null,\n ): [null, DrizzleFractionalIndex<Config> | null];\n };\n\n /**\n * Returns the indices to calculate the new index of the item to be inserted before the cursor.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @param cursor - A record of the cursor row columns that uniquely identifies the item within a group. If `null`, this function returns the indices to calculate the new index of the last item in the group.\n * @returns The indices to calculate the new index of the item to be inserted before the cursor.\n */\n readonly indicesForBefore: {\n (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config>,\n ):\n | [\n DrizzleFractionalIndex<Config> | null,\n DrizzleFractionalIndex<Config>,\n ]\n | undefined;\n (\n group: DrizzleFraciGroup<Config>,\n cursor: null,\n ): [DrizzleFractionalIndex<Config> | null, null];\n };\n\n /**\n * Returns the indices to calculate the new index of the first item in the group.\n * Identical to {@link FraciForDrizzleSync.indicesForAfter `indicesForAfter(null, group)`}.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @returns The indices to calculate the new index of the first item in the group.\n */\n readonly indicesForFirst: (\n group: DrizzleFraciGroup<Config>,\n ) => [null, DrizzleFractionalIndex<Config> | null];\n\n /**\n * Returns the indices to calculate the new index of the last item in the group.\n * Identical to {@link FraciForDrizzleSync.indicesForBefore `indicesForBefore(null, group)`}.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @returns The indices to calculate the new index of the last item in the group.\n */\n readonly indicesForLast: (\n group: DrizzleFraciGroup<Config>,\n ) => [DrizzleFractionalIndex<Config> | null, null];\n };\n\n/**\n * Creates a synchronous fractional indexing utility for Drizzle ORM.\n * This function enhances a fractional indexing instance with Drizzle-specific\n * methods for retrieving indices based on synchronous database queries.\n *\n * This is the synchronous counterpart to the {@link drizzleFraci} function.\n * Use this function when working with Bun SQLite.\n * The API is identical except that methods return values directly instead of Promises.\n *\n * @template Config - The type of the fractional indexing configuration\n *\n * @param client - The synchronous Drizzle database client to use for queries (SQLite in sync mode)\n * @param config - The configuration for fractional indexing\n * @returns An enhanced fractional indexing utility with Drizzle-specific synchronous methods\n *\n * @example\n * ```typescript\n * const db = drizzle(connection);\n * const taskFraci = drizzleFraciSync(db, defineDrizzleFraci({\n * fraciString({ lengthBase: BASE62, digitBase: BASE62 }),\n * tasks,\n * tasks.position,\n * { userId: tasks.userId },\n * { id: tasks.id }\n * }));\n *\n * // Get indices for inserting at the beginning of a user's task list\n * // Note: No await needed since this is synchronous\n * const [a, b] = taskFraci.indicesForFirst({ userId: 123 });\n * const [newPosition] = taskFraci.generateKeyBetween(a, b);\n * ```\n *\n * @see {@link drizzleFraci} - The asynchronous version of this function\n */\nexport function drizzleFraciSync<Config extends DrizzleFraciConfig>(\n client: SupportedDrizzleDatabaseSync,\n config: Config,\n): FraciForDrizzleSync<Config> {\n return {\n ...config.fraci,\n indicesForAfter: (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config> | null,\n ) => indicesForAfter(client, config, group, cursor),\n indicesForBefore: (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config> | null,\n ) => indicesForBefore(client, config, group, cursor),\n indicesForFirst: (group: DrizzleFraciGroup<Config>) =>\n indicesForAfter(client, config, group, null),\n indicesForLast: (group: DrizzleFraciGroup<Config>) =>\n indicesForBefore(client, config, group, null),\n } as FraciForDrizzleSync<Config>;\n}\n","import { asc, desc, eq, gte, isNull, lte, sql, type Column } from \"drizzle-orm\";\nimport type { AnyFractionalIndex as AFI } from \"../lib/types.js\";\n\n/**\n * Creates a SQL condition for equality comparison that safely handles null and undefined values.\n *\n * This function provides a more robust equality check than the standard `eq` operator:\n * - For non-null values: uses standard equality check\n * - For null values: uses `isNull` check\n * - For undefined values: returns FALSE (security measure for missing values)\n *\n * @param column - The database column to compare\n * @param value - The value to compare against (can be any type including null/undefined)\n * @returns A SQL condition for use in database queries\n */\nexport function equity(column: Column, value: unknown) {\n return value != null\n ? eq(column, value)\n : value === null\n ? // Use `isNull` if value is `null`\n isNull(column)\n : // SECURITY: Always return `FALSE` if value is `undefined`, meaning it's missing\n sql`FALSE`;\n}\n\n/**\n * Array of operator tuples for handling ascending and descending order operations.\n * Each tuple contains three elements:\n * 1. A sort function (asc or desc) for ordering query results\n * 2. A comparison operator (gte or lte) for filtering\n * 3. A function that transforms bound parameters based on sort direction\n *\n * This constant is used to abstract the differences between ascending and\n * descending operations when working with fractional indices.\n */\nexport const OPERATORS = [\n [\n asc,\n gte,\n (a: AFI | null, b: AFI | null): [AFI | null, AFI | null] => [a, b],\n ],\n [\n desc,\n lte,\n (a: AFI | null, b: AFI | null): [AFI | null, AFI | null] => [b, a],\n ],\n] as const;\n","import { and, sql } from \"drizzle-orm\";\nimport type { MySqlDatabase } from \"drizzle-orm/mysql-core\";\nimport type { PgDatabase } from \"drizzle-orm/pg-core\";\nimport type { BaseSQLiteDatabase } from \"drizzle-orm/sqlite-core\";\nimport type { AnyFractionalIndex as AFI } from \"../lib/types.js\";\nimport { equity, OPERATORS } from \"./common.js\";\nimport type { drizzleFraciSync, FraciForDrizzleSync } from \"./runtime-sync.js\";\nimport type {\n DrizzleFraciConfig,\n DrizzleFraciCursor,\n DrizzleFraciGroup,\n DrizzleFractionalIndex,\n} from \"./types.js\";\n\n/**\n * Union type of supported asynchronous Drizzle database clients.\n * This type includes SQLite (in async API), PostgreSQL, and MySQL database clients\n * that can be used with the fractional indexing functionality.\n */\nexport type SupportedDrizzleDatabase =\n | BaseSQLiteDatabase<\"async\", any, any>\n | PgDatabase<any, any, any>\n | MySqlDatabase<any, any, any, any>;\n\n/**\n * Internal type that combines all database types for implementation purposes.\n * This type is used to access common methods across different database clients\n * without having to handle each database type separately.\n */\ntype NarrowDatabase = BaseSQLiteDatabase<\"async\", any, any> &\n PgDatabase<any, any, any> &\n MySqlDatabase<any, any, any, any>;\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 client - The Drizzle database client\n * @param config - The fractional indexing configuration\n * @param group - The group context for the indices\n * @param cursor - The cursor position, or null for first/last position\n * @param reverse - Whether to retrieve indices in reverse order\n * @returns A tuple of indices, or undefined if the cursor doesn't exist\n */\nasync function indicesFor(\n client: SupportedDrizzleDatabase,\n {\n group: groupConfig,\n cursor: cursorConfig,\n column,\n table,\n }: DrizzleFraciConfig,\n group: DrizzleFraciGroup<DrizzleFraciConfig>,\n cursor: DrizzleFraciCursor<DrizzleFraciConfig> | null,\n reverse: boolean,\n): Promise<[AFI | null, AFI | null] | undefined> {\n const [order, compare, tuple] = OPERATORS[Number(reverse)];\n const fiSelector = { v: sql<AFI>`${column}` };\n\n // SECURITY: Always use config for `Object.entries` so that all fields are included\n const groupConditions = Object.entries(groupConfig).map(([key, column]) =>\n equity(column, group[key]),\n );\n\n // Case 1: No cursor provided - get the first/last item in the group\n // This is used for indicesForFirst and indicesForLast operations\n if (!cursor) {\n const item = await (client as NarrowDatabase)\n .select(fiSelector)\n .from(table)\n .where(and(...groupConditions))\n .limit(1)\n .orderBy(order(column));\n\n // Return [null, firstItem] or [lastItem, null] depending on direction\n return tuple(null, item[0]?.v ?? null);\n }\n\n // Case 2: Cursor provided - build condition to find the exact cursor item\n // This combines group conditions with cursor-specific conditions\n const cursorCondition = and(\n ...groupConditions,\n // SECURITY: Always use config for `Object.entries` so that all fields are included\n // This ensures we don't miss any cursor fields that should be matched\n ...Object.entries(cursorConfig).map(\n ([key, column]) => equity(column, cursor[key]), // Use equity to safely handle null/undefined\n ),\n );\n\n // Performance optimization: Use a subquery to get the fractional index of the cursor item\n // This avoids having to fetch the cursor item separately and then do another query\n const subQueryFIOfCursor = (client as NarrowDatabase)\n .select(fiSelector)\n .from(table)\n .where(cursorCondition)\n .limit(1);\n\n // Find an item adjacent to the cursor item in a single query\n // This is the main query that finds the items we need for generating a new index\n const items = await (client as NarrowDatabase)\n .select(fiSelector)\n .from(table)\n .where(\n and(\n ...groupConditions, // Stay within the same group\n compare(column, subQueryFIOfCursor), // Use gte/lte based on direction\n ),\n )\n .limit(2) // We need at most 2 items (the cursor item and one adjacent item)\n .orderBy(order(column)); // Sort in the appropriate direction\n\n // Process the results\n return items.length < 1\n ? undefined // Cursor item not found in the group\n : tuple(items[0].v, items[1]?.v ?? null); // Reorder based on direction\n}\n\n/**\n * Retrieves indices for positioning an item after a specified cursor.\n * This is a wrapper around the {@link indicesFor} function with `reverse` set to false.\n *\n * @param client - The Drizzle database client\n * @param config - The fractional indexing configuration\n * @param group - The group context for the indices\n * @param cursor - The cursor position, or null for the first position\n * @returns A tuple of indices, or undefined if the cursor doesn't exist\n */\nfunction indicesForAfter(\n client: SupportedDrizzleDatabase,\n config: DrizzleFraciConfig,\n group: DrizzleFraciGroup<DrizzleFraciConfig>,\n cursor: DrizzleFraciCursor<DrizzleFraciConfig> | null,\n): Promise<[AFI | null, AFI | null] | undefined> {\n return indicesFor(client, config, group, cursor, false);\n}\n\n/**\n * Retrieves indices for positioning an item before a specified cursor.\n * This is a wrapper around the {@link indicesFor} function with `reverse` set to true.\n *\n * @param client - The Drizzle database client\n * @param config - The fractional indexing configuration\n * @param group - The group context for the indices\n * @param cursor - The cursor position, or null for the last position\n * @returns A tuple of indices, or undefined if the cursor doesn't exist\n */\nfunction indicesForBefore(\n client: SupportedDrizzleDatabase,\n config: DrizzleFraciConfig,\n group: DrizzleFraciGroup<DrizzleFraciConfig>,\n cursor: DrizzleFraciCursor<DrizzleFraciConfig> | null,\n): Promise<[AFI | null, AFI | null] | undefined> {\n return indicesFor(client, config, group, cursor, true);\n}\n\n/**\n * Type representing the enhanced fractional indexing utility for Drizzle ORM with asynchronous database engine.\n * This type extends the base fractional indexing utility with additional\n * methods for retrieving indices based on asynchronous database queries.\n *\n * @template Config - The type of the fractional indexing configuration\n *\n * @see {@link drizzleFraci} - The main function to create an instance of this type\n * @see {@link FraciForDrizzleSync} - The synchronous version of this type\n */\nexport type FraciForDrizzle<Config extends DrizzleFraciConfig> =\n Config[\"fraci\"] & {\n /**\n * Returns the indices to calculate the new index of the item to be inserted after the cursor.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @param cursor - A record of the cursor row columns that uniquely identifies the item within a group. If `null`, this function returns the indices to calculate the new index of the first item in the group.\n * @returns The indices to calculate the new index of the item to be inserted after the cursor.\n */\n readonly indicesForAfter: {\n (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config>,\n ): Promise<\n | [\n DrizzleFractionalIndex<Config>,\n DrizzleFractionalIndex<Config> | null,\n ]\n | undefined\n >;\n (\n group: DrizzleFraciGroup<Config>,\n cursor: null,\n ): Promise<[null, DrizzleFractionalIndex<Config> | null]>;\n };\n\n /**\n * Returns the indices to calculate the new index of the item to be inserted before the cursor.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @param cursor - A record of the cursor row columns that uniquely identifies the item within a group. If `null`, this function returns the indices to calculate the new index of the last item in the group.\n * @returns The indices to calculate the new index of the item to be inserted before the cursor.\n */\n readonly indicesForBefore: {\n (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config>,\n ): Promise<\n | [\n DrizzleFractionalIndex<Config> | null,\n DrizzleFractionalIndex<Config>,\n ]\n | undefined\n >;\n (\n group: DrizzleFraciGroup<Config>,\n cursor: null,\n ): Promise<[DrizzleFractionalIndex<Config> | null, null]>;\n };\n\n /**\n * Returns the indices to calculate the new index of the first item in the group.\n * Identical to {@link FraciForDrizzle.indicesForAfter `indicesForAfter(null, group)`}.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @returns The indices to calculate the new index of the first item in the group.\n */\n readonly indicesForFirst: (\n group: DrizzleFraciGroup<Config>,\n ) => Promise<[null, DrizzleFractionalIndex<Config> | null]>;\n\n /**\n * Returns the indices to calculate the new index of the last item in the group.\n * Identical to {@link FraciForDrizzle.indicesForBefore `indicesForBefore(null, group)`}.\n *\n * @param group - A record of the columns that uniquely identifies the group.\n * @returns The indices to calculate the new index of the last item in the group.\n */\n readonly indicesForLast: (\n group: DrizzleFraciGroup<Config>,\n ) => Promise<[DrizzleFractionalIndex<Config> | null, null]>;\n };\n\n/**\n * Creates an asynchronous fractional indexing utility for Drizzle ORM.\n * This function enhances a fractional indexing instance with Drizzle-specific\n * methods for retrieving indices based on asynchronous database queries.\n *\n * This is the asynchronous version that works with all supported database engines.\n * For Bun SQLite, use the {@link drizzleFraciSync} function.\n * The API is identical except that methods return Promises instead of direct values.\n *\n * @template Config - The type of the fractional indexing configuration\n *\n * @param client - The asynchronous Drizzle database client to use for queries\n * @param config - The configuration for fractional indexing\n * @returns An enhanced fractional indexing utility with Drizzle-specific asynchronous methods\n *\n * @example\n * ```typescript\n * const db = drizzle(connection);\n * const taskFraci = drizzleFraci(db, defineDrizzleFraci({\n * fraciString({ lengthBase: BASE62, digitBase: BASE62 }),\n * tasks,\n * tasks.position,\n * { userId: tasks.userId },\n * { id: tasks.id }\n * }));\n *\n * // Get indices for inserting at the beginning of a user's task list\n * // Note: await is needed since this is asynchronous\n * const [a, b] = await taskFraci.indicesForFirst({ userId: 123 });\n * const [newPosition] = taskFraci.generateKeyBetween(a, b);\n * ```\n *\n * @see {@link drizzleFraciSync} - The synchronous version of this function\n */\nexport function drizzleFraci<Config extends DrizzleFraciConfig>(\n client: SupportedDrizzleDatabase,\n config: Config,\n): FraciForDrizzle<Config> {\n return {\n ...config.fraci,\n indicesForAfter: (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config> | null,\n ) => indicesForAfter(client, config, group, cursor),\n indicesForBefore: (\n group: DrizzleFraciGroup<Config>,\n cursor: DrizzleFraciCursor<Config> | null,\n ) => indicesForBefore(client, config, group, cursor),\n indicesForFirst: (group: DrizzleFraciGroup<Config>) =>\n indicesForAfter(client, config, group, null),\n indicesForLast: (group: DrizzleFraciGroup<Config>) =>\n indicesForBefore(client, config, group, null),\n } as FraciForDrizzle<Config>;\n}\n","import type { Column, Table } from \"drizzle-orm\";\nimport type { AnyFraci } from \"../factory.js\";\nimport type { FractionalIndexOf } from \"../types.js\";\nimport type { DrizzleFraciColumn, DrizzleFraciConfig } from \"./types.js\";\n\n/**\n * Creates a configuration object for fractional indexing with Drizzle ORM.\n * This function defines how fractional indices are integrated into a Drizzle schema,\n * specifying the table, column, grouping context, and cursor information.\n *\n * @template F - The fractional indexing utility type\n * @template T - The Drizzle table type\n * @template FraciColumn - The column type that stores fractional indices\n * @template Group - The record type for grouping columns\n * @template Cursor - The record type for cursor columns\n *\n * @param fraci - The fractional indexing utility instance\n * @param table - The Drizzle table object\n * @param column - The column that will store the fractional index\n * @param group - The columns that define the grouping context\n * @param cursor - The columns that uniquely identify a row within a group\n * @returns A configuration object for fractional indexing\n */\nexport function defineDrizzleFraci<\n F extends AnyFraci,\n T extends Table,\n FraciColumn extends DrizzleFraciColumn<FractionalIndexOf<F>>,\n Group extends Record<string, Column>,\n Cursor extends Record<string, Column>,\n>(\n fraci: F,\n table: T,\n column: FraciColumn,\n group: Group,\n cursor: Cursor,\n): DrizzleFraciConfig<F, T, FraciColumn, Group, Cursor> {\n return { fraci, table, column, group, cursor };\n}\n"],"mappings":"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","names":["drizzle_exports","__export","defineDrizzleFraci","drizzleFraci","drizzleFraciSync","__toCommonJS","import_drizzle_orm","import_drizzle_orm","equity","column","value","OPERATORS","a","b","indicesFor","client","groupConfig","cursorConfig","column","table","group","cursor","reverse","order","compare","tuple","OPERATORS","fiSelector","groupConditions","key","equity","item","cursorCondition","subQueryFIOfCursor","items","indicesForAfter","config","indicesForBefore","drizzleFraciSync","import_drizzle_orm","indicesFor","client","groupConfig","cursorConfig","column","table","group","cursor","reverse","order","compare","tuple","OPERATORS","fiSelector","groupConditions","key","equity","item","cursorCondition","subQueryFIOfCursor","items","indicesForAfter","config","indicesForBefore","drizzleFraci","defineDrizzleFraci","fraci","table","column","group","cursor"]}