@databricks/appkit 0.82.0 → 0.83.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CLAUDE.md +6 -0
  2. package/dist/appkit/package.js +1 -1
  3. package/dist/connectors/lakebase/index.js +1 -1
  4. package/dist/connectors/lakebase/routing-pool.d.ts +1 -1
  5. package/dist/connectors/lakebase/routing-pool.js +3 -3
  6. package/dist/connectors/lakebase/routing-pool.js.map +1 -1
  7. package/dist/context/caller-context.d.ts +22 -0
  8. package/dist/context/caller-context.d.ts.map +1 -0
  9. package/dist/context/caller-context.js +21 -0
  10. package/dist/context/caller-context.js.map +1 -0
  11. package/dist/context/deprecation.js +14 -0
  12. package/dist/context/deprecation.js.map +1 -0
  13. package/dist/context/execution-context.d.ts +12 -4
  14. package/dist/context/execution-context.d.ts.map +1 -1
  15. package/dist/context/execution-context.js +36 -34
  16. package/dist/context/execution-context.js.map +1 -1
  17. package/dist/context/index.d.ts +3 -2
  18. package/dist/context/index.js +2 -1
  19. package/dist/context/service-context.d.ts +18 -12
  20. package/dist/context/service-context.d.ts.map +1 -1
  21. package/dist/context/service-context.js +44 -54
  22. package/dist/context/service-context.js.map +1 -1
  23. package/dist/context/user-context.d.ts +5 -8
  24. package/dist/context/user-context.d.ts.map +1 -1
  25. package/dist/context/user-context.js +33 -6
  26. package/dist/context/user-context.js.map +1 -1
  27. package/dist/core/appkit.d.ts.map +1 -1
  28. package/dist/core/appkit.js +4 -2
  29. package/dist/core/appkit.js.map +1 -1
  30. package/dist/index.d.ts +7 -4
  31. package/dist/index.js +4 -2
  32. package/dist/plugin/plugin.d.ts +2 -2
  33. package/dist/plugin/plugin.d.ts.map +1 -1
  34. package/dist/plugin/plugin.js +6 -6
  35. package/dist/plugin/plugin.js.map +1 -1
  36. package/dist/plugins/agents/agents.d.ts +1 -1
  37. package/dist/plugins/ai-search/ai-search.d.ts +1 -1
  38. package/dist/plugins/analytics/analytics.d.ts +1 -1
  39. package/dist/plugins/analytics/analytics.d.ts.map +1 -1
  40. package/dist/plugins/analytics/analytics.js +3 -1
  41. package/dist/plugins/analytics/analytics.js.map +1 -1
  42. package/dist/plugins/database/database.d.ts +1 -1
  43. package/dist/plugins/files/plugin.d.ts +11 -11
  44. package/dist/plugins/files/plugin.js +17 -17
  45. package/dist/plugins/files/plugin.js.map +1 -1
  46. package/dist/plugins/genie/genie.d.ts +1 -1
  47. package/dist/plugins/jobs/plugin.d.ts +1 -1
  48. package/dist/plugins/lakebase/lakebase.d.ts +1 -1
  49. package/dist/plugins/lakebase/lakebase.d.ts.map +1 -1
  50. package/dist/plugins/lakebase/lakebase.js +4 -4
  51. package/dist/plugins/lakebase/lakebase.js.map +1 -1
  52. package/dist/plugins/server/index.d.ts +1 -1
  53. package/dist/plugins/server/index.js +2 -2
  54. package/dist/plugins/server/index.js.map +1 -1
  55. package/dist/plugins/server/remote-tunnel/remote-tunnel-manager.js +3 -3
  56. package/dist/plugins/server/remote-tunnel/remote-tunnel-manager.js.map +1 -1
  57. package/dist/plugins/server/static-server.js +3 -3
  58. package/dist/plugins/server/static-server.js.map +1 -1
  59. package/dist/plugins/server/utils.js +3 -3
  60. package/dist/plugins/server/utils.js.map +1 -1
  61. package/dist/plugins/server/vite-dev-server.js +4 -4
  62. package/dist/plugins/server/vite-dev-server.js.map +1 -1
  63. package/dist/plugins/serving/serving.d.ts +1 -1
  64. package/dist/resources/index.d.ts +1 -0
  65. package/dist/resources/index.js +3 -0
  66. package/dist/resources/warehouse.d.ts +16 -0
  67. package/dist/resources/warehouse.d.ts.map +1 -0
  68. package/dist/resources/warehouse.js +93 -0
  69. package/dist/resources/warehouse.js.map +1 -0
  70. package/dist/schemas/manifest.d.ts +9 -0
  71. package/dist/schemas/manifest.d.ts.map +1 -1
  72. package/dist/schemas/manifest.js +11 -0
  73. package/dist/schemas/manifest.js.map +1 -1
  74. package/dist/shared/src/schemas/manifest.d.ts +42 -33
  75. package/dist/shared/src/schemas/manifest.d.ts.map +1 -1
  76. package/dist/shared/src/schemas/manifest.js +11 -0
  77. package/dist/shared/src/schemas/manifest.js.map +1 -1
  78. package/dist/testing/create-test-app.js +2 -2
  79. package/dist/testing/create-test-app.js.map +1 -1
  80. package/dist/testing/fixtures.d.ts +3 -2
  81. package/dist/testing/fixtures.d.ts.map +1 -1
  82. package/dist/testing/fixtures.js +21 -14
  83. package/dist/testing/fixtures.js.map +1 -1
  84. package/dist/testing/reset-singletons.js +1 -1
  85. package/dist/type-generator/database/generate.js +3 -3
  86. package/dist/type-generator/database/generate.js.map +1 -1
  87. package/dist/type-generator/migration.js +2 -2
  88. package/dist/type-generator/migration.js.map +1 -1
  89. package/dist/type-generator/serving/server-file-extractor.js +3 -3
  90. package/dist/type-generator/serving/server-file-extractor.js.map +1 -1
  91. package/docs/api/appkit/Class.Plugin.md +1 -1
  92. package/docs/api/appkit/Function.getCurrentActorId.md +12 -0
  93. package/docs/api/appkit/Function.getCurrentPrincipalKey.md +12 -0
  94. package/docs/api/appkit/Function.getExecutionContext.md +5 -3
  95. package/docs/api/appkit/Function.getWarehouseId.md +20 -0
  96. package/docs/api/appkit/Interface.CallerContext.md +41 -0
  97. package/docs/api/appkit/Interface.PluginManifest.md +25 -2
  98. package/docs/api/appkit/TypeAlias.CallerPrincipal.md +13 -0
  99. package/docs/api/appkit/TypeAlias.ExecutionContext.md +6 -0
  100. package/docs/api/appkit.md +6 -0
  101. package/docs/plugins/analytics.md +8 -0
  102. package/llms.txt +6 -0
  103. package/package.json +1 -1
  104. package/sbom.cdx.json +1 -1
