@databricks/sdk-auth 0.0.0-dev → 0.1.0-dev.2
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/LICENSE +203 -0
- package/README.md +11 -1
- package/dist/auth.d.ts +81 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +47 -0
- package/dist/auth.js.map +1 -0
- package/dist/credentials/default/chain.d.ts +28 -0
- package/dist/credentials/default/chain.d.ts.map +1 -0
- package/dist/credentials/default/chain.js +62 -0
- package/dist/credentials/default/chain.js.map +1 -0
- package/dist/credentials/default/default-credentials.d.ts +25 -0
- package/dist/credentials/default/default-credentials.d.ts.map +1 -0
- package/dist/credentials/default/default-credentials.js +23 -0
- package/dist/credentials/default/default-credentials.js.map +1 -0
- package/dist/credentials/default/errors.d.ts +13 -0
- package/dist/credentials/default/errors.d.ts.map +1 -0
- package/dist/credentials/default/errors.js +15 -0
- package/dist/credentials/default/errors.js.map +1 -0
- package/dist/credentials/default/u2m-strategy.d.ts +9 -0
- package/dist/credentials/default/u2m-strategy.d.ts.map +1 -0
- package/dist/credentials/default/u2m-strategy.js +20 -0
- package/dist/credentials/default/u2m-strategy.js.map +1 -0
- package/dist/credentials/errors.d.ts +28 -0
- package/dist/credentials/errors.d.ts.map +1 -0
- package/dist/credentials/errors.js +32 -0
- package/dist/credentials/errors.js.map +1 -0
- package/dist/credentials/host-metadata.d.ts +45 -0
- package/dist/credentials/host-metadata.d.ts.map +1 -0
- package/dist/credentials/host-metadata.js +122 -0
- package/dist/credentials/host-metadata.js.map +1 -0
- package/dist/credentials/index.browser.d.ts +11 -0
- package/dist/credentials/index.browser.d.ts.map +1 -0
- package/dist/credentials/index.browser.js +9 -0
- package/dist/credentials/index.browser.js.map +1 -0
- package/dist/credentials/index.d.ts +14 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +10 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/credentials/m2m.d.ts +40 -0
- package/dist/credentials/m2m.d.ts.map +1 -0
- package/dist/credentials/m2m.js +91 -0
- package/dist/credentials/m2m.js.map +1 -0
- package/dist/credentials/pat.d.ts +14 -0
- package/dist/credentials/pat.d.ts.map +1 -0
- package/dist/credentials/pat.js +41 -0
- package/dist/credentials/pat.js.map +1 -0
- package/dist/credentials/u2m.d.ts +31 -0
- package/dist/credentials/u2m.d.ts.map +1 -0
- package/dist/credentials/u2m.js +157 -0
- package/dist/credentials/u2m.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/oidc/env.d.ts +10 -0
- package/dist/oidc/env.d.ts.map +1 -0
- package/dist/oidc/env.js +19 -0
- package/dist/oidc/env.js.map +1 -0
- package/dist/oidc/file.d.ts +7 -0
- package/dist/oidc/file.d.ts.map +1 -0
- package/dist/oidc/file.js +28 -0
- package/dist/oidc/file.js.map +1 -0
- package/dist/oidc/index.browser.d.ts +13 -0
- package/dist/oidc/index.browser.d.ts.map +1 -0
- package/dist/oidc/index.browser.js +11 -0
- package/dist/oidc/index.browser.js.map +1 -0
- package/dist/oidc/index.d.ts +14 -0
- package/dist/oidc/index.d.ts.map +1 -0
- package/dist/oidc/index.js +12 -0
- package/dist/oidc/index.js.map +1 -0
- package/dist/oidc/oidc.d.ts +21 -0
- package/dist/oidc/oidc.d.ts.map +1 -0
- package/dist/oidc/oidc.js +10 -0
- package/dist/oidc/oidc.js.map +1 -0
- package/dist/oidc/tokensource.d.ts +56 -0
- package/dist/oidc/tokensource.d.ts.map +1 -0
- package/dist/oidc/tokensource.js +62 -0
- package/dist/oidc/tokensource.js.map +1 -0
- package/package.json +52 -4
- package/src/auth.ts +117 -0
- package/src/credentials/default/chain.ts +75 -0
- package/src/credentials/default/default-credentials.ts +40 -0
- package/src/credentials/default/errors.ts +18 -0
- package/src/credentials/default/u2m-strategy.ts +20 -0
- package/src/credentials/errors.ts +51 -0
- package/src/credentials/host-metadata.ts +166 -0
- package/src/credentials/index.browser.ts +11 -0
- package/src/credentials/index.ts +14 -0
- package/src/credentials/m2m.ts +156 -0
- package/src/credentials/pat.ts +44 -0
- package/src/credentials/u2m.ts +212 -0
- package/src/index.ts +19 -0
- package/src/oidc/env.ts +21 -0
- package/src/oidc/file.ts +29 -0
- package/src/oidc/index.browser.ts +16 -0
- package/src/oidc/index.ts +17 -0
- package/src/oidc/oidc.ts +26 -0
- package/src/oidc/tokensource.ts +133 -0
- package/index.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/credentials/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH;;;;GAIG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,CAA0B;IAEvC,YAAY,IAA6B,EAAE,OAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAUD;;;;GAIG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,CAA0B;IAEvC,YAAY,IAA6B,EAAE,OAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HostMetadata holds the parsed response from the
|
|
3
|
+
* /.well-known/databricks-config discovery endpoint.
|
|
4
|
+
*/
|
|
5
|
+
export interface HostMetadata {
|
|
6
|
+
/**
|
|
7
|
+
* oidcEndpoint is the OIDC discovery URL for this host. For account hosts,
|
|
8
|
+
* this may contain an {account_id} placeholder that callers must
|
|
9
|
+
* substitute.
|
|
10
|
+
*/
|
|
11
|
+
oidcEndpoint: string;
|
|
12
|
+
/**
|
|
13
|
+
* accountId is the Databricks account ID associated with this host, if
|
|
14
|
+
* available.
|
|
15
|
+
*/
|
|
16
|
+
accountId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* workspaceId is the Databricks workspace ID associated with this host, if
|
|
19
|
+
* available.
|
|
20
|
+
*/
|
|
21
|
+
workspaceId?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* getHostMetadata fetches the raw Databricks well-known configuration from
|
|
25
|
+
* {host}/.well-known/databricks-config. The returned HostMetadata contains
|
|
26
|
+
* raw values with no substitution (e.g., {account_id} placeholders are left
|
|
27
|
+
* as-is). Callers are responsible for interpreting the result.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getHostMetadata(host: string): Promise<HostMetadata>;
|
|
30
|
+
/**
|
|
31
|
+
* resolveTokenEndpoint resolves the OAuth `token_endpoint` for the given
|
|
32
|
+
* Databricks host via a two-step discovery:
|
|
33
|
+
*
|
|
34
|
+
* 1. `GET {host}/.well-known/databricks-config` to obtain the OIDC root.
|
|
35
|
+
* 2. `GET {oidcRoot}/.well-known/oauth-authorization-server` to obtain the
|
|
36
|
+
* RFC 8414 authorization server metadata.
|
|
37
|
+
*
|
|
38
|
+
* If the OIDC root contains an `{account_id}` placeholder, it is substituted
|
|
39
|
+
* with the first defined value from: `configAccountId` (caller-supplied),
|
|
40
|
+
* then the `account_id` field returned by the host metadata response.
|
|
41
|
+
* Throws when any step fails, required fields are missing, or the placeholder
|
|
42
|
+
* cannot be resolved.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveTokenEndpoint(host: string, configAccountId?: string): Promise<string>;
|
|
45
|
+
//# sourceMappingURL=host-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-metadata.d.ts","sourceRoot":"","sources":["../../src/credentials/host-metadata.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCzE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,CAAC,CA+CjB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* getHostMetadata fetches the raw Databricks well-known configuration from
|
|
4
|
+
* {host}/.well-known/databricks-config. The returned HostMetadata contains
|
|
5
|
+
* raw values with no substitution (e.g., {account_id} placeholders are left
|
|
6
|
+
* as-is). Callers are responsible for interpreting the result.
|
|
7
|
+
*/
|
|
8
|
+
export async function getHostMetadata(host) {
|
|
9
|
+
const url = `${trimTrailingSlash(host)}/.well-known/databricks-config`;
|
|
10
|
+
let response;
|
|
11
|
+
try {
|
|
12
|
+
response = await fetch(url);
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
throw new Error(`fetching host metadata from ${url} failed: ${stringifyError(e)}`);
|
|
16
|
+
}
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
const text = await safeReadText(response);
|
|
19
|
+
throw new Error(`fetching host metadata from ${url} failed with status ` +
|
|
20
|
+
`${response.status.toString()}: ${text}`);
|
|
21
|
+
}
|
|
22
|
+
let raw;
|
|
23
|
+
try {
|
|
24
|
+
raw = await response.json();
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
throw new Error(`parsing host metadata from ${url} failed: ${stringifyError(e)}`);
|
|
28
|
+
}
|
|
29
|
+
const parsed = hostMetadataSchema.parse(raw);
|
|
30
|
+
return {
|
|
31
|
+
oidcEndpoint: parsed.oidc_endpoint,
|
|
32
|
+
...(parsed.account_id !== undefined && { accountId: parsed.account_id }),
|
|
33
|
+
...(parsed.workspace_id !== undefined && {
|
|
34
|
+
workspaceId: parsed.workspace_id,
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* resolveTokenEndpoint resolves the OAuth `token_endpoint` for the given
|
|
40
|
+
* Databricks host via a two-step discovery:
|
|
41
|
+
*
|
|
42
|
+
* 1. `GET {host}/.well-known/databricks-config` to obtain the OIDC root.
|
|
43
|
+
* 2. `GET {oidcRoot}/.well-known/oauth-authorization-server` to obtain the
|
|
44
|
+
* RFC 8414 authorization server metadata.
|
|
45
|
+
*
|
|
46
|
+
* If the OIDC root contains an `{account_id}` placeholder, it is substituted
|
|
47
|
+
* with the first defined value from: `configAccountId` (caller-supplied),
|
|
48
|
+
* then the `account_id` field returned by the host metadata response.
|
|
49
|
+
* Throws when any step fails, required fields are missing, or the placeholder
|
|
50
|
+
* cannot be resolved.
|
|
51
|
+
*/
|
|
52
|
+
export async function resolveTokenEndpoint(host, configAccountId) {
|
|
53
|
+
const meta = await getHostMetadata(host);
|
|
54
|
+
// Precedence mirrors the legacy SDK: a caller-supplied account ID
|
|
55
|
+
// overrides any value returned by the host metadata. The metadata
|
|
56
|
+
// back-fills only when the caller did not provide one.
|
|
57
|
+
const accountId = configAccountId !== undefined && configAccountId !== ''
|
|
58
|
+
? configAccountId
|
|
59
|
+
: meta.accountId;
|
|
60
|
+
let oidcRoot = meta.oidcEndpoint;
|
|
61
|
+
if (oidcRoot.includes('{account_id}')) {
|
|
62
|
+
if (accountId === undefined || accountId === '') {
|
|
63
|
+
throw new Error('host metadata oidc_endpoint contains {account_id} placeholder but ' +
|
|
64
|
+
'no account_id was provided or returned by the metadata response');
|
|
65
|
+
}
|
|
66
|
+
oidcRoot = oidcRoot.replaceAll('{account_id}', accountId);
|
|
67
|
+
}
|
|
68
|
+
const discoveryUrl = `${trimTrailingSlash(oidcRoot)}/.well-known/oauth-authorization-server`;
|
|
69
|
+
let response;
|
|
70
|
+
try {
|
|
71
|
+
response = await fetch(discoveryUrl);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
throw new Error(`fetching oauth authorization server metadata from ${discoveryUrl} ` +
|
|
75
|
+
`failed: ${stringifyError(e)}`);
|
|
76
|
+
}
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
const text = await safeReadText(response);
|
|
79
|
+
throw new Error(`fetching oauth authorization server metadata from ${discoveryUrl} ` +
|
|
80
|
+
`failed with status ${response.status.toString()}: ${text}`);
|
|
81
|
+
}
|
|
82
|
+
let raw;
|
|
83
|
+
try {
|
|
84
|
+
raw = await response.json();
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
throw new Error(`parsing oauth authorization server metadata from ${discoveryUrl} ` +
|
|
88
|
+
`failed: ${stringifyError(e)}`);
|
|
89
|
+
}
|
|
90
|
+
const parsed = oauthServerSchema.parse(raw);
|
|
91
|
+
return parsed.token_endpoint;
|
|
92
|
+
}
|
|
93
|
+
const hostMetadataSchema = z.object({
|
|
94
|
+
oidc_endpoint: z.string(),
|
|
95
|
+
account_id: z.string().optional(),
|
|
96
|
+
workspace_id: z.string().optional(),
|
|
97
|
+
});
|
|
98
|
+
const oauthServerSchema = z.object({
|
|
99
|
+
token_endpoint: z.string(),
|
|
100
|
+
});
|
|
101
|
+
function trimTrailingSlash(s) {
|
|
102
|
+
let end = s.length;
|
|
103
|
+
while (end > 0 && s.charAt(end - 1) === '/') {
|
|
104
|
+
end--;
|
|
105
|
+
}
|
|
106
|
+
return s.slice(0, end);
|
|
107
|
+
}
|
|
108
|
+
async function safeReadText(response) {
|
|
109
|
+
try {
|
|
110
|
+
return await response.text();
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return '';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function stringifyError(e) {
|
|
117
|
+
if (e instanceof Error) {
|
|
118
|
+
return e.message;
|
|
119
|
+
}
|
|
120
|
+
return String(e);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=host-metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-metadata.js","sourceRoot":"","sources":["../../src/credentials/host-metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser entry point for credential implementations. Excludes credentials
|
|
3
|
+
* that depend on Node.js-only APIs (e.g. `databricks-cli` auth which spawns
|
|
4
|
+
* the CLI binary).
|
|
5
|
+
*/
|
|
6
|
+
export { M2mCredentialsError } from './errors';
|
|
7
|
+
export type { M2mCredentialsErrorCode } from './errors';
|
|
8
|
+
export { newM2mCredentials } from './m2m';
|
|
9
|
+
export type { M2mCredentialsOptions } from './m2m';
|
|
10
|
+
export { newPatCredentials } from './pat';
|
|
11
|
+
//# sourceMappingURL=index.browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../../src/credentials/index.browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAC,uBAAuB,EAAC,MAAM,UAAU,CAAC;AACtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AACxC,YAAY,EAAC,qBAAqB,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser entry point for credential implementations. Excludes credentials
|
|
3
|
+
* that depend on Node.js-only APIs (e.g. `databricks-cli` auth which spawns
|
|
4
|
+
* the CLI binary).
|
|
5
|
+
*/
|
|
6
|
+
export { M2mCredentialsError } from './errors';
|
|
7
|
+
export { newM2mCredentials } from './m2m';
|
|
8
|
+
export { newPatCredentials } from './pat';
|
|
9
|
+
//# sourceMappingURL=index.browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../src/credentials/index.browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAE7C,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAExC,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential implementations for the Databricks SDK.
|
|
3
|
+
*/
|
|
4
|
+
export { M2mCredentialsError, U2mCredentialsError } from './errors';
|
|
5
|
+
export type { M2mCredentialsErrorCode, U2mCredentialsErrorCode } from './errors';
|
|
6
|
+
export { newM2mCredentials } from './m2m';
|
|
7
|
+
export type { M2mCredentialsOptions } from './m2m';
|
|
8
|
+
export { newPatCredentials } from './pat';
|
|
9
|
+
export { newU2mCredentials } from './u2m';
|
|
10
|
+
export type { U2mCredentialsOptions } from './u2m';
|
|
11
|
+
export { defaultCredentials } from './default/default-credentials';
|
|
12
|
+
export { DefaultCredentialsError } from './default/errors';
|
|
13
|
+
export type { DefaultCredentialsErrorCode } from './default/errors';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/credentials/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAC,mBAAmB,EAAE,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAClE,YAAY,EAAC,uBAAuB,EAAE,uBAAuB,EAAC,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AACxC,YAAY,EAAC,qBAAqB,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AACxC,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AACxC,YAAY,EAAC,qBAAqB,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAC,uBAAuB,EAAC,MAAM,kBAAkB,CAAC;AACzD,YAAY,EAAC,2BAA2B,EAAC,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential implementations for the Databricks SDK.
|
|
3
|
+
*/
|
|
4
|
+
export { M2mCredentialsError, U2mCredentialsError } from './errors';
|
|
5
|
+
export { newM2mCredentials } from './m2m';
|
|
6
|
+
export { newPatCredentials } from './pat';
|
|
7
|
+
export { newU2mCredentials } from './u2m';
|
|
8
|
+
export { defaultCredentials } from './default/default-credentials';
|
|
9
|
+
export { DefaultCredentialsError } from './default/errors';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/credentials/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAC,mBAAmB,EAAE,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAElE,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAExC,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AACxC,OAAO,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAExC,OAAO,EAAC,kBAAkB,EAAC,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAC,uBAAuB,EAAC,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine-to-machine (M2M) OAuth credentials for the Databricks SDK.
|
|
3
|
+
*/
|
|
4
|
+
import type { TokenCredentials } from '../auth';
|
|
5
|
+
/** Options for {@link newM2mCredentials}. */
|
|
6
|
+
export interface M2mCredentialsOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Databricks host (workspace or account) used to discover the OAuth token
|
|
9
|
+
* endpoint.
|
|
10
|
+
*/
|
|
11
|
+
host: string;
|
|
12
|
+
/**
|
|
13
|
+
* OAuth client ID issued to the service principal.
|
|
14
|
+
*/
|
|
15
|
+
clientId: string;
|
|
16
|
+
/**
|
|
17
|
+
* OAuth client secret issued to the service principal.
|
|
18
|
+
*/
|
|
19
|
+
clientSecret: string;
|
|
20
|
+
/**
|
|
21
|
+
* Databricks account ID. Required for account hosts.
|
|
22
|
+
*/
|
|
23
|
+
accountId?: string;
|
|
24
|
+
/**
|
|
25
|
+
* OAuth scopes to request. When omitted or empty, defaults to
|
|
26
|
+
* `['all-apis']`.
|
|
27
|
+
*/
|
|
28
|
+
scopes?: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a TokenCredentials that authenticates as a Databricks service
|
|
32
|
+
* principal using the OAuth client credentials grant.
|
|
33
|
+
*
|
|
34
|
+
* @param options - Host plus client credentials.
|
|
35
|
+
* @throws M2mCredentialsError when host, clientId, or clientSecret is empty,
|
|
36
|
+
* when token-endpoint discovery fails, or when the token endpoint returns
|
|
37
|
+
* an error.
|
|
38
|
+
*/
|
|
39
|
+
export declare function newM2mCredentials(options: M2mCredentialsOptions): TokenCredentials;
|
|
40
|
+
//# sourceMappingURL=m2m.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"m2m.d.ts","sourceRoot":"","sources":["../../src/credentials/m2m.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAQ,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAMrD,6CAA6C;AAC7C,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAID;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,qBAAqB,GAC7B,gBAAgB,CAuDlB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine-to-machine (M2M) OAuth credentials for the Databricks SDK.
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { newTokenCredentials, tokenProviderFn } from '../auth';
|
|
6
|
+
import { M2mCredentialsError } from './errors';
|
|
7
|
+
import { resolveTokenEndpoint } from './host-metadata';
|
|
8
|
+
const DEFAULT_SCOPES = ['all-apis'];
|
|
9
|
+
/**
|
|
10
|
+
* Creates a TokenCredentials that authenticates as a Databricks service
|
|
11
|
+
* principal using the OAuth client credentials grant.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Host plus client credentials.
|
|
14
|
+
* @throws M2mCredentialsError when host, clientId, or clientSecret is empty,
|
|
15
|
+
* when token-endpoint discovery fails, or when the token endpoint returns
|
|
16
|
+
* an error.
|
|
17
|
+
*/
|
|
18
|
+
export function newM2mCredentials(options) {
|
|
19
|
+
if (options.clientId === '') {
|
|
20
|
+
throw new M2mCredentialsError('CLIENT_ID_REQUIRED', 'clientId is required');
|
|
21
|
+
}
|
|
22
|
+
if (options.clientSecret === '') {
|
|
23
|
+
throw new M2mCredentialsError('CLIENT_SECRET_REQUIRED', 'clientSecret is required');
|
|
24
|
+
}
|
|
25
|
+
if (options.host === '') {
|
|
26
|
+
throw new M2mCredentialsError('HOST_REQUIRED', 'host is required');
|
|
27
|
+
}
|
|
28
|
+
const scopes = options.scopes !== undefined && options.scopes.length > 0
|
|
29
|
+
? options.scopes
|
|
30
|
+
: DEFAULT_SCOPES;
|
|
31
|
+
const body = new URLSearchParams({
|
|
32
|
+
grant_type: 'client_credentials',
|
|
33
|
+
scope: scopes.join(' '),
|
|
34
|
+
}).toString();
|
|
35
|
+
// Client ID and secret are URL-encoded before Basic auth encoding to
|
|
36
|
+
// avoid ambiguity with special characters in either value, matching the
|
|
37
|
+
// behavior of golang.org/x/oauth2.
|
|
38
|
+
const basicAuth = btoa(`${encodeURIComponent(options.clientId)}:${encodeURIComponent(options.clientSecret)}`);
|
|
39
|
+
let cachedTokenEndpoint;
|
|
40
|
+
const getTokenEndpoint = async () => {
|
|
41
|
+
if (cachedTokenEndpoint === undefined) {
|
|
42
|
+
try {
|
|
43
|
+
cachedTokenEndpoint = await resolveTokenEndpoint(options.host, options.accountId);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
throw new M2mCredentialsError('DISCOVERY_FAILED', `discovering token endpoint failed: ${stringifyError(e)}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return cachedTokenEndpoint;
|
|
50
|
+
};
|
|
51
|
+
const provider = tokenProviderFn(async () => {
|
|
52
|
+
const tokenEndpoint = await getTokenEndpoint();
|
|
53
|
+
return fetchAccessToken(tokenEndpoint, basicAuth, body);
|
|
54
|
+
});
|
|
55
|
+
return newTokenCredentials('oauth-m2m', provider);
|
|
56
|
+
}
|
|
57
|
+
async function fetchAccessToken(tokenEndpoint, basicAuth, body) {
|
|
58
|
+
const response = await fetch(tokenEndpoint, {
|
|
59
|
+
method: 'POST',
|
|
60
|
+
headers: {
|
|
61
|
+
Authorization: `Basic ${basicAuth}`,
|
|
62
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
63
|
+
},
|
|
64
|
+
body,
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const text = await response.text();
|
|
68
|
+
throw new M2mCredentialsError('TOKEN_REQUEST_FAILED', `token request failed with status ${response.status.toString()}: ${text}`);
|
|
69
|
+
}
|
|
70
|
+
const parsed = tokenResponseSchema.parse(await response.json());
|
|
71
|
+
const expiry = parsed.expires_in !== undefined
|
|
72
|
+
? new Date(Date.now() + parsed.expires_in * 1000)
|
|
73
|
+
: undefined;
|
|
74
|
+
return {
|
|
75
|
+
value: parsed.access_token,
|
|
76
|
+
...(parsed.token_type !== undefined && { type: parsed.token_type }),
|
|
77
|
+
...(expiry !== undefined && { expiry }),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const tokenResponseSchema = z.object({
|
|
81
|
+
access_token: z.string(),
|
|
82
|
+
token_type: z.string().optional(),
|
|
83
|
+
expires_in: z.number().optional(),
|
|
84
|
+
});
|
|
85
|
+
function stringifyError(e) {
|
|
86
|
+
if (e instanceof Error) {
|
|
87
|
+
return e.message;
|
|
88
|
+
}
|
|
89
|
+
return String(e);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=m2m.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"m2m.js","sourceRoot":"","sources":["../../src/credentials/m2m.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Personal Access Token (PAT) credentials for the Databricks SDK.
|
|
3
|
+
*/
|
|
4
|
+
import type { Credentials } from '../auth';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Credentials that can be used to authenticate with a Personal
|
|
7
|
+
* Access Token.
|
|
8
|
+
*
|
|
9
|
+
* @param token - The personal access token.
|
|
10
|
+
* @returns Credentials for PAT authentication.
|
|
11
|
+
* @throws TokenRequiredError if token is empty.
|
|
12
|
+
*/
|
|
13
|
+
export declare function newPatCredentials(token: string): Credentials;
|
|
14
|
+
//# sourceMappingURL=pat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pat.d.ts","sourceRoot":"","sources":["../../src/credentials/pat.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAS,MAAM,SAAS,CAAC;AAYjD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAK5D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Personal Access Token (PAT) credentials for the Databricks SDK.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Error thrown when a token is required but not provided.
|
|
6
|
+
*/
|
|
7
|
+
class TokenRequiredError extends Error {
|
|
8
|
+
constructor() {
|
|
9
|
+
super('token is required');
|
|
10
|
+
this.name = 'TokenRequiredError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Credentials that can be used to authenticate with a Personal
|
|
15
|
+
* Access Token.
|
|
16
|
+
*
|
|
17
|
+
* @param token - The personal access token.
|
|
18
|
+
* @returns Credentials for PAT authentication.
|
|
19
|
+
* @throws TokenRequiredError if token is empty.
|
|
20
|
+
*/
|
|
21
|
+
export function newPatCredentials(token) {
|
|
22
|
+
if (token === '') {
|
|
23
|
+
throw new TokenRequiredError();
|
|
24
|
+
}
|
|
25
|
+
return new PatCredentials(token);
|
|
26
|
+
}
|
|
27
|
+
class PatCredentials {
|
|
28
|
+
token;
|
|
29
|
+
constructor(token) {
|
|
30
|
+
this.token = token;
|
|
31
|
+
}
|
|
32
|
+
name() {
|
|
33
|
+
return 'pat';
|
|
34
|
+
}
|
|
35
|
+
authHeaders() {
|
|
36
|
+
return Promise.resolve([
|
|
37
|
+
{ key: 'Authorization', value: `Bearer ${this.token}` },
|
|
38
|
+
]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=pat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pat.js","sourceRoot":"","sources":["../../src/credentials/pat.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,kBAAmB,SAAQ,KAAK;IACpC;QACE,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,kBAAkB,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,cAAc;IACW;IAA7B,YAA6B,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAG,CAAC;IAE9C,IAAI;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,WAAW;QACT,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,EAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAC;SACtD,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databricks CLI ("U2M") credentials. Obtains access tokens by shelling out
|
|
3
|
+
* to the `databricks` CLI binary (>= 0.100.0). The CLI must have been logged
|
|
4
|
+
* in ahead of time via `databricks auth login`.
|
|
5
|
+
*
|
|
6
|
+
* Node.js only. Not exported from the browser entry point.
|
|
7
|
+
*/
|
|
8
|
+
import type { TokenCredentials } from '../auth';
|
|
9
|
+
/** Options for the Databricks CLI auth strategy. */
|
|
10
|
+
export interface U2mCredentialsOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The Databricks CLI profile name, as configured via `databricks auth
|
|
13
|
+
* login`.
|
|
14
|
+
*/
|
|
15
|
+
profile: string;
|
|
16
|
+
/**
|
|
17
|
+
* Path to the `databricks` CLI binary. If omitted, the binary is searched
|
|
18
|
+
* for in `PATH`.
|
|
19
|
+
*/
|
|
20
|
+
cliPath?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a TokenCredentials that obtains Databricks access tokens by
|
|
24
|
+
* shelling out to the Databricks CLI.
|
|
25
|
+
*
|
|
26
|
+
* @param options - CLI profile (required) and optional CLI binary path.
|
|
27
|
+
* @throws U2mCredentialsError when `profile` is empty, or when the CLI cannot
|
|
28
|
+
* be located, is out of date, or fails to return a usable token.
|
|
29
|
+
*/
|
|
30
|
+
export declare function newU2mCredentials(options: U2mCredentialsOptions): TokenCredentials;
|
|
31
|
+
//# sourceMappingURL=u2m.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"u2m.d.ts","sourceRoot":"","sources":["../../src/credentials/u2m.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,KAAK,EAAQ,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAarD,oDAAoD;AACpD,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,qBAAqB,GAC7B,gBAAgB,CAMlB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Databricks CLI ("U2M") credentials. Obtains access tokens by shelling out
|
|
3
|
+
* to the `databricks` CLI binary (>= 0.100.0). The CLI must have been logged
|
|
4
|
+
* in ahead of time via `databricks auth login`.
|
|
5
|
+
*
|
|
6
|
+
* Node.js only. Not exported from the browser entry point.
|
|
7
|
+
*/
|
|
8
|
+
import { execFile } from 'node:child_process';
|
|
9
|
+
import { stat } from 'node:fs/promises';
|
|
10
|
+
import { join, sep } from 'node:path';
|
|
11
|
+
import { env, platform } from 'node:process';
|
|
12
|
+
import { promisify } from 'node:util';
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { newTokenCredentials, tokenProviderFn } from '../auth';
|
|
15
|
+
import { U2mCredentialsError } from './errors';
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
/**
|
|
18
|
+
* Distinguishes the modern Go-based Databricks CLI (>= 0.100.0) from the
|
|
19
|
+
* legacy Python CLI by minimum file size.
|
|
20
|
+
*/
|
|
21
|
+
const DATABRICKS_CLI_MIN_SIZE = 1024 * 1024;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a TokenCredentials that obtains Databricks access tokens by
|
|
24
|
+
* shelling out to the Databricks CLI.
|
|
25
|
+
*
|
|
26
|
+
* @param options - CLI profile (required) and optional CLI binary path.
|
|
27
|
+
* @throws U2mCredentialsError when `profile` is empty, or when the CLI cannot
|
|
28
|
+
* be located, is out of date, or fails to return a usable token.
|
|
29
|
+
*/
|
|
30
|
+
export function newU2mCredentials(options) {
|
|
31
|
+
if (options.profile === '') {
|
|
32
|
+
throw new U2mCredentialsError('PROFILE_REQUIRED', 'profile is required');
|
|
33
|
+
}
|
|
34
|
+
const provider = tokenProviderFn(() => fetchCliToken(options));
|
|
35
|
+
return newTokenCredentials('databricks-cli', provider);
|
|
36
|
+
}
|
|
37
|
+
async function fetchCliToken(options) {
|
|
38
|
+
const cliPath = await findDatabricksCli(options.cliPath);
|
|
39
|
+
return execCliCommand([
|
|
40
|
+
cliPath,
|
|
41
|
+
'auth',
|
|
42
|
+
'token',
|
|
43
|
+
'--profile',
|
|
44
|
+
options.profile,
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
const cliTokenResponseSchema = z.object({
|
|
48
|
+
access_token: z.string().min(1),
|
|
49
|
+
token_type: z.string().optional(),
|
|
50
|
+
expiry: z.string(),
|
|
51
|
+
});
|
|
52
|
+
async function execCliCommand(args) {
|
|
53
|
+
const [cliPath, ...rest] = args;
|
|
54
|
+
let stdout;
|
|
55
|
+
try {
|
|
56
|
+
const result = await execFileAsync(cliPath, rest);
|
|
57
|
+
stdout = result.stdout;
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
throw new U2mCredentialsError('TOKEN_FETCH_FAILED', `cannot get access token: ${cliErrorMessage(e)}`);
|
|
61
|
+
}
|
|
62
|
+
let raw;
|
|
63
|
+
try {
|
|
64
|
+
raw = JSON.parse(stdout);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
const cause = e instanceof Error ? e.message : String(e);
|
|
68
|
+
throw new U2mCredentialsError('INVALID_RESPONSE', `cannot parse CLI response: ${cause}`);
|
|
69
|
+
}
|
|
70
|
+
const result = cliTokenResponseSchema.safeParse(raw);
|
|
71
|
+
if (!result.success) {
|
|
72
|
+
throw new U2mCredentialsError('INVALID_RESPONSE', `invalid CLI response: ${result.error.message}`);
|
|
73
|
+
}
|
|
74
|
+
const parsed = result.data;
|
|
75
|
+
const expiry = new Date(parsed.expiry);
|
|
76
|
+
if (Number.isNaN(expiry.getTime())) {
|
|
77
|
+
throw new U2mCredentialsError('INVALID_RESPONSE', `cannot parse token expiry: ${parsed.expiry}`);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
value: parsed.access_token,
|
|
81
|
+
...(parsed.token_type !== undefined && { type: parsed.token_type }),
|
|
82
|
+
expiry,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function cliErrorMessage(e) {
|
|
86
|
+
if (typeof e === 'object' && e !== null) {
|
|
87
|
+
const err = e;
|
|
88
|
+
if (err.stderr !== undefined) {
|
|
89
|
+
return err.stderr.toString().trim();
|
|
90
|
+
}
|
|
91
|
+
return err.message;
|
|
92
|
+
}
|
|
93
|
+
return String(e);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Locates the `databricks` CLI binary, either at `cliPath` (if provided) or
|
|
97
|
+
* by searching `PATH`. Validates that the binary is the modern Go CLI and
|
|
98
|
+
* not the legacy Python one, via a minimum-size check.
|
|
99
|
+
*/
|
|
100
|
+
async function findDatabricksCli(cliPath) {
|
|
101
|
+
if (cliPath !== undefined) {
|
|
102
|
+
if (cliPath.includes(sep) || cliPath.includes('/')) {
|
|
103
|
+
return validateCliPath(cliPath);
|
|
104
|
+
}
|
|
105
|
+
return findInPath(cliPath);
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
return await findInPath('databricks');
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
if (platform === 'win32') {
|
|
112
|
+
return findInPath('databricks.exe');
|
|
113
|
+
}
|
|
114
|
+
throw e;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function findInPath(name) {
|
|
118
|
+
const pathEnv = env.PATH ?? '';
|
|
119
|
+
if (pathEnv === '') {
|
|
120
|
+
throw new U2mCredentialsError('CLI_NOT_FOUND', 'databricks CLI not found');
|
|
121
|
+
}
|
|
122
|
+
const delim = platform === 'win32' ? ';' : ':';
|
|
123
|
+
let legacyError;
|
|
124
|
+
for (const dir of pathEnv.split(delim)) {
|
|
125
|
+
if (dir === '') {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
return await validateCliPath(join(dir, name));
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
if (e instanceof U2mCredentialsError &&
|
|
133
|
+
e.code === 'LEGACY_CLI_DETECTED') {
|
|
134
|
+
legacyError = e;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
throw (legacyError ??
|
|
139
|
+
new U2mCredentialsError('CLI_NOT_FOUND', 'databricks CLI not found'));
|
|
140
|
+
}
|
|
141
|
+
async function validateCliPath(path) {
|
|
142
|
+
let info;
|
|
143
|
+
try {
|
|
144
|
+
info = await stat(path);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
throw new U2mCredentialsError('CLI_NOT_FOUND', 'databricks CLI not found');
|
|
148
|
+
}
|
|
149
|
+
if (info.isDirectory()) {
|
|
150
|
+
throw new U2mCredentialsError('CLI_NOT_FOUND', 'databricks CLI not found');
|
|
151
|
+
}
|
|
152
|
+
if (info.size < DATABRICKS_CLI_MIN_SIZE) {
|
|
153
|
+
throw new U2mCredentialsError('LEGACY_CLI_DETECTED', 'legacy databricks CLI detected; upgrade to >= 0.100.0');
|
|
154
|
+
}
|
|
155
|
+
return path;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=u2m.js.map
|