@dbx-tools/auth 0.9.32 → 0.9.36

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 (72) hide show
  1. package/README.md +49 -97
  2. package/index.ts +8 -26
  3. package/lib/index.d.ts +8 -26
  4. package/lib/index.js +6 -22
  5. package/lib/src/{databricks-cli.d.ts → _databricks-cli.d.ts} +3 -7
  6. package/lib/src/_databricks-cli.js +172 -0
  7. package/lib/src/_errors.d.ts +5 -0
  8. package/lib/src/_errors.js +10 -0
  9. package/lib/src/{lifecycle.d.ts → _lifecycle.d.ts} +5 -5
  10. package/lib/src/_lifecycle.js +214 -0
  11. package/lib/src/_logging.d.ts +1 -1
  12. package/lib/src/_logging.js +2 -2
  13. package/lib/src/{personal-access-token.d.ts → _personal-access-token.d.ts} +1 -1
  14. package/lib/src/_personal-access-token.js +30 -0
  15. package/lib/src/_profile-config.d.ts +43 -0
  16. package/lib/src/_profile-config.js +443 -0
  17. package/lib/src/{service-principal.d.ts → _service-principal.d.ts} +1 -1
  18. package/lib/src/_service-principal.js +69 -0
  19. package/lib/src/{storage.d.ts → _storage.d.ts} +2 -13
  20. package/lib/src/_storage.js +94 -0
  21. package/lib/src/_types.d.ts +40 -0
  22. package/lib/src/_types.js +2 -0
  23. package/lib/src/client.d.ts +30 -0
  24. package/lib/src/client.js +223 -0
  25. package/lib/src/config.d.ts +36 -0
  26. package/lib/src/config.js +15 -0
  27. package/lib/src/profile.d.ts +11 -0
  28. package/lib/src/profile.js +21 -0
  29. package/lib/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +34 -10
  31. package/src/{databricks-cli.ts → _databricks-cli.ts} +20 -109
  32. package/src/_errors.ts +11 -0
  33. package/src/{lifecycle.ts → _lifecycle.ts} +12 -40
  34. package/src/_logging.ts +2 -2
  35. package/src/{personal-access-token.ts → _personal-access-token.ts} +1 -1
  36. package/src/_profile-config.ts +545 -0
  37. package/src/{service-principal.ts → _service-principal.ts} +2 -2
  38. package/src/{storage.ts → _storage.ts} +2 -31
  39. package/src/_types.ts +45 -0
  40. package/src/client.ts +291 -0
  41. package/src/config.ts +44 -0
  42. package/src/profile.ts +33 -0
  43. package/lib/exports.d.ts +0 -2
  44. package/lib/exports.js +0 -3
  45. package/lib/src/_profile-core.d.ts +0 -28
  46. package/lib/src/_profile-core.js +0 -216
  47. package/lib/src/_profile.d.ts +0 -15
  48. package/lib/src/_profile.js +0 -236
  49. package/lib/src/databricks-auth.d.ts +0 -11
  50. package/lib/src/databricks-auth.js +0 -314
  51. package/lib/src/databricks-cli.js +0 -239
  52. package/lib/src/errors.d.ts +0 -7
  53. package/lib/src/errors.js +0 -14
  54. package/lib/src/file-storage.d.ts +0 -20
  55. package/lib/src/file-storage.js +0 -207
  56. package/lib/src/generated/databricks-cli-assets.json +0 -33
  57. package/lib/src/http-client.d.ts +0 -23
  58. package/lib/src/http-client.js +0 -116
  59. package/lib/src/lifecycle.js +0 -233
  60. package/lib/src/personal-access-token.js +0 -30
  61. package/lib/src/service-principal.js +0 -69
  62. package/lib/src/storage.js +0 -112
  63. package/lib/src/types.d.ts +0 -165
  64. package/lib/src/types.js +0 -67
  65. package/src/_profile-core.ts +0 -258
  66. package/src/_profile.ts +0 -319
  67. package/src/databricks-auth.ts +0 -416
  68. package/src/errors.ts +0 -16
  69. package/src/file-storage.ts +0 -230
  70. package/src/generated/databricks-cli-assets.json +0 -33
  71. package/src/http-client.ts +0 -147
  72. package/src/types.ts +0 -196