package/CLAUDE.md CHANGED
@@ -122,12 +122,15 @@ npx @databricks/appkit docs <query>
122
122
  - [Function: fromSupervisorApi()](./docs/api/appkit/Function.fromSupervisorApi.md): Creates an AgentAdapter backed by the Databricks AI Gateway
123
123
  - [Function: functionToolToDefinition()](./docs/api/appkit/Function.functionToolToDefinition.md): Parameters
124
124
  - [Function: generateDatabaseCredential()](./docs/api/appkit/Function.generateDatabaseCredential.md): Generate OAuth credentials for Postgres database connection using the proper Postgres API.
125
+ - [Function: getCurrentActorId()](./docs/api/appkit/Function.getCurrentActorId.md): The initiating user in a caller scope; no user actor exists in service scope.
126
+ - [Function: getCurrentPrincipalKey()](./docs/api/appkit/Function.getCurrentPrincipalKey.md): Get the principal key for future cache keying.
125
127
  - [Function: getExecutionContext()](./docs/api/appkit/Function.getExecutionContext.md): Get the current execution context.
126
128
  - [Function: getLakebaseOrmConfig()](./docs/api/appkit/Function.getLakebaseOrmConfig.md): Get Lakebase connection configuration for ORMs that don't accept pg.Pool directly.
127
129
  - [Function: getLakebasePgConfig()](./docs/api/appkit/Function.getLakebasePgConfig.md): Get Lakebase connection configuration for PostgreSQL clients.
128
130
  - [Function: getPluginManifest()](./docs/api/appkit/Function.getPluginManifest.md): Loads and validates the manifest from a plugin constructor.
129
131
  - [Function: getResourceRequirements()](./docs/api/appkit/Function.getResourceRequirements.md): Gets the resource requirements from a plugin's manifest.
130
132
  - [Function: getUsernameWithApiLookup()](./docs/api/appkit/Function.getUsernameWithApiLookup.md): Resolves the PostgreSQL username for a Lakebase connection.
133
+ - [Function: getWarehouseId()](./docs/api/appkit/Function.getWarehouseId.md): Get the configured SQL warehouse ID after app initialization.
131
134
  - [Function: getWorkspaceClient()](./docs/api/appkit/Function.getWorkspaceClient.md): Get workspace client from config or SDK default auth chain
132
135
  - [Function: id()](./docs/api/appkit/Function.id.md): Returns
133
136
  - [Function: includes()](./docs/api/appkit/Function.includes.md): Passes when the value contains substring.
@@ -175,6 +178,7 @@ npx @databricks/appkit docs <query>
175
178
  - [Interface: AutoInheritToolsConfig](./docs/api/appkit/Interface.AutoInheritToolsConfig.md): Auto-inherit configuration. When enabled for a given agent origin, agents
176
179
  - [Interface: BasePluginConfig](./docs/api/appkit/Interface.BasePluginConfig.md): Base configuration interface for AppKit plugins
177
180
  - [Interface: CacheConfig](./docs/api/appkit/Interface.CacheConfig.md): Configuration for the CacheInterceptor. Controls TTL, size limits, storage backend, and probabilistic cleanup.
181
+ - [Interface: CallerContext](./docs/api/appkit/Interface.CallerContext.md): Caller identity and workspace for one immutable execution scope.
178
182
  - [Interface: CustomJudgeSpec](./docs/api/appkit/Interface.CustomJudgeSpec.md): A custom LLM-judge definition: a prompt template and choice→score mapping.
179
183
  - [Interface: DatabaseCredential](./docs/api/appkit/Interface.DatabaseCredential.md): Database credentials with OAuth token for Postgres connection
180
184
  - [Interface: DatabaseRegistry](./docs/api/appkit/Interface.DatabaseRegistry.md): CANONICAL augmentation target. Empty by default; the generated database.d.ts
@@ -262,6 +266,7 @@ npx @databricks/appkit docs <query>
262
266
  - [Type Alias: AgentTools](./docs/api/appkit/TypeAlias.AgentTools.md): Per-agent tool record. String keys map to inline tools, toolkit entries,
263
267
  - [Type Alias: AgentToolsFn()](./docs/api/appkit/TypeAlias.AgentToolsFn.md): Function form of AgentDefinition.tools. Receives the typed
264
268
  - [Type Alias: BaseSystemPromptOption](./docs/api/appkit/TypeAlias.BaseSystemPromptOption.md)
269
+ - [Type Alias: CallerPrincipal](./docs/api/appkit/TypeAlias.CallerPrincipal.md): The caller identity whose permissions authorize execution, not its resources.
265
270
  - [Type Alias: ConfigSchema](./docs/api/appkit/TypeAlias.ConfigSchema.md): Configuration schema definition for plugin config.
266
271
  - [Type Alias: DatabaseApiConfig<TSchema>](./docs/api/appkit/TypeAlias.DatabaseApiConfig.md): Full generated CRUD for every declared table by default. Set false to disable
267
272
  - [Type Alias: DatabaseApiWriteOperation](./docs/api/appkit/TypeAlias.DatabaseApiWriteOperation.md): Generated HTTP write operations.
@@ -269,6 +274,7 @@ npx @databricks/appkit docs <query>
269
274
  - [Type Alias: DatabaseExports](./docs/api/appkit/TypeAlias.DatabaseExports.md): Typed database API published by the plugin.
270
275
  - [Type Alias: EntityHooks<TTable>](./docs/api/appkit/TypeAlias.EntityHooks.md): Response shaping and mutation lifecycle declared for one table.
271
276
  - [Type Alias: EvalProgress](./docs/api/appkit/TypeAlias.EvalProgress.md)
277
+ - [Type Alias: ExecutionContext](./docs/api/appkit/TypeAlias.ExecutionContext.md)
272
278
  - [Type Alias: ExecutionResult<T>](./docs/api/appkit/TypeAlias.ExecutionResult.md): Discriminated union for plugin execution results.
273
279
  - [Type Alias: FileAction](./docs/api/appkit/TypeAlias.FileAction.md): Every action the files plugin can perform.
274
280
  - [Type Alias: FilePolicy()](./docs/api/appkit/TypeAlias.FilePolicy.md): A policy function that decides whether user may perform action on
