@databricks/appkit 0.24.0 → 0.25.1
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 +8 -1
- package/dist/appkit/package.js +1 -1
- package/dist/context/execution-context.js +1 -7
- package/dist/context/execution-context.js.map +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin/interceptors/retry.js +22 -0
- package/dist/plugin/interceptors/retry.js.map +1 -1
- package/dist/plugins/files/plugin.d.ts +46 -15
- package/dist/plugins/files/plugin.d.ts.map +1 -1
- package/dist/plugins/files/plugin.js +182 -103
- package/dist/plugins/files/plugin.js.map +1 -1
- package/dist/plugins/files/policy.d.ts +45 -0
- package/dist/plugins/files/policy.d.ts.map +1 -0
- package/dist/plugins/files/policy.js +63 -0
- package/dist/plugins/files/policy.js.map +1 -0
- package/dist/plugins/files/types.d.ts +16 -8
- package/dist/plugins/files/types.d.ts.map +1 -1
- package/dist/registry/manifest-loader.d.ts +2 -2
- package/dist/registry/manifest-loader.d.ts.map +1 -1
- package/docs/api/appkit/Class.PolicyDeniedError.md +52 -0
- package/docs/api/appkit/Interface.FilePolicyUser.md +23 -0
- package/docs/api/appkit/Interface.FileResource.md +36 -0
- package/docs/api/appkit/TypeAlias.FileAction.md +18 -0
- package/docs/api/appkit/TypeAlias.FilePolicy.md +20 -0
- package/docs/api/appkit/Variable.READ_ACTIONS.md +8 -0
- package/docs/api/appkit/Variable.WRITE_ACTIONS.md +8 -0
- package/docs/api/appkit.md +19 -12
- package/docs/faq.md +8 -8
- package/docs/plugins/execution-context.md +0 -1
- package/docs/plugins/files.md +150 -2
- package/docs/plugins/{serving.md → model-serving.md} +1 -1
- package/llms.txt +8 -1
- package/package.json +1 -1
- package/sbom.cdx.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -49,9 +49,9 @@ npx @databricks/appkit docs <query>
|
|
|
49
49
|
- [Files plugin](./docs/plugins/files.md): File operations against Databricks Unity Catalog Volumes. Supports listing, reading, downloading, uploading, deleting, and previewing files with built-in caching, retry, and timeout handling via the execution interceptor pipeline.
|
|
50
50
|
- [Genie plugin](./docs/plugins/genie.md): Integrates Databricks AI/BI Genie spaces into your AppKit application, enabling natural language data queries via a conversational interface.
|
|
51
51
|
- [Lakebase plugin](./docs/plugins/lakebase.md): Provides a PostgreSQL connection pool for Databricks Lakebase Autoscaling with automatic OAuth token refresh.
|
|
52
|
+
- [Model Serving plugin](./docs/plugins/model-serving.md): Provides an authenticated proxy to Databricks Model Serving endpoints, with invoke and streaming support.
|
|
52
53
|
- [Plugin management](./docs/plugins/plugin-management.md): AppKit includes a CLI for managing plugins. All commands are available under npx @databricks/appkit plugin.
|
|
53
54
|
- [Server plugin](./docs/plugins/server.md): Provides HTTP server capabilities with development and production modes.
|
|
54
|
-
- [Serving plugin](./docs/plugins/serving.md): Provides an authenticated proxy to Databricks Model Serving endpoints, with invoke and streaming support.
|
|
55
55
|
- [Vector Search plugin](./docs/plugins/vector-search.md): Query Databricks Vector Search indexes with hybrid search, reranking, and cursor pagination from your AppKit application.
|
|
56
56
|
|
|
57
57
|
## appkit API reference [collapsed]
|
|
@@ -64,6 +64,7 @@ npx @databricks/appkit docs <query>
|
|
|
64
64
|
- [Class: ExecutionError](./docs/api/appkit/Class.ExecutionError.md): Error thrown when an operation execution fails.
|
|
65
65
|
- [Class: InitializationError](./docs/api/appkit/Class.InitializationError.md): Error thrown when a service or component is not properly initialized.
|
|
66
66
|
- [Abstract Class: Plugin<TConfig>](./docs/api/appkit/Class.Plugin.md): Base abstract class for creating AppKit plugins.
|
|
67
|
+
- [Class: PolicyDeniedError](./docs/api/appkit/Class.PolicyDeniedError.md): Thrown when a policy denies an action.
|
|
67
68
|
- [Class: ResourceRegistry](./docs/api/appkit/Class.ResourceRegistry.md): Central registry for tracking plugin resource requirements.
|
|
68
69
|
- [Class: ServerError](./docs/api/appkit/Class.ServerError.md): Error thrown when server lifecycle operations fail.
|
|
69
70
|
- [Class: TunnelError](./docs/api/appkit/Class.TunnelError.md): Error thrown when remote tunnel operations fail.
|
|
@@ -89,6 +90,8 @@ npx @databricks/appkit docs <query>
|
|
|
89
90
|
- [Interface: CacheConfig](./docs/api/appkit/Interface.CacheConfig.md): Configuration for the CacheInterceptor. Controls TTL, size limits, storage backend, and probabilistic cleanup.
|
|
90
91
|
- [Interface: DatabaseCredential](./docs/api/appkit/Interface.DatabaseCredential.md): Database credentials with OAuth token for Postgres connection
|
|
91
92
|
- [Interface: EndpointConfig](./docs/api/appkit/Interface.EndpointConfig.md): Properties
|
|
93
|
+
- [Interface: FilePolicyUser](./docs/api/appkit/Interface.FilePolicyUser.md): Minimal user identity passed to the policy function.
|
|
94
|
+
- [Interface: FileResource](./docs/api/appkit/Interface.FileResource.md): Describes the file or directory being acted upon.
|
|
92
95
|
- [Interface: GenerateDatabaseCredentialRequest](./docs/api/appkit/Interface.GenerateDatabaseCredentialRequest.md): Request parameters for generating database OAuth credentials
|
|
93
96
|
- [Interface: ITelemetry](./docs/api/appkit/Interface.ITelemetry.md): Plugin-facing interface for OpenTelemetry instrumentation.
|
|
94
97
|
- [Interface: LakebasePoolConfig](./docs/api/appkit/Interface.LakebasePoolConfig.md): Configuration for creating a Lakebase connection pool
|
|
@@ -105,12 +108,16 @@ npx @databricks/appkit docs <query>
|
|
|
105
108
|
- [Interface: ValidationResult](./docs/api/appkit/Interface.ValidationResult.md): Result of validating all registered resources against the environment.
|
|
106
109
|
- [Type Alias: ConfigSchema](./docs/api/appkit/TypeAlias.ConfigSchema.md): Configuration schema definition for plugin config.
|
|
107
110
|
- [Type Alias: ExecutionResult<T>](./docs/api/appkit/TypeAlias.ExecutionResult.md): Discriminated union for plugin execution results.
|
|
111
|
+
- [Type Alias: FileAction](./docs/api/appkit/TypeAlias.FileAction.md): Every action the files plugin can perform.
|
|
112
|
+
- [Type Alias: FilePolicy()](./docs/api/appkit/TypeAlias.FilePolicy.md): A policy function that decides whether user may perform action on
|
|
108
113
|
- [Type Alias: IAppRouter](./docs/api/appkit/TypeAlias.IAppRouter.md): Express router type for plugin route registration
|
|
109
114
|
- [Type Alias: PluginData<T, U, N>](./docs/api/appkit/TypeAlias.PluginData.md): Tuple of plugin class, config, and name. Created by toPlugin() and passed to createApp().
|
|
110
115
|
- [Type Alias: ResourcePermission](./docs/api/appkit/TypeAlias.ResourcePermission.md): Union of all possible permission levels across all resource types.
|
|
111
116
|
- [Type Alias: ServingFactory](./docs/api/appkit/TypeAlias.ServingFactory.md): Factory function returned by AppKit.serving.
|
|
112
117
|
- [Type Alias: ToPlugin()<T, U, N>](./docs/api/appkit/TypeAlias.ToPlugin.md): Factory function type returned by toPlugin(). Accepts optional config and returns a PluginData tuple.
|
|
118
|
+
- [Variable: READ_ACTIONS](./docs/api/appkit/Variable.READ_ACTIONS.md): Actions that only read data.
|
|
113
119
|
- [Variable: sql](./docs/api/appkit/Variable.sql.md): SQL helper namespace
|
|
120
|
+
- [Variable: WRITE_ACTIONS](./docs/api/appkit/Variable.WRITE_ACTIONS.md): Actions that mutate data.
|
|
114
121
|
|
|
115
122
|
## appkit-ui API reference [collapsed]
|
|
116
123
|
|
package/dist/appkit/package.js
CHANGED
|
@@ -60,12 +60,6 @@ function getWarehouseId() {
|
|
|
60
60
|
function getWorkspaceId() {
|
|
61
61
|
return getExecutionContext().workspaceId;
|
|
62
62
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Check if currently running in a user context.
|
|
65
|
-
*/
|
|
66
|
-
function isInUserContext() {
|
|
67
|
-
return executionContextStorage.getStore() !== void 0;
|
|
68
|
-
}
|
|
69
63
|
var executionContextStorage;
|
|
70
64
|
var init_execution_context = __esmMin((() => {
|
|
71
65
|
init_errors();
|
|
@@ -76,5 +70,5 @@ var init_execution_context = __esmMin((() => {
|
|
|
76
70
|
|
|
77
71
|
//#endregion
|
|
78
72
|
init_execution_context();
|
|
79
|
-
export { getCurrentUserId, getExecutionContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, init_execution_context,
|
|
73
|
+
export { getCurrentUserId, getExecutionContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, init_execution_context, runInUserContext };
|
|
80
74
|
//# sourceMappingURL=execution-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context.js","names":[],"sources":["../../src/context/execution-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { ConfigurationError } from \"../errors\";\nimport { ServiceContext } from \"./service-context\";\nimport {\n type ExecutionContext,\n isUserContext,\n type UserContext,\n} from \"./user-context\";\n\n/**\n * AsyncLocalStorage for execution context.\n * Used to pass user context through the call stack without explicit parameters.\n */\nconst executionContextStorage = new AsyncLocalStorage<UserContext>();\n\n/**\n * Run a function in the context of a user.\n * All calls within the function will have access to the user context.\n *\n * @param userContext - The user context to use\n * @param fn - The function to run\n * @returns The result of the function\n */\nexport function runInUserContext<T>(userContext: UserContext, fn: () => T): T {\n return executionContextStorage.run(userContext, fn);\n}\n\n/**\n * Get the current execution context.\n *\n * - If running inside a user context (via asUser), returns the user context\n * - Otherwise, returns the service context\n *\n * @throws Error if ServiceContext is not initialized\n */\nexport function getExecutionContext(): ExecutionContext {\n const userContext = executionContextStorage.getStore();\n if (userContext) {\n return userContext;\n }\n return ServiceContext.get();\n}\n\n/**\n * Get the current user ID for cache keying and telemetry.\n *\n * Returns the user ID if in user context, otherwise the service user ID.\n */\nexport function getCurrentUserId(): string {\n const ctx = getExecutionContext();\n if (isUserContext(ctx)) {\n return ctx.userId;\n }\n return ctx.serviceUserId;\n}\n\n/**\n * Get the WorkspaceClient for the current execution context.\n */\nexport function getWorkspaceClient() {\n return getExecutionContext().client;\n}\n\n/**\n * Get the warehouse ID promise.\n */\nexport function getWarehouseId(): Promise<string> {\n const ctx = getExecutionContext();\n if (!ctx.warehouseId) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"No plugin requires a SQL Warehouse. Add a sql_warehouse resource to your plugin manifest, or set DATABRICKS_WAREHOUSE_ID\",\n );\n }\n return ctx.warehouseId;\n}\n\n/**\n * Get the workspace ID promise.\n */\nexport function getWorkspaceId(): Promise<string> {\n return getExecutionContext().workspaceId;\n}\n
|
|
1
|
+
{"version":3,"file":"execution-context.js","names":[],"sources":["../../src/context/execution-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { ConfigurationError } from \"../errors\";\nimport { ServiceContext } from \"./service-context\";\nimport {\n type ExecutionContext,\n isUserContext,\n type UserContext,\n} from \"./user-context\";\n\n/**\n * AsyncLocalStorage for execution context.\n * Used to pass user context through the call stack without explicit parameters.\n */\nconst executionContextStorage = new AsyncLocalStorage<UserContext>();\n\n/**\n * Run a function in the context of a user.\n * All calls within the function will have access to the user context.\n *\n * @param userContext - The user context to use\n * @param fn - The function to run\n * @returns The result of the function\n */\nexport function runInUserContext<T>(userContext: UserContext, fn: () => T): T {\n return executionContextStorage.run(userContext, fn);\n}\n\n/**\n * Get the current execution context.\n *\n * - If running inside a user context (via asUser), returns the user context\n * - Otherwise, returns the service context\n *\n * @throws Error if ServiceContext is not initialized\n */\nexport function getExecutionContext(): ExecutionContext {\n const userContext = executionContextStorage.getStore();\n if (userContext) {\n return userContext;\n }\n return ServiceContext.get();\n}\n\n/**\n * Get the current user ID for cache keying and telemetry.\n *\n * Returns the user ID if in user context, otherwise the service user ID.\n */\nexport function getCurrentUserId(): string {\n const ctx = getExecutionContext();\n if (isUserContext(ctx)) {\n return ctx.userId;\n }\n return ctx.serviceUserId;\n}\n\n/**\n * Get the WorkspaceClient for the current execution context.\n */\nexport function getWorkspaceClient() {\n return getExecutionContext().client;\n}\n\n/**\n * Get the warehouse ID promise.\n */\nexport function getWarehouseId(): Promise<string> {\n const ctx = getExecutionContext();\n if (!ctx.warehouseId) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"No plugin requires a SQL Warehouse. Add a sql_warehouse resource to your plugin manifest, or set DATABRICKS_WAREHOUSE_ID\",\n );\n }\n return ctx.warehouseId;\n}\n\n/**\n * Get the workspace ID promise.\n */\nexport function getWorkspaceId(): Promise<string> {\n return getExecutionContext().workspaceId;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,SAAgB,iBAAoB,aAA0B,IAAgB;AAC5E,QAAO,wBAAwB,IAAI,aAAa,GAAG;;;;;;;;;;AAWrD,SAAgB,sBAAwC;CACtD,MAAM,cAAc,wBAAwB,UAAU;AACtD,KAAI,YACF,QAAO;AAET,QAAO,eAAe,KAAK;;;;;;;AAQ7B,SAAgB,mBAA2B;CACzC,MAAM,MAAM,qBAAqB;AACjC,KAAI,cAAc,IAAI,CACpB,QAAO,IAAI;AAEb,QAAO,IAAI;;;;;AAMb,SAAgB,qBAAqB;AACnC,QAAO,qBAAqB,CAAC;;;;;AAM/B,SAAgB,iBAAkC;CAChD,MAAM,MAAM,qBAAqB;AACjC,KAAI,CAAC,IAAI,YACP,OAAM,mBAAmB,iBACvB,gBACA,2HACD;AAEH,QAAO,IAAI;;;;;AAMb,SAAgB,iBAAkC;AAChD,QAAO,qBAAqB,CAAC;;;;cAhFgB;uBACI;oBAK3B;CAMlB,0BAA0B,IAAI,mBAAgC"}
|
package/dist/context/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { ServiceContext, init_service_context } from "./service-context.js";
|
|
3
|
-
import { getCurrentUserId, getExecutionContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, init_execution_context,
|
|
3
|
+
import { getCurrentUserId, getExecutionContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, init_execution_context, runInUserContext } from "./execution-context.js";
|
|
4
4
|
|
|
5
5
|
//#region src/context/index.ts
|
|
6
6
|
var init_context = __esmMin((() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/context/index.ts"],"sourcesContent":["export {\n getCurrentUserId,\n getExecutionContext,\n getWarehouseId,\n getWorkspaceClient,\n getWorkspaceId,\n
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/context/index.ts"],"sourcesContent":["export {\n getCurrentUserId,\n getExecutionContext,\n getWarehouseId,\n getWorkspaceClient,\n getWorkspaceId,\n runInUserContext,\n} from \"./execution-context\";\nexport { ServiceContext } from \"./service-context\";\nexport type { UserContext } from \"./user-context\";\n"],"mappings":";;;;;;yBAO6B;uBACsB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { getPluginManifest, getResourceRequirements } from "./registry/manifest-
|
|
|
31
31
|
import { ResourceRegistry } from "./registry/resource-registry.js";
|
|
32
32
|
import "./registry/index.js";
|
|
33
33
|
import { analytics } from "./plugins/analytics/analytics.js";
|
|
34
|
+
import { FileAction, FilePolicy, FilePolicyUser, FileResource, PolicyDeniedError, READ_ACTIONS, WRITE_ACTIONS } from "./plugins/files/policy.js";
|
|
34
35
|
import { files } from "./plugins/files/plugin.js";
|
|
35
36
|
import { genie } from "./plugins/genie/genie.js";
|
|
36
37
|
import { lakebase } from "./plugins/lakebase/lakebase.js";
|
|
@@ -41,4 +42,4 @@ import "./plugins/index.js";
|
|
|
41
42
|
import { extractServingEndpoints, findServerFile } from "./type-generator/serving/server-file-extractor.js";
|
|
42
43
|
import { appKitServingTypesPlugin } from "./type-generator/serving/vite-plugin.js";
|
|
43
44
|
import { appKitTypesPlugin } from "./type-generator/vite-plugin.js";
|
|
44
|
-
export { AppKitError, AuthenticationError, type BasePluginConfig, type CacheConfig, CacheManager, type ConfigSchema, ConfigurationError, ConnectionError, type Counter, type DatabaseCredential, type EndpointConfig, ExecutionError, type ExecutionResult, type GenerateDatabaseCredentialRequest, type Histogram, type IAppRouter, type ITelemetry, InitializationError, type LakebasePoolConfig, Plugin, type PluginData, type PluginManifest, type RequestedClaims, RequestedClaimsPermissionSet, type RequestedResource, type ResourceEntry, type ResourceFieldEntry, type ResourcePermission, ResourceRegistry, type ResourceRequirement, ResourceType, ServerError, type ServingEndpointEntry, type ServingEndpointRegistry, type ServingFactory, SeverityNumber, type Span, SpanStatusCode, type StreamExecutionSettings, type TelemetryConfig, type ToPlugin, TunnelError, ValidationError, type ValidationResult, analytics, appKitServingTypesPlugin, appKitTypesPlugin, createApp, createLakebasePool, extractServingEndpoints, files, findServerFile, generateDatabaseCredential, genie, getExecutionContext, getLakebaseOrmConfig, getLakebasePgConfig, getPluginManifest, getResourceRequirements, getUsernameWithApiLookup, getWorkspaceClient, isSQLTypeMarker, lakebase, server, serving, sql, toPlugin };
|
|
45
|
+
export { AppKitError, AuthenticationError, type BasePluginConfig, type CacheConfig, CacheManager, type ConfigSchema, ConfigurationError, ConnectionError, type Counter, type DatabaseCredential, type EndpointConfig, ExecutionError, type ExecutionResult, type FileAction, type FilePolicy, type FilePolicyUser, type FileResource, type GenerateDatabaseCredentialRequest, type Histogram, type IAppRouter, type ITelemetry, InitializationError, type LakebasePoolConfig, Plugin, type PluginData, type PluginManifest, PolicyDeniedError, READ_ACTIONS, type RequestedClaims, RequestedClaimsPermissionSet, type RequestedResource, type ResourceEntry, type ResourceFieldEntry, type ResourcePermission, ResourceRegistry, type ResourceRequirement, ResourceType, ServerError, type ServingEndpointEntry, type ServingEndpointRegistry, type ServingFactory, SeverityNumber, type Span, SpanStatusCode, type StreamExecutionSettings, type TelemetryConfig, type ToPlugin, TunnelError, ValidationError, type ValidationResult, WRITE_ACTIONS, analytics, appKitServingTypesPlugin, appKitTypesPlugin, createApp, createLakebasePool, extractServingEndpoints, files, findServerFile, generateDatabaseCredential, genie, getExecutionContext, getLakebaseOrmConfig, getLakebasePgConfig, getPluginManifest, getResourceRequirements, getUsernameWithApiLookup, getWorkspaceClient, isSQLTypeMarker, lakebase, server, serving, sql, toPlugin };
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ import { Plugin } from "./plugin/plugin.js";
|
|
|
24
24
|
import { toPlugin } from "./plugin/to-plugin.js";
|
|
25
25
|
import "./plugin/index.js";
|
|
26
26
|
import { analytics } from "./plugins/analytics/analytics.js";
|
|
27
|
+
import { PolicyDeniedError, READ_ACTIONS, WRITE_ACTIONS } from "./plugins/files/policy.js";
|
|
27
28
|
import { files } from "./plugins/files/plugin.js";
|
|
28
29
|
import { genie } from "./plugins/genie/genie.js";
|
|
29
30
|
import { lakebase } from "./plugins/lakebase/lakebase.js";
|
|
@@ -39,5 +40,5 @@ init_context();
|
|
|
39
40
|
init_errors();
|
|
40
41
|
|
|
41
42
|
//#endregion
|
|
42
|
-
export { AppKitError, AuthenticationError, CacheManager, ConfigurationError, ConnectionError, ExecutionError, InitializationError, Plugin, RequestedClaimsPermissionSet, ResourceRegistry, ResourceType, ServerError, SeverityNumber, SpanStatusCode, TunnelError, ValidationError, analytics, appKitServingTypesPlugin, appKitTypesPlugin, createApp, createLakebasePool, extractServingEndpoints, files, findServerFile, generateDatabaseCredential, genie, getExecutionContext, getLakebaseOrmConfig, getLakebasePgConfig, getPluginManifest, getResourceRequirements, getUsernameWithApiLookup, getWorkspaceClient, isSQLTypeMarker, lakebase, server, serving, sql, toPlugin };
|
|
43
|
+
export { AppKitError, AuthenticationError, CacheManager, ConfigurationError, ConnectionError, ExecutionError, InitializationError, Plugin, PolicyDeniedError, READ_ACTIONS, RequestedClaimsPermissionSet, ResourceRegistry, ResourceType, ServerError, SeverityNumber, SpanStatusCode, TunnelError, ValidationError, WRITE_ACTIONS, analytics, appKitServingTypesPlugin, appKitTypesPlugin, createApp, createLakebasePool, extractServingEndpoints, files, findServerFile, generateDatabaseCredential, genie, getExecutionContext, getLakebaseOrmConfig, getLakebasePgConfig, getPluginManifest, getResourceRequirements, getUsernameWithApiLookup, getWorkspaceClient, isSQLTypeMarker, lakebase, server, serving, sql, toPlugin };
|
|
43
44
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Core library for building Databricks applications with type-safe SQL queries,\n * plugin architecture, and React integration.\n */\n\n// Types from shared\nexport type {\n BasePluginConfig,\n CacheConfig,\n IAppRouter,\n PluginData,\n StreamExecutionSettings,\n} from \"shared\";\nexport { isSQLTypeMarker, sql } from \"shared\";\nexport { CacheManager } from \"./cache\";\nexport type {\n DatabaseCredential,\n GenerateDatabaseCredentialRequest,\n LakebasePoolConfig,\n RequestedClaims,\n RequestedResource,\n} from \"./connectors/lakebase\";\n// Lakebase Autoscaling connector\nexport {\n createLakebasePool,\n generateDatabaseCredential,\n getLakebaseOrmConfig,\n getLakebasePgConfig,\n getUsernameWithApiLookup,\n getWorkspaceClient,\n RequestedClaimsPermissionSet,\n} from \"./connectors/lakebase\";\nexport { getExecutionContext } from \"./context\";\nexport { createApp } from \"./core\";\n// Errors\nexport {\n AppKitError,\n AuthenticationError,\n ConfigurationError,\n ConnectionError,\n ExecutionError,\n InitializationError,\n ServerError,\n TunnelError,\n ValidationError,\n} from \"./errors\";\n// Plugin authoring\nexport {\n type ExecutionResult,\n Plugin,\n type ToPlugin,\n toPlugin,\n} from \"./plugin\";\nexport { analytics, files, genie, lakebase, server, serving } from \"./plugins\";\nexport type {\n EndpointConfig,\n ServingEndpointEntry,\n ServingEndpointRegistry,\n ServingFactory,\n} from \"./plugins/serving/types\";\n// Registry types and utilities for plugin manifests\nexport type {\n ConfigSchema,\n PluginManifest,\n ResourceEntry,\n ResourceFieldEntry,\n ResourcePermission,\n ResourceRequirement,\n ValidationResult,\n} from \"./registry\";\nexport {\n getPluginManifest,\n getResourceRequirements,\n ResourceRegistry,\n ResourceType,\n} from \"./registry\";\n// Telemetry (for advanced custom telemetry)\nexport {\n type Counter,\n type Histogram,\n type ITelemetry,\n SeverityNumber,\n type Span,\n SpanStatusCode,\n type TelemetryConfig,\n} from \"./telemetry\";\nexport {\n extractServingEndpoints,\n findServerFile,\n} from \"./type-generator/serving/server-file-extractor\";\nexport { appKitServingTypesPlugin } from \"./type-generator/serving/vite-plugin\";\n// Vite plugin and type generation\nexport { appKitTypesPlugin } from \"./type-generator/vite-plugin\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Core library for building Databricks applications with type-safe SQL queries,\n * plugin architecture, and React integration.\n */\n\n// Types from shared\nexport type {\n BasePluginConfig,\n CacheConfig,\n IAppRouter,\n PluginData,\n StreamExecutionSettings,\n} from \"shared\";\nexport { isSQLTypeMarker, sql } from \"shared\";\nexport { CacheManager } from \"./cache\";\nexport type {\n DatabaseCredential,\n GenerateDatabaseCredentialRequest,\n LakebasePoolConfig,\n RequestedClaims,\n RequestedResource,\n} from \"./connectors/lakebase\";\n// Lakebase Autoscaling connector\nexport {\n createLakebasePool,\n generateDatabaseCredential,\n getLakebaseOrmConfig,\n getLakebasePgConfig,\n getUsernameWithApiLookup,\n getWorkspaceClient,\n RequestedClaimsPermissionSet,\n} from \"./connectors/lakebase\";\nexport { getExecutionContext } from \"./context\";\nexport { createApp } from \"./core\";\n// Errors\nexport {\n AppKitError,\n AuthenticationError,\n ConfigurationError,\n ConnectionError,\n ExecutionError,\n InitializationError,\n ServerError,\n TunnelError,\n ValidationError,\n} from \"./errors\";\n// Plugin authoring\nexport {\n type ExecutionResult,\n Plugin,\n type ToPlugin,\n toPlugin,\n} from \"./plugin\";\nexport { analytics, files, genie, lakebase, server, serving } from \"./plugins\";\n// Files plugin types (for custom policy authoring)\nexport type {\n FileAction,\n FilePolicy,\n FilePolicyUser,\n FileResource,\n} from \"./plugins/files/policy\";\nexport {\n PolicyDeniedError,\n READ_ACTIONS,\n WRITE_ACTIONS,\n} from \"./plugins/files/policy\";\nexport type {\n EndpointConfig,\n ServingEndpointEntry,\n ServingEndpointRegistry,\n ServingFactory,\n} from \"./plugins/serving/types\";\n// Registry types and utilities for plugin manifests\nexport type {\n ConfigSchema,\n PluginManifest,\n ResourceEntry,\n ResourceFieldEntry,\n ResourcePermission,\n ResourceRequirement,\n ValidationResult,\n} from \"./registry\";\nexport {\n getPluginManifest,\n getResourceRequirements,\n ResourceRegistry,\n ResourceType,\n} from \"./registry\";\n// Telemetry (for advanced custom telemetry)\nexport {\n type Counter,\n type Histogram,\n type ITelemetry,\n SeverityNumber,\n type Span,\n SpanStatusCode,\n type TelemetryConfig,\n} from \"./telemetry\";\nexport {\n extractServingEndpoints,\n findServerFile,\n} from \"./type-generator/serving/server-file-extractor\";\nexport { appKitServingTypesPlugin } from \"./type-generator/serving/vite-plugin\";\n// Vite plugin and type generation\nexport { appKitTypesPlugin } from \"./type-generator/vite-plugin\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkCgD;aAa9B"}
|
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
import { createLogger } from "../../logging/logger.js";
|
|
2
|
+
import { AppKitError, init_base } from "../../errors/base.js";
|
|
2
3
|
|
|
3
4
|
//#region src/plugin/interceptors/retry.ts
|
|
5
|
+
init_base();
|
|
4
6
|
const logger = createLogger("interceptors:retry");
|
|
7
|
+
/**
|
|
8
|
+
* Determines whether an error is safe to retry.
|
|
9
|
+
*
|
|
10
|
+
* Priority:
|
|
11
|
+
* 1. AppKitError — reads the `isRetryable` boolean property.
|
|
12
|
+
* 2. Databricks SDK ApiError (duck-typed) — calls `isRetryable()` method,
|
|
13
|
+
* or falls back to status-code heuristic (5xx / 429 → retryable).
|
|
14
|
+
* 3. Unknown errors — treated as retryable to preserve backward compatibility.
|
|
15
|
+
*/
|
|
16
|
+
function isRetryableError(error) {
|
|
17
|
+
if (error instanceof AppKitError) return error.isRetryable;
|
|
18
|
+
if (error instanceof Error && "statusCode" in error) {
|
|
19
|
+
const record = error;
|
|
20
|
+
if (typeof record.statusCode !== "number") return true;
|
|
21
|
+
if (typeof record.isRetryable === "function") return record.isRetryable();
|
|
22
|
+
return record.statusCode >= 500 || record.statusCode === 429;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
5
26
|
var RetryInterceptor = class {
|
|
6
27
|
attempts;
|
|
7
28
|
initialDelay;
|
|
@@ -24,6 +45,7 @@ var RetryInterceptor = class {
|
|
|
24
45
|
throw error;
|
|
25
46
|
}
|
|
26
47
|
if (context.signal?.aborted) throw error;
|
|
48
|
+
if (!isRetryableError(error)) throw error;
|
|
27
49
|
const delay = this.calculateDelay(attempt);
|
|
28
50
|
await this.sleep(delay);
|
|
29
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","names":[],"sources":["../../../src/plugin/interceptors/retry.ts"],"sourcesContent":["import type { RetryConfig } from \"shared\";\nimport { createLogger } from \"../../logging/logger\";\nimport type { ExecutionInterceptor, InterceptorContext } from \"./types\";\n\nconst logger = createLogger(\"interceptors:retry\");\n\n
|
|
1
|
+
{"version":3,"file":"retry.js","names":[],"sources":["../../../src/plugin/interceptors/retry.ts"],"sourcesContent":["import type { RetryConfig } from \"shared\";\nimport { AppKitError } from \"../../errors/base\";\nimport { createLogger } from \"../../logging/logger\";\nimport type { ExecutionInterceptor, InterceptorContext } from \"./types\";\n\nconst logger = createLogger(\"interceptors:retry\");\n\n/**\n * Determines whether an error is safe to retry.\n *\n * Priority:\n * 1. AppKitError — reads the `isRetryable` boolean property.\n * 2. Databricks SDK ApiError (duck-typed) — calls `isRetryable()` method,\n * or falls back to status-code heuristic (5xx / 429 → retryable).\n * 3. Unknown errors — treated as retryable to preserve backward compatibility.\n */\nfunction isRetryableError(error: unknown): boolean {\n if (error instanceof AppKitError) {\n return error.isRetryable;\n }\n\n if (error instanceof Error && \"statusCode\" in error) {\n const record = error as Record<string, unknown>;\n if (typeof record.statusCode !== \"number\") {\n return true;\n }\n if (typeof record.isRetryable === \"function\") {\n return (record.isRetryable as () => boolean)();\n }\n return record.statusCode >= 500 || record.statusCode === 429;\n }\n\n return true;\n}\n\nexport class RetryInterceptor implements ExecutionInterceptor {\n private attempts: number;\n private initialDelay: number;\n private maxDelay: number;\n\n constructor(config: RetryConfig) {\n this.attempts = config.attempts ?? 3;\n this.initialDelay = config.initialDelay ?? 1000;\n this.maxDelay = config.maxDelay ?? 30000;\n }\n\n async intercept<T>(\n fn: () => Promise<T>,\n context: InterceptorContext,\n ): Promise<T> {\n let lastError: Error | unknown;\n\n for (let attempt = 1; attempt <= this.attempts; attempt++) {\n try {\n const result = await fn();\n\n if (attempt > 1) {\n logger.event()?.setExecution({\n retry_attempts: attempt - 1,\n });\n }\n\n return result;\n } catch (error) {\n lastError = error;\n\n if (attempt === this.attempts) {\n logger.event()?.setExecution({\n retry_attempts: attempt - 1,\n });\n throw error;\n }\n\n if (context.signal?.aborted) {\n throw error;\n }\n\n if (!isRetryableError(error)) {\n throw error;\n }\n\n const delay = this.calculateDelay(attempt);\n await this.sleep(delay);\n }\n }\n\n throw lastError;\n }\n\n private calculateDelay(attempt: number): number {\n const delay = this.initialDelay * 2 ** (attempt - 1);\n const capped = Math.min(delay, this.maxDelay);\n\n return capped * Math.random();\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n"],"mappings":";;;;WACgD;AAIhD,MAAM,SAAS,aAAa,qBAAqB;;;;;;;;;;AAWjD,SAAS,iBAAiB,OAAyB;AACjD,KAAI,iBAAiB,YACnB,QAAO,MAAM;AAGf,KAAI,iBAAiB,SAAS,gBAAgB,OAAO;EACnD,MAAM,SAAS;AACf,MAAI,OAAO,OAAO,eAAe,SAC/B,QAAO;AAET,MAAI,OAAO,OAAO,gBAAgB,WAChC,QAAQ,OAAO,aAA+B;AAEhD,SAAO,OAAO,cAAc,OAAO,OAAO,eAAe;;AAG3D,QAAO;;AAGT,IAAa,mBAAb,MAA8D;CAC5D,AAAQ;CACR,AAAQ;CACR,AAAQ;CAER,YAAY,QAAqB;AAC/B,OAAK,WAAW,OAAO,YAAY;AACnC,OAAK,eAAe,OAAO,gBAAgB;AAC3C,OAAK,WAAW,OAAO,YAAY;;CAGrC,MAAM,UACJ,IACA,SACY;EACZ,IAAI;AAEJ,OAAK,IAAI,UAAU,GAAG,WAAW,KAAK,UAAU,UAC9C,KAAI;GACF,MAAM,SAAS,MAAM,IAAI;AAEzB,OAAI,UAAU,EACZ,QAAO,OAAO,EAAE,aAAa,EAC3B,gBAAgB,UAAU,GAC3B,CAAC;AAGJ,UAAO;WACA,OAAO;AACd,eAAY;AAEZ,OAAI,YAAY,KAAK,UAAU;AAC7B,WAAO,OAAO,EAAE,aAAa,EAC3B,gBAAgB,UAAU,GAC3B,CAAC;AACF,UAAM;;AAGR,OAAI,QAAQ,QAAQ,QAClB,OAAM;AAGR,OAAI,CAAC,iBAAiB,MAAM,CAC1B,OAAM;GAGR,MAAM,QAAQ,KAAK,eAAe,QAAQ;AAC1C,SAAM,KAAK,MAAM,MAAM;;AAI3B,QAAM;;CAGR,AAAQ,eAAe,SAAyB;EAC9C,MAAM,QAAQ,KAAK,eAAe,MAAM,UAAU;AAGlD,SAFe,KAAK,IAAI,OAAO,KAAK,SAAS,GAE7B,KAAK,QAAQ;;CAG/B,AAAQ,MAAM,IAA2B;AACvC,SAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { Plugin } from "../../plugin/plugin.js";
|
|
|
4
4
|
import "../../plugin/index.js";
|
|
5
5
|
import { PluginManifest, ResourceRequirement } from "../../registry/types.js";
|
|
6
6
|
import "../../registry/index.js";
|
|
7
|
+
import { FilePolicy, FilePolicyUser } from "./policy.js";
|
|
7
8
|
import { FilesExport, IFilesConfig, VolumeAPI, VolumeConfig } from "./types.js";
|
|
8
9
|
|
|
9
10
|
//#region src/plugins/files/plugin.d.ts
|
|
@@ -28,21 +29,22 @@ declare class FilesPlugin extends Plugin {
|
|
|
28
29
|
*/
|
|
29
30
|
static getResourceRequirements(config: IFilesConfig): ResourceRequirement[];
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
32
|
+
* Extract user identity from the request.
|
|
33
|
+
* Falls back to `getCurrentUserId()` in development mode.
|
|
33
34
|
*/
|
|
34
|
-
private
|
|
35
|
+
private _extractUser;
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
37
|
+
* Check the policy for a volume. No-op if no policy is configured.
|
|
38
|
+
* Throws `PolicyDeniedError` if denied.
|
|
38
39
|
*/
|
|
39
|
-
private
|
|
40
|
-
constructor(config: IFilesConfig);
|
|
40
|
+
private _checkPolicy;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* HTTP-level wrapper around `_checkPolicy`.
|
|
43
|
+
* Extracts user (401 on failure), runs policy (403 on denial).
|
|
44
|
+
* Returns `true` if the request may proceed, `false` if a response was sent.
|
|
44
45
|
*/
|
|
45
|
-
|
|
46
|
+
private _enforcePolicy;
|
|
47
|
+
constructor(config: IFilesConfig);
|
|
46
48
|
injectRoutes(router: IAppRouter): void;
|
|
47
49
|
/**
|
|
48
50
|
* Resolve `:volumeKey` from the request. Returns the connector and key,
|
|
@@ -59,6 +61,10 @@ declare class FilesPlugin extends Plugin {
|
|
|
59
61
|
* Invalidate cached list entries for a directory after a write operation.
|
|
60
62
|
* Uses the same cache-key format as `_handleList`: resolved path for
|
|
61
63
|
* subdirectories, `"__root__"` for the volume root.
|
|
64
|
+
*
|
|
65
|
+
* Cache keys include `getCurrentUserId()` — must match the identity used
|
|
66
|
+
* by `this.execute()` in `_handleList`. Both run in service-principal
|
|
67
|
+
* context; wrapping either in `runInUserContext` would break invalidation.
|
|
62
68
|
*/
|
|
63
69
|
private _invalidateListCache;
|
|
64
70
|
private _handleApiError;
|
|
@@ -79,6 +85,19 @@ declare class FilesPlugin extends Plugin {
|
|
|
79
85
|
private _handleUpload;
|
|
80
86
|
private _handleMkdir;
|
|
81
87
|
private _handleDelete;
|
|
88
|
+
/**
|
|
89
|
+
* Creates a VolumeAPI for a specific volume key.
|
|
90
|
+
*
|
|
91
|
+
* By default, enforces the volume's policy before each operation.
|
|
92
|
+
* Pass `bypassPolicy: true` to skip policy checks — useful for
|
|
93
|
+
* background jobs or migrations that should bypass user-facing policies.
|
|
94
|
+
*
|
|
95
|
+
* @security When `bypassPolicy` is `true`, no policy enforcement runs.
|
|
96
|
+
* Do not expose bypassed APIs to HTTP routes or end-user code paths.
|
|
97
|
+
*/
|
|
98
|
+
protected createVolumeAPI(volumeKey: string, user: FilePolicyUser, options?: {
|
|
99
|
+
bypassPolicy?: boolean;
|
|
100
|
+
}): VolumeAPI;
|
|
82
101
|
private inflightWrites;
|
|
83
102
|
private trackWrite;
|
|
84
103
|
shutdown(): Promise<void>;
|
|
@@ -86,13 +105,16 @@ declare class FilesPlugin extends Plugin {
|
|
|
86
105
|
* Returns the programmatic API for the Files plugin.
|
|
87
106
|
* Callable with a volume key to get a volume-scoped handle.
|
|
88
107
|
*
|
|
108
|
+
* All operations execute as the service principal.
|
|
109
|
+
* Use policies to control per-user access.
|
|
110
|
+
*
|
|
89
111
|
* @example
|
|
90
112
|
* ```ts
|
|
91
|
-
* //
|
|
92
|
-
* appKit.files("uploads").asUser(req).list()
|
|
93
|
-
*
|
|
94
|
-
* // Service principal access (logs a warning)
|
|
113
|
+
* // Service principal access
|
|
95
114
|
* appKit.files("uploads").list()
|
|
115
|
+
*
|
|
116
|
+
* // With policy: pass user identity for access control
|
|
117
|
+
* appKit.files("uploads").asUser(req).list()
|
|
96
118
|
* ```
|
|
97
119
|
*/
|
|
98
120
|
exports(): FilesExport;
|
|
@@ -101,7 +123,16 @@ declare class FilesPlugin extends Plugin {
|
|
|
101
123
|
/**
|
|
102
124
|
* @internal
|
|
103
125
|
*/
|
|
104
|
-
declare const files: ToPlugin<typeof FilesPlugin, IFilesConfig, string
|
|
126
|
+
declare const files: ToPlugin<typeof FilesPlugin, IFilesConfig, string> & {
|
|
127
|
+
policy: {
|
|
128
|
+
readonly all: (...policies: FilePolicy[]) => FilePolicy;
|
|
129
|
+
readonly any: (...policies: FilePolicy[]) => FilePolicy;
|
|
130
|
+
readonly not: (p: FilePolicy) => FilePolicy;
|
|
131
|
+
readonly publicRead: () => FilePolicy;
|
|
132
|
+
readonly denyAll: () => FilePolicy;
|
|
133
|
+
readonly allowAll: () => FilePolicy;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
105
136
|
//#endregion
|
|
106
137
|
export { FilesPlugin, files };
|
|
107
138
|
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../src/plugins/files/plugin.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../src/plugins/files/plugin.ts"],"mappings":";;;;;;;;;;cA2Ca,WAAA,SAAoB,MAAA;EAC/B,IAAA;;SAGO,QAAA,EAAuB,cAAA;EAAA,iBACb,WAAA;EAAA,UACC,MAAA,EAAQ,YAAA;EAAA,QAElB,gBAAA;EAAA,QACA,aAAA;EAAA,QACA,UAAA;EAJkB;;;;;EAAA,OAWnB,eAAA,CAAgB,MAAA,EAAQ,YAAA,GAAe,MAAA,SAAe,YAAA;EAuIzC;;;;EAAA,OAhHb,uBAAA,CAAwB,MAAA,EAAQ,YAAA,GAAe,mBAAA;EAs9B3C;;;;EAAA,QAh8BH,YAAA;EA9DuB;;;;EAAA,QAiFjB,YAAA;EA3EI;;;;;EAAA,QA4GJ,cAAA;cAsCF,MAAA,EAAQ,YAAA;EA8CpB,YAAA,CAAa,MAAA,EAAQ,UAAA;EArLyB;;;;EAAA,QAmTtC,cAAA;EA5R8C;;;;EAAA,QAmT9C,YAAA;EAAA,QAQA,aAAA;EA3MI;;;;;;;;;EAAA,QA+NJ,oBAAA;EAAA,QAgBA,eAAA;EAAA,QAqCA,gBAAA;EAAA,QAOM,WAAA;EAAA,QA8BA,WAAA;EAAA,QAmCA,eAAA;EAAA,QAWA,UAAA;EAqIA;;;;;EAAA,QArHA,UAAA;EAAA,QAiFA,aAAA;EAAA,QAoCA,eAAA;EAAA,QAoCA,cAAA;EAAA,QAoCA,aAAA;EAAA,QAgHA,YAAA;EAAA,QA0CA,aAAA;EA4GN;;;;;;;;;;EAAA,UAxDE,eAAA,CACR,SAAA,UACA,IAAA,EAAM,cAAA,EACN,OAAA;IAAY,YAAA;EAAA,IACX,SAAA;EAAA,QAoDK,cAAA;EAAA,QAEA,UAAA;EAOF,QAAA,CAAA,GAAY,OAAA;EA6EF;;;;;;;;;;;;;;;;EA1ChB,OAAA,CAAA,GAAW,WAAA;EAkCX,YAAA,CAAA,GAAgB,MAAA;AAAA;;;;cAQL,KAAA,EAAK,QAAA,QAAA,WAAA,EAAA,YAAA;;gCAAA,UAAA"}
|