@querypanel/node-sdk 1.0.25 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +23 -0
  2. package/dist/cjs/__tests__/ingest.test.d.ts +5 -0
  3. package/dist/cjs/__tests__/ingest.test.d.ts.map +1 -0
  4. package/dist/cjs/__tests__/ingest.test.js +95 -0
  5. package/dist/cjs/__tests__/ingest.test.js.map +1 -0
  6. package/dist/cjs/adapters/clickhouse.d.ts +48 -0
  7. package/dist/cjs/adapters/clickhouse.d.ts.map +1 -0
  8. package/dist/cjs/adapters/clickhouse.js +284 -0
  9. package/dist/cjs/adapters/clickhouse.js.map +1 -0
  10. package/dist/cjs/adapters/introspection.spec.d.ts +2 -0
  11. package/dist/cjs/adapters/introspection.spec.d.ts.map +1 -0
  12. package/dist/cjs/adapters/introspection.spec.js +192 -0
  13. package/dist/cjs/adapters/introspection.spec.js.map +1 -0
  14. package/dist/cjs/adapters/postgres.d.ts +46 -0
  15. package/dist/cjs/adapters/postgres.d.ts.map +1 -0
  16. package/dist/cjs/adapters/postgres.js +457 -0
  17. package/dist/cjs/adapters/postgres.js.map +1 -0
  18. package/dist/cjs/adapters/postgres.spec.d.ts +2 -0
  19. package/dist/cjs/adapters/postgres.spec.d.ts.map +1 -0
  20. package/dist/cjs/adapters/postgres.spec.js +37 -0
  21. package/dist/cjs/adapters/postgres.spec.js.map +1 -0
  22. package/dist/cjs/adapters/types.d.ts +38 -0
  23. package/dist/cjs/adapters/types.d.ts.map +1 -0
  24. package/dist/cjs/adapters/types.js +3 -0
  25. package/dist/cjs/adapters/types.js.map +1 -0
  26. package/dist/cjs/anonymize.spec.d.ts +2 -0
  27. package/dist/cjs/anonymize.spec.d.ts.map +1 -0
  28. package/dist/cjs/anonymize.spec.js +78 -0
  29. package/dist/cjs/anonymize.spec.js.map +1 -0
  30. package/dist/cjs/clickhouseClient.spec.d.ts +2 -0
  31. package/dist/cjs/clickhouseClient.spec.d.ts.map +1 -0
  32. package/dist/cjs/clickhouseClient.spec.js +286 -0
  33. package/dist/cjs/clickhouseClient.spec.js.map +1 -0
  34. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.d.ts +2 -0
  35. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.d.ts.map +1 -0
  36. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.js +119 -0
  37. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.js.map +1 -0
  38. package/dist/cjs/connectors/base.d.ts +13 -0
  39. package/dist/cjs/connectors/base.d.ts.map +1 -0
  40. package/dist/cjs/connectors/base.js +3 -0
  41. package/dist/cjs/connectors/base.js.map +1 -0
  42. package/dist/cjs/connectors/clickhouse.d.ts +53 -0
  43. package/dist/cjs/connectors/clickhouse.d.ts.map +1 -0
  44. package/dist/cjs/connectors/clickhouse.js +270 -0
  45. package/dist/cjs/connectors/clickhouse.js.map +1 -0
  46. package/dist/cjs/index.d.ts +490 -0
  47. package/dist/cjs/index.d.ts.map +1 -0
  48. package/dist/cjs/index.js +843 -0
  49. package/dist/cjs/index.js.map +1 -0
  50. package/dist/cjs/index.test.d.ts +2 -0
  51. package/dist/cjs/index.test.d.ts.map +1 -0
  52. package/dist/cjs/index.test.js +185 -0
  53. package/dist/cjs/index.test.js.map +1 -0
  54. package/dist/cjs/introspectV3.d.ts +45 -0
  55. package/dist/cjs/introspectV3.d.ts.map +1 -0
  56. package/dist/cjs/introspectV3.js +99 -0
  57. package/dist/cjs/introspectV3.js.map +1 -0
  58. package/dist/cjs/multidb.spec.d.ts +2 -0
  59. package/dist/cjs/multidb.spec.d.ts.map +1 -0
  60. package/dist/cjs/multidb.spec.js +76 -0
  61. package/dist/cjs/multidb.spec.js.map +1 -0
  62. package/dist/cjs/package.json +1 -0
  63. package/dist/cjs/schema/types.d.ts +73 -0
  64. package/dist/cjs/schema/types.d.ts.map +1 -0
  65. package/dist/cjs/schema/types.js +3 -0
  66. package/dist/cjs/schema/types.js.map +1 -0
  67. package/dist/cjs/tenant-isolation.spec.d.ts +2 -0
  68. package/dist/cjs/tenant-isolation.spec.d.ts.map +1 -0
  69. package/dist/cjs/tenant-isolation.spec.js +420 -0
  70. package/dist/cjs/tenant-isolation.spec.js.map +1 -0
  71. package/dist/cjs/utils/clickhouse.d.ts +9 -0
  72. package/dist/cjs/utils/clickhouse.d.ts.map +1 -0
  73. package/dist/cjs/utils/clickhouse.js +99 -0
  74. package/dist/cjs/utils/clickhouse.js.map +1 -0
  75. package/dist/esm/adapters/clickhouse.d.ts +48 -0
  76. package/dist/esm/adapters/clickhouse.d.ts.map +1 -0
  77. package/dist/esm/adapters/clickhouse.js +280 -0
  78. package/dist/esm/adapters/clickhouse.js.map +1 -0
  79. package/dist/esm/adapters/introspection.spec.d.ts +2 -0
  80. package/dist/esm/adapters/introspection.spec.d.ts.map +1 -0
  81. package/dist/esm/adapters/introspection.spec.js +190 -0
  82. package/dist/esm/adapters/introspection.spec.js.map +1 -0
  83. package/dist/esm/adapters/postgres.d.ts +46 -0
  84. package/dist/esm/adapters/postgres.d.ts.map +1 -0
  85. package/dist/esm/adapters/postgres.js +453 -0
  86. package/dist/esm/adapters/postgres.js.map +1 -0
  87. package/dist/esm/adapters/postgres.spec.d.ts +2 -0
  88. package/dist/esm/adapters/postgres.spec.d.ts.map +1 -0
  89. package/dist/esm/adapters/postgres.spec.js +35 -0
  90. package/dist/esm/adapters/postgres.spec.js.map +1 -0
  91. package/dist/esm/adapters/types.d.ts +38 -0
  92. package/dist/esm/adapters/types.d.ts.map +1 -0
  93. package/dist/esm/adapters/types.js +2 -0
  94. package/dist/esm/adapters/types.js.map +1 -0
  95. package/dist/esm/anonymize.spec.d.ts +2 -0
  96. package/dist/esm/anonymize.spec.d.ts.map +1 -0
  97. package/dist/esm/anonymize.spec.js +76 -0
  98. package/dist/esm/anonymize.spec.js.map +1 -0
  99. package/dist/esm/clickhouseClient.spec.d.ts +2 -0
  100. package/dist/esm/clickhouseClient.spec.d.ts.map +1 -0
  101. package/dist/esm/clickhouseClient.spec.js +281 -0
  102. package/dist/esm/clickhouseClient.spec.js.map +1 -0
  103. package/dist/esm/connectors/base.d.ts +14 -0
  104. package/dist/esm/connectors/base.d.ts.map +1 -0
  105. package/dist/esm/connectors/base.js +2 -0
  106. package/dist/esm/connectors/base.js.map +1 -0
  107. package/dist/esm/connectors/clickhouse.d.ts +35 -0
  108. package/dist/esm/connectors/clickhouse.d.ts.map +1 -0
  109. package/dist/esm/connectors/clickhouse.js +281 -0
  110. package/dist/esm/connectors/clickhouse.js.map +1 -0
  111. package/dist/esm/index.d.ts +490 -0
  112. package/dist/esm/index.d.ts.map +1 -0
  113. package/dist/esm/index.js +838 -0
  114. package/dist/esm/index.js.map +1 -0
  115. package/dist/esm/index.test.d.ts +2 -0
  116. package/dist/esm/index.test.d.ts.map +1 -0
  117. package/dist/esm/index.test.js +183 -0
  118. package/dist/esm/index.test.js.map +1 -0
  119. package/dist/esm/introspectV3.d.ts +45 -0
  120. package/dist/esm/introspectV3.d.ts.map +1 -0
  121. package/dist/esm/introspectV3.js +96 -0
  122. package/dist/esm/introspectV3.js.map +1 -0
  123. package/dist/esm/multidb.spec.d.ts +2 -0
  124. package/dist/esm/multidb.spec.d.ts.map +1 -0
  125. package/dist/esm/multidb.spec.js +74 -0
  126. package/dist/esm/multidb.spec.js.map +1 -0
  127. package/dist/esm/schema/types.d.ts +73 -0
  128. package/dist/esm/schema/types.d.ts.map +1 -0
  129. package/dist/esm/schema/types.js +2 -0
  130. package/dist/esm/schema/types.js.map +1 -0
  131. package/dist/esm/tenant-isolation.spec.d.ts +2 -0
  132. package/dist/esm/tenant-isolation.spec.d.ts.map +1 -0
  133. package/dist/esm/tenant-isolation.spec.js +418 -0
  134. package/dist/esm/tenant-isolation.spec.js.map +1 -0
  135. package/dist/esm/utils/clickhouse.d.ts +9 -0
  136. package/dist/esm/utils/clickhouse.d.ts.map +1 -0
  137. package/dist/esm/utils/clickhouse.js +92 -0
  138. package/dist/esm/utils/clickhouse.js.map +1 -0
  139. package/package.json +73 -53
  140. package/dist/index.cjs +0 -1471
  141. package/dist/index.cjs.map +0 -1
  142. package/dist/index.d.cts +0 -468
  143. package/dist/index.d.ts +0 -468
  144. package/dist/index.js +0 -1443
  145. package/dist/index.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/clickhouse.ts","../src/adapters/clickhouse.ts","../src/adapters/postgres.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { importPKCS8, SignJWT } from \"jose\";\nimport {\n\tClickHouseAdapter,\n\ttype ClickHouseAdapterOptions,\n\ttype ClickHouseClientFn,\n} from \"./adapters/clickhouse\";\nimport {\n\tPostgresAdapter,\n\ttype PostgresAdapterOptions,\n\ttype PostgresClientFn,\n} from \"./adapters/postgres\";\nimport type { DatabaseAdapter, DatabaseDialect } from \"./adapters/types\";\nimport type { SchemaIntrospection } from \"./schema/types\";\n\nexport { ClickHouseAdapter, PostgresAdapter };\n\nexport type {\n\tClickHouseAdapterOptions,\n\tClickHouseClientFn,\n\tDatabaseAdapter,\n\tDatabaseDialect,\n\tPostgresAdapterOptions,\n\tPostgresClientFn,\n\tSchemaIntrospection,\n};\n\nexport type ParamValue = string | number | boolean | string[] | number[];\nexport type ParamRecord = Record<string, ParamValue>;\n\nexport interface ContextDocument {\n\tsource?: string;\n\tpageContent: string;\n\tmetadata?: Record<string, unknown>;\n\tscore?: number;\n}\n\nexport interface ChartEnvelope {\n\tvegaLiteSpec: Record<string, unknown> | null;\n\tnotes: string | null;\n}\n\nexport interface AskOptions {\n\ttenantId?: string;\n\tuserId?: string;\n\tscopes?: string[];\n\tdatabase?: string;\n\tlastError?: string;\n\tpreviousSql?: string;\n\tmaxRetry?: number;\n\tchartMaxRetries?: number;\n\tdisableAutoSync?: boolean;\n}\n\nexport interface AskResponse {\n\tsql: string;\n\tparams: ParamRecord;\n\tparamMetadata: Array<Record<string, unknown>>;\n\trationale?: string;\n\tdialect: string;\n\tqueryId?: string;\n\trows: Array<Record<string, unknown>>;\n\tfields: string[];\n\tchart: ChartEnvelope;\n\tcontext?: ContextDocument[];\n}\n\nexport interface SchemaSyncOptions {\n\ttenantId?: string;\n\tuserId?: string;\n\tscopes?: string[];\n\ttables?: string[];\n\tforce?: boolean;\n}\n\nexport interface KnowledgeBaseAnnotation {\n\tid: string;\n\torganization_id: string;\n\ttarget_identifier: string;\n\tcontent: string;\n\tcreated_by: string;\n\tupdated_by: string;\n\tcreated_at: string;\n\tupdated_at: string;\n}\n\nexport interface KnowledgeBaseAnnotationInput {\n\ttargetIdentifier: string;\n\tcontent: string;\n\tuserId: string;\n\ttenantId?: string;\n}\n\nexport interface KnowledgeBaseChunkTable {\n\ttable_name: string;\n\tgold_sql?: Array<{ sql: string; description?: string; name?: string }>;\n\tglossary?: Array<{ term: string; definition: string }>;\n}\n\nexport interface KnowledgeBaseChunkRequest {\n\tdatabase: string;\n\tdialect: string;\n\ttables: KnowledgeBaseChunkTable[];\n\ttenantId?: string;\n}\n\nexport interface KnowledgeBaseChunksResponse {\n\tsuccess: boolean;\n\tmessage: string;\n\tchunks: {\n\t\ttotal: number;\n\t\tgold_sql: number;\n\t\tglossary: number;\n\t\tchunks_with_annotations: number;\n\t};\n}\n\nexport interface SdkChart {\n\tid: string;\n\ttitle: string;\n\tdescription: string | null;\n\tsql: string;\n\tsql_params: Record<string, unknown> | null;\n\tvega_lite_spec: Record<string, unknown>;\n\tquery_id: string | null;\n\torganization_id: string | null;\n\ttenant_id: string | null;\n\tuser_id: string | null;\n\tcreated_at: string | null;\n\tupdated_at: string | null;\n\tactive?: boolean;\n\tdatabase?: string | null;\n}\n\nexport interface SdkActiveChart {\n\tid: string;\n\tchart_id: string;\n\torder: number | null;\n\tmeta: Record<string, unknown> | null;\n\torganization_id: string | null;\n\ttenant_id: string | null;\n\tuser_id: string | null;\n\tcreated_at: string | null;\n\tupdated_at: string | null;\n\tchart?: SdkChart | null;\n}\n\nexport interface ChartCreateInput {\n\ttitle: string;\n\tdescription?: string;\n\tsql: string;\n\tsql_params?: Record<string, unknown>;\n\tvega_lite_spec: Record<string, unknown>;\n\tquery_id?: string;\n\tdatabase?: string;\n}\n\nexport interface ChartUpdateInput {\n\ttitle?: string;\n\tdescription?: string;\n\tsql?: string;\n\tsql_params?: Record<string, unknown>;\n\tvega_lite_spec?: Record<string, unknown>;\n\tdatabase?: string;\n}\n\nexport interface ActiveChartCreateInput {\n\tchart_id: string;\n\torder?: number;\n\tmeta?: Record<string, unknown>;\n}\n\nexport interface ActiveChartUpdateInput {\n\tchart_id?: string;\n\torder?: number;\n\tmeta?: Record<string, unknown>;\n}\n\nexport interface PaginationQuery {\n\tpage?: number;\n\tlimit?: number;\n}\n\nexport interface PaginationInfo {\n\tpage: number;\n\tlimit: number;\n\ttotal: number;\n\ttotalPages: number;\n\thasNext: boolean;\n\thasPrev: boolean;\n}\n\nexport interface PaginatedResponse<T> {\n\tdata: T[];\n\tpagination: PaginationInfo;\n}\n\nexport interface ChartListOptions {\n\ttenantId?: string;\n\tuserId?: string;\n\tscopes?: string[];\n\tpagination?: PaginationQuery;\n\tsortBy?: \"title\" | \"user_id\" | \"created_at\" | \"updated_at\";\n\tsortDir?: \"asc\" | \"desc\";\n\ttitle?: string;\n\tuserFilter?: string;\n\tcreatedFrom?: string;\n\tcreatedTo?: string;\n\tupdatedFrom?: string;\n\tupdatedTo?: string;\n\tincludeData?: boolean;\n}\n\nexport interface ActiveChartListOptions extends ChartListOptions {\n\twithData?: boolean;\n}\n\nexport interface IngestResponse {\n\tsuccess: boolean;\n\tmessage: string;\n\tchunks: number;\n\tchunks_with_annotations: number;\n\tschema_id?: string;\n\tschema_hash?: string;\n\tdrift_detected?: boolean;\n\tskipped?: boolean;\n}\n\ninterface DatabaseMetadata {\n\tname: string;\n\tdialect: DatabaseDialect;\n\tdescription?: string;\n\ttags?: string[];\n\ttenantFieldName?: string;\n\ttenantFieldType?: string;\n\tenforceTenantIsolation?: boolean;\n}\n\ninterface SchemaIngestColumn {\n\tname: string;\n\tdata_type: string;\n\tis_primary_key: boolean;\n\tdescription: string;\n}\n\ninterface SchemaIngestTable {\n\ttable_name: string;\n\tdescription: string;\n\tcolumns: SchemaIngestColumn[];\n}\n\ninterface SchemaIngestRequest {\n\tdatabase: string;\n\tdialect: string;\n\ttables: SchemaIngestTable[];\n}\n\ninterface ServerQueryResponse {\n\tsuccess: boolean;\n\tsql: string;\n\tparams?: Array<Record<string, unknown>>;\n\tdialect: string;\n\trationale?: string;\n\tqueryId?: string;\n\tcontext?: ContextDocument[];\n}\n\ninterface ServerChartResponse {\n\tchart: Record<string, unknown> | null;\n\tnotes: string | null;\n}\n\ninterface RequestOptions {\n\ttenantId?: string;\n\tuserId?: string;\n\tscopes?: string[];\n}\n\nexport class QueryPanelSdkAPI {\n\tprivate readonly baseUrl: string;\n\tprivate readonly privateKey: string;\n\tprivate readonly organizationId: string;\n\tprivate readonly defaultTenantId?: string;\n\tprivate readonly additionalHeaders?: Record<string, string>;\n\tprivate readonly fetchImpl: typeof fetch;\n\tprivate cachedPrivateKey?: Awaited<ReturnType<typeof importPKCS8>>;\n\n\tprivate databases = new Map<string, DatabaseAdapter>();\n\tprivate databaseMetadata = new Map<string, DatabaseMetadata>();\n\tprivate defaultDatabase?: string;\n\tprivate lastSyncHashes = new Map<string, string>();\n\tprivate syncedDatabases = new Set<string>();\n\n\tconstructor(\n\t\tbaseUrl: string,\n\t\tprivateKey: string,\n\t\torganizationId: string,\n\t\toptions?: {\n\t\t\tdefaultTenantId?: string;\n\t\t\tadditionalHeaders?: Record<string, string>;\n\t\t\tfetch?: typeof fetch;\n\t\t},\n\t) {\n\t\tif (!baseUrl) {\n\t\t\tthrow new Error(\"Base URL is required\");\n\t\t}\n\t\tif (!privateKey) {\n\t\t\tthrow new Error(\"Private key is required\");\n\t\t}\n\t\tif (!organizationId) {\n\t\t\tthrow new Error(\"Organization ID is required\");\n\t\t}\n\n\t\tthis.baseUrl = baseUrl.replace(/\\/+$/, \"\");\n\t\tthis.privateKey = privateKey;\n\t\tthis.organizationId = organizationId;\n\t\tthis.defaultTenantId = options?.defaultTenantId;\n\t\tthis.additionalHeaders = options?.additionalHeaders;\n\t\tthis.fetchImpl = options?.fetch ?? globalThis.fetch;\n\n\t\tif (!this.fetchImpl) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Fetch implementation not found. Provide options.fetch or use Node 18+.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tattachClickhouse(\n\t\tname: string,\n\t\tclientFn: ClickHouseClientFn,\n\t\toptions?: ClickHouseAdapterOptions & {\n\t\t\tdescription?: string;\n\t\t\ttags?: string[];\n\t\t\ttenantFieldName?: string;\n\t\t\ttenantFieldType?: string;\n\t\t\tenforceTenantIsolation?: boolean;\n\t\t},\n\t): void {\n\t\tconst adapter = new ClickHouseAdapter(clientFn, options);\n\t\tthis.attachDatabase(name, adapter);\n\n\t\tconst metadata: DatabaseMetadata = {\n\t\t\tname,\n\t\t\tdialect: \"clickhouse\",\n\t\t\tdescription: options?.description,\n\t\t\ttags: options?.tags,\n\t\t\ttenantFieldName: options?.tenantFieldName,\n\t\t\ttenantFieldType: options?.tenantFieldType ?? \"String\",\n\t\t\tenforceTenantIsolation: options?.tenantFieldName\n\t\t\t\t? (options?.enforceTenantIsolation ?? true)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\tthis.databaseMetadata.set(name, metadata);\n\t}\n\n\tattachPostgres(\n\t\tname: string,\n\t\tclientFn: PostgresClientFn,\n\t\toptions?: PostgresAdapterOptions & {\n\t\t\tdescription?: string;\n\t\t\ttags?: string[];\n\t\t\ttenantFieldName?: string;\n\t\t\tenforceTenantIsolation?: boolean;\n\t\t},\n\t): void {\n\t\tconst adapter = new PostgresAdapter(clientFn, options);\n\t\tthis.attachDatabase(name, adapter);\n\n\t\tconst metadata: DatabaseMetadata = {\n\t\t\tname,\n\t\t\tdialect: \"postgres\",\n\t\t\tdescription: options?.description,\n\t\t\ttags: options?.tags,\n\t\t\ttenantFieldName: options?.tenantFieldName,\n\t\t\tenforceTenantIsolation: options?.tenantFieldName\n\t\t\t\t? (options?.enforceTenantIsolation ?? true)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\tthis.databaseMetadata.set(name, metadata);\n\t}\n\n\tattachDatabase(name: string, adapter: DatabaseAdapter): void {\n\t\tthis.databases.set(name, adapter);\n\t\tif (!this.defaultDatabase) {\n\t\t\tthis.defaultDatabase = name;\n\t\t}\n\t}\n\n\tasync syncSchema(\n\t\tdatabaseName: string,\n\t\toptions: SchemaSyncOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<IngestResponse> {\n\t\tconst tenantId = this.resolveTenantId(options.tenantId);\n\t\tconst adapter = this.getDatabase(databaseName);\n\t\tconst introspection = await adapter.introspect(\n\t\t\toptions.tables ? { tables: options.tables } : undefined,\n\t\t);\n\n\t\tconst payload = this.buildSchemaRequest(\n\t\t\tdatabaseName,\n\t\t\tadapter,\n\t\t\tintrospection,\n\t\t);\n\t\tconst hash = this.hashSchemaRequest(payload);\n\t\tconst previousHash = this.lastSyncHashes.get(databaseName);\n\n\t\tif (!options.force && previousHash === hash) {\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: \"Schema unchanged; skipping ingestion\",\n\t\t\t\tchunks: 0,\n\t\t\t\tchunks_with_annotations: 0,\n\t\t\t\tschema_hash: hash,\n\t\t\t\tskipped: true,\n\t\t\t};\n\t\t}\n\n\t\t// Generate a session id so backend telemetry can correlate all work for this sync\n\t\tconst sessionId = randomUUID();\n\n\t\tconst response = await this.post<IngestResponse>(\n\t\t\t\"/ingest\",\n\t\t\tpayload,\n\t\t\ttenantId,\n\t\t\toptions.userId,\n\t\t\toptions.scopes,\n\t\t\tsignal,\n\t\t\tsessionId,\n\t\t);\n\n\t\tthis.lastSyncHashes.set(databaseName, hash);\n\t\tthis.syncedDatabases.add(databaseName);\n\n\t\treturn response;\n\t}\n\n\tasync ingestKnowledgeBaseChunks(\n\t\tpayload: KnowledgeBaseChunkRequest,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<KnowledgeBaseChunksResponse> {\n\t\tconst tenantId = this.resolveTenantId(\n\t\t\tpayload.tenantId ?? options?.tenantId,\n\t\t);\n\t\treturn await this.post<KnowledgeBaseChunksResponse>(\n\t\t\t\"/knowledge-base/chunks\",\n\t\t\t{\n\t\t\t\torganization_id: this.organizationId,\n\t\t\t\ttenant_id: tenantId,\n\t\t\t\tdatabase: payload.database,\n\t\t\t\tdialect: payload.dialect,\n\t\t\t\ttables: payload.tables,\n\t\t\t},\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync introspect(\n\t\tdatabaseName: string,\n\t\ttables?: string[],\n\t): Promise<SchemaIntrospection> {\n\t\tconst adapter = this.getDatabase(databaseName);\n\t\treturn await adapter.introspect(tables ? { tables } : undefined);\n\t}\n\n\tasync ask(\n\t\tquestion: string,\n\t\toptions: AskOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<AskResponse> {\n\t\tconst tenantId = this.resolveTenantId(options.tenantId);\n\n\t\tawait this.ensureSchemasSynced(\n\t\t\ttenantId,\n\t\t\toptions.userId,\n\t\t\toptions.scopes,\n\t\t\toptions.disableAutoSync,\n\t\t);\n\n\t\tconst sessionId = randomUUID();\n\n\t\tconst queryResponse = await this.post<ServerQueryResponse>(\n\t\t\t\"/query\",\n\t\t\t{\n\t\t\t\tquestion,\n\t\t\t\t...(options.lastError ? { last_error: options.lastError } : {}),\n\t\t\t\t...(options.previousSql ? { previous_sql: options.previousSql } : {}),\n\t\t\t\t...(options.maxRetry ? { max_retry: options.maxRetry } : {}),\n\t\t\t},\n\t\t\ttenantId,\n\t\t\toptions.userId,\n\t\t\toptions.scopes,\n\t\t\tsignal,\n\t\t\tsessionId,\n\t\t);\n\n\t\tconst databaseName = options.database ?? this.defaultDatabase;\n\t\tif (!databaseName) {\n\t\t\tthrow new Error(\n\t\t\t\t\"No database attached. Call attachPostgres/attachClickhouse first.\",\n\t\t\t);\n\t\t}\n\n\t\tconst adapter = this.getDatabase(databaseName);\n\t\tconst paramMetadata = Array.isArray(queryResponse.params)\n\t\t\t? queryResponse.params\n\t\t\t: [];\n\t\tconst paramValues = this.mapGeneratedParams(paramMetadata);\n\n\t\tconst metadata = this.databaseMetadata.get(databaseName);\n\t\tif (metadata) {\n\t\t\tqueryResponse.sql = this.ensureTenantIsolation(\n\t\t\t\tqueryResponse.sql,\n\t\t\t\tparamValues,\n\t\t\t\tmetadata,\n\t\t\t\ttenantId,\n\t\t\t);\n\t\t}\n\n\t\tawait adapter.validate(queryResponse.sql, paramValues);\n\t\tconst execution = await adapter.execute(queryResponse.sql, paramValues);\n\t\tconst rows = execution.rows ?? [];\n\n\t\tlet chart: ChartEnvelope = {\n\t\t\tvegaLiteSpec: null,\n\t\t\tnotes: rows.length === 0 ? \"Query returned no rows.\" : null,\n\t\t};\n\n\t\tif (rows.length > 0) {\n\t\t\tconst chartResponse = await this.post<ServerChartResponse>(\n\t\t\t\t\"/chart\",\n\t\t\t\t{\n\t\t\t\t\tquestion,\n\t\t\t\t\tsql: queryResponse.sql,\n\t\t\t\t\trationale: queryResponse.rationale,\n\t\t\t\t\tfields: execution.fields,\n\t\t\t\t\trows: anonymizeResults(rows),\n\t\t\t\t\tmax_retries: options.chartMaxRetries ?? 3,\n\t\t\t\t\tquery_id: queryResponse.queryId,\n\t\t\t\t},\n\t\t\t\ttenantId,\n\t\t\t\toptions.userId,\n\t\t\t\toptions.scopes,\n\t\t\t\tsignal,\n\t\t\t\tsessionId,\n\t\t\t);\n\n\t\t\tchart = {\n\t\t\t\tvegaLiteSpec: chartResponse.chart\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t...chartResponse.chart,\n\t\t\t\t\t\t\tdata: { values: rows },\n\t\t\t\t\t\t}\n\t\t\t\t\t: null,\n\t\t\t\tnotes: chartResponse.notes,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tsql: queryResponse.sql,\n\t\t\tparams: paramValues,\n\t\t\tparamMetadata,\n\t\t\trationale: queryResponse.rationale,\n\t\t\tdialect: queryResponse.dialect,\n\t\t\tqueryId: queryResponse.queryId,\n\t\t\trows,\n\t\t\tfields: execution.fields,\n\t\t\tchart,\n\t\t\tcontext: queryResponse.context,\n\t\t};\n\t}\n\n\tasync upsertAnnotation(\n\t\tinput: KnowledgeBaseAnnotationInput,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<KnowledgeBaseAnnotation> {\n\t\tconst tenantId = this.resolveTenantId(input.tenantId ?? options?.tenantId);\n\t\tconst response = await this.post<{\n\t\t\tsuccess: boolean;\n\t\t\tannotation: KnowledgeBaseAnnotation;\n\t\t}>(\n\t\t\t\"/knowledge-base/annotations\",\n\t\t\t{\n\t\t\t\torganization_id: this.organizationId,\n\t\t\t\ttenant_id: tenantId,\n\t\t\t\ttarget_identifier: input.targetIdentifier,\n\t\t\t\tcontent: input.content,\n\t\t\t\tuser_id: input.userId,\n\t\t\t},\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\n\t\treturn response.annotation;\n\t}\n\n\tasync listAnnotations(\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<KnowledgeBaseAnnotation[]> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tconst response = await this.get<{\n\t\t\tsuccess: boolean;\n\t\t\tannotations: KnowledgeBaseAnnotation[];\n\t\t}>(\n\t\t\t\"/knowledge-base/annotations\",\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\n\t\treturn response.annotations;\n\t}\n\n\tasync getAnnotation(\n\t\ttargetIdentifier: string,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<KnowledgeBaseAnnotation | null> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tconst response = await this.get<{\n\t\t\tsuccess: boolean;\n\t\t\tannotation: KnowledgeBaseAnnotation;\n\t\t}>(\n\t\t\t`/knowledge-base/annotations/${encodeURIComponent(targetIdentifier)}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t).catch((error: any) => {\n\t\t\tif (error?.status === 404) {\n\t\t\t\treturn { success: false, annotation: null as any };\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\n\t\treturn response.annotation ?? null;\n\t}\n\n\tasync deleteAnnotation(\n\t\ttargetIdentifier: string,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<void> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tawait this.delete(\n\t\t\t`/knowledge-base/annotations/${encodeURIComponent(targetIdentifier)}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync createChart(\n\t\tbody: ChartCreateInput,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<SdkChart> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\treturn await this.post<SdkChart>(\n\t\t\t\"/charts\",\n\t\t\tbody,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync listCharts(\n\t\toptions?: ChartListOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<PaginatedResponse<SdkChart>> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tconst params = new URLSearchParams();\n\t\tif (options?.pagination?.page)\n\t\t\tparams.set(\"page\", `${options.pagination.page}`);\n\t\tif (options?.pagination?.limit)\n\t\t\tparams.set(\"limit\", `${options.pagination.limit}`);\n\t\tif (options?.sortBy) params.set(\"sort_by\", options.sortBy);\n\t\tif (options?.sortDir) params.set(\"sort_dir\", options.sortDir);\n\t\tif (options?.title) params.set(\"title\", options.title);\n\t\tif (options?.userFilter) params.set(\"user_id\", options.userFilter);\n\t\tif (options?.createdFrom) params.set(\"created_from\", options.createdFrom);\n\t\tif (options?.createdTo) params.set(\"created_to\", options.createdTo);\n\t\tif (options?.updatedFrom) params.set(\"updated_from\", options.updatedFrom);\n\t\tif (options?.updatedTo) params.set(\"updated_to\", options.updatedTo);\n\n\t\tconst response = await this.get<PaginatedResponse<SdkChart>>(\n\t\t\t`/charts${params.toString() ? `?${params.toString()}` : \"\"}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\n\t\tif (options?.includeData) {\n\t\t\tresponse.data = await Promise.all(\n\t\t\t\tresponse.data.map(async (chart) => ({\n\t\t\t\t\t...chart,\n\t\t\t\t\tvega_lite_spec: {\n\t\t\t\t\t\t...chart.vega_lite_spec,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tvalues: await this.runSafeQueryOnClient(\n\t\t\t\t\t\t\t\tchart.sql,\n\t\t\t\t\t\t\t\tchart.database ?? undefined,\n\t\t\t\t\t\t\t\t(chart.sql_params as ParamRecord | null) ?? undefined,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t})),\n\t\t\t);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\tasync getChart(\n\t\tid: string,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<SdkChart> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tconst chart = await this.get<SdkChart>(\n\t\t\t`/charts/${encodeURIComponent(id)}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\n\t\treturn {\n\t\t\t...chart,\n\t\t\tvega_lite_spec: {\n\t\t\t\t...chart.vega_lite_spec,\n\t\t\t\tdata: {\n\t\t\t\t\tvalues: await this.runSafeQueryOnClient(\n\t\t\t\t\t\tchart.sql,\n\t\t\t\t\t\tchart.database ?? undefined,\n\t\t\t\t\t\t(chart.sql_params as ParamRecord | null) ?? undefined,\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync updateChart(\n\t\tid: string,\n\t\tbody: ChartUpdateInput,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<SdkChart> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\treturn await this.put<SdkChart>(\n\t\t\t`/charts/${encodeURIComponent(id)}`,\n\t\t\tbody,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync deleteChart(\n\t\tid: string,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<void> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tawait this.delete(\n\t\t\t`/charts/${encodeURIComponent(id)}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync createActiveChart(\n\t\tbody: ActiveChartCreateInput,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<SdkActiveChart> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\treturn await this.post<SdkActiveChart>(\n\t\t\t\"/active-charts\",\n\t\t\tbody,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync listActiveCharts(\n\t\toptions?: ActiveChartListOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<PaginatedResponse<SdkActiveChart>> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tconst params = new URLSearchParams();\n\t\tif (options?.pagination?.page)\n\t\t\tparams.set(\"page\", `${options.pagination.page}`);\n\t\tif (options?.pagination?.limit)\n\t\t\tparams.set(\"limit\", `${options.pagination.limit}`);\n\t\tif (options?.sortBy) params.set(\"sort_by\", options.sortBy);\n\t\tif (options?.sortDir) params.set(\"sort_dir\", options.sortDir);\n\t\tif (options?.title) params.set(\"name\", options.title);\n\t\tif (options?.userFilter) params.set(\"user_id\", options.userFilter);\n\t\tif (options?.createdFrom) params.set(\"created_from\", options.createdFrom);\n\t\tif (options?.createdTo) params.set(\"created_to\", options.createdTo);\n\t\tif (options?.updatedFrom) params.set(\"updated_from\", options.updatedFrom);\n\t\tif (options?.updatedTo) params.set(\"updated_to\", options.updatedTo);\n\n\t\tconst response = await this.get<PaginatedResponse<SdkActiveChart>>(\n\t\t\t`/active-charts${params.toString() ? `?${params.toString()}` : \"\"}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\n\t\tif (options?.withData) {\n\t\t\tresponse.data = await Promise.all(\n\t\t\t\tresponse.data.map(async (active) => ({\n\t\t\t\t\t...active,\n\t\t\t\t\tchart: active.chart\n\t\t\t\t\t\t? await this.getChart(active.chart_id, options, signal)\n\t\t\t\t\t\t: null,\n\t\t\t\t})),\n\t\t\t);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\tasync getActiveChart(\n\t\tid: string,\n\t\toptions?: ActiveChartListOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<SdkActiveChart> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tconst active = await this.get<SdkActiveChart>(\n\t\t\t`/active-charts/${encodeURIComponent(id)}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\n\t\tif (options?.withData && active.chart_id) {\n\t\t\treturn {\n\t\t\t\t...active,\n\t\t\t\tchart: await this.getChart(active.chart_id, options, signal),\n\t\t\t};\n\t\t}\n\n\t\treturn active;\n\t}\n\n\tasync updateActiveChart(\n\t\tid: string,\n\t\tbody: ActiveChartUpdateInput,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<SdkActiveChart> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\treturn await this.put<SdkActiveChart>(\n\t\t\t`/active-charts/${encodeURIComponent(id)}`,\n\t\t\tbody,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tasync deleteActiveChart(\n\t\tid: string,\n\t\toptions?: RequestOptions,\n\t\tsignal?: AbortSignal,\n\t): Promise<void> {\n\t\tconst tenantId = this.resolveTenantId(options?.tenantId);\n\t\tawait this.delete(\n\t\t\t`/active-charts/${encodeURIComponent(id)}`,\n\t\t\ttenantId,\n\t\t\toptions?.userId,\n\t\t\toptions?.scopes,\n\t\t\tsignal,\n\t\t);\n\t}\n\n\tprivate getDatabase(name?: string): DatabaseAdapter {\n\t\tconst dbName = name ?? this.defaultDatabase;\n\t\tif (!dbName) {\n\t\t\tthrow new Error(\"No database attached.\");\n\t\t}\n\t\tconst adapter = this.databases.get(dbName);\n\t\tif (!adapter) {\n\t\t\tthrow new Error(\n\t\t\t\t`Database '${dbName}' not found. Attached: ${Array.from(\n\t\t\t\t\tthis.databases.keys(),\n\t\t\t\t).join(\", \")}`,\n\t\t\t);\n\t\t}\n\t\treturn adapter;\n\t}\n\n\tprivate async ensureSchemasSynced(\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t\tdisableAutoSync?: boolean,\n\t): Promise<void> {\n\t\tif (disableAutoSync) return;\n\t\tconst unsynced = Array.from(this.databases.keys()).filter(\n\t\t\t(name) => !this.syncedDatabases.has(name),\n\t\t);\n\t\tawait Promise.all(\n\t\t\tunsynced.map((name) =>\n\t\t\t\tthis.syncSchema(name, { tenantId, userId, scopes }).catch((error) => {\n\t\t\t\t\tconsole.warn(`Failed to sync schema for ${name}:`, error);\n\t\t\t\t}),\n\t\t\t),\n\t\t);\n\t}\n\n\tprivate resolveTenantId(tenantId?: string): string {\n\t\tconst resolved = tenantId ?? this.defaultTenantId;\n\t\tif (!resolved) {\n\t\t\tthrow new Error(\n\t\t\t\t\"tenantId is required. Provide it per request or via defaultTenantId option.\",\n\t\t\t);\n\t\t}\n\t\treturn resolved;\n\t}\n\n\tprivate async headers(\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t\tincludeJson: boolean = true,\n\t\tsessionId?: string,\n\t): Promise<Record<string, string>> {\n\t\tconst token = await this.generateJWT(tenantId, userId, scopes);\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\tAccept: \"application/json\",\n\t\t};\n\t\tif (includeJson) {\n\t\t\theaders[\"Content-Type\"] = \"application/json\";\n\t\t}\n\t\tif (sessionId) {\n\t\t\theaders[\"x-session-id\"] = sessionId;\n\t\t}\n\t\tif (this.additionalHeaders) {\n\t\t\tObject.assign(headers, this.additionalHeaders);\n\t\t}\n\t\treturn headers;\n\t}\n\n\tprivate async request<T>(path: string, init: RequestInit): Promise<T> {\n\t\tconst response = await this.fetchImpl(`${this.baseUrl}${path}`, init);\n\t\tconst text = await response.text();\n\t\tlet json: any;\n\t\ttry {\n\t\t\tjson = text ? JSON.parse(text) : undefined;\n\t\t} catch {\n\t\t\tjson = undefined;\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tconst error = new Error(\n\t\t\t\tjson?.error || response.statusText || \"Request failed\",\n\t\t\t);\n\t\t\t(error as any).status = response.status;\n\t\t\tif (json?.details) (error as any).details = json.details;\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn json as T;\n\t}\n\n\tprivate async get<T>(\n\t\tpath: string,\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t\tsignal?: AbortSignal,\n\t\tsessionId?: string,\n\t): Promise<T> {\n\t\treturn await this.request<T>(path, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: await this.headers(tenantId, userId, scopes, false, sessionId),\n\t\t\tsignal,\n\t\t});\n\t}\n\n\tprivate async post<T>(\n\t\tpath: string,\n\t\tbody: unknown,\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t\tsignal?: AbortSignal,\n\t\tsessionId?: string,\n\t): Promise<T> {\n\t\treturn await this.request<T>(path, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: await this.headers(tenantId, userId, scopes, true, sessionId),\n\t\t\tbody: JSON.stringify(body ?? {}),\n\t\t\tsignal,\n\t\t});\n\t}\n\n\tprivate async put<T>(\n\t\tpath: string,\n\t\tbody: unknown,\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t\tsignal?: AbortSignal,\n\t\tsessionId?: string,\n\t): Promise<T> {\n\t\treturn await this.request<T>(path, {\n\t\t\tmethod: \"PUT\",\n\t\t\theaders: await this.headers(tenantId, userId, scopes, true, sessionId),\n\t\t\tbody: JSON.stringify(body ?? {}),\n\t\t\tsignal,\n\t\t});\n\t}\n\n\tprivate async delete<T = void>(\n\t\tpath: string,\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t\tsignal?: AbortSignal,\n\t\tsessionId?: string,\n\t): Promise<T> {\n\t\treturn await this.request<T>(path, {\n\t\t\tmethod: \"DELETE\",\n\t\t\theaders: await this.headers(tenantId, userId, scopes, false, sessionId),\n\t\t\tsignal,\n\t\t});\n\t}\n\n\tprivate async generateJWT(\n\t\ttenantId: string,\n\t\tuserId?: string,\n\t\tscopes?: string[],\n\t): Promise<string> {\n\t\tif (!this.cachedPrivateKey) {\n\t\t\tthis.cachedPrivateKey = await importPKCS8(this.privateKey, \"RS256\");\n\t\t}\n\n\t\tconst payload: Record<string, unknown> = {\n\t\t\torganizationId: this.organizationId,\n\t\t\ttenantId,\n\t\t};\n\n\t\tif (userId) payload.userId = userId;\n\t\tif (scopes?.length) payload.scopes = scopes;\n\n\t\treturn await new SignJWT(payload)\n\t\t\t.setProtectedHeader({ alg: \"RS256\" })\n\t\t\t.setIssuedAt()\n\t\t\t.setExpirationTime(\"1h\")\n\t\t\t.sign(this.cachedPrivateKey);\n\t}\n\n\tprivate buildSchemaRequest(\n\t\tdatabaseName: string,\n\t\tadapter: DatabaseAdapter,\n\t\tintrospection: SchemaIntrospection,\n\t): SchemaIngestRequest {\n\t\tconst dialect = adapter.getDialect();\n\t\tconst tables: SchemaIngestTable[] = introspection.tables.map((table) => ({\n\t\t\ttable_name: table.name,\n\t\t\tdescription: table.comment ?? `Table ${table.name}`,\n\t\t\tcolumns: table.columns.map((column) => ({\n\t\t\t\tname: column.name,\n\t\t\t\tdata_type: column.rawType ?? column.type,\n\t\t\t\tis_primary_key: Boolean(column.isPrimaryKey),\n\t\t\t\tdescription: column.comment ?? \"\",\n\t\t\t})),\n\t\t}));\n\n\t\treturn {\n\t\t\tdatabase: databaseName,\n\t\t\tdialect,\n\t\t\ttables,\n\t\t};\n\t}\n\n\tprivate hashSchemaRequest(payload: SchemaIngestRequest): string {\n\t\tconst normalized = payload.tables.map((table) => ({\n\t\t\tname: table.table_name,\n\t\t\tcolumns: table.columns.map((column) => ({\n\t\t\t\tname: column.name,\n\t\t\t\ttype: column.data_type,\n\t\t\t\tprimary: column.is_primary_key,\n\t\t\t})),\n\t\t}));\n\t\treturn createHash(\"sha256\")\n\t\t\t.update(JSON.stringify(normalized))\n\t\t\t.digest(\"hex\");\n\t}\n\n\tprivate mapGeneratedParams(\n\t\tparams: Array<Record<string, unknown>>,\n\t): ParamRecord {\n\t\tconst record: ParamRecord = {};\n\n\t\tparams.forEach((param, index) => {\n\t\t\tconst value = param.value as ParamValue | undefined;\n\t\t\tif (value === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nameCandidate =\n\t\t\t\t(typeof param.name === \"string\" && param.name.trim()) ||\n\t\t\t\t(typeof param.placeholder === \"string\" && param.placeholder.trim()) ||\n\t\t\t\t(typeof param.position === \"number\" && String(param.position)) ||\n\t\t\t\tString(index + 1);\n\t\t\tconst key = nameCandidate.replace(/[{}:$]/g, \"\").trim();\n\t\t\trecord[key] = value;\n\t\t});\n\n\t\treturn record;\n\t}\n\n\tprivate ensureTenantIsolation(\n\t\tsql: string,\n\t\tparams: ParamRecord,\n\t\tmetadata: DatabaseMetadata,\n\t\ttenantId: string,\n\t): string {\n\t\tif (\n\t\t\t!metadata.tenantFieldName ||\n\t\t\tmetadata.enforceTenantIsolation === false\n\t\t) {\n\t\t\treturn sql;\n\t\t}\n\n\t\tconst tenantField = metadata.tenantFieldName;\n\t\tconst paramKey = tenantField;\n\t\tparams[paramKey] = tenantId;\n\n\t\tconst normalizedSql = sql.toLowerCase();\n\t\tif (normalizedSql.includes(tenantField.toLowerCase())) {\n\t\t\treturn sql;\n\t\t}\n\n\t\tconst tenantPredicate =\n\t\t\tmetadata.dialect === \"clickhouse\"\n\t\t\t\t? `${tenantField} = {${tenantField}:${metadata.tenantFieldType ?? \"String\"}}`\n\t\t\t\t: `${tenantField} = '${tenantId}'`;\n\n\t\tif (/\\bwhere\\b/i.test(sql)) {\n\t\t\treturn sql.replace(\n\t\t\t\t/\\bwhere\\b/i,\n\t\t\t\t(match) => `${match} ${tenantPredicate} AND `,\n\t\t\t);\n\t\t}\n\n\t\treturn `${sql} WHERE ${tenantPredicate}`;\n\t}\n\n\tprivate async runSafeQueryOnClient(\n\t\tsql: string,\n\t\tdatabase?: string,\n\t\tparams?: ParamRecord,\n\t): Promise<Array<Record<string, unknown>>> {\n\t\ttry {\n\t\t\tconst adapter = this.getDatabase(database);\n\t\t\tconst result = await adapter.execute(sql, params);\n\t\t\treturn result.rows;\n\t\t} catch (error) {\n\t\t\tconsole.warn(\n\t\t\t\t`Failed to execute SQL locally for database '${database}':`,\n\t\t\t\terror,\n\t\t\t);\n\t\t\treturn [];\n\t\t}\n\t}\n}\n\nexport function anonymizeResults(\n\trows: Array<Record<string, unknown>>,\n): Array<Record<string, string>> {\n\tif (!rows?.length) return [];\n\treturn rows.map((row) => {\n\t\tconst masked: Record<string, string> = {};\n\t\tObject.entries(row).forEach(([key, value]) => {\n\t\t\tif (value === null) masked[key] = \"null\";\n\t\t\telse if (Array.isArray(value)) masked[key] = \"array\";\n\t\t\telse masked[key] = typeof value;\n\t\t});\n\t\treturn masked;\n\t});\n}\n","const WRAPPER_REGEX =\n /^(Nullable|LowCardinality|SimpleAggregateFunction)\\((.+)\\)$/i;\n\nexport function isNullableType(type: string): boolean {\n return /Nullable\\s*\\(/i.test(type);\n}\n\nexport function unwrapTypeModifiers(type: string): string {\n let current = type.trim();\n let match = WRAPPER_REGEX.exec(current);\n while (match) {\n const inner = match[2];\n if (!inner) {\n break;\n }\n current = inner.trim();\n match = WRAPPER_REGEX.exec(current);\n }\n return current;\n}\n\nexport function extractPrecisionScale(type: string): {\n precision?: number;\n scale?: number;\n} {\n const unwrapped = unwrapTypeModifiers(type);\n const decimalMatch = unwrapped.match(/Decimal(?:\\d+)?\\((\\d+)\\s*,\\s*(\\d+)\\)/i);\n if (!decimalMatch) return {};\n const precision = decimalMatch[1];\n const scale = decimalMatch[2];\n if (!precision || !scale) return {};\n return {\n precision: Number.parseInt(precision, 10),\n scale: Number.parseInt(scale, 10),\n };\n}\n\nexport function extractFixedStringLength(type: string): number | undefined {\n const unwrapped = unwrapTypeModifiers(type);\n const match = unwrapped.match(/^(?:FixedString|StringFixed)\\((\\d+)\\)$/i);\n if (!match) return undefined;\n const length = match[1];\n if (!length) return undefined;\n return Number.parseInt(length, 10);\n}\n\nexport function parseKeyExpression(expression?: string | null): string[] {\n if (!expression) return [];\n let value = expression.trim();\n if (!value) return [];\n if (/^tuple\\s*\\(/i.test(value) && value.endsWith(\")\")) {\n value = value.replace(/^tuple\\s*\\(/i, \"\").replace(/\\)$/, \"\");\n }\n\n const columns: string[] = [];\n let depth = 0;\n let token = \"\";\n for (const ch of value) {\n if (ch === \"(\") {\n depth += 1;\n token += ch;\n continue;\n }\n if (ch === \")\") {\n depth = Math.max(0, depth - 1);\n token += ch;\n continue;\n }\n if (ch === \",\" && depth === 0) {\n const col = token.trim();\n if (col) columns.push(stripWrapper(col));\n token = \"\";\n continue;\n }\n token += ch;\n }\n const last = token.trim();\n if (last) columns.push(stripWrapper(last));\n return columns.filter(Boolean);\n}\n\nfunction stripWrapper(value: string): string {\n const noQuotes = stripQuotes(value);\n const withoutTicks = noQuotes.replace(/`/g, \"\").trim();\n const parts = withoutTicks.split(\".\");\n return parts[parts.length - 1]?.trim() ?? \"\";\n}\n\nfunction stripQuotes(value: string): string {\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n return value;\n}\n","import type {\n ColumnSchema,\n IntrospectOptions,\n SchemaIntrospection,\n TableSchema,\n} from \"../schema/types\";\nimport {\n extractFixedStringLength,\n extractPrecisionScale,\n isNullableType,\n parseKeyExpression,\n unwrapTypeModifiers,\n} from \"../utils/clickhouse\";\nimport type { DatabaseAdapter, DatabaseExecutionResult } from \"./types\";\n\ntype QueryParams = {\n query: string;\n format?: string;\n};\n\ntype ClickHouseSettings = Record<string, unknown>;\ntype Row = Record<string, unknown>;\n\nexport interface ClickHouseAdapterOptions {\n /** Optional logical database name used in introspection metadata. */\n database?: string;\n /** Override the default response format used for query execution. */\n defaultFormat?: QueryParams[\"format\"];\n /**\n * Optional database kind label. Defaults to \"clickhouse\" but allows\n * sub-classing/custom branding if needed.\n */\n kind?: SchemaIntrospection[\"db\"][\"kind\"];\n /**\n * Optional allow-list of table names.\n * When specified, introspection and queries are restricted to these tables only.\n * ClickHouse tables are not schema-qualified, so just provide table names.\n */\n allowedTables?: string[];\n}\n\nexport type ClickHouseQueryResult = { json: () => Promise<unknown> };\n\nexport type ClickHouseClientFn = (\n params: QueryParams & {\n query_params?: Record<string, unknown>;\n clickhouse_settings?: ClickHouseSettings;\n },\n) => Promise<ClickHouseQueryResult | Array<Record<string, unknown>> | Row[]>;\n\ninterface QueryOptions {\n params?: Record<string, unknown>;\n format?: QueryParams[\"format\"];\n settings?: Record<string, unknown>;\n}\n\ntype TableRow = {\n name: string;\n engine: string;\n comment: string | null;\n total_rows: string | number | null;\n total_bytes: string | number | null;\n primary_key: string | null;\n sorting_key?: string | null;\n};\n\ntype ColumnRow = {\n table: string;\n name: string;\n type: string;\n position: number;\n default_kind: string | null;\n default_expression: string | null;\n comment: string | null;\n is_in_primary_key: string | number | null;\n};\n\nexport class ClickHouseAdapter implements DatabaseAdapter {\n private readonly databaseName: string;\n private readonly defaultFormat: QueryParams[\"format\"];\n private readonly kind: SchemaIntrospection[\"db\"][\"kind\"];\n private readonly allowedTables?: string[];\n\n constructor(\n private readonly clientFn: ClickHouseClientFn,\n options: ClickHouseAdapterOptions = {},\n ) {\n this.databaseName = options.database ?? \"default\";\n this.defaultFormat = options.defaultFormat ?? \"JSONEachRow\";\n this.kind = options.kind ?? \"clickhouse\";\n if (options.allowedTables) {\n this.allowedTables = normalizeTableFilter(options.allowedTables);\n }\n }\n\n async execute(\n sql: string,\n params?: Record<string, string | number | boolean | string[] | number[]>,\n ): Promise<DatabaseExecutionResult> {\n // Validate query against allowed tables if restrictions are in place\n if (this.allowedTables) {\n this.validateQueryTables(sql);\n }\n\n const queryOptions: QueryOptions = {\n format: this.defaultFormat,\n };\n if (params) {\n queryOptions.params = params;\n }\n\n const rows = await this.query<Record<string, unknown>>(sql, queryOptions);\n const fields = rows.length > 0 ? Object.keys(rows[0] ?? {}) : [];\n return { fields, rows };\n }\n\n async validate(\n sql: string,\n params?: Record<string, string | number | boolean | string[] | number[]>,\n ): Promise<void> {\n const queryOptions: QueryOptions = {\n format: this.defaultFormat,\n };\n if (params) {\n queryOptions.params = params;\n }\n\n await this.query(`EXPLAIN ${sql}`, queryOptions);\n }\n\n getDialect() {\n return \"clickhouse\" as const;\n }\n\n async introspect(options?: IntrospectOptions): Promise<SchemaIntrospection> {\n // Use adapter-level allowedTables if no specific tables provided in options\n const tablesToIntrospect = options?.tables\n ? normalizeTableFilter(options.tables)\n : this.allowedTables;\n const allowTables = tablesToIntrospect ?? [];\n const hasFilter = allowTables.length > 0;\n const queryParams: Record<string, unknown> = {\n db: this.databaseName,\n };\n if (hasFilter) {\n queryParams.tables = allowTables;\n }\n\n const filterClause = hasFilter ? \" AND name IN {tables:Array(String)}\" : \"\";\n const tables = await this.query<TableRow>(\n `SELECT name, engine, comment, total_rows, total_bytes, primary_key, sorting_key\n FROM system.tables\n WHERE database = {db:String}${filterClause}\n ORDER BY name`,\n { params: queryParams },\n );\n\n const columnFilterClause = hasFilter\n ? \" AND table IN {tables:Array(String)}\"\n : \"\";\n const columns = await this.query<ColumnRow>(\n `SELECT table, name, type, position, default_kind, default_expression, comment, is_in_primary_key\n FROM system.columns\n WHERE database = {db:String}${columnFilterClause}\n ORDER BY table, position`,\n { params: queryParams },\n );\n\n const columnsByTable = new Map<string, ColumnSchema[]>();\n for (const rawColumn of columns) {\n const list = columnsByTable.get(rawColumn.table) ?? [];\n list.push(transformColumnRow(rawColumn));\n columnsByTable.set(rawColumn.table, list);\n }\n\n const tableSchemas: TableSchema[] = tables.map((table) => {\n const tableColumns = columnsByTable.get(table.name) ?? [];\n const primaryKeyColumns = parseKeyExpression(table.primary_key);\n const totalRows = toNumber(table.total_rows);\n const totalBytes = toNumber(table.total_bytes);\n\n for (const column of tableColumns) {\n column.isPrimaryKey =\n column.isPrimaryKey || primaryKeyColumns.includes(column.name);\n }\n\n const indexes = primaryKeyColumns.length\n ? [\n {\n name: \"primary_key\",\n columns: primaryKeyColumns,\n unique: true,\n type: \"PRIMARY KEY\",\n ...(table.primary_key ? { definition: table.primary_key } : {}),\n },\n ]\n : [];\n\n const constraints = primaryKeyColumns.length\n ? [\n {\n name: \"primary_key\",\n type: \"PRIMARY KEY\",\n columns: primaryKeyColumns,\n },\n ]\n : [];\n\n const base: TableSchema = {\n name: table.name,\n schema: this.databaseName,\n type: asTableType(table.engine),\n engine: table.engine,\n columns: tableColumns,\n indexes,\n constraints,\n };\n\n const comment = sanitize(table.comment);\n if (comment !== undefined) {\n base.comment = comment;\n }\n\n const statistics = buildTableStatistics(totalRows, totalBytes);\n if (statistics) {\n base.statistics = statistics;\n }\n\n return base;\n });\n\n return {\n db: {\n kind: this.kind,\n name: this.databaseName,\n },\n tables: tableSchemas,\n introspectedAt: new Date().toISOString(),\n };\n }\n\n /**\n * Validate that the SQL query only references allowed tables.\n * This is a basic validation that extracts table-like patterns from the query.\n */\n private validateQueryTables(sql: string): void {\n if (!this.allowedTables || this.allowedTables.length === 0) {\n return;\n }\n\n const allowedSet = new Set(this.allowedTables);\n\n // Extract potential table references from SQL\n // This regex looks for identifiers after FROM/JOIN keywords\n // ClickHouse may use database.table notation\n const tablePattern =\n /(?:FROM|JOIN)\\s+(?:FINAL\\s+)?(?:(?:[a-zA-Z_][a-zA-Z0-9_]*)\\.)?([\"'`]?[a-zA-Z_][a-zA-Z0-9_]*[\"'`]?)/gi;\n const matches = sql.matchAll(tablePattern);\n\n for (const match of matches) {\n const table = match[1]?.replace(/[\"'`]/g, \"\");\n if (table) {\n if (!allowedSet.has(table)) {\n throw new Error(\n `Query references table \"${table}\" which is not in the allowed tables list`,\n );\n }\n }\n }\n }\n\n async close(): Promise<void> {\n // No-op: lifecycle of the underlying client is controlled by the caller.\n }\n\n private async query<T>(sql: string, options?: QueryOptions): Promise<T[]> {\n const params: QueryParams & {\n query_params?: Record<string, unknown>;\n clickhouse_settings?: ClickHouseSettings;\n } = {\n query: sql,\n };\n\n const format = options?.format ?? this.defaultFormat;\n if (format !== undefined) {\n params.format = format;\n }\n\n if (options?.params) {\n params.query_params = options.params;\n }\n\n if (options?.settings) {\n params.clickhouse_settings = options.settings as ClickHouseSettings;\n }\n\n const result = await this.clientFn(params);\n return this.extractRows<T>(result);\n }\n\n private async extractRows<T>(\n result: ClickHouseQueryResult | Array<Record<string, unknown>> | Row[],\n ): Promise<T[]> {\n if (Array.isArray(result)) {\n return result as T[];\n }\n\n if (\n result &&\n typeof (result as ClickHouseQueryResult).json === \"function\"\n ) {\n const payload = await (result as ClickHouseQueryResult).json();\n return normalizePayload<T>(payload);\n }\n\n return [];\n }\n}\n\nfunction normalizePayload<T>(payload: unknown): T[] {\n if (Array.isArray(payload)) {\n return payload as T[];\n }\n if (payload && typeof payload === \"object\") {\n const maybeData = (payload as { data?: unknown }).data;\n if (Array.isArray(maybeData)) {\n return maybeData as T[];\n }\n }\n return [];\n}\n\nfunction normalizeTableFilter(tables?: string[] | null): string[] {\n if (!tables?.length) return [];\n const seen = new Set<string>();\n const normalized: string[] = [];\n for (const table of tables) {\n if (!table) continue;\n const trimmed = table.trim();\n if (!trimmed) continue;\n const parts = trimmed.split(\".\");\n const tableName = parts[parts.length - 1];\n if (!tableName || seen.has(tableName)) continue;\n seen.add(tableName);\n normalized.push(tableName);\n }\n return normalized;\n}\n\nfunction transformColumnRow(row: ColumnRow): ColumnSchema {\n const nullable = isNullableType(row.type);\n const unwrappedType = unwrapTypeModifiers(row.type);\n const { precision, scale } = extractPrecisionScale(row.type);\n const maxLength = extractFixedStringLength(row.type);\n\n const column: ColumnSchema = {\n name: row.name,\n type: unwrappedType,\n rawType: row.type,\n nullable,\n isPrimaryKey: Boolean(toNumber(row.is_in_primary_key)),\n isForeignKey: false,\n };\n\n const defaultKind = sanitize(row.default_kind);\n if (defaultKind !== undefined) column.defaultKind = defaultKind;\n\n const defaultExpression = sanitize(row.default_expression);\n if (defaultExpression !== undefined) {\n column.defaultExpression = defaultExpression;\n }\n\n const comment = sanitize(row.comment);\n if (comment !== undefined) column.comment = comment;\n\n if (maxLength !== undefined) column.maxLength = maxLength;\n if (precision !== undefined) column.precision = precision;\n if (scale !== undefined) column.scale = scale;\n\n return column;\n}\n\nfunction asTableType(engine: unknown): TableSchema[\"type\"] {\n if (typeof engine === \"string\") {\n const normalized = engine.toLowerCase();\n // ClickHouse view engines: View, MaterializedView, LiveView\n if (normalized.includes(\"view\")) {\n return \"view\";\n }\n }\n return \"table\";\n}\n\nfunction buildTableStatistics(\n totalRows?: number,\n totalBytes?: number,\n): TableSchema[\"statistics\"] | undefined {\n if (totalRows === undefined && totalBytes === undefined) return undefined;\n const stats: NonNullable<TableSchema[\"statistics\"]> = {};\n if (totalRows !== undefined) stats.totalRows = totalRows;\n if (totalBytes !== undefined) stats.totalBytes = totalBytes;\n return stats;\n}\n\nfunction sanitize(value: unknown): string | undefined {\n if (value === null || value === undefined) return undefined;\n const trimmed = String(value).trim();\n return trimmed.length ? trimmed : undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n if (value === null || value === undefined) return undefined;\n if (typeof value === \"number\") return value;\n const parsed = Number.parseFloat(String(value));\n return Number.isNaN(parsed) ? undefined : parsed;\n}\n","import type {\n\tColumnSchema,\n\tConstraintSchema,\n\tIndexSchema,\n\tIntrospectOptions,\n\tSchemaIntrospection,\n\tTableSchema,\n} from \"../schema/types\";\nimport type { DatabaseAdapter, DatabaseExecutionResult } from \"./types\";\n\nexport interface PostgresQueryResult {\n\trows: Array<Record<string, unknown>>;\n\tfields: Array<{ name: string }>;\n}\n\nexport type PostgresClientFn = (\n\tsql: string,\n\tparams?: unknown[],\n) => Promise<PostgresQueryResult>;\n\nexport interface PostgresAdapterOptions {\n\t/** Logical database name used in introspection metadata. */\n\tdatabase?: string;\n\t/** Schema to assume when a table is provided without qualification. */\n\tdefaultSchema?: string;\n\t/** Optional database kind label. Defaults to \"postgres\". */\n\tkind?: SchemaIntrospection[\"db\"][\"kind\"];\n\t/**\n\t * Optional allow-list of table names (schema-qualified or bare).\n\t * When specified, introspection and queries are restricted to these tables only.\n\t */\n\tallowedTables?: string[];\n}\n\ntype TableRow = {\n\ttable_name: string;\n\tschema_name: string;\n\ttable_type: string;\n\tcomment: string | null;\n\ttotal_rows: number | null;\n\ttotal_bytes: number | null;\n};\n\ntype ColumnRow = {\n\ttable_name: string;\n\ttable_schema: string;\n\tcolumn_name: string;\n\tdata_type: string;\n\tudt_name: string | null;\n\tis_nullable: string;\n\tcolumn_default: string | null;\n\tcharacter_maximum_length: number | null;\n\tnumeric_precision: number | null;\n\tnumeric_scale: number | null;\n\tordinal_position: number;\n\tdescription: string | null;\n};\n\ntype ConstraintRow = {\n\ttable_schema: string;\n\ttable_name: string;\n\tconstraint_name: string;\n\tconstraint_type: string;\n\tcolumn_name: string | null;\n\tforeign_table_schema: string | null;\n\tforeign_table_name: string | null;\n\tforeign_column_name: string | null;\n};\n\ntype IndexRow = {\n\tschema_name: string;\n\ttable_name: string;\n\tindex_name: string;\n\tindisunique: boolean;\n\tcolumn_names: string[] | null;\n\tdefinition: string | null;\n};\n\ninterface NormalizedTable {\n\tschema: string;\n\ttable: string;\n}\n\nexport class PostgresAdapter implements DatabaseAdapter {\n\tprivate readonly databaseName: string;\n\tprivate readonly defaultSchema: string;\n\tprivate readonly kind: SchemaIntrospection[\"db\"][\"kind\"];\n\tprivate readonly allowedTables?: NormalizedTable[];\n\n\tconstructor(\n\t\tprivate readonly clientFn: PostgresClientFn,\n\t\toptions: PostgresAdapterOptions = {},\n\t) {\n\t\tthis.databaseName = options.database ?? \"postgres\";\n\t\tthis.defaultSchema = options.defaultSchema ?? \"public\";\n\t\tthis.kind = options.kind ?? \"postgres\";\n\t\tif (options.allowedTables) {\n\t\t\tthis.allowedTables = normalizeTableFilter(\n\t\t\t\toptions.allowedTables,\n\t\t\t\tthis.defaultSchema,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync execute(\n\t\tsql: string,\n\t\tparams?: Record<string, string | number | boolean | string[] | number[]>,\n\t): Promise<DatabaseExecutionResult> {\n\t\t// Validate query against allowed tables if restrictions are in place\n\t\tif (this.allowedTables) {\n\t\t\tthis.validateQueryTables(sql);\n\t\t}\n\n\t\t// Convert named params to positional array for PostgreSQL\n\t\tlet paramArray: unknown[] | undefined;\n\t\tif (params) {\n\t\t\tparamArray = this.convertNamedToPositionalParams(params);\n\t\t}\n\n\t\tconst result = await this.clientFn(sql, paramArray);\n\t\tconst fields = result.fields.map((f) => f.name);\n\t\treturn { fields, rows: result.rows };\n\t}\n\n\t/**\n\t * Validate that the SQL query only references allowed tables.\n\t * This is a basic validation that extracts table-like patterns from the query.\n\t */\n\tprivate validateQueryTables(sql: string): void {\n\t\tif (!this.allowedTables || this.allowedTables.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst allowedSet = new Set(\n\t\t\tthis.allowedTables.map((t) => tableKey(t.schema, t.table)),\n\t\t);\n\n\t\t// Extract potential table references from SQL\n\t\t// This regex looks for identifiers after FROM/JOIN keywords\n\t\tconst tablePattern =\n\t\t\t/(?:FROM|JOIN)\\s+(?:ONLY\\s+)?(?:([a-zA-Z_][a-zA-Z0-9_]*)\\.)?([\"']?[a-zA-Z_][a-zA-Z0-9_]*[\"']?)/gi;\n\t\tconst matches = sql.matchAll(tablePattern);\n\n\t\tfor (const match of matches) {\n\t\t\tconst schema = match[1] ?? this.defaultSchema;\n\t\t\tconst table = match[2]?.replace(/['\"]/g, \"\");\n\t\t\tif (table) {\n\t\t\t\tconst key = tableKey(schema, table);\n\t\t\t\tif (!allowedSet.has(key)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Query references table \"${schema}.${table}\" which is not in the allowed tables list`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Convert named params to positional array for PostgreSQL\n\t * PostgreSQL expects $1, $2, $3 in SQL and an array of values [val1, val2, val3]\n\t *\n\t * Supports two formats:\n\t * 1. Numeric keys: { '1': 'value1', '2': 'value2' } - maps directly to $1, $2\n\t * 2. Named keys: { 'tenant_id': 'value' } - values extracted in alphabetical order\n\t * 3. Mixed: { '1': 'value1', 'tenant_id': 'value' } - numeric keys first, then named keys\n\t */\n\tprivate convertNamedToPositionalParams(\n\t\tparams: Record<string, string | number | boolean | string[] | number[]>,\n\t): unknown[] {\n\t\t// Separate numeric and named keys\n\t\tconst numericKeys = Object.keys(params)\n\t\t\t.filter((k) => /^\\d+$/.test(k))\n\t\t\t.map((k) => Number.parseInt(k, 10))\n\t\t\t.sort((a, b) => a - b);\n\n\t\tconst namedKeys = Object.keys(params)\n\t\t\t.filter((k) => !/^\\d+$/.test(k))\n\t\t\t.sort(); // Alphabetical order for consistency\n\n\t\t// Build positional array\n\t\tconst positionalParams: unknown[] = [];\n\n\t\t// First, add values from numeric keys (in sorted order)\n\t\tfor (const key of numericKeys) {\n\t\t\tlet val: unknown = params[String(key)];\n\t\t\tif (typeof val === \"string\") {\n\t\t\t\t// Resolve placeholder tokens like `<tenant_id>` to their named values\n\t\t\t\tconst match = val.match(/^<([a-zA-Z0-9_]+)>$/);\n\t\t\t\tconst namedKey = match?.[1];\n\t\t\t\tif (namedKey && namedKey in params) {\n\t\t\t\t\tval = params[namedKey as keyof typeof params];\n\t\t\t\t}\n\t\t\t}\n\t\t\tpositionalParams.push(val);\n\t\t}\n\n\t\t// Then, add values from named keys (in alphabetical order)\n\t\t// This handles cases where tenant isolation adds named params like {'tenant_id': 'value'}\n\t\tfor (const key of namedKeys) {\n\t\t\tconst val = params[key];\n\t\t\tpositionalParams.push(val);\n\t\t}\n\n\t\treturn positionalParams;\n\t}\n\n\tasync validate(\n\t\tsql: string,\n\t\tparams?: Record<string, string | number | boolean | string[] | number[]>,\n\t): Promise<void> {\n\t\t// Convert named params to positional array for PostgreSQL\n\t\tlet paramArray: unknown[] | undefined;\n\t\tif (params) {\n\t\t\tparamArray = this.convertNamedToPositionalParams(params);\n\t\t}\n\n\t\tawait this.clientFn(`EXPLAIN ${sql}`, paramArray);\n\t}\n\n\tgetDialect() {\n\t\treturn \"postgres\" as const;\n\t}\n\n\tasync introspect(options?: IntrospectOptions): Promise<SchemaIntrospection> {\n\t\t// Use adapter-level allowedTables if no specific tables provided in options\n\t\tconst tablesToIntrospect = options?.tables\n\t\t\t? normalizeTableFilter(options.tables, this.defaultSchema)\n\t\t\t: this.allowedTables;\n\t\tconst normalizedTables = tablesToIntrospect ?? [];\n\n\t\tconst tablesResult = await this.clientFn(\n\t\t\tbuildTablesQuery(normalizedTables),\n\t\t);\n\t\tconst tableRows = tablesResult.rows as TableRow[];\n\n\t\tconst columnsResult = await this.clientFn(\n\t\t\tbuildColumnsQuery(normalizedTables),\n\t\t);\n\t\tconst columnRows = columnsResult.rows as ColumnRow[];\n\n\t\tconst constraintsResult = await this.clientFn(\n\t\t\tbuildConstraintsQuery(normalizedTables),\n\t\t);\n\t\tconst constraintRows = constraintsResult.rows as ConstraintRow[];\n\n\t\tconst indexesResult = await this.clientFn(\n\t\t\tbuildIndexesQuery(normalizedTables),\n\t\t);\n\t\tconst indexRows = indexesResult.rows as IndexRow[];\n\n\t\tconst tablesByKey = new Map<string, TableSchema>();\n\t\tconst columnsByKey = new Map<string, Map<string, ColumnSchema>>();\n\n\t\tfor (const row of tableRows) {\n\t\t\tconst key = tableKey(row.schema_name, row.table_name);\n\t\t\tconst statistics = buildTableStatistics(\n\t\t\t\ttoNumber(row.total_rows),\n\t\t\t\ttoNumber(row.total_bytes),\n\t\t\t);\n\n\t\t\tconst table: TableSchema = {\n\t\t\t\tname: row.table_name,\n\t\t\t\tschema: row.schema_name,\n\t\t\t\ttype: asTableType(row.table_type),\n\t\t\t\tcolumns: [],\n\t\t\t\tindexes: [],\n\t\t\t\tconstraints: [],\n\t\t\t};\n\n\t\t\tconst comment = sanitize(row.comment);\n\t\t\tif (comment !== undefined) {\n\t\t\t\ttable.comment = comment;\n\t\t\t}\n\t\t\tif (statistics) {\n\t\t\t\ttable.statistics = statistics;\n\t\t\t}\n\n\t\t\ttablesByKey.set(key, table);\n\t\t\tcolumnsByKey.set(key, new Map());\n\t\t}\n\n\t\tfor (const row of columnRows) {\n\t\t\tconst key = tableKey(row.table_schema, row.table_name);\n\t\t\tconst table = tablesByKey.get(key);\n\t\t\tif (!table) continue;\n\n\t\t\tconst column: ColumnSchema = {\n\t\t\t\tname: row.column_name,\n\t\t\t\ttype: row.data_type,\n\t\t\t\tnullable: row.is_nullable.toUpperCase() === \"YES\",\n\t\t\t\tisPrimaryKey: false,\n\t\t\t\tisForeignKey: false,\n\t\t\t};\n\n\t\t\tconst rawType = row.udt_name ?? undefined;\n\t\t\tif (rawType !== undefined) column.rawType = rawType;\n\n\t\t\tconst defaultExpression = sanitize(row.column_default);\n\t\t\tif (defaultExpression !== undefined)\n\t\t\t\tcolumn.defaultExpression = defaultExpression;\n\n\t\t\tconst comment = sanitize(row.description);\n\t\t\tif (comment !== undefined) column.comment = comment;\n\n\t\t\tconst maxLength = row.character_maximum_length ?? undefined;\n\t\t\tif (maxLength !== undefined) column.maxLength = maxLength;\n\n\t\t\tconst precision = row.numeric_precision ?? undefined;\n\t\t\tif (precision !== undefined) column.precision = precision;\n\n\t\t\tconst scale = row.numeric_scale ?? undefined;\n\t\t\tif (scale !== undefined) column.scale = scale;\n\n\t\t\ttable.columns.push(column);\n\t\t\tcolumnsByKey.get(key)?.set(row.column_name, column);\n\t\t}\n\n\t\tconst constraintGroups = groupConstraints(constraintRows);\n\t\tfor (const group of constraintGroups) {\n\t\t\tconst key = tableKey(group.table_schema, group.table_name);\n\t\t\tconst table = tablesByKey.get(key);\n\t\t\tif (!table) continue;\n\n\t\t\tconst constraint: ConstraintSchema = {\n\t\t\t\tname: group.constraint_name,\n\t\t\t\ttype: group.constraint_type,\n\t\t\t\tcolumns: [...group.columns],\n\t\t\t};\n\n\t\t\tif (group.type === \"FOREIGN KEY\") {\n\t\t\t\tif (group.foreign_table_name) {\n\t\t\t\t\tconst referencedTable = group.foreign_table_schema\n\t\t\t\t\t\t? `${group.foreign_table_schema}.${group.foreign_table_name}`\n\t\t\t\t\t\t: group.foreign_table_name;\n\t\t\t\t\tconstraint.referencedTable = referencedTable;\n\t\t\t\t}\n\t\t\t\tif (group.foreign_columns.length) {\n\t\t\t\t\tconstraint.referencedColumns = [...group.foreign_columns];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttable.constraints.push(constraint);\n\n\t\t\tfor (let index = 0; index < group.columns.length; index += 1) {\n\t\t\t\tconst columnName = group.columns[index];\n\t\t\t\tif (!columnName) continue;\n\t\t\t\tconst column = columnsByKey.get(key)?.get(columnName);\n\t\t\t\tif (!column) continue;\n\t\t\t\tif (group.type === \"PRIMARY KEY\") {\n\t\t\t\t\tcolumn.isPrimaryKey = true;\n\t\t\t\t}\n\t\t\t\tif (group.type === \"FOREIGN KEY\") {\n\t\t\t\t\tcolumn.isForeignKey = true;\n\t\t\t\t\tif (group.foreign_table_name) {\n\t\t\t\t\t\tcolumn.foreignKeyTable = group.foreign_table_schema\n\t\t\t\t\t\t\t? `${group.foreign_table_schema}.${group.foreign_table_name}`\n\t\t\t\t\t\t\t: group.foreign_table_name;\n\t\t\t\t\t}\n\t\t\t\t\tconst referencedColumn = group.foreign_columns[index];\n\t\t\t\t\tif (referencedColumn) {\n\t\t\t\t\t\tcolumn.foreignKeyColumn = referencedColumn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const row of indexRows) {\n\t\t\tconst key = tableKey(row.schema_name, row.table_name);\n\t\t\tconst table = tablesByKey.get(key);\n\t\t\tif (!table) continue;\n\t\t\tconst columns = coerceStringArray(row.column_names)\n\t\t\t\t.map((c) => c.trim())\n\t\t\t\t.filter(Boolean);\n\t\t\tconst index: IndexSchema = {\n\t\t\t\tname: row.index_name,\n\t\t\t\tcolumns,\n\t\t\t\tunique: Boolean(row.indisunique),\n\t\t\t\ttype: columns.length === 1 ? \"INDEX\" : \"COMPOSITE INDEX\",\n\t\t\t};\n\t\t\tconst definition = sanitize(row.definition);\n\t\t\tif (definition !== undefined) index.definition = definition;\n\t\t\ttable.indexes.push(index);\n\t\t}\n\n\t\tconst tables = Array.from(tablesByKey.values()).sort((a, b) => {\n\t\t\tif (a.schema === b.schema) {\n\t\t\t\treturn a.name.localeCompare(b.name);\n\t\t\t}\n\t\t\treturn a.schema.localeCompare(b.schema);\n\t\t});\n\n\t\treturn {\n\t\t\tdb: {\n\t\t\t\tkind: this.kind,\n\t\t\t\tname: this.databaseName,\n\t\t\t},\n\t\t\ttables,\n\t\t\tintrospectedAt: new Date().toISOString(),\n\t\t};\n\t}\n}\n\ninterface ConstraintGroup {\n\ttable_schema: string;\n\ttable_name: string;\n\tconstraint_name: string;\n\tconstraint_type: ConstraintSchema[\"type\"];\n\tcolumns: string[];\n\tforeign_table_schema?: string | null;\n\tforeign_table_name?: string | null;\n\tforeign_columns: string[];\n\ttype: ConstraintSchema[\"type\"];\n}\n\nfunction groupConstraints(rows: ConstraintRow[]): ConstraintGroup[] {\n\tconst groups = new Map<string, ConstraintGroup>();\n\n\tfor (const row of rows) {\n\t\tconst key = `${row.table_schema}.${row.table_name}.${row.constraint_name}`;\n\t\tlet group = groups.get(key);\n\t\tif (!group) {\n\t\t\tgroup = {\n\t\t\t\ttable_schema: row.table_schema,\n\t\t\t\ttable_name: row.table_name,\n\t\t\t\tconstraint_name: row.constraint_name,\n\t\t\t\tconstraint_type: row.constraint_type,\n\t\t\t\tcolumns: [],\n\t\t\t\tforeign_columns: [],\n\t\t\t\ttype: row.constraint_type,\n\t\t\t};\n\t\t\tgroups.set(key, group);\n\t\t}\n\n\t\tif (row.column_name) {\n\t\t\tgroup.columns.push(row.column_name);\n\t\t}\n\n\t\tif (row.constraint_type === \"FOREIGN KEY\") {\n\t\t\tgroup.foreign_table_schema = row.foreign_table_schema;\n\t\t\tgroup.foreign_table_name = row.foreign_table_name;\n\t\t\tif (row.foreign_column_name) {\n\t\t\t\tgroup.foreign_columns.push(row.foreign_column_name);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Array.from(groups.values());\n}\n\nfunction normalizeTableFilter(\n\ttables: string[] | undefined,\n\tdefaultSchema: string,\n): NormalizedTable[] {\n\tif (!tables?.length) return [];\n\tconst normalized: NormalizedTable[] = [];\n\tconst seen = new Set<string>();\n\n\tfor (const raw of tables) {\n\t\tif (!raw) continue;\n\t\tconst trimmed = raw.trim();\n\t\tif (!trimmed) continue;\n\t\tconst parts = trimmed.split(\".\");\n\t\tconst table = parts.pop() ?? \"\";\n\t\tconst schema = parts.pop() ?? defaultSchema;\n\t\tif (!isSafeIdentifier(schema) || !isSafeIdentifier(table)) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst key = tableKey(schema, table);\n\t\tif (seen.has(key)) continue;\n\t\tseen.add(key);\n\t\tnormalized.push({ schema, table });\n\t}\n\n\treturn normalized;\n}\n\nfunction buildTablesQuery(tables: NormalizedTable[]): string {\n\tconst filter = buildFilterClause(tables, \"n.nspname\", \"c.relname\");\n\treturn `SELECT\n c.relname AS table_name,\n n.nspname AS schema_name,\n CASE c.relkind\n WHEN 'r' THEN 'table'\n WHEN 'v' THEN 'view'\n WHEN 'm' THEN 'materialized_view'\n ELSE c.relkind::text\n END AS table_type,\n obj_description(c.oid) AS comment,\n c.reltuples AS total_rows,\n pg_total_relation_size(c.oid) AS total_bytes\n FROM pg_class c\n JOIN pg_namespace n ON n.oid = c.relnamespace\n WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')\n AND c.relkind IN ('r', 'v', 'm')\n ${filter}\n ORDER BY n.nspname, c.relname;`;\n}\n\nfunction buildColumnsQuery(tables: NormalizedTable[]): string {\n\tconst filter = buildFilterClause(\n\t\ttables,\n\t\t\"cols.table_schema\",\n\t\t\"cols.table_name\",\n\t);\n\treturn `SELECT\n cols.table_name,\n cols.table_schema,\n cols.column_name,\n cols.data_type,\n cols.udt_name,\n cols.is_nullable,\n cols.column_default,\n cols.character_maximum_length,\n cols.numeric_precision,\n cols.numeric_scale,\n cols.ordinal_position,\n pgd.description\n FROM information_schema.columns cols\n LEFT JOIN pg_catalog.pg_class c\n ON c.relname = cols.table_name\n AND c.relkind IN ('r', 'v', 'm')\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n LEFT JOIN pg_catalog.pg_attribute attr\n ON attr.attrelid = c.oid\n AND attr.attname = cols.column_name\n LEFT JOIN pg_catalog.pg_description pgd\n ON pgd.objoid = attr.attrelid AND pgd.objsubid = attr.attnum\n WHERE cols.table_schema NOT IN ('pg_catalog', 'information_schema')\n ${filter}\n ORDER BY cols.table_schema, cols.table_name, cols.ordinal_position;`;\n}\n\nfunction buildConstraintsQuery(tables: NormalizedTable[]): string {\n\tconst filter = buildFilterClause(tables, \"tc.table_schema\", \"tc.table_name\");\n\treturn `SELECT\n tc.table_schema,\n tc.table_name,\n tc.constraint_name,\n tc.constraint_type,\n kcu.column_name,\n ccu.table_schema AS foreign_table_schema,\n ccu.table_name AS foreign_table_name,\n ccu.column_name AS foreign_column_name\n FROM information_schema.table_constraints tc\n LEFT JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n LEFT JOIN information_schema.constraint_column_usage ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n WHERE tc.constraint_type IN ('PRIMARY KEY', 'UNIQUE', 'FOREIGN KEY')\n AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')\n ${filter}\n ORDER BY tc.table_schema, tc.table_name, tc.constraint_name, kcu.ordinal_position;`;\n}\n\nfunction buildIndexesQuery(tables: NormalizedTable[]): string {\n\tconst filter = buildFilterClause(tables, \"n.nspname\", \"c.relname\");\n\treturn `SELECT\n n.nspname AS schema_name,\n c.relname AS table_name,\n ci.relname AS index_name,\n idx.indisunique,\n array_remove(\n array_agg(pg_get_indexdef(idx.indexrelid, g.k, true) ORDER BY g.k),\n NULL\n ) AS column_names,\n pg_get_indexdef(idx.indexrelid) AS definition\n FROM pg_class c\n JOIN pg_namespace n ON n.oid = c.relnamespace\n JOIN pg_index idx ON idx.indrelid = c.oid\n JOIN pg_class ci ON ci.oid = idx.indexrelid\n JOIN LATERAL generate_subscripts(idx.indkey, 1) AS g(k) ON true\n WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')\n ${filter}\n GROUP BY n.nspname, c.relname, ci.relname, idx.indisunique, idx.indexrelid;`;\n}\n\nfunction buildFilterClause(\n\ttables: NormalizedTable[],\n\tschemaExpr: string,\n\ttableExpr: string,\n): string {\n\tif (!tables.length) return \"\";\n\tconst clauses = tables.map(({ schema, table }) => {\n\t\treturn `(${schemaExpr} = '${schema}' AND ${tableExpr} = '${table}')`;\n\t});\n\treturn `AND (${clauses.join(\" OR \")})`;\n}\n\nfunction tableKey(schema: string, table: string): string {\n\treturn `${schema}.${table}`;\n}\n\nfunction isSafeIdentifier(value: string): boolean {\n\treturn /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);\n}\n\nfunction asTableType(value: string): TableSchema[\"type\"] {\n\tconst normalized = value.toLowerCase();\n\tif (normalized.includes(\"view\")) {\n\t\treturn normalized.includes(\"materialized\") ? \"materialized_view\" : \"view\";\n\t}\n\treturn \"table\";\n}\n\nfunction buildTableStatistics(\n\ttotalRows?: number,\n\ttotalBytes?: number,\n): TableSchema[\"statistics\"] | undefined {\n\tif (totalRows === undefined && totalBytes === undefined) return undefined;\n\tconst stats: NonNullable<TableSchema[\"statistics\"]> = {};\n\tif (totalRows !== undefined) stats.totalRows = totalRows;\n\tif (totalBytes !== undefined) stats.totalBytes = totalBytes;\n\treturn stats;\n}\n\nfunction sanitize(value: unknown): string | undefined {\n\tif (value === null || value === undefined) return undefined;\n\tconst trimmed = String(value).trim();\n\treturn trimmed.length ? trimmed : undefined;\n}\n\nfunction toNumber(value: unknown): number | undefined {\n\tif (value === null || value === undefined) return undefined;\n\tif (typeof value === \"number\") return value;\n\tconst parsed = Number.parseFloat(String(value));\n\treturn Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction coerceStringArray(value: unknown): string[] {\n\tif (!value) return [];\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => String(entry));\n\t}\n\tconst text = String(value).trim();\n\tif (!text) return [];\n\tconst withoutBraces =\n\t\ttext.startsWith(\"{\") && text.endsWith(\"}\") ? text.slice(1, -1) : text;\n\tif (!withoutBraces) return [];\n\treturn withoutBraces\n\t\t.split(\",\")\n\t\t.map((part) => part.trim().replace(/^\"(.+)\"$/, \"$1\"))\n\t\t.filter(Boolean);\n}\n"],"mappings":"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","names":["normalizeTableFilter","buildTableStatistics","toNumber","asTableType","sanitize"]}