{"version":3,"file":"auto-index.cjs","sources":["../../../src/indexes/auto-index.ts"],"sourcesContent":["import { DEFAULT_COMPARE_OPTIONS } from '../utils'\nimport { hasVirtualPropPath } from '../virtual-props'\nimport { checkCollectionSizeForIndex, isDevModeEnabled } from './index-registry'\nimport type { CompareOptions } from '../query/builder/types'\nimport type { BasicExpression } from '../query/ir'\nimport type { CollectionImpl } from '../collection/index.js'\n\nexport interface AutoIndexConfig {\n  autoIndex?: `off` | `eager`\n}\n\nfunction shouldAutoIndex(collection: CollectionImpl<any, any, any, any, any>) {\n  // Only proceed if auto-indexing is enabled\n  // Note: autoIndex: 'eager' without defaultIndexType is caught at construction time\n  // in CollectionImpl, so we don't need to check for it here.\n  return collection.config.autoIndex === `eager`\n}\n\nexport function ensureIndexForField<\n  T extends Record<string, any>,\n  TKey extends string | number,\n>(\n  fieldName: string,\n  fieldPath: Array<string>,\n  collection: CollectionImpl<T, TKey, any, any, any>,\n  compareOptions?: CompareOptions,\n  compareFn?: (a: any, b: any) => number,\n) {\n  if (hasVirtualPropPath(fieldPath)) {\n    return\n  }\n  if (!shouldAutoIndex(collection)) {\n    return\n  }\n\n  const compareOpts = compareOptions ?? {\n    ...DEFAULT_COMPARE_OPTIONS,\n    ...collection.compareOptions,\n  }\n\n  // Check if we already have an index for this field\n  const existingIndex = Array.from(collection.indexes.values()).find(\n    (index) =>\n      index.matchesField(fieldPath) && index.matchesCompareOptions(compareOpts),\n  )\n\n  if (existingIndex) {\n    return // Index already exists\n  }\n\n  // Dev mode: check if collection size warrants an index suggestion\n  if (isDevModeEnabled()) {\n    checkCollectionSizeForIndex(\n      collection.id || `unknown`,\n      collection.size,\n      fieldPath,\n    )\n  }\n\n  // Create a new index for this field using the collection's createIndex method\n  // The collection will use its defaultIndexType\n  try {\n    collection.createIndex(\n      (row) => {\n        // Navigate through the field path\n        let current: any = row\n        for (const part of fieldPath) {\n          current = current[part]\n        }\n        return current\n      },\n      {\n        name: `auto:${fieldPath.join(`.`)}`,\n        options: compareFn ? { compareFn, compareOptions: compareOpts } : {},\n      },\n    )\n  } catch (error) {\n    console.warn(\n      `${collection.id ? `[${collection.id}] ` : ``}Failed to create auto-index for field path \"${fieldPath.join(`.`)}\":`,\n      error,\n    )\n  }\n}\n\n/**\n * Analyzes a where expression and creates indexes for all simple operations on single fields\n */\nexport function ensureIndexForExpression<\n  T extends Record<string, any>,\n  TKey extends string | number,\n>(\n  expression: BasicExpression,\n  collection: CollectionImpl<T, TKey, any, any, any>,\n): void {\n  if (!shouldAutoIndex(collection)) {\n    return\n  }\n\n  // Extract all indexable expressions and create indexes for them\n  const indexableExpressions = extractIndexableExpressions(expression)\n\n  for (const { fieldName, fieldPath } of indexableExpressions) {\n    ensureIndexForField(fieldName, fieldPath, collection)\n  }\n}\n\n/**\n * Extracts all indexable expressions from a where expression\n */\nfunction extractIndexableExpressions(\n  expression: BasicExpression,\n): Array<{ fieldName: string; fieldPath: Array<string> }> {\n  const results: Array<{ fieldName: string; fieldPath: Array<string> }> = []\n\n  function extractFromExpression(expr: BasicExpression): void {\n    if (expr.type !== `func`) {\n      return\n    }\n\n    const func = expr as any\n\n    // Handle 'and' expressions by recursively processing all arguments\n    if (func.name === `and`) {\n      for (const arg of func.args) {\n        extractFromExpression(arg)\n      }\n      return\n    }\n\n    // Check if this is a supported operation\n    const supportedOperations = [`eq`, `gt`, `gte`, `lt`, `lte`, `in`]\n    if (!supportedOperations.includes(func.name)) {\n      return\n    }\n\n    // Check if the first argument is a property reference\n    if (func.args.length < 1 || func.args[0].type !== `ref`) {\n      return\n    }\n\n    const fieldRef = func.args[0]\n    const fieldPath = fieldRef.path\n\n    // Skip if the path is empty\n    if (fieldPath.length === 0) {\n      return\n    }\n\n    // For nested paths, use the full path joined with underscores as the field name\n    // For simple paths, use the first (and only) element\n    const fieldName = fieldPath.join(`_`)\n    results.push({ fieldName, fieldPath })\n  }\n\n  extractFromExpression(expression)\n  return results\n}\n"],"names":["hasVirtualPropPath","DEFAULT_COMPARE_OPTIONS","isDevModeEnabled","checkCollectionSizeForIndex"],"mappings":";;;;;AAWA,SAAS,gBAAgB,YAAqD;AAI5E,SAAO,WAAW,OAAO,cAAc;AACzC;AAEO,SAAS,oBAId,WACA,WACA,YACA,gBACA,WACA;AACA,MAAIA,aAAAA,mBAAmB,SAAS,GAAG;AACjC;AAAA,EACF;AACA,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAEA,QAAM,cAAc,kBAAkB;AAAA,IACpC,GAAGC,MAAAA;AAAAA,IACH,GAAG,WAAW;AAAA,EAAA;AAIhB,QAAM,gBAAgB,MAAM,KAAK,WAAW,QAAQ,OAAA,CAAQ,EAAE;AAAA,IAC5D,CAAC,UACC,MAAM,aAAa,SAAS,KAAK,MAAM,sBAAsB,WAAW;AAAA,EAAA;AAG5E,MAAI,eAAe;AACjB;AAAA,EACF;AAGA,MAAIC,cAAAA,oBAAoB;AACtBC,kBAAAA;AAAAA,MACE,WAAW,MAAM;AAAA,MACjB,WAAW;AAAA,MACX;AAAA,IAAA;AAAA,EAEJ;AAIA,MAAI;AACF,eAAW;AAAA,MACT,CAAC,QAAQ;AAEP,YAAI,UAAe;AACnB,mBAAW,QAAQ,WAAW;AAC5B,oBAAU,QAAQ,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM,QAAQ,UAAU,KAAK,GAAG,CAAC;AAAA,QACjC,SAAS,YAAY,EAAE,WAAW,gBAAgB,YAAA,IAAgB,CAAA;AAAA,MAAC;AAAA,IACrE;AAAA,EAEJ,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,GAAG,WAAW,KAAK,IAAI,WAAW,EAAE,OAAO,EAAE,+CAA+C,UAAU,KAAK,GAAG,CAAC;AAAA,MAC/G;AAAA,IAAA;AAAA,EAEJ;AACF;AAKO,SAAS,yBAId,YACA,YACM;AACN,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,uBAAuB,4BAA4B,UAAU;AAEnE,aAAW,EAAE,WAAW,UAAA,KAAe,sBAAsB;AAC3D,wBAAoB,WAAW,WAAW,UAAU;AAAA,EACtD;AACF;AAKA,SAAS,4BACP,YACwD;AACxD,QAAM,UAAkE,CAAA;AAExE,WAAS,sBAAsB,MAA6B;AAC1D,QAAI,KAAK,SAAS,QAAQ;AACxB;AAAA,IACF;AAEA,UAAM,OAAO;AAGb,QAAI,KAAK,SAAS,OAAO;AACvB,iBAAW,OAAO,KAAK,MAAM;AAC3B,8BAAsB,GAAG;AAAA,MAC3B;AACA;AAAA,IACF;AAGA,UAAM,sBAAsB,CAAC,MAAM,MAAM,OAAO,MAAM,OAAO,IAAI;AACjE,QAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,GAAG;AAC5C;AAAA,IACF;AAGA,QAAI,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,EAAE,SAAS,OAAO;AACvD;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,KAAK,CAAC;AAC5B,UAAM,YAAY,SAAS;AAG3B,QAAI,UAAU,WAAW,GAAG;AAC1B;AAAA,IACF;AAIA,UAAM,YAAY,UAAU,KAAK,GAAG;AACpC,YAAQ,KAAK,EAAE,WAAW,UAAA,CAAW;AAAA,EACvC;AAEA,wBAAsB,UAAU;AAChC,SAAO;AACT;;;"}