@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.
- package/CLAUDE.md +1 -0
- package/dist/analytics/analytics.d.ts +11 -1
- package/dist/analytics/analytics.d.ts.map +1 -1
- package/dist/analytics/analytics.js +12 -5
- package/dist/analytics/analytics.js.map +1 -1
- package/dist/appkit/package.js +1 -1
- package/dist/cache/index.js +11 -10
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/storage/memory.js +4 -2
- package/dist/cache/storage/memory.js.map +1 -1
- package/dist/cache/storage/persistent.js +7 -0
- package/dist/cache/storage/persistent.js.map +1 -1
- package/dist/connectors/lakebase/client.js +8 -4
- package/dist/connectors/lakebase/client.js.map +1 -1
- package/dist/connectors/sql-warehouse/client.js +5 -2
- package/dist/connectors/sql-warehouse/client.js.map +1 -1
- package/dist/context/execution-context.d.ts +17 -0
- package/dist/context/execution-context.d.ts.map +1 -0
- package/dist/context/service-context.d.ts +21 -0
- package/dist/context/service-context.d.ts.map +1 -0
- package/dist/context/service-context.js +2 -6
- package/dist/context/service-context.js.map +1 -1
- package/dist/context/user-context.d.ts +29 -0
- package/dist/context/user-context.d.ts.map +1 -0
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/core/appkit.js +35 -12
- package/dist/core/appkit.js.map +1 -1
- package/dist/errors/authentication.js +3 -6
- package/dist/errors/authentication.js.map +1 -1
- package/dist/errors/base.js +4 -0
- package/dist/errors/base.js.map +1 -1
- package/dist/errors/configuration.js +3 -6
- package/dist/errors/configuration.js.map +1 -1
- package/dist/errors/connection.js +3 -6
- package/dist/errors/connection.js.map +1 -1
- package/dist/errors/execution.js +3 -6
- package/dist/errors/execution.js.map +1 -1
- package/dist/errors/initialization.js +3 -6
- package/dist/errors/initialization.js.map +1 -1
- package/dist/errors/server.js +3 -6
- package/dist/errors/server.js.map +1 -1
- package/dist/errors/tunnel.js +3 -6
- package/dist/errors/tunnel.js.map +1 -1
- package/dist/errors/validation.js +3 -6
- package/dist/errors/validation.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/logging/wide-event-emitter.js +1 -3
- package/dist/logging/wide-event-emitter.js.map +1 -1
- package/dist/logging/wide-event.js +2 -0
- package/dist/logging/wide-event.js.map +1 -1
- package/dist/plugin/dev-reader.js +3 -6
- package/dist/plugin/dev-reader.js.map +1 -1
- package/dist/plugin/interceptors/retry.js +3 -0
- package/dist/plugin/interceptors/retry.js.map +1 -1
- package/dist/plugin/plugin.d.ts +10 -24
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js +23 -30
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/server/base-server.js +2 -0
- package/dist/server/base-server.js.map +1 -1
- package/dist/server/index.d.ts +23 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +29 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/remote-tunnel/remote-tunnel-controller.js +30 -15
- package/dist/server/remote-tunnel/remote-tunnel-controller.js.map +1 -1
- package/dist/server/remote-tunnel/remote-tunnel-manager.js +5 -1
- package/dist/server/remote-tunnel/remote-tunnel-manager.js.map +1 -1
- package/dist/server/static-server.js +1 -0
- package/dist/server/static-server.js.map +1 -1
- package/dist/server/vite-dev-server.js +1 -0
- package/dist/server/vite-dev-server.js.map +1 -1
- package/dist/shared/src/plugin.d.ts +25 -1
- package/dist/shared/src/plugin.d.ts.map +1 -1
- package/dist/stream/arrow-stream-processor.js +5 -10
- package/dist/stream/arrow-stream-processor.js.map +1 -1
- package/dist/stream/buffers.js +7 -0
- package/dist/stream/buffers.js.map +1 -1
- package/dist/stream/stream-manager.js +5 -0
- package/dist/stream/stream-manager.js.map +1 -1
- package/dist/stream/stream-registry.js +1 -0
- package/dist/stream/stream-registry.js.map +1 -1
- package/dist/stream/validator.js +2 -6
- package/dist/stream/validator.js.map +1 -1
- package/dist/telemetry/noop.js +1 -0
- package/dist/telemetry/noop.js.map +1 -1
- package/dist/telemetry/telemetry-manager.js +4 -6
- package/dist/telemetry/telemetry-manager.js.map +1 -1
- package/dist/telemetry/telemetry-provider.js +3 -0
- package/dist/telemetry/telemetry-provider.js.map +1 -1
- package/dist/type-generator/spinner.js +9 -11
- package/dist/type-generator/spinner.js.map +1 -1
- package/docs/docs/api/appkit/Class.AppKitError/index.html +5 -3
- package/docs/docs/api/appkit/Class.AppKitError.md +7 -0
- package/docs/docs/api/appkit/Class.AuthenticationError/index.html +3 -3
- package/docs/docs/api/appkit/Class.ConfigurationError/index.html +3 -3
- package/docs/docs/api/appkit/Class.ConnectionError/index.html +3 -3
- package/docs/docs/api/appkit/Class.ExecutionError/index.html +3 -3
- package/docs/docs/api/appkit/Class.InitializationError/index.html +3 -3
- package/docs/docs/api/appkit/Class.Plugin/index.html +28 -21
- package/docs/docs/api/appkit/Class.Plugin.md +34 -34
- package/docs/docs/api/appkit/Class.ServerError/index.html +3 -3
- package/docs/docs/api/appkit/Class.TunnelError/index.html +3 -3
- package/docs/docs/api/appkit/Class.ValidationError/index.html +3 -3
- package/docs/docs/api/appkit/Function.appKitTypesPlugin/index.html +3 -3
- package/docs/docs/api/appkit/Function.createApp/index.html +4 -4
- package/docs/docs/api/appkit/Function.getExecutionContext/index.html +26 -0
- package/docs/docs/api/appkit/Function.getExecutionContext.md +19 -0
- package/docs/docs/api/appkit/Function.isSQLTypeMarker/index.html +4 -4
- package/docs/docs/api/appkit/Interface.BasePluginConfig/index.html +3 -3
- package/docs/docs/api/appkit/Interface.CacheConfig/index.html +3 -3
- package/docs/docs/api/appkit/Interface.ITelemetry/index.html +3 -3
- package/docs/docs/api/appkit/Interface.StreamExecutionSettings/index.html +3 -3
- package/docs/docs/api/appkit/Interface.TelemetryConfig/index.html +3 -3
- package/docs/docs/api/appkit/TypeAlias.IAppRouter/index.html +3 -3
- package/docs/docs/api/appkit/Variable.sql/index.html +3 -3
- package/docs/docs/api/appkit/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/AreaChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/BarChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/DataTable/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/DonutChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/HeatmapChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/LineChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/PieChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/RadarChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/ScatterChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/index.html +2 -2
- package/docs/docs/api/appkit-ui/styling/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Accordion/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Alert/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/AlertDialog/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/AspectRatio/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Avatar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Badge/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Breadcrumb/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Button/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ButtonGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Calendar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Card/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Carousel/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ChartContainer/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Checkbox/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Collapsible/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Command/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ContextMenu/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Dialog/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Drawer/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/DropdownMenu/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Empty/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Field/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/FormControl/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/HoverCard/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Input/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/InputGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/InputOTP/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Item/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Kbd/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Label/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Menubar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/NavigationMenu/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Pagination/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Popover/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Progress/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/RadioGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ResizableHandle/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ScrollArea/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Select/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Separator/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Sheet/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Sidebar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Skeleton/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Slider/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Spinner/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Switch/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Table/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Tabs/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Textarea/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Toaster/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Toggle/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ToggleGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Tooltip/index.html +2 -2
- package/docs/docs/api/appkit.md +6 -5
- package/docs/docs/api/index.html +2 -2
- package/docs/docs/app-management/index.html +2 -2
- package/docs/docs/architecture/index.html +2 -2
- package/docs/docs/category/development/index.html +2 -2
- package/docs/docs/configuration/index.html +2 -2
- package/docs/docs/core-principles/index.html +2 -2
- package/docs/docs/development/index.html +2 -2
- package/docs/docs/development/llm-guide/index.html +2 -2
- package/docs/docs/development/local-development/index.html +2 -2
- package/docs/docs/development/project-setup/index.html +2 -2
- package/docs/docs/development/remote-bridge/index.html +2 -2
- package/docs/docs/development/type-generation/index.html +2 -2
- package/docs/docs/index.html +2 -2
- package/docs/docs/plugins/index.html +7 -3
- package/docs/docs/plugins.md +36 -11
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-manager.js","names":[],"sources":["../../src/stream/stream-manager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { context } from \"@opentelemetry/api\";\nimport type { IAppResponse, StreamConfig } from \"shared\";\nimport { EventRingBuffer } from \"./buffers\";\nimport { streamDefaults } from \"./defaults\";\nimport { SSEWriter } from \"./sse-writer\";\nimport { StreamRegistry } from \"./stream-registry\";\nimport { SSEErrorCode, type StreamEntry, type StreamOperation } from \"./types\";\nimport { StreamValidator } from \"./validator\";\n\n// main entry point for Server-Sent events streaming\nexport class StreamManager {\n private activeOperations: Set<StreamOperation>;\n private streamRegistry: StreamRegistry;\n private sseWriter: SSEWriter;\n private maxEventSize: number;\n private bufferTTL: number;\n\n constructor(options?: StreamConfig) {\n this.streamRegistry = new StreamRegistry(\n options?.maxActiveStreams ?? streamDefaults.maxActiveStreams,\n );\n this.sseWriter = new SSEWriter();\n this.maxEventSize = options?.maxEventSize ?? streamDefaults.maxEventSize;\n this.bufferTTL = options?.bufferTTL ?? streamDefaults.bufferTTL;\n this.activeOperations = new Set();\n }\n\n // main streaming method - handles new connection and reconnection\n async stream(\n res: IAppResponse,\n handler: (signal: AbortSignal) => AsyncGenerator<any, void, unknown>,\n options?: StreamConfig,\n ): Promise<void> {\n const { streamId } = options || {};\n\n // check if response is already closed\n if (res.writableEnded || res.destroyed) {\n return;\n }\n\n // setup SSE headers\n this.sseWriter.setupHeaders(res);\n\n // handle reconnection\n if (streamId && StreamValidator.validateStreamId(streamId)) {\n const existingStream = this.streamRegistry.get(streamId);\n // if stream exists, attach to it\n if (existingStream) {\n return this._attachToExistingStream(res, existingStream, options);\n }\n }\n\n // if stream does not exist, create a new one\n return this._createNewStream(res, handler, options);\n }\n\n // abort all active operations\n abortAll(): void {\n this.activeOperations.forEach((operation) => {\n if (operation.heartbeat) clearInterval(operation.heartbeat);\n operation.controller.abort(\"Server shutdown\");\n });\n this.activeOperations.clear();\n this.streamRegistry.clear();\n }\n\n // get the number of active operations\n getActiveCount(): number {\n return this.activeOperations.size;\n }\n\n // attach to existing stream\n private async _attachToExistingStream(\n res: IAppResponse,\n streamEntry: StreamEntry,\n options?: StreamConfig,\n ): Promise<void> {\n // handle reconnection - replay missed events\n const lastEventId = res.req?.headers[\"last-event-id\"];\n\n if (StreamValidator.validateEventId(lastEventId)) {\n // cast to string after validation\n const validEventId = lastEventId as string;\n if (streamEntry.eventBuffer.has(validEventId)) {\n const missedEvents =\n streamEntry.eventBuffer.getEventsSince(validEventId);\n // broadcast missed events to client\n for (const event of missedEvents) {\n if (options?.userSignal?.aborted) break;\n this.sseWriter.writeBufferedEvent(res, event);\n }\n } else {\n // buffer overflow - send warning\n this.sseWriter.writeBufferOverflowWarning(res, validEventId);\n }\n }\n\n // add client to stream entry\n streamEntry.clients.add(res);\n streamEntry.lastAccess = Date.now();\n\n // start heartbeat\n const combinedSignal = this._combineSignals(\n streamEntry.abortController.signal,\n options?.userSignal,\n );\n const heartbeat = this.sseWriter.startHeartbeat(res, combinedSignal);\n\n // track operation\n const streamOperation: StreamOperation = {\n controller: streamEntry.abortController,\n type: \"stream\",\n heartbeat,\n };\n this.activeOperations.add(streamOperation);\n\n // handle client disconnect\n res.on(\"close\", () => {\n clearInterval(heartbeat);\n streamEntry.clients.delete(res);\n this.activeOperations.delete(streamOperation);\n\n // cleanup if stream is completed and no clients are connected\n if (streamEntry.isCompleted && streamEntry.clients.size === 0) {\n setTimeout(() => {\n if (streamEntry.clients.size === 0) {\n this.streamRegistry.remove(streamEntry.streamId);\n }\n }, this.bufferTTL);\n }\n });\n\n // if stream is completed, close connection\n if (streamEntry.isCompleted) {\n res.end();\n // cleanup operation\n this.activeOperations.delete(streamOperation);\n clearInterval(heartbeat);\n }\n }\n private async _createNewStream(\n res: IAppResponse,\n handler: (signal: AbortSignal) => AsyncGenerator<any, void, unknown>,\n options?: StreamConfig,\n ): Promise<void> {\n const streamId = options?.streamId ?? randomUUID();\n\n // abort stream if response is closed\n if (res.writableEnded || res.destroyed) {\n return;\n }\n\n const abortController = new AbortController();\n\n // create event buffer\n const eventBuffer = new EventRingBuffer(\n options?.bufferSize ?? streamDefaults.bufferSize,\n );\n\n // setup signals and heartbeat\n const combinedSignal = this._combineSignals(\n abortController.signal,\n options?.userSignal,\n );\n const heartbeat = this.sseWriter.startHeartbeat(res, combinedSignal);\n\n // capture the current trace context at stream creation time\n const traceContext = context.active();\n\n // abort stream if response is closed\n if (res.writableEnded || res.destroyed) {\n clearInterval(heartbeat);\n return;\n }\n\n // create stream entry\n const streamEntry: StreamEntry = {\n streamId,\n generator: handler(combinedSignal),\n eventBuffer,\n clients: new Set([res]),\n isCompleted: false,\n lastAccess: Date.now(),\n abortController,\n traceContext,\n };\n this.streamRegistry.add(streamEntry);\n\n // track operation\n const streamOperation: StreamOperation = {\n controller: abortController,\n type: \"stream\",\n heartbeat,\n };\n this.activeOperations.add(streamOperation);\n\n res.on(\"close\", () => {\n clearInterval(heartbeat);\n this.activeOperations.delete(streamOperation);\n streamEntry.clients.delete(res);\n });\n\n await this._processGeneratorInBackground(streamEntry);\n\n // cleanup\n clearInterval(heartbeat);\n this.activeOperations.delete(streamOperation);\n }\n\n private async _processGeneratorInBackground(\n streamEntry: StreamEntry,\n ): Promise<void> {\n // run the entire generator processing within the captured trace context\n return context.with(streamEntry.traceContext, async () => {\n try {\n // retrieve all events from generator\n for await (const event of streamEntry.generator) {\n if (streamEntry.abortController.signal.aborted) break;\n const eventId = randomUUID();\n const eventData = JSON.stringify(event);\n\n // validate event size\n if (eventData.length > this.maxEventSize) {\n const errorMsg = `Event exceeds max size of ${this.maxEventSize} bytes`;\n const errorCode = SSEErrorCode.INVALID_REQUEST;\n // broadcast error to all connected clients\n this._broadcastErrorToClients(\n streamEntry,\n eventId,\n errorMsg,\n errorCode,\n );\n continue;\n }\n\n // buffer event for reconnection\n streamEntry.eventBuffer.add({\n id: eventId,\n type: event.type,\n data: eventData,\n timestamp: Date.now(),\n });\n\n // broadcast to all connected clients\n this._broadcastEventsToClients(streamEntry, eventId, event);\n streamEntry.lastAccess = Date.now();\n }\n\n streamEntry.isCompleted = true;\n\n // close all clients\n this._closeAllClients(streamEntry);\n\n // cleanup if no clients are connected\n this._cleanupStream(streamEntry);\n } catch (error) {\n const errorMsg =\n error instanceof Error ? error.message : \"Internal server error\";\n const errorEventId = randomUUID();\n const errorCode = this._categorizeError(error);\n\n // buffer error event\n streamEntry.eventBuffer.add({\n id: errorEventId,\n type: \"error\",\n data: JSON.stringify({ error: errorMsg, code: errorCode }),\n timestamp: Date.now(),\n });\n\n // send error event to all connected clients\n this._broadcastErrorToClients(\n streamEntry,\n errorEventId,\n errorMsg,\n errorCode,\n true,\n );\n streamEntry.isCompleted = true;\n }\n });\n }\n\n private _combineSignals(\n internalSignal?: AbortSignal,\n userSignal?: AbortSignal,\n ): AbortSignal {\n if (!userSignal) return internalSignal || new AbortController().signal;\n\n const signals = [internalSignal, userSignal].filter(\n Boolean,\n ) as AbortSignal[];\n const controller = new AbortController();\n\n signals.forEach((signal) => {\n if (signal?.aborted) {\n controller.abort(signal.reason);\n return;\n }\n\n signal?.addEventListener(\n \"abort\",\n () => {\n controller.abort(signal.reason);\n },\n { once: true },\n );\n });\n return controller.signal;\n }\n\n // broadcast events to all connected clients\n private _broadcastEventsToClients(\n streamEntry: StreamEntry,\n eventId: string,\n event: any,\n ): void {\n for (const client of streamEntry.clients) {\n if (!client.writableEnded) {\n this.sseWriter.writeEvent(client, eventId, event);\n }\n }\n }\n\n // broadcast error to all connected clients\n private _broadcastErrorToClients(\n streamEntry: StreamEntry,\n eventId: string,\n errorMessage: string,\n errorCode: SSEErrorCode,\n closeClients: boolean = false,\n ): void {\n for (const client of streamEntry.clients) {\n if (!client.writableEnded) {\n this.sseWriter.writeError(client, eventId, errorMessage, errorCode);\n if (closeClients) {\n client.end();\n }\n }\n }\n }\n\n // close all connected clients\n private _closeAllClients(streamEntry: StreamEntry): void {\n for (const client of streamEntry.clients) {\n if (!client.writableEnded) {\n client.end();\n }\n }\n }\n\n // cleanup stream if no clients are connected\n private _cleanupStream(streamEntry: StreamEntry): void {\n if (streamEntry.clients.size === 0) {\n setTimeout(() => {\n if (streamEntry.clients.size === 0) {\n this.streamRegistry.remove(streamEntry.streamId);\n }\n }, this.bufferTTL);\n }\n }\n\n private _categorizeError(error: unknown): SSEErrorCode {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n if (message.includes(\"timeout\") || message.includes(\"timed out\")) {\n return SSEErrorCode.TIMEOUT;\n }\n\n if (message.includes(\"unavailable\") || message.includes(\"econnrefused\")) {\n return SSEErrorCode.TEMPORARY_UNAVAILABLE;\n }\n\n if (error.name === \"AbortError\") {\n return SSEErrorCode.STREAM_ABORTED;\n }\n }\n\n return SSEErrorCode.INTERNAL_ERROR;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stream-manager.js","names":[],"sources":["../../src/stream/stream-manager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { context } from \"@opentelemetry/api\";\nimport type { IAppResponse, StreamConfig } from \"shared\";\nimport { EventRingBuffer } from \"./buffers\";\nimport { streamDefaults } from \"./defaults\";\nimport { SSEWriter } from \"./sse-writer\";\nimport { StreamRegistry } from \"./stream-registry\";\nimport { SSEErrorCode, type StreamEntry, type StreamOperation } from \"./types\";\nimport { StreamValidator } from \"./validator\";\n\n// main entry point for Server-Sent events streaming\nexport class StreamManager {\n private activeOperations: Set<StreamOperation>;\n private streamRegistry: StreamRegistry;\n private sseWriter: SSEWriter;\n private maxEventSize: number;\n private bufferTTL: number;\n\n constructor(options?: StreamConfig) {\n this.streamRegistry = new StreamRegistry(\n options?.maxActiveStreams ?? streamDefaults.maxActiveStreams,\n );\n this.sseWriter = new SSEWriter();\n this.maxEventSize = options?.maxEventSize ?? streamDefaults.maxEventSize;\n this.bufferTTL = options?.bufferTTL ?? streamDefaults.bufferTTL;\n this.activeOperations = new Set();\n }\n\n // main streaming method - handles new connection and reconnection\n async stream(\n res: IAppResponse,\n handler: (signal: AbortSignal) => AsyncGenerator<any, void, unknown>,\n options?: StreamConfig,\n ): Promise<void> {\n const { streamId } = options || {};\n\n // check if response is already closed\n if (res.writableEnded || res.destroyed) {\n return;\n }\n\n // setup SSE headers\n this.sseWriter.setupHeaders(res);\n\n // handle reconnection\n if (streamId && StreamValidator.validateStreamId(streamId)) {\n const existingStream = this.streamRegistry.get(streamId);\n // if stream exists, attach to it\n if (existingStream) {\n return this._attachToExistingStream(res, existingStream, options);\n }\n }\n\n // if stream does not exist, create a new one\n return this._createNewStream(res, handler, options);\n }\n\n // abort all active operations\n abortAll(): void {\n this.activeOperations.forEach((operation) => {\n if (operation.heartbeat) clearInterval(operation.heartbeat);\n operation.controller.abort(\"Server shutdown\");\n });\n this.activeOperations.clear();\n this.streamRegistry.clear();\n }\n\n // get the number of active operations\n getActiveCount(): number {\n return this.activeOperations.size;\n }\n\n // attach to existing stream\n private async _attachToExistingStream(\n res: IAppResponse,\n streamEntry: StreamEntry,\n options?: StreamConfig,\n ): Promise<void> {\n // handle reconnection - replay missed events\n const lastEventId = res.req?.headers[\"last-event-id\"];\n\n if (StreamValidator.validateEventId(lastEventId)) {\n // cast to string after validation\n const validEventId = lastEventId as string;\n if (streamEntry.eventBuffer.has(validEventId)) {\n const missedEvents =\n streamEntry.eventBuffer.getEventsSince(validEventId);\n // broadcast missed events to client\n for (const event of missedEvents) {\n if (options?.userSignal?.aborted) break;\n this.sseWriter.writeBufferedEvent(res, event);\n }\n } else {\n // buffer overflow - send warning\n this.sseWriter.writeBufferOverflowWarning(res, validEventId);\n }\n }\n\n // add client to stream entry\n streamEntry.clients.add(res);\n streamEntry.lastAccess = Date.now();\n\n // start heartbeat\n const combinedSignal = this._combineSignals(\n streamEntry.abortController.signal,\n options?.userSignal,\n );\n const heartbeat = this.sseWriter.startHeartbeat(res, combinedSignal);\n\n // track operation\n const streamOperation: StreamOperation = {\n controller: streamEntry.abortController,\n type: \"stream\",\n heartbeat,\n };\n this.activeOperations.add(streamOperation);\n\n // handle client disconnect\n res.on(\"close\", () => {\n clearInterval(heartbeat);\n streamEntry.clients.delete(res);\n this.activeOperations.delete(streamOperation);\n\n // cleanup if stream is completed and no clients are connected\n if (streamEntry.isCompleted && streamEntry.clients.size === 0) {\n setTimeout(() => {\n if (streamEntry.clients.size === 0) {\n this.streamRegistry.remove(streamEntry.streamId);\n }\n }, this.bufferTTL);\n }\n });\n\n // if stream is completed, close connection\n if (streamEntry.isCompleted) {\n res.end();\n // cleanup operation\n this.activeOperations.delete(streamOperation);\n clearInterval(heartbeat);\n }\n }\n private async _createNewStream(\n res: IAppResponse,\n handler: (signal: AbortSignal) => AsyncGenerator<any, void, unknown>,\n options?: StreamConfig,\n ): Promise<void> {\n const streamId = options?.streamId ?? randomUUID();\n\n // abort stream if response is closed\n if (res.writableEnded || res.destroyed) {\n return;\n }\n\n const abortController = new AbortController();\n\n // create event buffer\n const eventBuffer = new EventRingBuffer(\n options?.bufferSize ?? streamDefaults.bufferSize,\n );\n\n // setup signals and heartbeat\n const combinedSignal = this._combineSignals(\n abortController.signal,\n options?.userSignal,\n );\n const heartbeat = this.sseWriter.startHeartbeat(res, combinedSignal);\n\n // capture the current trace context at stream creation time\n const traceContext = context.active();\n\n // abort stream if response is closed\n if (res.writableEnded || res.destroyed) {\n clearInterval(heartbeat);\n return;\n }\n\n // create stream entry\n const streamEntry: StreamEntry = {\n streamId,\n generator: handler(combinedSignal),\n eventBuffer,\n clients: new Set([res]),\n isCompleted: false,\n lastAccess: Date.now(),\n abortController,\n traceContext,\n };\n this.streamRegistry.add(streamEntry);\n\n // track operation\n const streamOperation: StreamOperation = {\n controller: abortController,\n type: \"stream\",\n heartbeat,\n };\n this.activeOperations.add(streamOperation);\n\n res.on(\"close\", () => {\n clearInterval(heartbeat);\n this.activeOperations.delete(streamOperation);\n streamEntry.clients.delete(res);\n });\n\n await this._processGeneratorInBackground(streamEntry);\n\n // cleanup\n clearInterval(heartbeat);\n this.activeOperations.delete(streamOperation);\n }\n\n private async _processGeneratorInBackground(\n streamEntry: StreamEntry,\n ): Promise<void> {\n // run the entire generator processing within the captured trace context\n return context.with(streamEntry.traceContext, async () => {\n try {\n // retrieve all events from generator\n for await (const event of streamEntry.generator) {\n if (streamEntry.abortController.signal.aborted) break;\n const eventId = randomUUID();\n const eventData = JSON.stringify(event);\n\n // validate event size\n if (eventData.length > this.maxEventSize) {\n const errorMsg = `Event exceeds max size of ${this.maxEventSize} bytes`;\n const errorCode = SSEErrorCode.INVALID_REQUEST;\n // broadcast error to all connected clients\n this._broadcastErrorToClients(\n streamEntry,\n eventId,\n errorMsg,\n errorCode,\n );\n continue;\n }\n\n // buffer event for reconnection\n streamEntry.eventBuffer.add({\n id: eventId,\n type: event.type,\n data: eventData,\n timestamp: Date.now(),\n });\n\n // broadcast to all connected clients\n this._broadcastEventsToClients(streamEntry, eventId, event);\n streamEntry.lastAccess = Date.now();\n }\n\n streamEntry.isCompleted = true;\n\n // close all clients\n this._closeAllClients(streamEntry);\n\n // cleanup if no clients are connected\n this._cleanupStream(streamEntry);\n } catch (error) {\n const errorMsg =\n error instanceof Error ? error.message : \"Internal server error\";\n const errorEventId = randomUUID();\n const errorCode = this._categorizeError(error);\n\n // buffer error event\n streamEntry.eventBuffer.add({\n id: errorEventId,\n type: \"error\",\n data: JSON.stringify({ error: errorMsg, code: errorCode }),\n timestamp: Date.now(),\n });\n\n // send error event to all connected clients\n this._broadcastErrorToClients(\n streamEntry,\n errorEventId,\n errorMsg,\n errorCode,\n true,\n );\n streamEntry.isCompleted = true;\n }\n });\n }\n\n private _combineSignals(\n internalSignal?: AbortSignal,\n userSignal?: AbortSignal,\n ): AbortSignal {\n if (!userSignal) return internalSignal || new AbortController().signal;\n\n const signals = [internalSignal, userSignal].filter(\n Boolean,\n ) as AbortSignal[];\n const controller = new AbortController();\n\n signals.forEach((signal) => {\n if (signal?.aborted) {\n controller.abort(signal.reason);\n return;\n }\n\n signal?.addEventListener(\n \"abort\",\n () => {\n controller.abort(signal.reason);\n },\n { once: true },\n );\n });\n return controller.signal;\n }\n\n // broadcast events to all connected clients\n private _broadcastEventsToClients(\n streamEntry: StreamEntry,\n eventId: string,\n event: any,\n ): void {\n for (const client of streamEntry.clients) {\n if (!client.writableEnded) {\n this.sseWriter.writeEvent(client, eventId, event);\n }\n }\n }\n\n // broadcast error to all connected clients\n private _broadcastErrorToClients(\n streamEntry: StreamEntry,\n eventId: string,\n errorMessage: string,\n errorCode: SSEErrorCode,\n closeClients: boolean = false,\n ): void {\n for (const client of streamEntry.clients) {\n if (!client.writableEnded) {\n this.sseWriter.writeError(client, eventId, errorMessage, errorCode);\n if (closeClients) {\n client.end();\n }\n }\n }\n }\n\n // close all connected clients\n private _closeAllClients(streamEntry: StreamEntry): void {\n for (const client of streamEntry.clients) {\n if (!client.writableEnded) {\n client.end();\n }\n }\n }\n\n // cleanup stream if no clients are connected\n private _cleanupStream(streamEntry: StreamEntry): void {\n if (streamEntry.clients.size === 0) {\n setTimeout(() => {\n if (streamEntry.clients.size === 0) {\n this.streamRegistry.remove(streamEntry.streamId);\n }\n }, this.bufferTTL);\n }\n }\n\n private _categorizeError(error: unknown): SSEErrorCode {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n if (message.includes(\"timeout\") || message.includes(\"timed out\")) {\n return SSEErrorCode.TIMEOUT;\n }\n\n if (message.includes(\"unavailable\") || message.includes(\"econnrefused\")) {\n return SSEErrorCode.TEMPORARY_UNAVAILABLE;\n }\n\n if (error.name === \"AbortError\") {\n return SSEErrorCode.STREAM_ABORTED;\n }\n }\n\n return SSEErrorCode.INTERNAL_ERROR;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-registry.js","names":[],"sources":["../../src/stream/stream-registry.ts"],"sourcesContent":["import { RingBuffer } from \"./buffers\";\nimport { SSEErrorCode, type StreamEntry } from \"./types\";\n\nexport class StreamRegistry {\n private streams: RingBuffer<StreamEntry>;\n\n constructor(maxActiveStreams: number) {\n this.streams = new RingBuffer<StreamEntry>(\n maxActiveStreams,\n (entry) => entry.streamId,\n );\n }\n\n // add a stream to the registry\n add(entry: StreamEntry): void {\n // enforce hard cap\n if (this.streams.getSize() >= this.streams.capacity) {\n this._evictOldestStream(entry.streamId);\n }\n\n this.streams.add(entry);\n }\n\n // get a stream from the registry\n get(streamId: string): StreamEntry | null {\n return this.streams.get(streamId);\n }\n\n // check if a stream exists in the registry\n has(streamId: string): boolean {\n return this.streams.has(streamId);\n }\n\n // remove a stream from the registry\n remove(streamId: string): void {\n this.streams.remove(streamId);\n }\n\n // get the number of streams in the registry\n size(): number {\n return this.streams.getSize();\n }\n\n clear(): void {\n const allStreams = this.streams.getAll();\n\n for (const stream of allStreams) {\n stream.abortController.abort(\"Server shutdown\");\n }\n\n this.streams.clear();\n }\n\n // evict the oldest stream from the registry\n private _evictOldestStream(excludeStreamId: string): void {\n const allStreams = this.streams.getAll();\n let oldestStream: StreamEntry | null = null;\n let oldestAccess = Infinity;\n\n // find the least recently accessed stream\n for (const stream of allStreams) {\n if (\n stream.streamId !== excludeStreamId &&\n stream.lastAccess < oldestAccess\n ) {\n oldestStream = stream;\n oldestAccess = stream.lastAccess;\n }\n }\n\n // abort the oldest stream\n if (oldestStream) {\n // broadcast stream eviction error to all clients\n for (const client of oldestStream.clients) {\n if (!client.writableEnded) {\n try {\n client.write(`event: error\\n`);\n client.write(\n `data: ${JSON.stringify({ error: \"Stream evicted\", code: SSEErrorCode.STREAM_EVICTED })}\\n\\n`,\n );\n } catch (_error) {\n // ignore\n }\n }\n }\n oldestStream.abortController.abort(\"Stream evicted\");\n this.streams.remove(oldestStream.streamId);\n }\n }\n}\n"],"mappings":";;;;AAGA,IAAa,iBAAb,MAA4B;
|
|
1
|
+
{"version":3,"file":"stream-registry.js","names":[],"sources":["../../src/stream/stream-registry.ts"],"sourcesContent":["import { RingBuffer } from \"./buffers\";\nimport { SSEErrorCode, type StreamEntry } from \"./types\";\n\nexport class StreamRegistry {\n private streams: RingBuffer<StreamEntry>;\n\n constructor(maxActiveStreams: number) {\n this.streams = new RingBuffer<StreamEntry>(\n maxActiveStreams,\n (entry) => entry.streamId,\n );\n }\n\n // add a stream to the registry\n add(entry: StreamEntry): void {\n // enforce hard cap\n if (this.streams.getSize() >= this.streams.capacity) {\n this._evictOldestStream(entry.streamId);\n }\n\n this.streams.add(entry);\n }\n\n // get a stream from the registry\n get(streamId: string): StreamEntry | null {\n return this.streams.get(streamId);\n }\n\n // check if a stream exists in the registry\n has(streamId: string): boolean {\n return this.streams.has(streamId);\n }\n\n // remove a stream from the registry\n remove(streamId: string): void {\n this.streams.remove(streamId);\n }\n\n // get the number of streams in the registry\n size(): number {\n return this.streams.getSize();\n }\n\n clear(): void {\n const allStreams = this.streams.getAll();\n\n for (const stream of allStreams) {\n stream.abortController.abort(\"Server shutdown\");\n }\n\n this.streams.clear();\n }\n\n // evict the oldest stream from the registry\n private _evictOldestStream(excludeStreamId: string): void {\n const allStreams = this.streams.getAll();\n let oldestStream: StreamEntry | null = null;\n let oldestAccess = Infinity;\n\n // find the least recently accessed stream\n for (const stream of allStreams) {\n if (\n stream.streamId !== excludeStreamId &&\n stream.lastAccess < oldestAccess\n ) {\n oldestStream = stream;\n oldestAccess = stream.lastAccess;\n }\n }\n\n // abort the oldest stream\n if (oldestStream) {\n // broadcast stream eviction error to all clients\n for (const client of oldestStream.clients) {\n if (!client.writableEnded) {\n try {\n client.write(`event: error\\n`);\n client.write(\n `data: ${JSON.stringify({ error: \"Stream evicted\", code: SSEErrorCode.STREAM_EVICTED })}\\n\\n`,\n );\n } catch (_error) {\n // ignore\n }\n }\n }\n oldestStream.abortController.abort(\"Stream evicted\");\n this.streams.remove(oldestStream.streamId);\n }\n }\n}\n"],"mappings":";;;;AAGA,IAAa,iBAAb,MAA4B;CAC1B,AAAQ;CAER,YAAY,kBAA0B;AACpC,OAAK,UAAU,IAAI,WACjB,mBACC,UAAU,MAAM,SAClB;;CAIH,IAAI,OAA0B;AAE5B,MAAI,KAAK,QAAQ,SAAS,IAAI,KAAK,QAAQ,SACzC,MAAK,mBAAmB,MAAM,SAAS;AAGzC,OAAK,QAAQ,IAAI,MAAM;;CAIzB,IAAI,UAAsC;AACxC,SAAO,KAAK,QAAQ,IAAI,SAAS;;CAInC,IAAI,UAA2B;AAC7B,SAAO,KAAK,QAAQ,IAAI,SAAS;;CAInC,OAAO,UAAwB;AAC7B,OAAK,QAAQ,OAAO,SAAS;;CAI/B,OAAe;AACb,SAAO,KAAK,QAAQ,SAAS;;CAG/B,QAAc;EACZ,MAAM,aAAa,KAAK,QAAQ,QAAQ;AAExC,OAAK,MAAM,UAAU,WACnB,QAAO,gBAAgB,MAAM,kBAAkB;AAGjD,OAAK,QAAQ,OAAO;;CAItB,AAAQ,mBAAmB,iBAA+B;EACxD,MAAM,aAAa,KAAK,QAAQ,QAAQ;EACxC,IAAI,eAAmC;EACvC,IAAI,eAAe;AAGnB,OAAK,MAAM,UAAU,WACnB,KACE,OAAO,aAAa,mBACpB,OAAO,aAAa,cACpB;AACA,kBAAe;AACf,kBAAe,OAAO;;AAK1B,MAAI,cAAc;AAEhB,QAAK,MAAM,UAAU,aAAa,QAChC,KAAI,CAAC,OAAO,cACV,KAAI;AACF,WAAO,MAAM,iBAAiB;AAC9B,WAAO,MACL,SAAS,KAAK,UAAU;KAAE,OAAO;KAAkB,MAAM,aAAa;KAAgB,CAAC,CAAC,MACzF;YACM,QAAQ;AAKrB,gBAAa,gBAAgB,MAAM,iBAAiB;AACpD,QAAK,QAAQ,OAAO,aAAa,SAAS"}
|
package/dist/stream/validator.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
//#region src/stream/validator.ts
|
|
2
2
|
var StreamValidator = class StreamValidator {
|
|
3
|
-
static {
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
static {
|
|
7
|
-
this.STREAM_ID_REGEX = /^[a-zA-Z0-9_-]+$/;
|
|
8
|
-
}
|
|
3
|
+
static UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4
|
+
static STREAM_ID_REGEX = /^[a-zA-Z0-9_-]+$/;
|
|
9
5
|
static validateEventId(eventId) {
|
|
10
6
|
if (!eventId || typeof eventId !== "string" || eventId.length !== 36) return false;
|
|
11
7
|
return StreamValidator.UUID_REGEX.test(eventId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","names":[],"sources":["../../src/stream/validator.ts"],"sourcesContent":["export class StreamValidator {\n private static readonly UUID_REGEX =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n private static readonly STREAM_ID_REGEX = /^[a-zA-Z0-9_-]+$/;\n\n // validates eventId format and throws on invalid input\n static validateEventId(eventId?: string | string[]): boolean {\n if (!eventId || typeof eventId !== \"string\" || eventId.length !== 36) {\n return false;\n }\n\n return StreamValidator.UUID_REGEX.test(eventId);\n }\n\n // validates streamId format and throws on invalid input\n static validateStreamId(streamId?: string): boolean {\n if (!streamId || streamId.length === 0 || streamId.length > 256) {\n return false;\n }\n\n if (!StreamValidator.STREAM_ID_REGEX.test(streamId)) {\n return false;\n }\n return true;\n }\n\n // sanitizes event type for SSE format\n static sanitizeEventType(type: string): string {\n return (type || \"message\").replace(/[\\r\\n]/g, \"\").slice(0, 100);\n }\n}\n"],"mappings":";AAAA,IAAa,kBAAb,MAAa,gBAAgB
|
|
1
|
+
{"version":3,"file":"validator.js","names":[],"sources":["../../src/stream/validator.ts"],"sourcesContent":["export class StreamValidator {\n private static readonly UUID_REGEX =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n private static readonly STREAM_ID_REGEX = /^[a-zA-Z0-9_-]+$/;\n\n // validates eventId format and throws on invalid input\n static validateEventId(eventId?: string | string[]): boolean {\n if (!eventId || typeof eventId !== \"string\" || eventId.length !== 36) {\n return false;\n }\n\n return StreamValidator.UUID_REGEX.test(eventId);\n }\n\n // validates streamId format and throws on invalid input\n static validateStreamId(streamId?: string): boolean {\n if (!streamId || streamId.length === 0 || streamId.length > 256) {\n return false;\n }\n\n if (!StreamValidator.STREAM_ID_REGEX.test(streamId)) {\n return false;\n }\n return true;\n }\n\n // sanitizes event type for SSE format\n static sanitizeEventType(type: string): string {\n return (type || \"message\").replace(/[\\r\\n]/g, \"\").slice(0, 100);\n }\n}\n"],"mappings":";AAAA,IAAa,kBAAb,MAAa,gBAAgB;CAC3B,OAAwB,aACtB;CAEF,OAAwB,kBAAkB;CAG1C,OAAO,gBAAgB,SAAsC;AAC3D,MAAI,CAAC,WAAW,OAAO,YAAY,YAAY,QAAQ,WAAW,GAChE,QAAO;AAGT,SAAO,gBAAgB,WAAW,KAAK,QAAQ;;CAIjD,OAAO,iBAAiB,UAA4B;AAClD,MAAI,CAAC,YAAY,SAAS,WAAW,KAAK,SAAS,SAAS,IAC1D,QAAO;AAGT,MAAI,CAAC,gBAAgB,gBAAgB,KAAK,SAAS,CACjD,QAAO;AAET,SAAO;;CAIT,OAAO,kBAAkB,MAAsB;AAC7C,UAAQ,QAAQ,WAAW,QAAQ,WAAW,GAAG,CAAC,MAAM,GAAG,IAAI"}
|
package/dist/telemetry/noop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noop.js","names":[],"sources":["../../src/telemetry/noop.ts"],"sourcesContent":["// Our own noop tracer implementation.\n// Why?\n// Unfortunately, noop tracer is not exported from the api package, unlike noop meter and noop logger.\n// Read more: https://github.com/open-telemetry/opentelemetry-js/issues/3455\n// and https://github.com/open-telemetry/opentelemetry-js/issues/4518\n//\n// The original implementation is here: https://github.com/open-telemetry/opentelemetry-js/blob/a7acd9355cd0c1da63d285dfb960efeacc3cbc15/api/src/trace/NoopTracer.ts#L32\n// licensed under the Apache License 2.0.\n// Our own implementation is much simpler but will do the job for our needs.\n\nimport type {\n Context,\n Span,\n SpanContext,\n SpanOptions,\n Tracer,\n} from \"@opentelemetry/api\";\nimport {\n createNoopMeter,\n INVALID_SPAN_CONTEXT,\n type SpanStatusCode,\n} from \"@opentelemetry/api\";\n\nclass NonRecordingSpan implements Span {\n private readonly _spanContext: SpanContext;\n\n constructor(spanContext: SpanContext = INVALID_SPAN_CONTEXT) {\n this._spanContext = spanContext;\n }\n\n spanContext(): SpanContext {\n return this._spanContext;\n }\n\n setAttribute(_key: string, _value: any): this {\n return this;\n }\n\n setAttributes(_attributes: any): this {\n return this;\n }\n\n addEvent(\n _name: string,\n _attributesOrStartTime?: any,\n _startTime?: any,\n ): this {\n return this;\n }\n\n addLink(_link: any): this {\n return this;\n }\n\n addLinks(_links: any[]): this {\n return this;\n }\n\n setStatus(_status: { code: SpanStatusCode; message?: string }): this {\n return this;\n }\n\n updateName(_name: string): this {\n return this;\n }\n\n end(_endTime?: number): void {}\n\n isRecording(): boolean {\n return false;\n }\n\n recordException(_exception: any, _time?: number): void {}\n}\n\nexport class NoopTracer implements Tracer {\n startSpan(_name: string, _options?: SpanOptions, _context?: Context): Span {\n return new NonRecordingSpan(INVALID_SPAN_CONTEXT);\n }\n\n startActiveSpan<F extends (span: Span) => any>(\n _name: string,\n ...args: [F] | [SpanOptions, F] | [SpanOptions, Context, F]\n ): ReturnType<F> | undefined {\n const fn = args[args.length - 1] as F;\n\n if (typeof fn !== \"function\") {\n return undefined as ReturnType<F>;\n }\n\n return fn(new NonRecordingSpan(INVALID_SPAN_CONTEXT));\n }\n}\n\nexport const NOOP_TRACER = new NoopTracer();\nexport const NOOP_METER = createNoopMeter();\nexport { NOOP_LOGGER } from \"@opentelemetry/api-logs\";\n"],"mappings":";;;;AAuBA,IAAM,mBAAN,MAAuC;
|
|
1
|
+
{"version":3,"file":"noop.js","names":[],"sources":["../../src/telemetry/noop.ts"],"sourcesContent":["// Our own noop tracer implementation.\n// Why?\n// Unfortunately, noop tracer is not exported from the api package, unlike noop meter and noop logger.\n// Read more: https://github.com/open-telemetry/opentelemetry-js/issues/3455\n// and https://github.com/open-telemetry/opentelemetry-js/issues/4518\n//\n// The original implementation is here: https://github.com/open-telemetry/opentelemetry-js/blob/a7acd9355cd0c1da63d285dfb960efeacc3cbc15/api/src/trace/NoopTracer.ts#L32\n// licensed under the Apache License 2.0.\n// Our own implementation is much simpler but will do the job for our needs.\n\nimport type {\n Context,\n Span,\n SpanContext,\n SpanOptions,\n Tracer,\n} from \"@opentelemetry/api\";\nimport {\n createNoopMeter,\n INVALID_SPAN_CONTEXT,\n type SpanStatusCode,\n} from \"@opentelemetry/api\";\n\nclass NonRecordingSpan implements Span {\n private readonly _spanContext: SpanContext;\n\n constructor(spanContext: SpanContext = INVALID_SPAN_CONTEXT) {\n this._spanContext = spanContext;\n }\n\n spanContext(): SpanContext {\n return this._spanContext;\n }\n\n setAttribute(_key: string, _value: any): this {\n return this;\n }\n\n setAttributes(_attributes: any): this {\n return this;\n }\n\n addEvent(\n _name: string,\n _attributesOrStartTime?: any,\n _startTime?: any,\n ): this {\n return this;\n }\n\n addLink(_link: any): this {\n return this;\n }\n\n addLinks(_links: any[]): this {\n return this;\n }\n\n setStatus(_status: { code: SpanStatusCode; message?: string }): this {\n return this;\n }\n\n updateName(_name: string): this {\n return this;\n }\n\n end(_endTime?: number): void {}\n\n isRecording(): boolean {\n return false;\n }\n\n recordException(_exception: any, _time?: number): void {}\n}\n\nexport class NoopTracer implements Tracer {\n startSpan(_name: string, _options?: SpanOptions, _context?: Context): Span {\n return new NonRecordingSpan(INVALID_SPAN_CONTEXT);\n }\n\n startActiveSpan<F extends (span: Span) => any>(\n _name: string,\n ...args: [F] | [SpanOptions, F] | [SpanOptions, Context, F]\n ): ReturnType<F> | undefined {\n const fn = args[args.length - 1] as F;\n\n if (typeof fn !== \"function\") {\n return undefined as ReturnType<F>;\n }\n\n return fn(new NonRecordingSpan(INVALID_SPAN_CONTEXT));\n }\n}\n\nexport const NOOP_TRACER = new NoopTracer();\nexport const NOOP_METER = createNoopMeter();\nexport { NOOP_LOGGER } from \"@opentelemetry/api-logs\";\n"],"mappings":";;;;AAuBA,IAAM,mBAAN,MAAuC;CACrC,AAAiB;CAEjB,YAAY,cAA2B,sBAAsB;AAC3D,OAAK,eAAe;;CAGtB,cAA2B;AACzB,SAAO,KAAK;;CAGd,aAAa,MAAc,QAAmB;AAC5C,SAAO;;CAGT,cAAc,aAAwB;AACpC,SAAO;;CAGT,SACE,OACA,wBACA,YACM;AACN,SAAO;;CAGT,QAAQ,OAAkB;AACxB,SAAO;;CAGT,SAAS,QAAqB;AAC5B,SAAO;;CAGT,UAAU,SAA2D;AACnE,SAAO;;CAGT,WAAW,OAAqB;AAC9B,SAAO;;CAGT,IAAI,UAAyB;CAE7B,cAAuB;AACrB,SAAO;;CAGT,gBAAgB,YAAiB,OAAsB;;AAGzD,IAAa,aAAb,MAA0C;CACxC,UAAU,OAAe,UAAwB,UAA0B;AACzE,SAAO,IAAI,iBAAiB,qBAAqB;;CAGnD,gBACE,OACA,GAAG,MACwB;EAC3B,MAAM,KAAK,KAAK,KAAK,SAAS;AAE9B,MAAI,OAAO,OAAO,WAChB;AAGF,SAAO,GAAG,IAAI,iBAAiB,qBAAqB,CAAC;;;AAIzD,MAAa,cAAc,IAAI,YAAY;AAC3C,MAAa,aAAa,iBAAiB"}
|
|
@@ -15,12 +15,10 @@ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic
|
|
|
15
15
|
//#region src/telemetry/telemetry-manager.ts
|
|
16
16
|
const logger = createLogger("telemetry");
|
|
17
17
|
var TelemetryManager = class TelemetryManager {
|
|
18
|
-
static
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.DEFAULT_FALLBACK_APP_NAME = "databricks-app";
|
|
23
|
-
}
|
|
18
|
+
static DEFAULT_EXPORT_INTERVAL_MS = 1e4;
|
|
19
|
+
static DEFAULT_FALLBACK_APP_NAME = "databricks-app";
|
|
20
|
+
static instance;
|
|
21
|
+
sdk;
|
|
24
22
|
/**
|
|
25
23
|
* Create a scoped telemetry provider for a specific plugin.
|
|
26
24
|
* The plugin's name will be used as the default tracer/meter name.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry-manager.js","names":[],"sources":["../../src/telemetry/telemetry-manager.ts"],"sourcesContent":["import { getNodeAutoInstrumentations } from \"@opentelemetry/auto-instrumentations-node\";\nimport { OTLPLogExporter } from \"@opentelemetry/exporter-logs-otlp-proto\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-proto\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\nimport {\n type Instrumentation,\n registerInstrumentations as otelRegisterInstrumentations,\n} from \"@opentelemetry/instrumentation\";\nimport {\n detectResources,\n envDetector,\n hostDetector,\n processDetector,\n type Resource,\n resourceFromAttributes,\n} from \"@opentelemetry/resources\";\nimport { BatchLogRecordProcessor } from \"@opentelemetry/sdk-logs\";\nimport { PeriodicExportingMetricReader } from \"@opentelemetry/sdk-metrics\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from \"@opentelemetry/semantic-conventions\";\nimport type { TelemetryOptions } from \"shared\";\nimport { createLogger } from \"../logging/logger\";\nimport { TelemetryProvider } from \"./telemetry-provider\";\nimport { AppKitSampler } from \"./trace-sampler\";\nimport type { TelemetryConfig } from \"./types\";\n\nconst logger = createLogger(\"telemetry\");\n\nexport class TelemetryManager {\n private static readonly DEFAULT_EXPORT_INTERVAL_MS = 10000;\n private static readonly DEFAULT_FALLBACK_APP_NAME = \"databricks-app\";\n\n private static instance?: TelemetryManager;\n private sdk?: NodeSDK;\n\n /**\n * Create a scoped telemetry provider for a specific plugin.\n * The plugin's name will be used as the default tracer/meter name.\n * @param pluginName - The name of the plugin to create scoped telemetry for\n * @param telemetryConfig - The telemetry configuration for the plugin\n * @returns A scoped telemetry instance for the plugin\n */\n static getProvider(\n pluginName: string,\n telemetryConfig?: TelemetryOptions,\n ): TelemetryProvider {\n const globalManager = TelemetryManager.getInstance();\n return new TelemetryProvider(pluginName, globalManager, telemetryConfig);\n }\n\n private constructor() {}\n\n static getInstance(): TelemetryManager {\n if (!TelemetryManager.instance) {\n TelemetryManager.instance = new TelemetryManager();\n }\n return TelemetryManager.instance;\n }\n\n static initialize(config: Partial<TelemetryConfig> = {}): void {\n const instance = TelemetryManager.getInstance();\n instance._initialize(config);\n }\n\n private _initialize(config: Partial<TelemetryConfig>): void {\n if (this.sdk) return;\n\n if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {\n return;\n }\n\n try {\n this.sdk = new NodeSDK({\n resource: this.createResource(config),\n autoDetectResources: false,\n sampler: new AppKitSampler(),\n traceExporter: new OTLPTraceExporter({ headers: config.headers }),\n metricReaders: [\n new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({ headers: config.headers }),\n exportIntervalMillis:\n config.exportIntervalMs ||\n TelemetryManager.DEFAULT_EXPORT_INTERVAL_MS,\n }),\n ],\n logRecordProcessors: [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({ headers: config.headers }),\n ),\n ],\n instrumentations: this.getDefaultInstrumentations(),\n });\n\n this.sdk.start();\n this.registerShutdown();\n logger.debug(\"Initialized successfully\");\n } catch (error) {\n logger.error(\"Failed to initialize: %O\", error);\n }\n }\n\n /**\n * Register OpenTelemetry instrumentations.\n * Can be called at any time, but recommended to call in plugin constructor.\n * @param instrumentations - Array of OpenTelemetry instrumentations to register\n */\n registerInstrumentations(instrumentations: Instrumentation[]): void {\n otelRegisterInstrumentations({\n // global providers set by NodeSDK.start()\n instrumentations,\n });\n }\n\n private createResource(config: Partial<TelemetryConfig>): Resource {\n const serviceName =\n config.serviceName ||\n process.env.OTEL_SERVICE_NAME ||\n process.env.DATABRICKS_APP_NAME ||\n TelemetryManager.DEFAULT_FALLBACK_APP_NAME;\n const initialResource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_SERVICE_VERSION]: config.serviceVersion ?? undefined,\n });\n const detectedResource = detectResources({\n detectors: [envDetector, hostDetector, processDetector],\n });\n return initialResource.merge(detectedResource);\n }\n\n private getDefaultInstrumentations(): Instrumentation[] {\n return [\n ...getNodeAutoInstrumentations({\n //\n // enabled as a part of the server plugin\n //\n \"@opentelemetry/instrumentation-http\": {\n enabled: false,\n },\n \"@opentelemetry/instrumentation-express\": {\n enabled: false,\n },\n //\n // reduce noise\n //\n \"@opentelemetry/instrumentation-fs\": {\n enabled: false,\n },\n \"@opentelemetry/instrumentation-dns\": {\n enabled: false,\n },\n \"@opentelemetry/instrumentation-net\": {\n enabled: false,\n },\n }),\n ];\n }\n\n private registerShutdown() {\n const shutdownFn = async () => {\n await TelemetryManager.getInstance().shutdown();\n };\n process.once(\"SIGTERM\", shutdownFn);\n process.once(\"SIGINT\", shutdownFn);\n }\n\n private async shutdown(): Promise<void> {\n if (!this.sdk) {\n return;\n }\n\n try {\n await this.sdk.shutdown();\n this.sdk = undefined;\n } catch (error) {\n logger.error(\"Error shutting down: %O\", error);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AA6BA,MAAM,SAAS,aAAa,YAAY;AAExC,IAAa,mBAAb,MAAa,iBAAiB
|
|
1
|
+
{"version":3,"file":"telemetry-manager.js","names":[],"sources":["../../src/telemetry/telemetry-manager.ts"],"sourcesContent":["import { getNodeAutoInstrumentations } from \"@opentelemetry/auto-instrumentations-node\";\nimport { OTLPLogExporter } from \"@opentelemetry/exporter-logs-otlp-proto\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-proto\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-proto\";\nimport {\n type Instrumentation,\n registerInstrumentations as otelRegisterInstrumentations,\n} from \"@opentelemetry/instrumentation\";\nimport {\n detectResources,\n envDetector,\n hostDetector,\n processDetector,\n type Resource,\n resourceFromAttributes,\n} from \"@opentelemetry/resources\";\nimport { BatchLogRecordProcessor } from \"@opentelemetry/sdk-logs\";\nimport { PeriodicExportingMetricReader } from \"@opentelemetry/sdk-metrics\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport {\n ATTR_SERVICE_NAME,\n ATTR_SERVICE_VERSION,\n} from \"@opentelemetry/semantic-conventions\";\nimport type { TelemetryOptions } from \"shared\";\nimport { createLogger } from \"../logging/logger\";\nimport { TelemetryProvider } from \"./telemetry-provider\";\nimport { AppKitSampler } from \"./trace-sampler\";\nimport type { TelemetryConfig } from \"./types\";\n\nconst logger = createLogger(\"telemetry\");\n\nexport class TelemetryManager {\n private static readonly DEFAULT_EXPORT_INTERVAL_MS = 10000;\n private static readonly DEFAULT_FALLBACK_APP_NAME = \"databricks-app\";\n\n private static instance?: TelemetryManager;\n private sdk?: NodeSDK;\n\n /**\n * Create a scoped telemetry provider for a specific plugin.\n * The plugin's name will be used as the default tracer/meter name.\n * @param pluginName - The name of the plugin to create scoped telemetry for\n * @param telemetryConfig - The telemetry configuration for the plugin\n * @returns A scoped telemetry instance for the plugin\n */\n static getProvider(\n pluginName: string,\n telemetryConfig?: TelemetryOptions,\n ): TelemetryProvider {\n const globalManager = TelemetryManager.getInstance();\n return new TelemetryProvider(pluginName, globalManager, telemetryConfig);\n }\n\n private constructor() {}\n\n static getInstance(): TelemetryManager {\n if (!TelemetryManager.instance) {\n TelemetryManager.instance = new TelemetryManager();\n }\n return TelemetryManager.instance;\n }\n\n static initialize(config: Partial<TelemetryConfig> = {}): void {\n const instance = TelemetryManager.getInstance();\n instance._initialize(config);\n }\n\n private _initialize(config: Partial<TelemetryConfig>): void {\n if (this.sdk) return;\n\n if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) {\n return;\n }\n\n try {\n this.sdk = new NodeSDK({\n resource: this.createResource(config),\n autoDetectResources: false,\n sampler: new AppKitSampler(),\n traceExporter: new OTLPTraceExporter({ headers: config.headers }),\n metricReaders: [\n new PeriodicExportingMetricReader({\n exporter: new OTLPMetricExporter({ headers: config.headers }),\n exportIntervalMillis:\n config.exportIntervalMs ||\n TelemetryManager.DEFAULT_EXPORT_INTERVAL_MS,\n }),\n ],\n logRecordProcessors: [\n new BatchLogRecordProcessor(\n new OTLPLogExporter({ headers: config.headers }),\n ),\n ],\n instrumentations: this.getDefaultInstrumentations(),\n });\n\n this.sdk.start();\n this.registerShutdown();\n logger.debug(\"Initialized successfully\");\n } catch (error) {\n logger.error(\"Failed to initialize: %O\", error);\n }\n }\n\n /**\n * Register OpenTelemetry instrumentations.\n * Can be called at any time, but recommended to call in plugin constructor.\n * @param instrumentations - Array of OpenTelemetry instrumentations to register\n */\n registerInstrumentations(instrumentations: Instrumentation[]): void {\n otelRegisterInstrumentations({\n // global providers set by NodeSDK.start()\n instrumentations,\n });\n }\n\n private createResource(config: Partial<TelemetryConfig>): Resource {\n const serviceName =\n config.serviceName ||\n process.env.OTEL_SERVICE_NAME ||\n process.env.DATABRICKS_APP_NAME ||\n TelemetryManager.DEFAULT_FALLBACK_APP_NAME;\n const initialResource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: serviceName,\n [ATTR_SERVICE_VERSION]: config.serviceVersion ?? undefined,\n });\n const detectedResource = detectResources({\n detectors: [envDetector, hostDetector, processDetector],\n });\n return initialResource.merge(detectedResource);\n }\n\n private getDefaultInstrumentations(): Instrumentation[] {\n return [\n ...getNodeAutoInstrumentations({\n //\n // enabled as a part of the server plugin\n //\n \"@opentelemetry/instrumentation-http\": {\n enabled: false,\n },\n \"@opentelemetry/instrumentation-express\": {\n enabled: false,\n },\n //\n // reduce noise\n //\n \"@opentelemetry/instrumentation-fs\": {\n enabled: false,\n },\n \"@opentelemetry/instrumentation-dns\": {\n enabled: false,\n },\n \"@opentelemetry/instrumentation-net\": {\n enabled: false,\n },\n }),\n ];\n }\n\n private registerShutdown() {\n const shutdownFn = async () => {\n await TelemetryManager.getInstance().shutdown();\n };\n process.once(\"SIGTERM\", shutdownFn);\n process.once(\"SIGINT\", shutdownFn);\n }\n\n private async shutdown(): Promise<void> {\n if (!this.sdk) {\n return;\n }\n\n try {\n await this.sdk.shutdown();\n this.sdk = undefined;\n } catch (error) {\n logger.error(\"Error shutting down: %O\", error);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AA6BA,MAAM,SAAS,aAAa,YAAY;AAExC,IAAa,mBAAb,MAAa,iBAAiB;CAC5B,OAAwB,6BAA6B;CACrD,OAAwB,4BAA4B;CAEpD,OAAe;CACf,AAAQ;;;;;;;;CASR,OAAO,YACL,YACA,iBACmB;AAEnB,SAAO,IAAI,kBAAkB,YADP,iBAAiB,aAAa,EACI,gBAAgB;;CAG1E,AAAQ,cAAc;CAEtB,OAAO,cAAgC;AACrC,MAAI,CAAC,iBAAiB,SACpB,kBAAiB,WAAW,IAAI,kBAAkB;AAEpD,SAAO,iBAAiB;;CAG1B,OAAO,WAAW,SAAmC,EAAE,EAAQ;AAE7D,EADiB,iBAAiB,aAAa,CACtC,YAAY,OAAO;;CAG9B,AAAQ,YAAY,QAAwC;AAC1D,MAAI,KAAK,IAAK;AAEd,MAAI,CAAC,QAAQ,IAAI,4BACf;AAGF,MAAI;AACF,QAAK,MAAM,IAAI,QAAQ;IACrB,UAAU,KAAK,eAAe,OAAO;IACrC,qBAAqB;IACrB,SAAS,IAAI,eAAe;IAC5B,eAAe,IAAI,kBAAkB,EAAE,SAAS,OAAO,SAAS,CAAC;IACjE,eAAe,CACb,IAAI,8BAA8B;KAChC,UAAU,IAAI,mBAAmB,EAAE,SAAS,OAAO,SAAS,CAAC;KAC7D,sBACE,OAAO,oBACP,iBAAiB;KACpB,CAAC,CACH;IACD,qBAAqB,CACnB,IAAI,wBACF,IAAI,gBAAgB,EAAE,SAAS,OAAO,SAAS,CAAC,CACjD,CACF;IACD,kBAAkB,KAAK,4BAA4B;IACpD,CAAC;AAEF,QAAK,IAAI,OAAO;AAChB,QAAK,kBAAkB;AACvB,UAAO,MAAM,2BAA2B;WACjC,OAAO;AACd,UAAO,MAAM,4BAA4B,MAAM;;;;;;;;CASnD,yBAAyB,kBAA2C;AAClE,2BAA6B,EAE3B,kBACD,CAAC;;CAGJ,AAAQ,eAAe,QAA4C;EACjE,MAAM,cACJ,OAAO,eACP,QAAQ,IAAI,qBACZ,QAAQ,IAAI,uBACZ,iBAAiB;EACnB,MAAM,kBAAkB,uBAAuB;IAC5C,oBAAoB;IACpB,uBAAuB,OAAO,kBAAkB;GAClD,CAAC;EACF,MAAM,mBAAmB,gBAAgB,EACvC,WAAW;GAAC;GAAa;GAAc;GAAgB,EACxD,CAAC;AACF,SAAO,gBAAgB,MAAM,iBAAiB;;CAGhD,AAAQ,6BAAgD;AACtD,SAAO,CACL,GAAG,4BAA4B;GAI7B,uCAAuC,EACrC,SAAS,OACV;GACD,0CAA0C,EACxC,SAAS,OACV;GAID,qCAAqC,EACnC,SAAS,OACV;GACD,sCAAsC,EACpC,SAAS,OACV;GACD,sCAAsC,EACpC,SAAS,OACV;GACF,CAAC,CACH;;CAGH,AAAQ,mBAAmB;EACzB,MAAM,aAAa,YAAY;AAC7B,SAAM,iBAAiB,aAAa,CAAC,UAAU;;AAEjD,UAAQ,KAAK,WAAW,WAAW;AACnC,UAAQ,KAAK,UAAU,WAAW;;CAGpC,MAAc,WAA0B;AACtC,MAAI,CAAC,KAAK,IACR;AAGF,MAAI;AACF,SAAM,KAAK,IAAI,UAAU;AACzB,QAAK,MAAM;WACJ,OAAO;AACd,UAAO,MAAM,2BAA2B,MAAM"}
|
|
@@ -9,6 +9,9 @@ import { logs } from "@opentelemetry/api-logs";
|
|
|
9
9
|
* Automatically uses the plugin name as the default tracer/meter name.
|
|
10
10
|
*/
|
|
11
11
|
var TelemetryProvider = class {
|
|
12
|
+
pluginName;
|
|
13
|
+
globalManager;
|
|
14
|
+
config;
|
|
12
15
|
constructor(pluginName, globalManager, telemetryConfig) {
|
|
13
16
|
this.pluginName = pluginName;
|
|
14
17
|
this.globalManager = globalManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry-provider.js","names":[],"sources":["../../src/telemetry/telemetry-provider.ts"],"sourcesContent":["import type { TelemetryOptions } from \"shared\";\nimport type { Meter, Span, SpanOptions, Tracer } from \"@opentelemetry/api\";\nimport { metrics, trace } from \"@opentelemetry/api\";\nimport { type Logger, type LogRecord, logs } from \"@opentelemetry/api-logs\";\nimport type { Instrumentation } from \"@opentelemetry/instrumentation\";\nimport {\n normalizeTelemetryOptions,\n type TelemetryProviderConfig,\n} from \"./config\";\nimport { NOOP_LOGGER, NOOP_METER, NOOP_TRACER } from \"./noop\";\nimport type { TelemetryManager } from \"./telemetry-manager\";\nimport type { InstrumentConfig, ITelemetry } from \"./types\";\n\n/**\n * Scoped telemetry instance for specific plugins and other classes.\n * Automatically uses the plugin name as the default tracer/meter name.\n */\nexport class TelemetryProvider implements ITelemetry {\n private readonly pluginName: string;\n private readonly globalManager: TelemetryManager;\n private readonly config: TelemetryProviderConfig;\n\n constructor(\n pluginName: string,\n globalManager: TelemetryManager,\n telemetryConfig?: TelemetryOptions,\n ) {\n this.pluginName = pluginName;\n this.globalManager = globalManager;\n this.config = normalizeTelemetryOptions(telemetryConfig);\n }\n\n /**\n * Gets a tracer for creating spans.\n * @param options - Optional tracer configuration.\n */\n getTracer(options?: InstrumentConfig): Tracer {\n if (!this.config.traces) {\n return NOOP_TRACER;\n }\n\n const tracerName = this.getInstrumentName(options);\n return trace.getTracer(tracerName);\n }\n\n /**\n * Gets a meter for recording metrics.\n * @param config - Optional meter configuration.\n */\n getMeter(config?: InstrumentConfig): Meter {\n if (!this.config.metrics) {\n return NOOP_METER;\n }\n\n const meterName = this.getInstrumentName(config);\n return metrics.getMeter(meterName);\n }\n\n /**\n * Gets a logger for emitting log records.\n * @param config - Optional logger configuration.\n */\n getLogger(config?: InstrumentConfig): Logger {\n if (!this.config.logs) {\n return NOOP_LOGGER;\n }\n\n const loggerName = this.getInstrumentName(config);\n return logs.getLogger(loggerName);\n }\n\n /**\n * Emits a log record using the default logger.\n * Convenience method for logging without explicitly getting a logger.\n * @param logRecord - The log record to emit\n */\n emit(logRecord: LogRecord): void {\n const logger = this.getLogger();\n logger.emit(logRecord);\n }\n\n /**\n * Register OpenTelemetry instrumentations.\n * Can be called at any time, but recommended to call in plugin constructor.\n * @param instrumentations - Array of OpenTelemetry instrumentations to register\n */\n registerInstrumentations(instrumentations: Instrumentation[]): void {\n if (!this.config.traces) {\n return;\n }\n\n this.globalManager.registerInstrumentations(instrumentations);\n }\n\n /**\n * Starts an active span and executes a callback function within its context.\n * Uses the plugin's default tracer unless custom tracer options are provided.\n * @param name - The name of the span\n * @param options - Span options including attributes, kind, etc.\n * @param fn - Callback function to execute within the span context\n * @param tracerOptions - Optional tracer configuration\n * @returns Promise resolving to the callback's return value\n */\n startActiveSpan<T>(\n name: string,\n options: SpanOptions,\n fn: (span: Span) => Promise<T>,\n tracerOptions?: InstrumentConfig,\n ): Promise<T> {\n const tracer = this.getTracer(tracerOptions);\n return tracer.startActiveSpan(name, options, fn);\n }\n\n private getInstrumentName(options?: InstrumentConfig): string {\n const prefix = this.pluginName;\n if (!options || !options.name) {\n return this.pluginName;\n }\n\n return options.includePrefix ? `${prefix}-${options.name}` : options.name;\n }\n}\n"],"mappings":";;;;;;;;;;AAiBA,IAAa,oBAAb,MAAqD;
|
|
1
|
+
{"version":3,"file":"telemetry-provider.js","names":[],"sources":["../../src/telemetry/telemetry-provider.ts"],"sourcesContent":["import type { TelemetryOptions } from \"shared\";\nimport type { Meter, Span, SpanOptions, Tracer } from \"@opentelemetry/api\";\nimport { metrics, trace } from \"@opentelemetry/api\";\nimport { type Logger, type LogRecord, logs } from \"@opentelemetry/api-logs\";\nimport type { Instrumentation } from \"@opentelemetry/instrumentation\";\nimport {\n normalizeTelemetryOptions,\n type TelemetryProviderConfig,\n} from \"./config\";\nimport { NOOP_LOGGER, NOOP_METER, NOOP_TRACER } from \"./noop\";\nimport type { TelemetryManager } from \"./telemetry-manager\";\nimport type { InstrumentConfig, ITelemetry } from \"./types\";\n\n/**\n * Scoped telemetry instance for specific plugins and other classes.\n * Automatically uses the plugin name as the default tracer/meter name.\n */\nexport class TelemetryProvider implements ITelemetry {\n private readonly pluginName: string;\n private readonly globalManager: TelemetryManager;\n private readonly config: TelemetryProviderConfig;\n\n constructor(\n pluginName: string,\n globalManager: TelemetryManager,\n telemetryConfig?: TelemetryOptions,\n ) {\n this.pluginName = pluginName;\n this.globalManager = globalManager;\n this.config = normalizeTelemetryOptions(telemetryConfig);\n }\n\n /**\n * Gets a tracer for creating spans.\n * @param options - Optional tracer configuration.\n */\n getTracer(options?: InstrumentConfig): Tracer {\n if (!this.config.traces) {\n return NOOP_TRACER;\n }\n\n const tracerName = this.getInstrumentName(options);\n return trace.getTracer(tracerName);\n }\n\n /**\n * Gets a meter for recording metrics.\n * @param config - Optional meter configuration.\n */\n getMeter(config?: InstrumentConfig): Meter {\n if (!this.config.metrics) {\n return NOOP_METER;\n }\n\n const meterName = this.getInstrumentName(config);\n return metrics.getMeter(meterName);\n }\n\n /**\n * Gets a logger for emitting log records.\n * @param config - Optional logger configuration.\n */\n getLogger(config?: InstrumentConfig): Logger {\n if (!this.config.logs) {\n return NOOP_LOGGER;\n }\n\n const loggerName = this.getInstrumentName(config);\n return logs.getLogger(loggerName);\n }\n\n /**\n * Emits a log record using the default logger.\n * Convenience method for logging without explicitly getting a logger.\n * @param logRecord - The log record to emit\n */\n emit(logRecord: LogRecord): void {\n const logger = this.getLogger();\n logger.emit(logRecord);\n }\n\n /**\n * Register OpenTelemetry instrumentations.\n * Can be called at any time, but recommended to call in plugin constructor.\n * @param instrumentations - Array of OpenTelemetry instrumentations to register\n */\n registerInstrumentations(instrumentations: Instrumentation[]): void {\n if (!this.config.traces) {\n return;\n }\n\n this.globalManager.registerInstrumentations(instrumentations);\n }\n\n /**\n * Starts an active span and executes a callback function within its context.\n * Uses the plugin's default tracer unless custom tracer options are provided.\n * @param name - The name of the span\n * @param options - Span options including attributes, kind, etc.\n * @param fn - Callback function to execute within the span context\n * @param tracerOptions - Optional tracer configuration\n * @returns Promise resolving to the callback's return value\n */\n startActiveSpan<T>(\n name: string,\n options: SpanOptions,\n fn: (span: Span) => Promise<T>,\n tracerOptions?: InstrumentConfig,\n ): Promise<T> {\n const tracer = this.getTracer(tracerOptions);\n return tracer.startActiveSpan(name, options, fn);\n }\n\n private getInstrumentName(options?: InstrumentConfig): string {\n const prefix = this.pluginName;\n if (!options || !options.name) {\n return this.pluginName;\n }\n\n return options.includePrefix ? `${prefix}-${options.name}` : options.name;\n }\n}\n"],"mappings":";;;;;;;;;;AAiBA,IAAa,oBAAb,MAAqD;CACnD,AAAiB;CACjB,AAAiB;CACjB,AAAiB;CAEjB,YACE,YACA,eACA,iBACA;AACA,OAAK,aAAa;AAClB,OAAK,gBAAgB;AACrB,OAAK,SAAS,0BAA0B,gBAAgB;;;;;;CAO1D,UAAU,SAAoC;AAC5C,MAAI,CAAC,KAAK,OAAO,OACf,QAAO;EAGT,MAAM,aAAa,KAAK,kBAAkB,QAAQ;AAClD,SAAO,MAAM,UAAU,WAAW;;;;;;CAOpC,SAAS,QAAkC;AACzC,MAAI,CAAC,KAAK,OAAO,QACf,QAAO;EAGT,MAAM,YAAY,KAAK,kBAAkB,OAAO;AAChD,SAAO,QAAQ,SAAS,UAAU;;;;;;CAOpC,UAAU,QAAmC;AAC3C,MAAI,CAAC,KAAK,OAAO,KACf,QAAO;EAGT,MAAM,aAAa,KAAK,kBAAkB,OAAO;AACjD,SAAO,KAAK,UAAU,WAAW;;;;;;;CAQnC,KAAK,WAA4B;AAE/B,EADe,KAAK,WAAW,CACxB,KAAK,UAAU;;;;;;;CAQxB,yBAAyB,kBAA2C;AAClE,MAAI,CAAC,KAAK,OAAO,OACf;AAGF,OAAK,cAAc,yBAAyB,iBAAiB;;;;;;;;;;;CAY/D,gBACE,MACA,SACA,IACA,eACY;AAEZ,SADe,KAAK,UAAU,cAAc,CAC9B,gBAAgB,MAAM,SAAS,GAAG;;CAGlD,AAAQ,kBAAkB,SAAoC;EAC5D,MAAM,SAAS,KAAK;AACpB,MAAI,CAAC,WAAW,CAAC,QAAQ,KACvB,QAAO,KAAK;AAGd,SAAO,QAAQ,gBAAgB,GAAG,OAAO,GAAG,QAAQ,SAAS,QAAQ"}
|
|
@@ -3,17 +3,15 @@
|
|
|
3
3
|
* Simple loading spinner for CLI
|
|
4
4
|
*/
|
|
5
5
|
var Spinner = class {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.text = "";
|
|
16
|
-
}
|
|
6
|
+
frames = [
|
|
7
|
+
" ",
|
|
8
|
+
". ",
|
|
9
|
+
".. ",
|
|
10
|
+
"..."
|
|
11
|
+
];
|
|
12
|
+
current = 0;
|
|
13
|
+
interval = null;
|
|
14
|
+
text = "";
|
|
17
15
|
start(text) {
|
|
18
16
|
this.text = text;
|
|
19
17
|
this.current = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.js","names":[],"sources":["../../src/type-generator/spinner.ts"],"sourcesContent":["/**\n * Simple loading spinner for CLI\n */\nexport class Spinner {\n private frames = [\" \", \". \", \".. \", \"...\"];\n private current = 0;\n private interval: NodeJS.Timeout | null = null;\n private text = \"\";\n\n start(text: string) {\n this.text = text;\n this.current = 0;\n process.stdout.write(` ${this.text}${this.frames[0]}`);\n this.interval = setInterval(() => {\n this.current = (this.current + 1) % this.frames.length;\n process.stdout.write(`\\r ${this.text}${this.frames[this.current]}`);\n }, 300);\n }\n\n stop(finalText?: string) {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n // clear the line and write the final text\n process.stdout.write(`\\x1b[2K\\r ${finalText || this.text}\\n`);\n }\n}\n"],"mappings":";;;;AAGA,IAAa,UAAb,MAAqB
|
|
1
|
+
{"version":3,"file":"spinner.js","names":[],"sources":["../../src/type-generator/spinner.ts"],"sourcesContent":["/**\n * Simple loading spinner for CLI\n */\nexport class Spinner {\n private frames = [\" \", \". \", \".. \", \"...\"];\n private current = 0;\n private interval: NodeJS.Timeout | null = null;\n private text = \"\";\n\n start(text: string) {\n this.text = text;\n this.current = 0;\n process.stdout.write(` ${this.text}${this.frames[0]}`);\n this.interval = setInterval(() => {\n this.current = (this.current + 1) % this.frames.length;\n process.stdout.write(`\\r ${this.text}${this.frames[this.current]}`);\n }, 300);\n }\n\n stop(finalText?: string) {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n // clear the line and write the final text\n process.stdout.write(`\\x1b[2K\\r ${finalText || this.text}\\n`);\n }\n}\n"],"mappings":";;;;AAGA,IAAa,UAAb,MAAqB;CACnB,AAAQ,SAAS;EAAC;EAAO;EAAO;EAAO;EAAM;CAC7C,AAAQ,UAAU;CAClB,AAAQ,WAAkC;CAC1C,AAAQ,OAAO;CAEf,MAAM,MAAc;AAClB,OAAK,OAAO;AACZ,OAAK,UAAU;AACf,UAAQ,OAAO,MAAM,KAAK,KAAK,OAAO,KAAK,OAAO,KAAK;AACvD,OAAK,WAAW,kBAAkB;AAChC,QAAK,WAAW,KAAK,UAAU,KAAK,KAAK,OAAO;AAChD,WAAQ,OAAO,MAAM,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,WAAW;KACnE,IAAI;;CAGT,KAAK,WAAoB;AACvB,MAAI,KAAK,UAAU;AACjB,iBAAc,KAAK,SAAS;AAC5B,QAAK,WAAW;;AAGlB,UAAQ,OAAO,MAAM,cAAc,aAAa,KAAK,KAAK,IAAI"}
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Abstract Class: AppKitError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Abstract Class: AppKitError | AppKit"><meta data-rh="true" name="description" content="Base error class for all AppKit errors."><meta data-rh="true" property="og:description" content="Base error class for all AppKit errors."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"AppKitError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.0ec7398f.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.46b4a147.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.109beba6.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
12
12
|
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
|
|
13
13
|
</defs></svg>
|
|
14
|
-
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const n=new URLSearchParams(window.location.search).entries();for(var[t,e]of n)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())</script><div id="__docusaurus"><link rel="preload" as="image" href="/appkit/img/logo.png"><div role="region" aria-label="Skip to main content"><a class="skipToContent_R3I2" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><div class="theme-announcement-bar announcementBar_Upl7" style="background-color:#f0f0f0;color:#000000" role="banner"><div class="announcementBarPlaceholder_Lvio"></div><div class="content_vq0X announcementBarContent_FIMQ">⚠️ AppKit is in an early development phase and is subject to change without notice. <strong>DO NOT</strong> use in production environments.</div><button type="button" aria-label="Close" class="clean-btn close closeButton_J8WU announcementBarClose_jD94"><svg viewBox="0 0 15 15" width="14" height="14"><g stroke="currentColor" stroke-width="3.1"><path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"></path></g></svg></button></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/appkit/"><div class="navbar__logo"><img src="/appkit/img/logo.png" alt="AppKit" class="themedComponent_hkXO themedComponent--light_BgK8"><img src="/appkit/img/logo.png" alt="AppKit" class="themedComponent_hkXO themedComponent--dark_RKPt"></div><b class="navbar__title text--truncate">AppKit</b></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/appkit/docs/">Documentation</a><a class="navbar__item navbar__link" href="/appkit/contributing">Contributing</a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://github.com/databricks/appkit" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_miaU"><use href="#theme-svg-external-link"></use></svg></a><div class="toggle_eFYw colorModeToggle_EPbi"><button class="clean-btn toggleButton_HRKp toggleButtonDisabled_bICu" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_brDO lightToggleIcon_vxPA"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_brDO darkToggleIcon_PZNO"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_brDO systemToggleIcon_A7x6"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_cVhq"><div class="navbar__search"><span aria-label="expand searchbar" role="button" class="search-icon" tabindex="0"></span><input id="search_input_react" type="search" placeholder="Loading..." aria-label="Search" class="navbar__search-input search-bar" disabled=""></div></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper__Y_W"><div class="docsWrapper_cIfN"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_xQFv" type="button"></button><div class="docRoot_FHtD"><aside class="theme-doc-sidebar-container docSidebarContainer_dvCd"><div class="sidebarViewport_GeRf"><div class="sidebar_T8N1"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_uyE9 menuWithAnnouncementBar_Bucd"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/"><span title="Getting started" class="linkLabel_hZzm">Getting started</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/app-management"><span title="App management" class="linkLabel_hZzm">App management</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/plugins"><span title="Plugins" class="linkLabel_hZzm">Plugins</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/architecture"><span title="Architecture" class="linkLabel_hZzm">Architecture</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/configuration"><span title="Configuration" class="linkLabel_hZzm">Configuration</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist" href="/appkit/docs/category/development"><span title="Development" class="categoryLinkLabel_ShmP">Development</span></a><button aria-label="Collapse sidebar category 'Development'" aria-expanded="true" type="button" class="clean-btn menu__caret"></button></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/local-development"><span title="Local development" class="linkLabel_hZzm">Local development</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/"><span title="Development" class="linkLabel_hZzm">Development</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/remote-bridge"><span title="Remote Bridge" class="linkLabel_hZzm">Remote Bridge</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/project-setup"><span title="Project setup" class="linkLabel_hZzm">Project setup</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/type-generation"><span title="Type generation" class="linkLabel_hZzm">Type generation</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/llm-guide"><span title="LLM Guide" class="linkLabel_hZzm">LLM Guide</span></a></li></ul></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/core-principles"><span title="Core principles" class="linkLabel_hZzm">Core principles</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist menu__link--active" href="/appkit/docs/api/"><span title="API reference" class="categoryLinkLabel_ShmP">API reference</span></a><button aria-label="Collapse sidebar category 'API reference'" aria-expanded="true" type="button" class="clean-btn menu__caret"></button></div><ul class="menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-2 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist menu__link--active" tabindex="0" href="/appkit/docs/api/appkit/"><span title="@databricks/appkit" class="categoryLinkLabel_ShmP">@databricks/appkit</span></a><button aria-label="Collapse sidebar category '@databricks/appkit'" aria-expanded="true" type="button" class="clean-btn menu__caret"></button></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/appkit/docs/api/appkit/Class.AppKitError"><span title="AppKitError" class="linkLabel_hZzm">AppKitError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.AuthenticationError"><span title="AuthenticationError" class="linkLabel_hZzm">AuthenticationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ConfigurationError"><span title="ConfigurationError" class="linkLabel_hZzm">ConfigurationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ConnectionError"><span title="ConnectionError" class="linkLabel_hZzm">ConnectionError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ExecutionError"><span title="ExecutionError" class="linkLabel_hZzm">ExecutionError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.InitializationError"><span title="InitializationError" class="linkLabel_hZzm">InitializationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.Plugin"><span title="Plugin" class="linkLabel_hZzm">Plugin</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ServerError"><span title="ServerError" class="linkLabel_hZzm">ServerError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.TunnelError"><span title="TunnelError" class="linkLabel_hZzm">TunnelError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ValidationError"><span title="ValidationError" class="linkLabel_hZzm">ValidationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.BasePluginConfig"><span title="BasePluginConfig" class="linkLabel_hZzm">BasePluginConfig</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.CacheConfig"><span title="CacheConfig" class="linkLabel_hZzm">CacheConfig</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.ITelemetry"><span title="ITelemetry" class="linkLabel_hZzm">ITelemetry</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.StreamExecutionSettings"><span title="StreamExecutionSettings" class="linkLabel_hZzm">StreamExecutionSettings</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.TelemetryConfig"><span title="TelemetryConfig" class="linkLabel_hZzm">TelemetryConfig</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-typealias"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/TypeAlias.IAppRouter"><span title="IAppRouter" class="linkLabel_hZzm">IAppRouter</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-variable"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Variable.sql"><span title="sql" class="linkLabel_hZzm">sql</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.appKitTypesPlugin"><span title="appKitTypesPlugin" class="linkLabel_hZzm">appKitTypesPlugin</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.createApp"><span title="createApp" class="linkLabel_hZzm">createApp</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.isSQLTypeMarker"><span title="isSQLTypeMarker" class="linkLabel_hZzm">isSQLTypeMarker</span></a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-2 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist" tabindex="0" href="/appkit/docs/api/appkit-ui/"><span title="@databricks/appkit-ui" class="categoryLinkLabel_ShmP">@databricks/appkit-ui</span></a><button aria-label="Expand sidebar category '@databricks/appkit-ui'" aria-expanded="false" type="button" class="clean-btn menu__caret"></button></div></li></ul></li></ul></nav></div></div></aside><main class="docMainContainer_P5br"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_poBZ"><div class="docItemContainer_TdBg"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_bEIa" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/appkit/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_sma7"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><a class="breadcrumbs__link" href="/appkit/docs/api/"><span>API reference</span></a></li><li class="breadcrumbs__item"><a class="breadcrumbs__link" href="/appkit/docs/api/appkit/"><span>@databricks/appkit</span></a></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">AppKitError</span></li></ul></nav><div class="tocCollapsible_gJxE theme-doc-toc-mobile tocMobile_ZHYV"><button type="button" class="clean-btn tocCollapsibleButton_uxuR">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Abstract Class: AppKitError</h1></header>
|
|
14
|
+
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const n=new URLSearchParams(window.location.search).entries();for(var[t,e]of n)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())</script><div id="__docusaurus"><link rel="preload" as="image" href="/appkit/img/logo.png"><div role="region" aria-label="Skip to main content"><a class="skipToContent_R3I2" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><div class="theme-announcement-bar announcementBar_Upl7" style="background-color:#f0f0f0;color:#000000" role="banner"><div class="announcementBarPlaceholder_Lvio"></div><div class="content_vq0X announcementBarContent_FIMQ">⚠️ AppKit is in an early development phase and is subject to change without notice. <strong>DO NOT</strong> use in production environments.</div><button type="button" aria-label="Close" class="clean-btn close closeButton_J8WU announcementBarClose_jD94"><svg viewBox="0 0 15 15" width="14" height="14"><g stroke="currentColor" stroke-width="3.1"><path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"></path></g></svg></button></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/appkit/"><div class="navbar__logo"><img src="/appkit/img/logo.png" alt="AppKit" class="themedComponent_hkXO themedComponent--light_BgK8"><img src="/appkit/img/logo.png" alt="AppKit" class="themedComponent_hkXO themedComponent--dark_RKPt"></div><b class="navbar__title text--truncate">AppKit</b></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/appkit/docs/">Documentation</a><a class="navbar__item navbar__link" href="/appkit/contributing">Contributing</a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://github.com/databricks/appkit" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-label="(opens in new tab)" class="iconExternalLink_miaU"><use href="#theme-svg-external-link"></use></svg></a><div class="toggle_eFYw colorModeToggle_EPbi"><button class="clean-btn toggleButton_HRKp toggleButtonDisabled_bICu" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_brDO lightToggleIcon_vxPA"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_brDO darkToggleIcon_PZNO"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_brDO systemToggleIcon_A7x6"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_cVhq"><div class="navbar__search"><span aria-label="expand searchbar" role="button" class="search-icon" tabindex="0"></span><input id="search_input_react" type="search" placeholder="Loading..." aria-label="Search" class="navbar__search-input search-bar" disabled=""></div></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper__Y_W"><div class="docsWrapper_cIfN"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_xQFv" type="button"></button><div class="docRoot_FHtD"><aside class="theme-doc-sidebar-container docSidebarContainer_dvCd"><div class="sidebarViewport_GeRf"><div class="sidebar_T8N1"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_uyE9 menuWithAnnouncementBar_Bucd"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/"><span title="Getting started" class="linkLabel_hZzm">Getting started</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/app-management"><span title="App management" class="linkLabel_hZzm">App management</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/plugins"><span title="Plugins" class="linkLabel_hZzm">Plugins</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/architecture"><span title="Architecture" class="linkLabel_hZzm">Architecture</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/configuration"><span title="Configuration" class="linkLabel_hZzm">Configuration</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist" href="/appkit/docs/category/development"><span title="Development" class="categoryLinkLabel_ShmP">Development</span></a><button aria-label="Collapse sidebar category 'Development'" aria-expanded="true" type="button" class="clean-btn menu__caret"></button></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/local-development"><span title="Local development" class="linkLabel_hZzm">Local development</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/"><span title="Development" class="linkLabel_hZzm">Development</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/remote-bridge"><span title="Remote Bridge" class="linkLabel_hZzm">Remote Bridge</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/project-setup"><span title="Project setup" class="linkLabel_hZzm">Project setup</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/type-generation"><span title="Type generation" class="linkLabel_hZzm">Type generation</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/appkit/docs/development/llm-guide"><span title="LLM Guide" class="linkLabel_hZzm">LLM Guide</span></a></li></ul></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appkit/docs/core-principles"><span title="Core principles" class="linkLabel_hZzm">Core principles</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist menu__link--active" href="/appkit/docs/api/"><span title="API reference" class="categoryLinkLabel_ShmP">API reference</span></a><button aria-label="Collapse sidebar category 'API reference'" aria-expanded="true" type="button" class="clean-btn menu__caret"></button></div><ul class="menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-2 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist menu__link--active" tabindex="0" href="/appkit/docs/api/appkit/"><span title="@databricks/appkit" class="categoryLinkLabel_ShmP">@databricks/appkit</span></a><button aria-label="Collapse sidebar category '@databricks/appkit'" aria-expanded="true" type="button" class="clean-btn menu__caret"></button></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/appkit/docs/api/appkit/Class.AppKitError"><span title="AppKitError" class="linkLabel_hZzm">AppKitError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.AuthenticationError"><span title="AuthenticationError" class="linkLabel_hZzm">AuthenticationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ConfigurationError"><span title="ConfigurationError" class="linkLabel_hZzm">ConfigurationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ConnectionError"><span title="ConnectionError" class="linkLabel_hZzm">ConnectionError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ExecutionError"><span title="ExecutionError" class="linkLabel_hZzm">ExecutionError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.InitializationError"><span title="InitializationError" class="linkLabel_hZzm">InitializationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.Plugin"><span title="Plugin" class="linkLabel_hZzm">Plugin</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ServerError"><span title="ServerError" class="linkLabel_hZzm">ServerError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.TunnelError"><span title="TunnelError" class="linkLabel_hZzm">TunnelError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-class"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Class.ValidationError"><span title="ValidationError" class="linkLabel_hZzm">ValidationError</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.BasePluginConfig"><span title="BasePluginConfig" class="linkLabel_hZzm">BasePluginConfig</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.CacheConfig"><span title="CacheConfig" class="linkLabel_hZzm">CacheConfig</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.ITelemetry"><span title="ITelemetry" class="linkLabel_hZzm">ITelemetry</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.StreamExecutionSettings"><span title="StreamExecutionSettings" class="linkLabel_hZzm">StreamExecutionSettings</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-interface"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Interface.TelemetryConfig"><span title="TelemetryConfig" class="linkLabel_hZzm">TelemetryConfig</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-typealias"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/TypeAlias.IAppRouter"><span title="IAppRouter" class="linkLabel_hZzm">IAppRouter</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-variable"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Variable.sql"><span title="sql" class="linkLabel_hZzm">sql</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.appKitTypesPlugin"><span title="appKitTypesPlugin" class="linkLabel_hZzm">appKitTypesPlugin</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.createApp"><span title="createApp" class="linkLabel_hZzm">createApp</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.getExecutionContext"><span title="getExecutionContext" class="linkLabel_hZzm">getExecutionContext</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-3 menu__list-item api-kind-function"><a class="menu__link" tabindex="0" href="/appkit/docs/api/appkit/Function.isSQLTypeMarker"><span title="isSQLTypeMarker" class="linkLabel_hZzm">isSQLTypeMarker</span></a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-2 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_P6CU menu__link menu__link--sublist" tabindex="0" href="/appkit/docs/api/appkit-ui/"><span title="@databricks/appkit-ui" class="categoryLinkLabel_ShmP">@databricks/appkit-ui</span></a><button aria-label="Expand sidebar category '@databricks/appkit-ui'" aria-expanded="false" type="button" class="clean-btn menu__caret"></button></div></li></ul></li></ul></nav></div></div></aside><main class="docMainContainer_P5br"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_poBZ"><div class="docItemContainer_TdBg"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_bEIa" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/appkit/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_sma7"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><a class="breadcrumbs__link" href="/appkit/docs/api/"><span>API reference</span></a></li><li class="breadcrumbs__item"><a class="breadcrumbs__link" href="/appkit/docs/api/appkit/"><span>@databricks/appkit</span></a></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">AppKitError</span></li></ul></nav><div class="tocCollapsible_gJxE theme-doc-toc-mobile tocMobile_ZHYV"><button type="button" class="clean-btn tocCollapsibleButton_uxuR">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Abstract Class: AppKitError</h1></header>
|
|
15
15
|
<p>Base error class for all AppKit errors.
|
|
16
16
|
Provides a consistent structure for error handling across the framework.</p>
|
|
17
17
|
<h2 class="anchor anchorTargetStickyNavbar_scV4" id="example">Example<a href="#example" class="hash-link" aria-label="Direct link to Example" title="Direct link to Example" translate="no"></a></h2>
|
|
@@ -44,6 +44,8 @@ Provides a consistent structure for error handling across the framework.</p>
|
|
|
44
44
|
<h3 class="anchor anchorTargetStickyNavbar_scV4" id="cause">cause?<a href="#cause" class="hash-link" aria-label="Direct link to cause?" title="Direct link to cause?" translate="no"></a></h3>
|
|
45
45
|
<div class="language-ts codeBlockContainer_crgn theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent__42J"><pre tabindex="0" class="prism-code language-ts codeBlock_CnLD thin-scrollbar" style="color:#000000;background-color:#ffffff"><code class="codeBlockLines_sJEA"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">readonly</span><span class="token plain"> optional cause</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> Error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre></div></div>
|
|
46
46
|
<p>Optional cause of the error</p>
|
|
47
|
+
<h4 class="anchor anchorTargetStickyNavbar_scV4" id="overrides-1">Overrides<a href="#overrides-1" class="hash-link" aria-label="Direct link to Overrides" title="Direct link to Overrides" translate="no"></a></h4>
|
|
48
|
+
<div class="language-ts codeBlockContainer_crgn theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent__42J"><pre tabindex="0" class="prism-code language-ts codeBlock_CnLD thin-scrollbar" style="color:#000000;background-color:#ffffff"><code class="codeBlockLines_sJEA"><span class="token-line" style="color:#000000"><span class="token plain">Error</span><span class="token punctuation" style="color:rgb(4, 81, 165)">.</span><span class="token plain">cause</span><br></span></code></pre></div></div>
|
|
47
49
|
<hr>
|
|
48
50
|
<h3 class="anchor anchorTargetStickyNavbar_scV4" id="code">code<a href="#code" class="hash-link" aria-label="Direct link to code" title="Direct link to code" translate="no"></a></h3>
|
|
49
51
|
<div class="language-ts codeBlockContainer_crgn theme-code-block" style="--prism-color:#000000;--prism-background-color:#ffffff"><div class="codeBlockContent__42J"><pre tabindex="0" class="prism-code language-ts codeBlock_CnLD thin-scrollbar" style="color:#000000;background-color:#ffffff"><code class="codeBlockLines_sJEA"><span class="token-line" style="color:#000000"><span class="token keyword" style="color:rgb(0, 0, 255)">abstract</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(0, 0, 255)">readonly</span><span class="token plain"> code</span><span class="token operator" style="color:rgb(0, 0, 0)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(0, 112, 193)">string</span><span class="token punctuation" style="color:rgb(4, 81, 165)">;</span><br></span></code></pre></div></div>
|