@@ -1,6 +1,6 @@
1
1
  //#region package.json
2
2
  var name = "@databricks/appkit";
3
- var version = "0.82.0";
3
+ var version = "0.83.0";
4
4
 
5
5
  //#endregion
6
6
  export { name, version };
@@ -2,8 +2,8 @@ import { createWorkspaceClient } from "../../shared/src/workspace-client/factory
2
2
  import { getClientOptions } from "../../context/client-options.js";
3
3
  import { ConfigurationError } from "../../errors/configuration.js";
4
4
  import "../../errors/index.js";
5
- import { ServiceContext } from "../../context/service-context.js";
6
5
  import { createLogger } from "../../logging/logger.js";
6
+ import { ServiceContext } from "../../context/service-context.js";
7
7
  import { createLakebasePoolManager } from "./pool-manager.js";
8
8
  import { RoutingPool } from "./routing-pool.js";
9
9
  import { RequestedClaimsPermissionSet, createLakebasePool, generateDatabaseCredential, getLakebaseOrmConfig, getLakebasePgConfig, getUsernameWithApiLookup, getUsernameWithApiLookup as getUsernameWithApiLookup$1, getWorkspaceClient } from "@databricks/lakebase";
@@ -1,4 +1,4 @@
1
- import "../../context/user-context.js";
1
+ import "../../context/caller-context.js";
2
2
  import { Pool, PoolClient, QueryResult, QueryResultRow } from "pg";
3
3
 
4
4
  //#region src/connectors/lakebase/routing-pool.d.ts
@@ -1,11 +1,11 @@
1
- import { getUserContext } from "../../context/execution-context.js";
1
+ import { getCallerContext } from "../../context/execution-context.js";
2
2
 
3
3
  //#region src/connectors/lakebase/routing-pool.ts
