@databricks/appkit 0.4.0 → 0.5.0

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 (201) hide show
  1. package/CLAUDE.md +1 -0
  2. package/dist/analytics/analytics.d.ts +11 -1
  3. package/dist/analytics/analytics.d.ts.map +1 -1
  4. package/dist/analytics/analytics.js +12 -5
  5. package/dist/analytics/analytics.js.map +1 -1
  6. package/dist/appkit/package.js +1 -1
  7. package/dist/cache/index.js +11 -10
  8. package/dist/cache/index.js.map +1 -1
  9. package/dist/cache/storage/memory.js +4 -2
  10. package/dist/cache/storage/memory.js.map +1 -1
  11. package/dist/cache/storage/persistent.js +7 -0
  12. package/dist/cache/storage/persistent.js.map +1 -1
  13. package/dist/connectors/lakebase/client.js +8 -4
  14. package/dist/connectors/lakebase/client.js.map +1 -1
  15. package/dist/connectors/sql-warehouse/client.js +5 -2
  16. package/dist/connectors/sql-warehouse/client.js.map +1 -1
  17. package/dist/context/execution-context.d.ts +17 -0
  18. package/dist/context/execution-context.d.ts.map +1 -0
  19. package/dist/context/service-context.d.ts +21 -0
  20. package/dist/context/service-context.d.ts.map +1 -0
  21. package/dist/context/service-context.js +2 -6
  22. package/dist/context/service-context.js.map +1 -1
  23. package/dist/context/user-context.d.ts +29 -0
  24. package/dist/context/user-context.d.ts.map +1 -0
  25. package/dist/core/appkit.d.ts.map +1 -1
  26. package/dist/core/appkit.js +35 -12
  27. package/dist/core/appkit.js.map +1 -1
  28. package/dist/errors/authentication.js +3 -6
  29. package/dist/errors/authentication.js.map +1 -1
  30. package/dist/errors/base.js +4 -0
  31. package/dist/errors/base.js.map +1 -1
  32. package/dist/errors/configuration.js +3 -6
  33. package/dist/errors/configuration.js.map +1 -1
  34. package/dist/errors/connection.js +3 -6
  35. package/dist/errors/connection.js.map +1 -1
  36. package/dist/errors/execution.js +3 -6
  37. package/dist/errors/execution.js.map +1 -1
  38. package/dist/errors/initialization.js +3 -6
  39. package/dist/errors/initialization.js.map +1 -1
  40. package/dist/errors/server.js +3 -6
  41. package/dist/errors/server.js.map +1 -1
  42. package/dist/errors/tunnel.js +3 -6
  43. package/dist/errors/tunnel.js.map +1 -1
  44. package/dist/errors/validation.js +3 -6
  45. package/dist/errors/validation.js.map +1 -1
  46. package/dist/index.d.ts +2 -1
  47. package/dist/index.js +4 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/logging/wide-event-emitter.js +1 -3
  50. package/dist/logging/wide-event-emitter.js.map +1 -1
  51. package/dist/logging/wide-event.js +2 -0
  52. package/dist/logging/wide-event.js.map +1 -1
  53. package/dist/plugin/dev-reader.js +3 -6
  54. package/dist/plugin/dev-reader.js.map +1 -1
  55. package/dist/plugin/interceptors/retry.js +3 -0
  56. package/dist/plugin/interceptors/retry.js.map +1 -1
  57. package/dist/plugin/plugin.d.ts +10 -24
  58. package/dist/plugin/plugin.d.ts.map +1 -1
  59. package/dist/plugin/plugin.js +23 -30
  60. package/dist/plugin/plugin.js.map +1 -1
  61. package/dist/server/base-server.js +2 -0
  62. package/dist/server/base-server.js.map +1 -1
  63. package/dist/server/index.d.ts +23 -1
  64. package/dist/server/index.d.ts.map +1 -1
  65. package/dist/server/index.js +29 -13
  66. package/dist/server/index.js.map +1 -1
  67. package/dist/server/remote-tunnel/remote-tunnel-controller.js +30 -15
  68. package/dist/server/remote-tunnel/remote-tunnel-controller.js.map +1 -1
  69. package/dist/server/remote-tunnel/remote-tunnel-manager.js +5 -1
  70. package/dist/server/remote-tunnel/remote-tunnel-manager.js.map +1 -1
  71. package/dist/server/static-server.js +1 -0
  72. package/dist/server/static-server.js.map +1 -1
  73. package/dist/server/vite-dev-server.js +1 -0
  74. package/dist/server/vite-dev-server.js.map +1 -1
  75. package/dist/shared/src/plugin.d.ts +25 -1
  76. package/dist/shared/src/plugin.d.ts.map +1 -1
  77. package/dist/stream/arrow-stream-processor.js +5 -10
  78. package/dist/stream/arrow-stream-processor.js.map +1 -1
  79. package/dist/stream/buffers.js +7 -0
  80. package/dist/stream/buffers.js.map +1 -1
  81. package/dist/stream/stream-manager.js +5 -0
  82. package/dist/stream/stream-manager.js.map +1 -1
  83. package/dist/stream/stream-registry.js +1 -0
  84. package/dist/stream/stream-registry.js.map +1 -1
  85. package/dist/stream/validator.js +2 -6
  86. package/dist/stream/validator.js.map +1 -1
  87. package/dist/telemetry/noop.js +1 -0
  88. package/dist/telemetry/noop.js.map +1 -1
  89. package/dist/telemetry/telemetry-manager.js +4 -6
  90. package/dist/telemetry/telemetry-manager.js.map +1 -1
  91. package/dist/telemetry/telemetry-provider.js +3 -0
  92. package/dist/telemetry/telemetry-provider.js.map +1 -1
  93. package/dist/type-generator/spinner.js +9 -11
  94. package/dist/type-generator/spinner.js.map +1 -1
  95. package/docs/docs/api/appkit/Class.AppKitError/index.html +5 -3
  96. package/docs/docs/api/appkit/Class.AppKitError.md +7 -0
  97. package/docs/docs/api/appkit/Class.AuthenticationError/index.html +3 -3
  98. package/docs/docs/api/appkit/Class.ConfigurationError/index.html +3 -3
  99. package/docs/docs/api/appkit/Class.ConnectionError/index.html +3 -3
  100. package/docs/docs/api/appkit/Class.ExecutionError/index.html +3 -3
  101. package/docs/docs/api/appkit/Class.InitializationError/index.html +3 -3
  102. package/docs/docs/api/appkit/Class.Plugin/index.html +28 -21
  103. package/docs/docs/api/appkit/Class.Plugin.md +34 -34
  104. package/docs/docs/api/appkit/Class.ServerError/index.html +3 -3
  105. package/docs/docs/api/appkit/Class.TunnelError/index.html +3 -3
  106. package/docs/docs/api/appkit/Class.ValidationError/index.html +3 -3
  107. package/docs/docs/api/appkit/Function.appKitTypesPlugin/index.html +3 -3
  108. package/docs/docs/api/appkit/Function.createApp/index.html +4 -4
  109. package/docs/docs/api/appkit/Function.getExecutionContext/index.html +26 -0
  110. package/docs/docs/api/appkit/Function.getExecutionContext.md +19 -0
  111. package/docs/docs/api/appkit/Function.isSQLTypeMarker/index.html +4 -4
  112. package/docs/docs/api/appkit/Interface.BasePluginConfig/index.html +3 -3
  113. package/docs/docs/api/appkit/Interface.CacheConfig/index.html +3 -3
  114. package/docs/docs/api/appkit/Interface.ITelemetry/index.html +3 -3
  115. package/docs/docs/api/appkit/Interface.StreamExecutionSettings/index.html +3 -3
  116. package/docs/docs/api/appkit/Interface.TelemetryConfig/index.html +3 -3
  117. package/docs/docs/api/appkit/TypeAlias.IAppRouter/index.html +3 -3
  118. package/docs/docs/api/appkit/Variable.sql/index.html +3 -3
  119. package/docs/docs/api/appkit/index.html +4 -4
  120. package/docs/docs/api/appkit-ui/data/AreaChart/index.html +2 -2
  121. package/docs/docs/api/appkit-ui/data/BarChart/index.html +2 -2
  122. package/docs/docs/api/appkit-ui/data/DataTable/index.html +2 -2
  123. package/docs/docs/api/appkit-ui/data/DonutChart/index.html +2 -2
  124. package/docs/docs/api/appkit-ui/data/HeatmapChart/index.html +2 -2
  125. package/docs/docs/api/appkit-ui/data/LineChart/index.html +2 -2
  126. package/docs/docs/api/appkit-ui/data/PieChart/index.html +2 -2
  127. package/docs/docs/api/appkit-ui/data/RadarChart/index.html +2 -2
  128. package/docs/docs/api/appkit-ui/data/ScatterChart/index.html +2 -2
  129. package/docs/docs/api/appkit-ui/index.html +2 -2
  130. package/docs/docs/api/appkit-ui/styling/index.html +2 -2
  131. package/docs/docs/api/appkit-ui/ui/Accordion/index.html +2 -2
  132. package/docs/docs/api/appkit-ui/ui/Alert/index.html +2 -2
  133. package/docs/docs/api/appkit-ui/ui/AlertDialog/index.html +2 -2
  134. package/docs/docs/api/appkit-ui/ui/AspectRatio/index.html +2 -2
  135. package/docs/docs/api/appkit-ui/ui/Avatar/index.html +2 -2
  136. package/docs/docs/api/appkit-ui/ui/Badge/index.html +2 -2
  137. package/docs/docs/api/appkit-ui/ui/Breadcrumb/index.html +2 -2
  138. package/docs/docs/api/appkit-ui/ui/Button/index.html +2 -2
  139. package/docs/docs/api/appkit-ui/ui/ButtonGroup/index.html +2 -2
  140. package/docs/docs/api/appkit-ui/ui/Calendar/index.html +2 -2
  141. package/docs/docs/api/appkit-ui/ui/Card/index.html +2 -2
  142. package/docs/docs/api/appkit-ui/ui/Carousel/index.html +2 -2
  143. package/docs/docs/api/appkit-ui/ui/ChartContainer/index.html +2 -2
  144. package/docs/docs/api/appkit-ui/ui/Checkbox/index.html +2 -2
  145. package/docs/docs/api/appkit-ui/ui/Collapsible/index.html +2 -2
  146. package/docs/docs/api/appkit-ui/ui/Command/index.html +2 -2
  147. package/docs/docs/api/appkit-ui/ui/ContextMenu/index.html +2 -2
  148. package/docs/docs/api/appkit-ui/ui/Dialog/index.html +2 -2
  149. package/docs/docs/api/appkit-ui/ui/Drawer/index.html +2 -2
  150. package/docs/docs/api/appkit-ui/ui/DropdownMenu/index.html +2 -2
  151. package/docs/docs/api/appkit-ui/ui/Empty/index.html +2 -2
  152. package/docs/docs/api/appkit-ui/ui/Field/index.html +2 -2
  153. package/docs/docs/api/appkit-ui/ui/FormControl/index.html +2 -2
  154. package/docs/docs/api/appkit-ui/ui/HoverCard/index.html +2 -2
  155. package/docs/docs/api/appkit-ui/ui/Input/index.html +2 -2
  156. package/docs/docs/api/appkit-ui/ui/InputGroup/index.html +2 -2
  157. package/docs/docs/api/appkit-ui/ui/InputOTP/index.html +2 -2
  158. package/docs/docs/api/appkit-ui/ui/Item/index.html +2 -2
  159. package/docs/docs/api/appkit-ui/ui/Kbd/index.html +2 -2
  160. package/docs/docs/api/appkit-ui/ui/Label/index.html +2 -2
  161. package/docs/docs/api/appkit-ui/ui/Menubar/index.html +2 -2
  162. package/docs/docs/api/appkit-ui/ui/NavigationMenu/index.html +2 -2
  163. package/docs/docs/api/appkit-ui/ui/Pagination/index.html +2 -2
  164. package/docs/docs/api/appkit-ui/ui/Popover/index.html +2 -2
  165. package/docs/docs/api/appkit-ui/ui/Progress/index.html +2 -2
  166. package/docs/docs/api/appkit-ui/ui/RadioGroup/index.html +2 -2
  167. package/docs/docs/api/appkit-ui/ui/ResizableHandle/index.html +2 -2
  168. package/docs/docs/api/appkit-ui/ui/ScrollArea/index.html +2 -2
  169. package/docs/docs/api/appkit-ui/ui/Select/index.html +2 -2
  170. package/docs/docs/api/appkit-ui/ui/Separator/index.html +2 -2
  171. package/docs/docs/api/appkit-ui/ui/Sheet/index.html +2 -2
  172. package/docs/docs/api/appkit-ui/ui/Sidebar/index.html +2 -2
  173. package/docs/docs/api/appkit-ui/ui/Skeleton/index.html +2 -2
  174. package/docs/docs/api/appkit-ui/ui/Slider/index.html +2 -2
  175. package/docs/docs/api/appkit-ui/ui/Spinner/index.html +2 -2
  176. package/docs/docs/api/appkit-ui/ui/Switch/index.html +2 -2
  177. package/docs/docs/api/appkit-ui/ui/Table/index.html +2 -2
  178. package/docs/docs/api/appkit-ui/ui/Tabs/index.html +2 -2
  179. package/docs/docs/api/appkit-ui/ui/Textarea/index.html +2 -2
  180. package/docs/docs/api/appkit-ui/ui/Toaster/index.html +2 -2
  181. package/docs/docs/api/appkit-ui/ui/Toggle/index.html +2 -2
  182. package/docs/docs/api/appkit-ui/ui/ToggleGroup/index.html +2 -2
  183. package/docs/docs/api/appkit-ui/ui/Tooltip/index.html +2 -2
  184. package/docs/docs/api/appkit.md +6 -5
  185. package/docs/docs/api/index.html +2 -2
  186. package/docs/docs/app-management/index.html +2 -2
  187. package/docs/docs/architecture/index.html +2 -2
  188. package/docs/docs/category/development/index.html +2 -2
  189. package/docs/docs/configuration/index.html +2 -2
  190. package/docs/docs/core-principles/index.html +2 -2
  191. package/docs/docs/development/index.html +2 -2
  192. package/docs/docs/development/llm-guide/index.html +2 -2
  193. package/docs/docs/development/local-development/index.html +2 -2
  194. package/docs/docs/development/project-setup/index.html +2 -2
  195. package/docs/docs/development/remote-bridge/index.html +2 -2
  196. package/docs/docs/development/type-generation/index.html +2 -2
  197. package/docs/docs/index.html +2 -2
  198. package/docs/docs/plugins/index.html +7 -3
  199. package/docs/docs/plugins.md +36 -11
  200. package/llms.txt +1 -0
  201. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../../../src/connectors/sql-warehouse/client.ts"],"sourcesContent":["import {\n Context,\n type sql,\n type WorkspaceClient,\n} from \"@databricks/sdk-experimental\";\nimport type { TelemetryOptions } from \"shared\";\nimport {\n AppKitError,\n ConnectionError,\n ExecutionError,\n ValidationError,\n} from \"../../errors\";\nimport { createLogger } from \"../../logging/logger\";\nimport { ArrowStreamProcessor } from \"../../stream/arrow-stream-processor\";\nimport type { TelemetryProvider } from \"../../telemetry\";\nimport {\n type Counter,\n type Histogram,\n type Span,\n SpanKind,\n SpanStatusCode,\n TelemetryManager,\n} from \"../../telemetry\";\nimport { executeStatementDefaults } from \"./defaults\";\n\nconst logger = createLogger(\"connectors:sql-warehouse\");\n\nexport interface SQLWarehouseConfig {\n timeout?: number;\n telemetry?: TelemetryOptions;\n}\n\nexport class SQLWarehouseConnector {\n private readonly name = \"sql-warehouse\";\n\n private config: SQLWarehouseConfig;\n\n // Lazy-initialized: only created when Arrow format is used\n private _arrowProcessor: ArrowStreamProcessor | null = null;\n // telemetry\n private readonly telemetry: TelemetryProvider;\n private readonly telemetryMetrics: {\n queryCount: Counter;\n queryDuration: Histogram;\n };\n\n constructor(config: SQLWarehouseConfig) {\n this.config = config;\n\n this.telemetry = TelemetryManager.getProvider(\n this.name,\n this.config.telemetry,\n );\n this.telemetryMetrics = {\n queryCount: this.telemetry.getMeter().createCounter(\"query.count\", {\n description: \"Total number of queries executed\",\n unit: \"1\",\n }),\n queryDuration: this.telemetry\n .getMeter()\n .createHistogram(\"query.duration\", {\n description: \"Duration of queries executed\",\n unit: \"ms\",\n }),\n };\n }\n\n /**\n * Lazily initializes and returns the ArrowStreamProcessor.\n * Only created on first Arrow format query to avoid unnecessary allocation.\n */\n private get arrowProcessor(): ArrowStreamProcessor {\n if (!this._arrowProcessor) {\n this._arrowProcessor = new ArrowStreamProcessor({\n timeout: this.config.timeout || executeStatementDefaults.timeout,\n maxConcurrentDownloads:\n ArrowStreamProcessor.DEFAULT_MAX_CONCURRENT_DOWNLOADS,\n retries: ArrowStreamProcessor.DEFAULT_RETRIES,\n });\n }\n return this._arrowProcessor;\n }\n\n async executeStatement(\n workspaceClient: WorkspaceClient,\n input: sql.ExecuteStatementRequest,\n signal?: AbortSignal,\n ) {\n const startTime = Date.now();\n let success = false;\n\n // if signal is aborted, throw an error\n if (signal?.aborted) {\n throw ExecutionError.canceled();\n }\n\n return this.telemetry.startActiveSpan(\n \"sql.query\",\n {\n kind: SpanKind.CLIENT,\n attributes: {\n \"db.system\": \"databricks\",\n \"db.warehouse_id\": input.warehouse_id || \"\",\n \"db.catalog\": input.catalog ?? \"\",\n \"db.schema\": input.schema ?? \"\",\n \"db.statement\": input.statement?.substring(0, 500) || \"\",\n \"db.has_parameters\": !!input.parameters,\n },\n },\n async (span: Span) => {\n let abortHandler: (() => void) | undefined;\n let isAborted = false;\n\n if (signal) {\n abortHandler = () => {\n // abort span if not recording\n if (!span.isRecording()) return;\n isAborted = true;\n span.setAttribute(\"cancelled\", true);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: \"Query cancelled by client\",\n });\n span.end();\n };\n signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n\n try {\n // validate required fields\n if (!input.statement) {\n throw ValidationError.missingField(\"statement\");\n }\n\n if (!input.warehouse_id) {\n throw ValidationError.missingField(\"warehouse_id\");\n }\n\n const body: sql.ExecuteStatementRequest = {\n statement: input.statement,\n parameters: input.parameters,\n warehouse_id: input.warehouse_id,\n catalog: input.catalog,\n schema: input.schema,\n wait_timeout:\n input.wait_timeout || executeStatementDefaults.wait_timeout,\n disposition:\n input.disposition || executeStatementDefaults.disposition,\n format: input.format || executeStatementDefaults.format,\n byte_limit: input.byte_limit,\n row_limit: input.row_limit,\n on_wait_timeout:\n input.on_wait_timeout || executeStatementDefaults.on_wait_timeout,\n };\n\n span.addEvent(\"statement.submitting\", {\n \"db.warehouse_id\": input.warehouse_id,\n });\n\n const response =\n await workspaceClient.statementExecution.executeStatement(\n body,\n this._createContext(signal),\n );\n\n if (!response) {\n throw ConnectionError.apiFailure(\"SQL Warehouse\");\n }\n const status = response.status;\n const statementId = response.statement_id as string;\n\n span.setAttribute(\"db.statement_id\", statementId);\n span.addEvent(\"statement.submitted\", {\n \"db.statement_id\": response.statement_id,\n \"db.status\": status?.state,\n });\n\n let result:\n | sql.StatementResponse\n | { result: { statement_id: string; status: sql.StatementStatus } };\n\n switch (status?.state) {\n case \"RUNNING\":\n case \"PENDING\":\n span.addEvent(\"statement.polling_started\", {\n \"db.status\": response.status?.state,\n });\n result = await this._pollForStatementResult(\n workspaceClient,\n statementId,\n this.config.timeout,\n signal,\n );\n break;\n case \"SUCCEEDED\":\n result = this._transformDataArray(response);\n break;\n case \"FAILED\":\n throw ExecutionError.statementFailed(status.error?.message);\n case \"CANCELED\":\n throw ExecutionError.canceled();\n case \"CLOSED\":\n throw ExecutionError.resultsClosed();\n default:\n throw ExecutionError.unknownState(\n String(status?.state ?? \"unknown\"),\n );\n }\n\n const resultData = result.result as any;\n const rowCount =\n resultData?.data?.length ?? resultData?.data_array?.length ?? 0;\n\n if (rowCount > 0) {\n span.setAttribute(\"db.result.row_count\", rowCount);\n }\n\n const duration = Date.now() - startTime;\n logger.event()?.setContext(\"sql-warehouse\", {\n warehouse_id: input.warehouse_id,\n rows_returned: rowCount,\n query_duration_ms: duration,\n });\n\n success = true;\n // only set success status if not aborted\n if (!isAborted) {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n return result;\n } catch (error) {\n // only record error if not already handled by abort\n if (!isAborted) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n\n if (error instanceof AppKitError) {\n throw error;\n }\n throw ExecutionError.statementFailed(\n error instanceof Error ? error.message : String(error),\n );\n } finally {\n // remove abort handler\n if (abortHandler && signal) {\n signal.removeEventListener(\"abort\", abortHandler);\n }\n\n const duration = Date.now() - startTime;\n\n // end span if not already ended by abort handler\n if (!isAborted) {\n span.end();\n }\n\n const attributes = {\n \"db.warehouse_id\": input.warehouse_id,\n \"db.catalog\": input.catalog ?? \"\",\n \"db.schema\": input.schema ?? \"\",\n \"db.statement\": input.statement?.substring(0, 500) || \"\",\n success: success.toString(),\n };\n\n this.telemetryMetrics.queryCount.add(1, attributes);\n this.telemetryMetrics.queryDuration.record(duration, attributes);\n }\n },\n { name: this.name, includePrefix: true },\n );\n }\n\n private async _pollForStatementResult(\n workspaceClient: WorkspaceClient,\n statementId: string,\n timeout = executeStatementDefaults.timeout,\n signal?: AbortSignal,\n ) {\n return this.telemetry.startActiveSpan(\n \"sql.poll\",\n {\n attributes: {\n \"db.statement_id\": statementId,\n \"db.polling.timeout\": timeout,\n },\n },\n async (span: Span) => {\n try {\n const startTime = Date.now();\n let delay = 1000;\n const maxDelayBetweenPolls = 5000; // max 5 seconds between polls\n let pollCount = 0;\n\n while (true) {\n pollCount++;\n span.setAttribute(\"db.polling.current_attempt\", pollCount);\n\n // check if timeout exceeded\n const elapsedTime = Date.now() - startTime;\n if (elapsedTime > timeout) {\n const error = ExecutionError.statementFailed(\n `Polling timeout exceeded after ${timeout}ms (elapsed: ${elapsedTime}ms)`,\n );\n span.recordException(error);\n span.setStatus({ code: SpanStatusCode.ERROR });\n throw error;\n }\n\n if (signal?.aborted) {\n const error = ExecutionError.canceled();\n span.recordException(error);\n span.setStatus({ code: SpanStatusCode.ERROR });\n throw error;\n }\n\n span.addEvent(\"polling.attempt\", {\n \"poll.attempt\": pollCount,\n \"poll.delay_ms\": delay,\n \"poll.elapsed_ms\": elapsedTime,\n });\n\n const response =\n await workspaceClient.statementExecution.getStatement(\n {\n statement_id: statementId,\n },\n this._createContext(signal),\n );\n if (!response) {\n throw ConnectionError.apiFailure(\"SQL Warehouse\");\n }\n\n const status = response.status;\n\n span.addEvent(\"polling.status_check\", {\n \"db.status\": status?.state,\n \"poll.attempt\": pollCount,\n });\n\n switch (status?.state) {\n case \"PENDING\":\n case \"RUNNING\":\n // continue polling\n break;\n case \"SUCCEEDED\":\n span.setAttribute(\"db.polling.attempts\", pollCount);\n span.setAttribute(\"db.polling.total_duration_ms\", elapsedTime);\n span.addEvent(\"polling.completed\", {\n \"poll.attempts\": pollCount,\n \"poll.duration_ms\": elapsedTime,\n });\n span.setStatus({ code: SpanStatusCode.OK });\n return this._transformDataArray(response);\n case \"FAILED\":\n throw ExecutionError.statementFailed(status.error?.message);\n case \"CANCELED\":\n throw ExecutionError.canceled();\n case \"CLOSED\":\n throw ExecutionError.resultsClosed();\n default:\n throw ExecutionError.unknownState(\n String(status?.state ?? \"unknown\"),\n );\n }\n\n // continue polling after delay\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * 2, maxDelayBetweenPolls);\n }\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n\n if (error instanceof AppKitError) {\n throw error;\n }\n throw ExecutionError.statementFailed(\n error instanceof Error ? error.message : String(error),\n );\n } finally {\n span.end();\n }\n },\n { name: this.name, includePrefix: true },\n );\n }\n\n private _transformDataArray(response: sql.StatementResponse) {\n if (response.manifest?.format === \"ARROW_STREAM\") {\n return this.updateWithArrowStatus(response);\n }\n\n if (!response.result?.data_array || !response.manifest?.schema?.columns) {\n return response;\n }\n\n const columns = response.manifest.schema.columns;\n\n const transformedData = response.result.data_array.map((row) => {\n const obj: Record<string, unknown> = {};\n row.forEach((value, index) => {\n const column = columns[index];\n const columnName = column?.name || `column_${index}`;\n\n // attempt to parse JSON strings for string columns\n if (\n column?.type_name === \"STRING\" &&\n typeof value === \"string\" &&\n value &&\n (value[0] === \"{\" || value[0] === \"[\")\n ) {\n try {\n obj[columnName] = JSON.parse(value);\n } catch {\n // if parsing fails, keep as string\n obj[columnName] = value;\n }\n } else {\n obj[columnName] = value;\n }\n });\n return obj;\n });\n\n // remove data_array\n const { data_array: _data_array, ...restResult } = response.result;\n return {\n ...response,\n result: {\n ...restResult,\n data: transformedData,\n },\n };\n }\n\n private updateWithArrowStatus(response: sql.StatementResponse): {\n result: { statement_id: string; status: sql.StatementStatus };\n } {\n return {\n result: {\n statement_id: response.statement_id as string,\n status: {\n state: response.status?.state,\n error: response.status?.error,\n } as sql.StatementStatus,\n },\n };\n }\n\n async getArrowData(\n workspaceClient: WorkspaceClient,\n jobId: string,\n signal?: AbortSignal,\n ): Promise<ReturnType<typeof this.arrowProcessor.processChunks>> {\n const startTime = Date.now();\n\n return this.telemetry.startActiveSpan(\n \"arrow.getData\",\n {\n kind: SpanKind.CLIENT,\n attributes: {\n \"db.system\": \"databricks\",\n \"arrow.job_id\": jobId,\n },\n },\n async (span: Span) => {\n try {\n const response =\n await workspaceClient.statementExecution.getStatement(\n { statement_id: jobId },\n this._createContext(signal),\n );\n\n const chunks = response.result?.external_links;\n const schema = response.manifest?.schema;\n\n if (!chunks || !schema) {\n throw ExecutionError.missingData(\"chunks or schema\");\n }\n\n span.setAttribute(\"arrow.chunk_count\", chunks.length);\n\n const result = await this.arrowProcessor.processChunks(\n chunks,\n schema,\n signal,\n );\n\n span.setAttribute(\"arrow.data_size_bytes\", result.data.length);\n span.setStatus({ code: SpanStatusCode.OK });\n\n const duration = Date.now() - startTime;\n this.telemetryMetrics.queryDuration.record(duration, {\n operation: \"arrow.getData\",\n status: \"success\",\n });\n\n logger.event()?.setContext(\"sql-warehouse\", {\n arrow_data_size_bytes: result.data.length,\n arrow_job_id: jobId,\n });\n\n return result;\n } catch (error) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n span.recordException(error as Error);\n\n const duration = Date.now() - startTime;\n this.telemetryMetrics.queryDuration.record(duration, {\n operation: \"arrow.getData\",\n status: \"error\",\n });\n\n logger.error(\"Failed Arrow job: %s %O\", jobId, error);\n\n if (error instanceof AppKitError) {\n throw error;\n }\n throw ExecutionError.statementFailed(\n error instanceof Error ? error.message : String(error),\n );\n }\n },\n );\n }\n\n // create context for cancellation token\n private _createContext(signal?: AbortSignal) {\n return new Context({\n cancellationToken: {\n isCancellationRequested: signal?.aborted ?? false,\n onCancellationRequested: (cb: () => void) => {\n signal?.addEventListener(\"abort\", cb, { once: true });\n },\n },\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../../src/connectors/sql-warehouse/client.ts"],"sourcesContent":["import {\n Context,\n type sql,\n type WorkspaceClient,\n} from \"@databricks/sdk-experimental\";\nimport type { TelemetryOptions } from \"shared\";\nimport {\n AppKitError,\n ConnectionError,\n ExecutionError,\n ValidationError,\n} from \"../../errors\";\nimport { createLogger } from \"../../logging/logger\";\nimport { ArrowStreamProcessor } from \"../../stream/arrow-stream-processor\";\nimport type { TelemetryProvider } from \"../../telemetry\";\nimport {\n type Counter,\n type Histogram,\n type Span,\n SpanKind,\n SpanStatusCode,\n TelemetryManager,\n} from \"../../telemetry\";\nimport { executeStatementDefaults } from \"./defaults\";\n\nconst logger = createLogger(\"connectors:sql-warehouse\");\n\nexport interface SQLWarehouseConfig {\n timeout?: number;\n telemetry?: TelemetryOptions;\n}\n\nexport class SQLWarehouseConnector {\n private readonly name = \"sql-warehouse\";\n\n private config: SQLWarehouseConfig;\n\n // Lazy-initialized: only created when Arrow format is used\n private _arrowProcessor: ArrowStreamProcessor | null = null;\n // telemetry\n private readonly telemetry: TelemetryProvider;\n private readonly telemetryMetrics: {\n queryCount: Counter;\n queryDuration: Histogram;\n };\n\n constructor(config: SQLWarehouseConfig) {\n this.config = config;\n\n this.telemetry = TelemetryManager.getProvider(\n this.name,\n this.config.telemetry,\n );\n this.telemetryMetrics = {\n queryCount: this.telemetry.getMeter().createCounter(\"query.count\", {\n description: \"Total number of queries executed\",\n unit: \"1\",\n }),\n queryDuration: this.telemetry\n .getMeter()\n .createHistogram(\"query.duration\", {\n description: \"Duration of queries executed\",\n unit: \"ms\",\n }),\n };\n }\n\n /**\n * Lazily initializes and returns the ArrowStreamProcessor.\n * Only created on first Arrow format query to avoid unnecessary allocation.\n */\n private get arrowProcessor(): ArrowStreamProcessor {\n if (!this._arrowProcessor) {\n this._arrowProcessor = new ArrowStreamProcessor({\n timeout: this.config.timeout || executeStatementDefaults.timeout,\n maxConcurrentDownloads:\n ArrowStreamProcessor.DEFAULT_MAX_CONCURRENT_DOWNLOADS,\n retries: ArrowStreamProcessor.DEFAULT_RETRIES,\n });\n }\n return this._arrowProcessor;\n }\n\n async executeStatement(\n workspaceClient: WorkspaceClient,\n input: sql.ExecuteStatementRequest,\n signal?: AbortSignal,\n ) {\n const startTime = Date.now();\n let success = false;\n\n // if signal is aborted, throw an error\n if (signal?.aborted) {\n throw ExecutionError.canceled();\n }\n\n return this.telemetry.startActiveSpan(\n \"sql.query\",\n {\n kind: SpanKind.CLIENT,\n attributes: {\n \"db.system\": \"databricks\",\n \"db.warehouse_id\": input.warehouse_id || \"\",\n \"db.catalog\": input.catalog ?? \"\",\n \"db.schema\": input.schema ?? \"\",\n \"db.statement\": input.statement?.substring(0, 500) || \"\",\n \"db.has_parameters\": !!input.parameters,\n },\n },\n async (span: Span) => {\n let abortHandler: (() => void) | undefined;\n let isAborted = false;\n\n if (signal) {\n abortHandler = () => {\n // abort span if not recording\n if (!span.isRecording()) return;\n isAborted = true;\n span.setAttribute(\"cancelled\", true);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: \"Query cancelled by client\",\n });\n span.end();\n };\n signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n\n try {\n // validate required fields\n if (!input.statement) {\n throw ValidationError.missingField(\"statement\");\n }\n\n if (!input.warehouse_id) {\n throw ValidationError.missingField(\"warehouse_id\");\n }\n\n const body: sql.ExecuteStatementRequest = {\n statement: input.statement,\n parameters: input.parameters,\n warehouse_id: input.warehouse_id,\n catalog: input.catalog,\n schema: input.schema,\n wait_timeout:\n input.wait_timeout || executeStatementDefaults.wait_timeout,\n disposition:\n input.disposition || executeStatementDefaults.disposition,\n format: input.format || executeStatementDefaults.format,\n byte_limit: input.byte_limit,\n row_limit: input.row_limit,\n on_wait_timeout:\n input.on_wait_timeout || executeStatementDefaults.on_wait_timeout,\n };\n\n span.addEvent(\"statement.submitting\", {\n \"db.warehouse_id\": input.warehouse_id,\n });\n\n const response =\n await workspaceClient.statementExecution.executeStatement(\n body,\n this._createContext(signal),\n );\n\n if (!response) {\n throw ConnectionError.apiFailure(\"SQL Warehouse\");\n }\n const status = response.status;\n const statementId = response.statement_id as string;\n\n span.setAttribute(\"db.statement_id\", statementId);\n span.addEvent(\"statement.submitted\", {\n \"db.statement_id\": response.statement_id,\n \"db.status\": status?.state,\n });\n\n let result:\n | sql.StatementResponse\n | { result: { statement_id: string; status: sql.StatementStatus } };\n\n switch (status?.state) {\n case \"RUNNING\":\n case \"PENDING\":\n span.addEvent(\"statement.polling_started\", {\n \"db.status\": response.status?.state,\n });\n result = await this._pollForStatementResult(\n workspaceClient,\n statementId,\n this.config.timeout,\n signal,\n );\n break;\n case \"SUCCEEDED\":\n result = this._transformDataArray(response);\n break;\n case \"FAILED\":\n throw ExecutionError.statementFailed(status.error?.message);\n case \"CANCELED\":\n throw ExecutionError.canceled();\n case \"CLOSED\":\n throw ExecutionError.resultsClosed();\n default:\n throw ExecutionError.unknownState(\n String(status?.state ?? \"unknown\"),\n );\n }\n\n const resultData = result.result as any;\n const rowCount =\n resultData?.data?.length ?? resultData?.data_array?.length ?? 0;\n\n if (rowCount > 0) {\n span.setAttribute(\"db.result.row_count\", rowCount);\n }\n\n const duration = Date.now() - startTime;\n logger.event()?.setContext(\"sql-warehouse\", {\n warehouse_id: input.warehouse_id,\n rows_returned: rowCount,\n query_duration_ms: duration,\n });\n\n success = true;\n // only set success status if not aborted\n if (!isAborted) {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n return result;\n } catch (error) {\n // only record error if not already handled by abort\n if (!isAborted) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n }\n\n if (error instanceof AppKitError) {\n throw error;\n }\n throw ExecutionError.statementFailed(\n error instanceof Error ? error.message : String(error),\n );\n } finally {\n // remove abort handler\n if (abortHandler && signal) {\n signal.removeEventListener(\"abort\", abortHandler);\n }\n\n const duration = Date.now() - startTime;\n\n // end span if not already ended by abort handler\n if (!isAborted) {\n span.end();\n }\n\n const attributes = {\n \"db.warehouse_id\": input.warehouse_id,\n \"db.catalog\": input.catalog ?? \"\",\n \"db.schema\": input.schema ?? \"\",\n \"db.statement\": input.statement?.substring(0, 500) || \"\",\n success: success.toString(),\n };\n\n this.telemetryMetrics.queryCount.add(1, attributes);\n this.telemetryMetrics.queryDuration.record(duration, attributes);\n }\n },\n { name: this.name, includePrefix: true },\n );\n }\n\n private async _pollForStatementResult(\n workspaceClient: WorkspaceClient,\n statementId: string,\n timeout = executeStatementDefaults.timeout,\n signal?: AbortSignal,\n ) {\n return this.telemetry.startActiveSpan(\n \"sql.poll\",\n {\n attributes: {\n \"db.statement_id\": statementId,\n \"db.polling.timeout\": timeout,\n },\n },\n async (span: Span) => {\n try {\n const startTime = Date.now();\n let delay = 1000;\n const maxDelayBetweenPolls = 5000; // max 5 seconds between polls\n let pollCount = 0;\n\n while (true) {\n pollCount++;\n span.setAttribute(\"db.polling.current_attempt\", pollCount);\n\n // check if timeout exceeded\n const elapsedTime = Date.now() - startTime;\n if (elapsedTime > timeout) {\n const error = ExecutionError.statementFailed(\n `Polling timeout exceeded after ${timeout}ms (elapsed: ${elapsedTime}ms)`,\n );\n span.recordException(error);\n span.setStatus({ code: SpanStatusCode.ERROR });\n throw error;\n }\n\n if (signal?.aborted) {\n const error = ExecutionError.canceled();\n span.recordException(error);\n span.setStatus({ code: SpanStatusCode.ERROR });\n throw error;\n }\n\n span.addEvent(\"polling.attempt\", {\n \"poll.attempt\": pollCount,\n \"poll.delay_ms\": delay,\n \"poll.elapsed_ms\": elapsedTime,\n });\n\n const response =\n await workspaceClient.statementExecution.getStatement(\n {\n statement_id: statementId,\n },\n this._createContext(signal),\n );\n if (!response) {\n throw ConnectionError.apiFailure(\"SQL Warehouse\");\n }\n\n const status = response.status;\n\n span.addEvent(\"polling.status_check\", {\n \"db.status\": status?.state,\n \"poll.attempt\": pollCount,\n });\n\n switch (status?.state) {\n case \"PENDING\":\n case \"RUNNING\":\n // continue polling\n break;\n case \"SUCCEEDED\":\n span.setAttribute(\"db.polling.attempts\", pollCount);\n span.setAttribute(\"db.polling.total_duration_ms\", elapsedTime);\n span.addEvent(\"polling.completed\", {\n \"poll.attempts\": pollCount,\n \"poll.duration_ms\": elapsedTime,\n });\n span.setStatus({ code: SpanStatusCode.OK });\n return this._transformDataArray(response);\n case \"FAILED\":\n throw ExecutionError.statementFailed(status.error?.message);\n case \"CANCELED\":\n throw ExecutionError.canceled();\n case \"CLOSED\":\n throw ExecutionError.resultsClosed();\n default:\n throw ExecutionError.unknownState(\n String(status?.state ?? \"unknown\"),\n );\n }\n\n // continue polling after delay\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * 2, maxDelayBetweenPolls);\n }\n } catch (error) {\n span.recordException(error as Error);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : String(error),\n });\n\n if (error instanceof AppKitError) {\n throw error;\n }\n throw ExecutionError.statementFailed(\n error instanceof Error ? error.message : String(error),\n );\n } finally {\n span.end();\n }\n },\n { name: this.name, includePrefix: true },\n );\n }\n\n private _transformDataArray(response: sql.StatementResponse) {\n if (response.manifest?.format === \"ARROW_STREAM\") {\n return this.updateWithArrowStatus(response);\n }\n\n if (!response.result?.data_array || !response.manifest?.schema?.columns) {\n return response;\n }\n\n const columns = response.manifest.schema.columns;\n\n const transformedData = response.result.data_array.map((row) => {\n const obj: Record<string, unknown> = {};\n row.forEach((value, index) => {\n const column = columns[index];\n const columnName = column?.name || `column_${index}`;\n\n // attempt to parse JSON strings for string columns\n if (\n column?.type_name === \"STRING\" &&\n typeof value === \"string\" &&\n value &&\n (value[0] === \"{\" || value[0] === \"[\")\n ) {\n try {\n obj[columnName] = JSON.parse(value);\n } catch {\n // if parsing fails, keep as string\n obj[columnName] = value;\n }\n } else {\n obj[columnName] = value;\n }\n });\n return obj;\n });\n\n // remove data_array\n const { data_array: _data_array, ...restResult } = response.result;\n return {\n ...response,\n result: {\n ...restResult,\n data: transformedData,\n },\n };\n }\n\n private updateWithArrowStatus(response: sql.StatementResponse): {\n result: { statement_id: string; status: sql.StatementStatus };\n } {\n return {\n result: {\n statement_id: response.statement_id as string,\n status: {\n state: response.status?.state,\n error: response.status?.error,\n } as sql.StatementStatus,\n },\n };\n }\n\n async getArrowData(\n workspaceClient: WorkspaceClient,\n jobId: string,\n signal?: AbortSignal,\n ): Promise<ReturnType<typeof this.arrowProcessor.processChunks>> {\n const startTime = Date.now();\n\n return this.telemetry.startActiveSpan(\n \"arrow.getData\",\n {\n kind: SpanKind.CLIENT,\n attributes: {\n \"db.system\": \"databricks\",\n \"arrow.job_id\": jobId,\n },\n },\n async (span: Span) => {\n try {\n const response =\n await workspaceClient.statementExecution.getStatement(\n { statement_id: jobId },\n this._createContext(signal),\n );\n\n const chunks = response.result?.external_links;\n const schema = response.manifest?.schema;\n\n if (!chunks || !schema) {\n throw ExecutionError.missingData(\"chunks or schema\");\n }\n\n span.setAttribute(\"arrow.chunk_count\", chunks.length);\n\n const result = await this.arrowProcessor.processChunks(\n chunks,\n schema,\n signal,\n );\n\n span.setAttribute(\"arrow.data_size_bytes\", result.data.length);\n span.setStatus({ code: SpanStatusCode.OK });\n\n const duration = Date.now() - startTime;\n this.telemetryMetrics.queryDuration.record(duration, {\n operation: \"arrow.getData\",\n status: \"success\",\n });\n\n logger.event()?.setContext(\"sql-warehouse\", {\n arrow_data_size_bytes: result.data.length,\n arrow_job_id: jobId,\n });\n\n return result;\n } catch (error) {\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: error instanceof Error ? error.message : \"Unknown error\",\n });\n span.recordException(error as Error);\n\n const duration = Date.now() - startTime;\n this.telemetryMetrics.queryDuration.record(duration, {\n operation: \"arrow.getData\",\n status: \"error\",\n });\n\n logger.error(\"Failed Arrow job: %s %O\", jobId, error);\n\n if (error instanceof AppKitError) {\n throw error;\n }\n throw ExecutionError.statementFailed(\n error instanceof Error ? error.message : String(error),\n );\n }\n },\n );\n }\n\n // create context for cancellation token\n private _createContext(signal?: AbortSignal) {\n return new Context({\n cancellationToken: {\n isCancellationRequested: signal?.aborted ?? false,\n onCancellationRequested: (cb: () => void) => {\n signal?.addEventListener(\"abort\", cb, { once: true });\n },\n },\n });\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { ExecutionContext } from "./user-context.js";
2
+ import "@databricks/sdk-experimental";
3
+
4
+ //#region src/context/execution-context.d.ts
5
+
6
+ /**
7
+ * Get the current execution context.
8
+ *
9
+ * - If running inside a user context (via asUser), returns the user context
10
+ * - Otherwise, returns the service context
11
+ *
12
+ * @throws Error if ServiceContext is not initialized
13
+ */
14
+ declare function getExecutionContext(): ExecutionContext;
15
+ //#endregion
16
+ export { getExecutionContext };
17
+ //# sourceMappingURL=execution-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-context.d.ts","names":[],"sources":["../../src/context/execution-context.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;iBAkCgB,mBAAA,CAAA,GAAuB"}
@@ -0,0 +1,21 @@
1
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
2
+
3
+ //#region src/context/service-context.d.ts
4
+
5
+ /**
6
+ * Service context holds the service principal client and shared resources.
7
+ * This is initialized once at app startup and shared across all requests.
8
+ */
9
+ interface ServiceContextState {
10
+ /** WorkspaceClient authenticated as the service principal */
11
+ client: WorkspaceClient;
12
+ /** The service principal's user ID */
13
+ serviceUserId: string;
14
+ /** Promise that resolves to the warehouse ID */
15
+ warehouseId: Promise<string>;
16
+ /** Promise that resolves to the workspace ID */
17
+ workspaceId: Promise<string>;
18
+ }
19
+ //#endregion
20
+ export { ServiceContextState };
21
+ //# sourceMappingURL=service-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-context.d.ts","names":[],"sources":["../../src/context/service-context.ts"],"sourcesContent":[],"mappings":";;;;;AAqBA;;;AAMe,UANE,mBAAA,CAMF;;EAEO,MAAA,EANZ,eAMY;;;;eAFP;;eAEA"}
@@ -20,12 +20,8 @@ var ServiceContext;
20
20
  var init_service_context = __esmMin((() => {
21
21
  init_errors();
22
22
  ServiceContext = class ServiceContext {
23
- static {
24
- this.instance = null;
25
- }
26
- static {
27
- this.initPromise = null;
28
- }
23
+ static instance = null;
24
+ static initPromise = null;
29
25
  /**
30
26
  * Initialize the service context. Should be called once at app startup.
31
27
  * Safe to call multiple times - will return the same instance.
@@ -1 +1 @@
1
- {"version":3,"file":"service-context.js","names":["productName","productVersion"],"sources":["../../src/context/service-context.ts"],"sourcesContent":["import {\n type ClientOptions,\n type sql,\n WorkspaceClient,\n} from \"@databricks/sdk-experimental\";\nimport { coerce } from \"semver\";\nimport {\n name as productName,\n version as productVersion,\n} from \"../../package.json\";\nimport {\n AuthenticationError,\n ConfigurationError,\n InitializationError,\n} from \"../errors\";\nimport type { UserContext } from \"./user-context\";\n\n/**\n * Service context holds the service principal client and shared resources.\n * This is initialized once at app startup and shared across all requests.\n */\nexport interface ServiceContextState {\n /** WorkspaceClient authenticated as the service principal */\n client: WorkspaceClient;\n /** The service principal's user ID */\n serviceUserId: string;\n /** Promise that resolves to the warehouse ID */\n warehouseId: Promise<string>;\n /** Promise that resolves to the workspace ID */\n workspaceId: Promise<string>;\n}\n\nfunction getClientOptions(): ClientOptions {\n const isDev = process.env.NODE_ENV === \"development\";\n const semver = coerce(productVersion);\n const normalizedVersion = (semver?.version ??\n productVersion) as ClientOptions[\"productVersion\"];\n\n return {\n product: productName,\n productVersion: normalizedVersion,\n ...(isDev && { userAgentExtra: { mode: \"dev\" } }),\n };\n}\n\n/**\n * ServiceContext is a singleton that manages the service principal's\n * WorkspaceClient and shared resources like warehouse/workspace IDs.\n *\n * It's initialized once at app startup and provides the foundation\n * for both service principal and user context execution.\n */\nexport class ServiceContext {\n private static instance: ServiceContextState | null = null;\n private static initPromise: Promise<ServiceContextState> | null = null;\n\n /**\n * Initialize the service context. Should be called once at app startup.\n * Safe to call multiple times - will return the same instance.\n */\n static async initialize(): Promise<ServiceContextState> {\n if (ServiceContext.instance) {\n return ServiceContext.instance;\n }\n\n if (ServiceContext.initPromise) {\n return ServiceContext.initPromise;\n }\n\n ServiceContext.initPromise = ServiceContext.createContext();\n ServiceContext.instance = await ServiceContext.initPromise;\n return ServiceContext.instance;\n }\n\n /**\n * Get the initialized service context.\n * @throws Error if not initialized\n */\n static get(): ServiceContextState {\n if (!ServiceContext.instance) {\n throw InitializationError.notInitialized(\n \"ServiceContext\",\n \"Call ServiceContext.initialize() first\",\n );\n }\n return ServiceContext.instance;\n }\n\n /**\n * Check if the service context has been initialized.\n */\n static isInitialized(): boolean {\n return ServiceContext.instance !== null;\n }\n\n /**\n * Create a user context from request headers.\n *\n * @param token - The user's access token from x-forwarded-access-token header\n * @param userId - The user's ID from x-forwarded-user header\n * @param userName - Optional user name\n * @throws Error if token is not provided\n */\n static createUserContext(\n token: string,\n userId: string,\n userName?: string,\n ): UserContext {\n if (!token) {\n throw AuthenticationError.missingToken(\"user token\");\n }\n\n const host = process.env.DATABRICKS_HOST;\n if (!host) {\n throw ConfigurationError.missingEnvVar(\"DATABRICKS_HOST\");\n }\n\n const serviceCtx = ServiceContext.get();\n\n // Create user client with the OAuth token from Databricks Apps\n // Note: We use authType: \"pat\" because the token is passed as a Bearer token\n // just like a PAT, even though it's technically an OAuth token\n const userClient = new WorkspaceClient(\n {\n token,\n host,\n authType: \"pat\",\n },\n getClientOptions(),\n );\n\n return {\n client: userClient,\n userId,\n userName,\n warehouseId: serviceCtx.warehouseId,\n workspaceId: serviceCtx.workspaceId,\n isUserContext: true,\n };\n }\n\n /**\n * Get the client options for WorkspaceClient.\n * Exposed for testing purposes.\n */\n static getClientOptions(): ClientOptions {\n return getClientOptions();\n }\n\n private static async createContext(): Promise<ServiceContextState> {\n const client = new WorkspaceClient({}, getClientOptions());\n\n const warehouseId = ServiceContext.getWarehouseId(client);\n const workspaceId = ServiceContext.getWorkspaceId(client);\n const currentUser = await client.currentUser.me();\n\n if (!currentUser.id) {\n throw ConfigurationError.resourceNotFound(\"Service user ID\");\n }\n\n return {\n client,\n serviceUserId: currentUser.id,\n warehouseId,\n workspaceId,\n };\n }\n\n private static async getWorkspaceId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WORKSPACE_ID) {\n return process.env.DATABRICKS_WORKSPACE_ID;\n }\n\n const response = (await client.apiClient.request({\n path: \"/api/2.0/preview/scim/v2/Me\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {},\n responseHeaders: [\"x-databricks-org-id\"],\n })) as { \"x-databricks-org-id\": string };\n\n if (!response[\"x-databricks-org-id\"]) {\n throw ConfigurationError.resourceNotFound(\"Workspace ID\");\n }\n\n return response[\"x-databricks-org-id\"];\n }\n\n private static async getWarehouseId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WAREHOUSE_ID) {\n return process.env.DATABRICKS_WAREHOUSE_ID;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n const response = (await client.apiClient.request({\n path: \"/api/2.0/sql/warehouses\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {\n skip_cannot_use: \"true\",\n },\n })) as { warehouses: sql.EndpointInfo[] };\n\n const priorities: Record<sql.State, number> = {\n RUNNING: 0,\n STOPPED: 1,\n STARTING: 2,\n STOPPING: 3,\n DELETED: 99,\n DELETING: 99,\n };\n\n const warehouses = (response.warehouses || []).sort((a, b) => {\n return (\n priorities[a.state as sql.State] - priorities[b.state as sql.State]\n );\n });\n\n if (response.warehouses.length === 0) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n const firstWarehouse = warehouses[0];\n if (\n firstWarehouse.state === \"DELETED\" ||\n firstWarehouse.state === \"DELETING\" ||\n !firstWarehouse.id\n ) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n return firstWarehouse.id;\n }\n\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n /**\n * Reset the service context. Only for testing purposes.\n */\n static reset(): void {\n ServiceContext.instance = null;\n ServiceContext.initPromise = null;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service-context.js","names":["productName","productVersion"],"sources":["../../src/context/service-context.ts"],"sourcesContent":["import {\n type ClientOptions,\n type sql,\n WorkspaceClient,\n} from \"@databricks/sdk-experimental\";\nimport { coerce } from \"semver\";\nimport {\n name as productName,\n version as productVersion,\n} from \"../../package.json\";\nimport {\n AuthenticationError,\n ConfigurationError,\n InitializationError,\n} from \"../errors\";\nimport type { UserContext } from \"./user-context\";\n\n/**\n * Service context holds the service principal client and shared resources.\n * This is initialized once at app startup and shared across all requests.\n */\nexport interface ServiceContextState {\n /** WorkspaceClient authenticated as the service principal */\n client: WorkspaceClient;\n /** The service principal's user ID */\n serviceUserId: string;\n /** Promise that resolves to the warehouse ID */\n warehouseId: Promise<string>;\n /** Promise that resolves to the workspace ID */\n workspaceId: Promise<string>;\n}\n\nfunction getClientOptions(): ClientOptions {\n const isDev = process.env.NODE_ENV === \"development\";\n const semver = coerce(productVersion);\n const normalizedVersion = (semver?.version ??\n productVersion) as ClientOptions[\"productVersion\"];\n\n return {\n product: productName,\n productVersion: normalizedVersion,\n ...(isDev && { userAgentExtra: { mode: \"dev\" } }),\n };\n}\n\n/**\n * ServiceContext is a singleton that manages the service principal's\n * WorkspaceClient and shared resources like warehouse/workspace IDs.\n *\n * It's initialized once at app startup and provides the foundation\n * for both service principal and user context execution.\n */\nexport class ServiceContext {\n private static instance: ServiceContextState | null = null;\n private static initPromise: Promise<ServiceContextState> | null = null;\n\n /**\n * Initialize the service context. Should be called once at app startup.\n * Safe to call multiple times - will return the same instance.\n */\n static async initialize(): Promise<ServiceContextState> {\n if (ServiceContext.instance) {\n return ServiceContext.instance;\n }\n\n if (ServiceContext.initPromise) {\n return ServiceContext.initPromise;\n }\n\n ServiceContext.initPromise = ServiceContext.createContext();\n ServiceContext.instance = await ServiceContext.initPromise;\n return ServiceContext.instance;\n }\n\n /**\n * Get the initialized service context.\n * @throws Error if not initialized\n */\n static get(): ServiceContextState {\n if (!ServiceContext.instance) {\n throw InitializationError.notInitialized(\n \"ServiceContext\",\n \"Call ServiceContext.initialize() first\",\n );\n }\n return ServiceContext.instance;\n }\n\n /**\n * Check if the service context has been initialized.\n */\n static isInitialized(): boolean {\n return ServiceContext.instance !== null;\n }\n\n /**\n * Create a user context from request headers.\n *\n * @param token - The user's access token from x-forwarded-access-token header\n * @param userId - The user's ID from x-forwarded-user header\n * @param userName - Optional user name\n * @throws Error if token is not provided\n */\n static createUserContext(\n token: string,\n userId: string,\n userName?: string,\n ): UserContext {\n if (!token) {\n throw AuthenticationError.missingToken(\"user token\");\n }\n\n const host = process.env.DATABRICKS_HOST;\n if (!host) {\n throw ConfigurationError.missingEnvVar(\"DATABRICKS_HOST\");\n }\n\n const serviceCtx = ServiceContext.get();\n\n // Create user client with the OAuth token from Databricks Apps\n // Note: We use authType: \"pat\" because the token is passed as a Bearer token\n // just like a PAT, even though it's technically an OAuth token\n const userClient = new WorkspaceClient(\n {\n token,\n host,\n authType: \"pat\",\n },\n getClientOptions(),\n );\n\n return {\n client: userClient,\n userId,\n userName,\n warehouseId: serviceCtx.warehouseId,\n workspaceId: serviceCtx.workspaceId,\n isUserContext: true,\n };\n }\n\n /**\n * Get the client options for WorkspaceClient.\n * Exposed for testing purposes.\n */\n static getClientOptions(): ClientOptions {\n return getClientOptions();\n }\n\n private static async createContext(): Promise<ServiceContextState> {\n const client = new WorkspaceClient({}, getClientOptions());\n\n const warehouseId = ServiceContext.getWarehouseId(client);\n const workspaceId = ServiceContext.getWorkspaceId(client);\n const currentUser = await client.currentUser.me();\n\n if (!currentUser.id) {\n throw ConfigurationError.resourceNotFound(\"Service user ID\");\n }\n\n return {\n client,\n serviceUserId: currentUser.id,\n warehouseId,\n workspaceId,\n };\n }\n\n private static async getWorkspaceId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WORKSPACE_ID) {\n return process.env.DATABRICKS_WORKSPACE_ID;\n }\n\n const response = (await client.apiClient.request({\n path: \"/api/2.0/preview/scim/v2/Me\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {},\n responseHeaders: [\"x-databricks-org-id\"],\n })) as { \"x-databricks-org-id\": string };\n\n if (!response[\"x-databricks-org-id\"]) {\n throw ConfigurationError.resourceNotFound(\"Workspace ID\");\n }\n\n return response[\"x-databricks-org-id\"];\n }\n\n private static async getWarehouseId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WAREHOUSE_ID) {\n return process.env.DATABRICKS_WAREHOUSE_ID;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n const response = (await client.apiClient.request({\n path: \"/api/2.0/sql/warehouses\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {\n skip_cannot_use: \"true\",\n },\n })) as { warehouses: sql.EndpointInfo[] };\n\n const priorities: Record<sql.State, number> = {\n RUNNING: 0,\n STOPPED: 1,\n STARTING: 2,\n STOPPING: 3,\n DELETED: 99,\n DELETING: 99,\n };\n\n const warehouses = (response.warehouses || []).sort((a, b) => {\n return (\n priorities[a.state as sql.State] - priorities[b.state as sql.State]\n );\n });\n\n if (response.warehouses.length === 0) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n const firstWarehouse = warehouses[0];\n if (\n firstWarehouse.state === \"DELETED\" ||\n firstWarehouse.state === \"DELETING\" ||\n !firstWarehouse.id\n ) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n return firstWarehouse.id;\n }\n\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n /**\n * Reset the service context. Only for testing purposes.\n */\n static reset(): void {\n ServiceContext.instance = null;\n ServiceContext.initPromise = null;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { ServiceContextState } from "./service-context.js";
2
+
3
+ //#region src/context/user-context.d.ts
4
+
5
+ /**
6
+ * User execution context extends the service context with user-specific data.
7
+ * Created on-demand when asUser(req) is called.
8
+ */
9
+ interface UserContext {
10
+ /** WorkspaceClient authenticated as the user */
11
+ client: ServiceContextState["client"];
12
+ /** The user's ID (from request headers) */
13
+ userId: string;
14
+ /** The user's name (from request headers) */
15
+ userName?: string;
16
+ /** Promise that resolves to the warehouse ID (inherited from service context) */
17
+ warehouseId: Promise<string>;
18
+ /** Promise that resolves to the workspace ID (inherited from service context) */
19
+ workspaceId: Promise<string>;
20
+ /** Flag indicating this is a user context */
21
+ isUserContext: true;
22
+ }
23
+ /**
24
+ * Execution context can be either service or user context.
25
+ */
26
+ type ExecutionContext = ServiceContextState | UserContext;
27
+ //#endregion
28
+ export { ExecutionContext };
29
+ //# sourceMappingURL=user-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-context.d.ts","names":[],"sources":["../../src/context/user-context.ts"],"sourcesContent":[],"mappings":";;;;;;AAMA;;AAEU,UAFO,WAAA,CAEP;;QAQK,EARL,mBAQK,CAAA,QAAA,CAAA;EAAO;EAQV,MAAA,EAAA,MAAA;EAAgB;UAAG,CAAA,EAAA,MAAA;;EAAiC,WAAA,EAVjD,OAUiD,CAAA,MAAA,CAAA;;eARjD;;;;;;;KAQH,gBAAA,GAAmB,sBAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"appkit.d.ts","names":[],"sources":["../../src/core/appkit.ts"],"sourcesContent":[],"mappings":";;;;;;;;;iBAoIsB,oBACV,WAAW;YAGT;cACE;UACJ;IAET,QAAQ,UAAU"}
1
+ {"version":3,"file":"appkit.d.ts","names":[],"sources":["../../src/core/appkit.ts"],"sourcesContent":[],"mappings":";;;;;;;;;iBAuLsB,oBACV,WAAW;YAGT;cACE;UACJ;IAET,QAAQ,UAAU"}
@@ -7,12 +7,9 @@ import { CacheManager } from "../cache/index.js";
7
7
  //#region src/core/appkit.ts
8
8
  init_context();
9
9
  var AppKit = class AppKit {
10
- static {
11
- this._instance = null;
12
- }
10
+ #pluginInstances = {};
11
+ #setupPromises = [];
13
12
  constructor(config) {
14
- this.pluginInstances = {};
15
- this.setupPromises = [];
16
13
  const { plugins, ...globalConfig } = config;
17
14
  const pluginEntries = Object.entries(plugins);
18
15
  const corePlugins = pluginEntries.filter(([_, p]) => {
@@ -22,7 +19,7 @@ var AppKit = class AppKit {
22
19
  const deferredPlugins = pluginEntries.filter(([_, p]) => (p?.plugin?.phase ?? "normal") === "deferred");
23
20
  for (const [name, pluginData] of corePlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData);
24
21
  for (const [name, pluginData] of normalPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData);
25
- for (const [name, pluginData] of deferredPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, { plugins: this.pluginInstances });
22
+ for (const [name, pluginData] of deferredPlugins) if (pluginData) this.createAndRegisterPlugin(globalConfig, name, pluginData, { plugins: this.#pluginInstances });
26
23
  }
27
24
  createAndRegisterPlugin(config, name, pluginData, extraData) {
28
25
  const { plugin: Plugin, config: pluginConfig } = pluginData;
@@ -33,24 +30,50 @@ var AppKit = class AppKit {
33
30
  name,
34
31
  ...extraData
35
32
  });
36
- this.pluginInstances[name] = pluginInstance;
33
+ this.#pluginInstances[name] = pluginInstance;
37
34
  pluginInstance.validateEnv();
38
- this.setupPromises.push(pluginInstance.setup());
35
+ this.#setupPromises.push(pluginInstance.setup());
36
+ const self = this;
39
37
  Object.defineProperty(this, name, {
40
38
  get() {
41
- return this.pluginInstances[name];
39
+ const plugin = self.#pluginInstances[name];
40
+ return self.wrapWithAsUser(plugin);
42
41
  },
43
42
  enumerable: true
44
43
  });
45
44
  }
45
+ /**
46
+ * Binds all function properties in an exports object to the given context.
47
+ */
48
+ bindExportMethods(exports, context) {
49
+ for (const key in exports) if (Object.hasOwn(exports, key) && typeof exports[key] === "function") exports[key] = exports[key].bind(context);
50
+ }
51
+ /**
52
+ * Wraps a plugin's exports with an `asUser` method that returns
53
+ * a user-scoped version of the exports.
54
+ */
55
+ wrapWithAsUser(plugin) {
56
+ const pluginExports = plugin.exports?.() ?? {};
57
+ this.bindExportMethods(pluginExports, plugin);
58
+ if (typeof plugin.asUser !== "function") return pluginExports;
59
+ return {
60
+ ...pluginExports,
61
+ asUser: (req) => {
62
+ const userPlugin = plugin.asUser(req);
63
+ const userExports = userPlugin.exports?.() ?? {};
64
+ this.bindExportMethods(userExports, userPlugin);
65
+ return userExports;
66
+ }
67
+ };
68
+ }
46
69
  static async _createApp(config = {}) {
47
70
  TelemetryManager.initialize(config?.telemetry);
48
71
  await CacheManager.getInstance(config?.cache);
49
72
  await ServiceContext.initialize();
50
73
  const rawPlugins = config.plugins;
51
- AppKit._instance = new AppKit({ plugins: AppKit.preparePlugins(rawPlugins) });
52
- await Promise.all(AppKit._instance.setupPromises);
53
- return AppKit._instance;
74
+ const instance = new AppKit({ plugins: AppKit.preparePlugins(rawPlugins) });
75
+ await Promise.all(instance.#setupPromises);
76
+ return instance;
54
77
  }
55
78
  static preparePlugins(plugins) {
56
79
  const result = {};
@@ -1 +1 @@
1
- {"version":3,"file":"appkit.js","names":[],"sources":["../../src/core/appkit.ts"],"sourcesContent":["import type {\n BasePlugin,\n CacheConfig,\n InputPluginMap,\n OptionalConfigPluginDef,\n PluginConstructor,\n PluginData,\n PluginMap,\n} from \"shared\";\nimport { CacheManager } from \"../cache\";\nimport { ServiceContext } from \"../context\";\nimport type { TelemetryConfig } from \"../telemetry\";\nimport { TelemetryManager } from \"../telemetry\";\n\nexport class AppKit<TPlugins extends InputPluginMap> {\n private static _instance: AppKit<InputPluginMap> | null = null;\n private pluginInstances: Record<string, BasePlugin> = {};\n private setupPromises: Promise<void>[] = [];\n\n private constructor(config: { plugins: TPlugins }) {\n const { plugins, ...globalConfig } = config;\n\n const pluginEntries = Object.entries(plugins);\n\n const corePlugins = pluginEntries.filter(([_, p]) => {\n return (p?.plugin?.phase ?? \"normal\") === \"core\";\n });\n const normalPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"normal\",\n );\n const deferredPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"deferred\",\n );\n\n for (const [name, pluginData] of corePlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of normalPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of deferredPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n plugins: this.pluginInstances,\n });\n }\n }\n }\n\n private createAndRegisterPlugin<T extends PluginConstructor>(\n config: Omit<{ plugins: TPlugins }, \"plugins\">,\n name: string,\n pluginData: OptionalConfigPluginDef<T>,\n extraData?: Record<string, unknown>,\n ) {\n const { plugin: Plugin, config: pluginConfig } = pluginData;\n const baseConfig = {\n ...config,\n ...Plugin.DEFAULT_CONFIG,\n ...pluginConfig,\n name,\n ...extraData,\n };\n const pluginInstance = new Plugin(baseConfig);\n\n this.pluginInstances[name] = pluginInstance;\n\n pluginInstance.validateEnv();\n\n this.setupPromises.push(pluginInstance.setup());\n\n Object.defineProperty(this, name, {\n get() {\n return this.pluginInstances[name];\n },\n enumerable: true,\n });\n }\n\n static async _createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n >(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n } = {},\n ): Promise<PluginMap<T>> {\n // Initialize core services\n TelemetryManager.initialize(config?.telemetry);\n await CacheManager.getInstance(config?.cache);\n\n // Initialize ServiceContext for Databricks client management\n // This provides the service principal client and shared resources\n await ServiceContext.initialize();\n\n const rawPlugins = config.plugins as T;\n const preparedPlugins = AppKit.preparePlugins(rawPlugins);\n const mergedConfig = {\n plugins: preparedPlugins,\n };\n\n AppKit._instance = new AppKit(mergedConfig);\n\n await Promise.all(AppKit._instance.setupPromises);\n\n return AppKit._instance as unknown as PluginMap<T>;\n }\n\n private static preparePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n ) {\n const result: InputPluginMap = {};\n for (const currentPlugin of plugins) {\n result[currentPlugin.name] = {\n plugin: currentPlugin.plugin,\n config: currentPlugin.config as Record<string, unknown>,\n };\n }\n return result;\n }\n}\n\n/**\n * Bootstraps AppKit with the provided configuration.\n */\nexport async function createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n>(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n } = {},\n): Promise<PluginMap<T>> {\n return AppKit._createApp(config);\n}\n"],"mappings":";;;;;;;cAU4C;AAI5C,IAAa,SAAb,MAAa,OAAwC;;mBACO;;CAI1D,AAAQ,YAAY,QAA+B;yBAHG,EAAE;uBACf,EAAE;EAGzC,MAAM,EAAE,SAAS,GAAG,iBAAiB;EAErC,MAAM,gBAAgB,OAAO,QAAQ,QAAQ;EAE7C,MAAM,cAAc,cAAc,QAAQ,CAAC,GAAG,OAAO;AACnD,WAAQ,GAAG,QAAQ,SAAS,cAAc;IAC1C;EACF,MAAM,gBAAgB,cAAc,QACjC,CAAC,GAAG,QAAQ,GAAG,QAAQ,SAAS,cAAc,SAChD;EACD,MAAM,kBAAkB,cAAc,QACnC,CAAC,GAAG,QAAQ,GAAG,QAAQ,SAAS,cAAc,WAChD;AAED,OAAK,MAAM,CAAC,MAAM,eAAe,YAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,WAAW;AAIhE,OAAK,MAAM,CAAC,MAAM,eAAe,cAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,WAAW;AAIhE,OAAK,MAAM,CAAC,MAAM,eAAe,gBAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,YAAY,EAC3D,SAAS,KAAK,iBACf,CAAC;;CAKR,AAAQ,wBACN,QACA,MACA,YACA,WACA;EACA,MAAM,EAAE,QAAQ,QAAQ,QAAQ,iBAAiB;EAQjD,MAAM,iBAAiB,IAAI,OAPR;GACjB,GAAG;GACH,GAAG,OAAO;GACV,GAAG;GACH;GACA,GAAG;GACJ,CAC4C;AAE7C,OAAK,gBAAgB,QAAQ;AAE7B,iBAAe,aAAa;AAE5B,OAAK,cAAc,KAAK,eAAe,OAAO,CAAC;AAE/C,SAAO,eAAe,MAAM,MAAM;GAChC,MAAM;AACJ,WAAO,KAAK,gBAAgB;;GAE9B,YAAY;GACb,CAAC;;CAGJ,aAAa,WAGX,SAII,EAAE,EACiB;AAEvB,mBAAiB,WAAW,QAAQ,UAAU;AAC9C,QAAM,aAAa,YAAY,QAAQ,MAAM;AAI7C,QAAM,eAAe,YAAY;EAEjC,MAAM,aAAa,OAAO;AAM1B,SAAO,YAAY,IAAI,OAJF,EACnB,SAFsB,OAAO,eAAe,WAAW,EAGxD,CAE0C;AAE3C,QAAM,QAAQ,IAAI,OAAO,UAAU,cAAc;AAEjD,SAAO,OAAO;;CAGhB,OAAe,eACb,SACA;EACA,MAAM,SAAyB,EAAE;AACjC,OAAK,MAAM,iBAAiB,QAC1B,QAAO,cAAc,QAAQ;GAC3B,QAAQ,cAAc;GACtB,QAAQ,cAAc;GACvB;AAEH,SAAO;;;;;;AAOX,eAAsB,UAGpB,SAII,EAAE,EACiB;AACvB,QAAO,OAAO,WAAW,OAAO"}
1
+ {"version":3,"file":"appkit.js","names":["#pluginInstances","#setupPromises"],"sources":["../../src/core/appkit.ts"],"sourcesContent":["import type {\n BasePlugin,\n CacheConfig,\n InputPluginMap,\n OptionalConfigPluginDef,\n PluginConstructor,\n PluginData,\n PluginMap,\n} from \"shared\";\nimport { CacheManager } from \"../cache\";\nimport { ServiceContext } from \"../context\";\nimport type { TelemetryConfig } from \"../telemetry\";\nimport { TelemetryManager } from \"../telemetry\";\n\nexport class AppKit<TPlugins extends InputPluginMap> {\n #pluginInstances: Record<string, BasePlugin> = {};\n #setupPromises: Promise<void>[] = [];\n\n private constructor(config: { plugins: TPlugins }) {\n const { plugins, ...globalConfig } = config;\n\n const pluginEntries = Object.entries(plugins);\n\n const corePlugins = pluginEntries.filter(([_, p]) => {\n return (p?.plugin?.phase ?? \"normal\") === \"core\";\n });\n const normalPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"normal\",\n );\n const deferredPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"deferred\",\n );\n\n for (const [name, pluginData] of corePlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of normalPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of deferredPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n plugins: this.#pluginInstances,\n });\n }\n }\n }\n\n private createAndRegisterPlugin<T extends PluginConstructor>(\n config: Omit<{ plugins: TPlugins }, \"plugins\">,\n name: string,\n pluginData: OptionalConfigPluginDef<T>,\n extraData?: Record<string, unknown>,\n ) {\n const { plugin: Plugin, config: pluginConfig } = pluginData;\n const baseConfig = {\n ...config,\n ...Plugin.DEFAULT_CONFIG,\n ...pluginConfig,\n name,\n ...extraData,\n };\n const pluginInstance = new Plugin(baseConfig);\n\n this.#pluginInstances[name] = pluginInstance;\n\n pluginInstance.validateEnv();\n\n this.#setupPromises.push(pluginInstance.setup());\n\n const self = this;\n\n Object.defineProperty(this, name, {\n get() {\n const plugin = self.#pluginInstances[name];\n return self.wrapWithAsUser(plugin);\n },\n enumerable: true,\n });\n }\n\n /**\n * Binds all function properties in an exports object to the given context.\n */\n private bindExportMethods(\n exports: Record<string, unknown>,\n context: BasePlugin,\n ) {\n for (const key in exports) {\n if (Object.hasOwn(exports, key) && typeof exports[key] === \"function\") {\n exports[key] = (exports[key] as (...args: unknown[]) => unknown).bind(\n context,\n );\n }\n }\n }\n\n /**\n * Wraps a plugin's exports with an `asUser` method that returns\n * a user-scoped version of the exports.\n */\n private wrapWithAsUser<T extends BasePlugin>(plugin: T) {\n // If plugin doesn't implement exports(), return empty object\n const pluginExports = (plugin.exports?.() ?? {}) as Record<string, unknown>;\n this.bindExportMethods(pluginExports, plugin);\n\n // If plugin doesn't support asUser (no asUser method), return exports as-is\n if (typeof (plugin as any).asUser !== \"function\") {\n return pluginExports;\n }\n\n return {\n ...pluginExports,\n /**\n * Execute operations using the user's identity from the request.\n * Returns user-scoped exports where all methods execute with the\n * user's Databricks credentials instead of the service principal.\n */\n asUser: (req: import(\"express\").Request) => {\n const userPlugin = (plugin as any).asUser(req);\n const userExports = (userPlugin.exports?.() ?? {}) as Record<\n string,\n unknown\n >;\n this.bindExportMethods(userExports, userPlugin);\n return userExports;\n },\n };\n }\n\n static async _createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n >(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n } = {},\n ): Promise<PluginMap<T>> {\n // Initialize core services\n TelemetryManager.initialize(config?.telemetry);\n await CacheManager.getInstance(config?.cache);\n\n // Initialize ServiceContext for Databricks client management\n // This provides the service principal client and shared resources\n await ServiceContext.initialize();\n\n const rawPlugins = config.plugins as T;\n const preparedPlugins = AppKit.preparePlugins(rawPlugins);\n const mergedConfig = {\n plugins: preparedPlugins,\n };\n\n const instance = new AppKit(mergedConfig);\n\n await Promise.all(instance.#setupPromises);\n\n return instance as unknown as PluginMap<T>;\n }\n\n private static preparePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n ) {\n const result: InputPluginMap = {};\n for (const currentPlugin of plugins) {\n result[currentPlugin.name] = {\n plugin: currentPlugin.plugin,\n config: currentPlugin.config as Record<string, unknown>,\n };\n }\n return result;\n }\n}\n\n/**\n * Bootstraps AppKit with the provided configuration.\n */\nexport async function createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n>(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n } = {},\n): Promise<PluginMap<T>> {\n return AppKit._createApp(config);\n}\n"],"mappings":";;;;;;;cAU4C;AAI5C,IAAa,SAAb,MAAa,OAAwC;CACnD,mBAA+C,EAAE;CACjD,iBAAkC,EAAE;CAEpC,AAAQ,YAAY,QAA+B;EACjD,MAAM,EAAE,SAAS,GAAG,iBAAiB;EAErC,MAAM,gBAAgB,OAAO,QAAQ,QAAQ;EAE7C,MAAM,cAAc,cAAc,QAAQ,CAAC,GAAG,OAAO;AACnD,WAAQ,GAAG,QAAQ,SAAS,cAAc;IAC1C;EACF,MAAM,gBAAgB,cAAc,QACjC,CAAC,GAAG,QAAQ,GAAG,QAAQ,SAAS,cAAc,SAChD;EACD,MAAM,kBAAkB,cAAc,QACnC,CAAC,GAAG,QAAQ,GAAG,QAAQ,SAAS,cAAc,WAChD;AAED,OAAK,MAAM,CAAC,MAAM,eAAe,YAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,WAAW;AAIhE,OAAK,MAAM,CAAC,MAAM,eAAe,cAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,WAAW;AAIhE,OAAK,MAAM,CAAC,MAAM,eAAe,gBAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,YAAY,EAC3D,SAAS,MAAKA,iBACf,CAAC;;CAKR,AAAQ,wBACN,QACA,MACA,YACA,WACA;EACA,MAAM,EAAE,QAAQ,QAAQ,QAAQ,iBAAiB;EAQjD,MAAM,iBAAiB,IAAI,OAPR;GACjB,GAAG;GACH,GAAG,OAAO;GACV,GAAG;GACH;GACA,GAAG;GACJ,CAC4C;AAE7C,QAAKA,gBAAiB,QAAQ;AAE9B,iBAAe,aAAa;AAE5B,QAAKC,cAAe,KAAK,eAAe,OAAO,CAAC;EAEhD,MAAM,OAAO;AAEb,SAAO,eAAe,MAAM,MAAM;GAChC,MAAM;IACJ,MAAM,SAAS,MAAKD,gBAAiB;AACrC,WAAO,KAAK,eAAe,OAAO;;GAEpC,YAAY;GACb,CAAC;;;;;CAMJ,AAAQ,kBACN,SACA,SACA;AACA,OAAK,MAAM,OAAO,QAChB,KAAI,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO,QAAQ,SAAS,WACzD,SAAQ,OAAQ,QAAQ,KAAyC,KAC/D,QACD;;;;;;CASP,AAAQ,eAAqC,QAAW;EAEtD,MAAM,gBAAiB,OAAO,WAAW,IAAI,EAAE;AAC/C,OAAK,kBAAkB,eAAe,OAAO;AAG7C,MAAI,OAAQ,OAAe,WAAW,WACpC,QAAO;AAGT,SAAO;GACL,GAAG;GAMH,SAAS,QAAmC;IAC1C,MAAM,aAAc,OAAe,OAAO,IAAI;IAC9C,MAAM,cAAe,WAAW,WAAW,IAAI,EAAE;AAIjD,SAAK,kBAAkB,aAAa,WAAW;AAC/C,WAAO;;GAEV;;CAGH,aAAa,WAGX,SAII,EAAE,EACiB;AAEvB,mBAAiB,WAAW,QAAQ,UAAU;AAC9C,QAAM,aAAa,YAAY,QAAQ,MAAM;AAI7C,QAAM,eAAe,YAAY;EAEjC,MAAM,aAAa,OAAO;EAM1B,MAAM,WAAW,IAAI,OAJA,EACnB,SAFsB,OAAO,eAAe,WAAW,EAGxD,CAEwC;AAEzC,QAAM,QAAQ,IAAI,UAASC,cAAe;AAE1C,SAAO;;CAGT,OAAe,eACb,SACA;EACA,MAAM,SAAyB,EAAE;AACjC,OAAK,MAAM,iBAAiB,QAC1B,QAAO,cAAc,QAAQ;GAC3B,QAAQ,cAAc;GACtB,QAAQ,cAAc;GACvB;AAEH,SAAO;;;;;;AAOX,eAAsB,UAGpB,SAII,EAAE,EACiB;AACvB,QAAO,OAAO,WAAW,OAAO"}
@@ -6,12 +6,9 @@ var AuthenticationError;
6
6
  var init_authentication = __esmMin((() => {
7
7
  init_base();
8
8
  AuthenticationError = class AuthenticationError extends AppKitError {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.code = "AUTHENTICATION_ERROR";
12
- this.statusCode = 401;
13
- this.isRetryable = false;
14
- }
9
+ code = "AUTHENTICATION_ERROR";
10
+ statusCode = 401;
11
+ isRetryable = false;
15
12
  /**
16
13
  * Create an authentication error for missing token
17
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.js","names":[],"sources":["../../src/errors/authentication.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when authentication fails.\n * Use for missing tokens, invalid credentials, or authorization failures.\n *\n * @example\n * ```typescript\n * throw new AuthenticationError(\"User token is required\");\n * throw new AuthenticationError(\"Failed to generate credentials\", { cause: originalError });\n * ```\n */\nexport class AuthenticationError extends AppKitError {\n readonly code = \"AUTHENTICATION_ERROR\";\n readonly statusCode = 401;\n readonly isRetryable = false;\n\n /**\n * Create an authentication error for missing token\n */\n static missingToken(tokenType = \"access token\"): AuthenticationError {\n return new AuthenticationError(`Missing ${tokenType} in request headers`, {\n context: { tokenType },\n });\n }\n\n /**\n * Create an authentication error for missing user identity\n */\n static missingUserId(): AuthenticationError {\n return new AuthenticationError(\n \"User ID not available in request headers. \" +\n \"Ensure the request has the x-forwarded-user header.\",\n );\n }\n\n /**\n * Create an authentication error for credential generation failure\n */\n static credentialsFailed(\n instance: string,\n cause?: Error,\n ): AuthenticationError {\n return new AuthenticationError(\n `Failed to generate credentials for instance: ${instance}`,\n { cause, context: { instance } },\n );\n }\n\n /**\n * Create an authentication error for failed user lookup\n */\n static userLookupFailed(cause?: Error): AuthenticationError {\n return new AuthenticationError(\n \"Failed to get current user from Databricks workspace\",\n { cause },\n );\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,sBAAb,MAAa,4BAA4B,YAAY;;;eACnC;qBACM;sBACC;;;;;EAKvB,OAAO,aAAa,YAAY,gBAAqC;AACnE,UAAO,IAAI,oBAAoB,WAAW,UAAU,sBAAsB,EACxE,SAAS,EAAE,WAAW,EACvB,CAAC;;;;;EAMJ,OAAO,gBAAqC;AAC1C,UAAO,IAAI,oBACT,gGAED;;;;;EAMH,OAAO,kBACL,UACA,OACqB;AACrB,UAAO,IAAI,oBACT,gDAAgD,YAChD;IAAE;IAAO,SAAS,EAAE,UAAU;IAAE,CACjC;;;;;EAMH,OAAO,iBAAiB,OAAoC;AAC1D,UAAO,IAAI,oBACT,wDACA,EAAE,OAAO,CACV"}
1
+ {"version":3,"file":"authentication.js","names":[],"sources":["../../src/errors/authentication.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when authentication fails.\n * Use for missing tokens, invalid credentials, or authorization failures.\n *\n * @example\n * ```typescript\n * throw new AuthenticationError(\"User token is required\");\n * throw new AuthenticationError(\"Failed to generate credentials\", { cause: originalError });\n * ```\n */\nexport class AuthenticationError extends AppKitError {\n readonly code = \"AUTHENTICATION_ERROR\";\n readonly statusCode = 401;\n readonly isRetryable = false;\n\n /**\n * Create an authentication error for missing token\n */\n static missingToken(tokenType = \"access token\"): AuthenticationError {\n return new AuthenticationError(`Missing ${tokenType} in request headers`, {\n context: { tokenType },\n });\n }\n\n /**\n * Create an authentication error for missing user identity\n */\n static missingUserId(): AuthenticationError {\n return new AuthenticationError(\n \"User ID not available in request headers. \" +\n \"Ensure the request has the x-forwarded-user header.\",\n );\n }\n\n /**\n * Create an authentication error for credential generation failure\n */\n static credentialsFailed(\n instance: string,\n cause?: Error,\n ): AuthenticationError {\n return new AuthenticationError(\n `Failed to generate credentials for instance: ${instance}`,\n { cause, context: { instance } },\n );\n }\n\n /**\n * Create an authentication error for failed user lookup\n */\n static userLookupFailed(cause?: Error): AuthenticationError {\n return new AuthenticationError(\n \"Failed to get current user from Databricks workspace\",\n { cause },\n );\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,sBAAb,MAAa,4BAA4B,YAAY;EACnD,AAAS,OAAO;EAChB,AAAS,aAAa;EACtB,AAAS,cAAc;;;;EAKvB,OAAO,aAAa,YAAY,gBAAqC;AACnE,UAAO,IAAI,oBAAoB,WAAW,UAAU,sBAAsB,EACxE,SAAS,EAAE,WAAW,EACvB,CAAC;;;;;EAMJ,OAAO,gBAAqC;AAC1C,UAAO,IAAI,oBACT,gGAED;;;;;EAMH,OAAO,kBACL,UACA,OACqB;AACrB,UAAO,IAAI,oBACT,gDAAgD,YAChD;IAAE;IAAO,SAAS,EAAE,UAAU;IAAE,CACjC;;;;;EAMH,OAAO,iBAAiB,OAAoC;AAC1D,UAAO,IAAI,oBACT,wDACA,EAAE,OAAO,CACV"}
@@ -13,6 +13,10 @@ var init_base = __esmMin((() => {
13
13
  /apikey/i
14
14
  ];
15
15
  AppKitError = class extends Error {
16
+ /** Optional cause of the error */
17
+ cause;
18
+ /** Additional context for the error */
19
+ context;
16
20
  constructor(message, options) {
17
21
  super(message);
18
22
  this.name = this.constructor.name;
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","names":[],"sources":["../../src/errors/base.ts"],"sourcesContent":["/** Fields that should be redacted in logs/serialization for security */\nconst SENSITIVE_FIELD_PATTERNS = [\n /token/i,\n /password/i,\n /secret/i,\n /credential/i,\n /auth/i,\n /key$/i,\n /apikey/i,\n];\n\n/**\n * Base error class for all AppKit errors.\n * Provides a consistent structure for error handling across the framework.\n *\n * @example\n * ```typescript\n * // Catching errors by type\n * try {\n * await lakebase.query(\"...\");\n * } catch (e) {\n * if (e instanceof AuthenticationError) {\n * // Re-authenticate\n * } else if (e instanceof ConnectionError && e.isRetryable) {\n * // Retry with backoff\n * }\n * }\n *\n * // Logging errors\n * console.error(error.toJSON()); // Safe for logging, sensitive values redacted\n * ```\n */\nexport abstract class AppKitError extends Error {\n /** Error code for programmatic error handling */\n abstract readonly code: string;\n\n /** HTTP status code suggestion (can be overridden) */\n abstract readonly statusCode: number;\n\n /** Whether this error type is generally safe to retry */\n abstract readonly isRetryable: boolean;\n\n /** Optional cause of the error */\n readonly cause?: Error;\n\n /** Additional context for the error */\n readonly context?: Record<string, unknown>;\n\n constructor(\n message: string,\n options?: { cause?: Error; context?: Record<string, unknown> },\n ) {\n super(message);\n this.name = this.constructor.name;\n this.cause = options?.cause;\n this.context = options?.context;\n\n // Maintains proper stack trace for where the error was thrown\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * Convert error to JSON for logging/serialization.\n * Sensitive values in context are automatically redacted.\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n isRetryable: this.isRetryable,\n context: this.sanitizeContext(this.context),\n cause: this.cause?.message,\n stack: this.stack,\n };\n }\n\n /**\n * Create a human-readable string representation\n */\n toString(): string {\n let str = `${this.name} [${this.code}]: ${this.message}`;\n if (this.cause) {\n str += ` (caused by: ${this.cause.message})`;\n }\n return str;\n }\n\n /**\n * Sanitize context by redacting sensitive field values\n */\n private sanitizeContext(\n context?: Record<string, unknown>,\n ): Record<string, unknown> | undefined {\n if (!context) return undefined;\n\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(context)) {\n if (this.isSensitiveField(key)) {\n sanitized[key] = \"[REDACTED]\";\n } else if (typeof value === \"object\" && value !== null) {\n // Don't deep-sanitize nested objects, just indicate their type\n sanitized[key] = Array.isArray(value)\n ? `[Array(${value.length})]`\n : \"[Object]\";\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n }\n\n /**\n * Check if a field name matches sensitive patterns\n */\n private isSensitiveField(fieldName: string): boolean {\n return SENSITIVE_FIELD_PATTERNS.some((pattern) => pattern.test(fieldName));\n }\n}\n"],"mappings":";;;;;CACM,2BAA2B;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CAuBqB,cAAtB,cAA0C,MAAM;EAgB9C,YACE,SACA,SACA;AACA,SAAM,QAAQ;AACd,QAAK,OAAO,KAAK,YAAY;AAC7B,QAAK,QAAQ,SAAS;AACtB,QAAK,UAAU,SAAS;AAGxB,OAAI,MAAM,kBACR,OAAM,kBAAkB,MAAM,KAAK,YAAY;;;;;;EAQnD,SAAkC;AAChC,UAAO;IACL,MAAM,KAAK;IACX,MAAM,KAAK;IACX,SAAS,KAAK;IACd,YAAY,KAAK;IACjB,aAAa,KAAK;IAClB,SAAS,KAAK,gBAAgB,KAAK,QAAQ;IAC3C,OAAO,KAAK,OAAO;IACnB,OAAO,KAAK;IACb;;;;;EAMH,WAAmB;GACjB,IAAI,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK;AAC/C,OAAI,KAAK,MACP,QAAO,gBAAgB,KAAK,MAAM,QAAQ;AAE5C,UAAO;;;;;EAMT,AAAQ,gBACN,SACqC;AACrC,OAAI,CAAC,QAAS,QAAO;GAErB,MAAM,YAAqC,EAAE;AAC7C,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,KAAI,KAAK,iBAAiB,IAAI,CAC5B,WAAU,OAAO;YACR,OAAO,UAAU,YAAY,UAAU,KAEhD,WAAU,OAAO,MAAM,QAAQ,MAAM,GACjC,UAAU,MAAM,OAAO,MACvB;OAEJ,WAAU,OAAO;AAGrB,UAAO;;;;;EAMT,AAAQ,iBAAiB,WAA4B;AACnD,UAAO,yBAAyB,MAAM,YAAY,QAAQ,KAAK,UAAU,CAAC"}
1
+ {"version":3,"file":"base.js","names":[],"sources":["../../src/errors/base.ts"],"sourcesContent":["/** Fields that should be redacted in logs/serialization for security */\nconst SENSITIVE_FIELD_PATTERNS = [\n /token/i,\n /password/i,\n /secret/i,\n /credential/i,\n /auth/i,\n /key$/i,\n /apikey/i,\n];\n\n/**\n * Base error class for all AppKit errors.\n * Provides a consistent structure for error handling across the framework.\n *\n * @example\n * ```typescript\n * // Catching errors by type\n * try {\n * await lakebase.query(\"...\");\n * } catch (e) {\n * if (e instanceof AuthenticationError) {\n * // Re-authenticate\n * } else if (e instanceof ConnectionError && e.isRetryable) {\n * // Retry with backoff\n * }\n * }\n *\n * // Logging errors\n * console.error(error.toJSON()); // Safe for logging, sensitive values redacted\n * ```\n */\nexport abstract class AppKitError extends Error {\n /** Error code for programmatic error handling */\n abstract readonly code: string;\n\n /** HTTP status code suggestion (can be overridden) */\n abstract readonly statusCode: number;\n\n /** Whether this error type is generally safe to retry */\n abstract readonly isRetryable: boolean;\n\n /** Optional cause of the error */\n readonly cause?: Error;\n\n /** Additional context for the error */\n readonly context?: Record<string, unknown>;\n\n constructor(\n message: string,\n options?: { cause?: Error; context?: Record<string, unknown> },\n ) {\n super(message);\n this.name = this.constructor.name;\n this.cause = options?.cause;\n this.context = options?.context;\n\n // Maintains proper stack trace for where the error was thrown\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n\n /**\n * Convert error to JSON for logging/serialization.\n * Sensitive values in context are automatically redacted.\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n isRetryable: this.isRetryable,\n context: this.sanitizeContext(this.context),\n cause: this.cause?.message,\n stack: this.stack,\n };\n }\n\n /**\n * Create a human-readable string representation\n */\n toString(): string {\n let str = `${this.name} [${this.code}]: ${this.message}`;\n if (this.cause) {\n str += ` (caused by: ${this.cause.message})`;\n }\n return str;\n }\n\n /**\n * Sanitize context by redacting sensitive field values\n */\n private sanitizeContext(\n context?: Record<string, unknown>,\n ): Record<string, unknown> | undefined {\n if (!context) return undefined;\n\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(context)) {\n if (this.isSensitiveField(key)) {\n sanitized[key] = \"[REDACTED]\";\n } else if (typeof value === \"object\" && value !== null) {\n // Don't deep-sanitize nested objects, just indicate their type\n sanitized[key] = Array.isArray(value)\n ? `[Array(${value.length})]`\n : \"[Object]\";\n } else {\n sanitized[key] = value;\n }\n }\n return sanitized;\n }\n\n /**\n * Check if a field name matches sensitive patterns\n */\n private isSensitiveField(fieldName: string): boolean {\n return SENSITIVE_FIELD_PATTERNS.some((pattern) => pattern.test(fieldName));\n }\n}\n"],"mappings":";;;;;CACM,2BAA2B;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CAuBqB,cAAtB,cAA0C,MAAM;;EAW9C,AAAS;;EAGT,AAAS;EAET,YACE,SACA,SACA;AACA,SAAM,QAAQ;AACd,QAAK,OAAO,KAAK,YAAY;AAC7B,QAAK,QAAQ,SAAS;AACtB,QAAK,UAAU,SAAS;AAGxB,OAAI,MAAM,kBACR,OAAM,kBAAkB,MAAM,KAAK,YAAY;;;;;;EAQnD,SAAkC;AAChC,UAAO;IACL,MAAM,KAAK;IACX,MAAM,KAAK;IACX,SAAS,KAAK;IACd,YAAY,KAAK;IACjB,aAAa,KAAK;IAClB,SAAS,KAAK,gBAAgB,KAAK,QAAQ;IAC3C,OAAO,KAAK,OAAO;IACnB,OAAO,KAAK;IACb;;;;;EAMH,WAAmB;GACjB,IAAI,MAAM,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK;AAC/C,OAAI,KAAK,MACP,QAAO,gBAAgB,KAAK,MAAM,QAAQ;AAE5C,UAAO;;;;;EAMT,AAAQ,gBACN,SACqC;AACrC,OAAI,CAAC,QAAS,QAAO;GAErB,MAAM,YAAqC,EAAE;AAC7C,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,CAChD,KAAI,KAAK,iBAAiB,IAAI,CAC5B,WAAU,OAAO;YACR,OAAO,UAAU,YAAY,UAAU,KAEhD,WAAU,OAAO,MAAM,QAAQ,MAAM,GACjC,UAAU,MAAM,OAAO,MACvB;OAEJ,WAAU,OAAO;AAGrB,UAAO;;;;;EAMT,AAAQ,iBAAiB,WAA4B;AACnD,UAAO,yBAAyB,MAAM,YAAY,QAAQ,KAAK,UAAU,CAAC"}
@@ -6,12 +6,9 @@ var ConfigurationError;
6
6
  var init_configuration = __esmMin((() => {
7
7
  init_base();
8
8
  ConfigurationError = class ConfigurationError extends AppKitError {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.code = "CONFIGURATION_ERROR";
12
- this.statusCode = 500;
13
- this.isRetryable = false;
14
- }
9
+ code = "CONFIGURATION_ERROR";
10
+ statusCode = 500;
11
+ isRetryable = false;
15
12
  /**
16
13
  * Create a configuration error for missing environment variable
17
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"configuration.js","names":[],"sources":["../../src/errors/configuration.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when configuration is missing or invalid.\n * Use for missing environment variables, invalid settings, or setup issues.\n *\n * @example\n * ```typescript\n * throw new ConfigurationError(\"DATABRICKS_HOST environment variable is required\");\n * throw new ConfigurationError(\"Warehouse ID not found\", { context: { env: \"production\" } });\n * ```\n */\nexport class ConfigurationError extends AppKitError {\n readonly code = \"CONFIGURATION_ERROR\";\n readonly statusCode = 500;\n readonly isRetryable = false;\n\n /**\n * Create a configuration error for missing environment variable\n */\n static missingEnvVar(varName: string): ConfigurationError {\n return new ConfigurationError(\n `${varName} environment variable is required`,\n { context: { envVar: varName } },\n );\n }\n\n /**\n * Create a configuration error for missing resource\n */\n static resourceNotFound(resource: string, hint?: string): ConfigurationError {\n const message = hint\n ? `${resource} not found. ${hint}`\n : `${resource} not found`;\n return new ConfigurationError(message, { context: { resource } });\n }\n\n /**\n * Create a configuration error for invalid connection config\n */\n static invalidConnection(\n service: string,\n details?: string,\n ): ConfigurationError {\n const message = details\n ? `${service} connection not configured. ${details}`\n : `${service} connection not configured`;\n return new ConfigurationError(message, { context: { service } });\n }\n\n /**\n * Create a configuration error for missing connection string parameter\n */\n static missingConnectionParam(param: string): ConfigurationError {\n return new ConfigurationError(\n `Connection string must include ${param} parameter`,\n { context: { parameter: param } },\n );\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,qBAAb,MAAa,2BAA2B,YAAY;;;eAClC;qBACM;sBACC;;;;;EAKvB,OAAO,cAAc,SAAqC;AACxD,UAAO,IAAI,mBACT,GAAG,QAAQ,oCACX,EAAE,SAAS,EAAE,QAAQ,SAAS,EAAE,CACjC;;;;;EAMH,OAAO,iBAAiB,UAAkB,MAAmC;AAI3E,UAAO,IAAI,mBAHK,OACZ,GAAG,SAAS,cAAc,SAC1B,GAAG,SAAS,aACuB,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;;;;;EAMnE,OAAO,kBACL,SACA,SACoB;AAIpB,UAAO,IAAI,mBAHK,UACZ,GAAG,QAAQ,8BAA8B,YACzC,GAAG,QAAQ,6BACwB,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;;;;;EAMlE,OAAO,uBAAuB,OAAmC;AAC/D,UAAO,IAAI,mBACT,kCAAkC,MAAM,aACxC,EAAE,SAAS,EAAE,WAAW,OAAO,EAAE,CAClC"}
1
+ {"version":3,"file":"configuration.js","names":[],"sources":["../../src/errors/configuration.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when configuration is missing or invalid.\n * Use for missing environment variables, invalid settings, or setup issues.\n *\n * @example\n * ```typescript\n * throw new ConfigurationError(\"DATABRICKS_HOST environment variable is required\");\n * throw new ConfigurationError(\"Warehouse ID not found\", { context: { env: \"production\" } });\n * ```\n */\nexport class ConfigurationError extends AppKitError {\n readonly code = \"CONFIGURATION_ERROR\";\n readonly statusCode = 500;\n readonly isRetryable = false;\n\n /**\n * Create a configuration error for missing environment variable\n */\n static missingEnvVar(varName: string): ConfigurationError {\n return new ConfigurationError(\n `${varName} environment variable is required`,\n { context: { envVar: varName } },\n );\n }\n\n /**\n * Create a configuration error for missing resource\n */\n static resourceNotFound(resource: string, hint?: string): ConfigurationError {\n const message = hint\n ? `${resource} not found. ${hint}`\n : `${resource} not found`;\n return new ConfigurationError(message, { context: { resource } });\n }\n\n /**\n * Create a configuration error for invalid connection config\n */\n static invalidConnection(\n service: string,\n details?: string,\n ): ConfigurationError {\n const message = details\n ? `${service} connection not configured. ${details}`\n : `${service} connection not configured`;\n return new ConfigurationError(message, { context: { service } });\n }\n\n /**\n * Create a configuration error for missing connection string parameter\n */\n static missingConnectionParam(param: string): ConfigurationError {\n return new ConfigurationError(\n `Connection string must include ${param} parameter`,\n { context: { parameter: param } },\n );\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,qBAAb,MAAa,2BAA2B,YAAY;EAClD,AAAS,OAAO;EAChB,AAAS,aAAa;EACtB,AAAS,cAAc;;;;EAKvB,OAAO,cAAc,SAAqC;AACxD,UAAO,IAAI,mBACT,GAAG,QAAQ,oCACX,EAAE,SAAS,EAAE,QAAQ,SAAS,EAAE,CACjC;;;;;EAMH,OAAO,iBAAiB,UAAkB,MAAmC;AAI3E,UAAO,IAAI,mBAHK,OACZ,GAAG,SAAS,cAAc,SAC1B,GAAG,SAAS,aACuB,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;;;;;EAMnE,OAAO,kBACL,SACA,SACoB;AAIpB,UAAO,IAAI,mBAHK,UACZ,GAAG,QAAQ,8BAA8B,YACzC,GAAG,QAAQ,6BACwB,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;;;;;EAMlE,OAAO,uBAAuB,OAAmC;AAC/D,UAAO,IAAI,mBACT,kCAAkC,MAAM,aACxC,EAAE,SAAS,EAAE,WAAW,OAAO,EAAE,CAClC"}
@@ -6,12 +6,9 @@ var ConnectionError;
6
6
  var init_connection = __esmMin((() => {
7
7
  init_base();
8
8
  ConnectionError = class ConnectionError extends AppKitError {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.code = "CONNECTION_ERROR";
12
- this.statusCode = 503;
13
- this.isRetryable = true;
14
- }
9
+ code = "CONNECTION_ERROR";
10
+ statusCode = 503;
11
+ isRetryable = true;
15
12
  /**
16
13
  * Create a connection error for query failure
17
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","names":[],"sources":["../../src/errors/connection.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when a connection or network operation fails.\n * Use for database pool errors, API failures, timeouts, etc.\n *\n * @example\n * ```typescript\n * throw new ConnectionError(\"Query failed\", { cause: pgError });\n * throw new ConnectionError(\"No response received from SQL Warehouse API\");\n * ```\n */\nexport class ConnectionError extends AppKitError {\n readonly code = \"CONNECTION_ERROR\";\n readonly statusCode = 503;\n readonly isRetryable = true;\n\n /**\n * Create a connection error for query failure\n */\n static queryFailed(cause?: Error): ConnectionError {\n return new ConnectionError(\"Query failed\", { cause });\n }\n\n /**\n * Create a connection error for transaction failure\n */\n static transactionFailed(cause?: Error): ConnectionError {\n return new ConnectionError(\"Transaction failed\", { cause });\n }\n\n /**\n * Create a connection error for pool errors\n */\n static poolError(operation: string, cause?: Error): ConnectionError {\n return new ConnectionError(`Connection pool error: ${operation}`, {\n cause,\n });\n }\n\n /**\n * Create a connection error for API failures\n */\n static apiFailure(service: string, cause?: Error): ConnectionError {\n return new ConnectionError(`No response received from ${service} API`, {\n cause,\n context: { service },\n });\n }\n\n /**\n * Create a connection error for client unavailable\n */\n static clientUnavailable(clientType: string, hint?: string): ConnectionError {\n const message = hint\n ? `${clientType} not available. ${hint}`\n : `${clientType} not available`;\n return new ConnectionError(message, { context: { clientType } });\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,kBAAb,MAAa,wBAAwB,YAAY;;;eAC/B;qBACM;sBACC;;;;;EAKvB,OAAO,YAAY,OAAgC;AACjD,UAAO,IAAI,gBAAgB,gBAAgB,EAAE,OAAO,CAAC;;;;;EAMvD,OAAO,kBAAkB,OAAgC;AACvD,UAAO,IAAI,gBAAgB,sBAAsB,EAAE,OAAO,CAAC;;;;;EAM7D,OAAO,UAAU,WAAmB,OAAgC;AAClE,UAAO,IAAI,gBAAgB,0BAA0B,aAAa,EAChE,OACD,CAAC;;;;;EAMJ,OAAO,WAAW,SAAiB,OAAgC;AACjE,UAAO,IAAI,gBAAgB,6BAA6B,QAAQ,OAAO;IACrE;IACA,SAAS,EAAE,SAAS;IACrB,CAAC;;;;;EAMJ,OAAO,kBAAkB,YAAoB,MAAgC;AAI3E,UAAO,IAAI,gBAHK,OACZ,GAAG,WAAW,kBAAkB,SAChC,GAAG,WAAW,iBACkB,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"connection.js","names":[],"sources":["../../src/errors/connection.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when a connection or network operation fails.\n * Use for database pool errors, API failures, timeouts, etc.\n *\n * @example\n * ```typescript\n * throw new ConnectionError(\"Query failed\", { cause: pgError });\n * throw new ConnectionError(\"No response received from SQL Warehouse API\");\n * ```\n */\nexport class ConnectionError extends AppKitError {\n readonly code = \"CONNECTION_ERROR\";\n readonly statusCode = 503;\n readonly isRetryable = true;\n\n /**\n * Create a connection error for query failure\n */\n static queryFailed(cause?: Error): ConnectionError {\n return new ConnectionError(\"Query failed\", { cause });\n }\n\n /**\n * Create a connection error for transaction failure\n */\n static transactionFailed(cause?: Error): ConnectionError {\n return new ConnectionError(\"Transaction failed\", { cause });\n }\n\n /**\n * Create a connection error for pool errors\n */\n static poolError(operation: string, cause?: Error): ConnectionError {\n return new ConnectionError(`Connection pool error: ${operation}`, {\n cause,\n });\n }\n\n /**\n * Create a connection error for API failures\n */\n static apiFailure(service: string, cause?: Error): ConnectionError {\n return new ConnectionError(`No response received from ${service} API`, {\n cause,\n context: { service },\n });\n }\n\n /**\n * Create a connection error for client unavailable\n */\n static clientUnavailable(clientType: string, hint?: string): ConnectionError {\n const message = hint\n ? `${clientType} not available. ${hint}`\n : `${clientType} not available`;\n return new ConnectionError(message, { context: { clientType } });\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,kBAAb,MAAa,wBAAwB,YAAY;EAC/C,AAAS,OAAO;EAChB,AAAS,aAAa;EACtB,AAAS,cAAc;;;;EAKvB,OAAO,YAAY,OAAgC;AACjD,UAAO,IAAI,gBAAgB,gBAAgB,EAAE,OAAO,CAAC;;;;;EAMvD,OAAO,kBAAkB,OAAgC;AACvD,UAAO,IAAI,gBAAgB,sBAAsB,EAAE,OAAO,CAAC;;;;;EAM7D,OAAO,UAAU,WAAmB,OAAgC;AAClE,UAAO,IAAI,gBAAgB,0BAA0B,aAAa,EAChE,OACD,CAAC;;;;;EAMJ,OAAO,WAAW,SAAiB,OAAgC;AACjE,UAAO,IAAI,gBAAgB,6BAA6B,QAAQ,OAAO;IACrE;IACA,SAAS,EAAE,SAAS;IACrB,CAAC;;;;;EAMJ,OAAO,kBAAkB,YAAoB,MAAgC;AAI3E,UAAO,IAAI,gBAHK,OACZ,GAAG,WAAW,kBAAkB,SAChC,GAAG,WAAW,iBACkB,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC"}
@@ -6,12 +6,9 @@ var ExecutionError;
6
6
  var init_execution = __esmMin((() => {
7
7
  init_base();
8
8
  ExecutionError = class ExecutionError extends AppKitError {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.code = "EXECUTION_ERROR";
12
- this.statusCode = 500;
13
- this.isRetryable = false;
14
- }
9
+ code = "EXECUTION_ERROR";
10
+ statusCode = 500;
11
+ isRetryable = false;
15
12
  /**
16
13
  * Create an execution error for statement failure
17
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"execution.js","names":[],"sources":["../../src/errors/execution.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when an operation execution fails.\n * Use for statement failures, canceled operations, or unexpected states.\n *\n * @example\n * ```typescript\n * throw new ExecutionError(\"Statement failed: syntax error\");\n * throw new ExecutionError(\"Statement was canceled\");\n * ```\n */\nexport class ExecutionError extends AppKitError {\n readonly code = \"EXECUTION_ERROR\";\n readonly statusCode = 500;\n readonly isRetryable = false;\n\n /**\n * Create an execution error for statement failure\n */\n static statementFailed(errorMessage?: string): ExecutionError {\n const message = errorMessage\n ? `Statement failed: ${errorMessage}`\n : \"Statement failed: Unknown error\";\n return new ExecutionError(message);\n }\n\n /**\n * Create an execution error for canceled operation\n */\n static canceled(): ExecutionError {\n return new ExecutionError(\"Statement was canceled\");\n }\n\n /**\n * Create an execution error for closed/expired results\n */\n static resultsClosed(): ExecutionError {\n return new ExecutionError(\n \"Statement execution completed but results are no longer available (CLOSED state)\",\n );\n }\n\n /**\n * Create an execution error for unknown state\n */\n static unknownState(state: string): ExecutionError {\n return new ExecutionError(`Unknown statement state: ${state}`, {\n context: { state },\n });\n }\n\n /**\n * Create an execution error for missing data\n */\n static missingData(dataType: string): ExecutionError {\n return new ExecutionError(`No ${dataType} found in response`, {\n context: { dataType },\n });\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,iBAAb,MAAa,uBAAuB,YAAY;;;eAC9B;qBACM;sBACC;;;;;EAKvB,OAAO,gBAAgB,cAAuC;AAI5D,UAAO,IAAI,eAHK,eACZ,qBAAqB,iBACrB,kCAC8B;;;;;EAMpC,OAAO,WAA2B;AAChC,UAAO,IAAI,eAAe,yBAAyB;;;;;EAMrD,OAAO,gBAAgC;AACrC,UAAO,IAAI,eACT,mFACD;;;;;EAMH,OAAO,aAAa,OAA+B;AACjD,UAAO,IAAI,eAAe,4BAA4B,SAAS,EAC7D,SAAS,EAAE,OAAO,EACnB,CAAC;;;;;EAMJ,OAAO,YAAY,UAAkC;AACnD,UAAO,IAAI,eAAe,MAAM,SAAS,qBAAqB,EAC5D,SAAS,EAAE,UAAU,EACtB,CAAC"}
1
+ {"version":3,"file":"execution.js","names":[],"sources":["../../src/errors/execution.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when an operation execution fails.\n * Use for statement failures, canceled operations, or unexpected states.\n *\n * @example\n * ```typescript\n * throw new ExecutionError(\"Statement failed: syntax error\");\n * throw new ExecutionError(\"Statement was canceled\");\n * ```\n */\nexport class ExecutionError extends AppKitError {\n readonly code = \"EXECUTION_ERROR\";\n readonly statusCode = 500;\n readonly isRetryable = false;\n\n /**\n * Create an execution error for statement failure\n */\n static statementFailed(errorMessage?: string): ExecutionError {\n const message = errorMessage\n ? `Statement failed: ${errorMessage}`\n : \"Statement failed: Unknown error\";\n return new ExecutionError(message);\n }\n\n /**\n * Create an execution error for canceled operation\n */\n static canceled(): ExecutionError {\n return new ExecutionError(\"Statement was canceled\");\n }\n\n /**\n * Create an execution error for closed/expired results\n */\n static resultsClosed(): ExecutionError {\n return new ExecutionError(\n \"Statement execution completed but results are no longer available (CLOSED state)\",\n );\n }\n\n /**\n * Create an execution error for unknown state\n */\n static unknownState(state: string): ExecutionError {\n return new ExecutionError(`Unknown statement state: ${state}`, {\n context: { state },\n });\n }\n\n /**\n * Create an execution error for missing data\n */\n static missingData(dataType: string): ExecutionError {\n return new ExecutionError(`No ${dataType} found in response`, {\n context: { dataType },\n });\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,iBAAb,MAAa,uBAAuB,YAAY;EAC9C,AAAS,OAAO;EAChB,AAAS,aAAa;EACtB,AAAS,cAAc;;;;EAKvB,OAAO,gBAAgB,cAAuC;AAI5D,UAAO,IAAI,eAHK,eACZ,qBAAqB,iBACrB,kCAC8B;;;;;EAMpC,OAAO,WAA2B;AAChC,UAAO,IAAI,eAAe,yBAAyB;;;;;EAMrD,OAAO,gBAAgC;AACrC,UAAO,IAAI,eACT,mFACD;;;;;EAMH,OAAO,aAAa,OAA+B;AACjD,UAAO,IAAI,eAAe,4BAA4B,SAAS,EAC7D,SAAS,EAAE,OAAO,EACnB,CAAC;;;;;EAMJ,OAAO,YAAY,UAAkC;AACnD,UAAO,IAAI,eAAe,MAAM,SAAS,qBAAqB,EAC5D,SAAS,EAAE,UAAU,EACtB,CAAC"}
@@ -6,12 +6,9 @@ var InitializationError;
6
6
  var init_initialization = __esmMin((() => {
7
7
  init_base();
8
8
  InitializationError = class InitializationError extends AppKitError {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.code = "INITIALIZATION_ERROR";
12
- this.statusCode = 500;
13
- this.isRetryable = true;
14
- }
9
+ code = "INITIALIZATION_ERROR";
10
+ statusCode = 500;
11
+ isRetryable = true;
15
12
  /**
16
13
  * Create an initialization error for a service that is not ready
17
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"initialization.js","names":[],"sources":["../../src/errors/initialization.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when a service or component is not properly initialized.\n * Use when accessing services before they are ready.\n *\n * @example\n * ```typescript\n * throw new InitializationError(\"CacheManager not initialized\");\n * throw new InitializationError(\"ServiceContext not initialized. Call ServiceContext.initialize() first.\");\n * ```\n */\nexport class InitializationError extends AppKitError {\n readonly code = \"INITIALIZATION_ERROR\";\n readonly statusCode = 500;\n readonly isRetryable = true;\n\n /**\n * Create an initialization error for a service that is not ready\n */\n static notInitialized(\n serviceName: string,\n hint?: string,\n ): InitializationError {\n const message = hint\n ? `${serviceName} not initialized. ${hint}`\n : `${serviceName} not initialized`;\n return new InitializationError(message, {\n context: { service: serviceName },\n });\n }\n\n /**\n * Create an initialization error for setup failure\n */\n static setupFailed(component: string, cause?: Error): InitializationError {\n return new InitializationError(`Failed to initialize ${component}`, {\n cause,\n context: { component },\n });\n }\n\n /**\n * Create an initialization error for migration failure\n */\n static migrationFailed(cause?: Error): InitializationError {\n return new InitializationError(\n \"Error in running migrations for persistent storage\",\n { cause },\n );\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,sBAAb,MAAa,4BAA4B,YAAY;;;eACnC;qBACM;sBACC;;;;;EAKvB,OAAO,eACL,aACA,MACqB;AAIrB,UAAO,IAAI,oBAHK,OACZ,GAAG,YAAY,oBAAoB,SACnC,GAAG,YAAY,mBACqB,EACtC,SAAS,EAAE,SAAS,aAAa,EAClC,CAAC;;;;;EAMJ,OAAO,YAAY,WAAmB,OAAoC;AACxE,UAAO,IAAI,oBAAoB,wBAAwB,aAAa;IAClE;IACA,SAAS,EAAE,WAAW;IACvB,CAAC;;;;;EAMJ,OAAO,gBAAgB,OAAoC;AACzD,UAAO,IAAI,oBACT,sDACA,EAAE,OAAO,CACV"}
1
+ {"version":3,"file":"initialization.js","names":[],"sources":["../../src/errors/initialization.ts"],"sourcesContent":["import { AppKitError } from \"./base\";\n\n/**\n * Error thrown when a service or component is not properly initialized.\n * Use when accessing services before they are ready.\n *\n * @example\n * ```typescript\n * throw new InitializationError(\"CacheManager not initialized\");\n * throw new InitializationError(\"ServiceContext not initialized. Call ServiceContext.initialize() first.\");\n * ```\n */\nexport class InitializationError extends AppKitError {\n readonly code = \"INITIALIZATION_ERROR\";\n readonly statusCode = 500;\n readonly isRetryable = true;\n\n /**\n * Create an initialization error for a service that is not ready\n */\n static notInitialized(\n serviceName: string,\n hint?: string,\n ): InitializationError {\n const message = hint\n ? `${serviceName} not initialized. ${hint}`\n : `${serviceName} not initialized`;\n return new InitializationError(message, {\n context: { service: serviceName },\n });\n }\n\n /**\n * Create an initialization error for setup failure\n */\n static setupFailed(component: string, cause?: Error): InitializationError {\n return new InitializationError(`Failed to initialize ${component}`, {\n cause,\n context: { component },\n });\n }\n\n /**\n * Create an initialization error for migration failure\n */\n static migrationFailed(cause?: Error): InitializationError {\n return new InitializationError(\n \"Error in running migrations for persistent storage\",\n { cause },\n );\n }\n}\n"],"mappings":";;;;;;YAAqC;CAYxB,sBAAb,MAAa,4BAA4B,YAAY;EACnD,AAAS,OAAO;EAChB,AAAS,aAAa;EACtB,AAAS,cAAc;;;;EAKvB,OAAO,eACL,aACA,MACqB;AAIrB,UAAO,IAAI,oBAHK,OACZ,GAAG,YAAY,oBAAoB,SACnC,GAAG,YAAY,mBACqB,EACtC,SAAS,EAAE,SAAS,aAAa,EAClC,CAAC;;;;;EAMJ,OAAO,YAAY,WAAmB,OAAoC;AACxE,UAAO,IAAI,oBAAoB,wBAAwB,aAAa;IAClE;IACA,SAAS,EAAE,WAAW;IACvB,CAAC;;;;;EAMJ,OAAO,gBAAgB,OAAoC;AACzD,UAAO,IAAI,oBACT,sDACA,EAAE,OAAO,CACV"}
@@ -6,12 +6,9 @@ var ServerError;
6
6
  var init_server = __esmMin((() => {
7
7
  init_base();
8
8
  ServerError = class ServerError extends AppKitError {
9
- constructor(..._args) {
10
- super(..._args);
11
- this.code = "SERVER_ERROR";
12
- this.statusCode = 500;
13
- this.isRetryable = false;
14
- }
9
+ code = "SERVER_ERROR";
10
+ statusCode = 500;
11
+ isRetryable = false;
15
12
  /**
16
13
  * Create a server error for autoStart conflict
17
14
  */