{"version":3,"file":"manager-qfbUL7ru.mjs","names":[],"sources":["../src/plugin/manager.ts"],"sourcesContent":["import { db, type TailorAnyDBType } from \"#/configure/services/tailordb/index\";\nimport {\n  getPluginGenerationDependencies,\n  getRawPluginTableName,\n  hasGenerationHooks,\n} from \"#/plugin/guards\";\nimport { assertDefined } from \"#/utils/assert\";\nimport type {\n  TailorTypePermission,\n  TailorTypeGqlPermission,\n} from \"#/configure/services/tailordb/permission\";\nimport type {\n  TailorAnyDBField,\n  TypeHook,\n  TypeValidateFn,\n} from \"#/configure/services/tailordb/types\";\nimport type {\n  DependencyKind,\n  Plugin,\n  PluginAttachment,\n  PluginGeneratedExecutor,\n  PluginGeneratedTable,\n  PluginNamespaceProcessContext,\n  PluginOutput,\n  TablePluginOutput,\n} from \"#/plugin/types\";\nimport type { TailorDBTypeRaw } from \"#/types/tailordb.generated\";\n\n/**\n * Context for processing a single plugin attachment on a raw TailorDBType\n */\nexport interface ProcessAttachmentContext {\n  table: TailorAnyDBType;\n  tableConfig: unknown;\n  namespace: string;\n  pluginId: string;\n}\n\n/**\n * Information about a plugin-generated table (for table file generation)\n */\nexport interface PluginGeneratedTableInfo {\n  /** Plugin ID that generated this table */\n  pluginId: string;\n  /** Plugin import path for resolving executor files */\n  pluginImportPath: string;\n  /** Source table name that triggered the plugin */\n  sourceTableName: string;\n  /** Kind identifier for this generated table */\n  kind: string;\n  /** The generated TailorDB table object */\n  table: PluginGeneratedTable;\n  /** Namespace where this table was generated */\n  namespace: string;\n  /** Plugin config used to generate this table */\n  pluginConfig?: unknown;\n}\n\n/**\n * Extended executor info with plugin import path\n */\nexport interface PluginExecutorInfoExtended extends PluginExecutorInfo {\n  /** Plugin's import path for resolving executor files */\n  pluginImportPath: string;\n}\n\n/**\n * Result of processing a table-attached plugin\n */\nexport type ProcessAttachmentResult =\n  | { success: true; output: TablePluginOutput }\n  | { success: false; error: string };\n\n/**\n * Result of processing a namespace plugin\n */\nexport type ProcessNamespaceResult =\n  | { success: true; output: PluginOutput }\n  | { success: false; error: string };\n\n/**\n * Parameters for processing all plugin attachments of a TailorDB table.\n */\nexport interface ProcessAttachmentsForTableParams {\n  rawTable: TailorDBTypeRaw;\n  attachments: PluginAttachment[];\n  namespace: string;\n}\n\n/**\n * Progress event emitted while processing plugin attachments for a TailorDB table.\n * Plain data so the caller (typically the cli) can format and output it.\n */\ntype ProcessAttachmentEvent =\n  | { kind: \"extended\"; tableName: string; fieldCount: number; pluginId: string }\n  | { kind: \"generated\"; tableName: string; pluginId: string };\n\n/**\n * Generated table produced by a plugin during attachment processing.\n * `table` is raw plugin output; the caller must validate it before use.\n */\ninterface ProcessAttachmentsGeneratedTable {\n  tableName: string;\n  table: unknown;\n  kind: string;\n  pluginId: string;\n  pluginImportPath: string;\n  pluginConfig?: unknown;\n}\n\n/**\n * Result of {@link PluginManager.processAttachmentsForTable}.\n */\nexport interface ProcessAttachmentsForTableResult {\n  /**\n   * Final table after all extends are applied; undefined if no plugin extended the table.\n   * Raw builder output; the caller must validate it before use.\n   */\n  extendedTable?: unknown;\n  /** Tables newly generated by plugins for this attachment chain. */\n  generatedTables: ProcessAttachmentsGeneratedTable[];\n  /** Events for the caller to render. */\n  events: ProcessAttachmentEvent[];\n}\n\n/**\n * Information about a plugin-generated executor\n */\nexport interface PluginExecutorInfo {\n  /** The executor definition */\n  executor: PluginGeneratedExecutor;\n  /** Plugin ID that generated this executor */\n  pluginId: string;\n  /** Namespace where the executor was generated */\n  namespace: string;\n  /** Source table name (for table-attached executors, undefined for namespace) */\n  sourceTableName?: string;\n}\n\n/**\n * Manages plugin registration and processing\n */\nexport class PluginManager {\n  private plugins: Map<string, Plugin> = new Map();\n  private generatedExecutors: PluginExecutorInfo[] = [];\n  private generatedTables: PluginGeneratedTableInfo[] = [];\n  private namespaceGeneratedTableKeys: Set<string> = new Set();\n  private namespaceGeneratedExecutorKeys: Set<string> = new Set();\n\n  /** Generated plugin executor file paths */\n  private pluginExecutorFiles: string[] = [];\n\n  constructor(plugins: Plugin[] = []) {\n    for (const plugin of plugins) {\n      if (this.plugins.has(plugin.id)) {\n        throw new Error(\n          `Duplicate plugin ID \"${plugin.id}\" detected. Each plugin must have a unique ID.`,\n        );\n      }\n      this.plugins.set(plugin.id, plugin);\n    }\n  }\n\n  /**\n   * Process a single plugin attachment on a raw TailorDBType.\n   * This method is called during table loading before parsing.\n   * @param context - Context containing the raw table, config, namespace, and plugin ID\n   * @returns Result with plugin output on success, or error message on failure\n   */\n  async processAttachment(context: ProcessAttachmentContext): Promise<ProcessAttachmentResult> {\n    const plugin = this.plugins.get(context.pluginId);\n    if (!plugin) {\n      return {\n        success: false,\n        error: `Plugin \"${context.pluginId}\" not found`,\n      };\n    }\n\n    const tableConfigRequired = plugin.tableConfigRequired;\n    const resolvedRequired =\n      typeof tableConfigRequired === \"function\"\n        ? tableConfigRequired(plugin.pluginConfig)\n        : tableConfigRequired === true;\n    if (resolvedRequired && (context.tableConfig === undefined || context.tableConfig === null)) {\n      return {\n        success: false,\n        error: `Plugin \"${plugin.id}\" requires tableConfig, but none was provided for table \"${context.table.name}\".`,\n      };\n    }\n\n    // Check if plugin supports table-attached processing\n    if (!plugin.onTableLoaded) {\n      return {\n        success: false,\n        error: `Plugin \"${plugin.id}\" does not support table-attached processing (missing onTableLoaded method). Use onNamespaceLoaded via definePlugins() instead.`,\n      };\n    }\n\n    // Execute plugin onTableLoaded with the raw TailorDB table\n    let output: TablePluginOutput;\n    try {\n      output = await plugin.onTableLoaded({\n        table: context.table,\n        tableConfig: context.tableConfig,\n        pluginConfig: plugin.pluginConfig,\n        namespace: context.namespace,\n      });\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      return {\n        success: false,\n        error: `Plugin \"${plugin.id}\" threw an error while processing table \"${context.table.name}\": ${message}`,\n      };\n    }\n\n    // Collect generated tables\n    if (output.tables && Object.keys(output.tables).length > 0) {\n      // importPath is guaranteed by schema validation for plugins with definition-time hooks\n      const importPath = assertDefined(\n        plugin.importPath,\n        `plugin \"${plugin.id}\" missing importPath`,\n      );\n      for (const [kind, table] of Object.entries(output.tables)) {\n        this.generatedTables.push({\n          pluginId: context.pluginId,\n          pluginImportPath: importPath,\n          sourceTableName: context.table.name,\n          kind,\n          table,\n          namespace: context.namespace,\n          pluginConfig: plugin.pluginConfig,\n        });\n      }\n    }\n\n    // Collect generated executors\n    if (output.executors && output.executors.length > 0) {\n      for (const executor of output.executors) {\n        this.generatedExecutors.push({\n          executor,\n          pluginId: context.pluginId,\n          namespace: context.namespace,\n          sourceTableName: context.table.name,\n        });\n      }\n    }\n\n    return { success: true, output };\n  }\n\n  /**\n   * Process namespace plugins that don't require a source table.\n   * This method is called once per namespace for plugins with onNamespaceLoaded method.\n   * @param namespace - The target namespace for generated tables\n   * @returns Array of results with plugin outputs and configs\n   */\n  async processNamespacePlugins(\n    namespace: string,\n  ): Promise<Array<{ pluginId: string; config: unknown; result: ProcessNamespaceResult }>> {\n    const results: Array<{ pluginId: string; config: unknown; result: ProcessNamespaceResult }> =\n      [];\n\n    for (const [pluginId, plugin] of this.plugins) {\n      // Skip plugins without onNamespaceLoaded method\n      if (!plugin.onNamespaceLoaded) {\n        continue;\n      }\n\n      // Use stored plugin config (from definePlugins)\n      const config = plugin.pluginConfig;\n\n      // Execute plugin onNamespaceLoaded\n      const context: PluginNamespaceProcessContext = {\n        pluginConfig: config,\n        namespace,\n      };\n\n      let output: Awaited<ReturnType<NonNullable<Plugin[\"onNamespaceLoaded\"]>>>;\n      try {\n        output = await plugin.onNamespaceLoaded(context);\n      } catch (error) {\n        const message = error instanceof Error ? error.message : String(error);\n        results.push({\n          pluginId,\n          config,\n          result: {\n            success: false,\n            error: `Plugin \"${plugin.id}\" threw an error during namespace processing for \"${namespace}\": ${message}`,\n          },\n        });\n        continue;\n      }\n\n      // Collect generated executors (namespace - no source table)\n      if (output.executors && output.executors.length > 0) {\n        for (const executor of output.executors) {\n          const executorKey = `${pluginId}:${executor.name}`;\n          if (this.namespaceGeneratedExecutorKeys.has(executorKey)) {\n            continue;\n          }\n          this.namespaceGeneratedExecutorKeys.add(executorKey);\n          this.generatedExecutors.push({\n            executor,\n            pluginId,\n            namespace,\n          });\n        }\n      }\n\n      // Collect generated tables (namespace - no source table)\n      if (output.tables && Object.keys(output.tables).length > 0) {\n        // importPath is guaranteed by schema validation for plugins with definition-time hooks\n        const importPath = assertDefined(\n          plugin.importPath,\n          `plugin \"${plugin.id}\" missing importPath`,\n        );\n        for (const [kind, table] of Object.entries(output.tables)) {\n          const tableKey = `${pluginId}:${kind}:${getRawPluginTableName(table) ?? \"\"}`;\n          if (this.namespaceGeneratedTableKeys.has(tableKey)) {\n            continue;\n          }\n          this.namespaceGeneratedTableKeys.add(tableKey);\n          this.generatedTables.push({\n            pluginId,\n            pluginImportPath: importPath,\n            sourceTableName: \"(namespace)\",\n            kind,\n            table,\n            namespace,\n            pluginConfig: plugin.pluginConfig,\n          });\n        }\n      }\n\n      results.push({\n        pluginId,\n        config,\n        result: { success: true, output },\n      });\n    }\n\n    return results;\n  }\n\n  /**\n   * Run every plugin attachment for a single TailorDB table in order, threading the\n   * extended table through the chain. Returns plain data (no logging, no shared state)\n   * so the caller decides how to apply updates and render progress.\n   * @param params - The raw table, its attachments, and the target namespace\n   * @returns Final extended table (if any), generated tables, and render events\n   */\n  async processAttachmentsForTable(\n    params: ProcessAttachmentsForTableParams,\n  ): Promise<ProcessAttachmentsForTableResult> {\n    const { rawTable, attachments, namespace } = params;\n    // The runtime value is a configure-layer builder instance; we accept the structural\n    // TailorDBTypeRaw at the boundary so callers (cli) don't need to depend on TailorAnyDBType.\n    let currentTable: TailorAnyDBType = rawTable as unknown as TailorAnyDBType;\n    let extendedTable: TailorAnyDBType | undefined;\n    const generatedTables: ProcessAttachmentsGeneratedTable[] = [];\n    const events: ProcessAttachmentEvent[] = [];\n\n    for (const attachment of attachments) {\n      const result = await this.processAttachment({\n        table: currentTable,\n        tableConfig: attachment.config,\n        namespace,\n        pluginId: attachment.pluginId,\n      });\n      if (!result.success) {\n        throw new Error(result.error);\n      }\n\n      const output = result.output;\n      const extendFields = output.extends?.fields;\n      if (extendFields && Object.keys(extendFields).length > 0) {\n        currentTable = this.extendTable({\n          originalTable: currentTable,\n          extendFields,\n          pluginId: attachment.pluginId,\n        });\n        extendedTable = currentTable;\n        events.push({\n          kind: \"extended\",\n          tableName: currentTable.name,\n          fieldCount: Object.keys(extendFields).length,\n          pluginId: attachment.pluginId,\n        });\n      }\n\n      const plugin = this.getPlugin(attachment.pluginId);\n      for (const [kind, table] of Object.entries(output.tables ?? {})) {\n        const tableName = getRawPluginTableName(table) ?? \"\";\n        generatedTables.push({\n          tableName,\n          table,\n          kind,\n          pluginId: attachment.pluginId,\n          pluginImportPath: this.getPluginImportPath(attachment.pluginId) ?? \"\",\n          pluginConfig: plugin?.pluginConfig,\n        });\n        events.push({ kind: \"generated\", tableName, pluginId: attachment.pluginId });\n      }\n    }\n\n    return { extendedTable, generatedTables, events };\n  }\n\n  /**\n   * Get plugins that have onNamespaceLoaded method\n   * @returns Array of plugin IDs that support namespace processing\n   */\n  getNamespacePluginIds(): string[] {\n    return Array.from(this.plugins.entries())\n      .filter(([, plugin]) => plugin.onNamespaceLoaded !== undefined)\n      .map(([id]) => id);\n  }\n\n  /**\n   * Get the count of registered plugins\n   * @returns Number of registered plugins\n   */\n  get pluginCount(): number {\n    return this.plugins.size;\n  }\n\n  /**\n   * Get a plugin by its ID\n   * @param pluginId - The plugin ID to look up\n   * @returns The plugin instance, or undefined if not found\n   */\n  getPlugin(pluginId: string): Plugin | undefined {\n    return this.plugins.get(pluginId);\n  }\n\n  /**\n   * Get the import path for a plugin\n   * @param pluginId - The plugin ID to look up\n   * @returns The plugin's import path, or undefined if not found\n   */\n  getPluginImportPath(pluginId: string): string | undefined {\n    return this.plugins.get(pluginId)?.importPath;\n  }\n\n  /**\n   * Get all plugin-generated executors\n   * @returns Array of plugin-generated executor info\n   */\n  getPluginGeneratedExecutors(): ReadonlyArray<PluginExecutorInfo> {\n    return this.generatedExecutors;\n  }\n\n  /**\n   * Get all plugin-generated executors with import paths\n   * @returns Array of plugin-generated executor info with import paths\n   */\n  getPluginGeneratedExecutorsWithImportPath(): ReadonlyArray<PluginExecutorInfoExtended> {\n    return this.generatedExecutors.map((info) => ({\n      ...info,\n      pluginImportPath: this.getPluginImportPath(info.pluginId) ?? \"\",\n    }));\n  }\n\n  /**\n   * Get all plugin-generated tables\n   * @returns Array of plugin-generated table info\n   */\n  getPluginGeneratedTables(): ReadonlyArray<PluginGeneratedTableInfo> {\n    return this.generatedTables;\n  }\n\n  /**\n   * Get plugin-generated executors for a specific namespace\n   * @param namespace - The namespace to filter by\n   * @returns Array of plugin-generated executor info for the namespace\n   */\n  getPluginGeneratedExecutorsForNamespace(namespace: string): ReadonlyArray<PluginExecutorInfo> {\n    return this.generatedExecutors.filter((info) => info.namespace === namespace);\n  }\n\n  /**\n   * Get plugins that have any generation-time hooks.\n   * @returns Array of plugins with generation hooks\n   */\n  getPluginsWithGenerationHooks(): Plugin[] {\n    return Array.from(this.plugins.values()).filter((plugin) => hasGenerationHooks(plugin));\n  }\n\n  /**\n   * Get the generation-time dependencies for a specific plugin.\n   * @param pluginId - The plugin ID to look up\n   * @returns Set of dependency kinds, or empty set if plugin not found\n   */\n  getPluginGenerationDependencies(pluginId: string): Set<DependencyKind> {\n    const plugin = this.plugins.get(pluginId);\n    if (!plugin) return new Set();\n    return getPluginGenerationDependencies(plugin);\n  }\n\n  /**\n   * Generate plugin files (tables and executors) and store the executor file paths.\n   * @param params - Parameters for file generation\n   * @returns Generated executor file paths\n   */\n  generatePluginFiles(params: GeneratePluginFilesParams): string[] {\n    const { outputDir, sourceTableInfoMap, configPath, tableGenerator, executorGenerator } = params;\n\n    // Generate table files\n    const tableGenerationResult = tableGenerator(this.generatedTables, outputDir);\n\n    // Generate executor files\n    const pluginExecutors = this.getPluginGeneratedExecutorsWithImportPath();\n    this.pluginExecutorFiles = executorGenerator(\n      pluginExecutors,\n      outputDir,\n      tableGenerationResult,\n      sourceTableInfoMap,\n      configPath,\n    );\n\n    return this.pluginExecutorFiles;\n  }\n\n  /**\n   * Extend a TailorDB table with new fields.\n   * This method handles the `db.table()` call and metadata copying internally.\n   * @param params - Parameters for table extension\n   * @returns The extended TailorDB table\n   */\n  extendTable(params: ExtendTableParams): TailorAnyDBType {\n    const { originalTable, extendFields, pluginId } = params;\n    const existingFieldNames = Object.keys(originalTable.fields);\n    const existingFileNames = Object.keys(originalTable.metadata.files);\n    const newFieldNames = Object.keys(extendFields);\n    const duplicateFields = newFieldNames.filter((name) => existingFieldNames.includes(name));\n    const duplicateFiles = newFieldNames.filter((name) => existingFileNames.includes(name));\n\n    if (duplicateFields.length > 0) {\n      throw new Error(\n        `Plugin \"${pluginId}\" attempted to add fields that already exist in table \"${originalTable.name}\": ${duplicateFields.join(\", \")}. ` +\n          `extendFields cannot overwrite existing fields.`,\n      );\n    }\n\n    if (duplicateFiles.length > 0) {\n      throw new Error(\n        `Plugin \"${pluginId}\" attempted to add fields that collide with file keys already declared via .files() on table \"${originalTable.name}\": ${duplicateFiles.join(\", \")}.`,\n      );\n    }\n\n    const mergedFields = {\n      ...originalTable.fields,\n      ...extendFields,\n    };\n\n    const { id: _id, ...fieldsWithoutId } = mergedFields;\n    const pluralForm = originalTable.metadata.settings?.pluralForm;\n    const tableName = pluralForm\n      ? ([originalTable.name, pluralForm] as [string, string])\n      : originalTable.name;\n    const extendedTable = db.table(tableName, fieldsWithoutId);\n    return copyMetadataToExtendedTable(originalTable, extendedTable);\n  }\n}\n\n/**\n * Source info for user-defined tables\n */\nexport type SourceTableInfo = {\n  filePath: string;\n  exportName: string;\n};\n\n/**\n * Result of generating plugin table files\n */\nexport interface PluginTableGenerationResult {\n  /** Map of table name to generated file path (relative to outputDir) */\n  tableFilePaths: Map<string, string>;\n  /** List of all generated file paths (absolute) */\n  generatedFiles: string[];\n}\n\n/**\n * Parameters for generating plugin files\n */\nexport interface GeneratePluginFilesParams {\n  /** Base output directory (e.g., .tailor/plugin) */\n  outputDir: string;\n  /** Map of source table names to their source info */\n  sourceTableInfoMap: Map<string, SourceTableInfo>;\n  /** Path to tailor.config.ts (used for resolving plugin import paths) */\n  configPath: string;\n  /** Function to generate table files */\n  tableGenerator: (\n    tables: ReadonlyArray<PluginGeneratedTableInfo>,\n    outputDir: string,\n  ) => PluginTableGenerationResult;\n  /** Function to generate executor files */\n  executorGenerator: (\n    executors: ReadonlyArray<PluginExecutorInfoExtended>,\n    outputDir: string,\n    tableGenerationResult: PluginTableGenerationResult,\n    sourceTableInfoMap: Map<string, SourceTableInfo>,\n    configPath: string,\n  ) => string[];\n}\n\n/**\n * Parameters for extending a TailorDB table\n */\nexport interface ExtendTableParams {\n  /** The original TailorDB table to extend */\n  originalTable: TailorAnyDBType;\n  /** New fields to add to the table */\n  extendFields: Record<string, unknown>;\n  /** The ID of the plugin extending the table */\n  pluginId: string;\n}\n\n/**\n * Copy metadata from original table to extended table.\n * Preserves files, settings, permissions, indexes, and plugins.\n * @param original - The original TailorDB table with metadata\n * @param extended - The newly created extended table\n * @returns The extended table with copied metadata\n */\nfunction copyMetadataToExtendedTable(\n  original: TailorAnyDBType,\n  extended: TailorAnyDBType,\n): TailorAnyDBType {\n  let result = extended;\n\n  // Copy description\n  if (original._description) {\n    result = result.description(original._description);\n  }\n\n  // Copy files metadata\n  const metadata = original.metadata;\n  if (Object.keys(metadata.files).length > 0) {\n    result = result.files(metadata.files);\n  }\n\n  // Copy settings/features (excluding pluralForm which is set during construction)\n  if (metadata.settings) {\n    const { pluralForm: _pluralForm, ...features } = metadata.settings;\n    if (Object.keys(features).length > 0) {\n      result = result.features(\n        features as typeof features & { aggregation?: true; bulkUpsert?: true },\n      );\n    }\n  }\n\n  // Copy permissions from metadata\n  // Zod schema operand types are wider unions than the configure layer's discriminated PermissionCondition,\n  // so type assertions are needed here.\n  if (metadata.permissions.record) {\n    result = result.permission(metadata.permissions.record as TailorTypePermission);\n  }\n  if (metadata.permissions.gql) {\n    result = result.gqlPermission(metadata.permissions.gql as TailorTypeGqlPermission);\n  }\n\n  // Copy indexes from metadata (indexes are stored in metadata, not as a direct property)\n  if (metadata.indexes && Object.keys(metadata.indexes).length > 0) {\n    const indexDefs = Object.entries(metadata.indexes).map(([name, def]) => ({\n      name,\n      // Cast fields array to tuple type (IndexDef expects [T, T, ...T[]])\n      fields: def.fields as [string, string, ...string[]],\n      unique: def.unique,\n    }));\n    result = result.indexes(...indexDefs);\n  }\n\n  if (metadata.typeHook) {\n    result = result.hooks(metadata.typeHook as TypeHook<Record<string, TailorAnyDBField>>);\n  }\n  if (metadata.typeValidate) {\n    result = result.validate(\n      metadata.typeValidate as TypeValidateFn<Record<string, TailorAnyDBField>>,\n    );\n  }\n\n  // Copy plugins (but don't re-process them)\n  if (original.plugins.length > 0) {\n    for (const plugin of original.plugins) {\n      // Use type assertion as plugin ID is dynamic at runtime\n      result = result.plugin({\n        [plugin.pluginId]: plugin.config,\n      });\n    }\n  }\n\n  return result;\n}\n"],"mappings":"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"}