4
4
  /**
5
5
  * A `pg.Pool`-like wrapper that routes queries to the appropriate pool
6
6
  * based on the current execution context.
7
7
  *
8
- * When called inside `runInUserContext()` (set up by `Plugin.asUser(req)`),
8
+ * When called inside `runInCallerContext()` (set up by `Plugin.asUser(req)`),
9
9
  * queries route to the per-user pool returned by `resolveUserPool`.
10
10
  * Otherwise, queries route to the service-principal pool.
11
11
  *
@@ -19,7 +19,7 @@ var RoutingPool = class {
19
19
  this.resolveUserPool = resolveUserPool;
20
20
  }
21
21
  activePool() {
22
- const userCtx = getUserContext();
22
+ const userCtx = getCallerContext();
23
23
  return userCtx ? this.resolveUserPool(userCtx) : this.spPool;
24
24
  }
25
25
  query(text, values) {
@@ -1 +1 @@
1
- {"version":3,"file":"routing-pool.js","names":[],"sources":["../../../src/connectors/lakebase/routing-pool.ts"],"sourcesContent":["import type { Pool, PoolClient, QueryResult, QueryResultRow } from \"pg\";\n\nimport { getUserContext } from \"../../context/execution-context\";\nimport type { UserContext } from \"../../context/user-context\";\n\n/**\n * Subset of `pg.Pool` exposed by the Lakebase plugin.\n *\n * RoutingPool does not extend EventEmitter — event listener methods\n * like `on('error', ...)` are not available. Use `query()`, `connect()`,\n * and `end()` for all pool operations.\n */\nexport interface LakebasePool {\n query<T extends QueryResultRow = any>(\n text: string,\n values?: unknown[],\n ): Promise<QueryResult<T>>;\n connect(): Promise<PoolClient>;\n end(): Promise<void>;\n readonly totalCount: number;\n readonly idleCount: number;\n readonly waitingCount: number;\n}\n\n/**\n * A `pg.Pool`-like wrapper that routes queries to the appropriate pool\n * based on the current execution context.\n *\n * When called inside `runInUserContext()` (set up by `Plugin.asUser(req)`),\n * queries route to the per-user pool returned by `resolveUserPool`.\n * Otherwise, queries route to the service-principal pool.\n *\n * This enables OBO (On-Behalf-Of) without custom `asUser()` overrides —\n * the base class sets up AsyncLocalStorage context, and the RoutingPool\n * reads it transparently.\n */\nexport class RoutingPool implements LakebasePool {\n constructor(\n private spPool: Pool,\n private resolveUserPool: (ctx: UserContext) => Pool,\n ) {}\n\n private activePool(): Pool {\n const userCtx = getUserContext();\n return userCtx ? this.resolveUserPool(userCtx) : this.spPool;\n }\n\n query<T extends QueryResultRow = any>(\n text: string,\n values?: unknown[],\n ): Promise<QueryResult<T>> {\n return this.activePool().query<T>(text, values);\n }\n\n connect(): Promise<PoolClient> {\n return this.activePool().connect();\n }\n\n async end(): Promise<void> {\n await this.spPool.end();\n }\n\n get totalCount() {\n return this.spPool.totalCount;\n }\n get idleCount() {\n return this.spPool.idleCount;\n }\n get waitingCount() {\n return this.spPool.waitingCount;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAoCA,IAAa,cAAb,MAAiD;CAC/C,YACE,AAAQ,QACR,AAAQ,iBACR;EAFQ;EACA;;CAGV,AAAQ,aAAmB;EACzB,MAAM,UAAU,gBAAgB;AAChC,SAAO,UAAU,KAAK,gBAAgB,QAAQ,GAAG,KAAK;;CAGxD,MACE,MACA,QACyB;AACzB,SAAO,KAAK,YAAY,CAAC,MAAS,MAAM,OAAO;;CAGjD,UAA+B;AAC7B,SAAO,KAAK,YAAY,CAAC,SAAS;;CAGpC,MAAM,MAAqB;AACzB,QAAM,KAAK,OAAO,KAAK;;CAGzB,IAAI,aAAa;AACf,SAAO,KAAK,OAAO;;CAErB,IAAI,YAAY;AACd,SAAO,KAAK,OAAO;;CAErB,IAAI,eAAe;AACjB,SAAO,KAAK,OAAO"}
1
+ {"version":3,"file":"routing-pool.js","names":[],"sources":["../../../src/connectors/lakebase/routing-pool.ts"],"sourcesContent":["import type { Pool, PoolClient, QueryResult, QueryResultRow } from \"pg\";\n\nimport type { CallerContext } from \"../../context/caller-context\";\nimport { getCallerContext } from \"../../context/execution-context\";\n\n/**\n * Subset of `pg.Pool` exposed by the Lakebase plugin.\n *\n * RoutingPool does not extend EventEmitter — event listener methods\n * like `on('error', ...)` are not available. Use `query()`, `connect()`,\n * and `end()` for all pool operations.\n */\nexport interface LakebasePool {\n query<T extends QueryResultRow = any>(\n text: string,\n values?: unknown[],\n ): Promise<QueryResult<T>>;\n connect(): Promise<PoolClient>;\n end(): Promise<void>;\n readonly totalCount: number;\n readonly idleCount: number;\n readonly waitingCount: number;\n}\n\n/**\n * A `pg.Pool`-like wrapper that routes queries to the appropriate pool\n * based on the current execution context.\n *\n * When called inside `runInCallerContext()` (set up by `Plugin.asUser(req)`),\n * queries route to the per-user pool returned by `resolveUserPool`.\n * Otherwise, queries route to the service-principal pool.\n *\n * This enables OBO (On-Behalf-Of) without custom `asUser()` overrides —\n * the base class sets up AsyncLocalStorage context, and the RoutingPool\n * reads it transparently.\n */\nexport class RoutingPool implements LakebasePool {\n constructor(\n private spPool: Pool,\n private resolveUserPool: (ctx: CallerContext) => Pool,\n ) {}\n\n private activePool(): Pool {\n const userCtx = getCallerContext();\n return userCtx ? this.resolveUserPool(userCtx) : this.spPool;\n }\n\n query<T extends QueryResultRow = any>(\n text: string,\n values?: unknown[],\n ): Promise<QueryResult<T>> {\n return this.activePool().query<T>(text, values);\n }\n\n connect(): Promise<PoolClient> {\n return this.activePool().connect();\n }\n\n async end(): Promise<void> {\n await this.spPool.end();\n }\n\n get totalCount() {\n return this.spPool.totalCount;\n }\n get idleCount() {\n return this.spPool.idleCount;\n }\n get waitingCount() {\n return this.spPool.waitingCount;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAoCA,IAAa,cAAb,MAAiD;CAC/C,YACE,AAAQ,QACR,AAAQ,iBACR;EAFQ;EACA;;CAGV,AAAQ,aAAmB;EACzB,MAAM,UAAU,kBAAkB;AAClC,SAAO,UAAU,KAAK,gBAAgB,QAAQ,GAAG,KAAK;;CAGxD,MACE,MACA,QACyB;AACzB,SAAO,KAAK,YAAY,CAAC,MAAS,MAAM,OAAO;;CAGjD,UAA+B;AAC7B,SAAO,KAAK,YAAY,CAAC,SAAS;;CAGpC,MAAM,MAAqB;AACzB,QAAM,KAAK,OAAO,KAAK;;CAGzB,IAAI,aAAa;AACf,SAAO,KAAK,OAAO;;CAErB,IAAI,YAAY;AACd,SAAO,KAAK,OAAO;;CAErB,IAAI,eAAe;AACjB,SAAO,KAAK,OAAO"}
@@ -0,0 +1,22 @@
1
+ import { ServiceContextState } from "./service-context.js";
2
+
3
+ //#region src/context/caller-context.d.ts
4
+ /** The caller identity whose permissions authorize execution, not its resources. */
5
+ type CallerPrincipal = Readonly<{
6
+ type: "user";
7
+ userId: string;
8
+ userName?: string;
9
+ userEmail?: string;
10
+ }>;
11
+ /** Caller identity and workspace for one immutable execution scope. */
12
+ interface CallerContext {
13
+ readonly client: ServiceContextState["client"];
14
+ readonly principal: CallerPrincipal;
15
+ /** Truncated SHA-256 hash of the caller token, used to detect rotation. */
16
+ readonly tokenFingerprint?: string;
17
+ readonly workspaceId: Promise<string>;
18
+ }
19
+ type ExecutionContext = ServiceContextState | CallerContext;
20
+ //#endregion
21
+ export { CallerContext, CallerPrincipal, ExecutionContext };
22
+ //# sourceMappingURL=caller-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caller-context.d.ts","names":[],"sources":["../../src/context/caller-context.ts"],"mappings":";;;;KAGY,eAAA,GAAkB,QAAA;EAC5B,IAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;AAAA;;UAIe,aAAA;EAAA,SACN,MAAA,EAAQ,mBAAA;EAAA,SACR,SAAA,EAAW,eAAA;EANX;EAAA,SAQA,gBAAA;EAAA,SACA,WAAA,EAAa,OAAA;AAAA;AAAA,KAkBZ,gBAAA,GAAmB,mBAAA,GAAsB,aAAA"}
@@ -0,0 +1,21 @@
1
+ //#region src/context/caller-context.ts
2
+ const snapshots = /* @__PURE__ */ new WeakSet();
3
+ /** Snapshot identity without freezing the SDK client's internal lifecycle. */
4
+ function snapshotCallerContext(ctx) {
5
+ if (snapshots.has(ctx)) return ctx;
6
+ const snapshot = Object.freeze({
7
+ client: ctx.client,
8
+ principal: Object.freeze({ ...ctx.principal }),
9
+ tokenFingerprint: ctx.tokenFingerprint,
10
+ workspaceId: ctx.workspaceId
11
+ });
12
+ snapshots.add(snapshot);
13
+ return snapshot;
14
+ }
15
+ function isCallerContext(ctx) {
16
+ return "principal" in ctx && ctx.principal.type === "user";
17
+ }
18
+
19
+ //#endregion
20
+ export { isCallerContext, snapshotCallerContext };
21
+ //# sourceMappingURL=caller-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caller-context.js","names":[],"sources":["../../src/context/caller-context.ts"],"sourcesContent":["import type { ServiceContextState } from \"./service-context\";\n\n/** The caller identity whose permissions authorize execution, not its resources. */\nexport type CallerPrincipal = Readonly<{\n type: \"user\";\n userId: string;\n userName?: string;\n userEmail?: string;\n}>;\n\n/** Caller identity and workspace for one immutable execution scope. */\nexport interface CallerContext {\n readonly client: ServiceContextState[\"client\"];\n readonly principal: CallerPrincipal;\n /** Truncated SHA-256 hash of the caller token, used to detect rotation. */\n readonly tokenFingerprint?: string;\n readonly workspaceId: Promise<string>;\n}\n\nconst snapshots = new WeakSet<CallerContext>();\n\n/** Snapshot identity without freezing the SDK client's internal lifecycle. */\nexport function snapshotCallerContext(ctx: CallerContext): CallerContext {\n if (snapshots.has(ctx)) return ctx;\n const snapshot = Object.freeze({\n client: ctx.client,\n principal: Object.freeze({ ...ctx.principal }),\n tokenFingerprint: ctx.tokenFingerprint,\n workspaceId: ctx.workspaceId,\n });\n snapshots.add(snapshot);\n return snapshot;\n}\n\nexport type ExecutionContext = ServiceContextState | CallerContext;\n\nexport function isCallerContext(ctx: ExecutionContext): ctx is CallerContext {\n return \"principal\" in ctx && ctx.principal.type === \"user\";\n}\n"],"mappings":";AAmBA,MAAM,4BAAY,IAAI,SAAwB;;AAG9C,SAAgB,sBAAsB,KAAmC;AACvE,KAAI,UAAU,IAAI,IAAI,CAAE,QAAO;CAC/B,MAAM,WAAW,OAAO,OAAO;EAC7B,QAAQ,IAAI;EACZ,WAAW,OAAO,OAAO,EAAE,GAAG,IAAI,WAAW,CAAC;EAC9C,kBAAkB,IAAI;EACtB,aAAa,IAAI;EAClB,CAAC;AACF,WAAU,IAAI,SAAS;AACvB,QAAO;;AAKT,SAAgB,gBAAgB,KAA6C;AAC3E,QAAO,eAAe,OAAO,IAAI,UAAU,SAAS"}
@@ -0,0 +1,14 @@
1
+ import { createLogger } from "../logging/logger.js";
2
+
3
+ //#region src/context/deprecation.ts
4
+ const logger = createLogger("execution-context");
5
+ const warned = /* @__PURE__ */ new Set();
6
+ function warnContextDeprecation(name, replacement) {
7
+ if (warned.has(name)) return;
8
+ warned.add(name);
9
+ logger.warn(`${name} is deprecated. Use ${replacement} instead.`);
10
+ }
11
+
12
+ //#endregion
13
+ export { warnContextDeprecation };
14
+ //# sourceMappingURL=deprecation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deprecation.js","names":[],"sources":["../../src/context/deprecation.ts"],"sourcesContent":["import { createLogger } from \"../logging/logger\";\n\nconst logger = createLogger(\"execution-context\");\nconst warned = new Set<string>();\n\nexport function warnContextDeprecation(\n name: string,\n replacement: string,\n): void {\n if (warned.has(name)) return;\n warned.add(name);\n logger.warn(`${name} is deprecated. Use ${replacement} instead.`);\n}\n"],"mappings":";;;AAEA,MAAM,SAAS,aAAa,oBAAoB;AAChD,MAAM,yBAAS,IAAI,KAAa;AAEhC,SAAgB,uBACd,MACA,aACM;AACN,KAAI,OAAO,IAAI,KAAK,CAAE;AACtB,QAAO,IAAI,KAAK;AAChB,QAAO,KAAK,GAAG,KAAK,sBAAsB,YAAY,WAAW"}
@@ -1,15 +1,23 @@
1
- import { ExecutionContext } from "./user-context.js";
1
+ import { UserContext } from "./user-context.js";
2
+ import { ServiceContextState } from "./service-context.js";
3
+ import { CallerContext } from "./caller-context.js";
2
4
 
3
5
  //#region src/context/execution-context.d.ts
4
6
  /**
5
7
  * Get the current execution context.
6
8
  *
7
- * - If running inside a user context (via asUser), returns the user context
9
+ * - If running inside a caller context (via asUser), returns the caller context
8
10
  * - Otherwise, returns the service context
9
11
  *
10
12
  * @throws Error if ServiceContext is not initialized
11
13
  */
12
- declare function getExecutionContext(): ExecutionContext;
14
+ declare function getExecutionContext(): ServiceContextState | (CallerContext & UserContext);
15
+ /**
16
+ * Get the principal key for future cache keying: `app` or `user:<id>`.
17
+ */
18
+ declare function getCurrentPrincipalKey(): string;
19
+ /** The initiating user in a caller scope; no user actor exists in service scope. */
20
+ declare function getCurrentActorId(): string | undefined;
13
21
  //#endregion
14
- export { getExecutionContext };
22
+ export { getCurrentActorId, getCurrentPrincipalKey, getExecutionContext };
15
23
  //# sourceMappingURL=execution-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"execution-context.d.ts","names":[],"sources":["../../src/context/execution-context.ts"],"mappings":";;;;;;;;;;;iBAoCgB,mBAAA,CAAA,GAAuB,gBAAA"}
1
+ {"version":3,"file":"execution-context.d.ts","names":[],"sources":["../../src/context/execution-context.ts"],"mappings":";;;;;;;;;AAkFA;;;;iBAbgB,mBAAA,CAAA,GACZ,mBAAA,IACC,aAAA,GAAgB,WAAA;AAiBrB;;;AAAA,iBANgB,sBAAA,CAAA;;iBAMA,iBAAA,CAAA"}
@@ -1,68 +1,70 @@
1
- import { ConfigurationError } from "../errors/configuration.js";
2
- import "../errors/index.js";
1
+ import { captureWarehouseId, runWithResourceBindings } from "../resources/warehouse.js";
2
+ import { snapshotCallerContext } from "./caller-context.js";
3
+ import { warnContextDeprecation } from "./deprecation.js";
4
+ import { legacyUserContext } from "./user-context.js";
3
5
  import { ServiceContext } from "./service-context.js";
4
- import { isUserContext } from "./user-context.js";
5
6
  import { AsyncLocalStorage } from "node:async_hooks";
6
7
 
7
8
  //#region src/context/execution-context.ts
8
- /**
9
- * AsyncLocalStorage for execution context.
10
- * Used to pass user context through the call stack without explicit parameters.
11
- */
12
9
  const executionContextStorage = new AsyncLocalStorage();
10
+ function runInCallerScope(callerContext, fn, legacyResources) {
11
+ const caller = snapshotCallerContext(callerContext);
12
+ return runWithResourceBindings(legacyResources, () => executionContextStorage.run(caller, fn));
13
+ }
13
14
  /**
14
- * Run a function in the context of a user.
15
- * All calls within the function will have access to the user context.
15
+ * Run a function with an immutable snapshot of the caller context.
16
+ * Nested and concurrent scopes keep their own identities.
16
17
  *
17
- * @param userContext - The user context to use
18
+ * @param callerContext - The caller context to use
18
19
  * @param fn - The function to run
19
20
  * @returns The result of the function
20
21
  */
21
- function runInUserContext(userContext, fn) {
22
- return executionContextStorage.run(userContext, fn);
22
+ function runInCallerContext(callerContext, fn) {
23
+ return runInCallerScope(callerContext, fn);
23
24
  }
24
25
  /**
25
26
  * Get the current execution context.
26
27
  *
27
- * - If running inside a user context (via asUser), returns the user context
28
+ * - If running inside a caller context (via asUser), returns the caller context
28
29
  * - Otherwise, returns the service context
29
30
  *
30
31
  * @throws Error if ServiceContext is not initialized
31
32
  */
32
33
  function getExecutionContext() {
33
- const userContext = executionContextStorage.getStore();
34
- if (userContext) return userContext;
34
+ const callerContext = executionContextStorage.getStore();
35
+ if (callerContext) return legacyUserContext(callerContext, captureWarehouseId());
35
36
  return ServiceContext.get();
36
37
  }
37
38
  /**
38
- * Get the current user ID for cache keying and telemetry.
39
- *
40
- * Returns the user ID if in user context, otherwise the service user ID.
39
+ * Get the principal key for future cache keying: `app` or `user:<id>`.
41
40
  */
42
- function getCurrentUserId() {
43
- const ctx = getExecutionContext();
44
- if (isUserContext(ctx)) return ctx.userId;
45
- return ctx.serviceUserId;
41
+ function getCurrentPrincipalKey() {
42
+ const caller = getCallerContext();
43
+ return caller ? `user:${caller.principal.userId}` : "app";
44
+ }
45
+ /** The initiating user in a caller scope; no user actor exists in service scope. */
46
+ function getCurrentActorId() {
47
+ return getCallerContext()?.principal.userId;
46
48
  }
47
49
  /**
48
- * Get the WorkspaceClient for the current execution context.
50
+ * @deprecated Use getCurrentPrincipalKey for new cache keys or getCurrentActorId
51
+ * for audit. Preserves the bare user or service ID for existing callers.
49
52
  */
50
- function getWorkspaceClient() {
51
- return getExecutionContext().client;
53
+ function getCurrentUserId() {
54
+ warnContextDeprecation("getCurrentUserId", "getCurrentPrincipalKey (cache) or getCurrentActorId (audit)");
55
+ return getCurrentActorId() ?? ServiceContext.get().serviceUserId;
52
56
  }
53
57
  /**
54
- * Get the warehouse ID promise.
58
+ * Get the WorkspaceClient for the current execution context.
55
59
  */
56
- function getWarehouseId() {
57
- const ctx = getExecutionContext();
58
- if (!ctx.warehouseId) throw ConfigurationError.resourceNotFound("Warehouse ID", "No plugin requires a SQL Warehouse. Add a sql_warehouse resource to your plugin manifest, or set DATABRICKS_WAREHOUSE_ID");
59
- return ctx.warehouseId;
60
+ function getWorkspaceClient() {
61
+ return (getCallerContext() ?? ServiceContext.get()).client;
60
62
  }
61
63
  /**
62
64
  * Get the workspace ID promise.
63
65
  */
64
66
  function getWorkspaceId() {
65
- return getExecutionContext().workspaceId;
67
+ return (getCallerContext() ?? ServiceContext.get()).workspaceId;
66
68
  }
67
69
  /**
68
70
  * Check if currently running in a user context.
@@ -71,14 +73,14 @@ function isInUserContext() {
71
73
  return executionContextStorage.getStore() !== void 0;
72
74
  }
73
75
  /**
74
- * Get the user context if one is active, otherwise `undefined`.
76
+ * Get the caller context if one is active, otherwise `undefined`.
75
77
  * Unlike `getExecutionContext()`, this does not require `ServiceContext`
76
78
  * to be initialized and never throws.
77
79
  */
78
- function getUserContext() {
80
+ function getCallerContext() {
79
81
  return executionContextStorage.getStore();
80
82
  }
81
83
 
82
84
  //#endregion
83
- export { getCurrentUserId, getExecutionContext, getUserContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, isInUserContext, runInUserContext };
85
+ export { getCallerContext, getCurrentActorId, getCurrentPrincipalKey, getCurrentUserId, getExecutionContext, getWorkspaceClient, getWorkspaceId, isInUserContext, runInCallerContext };
84
86
  //# 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\";\n\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\n/**\n * Check if currently running in a user context.\n */\nexport function isInUserContext(): boolean {\n const ctx = executionContextStorage.getStore();\n return ctx !== undefined;\n}\n\n/**\n * Get the user context if one is active, otherwise `undefined`.\n * Unlike `getExecutionContext()`, this does not require `ServiceContext`\n * to be initialized and never throws.\n */\nexport function getUserContext(): UserContext | undefined {\n return executionContextStorage.getStore();\n}\n"],"mappings":";;;;;;;;;;;AAcA,MAAM,0BAA0B,IAAI,mBAAgC;;;;;;;;;AAUpE,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;;;;;AAM/B,SAAgB,kBAA2B;AAEzC,QADY,wBAAwB,UAAU,KAC/B;;;;;;;AAQjB,SAAgB,iBAA0C;AACxD,QAAO,wBAAwB,UAAU"}
1
+ {"version":3,"file":"execution-context.js","names":[],"sources":["../../src/context/execution-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport {\n captureWarehouseId,\n getWarehouseId as getResourceWarehouseId,\n runWithResourceBindings,\n type WarehouseBinding,\n} from \"../resources/warehouse\";\nimport { type CallerContext, snapshotCallerContext } from \"./caller-context\";\nimport { warnContextDeprecation } from \"./deprecation\";\nimport { ServiceContext, type ServiceContextState } from \"./service-context\";\nimport {\n legacyUserContext,\n toCallerContext,\n type UserContext,\n} from \"./user-context\";\n\nconst executionContextStorage = new AsyncLocalStorage<CallerContext>();\n\nfunction runInCallerScope<T>(\n callerContext: CallerContext,\n fn: () => T,\n legacyResources?: WarehouseBinding,\n): T {\n const caller = snapshotCallerContext(callerContext);\n return runWithResourceBindings(legacyResources, () =>\n executionContextStorage.run(caller, fn),\n );\n}\n\n/**\n * Run a function with an immutable snapshot of the caller context.\n * Nested and concurrent scopes keep their own identities.\n *\n * @param callerContext - The caller context to use\n * @param fn - The function to run\n * @returns The result of the function\n */\nexport function runInCallerContext<T>(\n callerContext: CallerContext,\n fn: () => T,\n): T {\n return runInCallerScope(callerContext, fn);\n}\n\n/** @deprecated Use runInCallerContext. */\nexport function runInUserContext<T>(\n userContext: UserContext | (CallerContext & Pick<UserContext, \"warehouseId\">),\n fn: () => T,\n): T {\n warnContextDeprecation(\"runInUserContext\", \"runInCallerContext\");\n if (!(\"principal\" in userContext) || \"warehouseId\" in userContext) {\n return runInCallerScope(\n toCallerContext(userContext),\n fn,\n Object.freeze({ warehouseId: userContext.warehouseId }),\n );\n }\n return runInCallerContext(toCallerContext(userContext), fn);\n}\n\n/**\n * Get the current execution context.\n *\n * - If running inside a caller context (via asUser), returns the caller context\n * - Otherwise, returns the service context\n *\n * @throws Error if ServiceContext is not initialized\n */\nexport function getExecutionContext():\n | ServiceContextState\n | (CallerContext & UserContext) {\n const callerContext = executionContextStorage.getStore();\n if (callerContext) {\n return legacyUserContext(callerContext, captureWarehouseId());\n }\n return ServiceContext.get();\n}\n\n/**\n * Get the principal key for future cache keying: `app` or `user:<id>`.\n */\nexport function getCurrentPrincipalKey(): string {\n const caller = getCallerContext();\n return caller ? `user:${caller.principal.userId}` : \"app\";\n}\n\n/** The initiating user in a caller scope; no user actor exists in service scope. */\nexport function getCurrentActorId(): string | undefined {\n return getCallerContext()?.principal.userId;\n}\n\n/**\n * @deprecated Use getCurrentPrincipalKey for new cache keys or getCurrentActorId\n * for audit. Preserves the bare user or service ID for existing callers.\n */\nexport function getCurrentUserId(): string {\n warnContextDeprecation(\n \"getCurrentUserId\",\n \"getCurrentPrincipalKey (cache) or getCurrentActorId (audit)\",\n );\n return getCurrentActorId() ?? ServiceContext.get().serviceUserId;\n}\n\n/**\n * Get the WorkspaceClient for the current execution context.\n */\nexport function getWorkspaceClient() {\n return (getCallerContext() ?? ServiceContext.get()).client;\n}\n\n/**\n * @deprecated Import getWarehouseId from @databricks/appkit instead of context.\n */\nexport function getWarehouseId(): Promise<string> {\n warnContextDeprecation(\n \"context.getWarehouseId\",\n \"getWarehouseId() from @databricks/appkit\",\n );\n return getResourceWarehouseId();\n}\n\n/**\n * Get the workspace ID promise.\n */\nexport function getWorkspaceId(): Promise<string> {\n return (getCallerContext() ?? ServiceContext.get()).workspaceId;\n}\n\n/**\n * Check if currently running in a user context.\n */\nexport function isInUserContext(): boolean {\n const ctx = executionContextStorage.getStore();\n return ctx !== undefined;\n}\n\n/**\n * Get the caller context if one is active, otherwise `undefined`.\n * Unlike `getExecutionContext()`, this does not require `ServiceContext`\n * to be initialized and never throws.\n */\nexport function getCallerContext(): CallerContext | undefined {\n return executionContextStorage.getStore();\n}\n\n/** @deprecated Use getCallerContext and its principal field. */\nexport function getUserContext(): (CallerContext & UserContext) | undefined {\n warnContextDeprecation(\"getUserContext\", \"getCallerContext\");\n const scope = executionContextStorage.getStore();\n return scope ? legacyUserContext(scope, captureWarehouseId()) : undefined;\n}\n"],"mappings":";;;;;;;;AAiBA,MAAM,0BAA0B,IAAI,mBAAkC;AAEtE,SAAS,iBACP,eACA,IACA,iBACG;CACH,MAAM,SAAS,sBAAsB,cAAc;AACnD,QAAO,wBAAwB,uBAC7B,wBAAwB,IAAI,QAAQ,GAAG,CACxC;;;;;;;;;;AAWH,SAAgB,mBACd,eACA,IACG;AACH,QAAO,iBAAiB,eAAe,GAAG;;;;;;;;;;AA2B5C,SAAgB,sBAEkB;CAChC,MAAM,gBAAgB,wBAAwB,UAAU;AACxD,KAAI,cACF,QAAO,kBAAkB,eAAe,oBAAoB,CAAC;AAE/D,QAAO,eAAe,KAAK;;;;;AAM7B,SAAgB,yBAAiC;CAC/C,MAAM,SAAS,kBAAkB;AACjC,QAAO,SAAS,QAAQ,OAAO,UAAU,WAAW;;;AAItD,SAAgB,oBAAwC;AACtD,QAAO,kBAAkB,EAAE,UAAU;;;;;;AAOvC,SAAgB,mBAA2B;AACzC,wBACE,oBACA,8DACD;AACD,QAAO,mBAAmB,IAAI,eAAe,KAAK,CAAC;;;;;AAMrD,SAAgB,qBAAqB;AACnC,SAAQ,kBAAkB,IAAI,eAAe,KAAK,EAAE;;;;;AAiBtD,SAAgB,iBAAkC;AAChD,SAAQ,kBAAkB,IAAI,eAAe,KAAK,EAAE;;;;;AAMtD,SAAgB,kBAA2B;AAEzC,QADY,wBAAwB,UAAU,KAC/B;;;;;;;AAQjB,SAAgB,mBAA8C;AAC5D,QAAO,wBAAwB,UAAU"}
@@ -1,3 +1,4 @@
1
- import { ServiceContext } from "./service-context.js";
2
1
  import { UserContext } from "./user-context.js";
3
- import { getExecutionContext } from "./execution-context.js";
2
+ import { ServiceContext } from "./service-context.js";
3
+ import { CallerContext, CallerPrincipal, ExecutionContext } from "./caller-context.js";
4
+ import { getCurrentActorId, getCurrentPrincipalKey, getExecutionContext } from "./execution-context.js";
@@ -1,4 +1,5 @@
1
+ import { isCallerContext } from "./caller-context.js";
1
2
  import { ServiceContext } from "./service-context.js";
2
- import { getCurrentUserId, getExecutionContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, runInUserContext } from "./execution-context.js";
3
+ import { getCallerContext, getCurrentActorId, getCurrentPrincipalKey, getCurrentUserId, getExecutionContext, getWorkspaceClient, getWorkspaceId, runInCallerContext } from "./execution-context.js";
3
4
 
4
5
  export { getWorkspaceClient };
@@ -1,24 +1,28 @@
1
1
  import { ClientOptions, WorkspaceClient } from "../workspace-client/index.js";
2
2
  import { UserContext } from "./user-context.js";
3
+ import { CallerContext } from "./caller-context.js";
3
4
 
4
5
  //#region src/context/service-context.d.ts
5
6
  /**
6
- * Service context holds the service principal client and shared resources.
7
+ * Service context holds the service principal identity and workspace client.
7
8
  * This is initialized once at app startup and shared across all requests.
8
9
  */
9
10
  interface ServiceContextState {
10
11
  /** WorkspaceClient authenticated as the service principal */
11
- client: WorkspaceClient;
12
+ readonly client: WorkspaceClient;
12
13
  /** The service principal's user ID */
13
- serviceUserId: string;
14
- /** Promise that resolves to the warehouse ID (only present when a plugin requires `SQL_WAREHOUSE` resource) */
15
- warehouseId?: Promise<string>;
14
+ readonly serviceUserId: string;
15
+ /**
16
+ * @deprecated Use getWarehouseId() from @databricks/appkit.
17
+ * Retained for backward compatibility.
18
+ */
19
+ readonly warehouseId?: Promise<string>;
16
20
  /** Promise that resolves to the workspace ID */
17
- workspaceId: Promise<string>;
21
+ readonly workspaceId: Promise<string>;
18
22
  }
19
23
  /**
20
24
  * ServiceContext is a singleton that manages the service principal's
21
- * WorkspaceClient and shared resources like warehouse/workspace IDs.
25
+ * WorkspaceClient and workspace ID. WarehouseResource owns warehouse bindings.
22
26
  *
23
27
  * It's initialized once at app startup and provides the foundation
24
28
  * for both service principal and user context execution.
@@ -30,12 +34,12 @@ declare class ServiceContext {
30
34
  * Initialize the service context. Should be called once at app startup.
31
35
  * Safe to call multiple times - will return the same instance.
32
36
  *
33
- * @param options - Which shared resources to resolve (derived from plugin manifests).
37
+ * @param options - A resolved warehouse ID, or a boolean enabling discovery.
34
38
  * @param client - Optional pre-configured WorkspaceClient to use instead
35
39
  * of creating one from environment credentials.
36
40
  */
37
41
  static initialize(options?: {
38
- warehouseId?: boolean;
42
+ warehouseId?: boolean | string;
39
43
  }, client?: WorkspaceClient): Promise<ServiceContextState>;
40
44
  /**
41
45
  * Get the initialized service context.
@@ -47,14 +51,17 @@ declare class ServiceContext {
47
51
  */
48
52
  static isInitialized(): boolean;
49
53
  /**
50
- * Create a user context from request headers.
54
+ * Create an immutable caller context from the existing user request headers.
51
55
  *
52
56
  * @param token - The user's access token from x-forwarded-access-token header
53
57
  * @param userId - The user's ID from x-forwarded-user header
54
58
  * @param userName - Optional user name
59
+ * @param userEmail - Optional email from x-forwarded-email
55
60
  * @throws Error if token is not provided
56
61
  */
57
- static createUserContext(token: string, userId: string, userName?: string, userEmail?: string): UserContext;
62
+ static createCallerContext(token: string, userId: string, userName?: string, userEmail?: string): CallerContext;
63
+ /** @deprecated Use ServiceContext.createCallerContext. */
64
+ static createUserContext(token: string, userId: string, userName?: string, userEmail?: string): CallerContext & UserContext;
58
65
  /**
59
66
  * Get the client options for WorkspaceClient.
60
67
  * Exposed for testing purposes.
@@ -62,7 +69,6 @@ declare class ServiceContext {
62
69
  static getClientOptions(): ClientOptions;
63
70
  private static createContext;
64
71
  private static getWorkspaceId;
65
- private static getWarehouseId;
66
72
  /**
67
73
  * Reset the service context. Only for testing purposes.
68
74
  */
@@ -1 +1 @@
1
- {"version":3,"file":"service-context.d.ts","names":[],"sources":["../../src/context/service-context.ts"],"mappings":";;;;;;AAqBA;;UAAiB,mBAAA;EAEP;EAAR,MAAA,EAAQ,eAAA;EAMK;EAJb,aAAA;EAIoB;EAFpB,WAAA,GAAc,OAAA;EAJN;EAMR,WAAA,EAAa,OAAA;AAAA;;;;;;AAUf;;cAAa,cAAA;EAAA,eACI,QAAA;EAAA,eACA,WAAA;EAaZ;;;;;;;;EAAA,OAHU,UAAA,CACX,OAAA;IAAY,WAAA;EAAA,GACZ,MAAA,GAAS,eAAA,GACR,OAAA,CAAQ,mBAAA;EADA;;;;EAAA,OAmBJ,GAAA,CAAA,GAAO,mBAAA;EAAA;;;EAAA,OAaP,aAAA,CAAA;EAcL;;;;;;;;EAAA,OAFK,iBAAA,CACL,KAAA,UACA,MAAA,UACA,QAAA,WACA,SAAA,YACC,WAAA;EAqLI;;;;EAAA,OA1IA,gBAAA,CAAA,GAAoB,aAAA;EAAA,eAIN,aAAA;EAAA,eA2CA,cAAA;EAAA,eAuBA,cAAA;;;;SAoEd,KAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"service-context.d.ts","names":[],"sources":["../../src/context/service-context.ts"],"mappings":";;;;;;;AAuBA;;UAAiB,mBAAA;EAEE;EAAA,SAAR,MAAA,EAAQ,eAAA;EASK;EAAA,SAPb,aAAA;EAOoB;;;;EAAA,SAFpB,WAAA,GAAc,OAAA;EAAA;EAAA,SAEd,WAAA,EAAa,OAAA;AAAA;;;AAUxB;;;;;cAAa,cAAA;EAAA,eACI,QAAA;EAAA,eACA,WAAA;EAuGZ;;;;;;;;EAAA,OA7FU,UAAA,CACX,OAAA;IAAY,WAAA;EAAA,GACZ,MAAA,GAAS,eAAA,GACR,OAAA,CAAQ,mBAAA;EADT;;;;EAAA,OAmBK,GAAA,CAAA,GAAO,mBAAA;EAaP;;;EAAA,OAAA,aAAA,CAAA;EAgBL;;;;;;;;;EAAA,OAHK,mBAAA,CACL,KAAA,UACA,MAAA,UACA,QAAA,WACA,SAAA,YACC,aAAA;EA4DI;EAAA,OAxBA,iBAAA,CACL,KAAA,UACA,MAAA,UACA,QAAA,WACA,SAAA,YACC,aAAA,GAAgB,WAAA;EAuBE;;;;EAAA,OAJd,gBAAA,CAAA,GAAoB,aAAA;EAAA,eAIN,aAAA;EAAA,eA4CA,cAAA;;;;SA0Bd,KAAA,CAAA;AAAA"}