@@ -1,147 +0,0 @@
1
- import { authLogger } from "./_logging.ts";
2
- import { AuthError } from "./errors.ts";
3
- import { createAuthClient, type DatabricksAuthDependencies } from "./databricks-auth.ts";
4
- import type { AuthClient, DatabricksAuthOptions } from "./types.ts";
5
- import { DEFAULT_ACCESS_TOKEN_HEADER, WORKSPACE_ID_HEADER } from "./types.ts";
6
-
7
- const logger = authLogger("http");
8
-
9
- /** Options for one Databricks JSON API request. */
10
- export interface DatabricksRequestOptions {
11
- method?: string;
12
- body?: unknown;
13
- headers?: Headers | Record<string, string> | [string, string][];
14
- login?: boolean;
15
- signal?: AbortSignal;
16
- }
17
-
18
- /** Dependency-light Databricks JSON client with one rejected-token refresh. */
19
- export class DatabricksClient {
20
- private constructor(
21
- readonly auth: AuthClient,
22
- private readonly fetcher: typeof globalThis.fetch,
23
- ) {}
24
-
25
- static async create(
26
- options: DatabricksAuthOptions = { preferUserToMachine: true },
27
- dependencies: DatabricksAuthDependencies = {},
28
- ): Promise<DatabricksClient> {
29
- const client = new DatabricksClient(
30
- await createAuthClient(options, undefined, dependencies),
31
- dependencies.fetch ?? globalThis.fetch,
32
- );
33
- logger.debug("created Databricks HTTP client", {
34
- profile: client.profile(),
35
- host: client.host(),
36
- hasWorkspaceId: Boolean(client.workspaceId()),
37
- });
38
- return client;
39
- }
40
-
41
- profile(): string {
42
- return this.auth.status().profile;
43
- }
44
-
45
- host(): string {
46
- return this.auth.status().host;
47
- }
48
-
49
- principal(): string {
50
- return this.auth.principal();
51
- }
52
-
53
- workspaceId(): string | undefined {
54
- return this.auth.workspaceId();
55
- }
56
-
57
- async request(path: string, options: DatabricksRequestOptions = {}): Promise<unknown> {
58
- const url = new URL(path, `${this.host().replace(/\/$/, "")}/`).toString();
59
- const method = options.method ?? (options.body === undefined ? "GET" : "POST");
60
- const requestUrl = new URL(url);
61
- logger.debug("sending Databricks API request", {
62
- method,
63
- origin: requestUrl.origin,
64
- path: requestUrl.pathname,
65
- hasBody: options.body !== undefined,
66
- login: options.login ?? "auto",
67
- });
68
- let authHeaders = await this.auth.authenticate(options.login);
69
- let response = await this.send(url, method, authHeaders, options);
70
- logger.debug("received Databricks API response", {
71
- method,
72
- path: requestUrl.pathname,
73
- status: response.status,
74
- attempt: 1,
75
- });
76
- if (response.status === 401) {
77
- logger.debug("refreshing rejected Databricks API credential", {
78
- method,
79
- path: requestUrl.pathname,
80
- });
81
- await this.auth.refreshRejectedToken(
82
- accessTokenFromHeaders(authHeaders),
83
- options.login ?? true,
84
- );
85
- authHeaders = await this.auth.authenticate(false);
86
- response = await this.send(url, method, authHeaders, options);
87
- logger.debug("received Databricks API response", {
88
- method,
89
- path: requestUrl.pathname,
90
- status: response.status,
91
- attempt: 2,
92
- });
93
- }
94
- const text = await response.text();
95
- if (!response.ok)
96
- throw new AuthError(
97
- "http",
98
- `Databricks API ${path} returned HTTP ${response.status}: ${text}`,
99
- );
100
- if (!text) {
101
- logger.debug("Databricks API response had no body", {
102
- method,
103
- path: requestUrl.pathname,
104
- });
105
- return undefined;
106
- }
107
- try {
108
- const value = JSON.parse(text);
109
- logger.debug("parsed Databricks API JSON response", {
110
- method,
111
- path: requestUrl.pathname,
112
- });
113
- return value;
114
- } catch (cause) {
115
- throw new AuthError("http", `Databricks API ${path} did not return JSON`, { cause });
116
- }
117
- }
118
-
119
- private send(
120
- url: string,
121
- method: string,
122
- authHeaders: Record<string, string>,
123
- options: DatabricksRequestOptions,
124
- ): Promise<Response> {
125
- const headers = new Headers(options.headers);
126
- headers.delete(DEFAULT_ACCESS_TOKEN_HEADER);
127
- headers.delete(WORKSPACE_ID_HEADER);
128
- for (const [name, value] of Object.entries(authHeaders)) headers.set(name, value);
129
- headers.set("accept", "application/json");
130
- if (options.body !== undefined) headers.set("content-type", "application/json");
131
- return this.fetcher(url, {
132
- method,
133
- headers,
134
- ...(options.body !== undefined ? { body: JSON.stringify(options.body) } : {}),
135
- signal: options.signal,
136
- });
137
- }
138
- }
139
-
140
- function accessTokenFromHeaders(headers: Record<string, string>): string {
141
- const authorization = headers[DEFAULT_ACCESS_TOKEN_HEADER];
142
- const separator = authorization?.indexOf(" ") ?? -1;
143
- if (separator < 1 || !authorization?.slice(separator + 1).trim()) {
144
- throw new AuthError("http", "Authentication headers did not contain an access token");
145
- }
146
- return authorization.slice(separator + 1).trim();
147
- }
package/src/types.ts DELETED
@@ -1,196 +0,0 @@
1
- /** Authentication strategy selected from Databricks configuration. */
2
- export enum AuthKind {
3
- UserToMachine = "user-to-machine",
4
- MachineToMachine = "machine-to-machine",
5
- PersonalAccessToken = "personal-access-token",
6
- AppServicePrincipal = "app-service-principal",
7
- AppOnBehalfOf = "app-on-behalf-of",
8
- }
9
-
10
- /** Scope of the Databricks authentication target. */
11
- export enum TargetKind {
12
- Workspace = "workspace",
13
- Account = "account",
14
- Unified = "unified",
15
- }
16
-
17
- /** Built-in credential storage backend. */
18
- export enum Storage {
19
- Auto = "auto",
20
- Memory = "memory",
21
- File = "file",
22
- }
23
-
24
- /** File organization used by a persistent credential store. */
25
- export enum FileLayout {
26
- Single = "single",
27
- PerCredential = "per-credential",
28
- }
29
-
30
- /** Stored OAuth credential, including renewal metadata. */
31
- export interface Token {
32
- accessToken: string;
33
- tokenType: string;
34
- refreshToken?: string;
35
- expiry?: string;
36
- scopes: string[];
37
- }
38
-
39
- /** Public credential result; deliberately excludes the refresh token. */
40
- export interface AccessToken {
41
- accessToken: string;
42
- tokenType: string;
43
- expiry?: string;
44
- scopes: string[];
45
- }
46
-
47
- /** Shared lifecycle configuration embedded by every provider. All times in milliseconds. */
48
- export interface AuthOptions {
49
- refreshBufferMs: number;
50
- /**
51
- * Opt-in cap, in milliseconds, on waiting to acquire the per-credential
52
- * refresh lock. `0` (the default) means wait indefinitely: a holder may
53
- * legitimately run for minutes (an interactive login that opens a browser),
54
- * and the caller owns the overall request budget. Set a positive value to
55
- * fail fast instead.
56
- */
57
- lockTimeoutMs: number;
58
- loginTimeoutMs: number;
59
- }
60
-
61
- const AUTH_DEFAULTS: AuthOptions = {
62
- refreshBufferMs: 300_000,
63
- lockTimeoutMs: 0,
64
- loginTimeoutMs: 900_000,
65
- };
66
-
67
- /** Record-style factory retained for straightforward Node/Python bridging. */
68
- export const AuthOptions = {
69
- create(options: Partial<AuthOptions> = {}): AuthOptions {
70
- return { ...AUTH_DEFAULTS, ...options };
71
- },
72
- defaults(): Readonly<AuthOptions> {
73
- return Object.freeze({ ...AUTH_DEFAULTS });
74
- },
75
- };
76
-
77
- /** Secret-free metadata discovered from one Databricks CLI profile. */
78
- export interface DatabricksProfileSummary {
79
- name: string;
80
- host?: string;
81
- accountId?: string;
82
- workspaceId?: string;
83
- target: TargetKind;
84
- authKind: AuthKind;
85
- }
86
-
87
- /** Resolved Databricks identity and active storage backend. */
88
- export interface DatabricksAuthStatus {
89
- profile: string;
90
- host: string;
91
- storage: Storage;
92
- }
93
-
94
- /** Public Databricks authentication options. */
95
- export interface DatabricksAuthOptions {
96
- profile?: string;
97
- host?: string;
98
- accountId?: string;
99
- workspaceId?: string;
100
- configFile?: string;
101
- clientId?: string;
102
- clientSecret?: string;
103
- accessToken?: string;
104
- groupId?: string;
105
- authType?: string;
106
- scopes?: string[];
107
- target?: string;
108
- cacheDir?: string;
109
- auth?: AuthOptions;
110
- requestHeaders?: Record<string, string>;
111
- accessTokenHeader?: string;
112
- installCliInApp?: boolean;
113
- preferUserToMachine: boolean;
114
- }
115
-
116
- /** Record-style factory retained for callers migrating from generated bindings. */
117
- export const DatabricksAuthOptions = {
118
- create(options: Partial<DatabricksAuthOptions> = {}): DatabricksAuthOptions {
119
- return { preferUserToMachine: true, ...options };
120
- },
121
- defaults(): Readonly<DatabricksAuthOptions> {
122
- return Object.freeze({ preferUserToMachine: true });
123
- },
124
- };
125
-
126
- /** Resolved profile with secrets retained only for provider construction. */
127
- export interface DatabricksProfile extends DatabricksProfileSummary {
128
- host: string;
129
- authType?: string;
130
- clientId: string;
131
- groupId?: string;
132
- scopes: string[];
133
- clientSecret?: string;
134
- accessToken?: string;
135
- cacheKey: string;
136
- principal: string;
137
- }
138
-
139
- /** Cross-language lease adapter; implementations may use files, databases, or FFI. */
140
- export interface LockAdapter {
141
- /** Acquire the key's lease. Omit `timeoutMs` (or pass `0`) to wait indefinitely. */
142
- acquire(key: string, timeoutMs?: number): Promise<string>;
143
- release(lease: string): Promise<void>;
144
- }
145
-
146
- /** Cross-language credential persistence contract. */
147
- export interface CredentialStore {
148
- load(key: string): Promise<Token | undefined>;
149
- prepareWrite(): Promise<void>;
150
- save(key: string, token: Token): Promise<void>;
151
- remove(key: string): Promise<void>;
152
- acquireLock(key: string, timeoutMs?: number): Promise<string>;
153
- releaseLock(lease: string): Promise<void>;
154
- name(): string;
155
- }
156
-
157
- /** Provider-specific token acquisition. */
158
- export interface TokenProvider {
159
- authenticate(timeoutMs: number): Promise<Token>;
160
- login(timeoutMs: number): Promise<Token>;
161
- refresh(token: Token): Promise<Token>;
162
- canAuthenticateSilently(): boolean;
163
- }
164
-
165
- /** Stable facade shared by Node, the CLI, and generated language bindings. */
166
- export interface AuthClient {
167
- challenge(): Promise<void>;
168
- token(login?: boolean): Promise<AccessToken>;
169
- authenticate(login?: boolean): Promise<Record<string, string>>;
170
- authorizationHeaderForUrl(requestUrl: string, login?: boolean): Promise<string | undefined>;
171
- requestHeadersForUrl(requestUrl: string, login?: boolean): Promise<Record<string, string>>;
172
- forceRefreshToken(login?: boolean): Promise<AccessToken>;
173
- refreshRejectedToken(staleAccessToken: string, login?: boolean): Promise<AccessToken>;
174
- logout(): Promise<void>;
175
- status(): DatabricksAuthStatus;
176
- principal(): string;
177
- workspaceId(): string | undefined;
178
- authKind(): AuthKind;
179
- profile(name?: string): DatabricksProfileSummary;
180
- listProfiles(refresh?: boolean): DatabricksProfileSummary[];
181
- }
182
-
183
- /** Public OAuth client used by Databricks CLI-compatible user authentication. */
184
- export const DEFAULT_CLIENT_ID = "databricks-cli";
185
- /** Default Databricks profile configuration path. */
186
- export const DEFAULT_CONFIG_FILE = "~/.databrickscfg";
187
- /** Default Databricks account console origin. */
188
- export const DEFAULT_ACCOUNTS_HOST = "https://accounts.cloud.databricks.com";
189
- /** Canonical request header carrying a bearer access token. */
190
- export const DEFAULT_ACCESS_TOKEN_HEADER = "authorization";
191
- /** Canonical request header carrying the resolved Databricks workspace ID. */
192
- export const WORKSPACE_ID_HEADER = "x-databricks-workspace-id";
193
- /** Authentication type for Databricks App on-behalf-of request credentials. */
194
- export const AUTH_TYPE_APP_OBO = "app_obo";
195
- /** Authentication type for Databricks App service-principal credentials. */
196
- export const AUTH_TYPE_APP_SP = "app_sp";