feat(appkit): introduce workspace-client wrapper over the Databricks SDK#475
Open
MarioCadenas wants to merge 1 commit into
Open
feat(appkit): introduce workspace-client wrapper over the Databricks SDK#475MarioCadenas wants to merge 1 commit into
MarioCadenas wants to merge 1 commit into
Conversation
MarioCadenas
marked this pull request as draft
July 10, 2026 14:38
MarioCadenas
force-pushed
the
feat/workspace-client-wrapper
branch
from
July 23, 2026 14:23
01e0549 to
395c4a2
Compare
Contributor
📦 Bundle size reportCompared against
|
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 788 KB (+4.2 KB) | 275 KB (+1.6 KB) |
| Type declarations | 289 KB (+4.4 KB) | 99 KB (+2.0 KB) |
| Source maps | 1.5 MB (+8.5 KB) | 513 KB (+3.5 KB) |
| Other | 11 KB | 3.7 KB |
| Total | 2.6 MB (+17 KB) | 890 KB (+7.1 KB) |
Per-entry composition (own code — deps external (as shipped))
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
. |
85 KB (+69 B) | 2.5 KB | 88 KB (+69 B) | external | 279 KB (+114 B) |
./beta |
40 KB (+300 B) | 231 B | 40 KB (+300 B) | external | 120 KB (+682 B) |
./type-generator |
19 KB (+226 B) | 0 B | 19 KB (+226 B) | external | 54 KB (+645 B) |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
. |
index.js |
initial | 81 KB |
. |
utils.js |
initial | 4.0 KB |
. |
remote-tunnel-manager.js |
lazy | 2.5 KB |
./beta |
beta.js |
initial | 30 KB |
./beta |
databricks.js |
initial | 5.8 KB |
./beta |
service-context.js |
initial | 3.1 KB |
./beta |
client.js |
initial | 570 B |
./beta |
databricks.js |
lazy | 128 B |
./beta |
index.js |
lazy | 103 B |
./type-generator |
index.js |
initial | 19 KB |
@databricks/appkit-ui
npm tarball (packed): 295 KB — gzipped download (dist + bin; excludes release-only docs/NOTICE).
| dist | raw | gzip |
|---|---|---|
| JS (runtime) | 350 KB | 116 KB |
| Type declarations | 201 KB | 72 KB |
| Source maps | 669 KB | 218 KB |
| CSS | 16 KB | 3.3 KB |
| Total | 1.2 MB | 410 KB |
Per-entry composition (consumer bundle — deps bundled, peerDeps external)
| Entry | Initial (gz) | Lazy (gz) | Total (gz) | node_modules (min) | Own code (min) |
|---|---|---|---|---|---|
./js |
4.3 KB | 49 KB | 54 KB | 208 KB | 12 KB |
./js/beta |
20 B | 0 B | 20 B | 0 B | 0 B |
./react |
428 KB | 49 KB | 476 KB | 1.3 MB | 163 KB |
./react/beta |
20 B | 0 B | 20 B | 0 B | 0 B |
Chunks:
| Entry | Chunk | Load | Size (gz) |
|---|---|---|---|
./js |
index.js |
initial | 4.2 KB |
./js |
chunk |
initial | 120 B |
./js |
apache-arrow |
lazy | 49 KB |
./js/beta |
beta.js |
initial | 20 B |
./react |
index.js |
initial | 426 KB |
./react |
tslib |
initial | 2.1 KB |
./react |
apache-arrow |
lazy | 49 KB |
./react/beta |
beta.js |
initial | 20 B |
MarioCadenas
force-pushed
the
feat/workspace-client-wrapper
branch
from
July 23, 2026 15:48
395c4a2 to
f45fda6
Compare
Add packages/appkit/src/workspace-client/ — a facade over the legacy
@databricks/sdk-experimental client that mirrors the modular Databricks
SDK's multi-client shape. This prepares the library for an incremental,
per-service migration to the modular SDK without migrating anything yet.
- legacy.ts is the ONLY module importing @databricks/sdk-experimental;
it constructs the client and re-exports the SDK symbols AppKit uses.
- The WorkspaceClient facade exposes per-service accessors (files,
warehouses, genie, jobs, statementExecution, servingEndpoints,
currentUser, config, apiClient), each legacy-typed and delegating to
the underlying client. Migrating a service later is a localized swap:
one getter + its accessor type + one connector.
- createWorkspaceClient() replaces every `new WorkspaceClient(...)` site
(runtime + build-time type-generator); toLegacyWorkspaceClient() is the
escape hatch for @databricks/lakebase.
- createApp({ client }) and the public index now expose the wrapper type
instead of the raw SDK client.
- A Biome noRestrictedImports boundary rule forbids importing
@databricks/sdk-experimental outside workspace-client/, keeping the seam
enforceable. Tests mock the wrapper rather than the SDK.
Time is sourced off the SDK namespace (SDK.Time ?? SDK.default.Time)
because the SDK's CommonJS `Time` export is a getter that defeats Node's
static ESM named-export detection — a direct `export { Time }` throws at
link time.
Signed-off-by: MarioCadenas <MarioCadenas@users.noreply.github.com>
MarioCadenas
force-pushed
the
feat/workspace-client-wrapper
branch
from
July 23, 2026 16:02
f45fda6 to
9e0715b
Compare
MarioCadenas
marked this pull request as ready for review
July 23, 2026 16:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Introduces
packages/appkit/src/workspace-client/— a facade over the legacy@databricks/sdk-experimentalclient that mirrors the modular Databricks SDK's multi-client shape. This prepares the library for an incremental, per-service migration to the modular SDK. Nothing is migrated yet — every service still delegates to the legacy client.Supersedes the exploration in #414, which actually migrated services (files/warehouses/vectorSearch), added upstream patches, and introduced dual-error handling. This PR does only the seam.
Why introduce a wrapper that changes nothing?
Fair question — on its own this PR adds indirection that delegates every call straight back to the same SDK. The value is entirely in what it unblocks.
AppKit is on
@databricks/sdk-experimental(one monolithicWorkspaceClient). The supported SDK isdatabricks/sdk-js— a modular architecture: a@databricks/sdk-core+-auth+-optionsfoundation plus one@databricks/sdk-<service>package per API, each constructed likenew FilesClient({ host, credentials }). We want to move onto it, but a big-bang migration is risky (that's what #414 was, and it was too large to land safely).So the plan is migrate one service at a time, each in its own PR, with the app fully working after every step. This wrapper is the seam that makes that possible:
wrapper.files,wrapper.genie, …), and a Biome boundary rule guarantees nothing else in appkit imports the SDK directly. So migrating a service is a localized change — one getter inclient.ts, one accessor type, one connector — with a provably bounded blast radius.toLegacyWorkspaceClient()is the deliberate escape hatch for code still on the old SDK (notably@databricks/lakebase), so the seam can be complete even while the migration is partial.That's why the boundary rule and escape hatch exist — they're the mechanism for a safe, incremental migration, not speculative abstraction.
Where this goes (for context, not in this PR)
Coverage was verified 2026-07-23: every service appkit uses now has a published modular package (
sdk-files,sdk-warehouses,sdk-vectorsearch,sdk-statementexecution,sdk-scimfor currentUser,sdk-modelservingfor serving,sdk-genie,sdk-jobs), so full migration and eventual removal ofsdk-experimentalis a reachable end state. Rough sequence: clean services first (files/warehouses/vectorSearch, PoC-proven), then statementExecution + the raw-apiClient.requestsites →sdk-core/http, then the divergent ones last (genie/jobs need a connector rewrite for the waiter idiom + camelCase fields). The honest caveat: the wrapper makes the wiring trivial but does not shrink the per-connector rewrite — that's real, case-by-case work per service.Full plan lives in the AppKit roadmap under Pillar 4 → "SDK migration".
Design
legacy.tsis the only module that imports@databricks/sdk-experimental. It constructs the client and re-exports the SDK symbols AppKit uses (Context,ConfigError,Time,TimeUnits, type namespacesfiles/jobs/serving/sql, etc.).WorkspaceClientfacade exposes per-service accessors (files,warehouses,genie,jobs,statementExecution,servingEndpoints,currentUser,config,apiClient), each legacy-typed and delegating to the underlying client. Migrating a service later is a localized swap: one getter + its accessor type + one connector — the rest of the codebase never touches the SDK.createWorkspaceClient()replaces everynew WorkspaceClient(...)site (runtime + build-time type-generator).toLegacyWorkspaceClient()is the escape hatch for@databricks/lakebase, which is still on the old SDK.createApp({ client })and the public package index now expose the wrapper type instead of the raw SDK client. (Breaking at the type level for anyone passing a raw SDK client tocreateApp— no known external users.)noRestrictedImportsboundary rule forbids importing@databricks/sdk-experimentaloutsideworkspace-client/, so the seam stays enforceable. Tests mock the wrapper rather than the SDK.Note on
TimeTimeis sourced off the SDK namespace (SDK.Time ?? SDK.default.Time) rather than a staticexport { Time }. The SDK's CommonJSTimeexport is emitted as a getter calling__importDefault(...), which defeats Node's static ESM named-export detection — a direct re-export throws "does not provide an export named 'Time'" at link time. This mirrors the guard the genie connector already used.Verification
pnpm build— clean, publint OKpnpm -r typecheck— 0 errors, all packages@databricks/sdk-experimentalimported only inworkspace-client/pnpm check— 0 errors, 63 warnings (identical tomainbaseline)Timefix end-to-end