{"version":3,"file":"index-registry.cjs","sources":["../../../src/indexes/index-registry.ts"],"sourcesContent":["import { devBuild } from '../error-message'\n\n/**\n * Index Dev Mode - Helps developers identify when indexes would improve performance\n *\n * Dev mode suggestions are ON by default in non-production builds.\n */\n\n// Dev mode detection settings - ON by default in non-production\nlet devModeConfig: IndexDevModeConfig = {\n  enabled: true,\n  collectionSizeThreshold: 1000,\n  slowQueryThresholdMs: 10,\n  onSuggestion: null,\n}\n\nexport interface IndexDevModeConfig {\n  /** Enable dev mode index suggestions */\n  enabled: boolean\n  /** Suggest indexes when collection has more than this many items */\n  collectionSizeThreshold: number\n  /** Suggest indexes when queries take longer than this (ms) */\n  slowQueryThresholdMs: number\n  /** Custom handler for index suggestions */\n  onSuggestion: ((suggestion: IndexSuggestion) => void) | null\n}\n\nexport interface IndexSuggestion {\n  type: `collection-size` | `slow-query` | `frequent-field`\n  collectionId: string\n  fieldPath: Array<string>\n  message: string\n  collectionSize?: number\n  queryTimeMs?: number\n  queryCount?: number\n}\n\n// Track query patterns for dev mode\nconst queryPatterns = new Map<\n  string,\n  {\n    fieldPath: Array<string>\n    queryCount: number\n    totalTimeMs: number\n    avgTimeMs: number\n  }\n>()\n\n/**\n * Configure dev mode for index suggestions\n */\nexport function configureIndexDevMode(\n  config: Partial<IndexDevModeConfig>,\n): void {\n  devModeConfig = { ...devModeConfig, ...config }\n}\n\n/**\n * Get current dev mode configuration\n */\nexport function getIndexDevModeConfig(): IndexDevModeConfig {\n  return devModeConfig\n}\n\n/**\n * Check if dev mode is enabled\n */\nexport function isDevModeEnabled(): boolean {\n  return (\n    devBuild() && process.env.NODE_ENV !== `production` && devModeConfig.enabled\n  )\n}\n\n/**\n * Emit an index suggestion (dev mode only). Every suggestion's text is written\n * here, behind the erasable guard, so production bundles drop all of it.\n */\nexport function emitIndexSuggestion(\n  details: Omit<IndexSuggestion, `message`>,\n): void {\n  if (!(\n    devBuild() &&\n    process.env.NODE_ENV !== `production` &&\n    devModeConfig.enabled\n  ))\n    return\n\n  const field = details.fieldPath.join(`.`)\n  const { type, collectionId, fieldPath, ...stats } = details\n  // The keys keep the order callers saw before the text moved here.\n  const suggestion: IndexSuggestion = {\n    type,\n    collectionId,\n    fieldPath,\n    message:\n      type === `slow-query`\n        ? `Queries on \"${field}\" are slow (avg ${(stats.queryTimeMs ?? 0).toFixed(1)}ms). Consider adding an index.`\n        : `Collection has ${stats.collectionSize} items. Queries on \"${field}\" may benefit from an index.`,\n    ...stats,\n  }\n  if (devModeConfig.onSuggestion) {\n    try {\n      devModeConfig.onSuggestion(suggestion)\n    } catch {\n      // Don't let a buggy callback crash query execution\n    }\n  } else {\n    // Default: log to console with helpful formatting\n    console.warn(\n      `[TanStack DB] Index suggestion for \"${suggestion.collectionId}\":\\n` +\n        `  ${suggestion.message}\\n` +\n        `  Field: ${suggestion.fieldPath.join(`.`)}\\n` +\n        `  Add index: collection.createIndex((row) => row.${suggestion.fieldPath.join(`.`)})`,\n    )\n  }\n}\n\n/**\n * Track a query for dev mode analysis\n */\nexport function trackQuery(\n  collectionId: string,\n  fieldPath: Array<string>,\n  executionTimeMs: number,\n): void {\n  // Inline, not isDevModeEnabled(): production bundles then drop this body.\n  if (!(\n    devBuild() &&\n    process.env.NODE_ENV !== `production` &&\n    devModeConfig.enabled\n  ))\n    return\n\n  const key = `${collectionId}:${fieldPath.join(`.`)}`\n  const existing = queryPatterns.get(key)\n\n  if (existing) {\n    existing.queryCount++\n    existing.totalTimeMs += executionTimeMs\n    existing.avgTimeMs = existing.totalTimeMs / existing.queryCount\n  } else {\n    queryPatterns.set(key, {\n      fieldPath,\n      queryCount: 1,\n      totalTimeMs: executionTimeMs,\n      avgTimeMs: executionTimeMs,\n    })\n  }\n\n  // Check if we should suggest an index\n  const pattern = queryPatterns.get(key)!\n  if (pattern.avgTimeMs > devModeConfig.slowQueryThresholdMs) {\n    emitIndexSuggestion({\n      type: `slow-query`,\n      collectionId,\n      fieldPath,\n      queryTimeMs: pattern.avgTimeMs,\n      queryCount: pattern.queryCount,\n    })\n  }\n}\n\n/**\n * Check collection size and suggest index if needed (dev mode)\n */\nexport function checkCollectionSizeForIndex(\n  collectionId: string,\n  collectionSize: number,\n  fieldPath: Array<string>,\n): void {\n  // Inline, not isDevModeEnabled(): production bundles then drop this body.\n  if (!(\n    devBuild() &&\n    process.env.NODE_ENV !== `production` &&\n    devModeConfig.enabled\n  ))\n    return\n\n  if (collectionSize > devModeConfig.collectionSizeThreshold) {\n    emitIndexSuggestion({\n      type: `collection-size`,\n      collectionId,\n      fieldPath,\n      collectionSize,\n    })\n  }\n}\n\n/**\n * Clear query pattern tracking (useful for tests)\n */\nexport function clearQueryPatterns(): void {\n  queryPatterns.clear()\n}\n\n/**\n * Get query patterns (useful for debugging/testing)\n */\nexport function getQueryPatterns(): Map<\n  string,\n  {\n    fieldPath: Array<string>\n    queryCount: number\n    totalTimeMs: number\n    avgTimeMs: number\n  }\n> {\n  return new Map(queryPatterns)\n}\n"],"names":["devBuild"],"mappings":";;;AASA,IAAI,gBAAoC;AAAA,EACtC,SAAS;AAAA,EACT,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,cAAc;AAChB;AAwBA,MAAM,oCAAoB,IAAA;AAanB,SAAS,sBACd,QACM;AACN,kBAAgB,EAAE,GAAG,eAAe,GAAG,OAAA;AACzC;AAKO,SAAS,wBAA4C;AAC1D,SAAO;AACT;AAKO,SAAS,mBAA4B;AAC1C,SACEA,aAAAA,cAAc,QAAQ,IAAI,aAAa,gBAAgB,cAAc;AAEzE;AAMO,SAAS,oBACd,SACM;AACN,MAAI,EACFA,aAAAA,cACA,QAAQ,IAAI,aAAa,gBACzB,cAAc;AAEd;AAEF,QAAM,QAAQ,QAAQ,UAAU,KAAK,GAAG;AACxC,QAAM,EAAE,MAAM,cAAc,WAAW,GAAG,UAAU;AAEpD,QAAM,aAA8B;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA,SACE,SAAS,eACL,eAAe,KAAK,oBAAoB,MAAM,eAAe,GAAG,QAAQ,CAAC,CAAC,mCAC1E,kBAAkB,MAAM,cAAc,uBAAuB,KAAK;AAAA,IACxE,GAAG;AAAA,EAAA;AAEL,MAAI,cAAc,cAAc;AAC9B,QAAI;AACF,oBAAc,aAAa,UAAU;AAAA,IACvC,QAAQ;AAAA,IAER;AAAA,EACF,OAAO;AAEL,YAAQ;AAAA,MACN,uCAAuC,WAAW,YAAY;AAAA,IACvD,WAAW,OAAO;AAAA,WACX,WAAW,UAAU,KAAK,GAAG,CAAC;AAAA,mDACU,WAAW,UAAU,KAAK,GAAG,CAAC;AAAA,IAAA;AAAA,EAExF;AACF;AAKO,SAAS,WACd,cACA,WACA,iBACM;AAEN,MAAI,EACFA,aAAAA,cACA,QAAQ,IAAI,aAAa,gBACzB,cAAc;AAEd;AAEF,QAAM,MAAM,GAAG,YAAY,IAAI,UAAU,KAAK,GAAG,CAAC;AAClD,QAAM,WAAW,cAAc,IAAI,GAAG;AAEtC,MAAI,UAAU;AACZ,aAAS;AACT,aAAS,eAAe;AACxB,aAAS,YAAY,SAAS,cAAc,SAAS;AAAA,EACvD,OAAO;AACL,kBAAc,IAAI,KAAK;AAAA,MACrB;AAAA,MACA,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,WAAW;AAAA,IAAA,CACZ;AAAA,EACH;AAGA,QAAM,UAAU,cAAc,IAAI,GAAG;AACrC,MAAI,QAAQ,YAAY,cAAc,sBAAsB;AAC1D,wBAAoB;AAAA,MAClB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,aAAa,QAAQ;AAAA,MACrB,YAAY,QAAQ;AAAA,IAAA,CACrB;AAAA,EACH;AACF;AAKO,SAAS,4BACd,cACA,gBACA,WACM;AAEN,MAAI,EACFA,aAAAA,cACA,QAAQ,IAAI,aAAa,gBACzB,cAAc;AAEd;AAEF,MAAI,iBAAiB,cAAc,yBAAyB;AAC1D,wBAAoB;AAAA,MAClB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AACF;AAKO,SAAS,qBAA2B;AACzC,gBAAc,MAAA;AAChB;AAKO,SAAS,mBAQd;AACA,SAAO,IAAI,IAAI,aAAa;AAC9B;;;;;;;;;"}