@kidd-cli/core 0.2.0 → 0.4.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.
- package/README.md +2 -3
- package/dist/{config-Db_sjFU-.js → config-D8e5qxLp.js} +5 -17
- package/dist/config-D8e5qxLp.js.map +1 -0
- package/dist/{create-store-D-fQpCql.js → create-store-OHdkm_Yt.js} +3 -4
- package/dist/{create-store-D-fQpCql.js.map → create-store-OHdkm_Yt.js.map} +1 -1
- package/dist/index.d.ts +36 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +297 -73
- package/dist/index.js.map +1 -1
- package/dist/lib/config.js +3 -4
- package/dist/lib/logger.d.ts +1 -1
- package/dist/lib/logger.js +1 -2
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/project.d.ts +1 -1
- package/dist/lib/project.d.ts.map +1 -1
- package/dist/lib/project.js +2 -3
- package/dist/lib/store.d.ts +1 -1
- package/dist/lib/store.js +3 -4
- package/dist/{logger-BkQQej8h.d.ts → logger-9j49T5da.d.ts} +1 -1
- package/dist/{logger-BkQQej8h.d.ts.map → logger-9j49T5da.d.ts.map} +1 -1
- package/dist/middleware/auth.d.ts +81 -41
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +287 -233
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/http.d.ts +1 -1
- package/dist/middleware/http.js +163 -4
- package/dist/middleware/http.js.map +1 -1
- package/dist/{middleware-BFBKNSPQ.js → middleware-BWnPSRWR.js} +2 -4
- package/dist/{middleware-BFBKNSPQ.js.map → middleware-BWnPSRWR.js.map} +1 -1
- package/dist/{project-DuXgjaa_.js → project-D0g84bZY.js} +4 -8
- package/dist/project-D0g84bZY.js.map +1 -0
- package/dist/{types-C0CYivzY.d.ts → types-D-BxshYM.d.ts} +1 -1
- package/dist/{types-C0CYivzY.d.ts.map → types-D-BxshYM.d.ts.map} +1 -1
- package/dist/{types-BaZ5WqVM.d.ts → types-U73X_oQ_.d.ts} +60 -10
- package/dist/types-U73X_oQ_.d.ts.map +1 -0
- package/package.json +7 -7
- package/dist/config-Db_sjFU-.js.map +0 -1
- package/dist/create-http-client-tZJWlWp1.js +0 -165
- package/dist/create-http-client-tZJWlWp1.js.map +0 -1
- package/dist/project-DuXgjaa_.js.map +0 -1
- package/dist/types-BaZ5WqVM.d.ts.map +0 -1
package/dist/middleware/auth.js
CHANGED
|
@@ -1,40 +1,18 @@
|
|
|
1
|
-
import { n as decorateContext, t as middleware } from "../middleware-
|
|
2
|
-
import "../project-
|
|
3
|
-
import { t as createStore } from "../create-store-
|
|
4
|
-
import { t as createHttpClient } from "../create-http-client-tZJWlWp1.js";
|
|
1
|
+
import { n as decorateContext, t as middleware } from "../middleware-BWnPSRWR.js";
|
|
2
|
+
import "../project-D0g84bZY.js";
|
|
3
|
+
import { t as createStore } from "../create-store-OHdkm_Yt.js";
|
|
5
4
|
import { join } from "node:path";
|
|
6
|
-
import { ok } from "@kidd-cli/utils/fp";
|
|
5
|
+
import { attempt, attemptAsync, isPlainObject, match, ok } from "@kidd-cli/utils/fp";
|
|
6
|
+
import { z } from "zod";
|
|
7
7
|
import { match as match$1 } from "ts-pattern";
|
|
8
8
|
import { platform } from "node:os";
|
|
9
9
|
import { readFileSync } from "node:fs";
|
|
10
|
-
import { Buffer } from "node:buffer";
|
|
11
10
|
import { execFile } from "node:child_process";
|
|
12
11
|
import { createServer } from "node:http";
|
|
13
12
|
import { parse } from "dotenv";
|
|
14
13
|
import { attempt as attempt$1 } from "es-toolkit";
|
|
15
|
-
import { z } from "zod";
|
|
16
14
|
import { createHash, randomBytes } from "node:crypto";
|
|
17
|
-
|
|
18
|
-
//#region src/middleware/http/build-auth-headers.ts
|
|
19
|
-
/**
|
|
20
|
-
* Convert auth credentials into HTTP headers.
|
|
21
|
-
*
|
|
22
|
-
* Uses exhaustive pattern matching to map each credential variant to
|
|
23
|
-
* the appropriate header format.
|
|
24
|
-
*
|
|
25
|
-
* @module
|
|
26
|
-
*/
|
|
27
|
-
/**
|
|
28
|
-
* Convert an auth credential into HTTP headers.
|
|
29
|
-
*
|
|
30
|
-
* @param credential - The credential to convert.
|
|
31
|
-
* @returns A record of header name to header value.
|
|
32
|
-
*/
|
|
33
|
-
function buildAuthHeaders(credential) {
|
|
34
|
-
return match$1(credential).with({ type: "bearer" }, (c) => ({ Authorization: `Bearer ${c.token}` })).with({ type: "basic" }, (c) => ({ Authorization: `Basic ${Buffer.from(`${c.username}:${c.password}`).toString("base64")}` })).with({ type: "api-key" }, (c) => ({ [c.headerName]: c.key })).with({ type: "custom" }, (c) => ({ ...c.headers })).exhaustive();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
15
|
+
import { Buffer } from "node:buffer";
|
|
38
16
|
//#region src/middleware/auth/constants.ts
|
|
39
17
|
/**
|
|
40
18
|
* Default filename for file-based credential storage.
|
|
@@ -45,10 +23,6 @@ const DEFAULT_AUTH_FILENAME = "auth.json";
|
|
|
45
23
|
*/
|
|
46
24
|
const TOKEN_VAR_SUFFIX = "_TOKEN";
|
|
47
25
|
/**
|
|
48
|
-
* Default port for the local OAuth callback server (`0` = ephemeral).
|
|
49
|
-
*/
|
|
50
|
-
const DEFAULT_OAUTH_PORT = 0;
|
|
51
|
-
/**
|
|
52
26
|
* Default callback path for the local OAuth server.
|
|
53
27
|
*/
|
|
54
28
|
const DEFAULT_OAUTH_CALLBACK_PATH = "/callback";
|
|
@@ -76,7 +50,6 @@ const DEFAULT_DEVICE_CODE_TIMEOUT = 3e5;
|
|
|
76
50
|
function deriveTokenVar(cliName) {
|
|
77
51
|
return `${cliName.replaceAll("-", "_").toUpperCase()}${TOKEN_VAR_SUFFIX}`;
|
|
78
52
|
}
|
|
79
|
-
|
|
80
53
|
//#endregion
|
|
81
54
|
//#region src/middleware/auth/credential.ts
|
|
82
55
|
/**
|
|
@@ -119,18 +92,15 @@ function createBearerCredential(token) {
|
|
|
119
92
|
* @returns The fetch Response on success, null on failure.
|
|
120
93
|
*/
|
|
121
94
|
async function postFormEncoded(url, params, signal) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
95
|
+
const [fetchError, response] = await attemptAsync(() => fetch(url, {
|
|
96
|
+
body: params.toString(),
|
|
97
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
98
|
+
method: "POST",
|
|
99
|
+
signal
|
|
100
|
+
}));
|
|
101
|
+
if (fetchError) return null;
|
|
102
|
+
return response;
|
|
132
103
|
}
|
|
133
|
-
|
|
134
104
|
//#endregion
|
|
135
105
|
//#region src/middleware/auth/oauth-server.ts
|
|
136
106
|
/**
|
|
@@ -245,14 +215,11 @@ function sendSuccessPage(res) {
|
|
|
245
215
|
* @returns True when the URL uses HTTPS or HTTP on a loopback address.
|
|
246
216
|
*/
|
|
247
217
|
function isSecureAuthUrl(url) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
} catch {
|
|
254
|
-
return false;
|
|
255
|
-
}
|
|
218
|
+
const [error, parsed] = attempt(() => new URL(url));
|
|
219
|
+
if (error || !parsed) return false;
|
|
220
|
+
if (parsed.protocol === "https:") return true;
|
|
221
|
+
if (parsed.protocol !== "http:") return false;
|
|
222
|
+
return isLoopbackHost(parsed.hostname);
|
|
256
223
|
}
|
|
257
224
|
/**
|
|
258
225
|
* Open a URL in the user's default browser using a platform-specific command.
|
|
@@ -269,7 +236,7 @@ function isSecureAuthUrl(url) {
|
|
|
269
236
|
*/
|
|
270
237
|
function openBrowser(url) {
|
|
271
238
|
if (!isHttpUrl(url)) return;
|
|
272
|
-
const { command, args } = match
|
|
239
|
+
const { command, args } = match(platform()).with("darwin", () => ({
|
|
273
240
|
args: [url],
|
|
274
241
|
command: "open"
|
|
275
242
|
})).with("win32", () => ({
|
|
@@ -330,12 +297,9 @@ function startLocalServer(options) {
|
|
|
330
297
|
* @returns True when the URL uses http: or https: protocol.
|
|
331
298
|
*/
|
|
332
299
|
function isHttpUrl(url) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
} catch {
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
300
|
+
const [error, parsed] = attempt(() => new URL(url));
|
|
301
|
+
if (error || !parsed) return false;
|
|
302
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:";
|
|
339
303
|
}
|
|
340
304
|
/**
|
|
341
305
|
* Check whether a hostname is a loopback address.
|
|
@@ -364,7 +328,6 @@ function isLoopbackHost(hostname) {
|
|
|
364
328
|
function escapeCmdMeta(url) {
|
|
365
329
|
return url.replaceAll(/[&|<>^]/g, "^$&");
|
|
366
330
|
}
|
|
367
|
-
|
|
368
331
|
//#endregion
|
|
369
332
|
//#region src/middleware/auth/strategies/device-code.ts
|
|
370
333
|
/**
|
|
@@ -432,11 +395,9 @@ async function requestDeviceAuth(options) {
|
|
|
432
395
|
const response = await postFormEncoded(options.deviceAuthUrl, body, options.signal);
|
|
433
396
|
if (!response) return null;
|
|
434
397
|
if (!response.ok) return null;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return null;
|
|
439
|
-
}
|
|
398
|
+
const [parseError, data] = await attemptAsync(() => response.json());
|
|
399
|
+
if (parseError) return null;
|
|
400
|
+
return parseDeviceAuthResponse(data);
|
|
440
401
|
}
|
|
441
402
|
/**
|
|
442
403
|
* Parse a device authorization response body.
|
|
@@ -446,17 +407,16 @@ async function requestDeviceAuth(options) {
|
|
|
446
407
|
* @returns The parsed response, or null if required fields are missing.
|
|
447
408
|
*/
|
|
448
409
|
function parseDeviceAuthResponse(data) {
|
|
449
|
-
if (
|
|
450
|
-
|
|
451
|
-
if (typeof
|
|
452
|
-
if (typeof
|
|
453
|
-
|
|
454
|
-
const interval = resolveServerInterval(record.interval);
|
|
410
|
+
if (!isPlainObject(data)) return null;
|
|
411
|
+
if (typeof data.device_code !== "string" || data.device_code === "") return null;
|
|
412
|
+
if (typeof data.user_code !== "string" || data.user_code === "") return null;
|
|
413
|
+
if (typeof data.verification_uri !== "string" || data.verification_uri === "") return null;
|
|
414
|
+
const interval = resolveServerInterval(data.interval);
|
|
455
415
|
return {
|
|
456
|
-
deviceCode:
|
|
416
|
+
deviceCode: data.device_code,
|
|
457
417
|
interval,
|
|
458
|
-
userCode:
|
|
459
|
-
verificationUri:
|
|
418
|
+
userCode: data.user_code,
|
|
419
|
+
verificationUri: data.verification_uri
|
|
460
420
|
};
|
|
461
421
|
}
|
|
462
422
|
/**
|
|
@@ -471,12 +431,10 @@ function parseDeviceAuthResponse(data) {
|
|
|
471
431
|
* @param userCode - The code the user should enter.
|
|
472
432
|
*/
|
|
473
433
|
async function displayUserCode(prompts, verificationUri, userCode) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
});
|
|
479
|
-
} catch {}
|
|
434
|
+
await attemptAsync(() => prompts.text({
|
|
435
|
+
defaultValue: "",
|
|
436
|
+
message: `Open ${verificationUri} and enter code: ${userCode} (press Enter to continue)`
|
|
437
|
+
}));
|
|
480
438
|
}
|
|
481
439
|
/**
|
|
482
440
|
* Resolve the poll interval, preferring server-provided value.
|
|
@@ -507,7 +465,7 @@ async function pollForToken(options) {
|
|
|
507
465
|
if (Date.now() >= options.deadline) return null;
|
|
508
466
|
await sleep(options.interval);
|
|
509
467
|
if (Date.now() >= options.deadline) return null;
|
|
510
|
-
return match
|
|
468
|
+
return match(await requestToken({
|
|
511
469
|
clientId: options.clientId,
|
|
512
470
|
deviceCode: options.deviceCode,
|
|
513
471
|
signal: options.signal,
|
|
@@ -555,24 +513,19 @@ async function requestToken(options) {
|
|
|
555
513
|
});
|
|
556
514
|
const response = await postFormEncoded(options.tokenUrl, body, options.signal);
|
|
557
515
|
if (!response) return { status: "error" };
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
if (
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
if (typeof record.error !== "string") return { status: "error" };
|
|
570
|
-
return match$1(record.error).with("authorization_pending", () => ({ status: "pending" })).with("slow_down", () => ({ status: "slow_down" })).with("expired_token", () => ({ status: "expired" })).with("access_denied", () => ({ status: "denied" })).otherwise(() => ({ status: "error" }));
|
|
571
|
-
} catch {
|
|
572
|
-
return { status: "error" };
|
|
516
|
+
const [parseError, data] = await attemptAsync(() => response.json());
|
|
517
|
+
if (parseError) return { status: "error" };
|
|
518
|
+
if (!isPlainObject(data)) return { status: "error" };
|
|
519
|
+
if (response.ok && typeof data.access_token === "string" && data.access_token !== "") {
|
|
520
|
+
if (typeof data.token_type === "string" && data.token_type.toLowerCase() !== "bearer") return { status: "error" };
|
|
521
|
+
return {
|
|
522
|
+
credential: createBearerCredential(data.access_token),
|
|
523
|
+
status: "success"
|
|
524
|
+
};
|
|
573
525
|
}
|
|
526
|
+
if (typeof data.error !== "string") return { status: "error" };
|
|
527
|
+
return match(data.error).with("authorization_pending", () => ({ status: "pending" })).with("slow_down", () => ({ status: "slow_down" })).with("expired_token", () => ({ status: "expired" })).with("access_denied", () => ({ status: "denied" })).otherwise(() => ({ status: "error" }));
|
|
574
528
|
}
|
|
575
|
-
|
|
576
529
|
//#endregion
|
|
577
530
|
//#region src/middleware/auth/strategies/dotenv.ts
|
|
578
531
|
/**
|
|
@@ -594,7 +547,6 @@ function resolveFromDotenv(options) {
|
|
|
594
547
|
if (!isValidToken(token)) return null;
|
|
595
548
|
return createBearerCredential(token);
|
|
596
549
|
}
|
|
597
|
-
|
|
598
550
|
//#endregion
|
|
599
551
|
//#region src/middleware/auth/strategies/env.ts
|
|
600
552
|
/**
|
|
@@ -608,7 +560,6 @@ function resolveFromEnv(options) {
|
|
|
608
560
|
if (!isValidToken(token)) return null;
|
|
609
561
|
return createBearerCredential(token);
|
|
610
562
|
}
|
|
611
|
-
|
|
612
563
|
//#endregion
|
|
613
564
|
//#region src/middleware/auth/schema.ts
|
|
614
565
|
/**
|
|
@@ -651,7 +602,6 @@ const authCredentialSchema = z.discriminatedUnion("type", [
|
|
|
651
602
|
apiKeyCredentialSchema,
|
|
652
603
|
customCredentialSchema
|
|
653
604
|
]);
|
|
654
|
-
|
|
655
605
|
//#endregion
|
|
656
606
|
//#region src/middleware/auth/strategies/file.ts
|
|
657
607
|
/**
|
|
@@ -671,7 +621,6 @@ function resolveFromFile(options) {
|
|
|
671
621
|
if (!result.success) return null;
|
|
672
622
|
return result.data;
|
|
673
623
|
}
|
|
674
|
-
|
|
675
624
|
//#endregion
|
|
676
625
|
//#region src/middleware/auth/strategies/oauth.ts
|
|
677
626
|
/**
|
|
@@ -867,18 +816,13 @@ async function exchangeCodeForToken(options) {
|
|
|
867
816
|
const response = await postFormEncoded(options.tokenUrl, body);
|
|
868
817
|
if (!response) return null;
|
|
869
818
|
if (!response.ok) return null;
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
return createBearerCredential(record.access_token);
|
|
877
|
-
} catch {
|
|
878
|
-
return null;
|
|
879
|
-
}
|
|
819
|
+
const [parseError, data] = await attemptAsync(() => response.json());
|
|
820
|
+
if (parseError) return null;
|
|
821
|
+
if (!isPlainObject(data)) return null;
|
|
822
|
+
if (typeof data.access_token !== "string" || data.access_token === "") return null;
|
|
823
|
+
if (typeof data.token_type === "string" && data.token_type.toLowerCase() !== "bearer") return null;
|
|
824
|
+
return createBearerCredential(data.access_token);
|
|
880
825
|
}
|
|
881
|
-
|
|
882
826
|
//#endregion
|
|
883
827
|
//#region src/middleware/auth/strategies/token.ts
|
|
884
828
|
/**
|
|
@@ -893,31 +837,27 @@ async function exchangeCodeForToken(options) {
|
|
|
893
837
|
* @returns A bearer credential on input, null on cancellation.
|
|
894
838
|
*/
|
|
895
839
|
async function resolveFromToken(options) {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
} catch {
|
|
901
|
-
return null;
|
|
902
|
-
}
|
|
840
|
+
const [promptError, token] = await attemptAsync(() => options.prompts.password({ message: options.message }));
|
|
841
|
+
if (promptError) return null;
|
|
842
|
+
if (!isValidToken(token)) return null;
|
|
843
|
+
return createBearerCredential(token);
|
|
903
844
|
}
|
|
904
|
-
|
|
905
845
|
//#endregion
|
|
906
846
|
//#region src/middleware/auth/chain.ts
|
|
907
847
|
const DEFAULT_PROMPT_MESSAGE = "Enter your API key";
|
|
908
848
|
/**
|
|
909
|
-
* Chain credential
|
|
849
|
+
* Chain credential strategies, returning the first non-null result.
|
|
910
850
|
*
|
|
911
|
-
* Walks the
|
|
912
|
-
* appropriate
|
|
851
|
+
* Walks the strategy list in order, dispatching each config to the
|
|
852
|
+
* appropriate strategy function via pattern matching. Short-circuits
|
|
913
853
|
* on the first successful resolution.
|
|
914
854
|
*
|
|
915
|
-
* @param options - Options with
|
|
916
|
-
* @returns The first resolved credential, or null if all
|
|
855
|
+
* @param options - Options with strategies, CLI name, and prompts instance.
|
|
856
|
+
* @returns The first resolved credential, or null if all strategies fail.
|
|
917
857
|
*/
|
|
918
858
|
async function runStrategyChain(options) {
|
|
919
859
|
const defaultTokenVar = deriveTokenVar(options.cliName);
|
|
920
|
-
return
|
|
860
|
+
return tryStrategies(options.strategies, 0, defaultTokenVar, options);
|
|
921
861
|
}
|
|
922
862
|
/**
|
|
923
863
|
* Return the given value when defined, otherwise the fallback.
|
|
@@ -931,33 +871,33 @@ function withDefault(value, fallback) {
|
|
|
931
871
|
return fallback;
|
|
932
872
|
}
|
|
933
873
|
/**
|
|
934
|
-
* Recursively try
|
|
874
|
+
* Recursively try strategies until one returns a credential or the list is exhausted.
|
|
935
875
|
*
|
|
936
876
|
* @private
|
|
937
|
-
* @param configs - The
|
|
877
|
+
* @param configs - The strategy configs.
|
|
938
878
|
* @param index - The current index.
|
|
939
879
|
* @param defaultTokenVar - The derived default token env var name.
|
|
940
880
|
* @param context - The resolve options for prompts access.
|
|
941
881
|
* @returns The first resolved credential, or null.
|
|
942
882
|
*/
|
|
943
|
-
async function
|
|
883
|
+
async function tryStrategies(configs, index, defaultTokenVar, context) {
|
|
944
884
|
if (index >= configs.length) return null;
|
|
945
885
|
const config = configs[index];
|
|
946
886
|
if (config === void 0) return null;
|
|
947
|
-
const credential = await
|
|
887
|
+
const credential = await dispatchStrategy(config, defaultTokenVar, context);
|
|
948
888
|
if (credential) return credential;
|
|
949
|
-
return
|
|
889
|
+
return tryStrategies(configs, index + 1, defaultTokenVar, context);
|
|
950
890
|
}
|
|
951
891
|
/**
|
|
952
|
-
* Dispatch a single
|
|
892
|
+
* Dispatch a single strategy config to its implementation.
|
|
953
893
|
*
|
|
954
894
|
* @private
|
|
955
|
-
* @param config - The
|
|
895
|
+
* @param config - The strategy config to dispatch.
|
|
956
896
|
* @param defaultTokenVar - The derived default token env var name.
|
|
957
897
|
* @param context - The resolve options for prompts access.
|
|
958
898
|
* @returns The resolved credential, or null.
|
|
959
899
|
*/
|
|
960
|
-
async function
|
|
900
|
+
async function dispatchStrategy(config, defaultTokenVar, context) {
|
|
961
901
|
return match$1(config).with({ source: "env" }, (c) => resolveFromEnv({ tokenVar: withDefault(c.tokenVar, defaultTokenVar) })).with({ source: "dotenv" }, (c) => resolveFromDotenv({
|
|
962
902
|
path: withDefault(c.path, join(process.cwd(), ".env")),
|
|
963
903
|
tokenVar: withDefault(c.tokenVar, defaultTokenVar)
|
|
@@ -968,7 +908,7 @@ async function dispatchResolver(config, defaultTokenVar, context) {
|
|
|
968
908
|
authUrl: c.authUrl,
|
|
969
909
|
callbackPath: withDefault(c.callbackPath, DEFAULT_OAUTH_CALLBACK_PATH),
|
|
970
910
|
clientId: c.clientId,
|
|
971
|
-
port: withDefault(c.port,
|
|
911
|
+
port: withDefault(c.port, 0),
|
|
972
912
|
scopes: withDefault(c.scopes, []),
|
|
973
913
|
timeout: withDefault(c.timeout, DEFAULT_OAUTH_TIMEOUT),
|
|
974
914
|
tokenUrl: c.tokenUrl
|
|
@@ -986,7 +926,6 @@ async function dispatchResolver(config, defaultTokenVar, context) {
|
|
|
986
926
|
prompts: context.prompts
|
|
987
927
|
})).with({ source: "custom" }, (c) => c.resolver()).exhaustive();
|
|
988
928
|
}
|
|
989
|
-
|
|
990
929
|
//#endregion
|
|
991
930
|
//#region src/middleware/auth/context.ts
|
|
992
931
|
/**
|
|
@@ -994,14 +933,14 @@ async function dispatchResolver(config, defaultTokenVar, context) {
|
|
|
994
933
|
*
|
|
995
934
|
* No credential data is stored on the returned object. `credential()`
|
|
996
935
|
* resolves passively on every call, `authenticated()` checks existence,
|
|
997
|
-
* `login()` runs the configured interactive
|
|
936
|
+
* `login()` runs the configured interactive strategies, saves the
|
|
998
937
|
* credential to the global file store, and `logout()` removes it.
|
|
999
938
|
*
|
|
1000
939
|
* @param options - Factory options.
|
|
1001
940
|
* @returns An AuthContext instance.
|
|
1002
941
|
*/
|
|
1003
942
|
function createAuthContext(options) {
|
|
1004
|
-
const {
|
|
943
|
+
const { strategies, cliName, prompts, resolveCredential, validate } = options;
|
|
1005
944
|
/**
|
|
1006
945
|
* Resolve the current credential from passive sources (file, env).
|
|
1007
946
|
*
|
|
@@ -1021,27 +960,33 @@ function createAuthContext(options) {
|
|
|
1021
960
|
return resolveCredential() !== null;
|
|
1022
961
|
}
|
|
1023
962
|
/**
|
|
1024
|
-
* Run configured
|
|
963
|
+
* Run configured strategies interactively and persist the credential.
|
|
964
|
+
*
|
|
965
|
+
* When `loginOptions.strategies` is provided, those strategies are used
|
|
966
|
+
* instead of the default configured list.
|
|
1025
967
|
*
|
|
1026
968
|
* @private
|
|
969
|
+
* @param loginOptions - Optional overrides for the login attempt.
|
|
1027
970
|
* @returns A Result with the credential on success or an AuthError on failure.
|
|
1028
971
|
*/
|
|
1029
|
-
async function login() {
|
|
972
|
+
async function login(loginOptions) {
|
|
1030
973
|
const resolved = await runStrategyChain({
|
|
1031
974
|
cliName,
|
|
1032
975
|
prompts,
|
|
1033
|
-
|
|
976
|
+
strategies: resolveLoginStrategies(loginOptions, strategies)
|
|
1034
977
|
});
|
|
1035
978
|
if (resolved === null) return authError({
|
|
1036
979
|
message: "No credential resolved from any source",
|
|
1037
980
|
type: "no_credential"
|
|
1038
981
|
});
|
|
1039
|
-
const [
|
|
982
|
+
const [validationError, validatedCredential] = await runValidation(resolveLoginValidate(loginOptions, validate), resolved);
|
|
983
|
+
if (validationError) return [validationError, null];
|
|
984
|
+
const [saveError] = createStore({ dirName: `.${cliName}` }).save(DEFAULT_AUTH_FILENAME, validatedCredential);
|
|
1040
985
|
if (saveError) return authError({
|
|
1041
986
|
message: `Failed to save credential: ${saveError.message}`,
|
|
1042
987
|
type: "save_failed"
|
|
1043
988
|
});
|
|
1044
|
-
return ok(
|
|
989
|
+
return ok(validatedCredential);
|
|
1045
990
|
}
|
|
1046
991
|
/**
|
|
1047
992
|
* Remove the stored credential from disk.
|
|
@@ -1074,15 +1019,157 @@ function createAuthContext(options) {
|
|
|
1074
1019
|
function authError(error) {
|
|
1075
1020
|
return [error, null];
|
|
1076
1021
|
}
|
|
1077
|
-
|
|
1022
|
+
/**
|
|
1023
|
+
* Resolve the active strategies for a login attempt.
|
|
1024
|
+
*
|
|
1025
|
+
* Returns the override strategies from login options when provided,
|
|
1026
|
+
* otherwise falls back to the configured strategies.
|
|
1027
|
+
*
|
|
1028
|
+
* @private
|
|
1029
|
+
* @param loginOptions - Optional login overrides.
|
|
1030
|
+
* @param configured - The default configured strategies.
|
|
1031
|
+
* @returns The strategies to use for the login attempt.
|
|
1032
|
+
*/
|
|
1033
|
+
function resolveLoginStrategies(loginOptions, configured) {
|
|
1034
|
+
if (loginOptions !== void 0 && loginOptions.strategies !== void 0) return loginOptions.strategies;
|
|
1035
|
+
return configured;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Resolve the active validate callback for a login attempt.
|
|
1039
|
+
*
|
|
1040
|
+
* Returns the override from login options when provided,
|
|
1041
|
+
* otherwise falls back to the configured validate callback.
|
|
1042
|
+
*
|
|
1043
|
+
* @private
|
|
1044
|
+
* @param loginOptions - Optional login overrides.
|
|
1045
|
+
* @param configured - The default configured validate callback.
|
|
1046
|
+
* @returns The validate callback to use, or undefined.
|
|
1047
|
+
*/
|
|
1048
|
+
function resolveLoginValidate(loginOptions, configured) {
|
|
1049
|
+
if (loginOptions !== void 0 && loginOptions.validate !== void 0) return loginOptions.validate;
|
|
1050
|
+
return configured;
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Run the validate callback against a resolved credential.
|
|
1054
|
+
*
|
|
1055
|
+
* When no validate callback is provided, returns the credential as-is.
|
|
1056
|
+
* When validation fails, returns the error Result.
|
|
1057
|
+
* When validation succeeds, returns the (possibly transformed) credential.
|
|
1058
|
+
*
|
|
1059
|
+
* @private
|
|
1060
|
+
* @param validateFn - The validate callback, or undefined.
|
|
1061
|
+
* @param credential - The resolved credential to validate.
|
|
1062
|
+
* @returns A Result with the validated credential or an AuthError.
|
|
1063
|
+
*/
|
|
1064
|
+
async function runValidation(validateFn, credential) {
|
|
1065
|
+
if (validateFn === void 0) return ok(credential);
|
|
1066
|
+
const [validationError, validatedCredential] = await validateFn(credential);
|
|
1067
|
+
if (validationError) return authError({
|
|
1068
|
+
message: validationError.message,
|
|
1069
|
+
type: "validation_failed"
|
|
1070
|
+
});
|
|
1071
|
+
return ok(validatedCredential);
|
|
1072
|
+
}
|
|
1073
|
+
//#endregion
|
|
1074
|
+
//#region src/middleware/http/build-auth-headers.ts
|
|
1075
|
+
/**
|
|
1076
|
+
* Convert auth credentials into HTTP headers.
|
|
1077
|
+
*
|
|
1078
|
+
* Uses exhaustive pattern matching to map each credential variant to
|
|
1079
|
+
* the appropriate header format.
|
|
1080
|
+
*
|
|
1081
|
+
* @module
|
|
1082
|
+
*/
|
|
1083
|
+
/**
|
|
1084
|
+
* Convert an auth credential into HTTP headers.
|
|
1085
|
+
*
|
|
1086
|
+
* @param credential - The credential to convert.
|
|
1087
|
+
* @returns A record of header name to header value.
|
|
1088
|
+
*/
|
|
1089
|
+
function buildAuthHeaders(credential) {
|
|
1090
|
+
return match$1(credential).with({ type: "bearer" }, (c) => ({ Authorization: `Bearer ${c.token}` })).with({ type: "basic" }, (c) => ({ Authorization: `Basic ${Buffer.from(`${c.username}:${c.password}`).toString("base64")}` })).with({ type: "api-key" }, (c) => ({ [c.headerName]: c.key })).with({ type: "custom" }, (c) => ({ ...c.headers })).exhaustive();
|
|
1091
|
+
}
|
|
1092
|
+
//#endregion
|
|
1093
|
+
//#region src/middleware/auth/headers.ts
|
|
1094
|
+
/**
|
|
1095
|
+
* Create a function that resolves auth credentials from `ctx.auth` into HTTP headers.
|
|
1096
|
+
*
|
|
1097
|
+
* The returned function reads `ctx.auth.credential()` and converts the credential
|
|
1098
|
+
* into the appropriate header format using `buildAuthHeaders()`. Returns an empty
|
|
1099
|
+
* record when no auth middleware is present or no credential exists.
|
|
1100
|
+
*
|
|
1101
|
+
* @returns A function that takes a Context and returns auth headers.
|
|
1102
|
+
*/
|
|
1103
|
+
function createAuthHeaders() {
|
|
1104
|
+
return function resolveHeaders(ctx) {
|
|
1105
|
+
if (!("auth" in ctx)) return {};
|
|
1106
|
+
const credential = ctx.auth.credential();
|
|
1107
|
+
if (credential === null) return {};
|
|
1108
|
+
return buildAuthHeaders(credential);
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
//#endregion
|
|
1112
|
+
//#region src/middleware/auth/require.ts
|
|
1113
|
+
/**
|
|
1114
|
+
* Enforcement gate middleware that requires authentication.
|
|
1115
|
+
*
|
|
1116
|
+
* @module
|
|
1117
|
+
*/
|
|
1118
|
+
const DEFAULT_MESSAGE = "Authentication required.";
|
|
1119
|
+
/**
|
|
1120
|
+
* Create an enforcement middleware that gates on authentication.
|
|
1121
|
+
*
|
|
1122
|
+
* When `ctx.auth.authenticated()` returns true, the middleware calls
|
|
1123
|
+
* `next()`. When not authenticated, it calls `ctx.fail()` with the
|
|
1124
|
+
* provided (or default) message. When `ctx.auth` is absent (auth
|
|
1125
|
+
* middleware not configured), it calls `ctx.fail()` with an
|
|
1126
|
+
* `AUTH_MIDDLEWARE_MISSING` code.
|
|
1127
|
+
*
|
|
1128
|
+
* @param options - Optional configuration for the require gate.
|
|
1129
|
+
* @returns A Middleware that enforces authentication.
|
|
1130
|
+
*/
|
|
1131
|
+
function createAuthRequire(options) {
|
|
1132
|
+
const message = resolveMessage(options);
|
|
1133
|
+
return middleware((ctx, next) => {
|
|
1134
|
+
if (!hasProperty(ctx, "auth")) ctx.fail("auth.require() must run after auth() middleware", { code: "AUTH_MIDDLEWARE_MISSING" });
|
|
1135
|
+
if (!ctx.auth.authenticated()) ctx.fail(message, { code: "AUTH_REQUIRED" });
|
|
1136
|
+
return next();
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Runtime property check that avoids TypeScript's `in` narrowing.
|
|
1141
|
+
*
|
|
1142
|
+
* The `Context` interface declares `auth` via module augmentation,
|
|
1143
|
+
* so `!('auth' in ctx)` narrows to `never`. This function uses an
|
|
1144
|
+
* `unknown` cast to bypass the narrowing and perform a pure runtime
|
|
1145
|
+
* check.
|
|
1146
|
+
*
|
|
1147
|
+
* @private
|
|
1148
|
+
* @param obj - The object to inspect.
|
|
1149
|
+
* @param key - The property name to check.
|
|
1150
|
+
* @returns True when the property exists on the object.
|
|
1151
|
+
*/
|
|
1152
|
+
function hasProperty(obj, key) {
|
|
1153
|
+
return typeof obj === "object" && obj !== null && key in obj;
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Resolve the failure message from optional require options.
|
|
1157
|
+
*
|
|
1158
|
+
* @private
|
|
1159
|
+
* @param options - Optional require gate options.
|
|
1160
|
+
* @returns The resolved message string.
|
|
1161
|
+
*/
|
|
1162
|
+
function resolveMessage(options) {
|
|
1163
|
+
if (options !== void 0 && options.message !== void 0) return options.message;
|
|
1164
|
+
return DEFAULT_MESSAGE;
|
|
1165
|
+
}
|
|
1078
1166
|
//#endregion
|
|
1079
1167
|
//#region src/middleware/auth/auth.ts
|
|
1080
1168
|
/**
|
|
1081
|
-
* Auth middleware factory with
|
|
1169
|
+
* Auth middleware factory with strategy builder functions.
|
|
1082
1170
|
*
|
|
1083
1171
|
* Decorates `ctx.auth` with functions to resolve credentials on demand
|
|
1084
|
-
* and run interactive authentication.
|
|
1085
|
-
* HTTP clients via the `http` option.
|
|
1172
|
+
* and run interactive authentication.
|
|
1086
1173
|
*
|
|
1087
1174
|
* @module
|
|
1088
1175
|
*/
|
|
@@ -1095,44 +1182,32 @@ function authError(error) {
|
|
|
1095
1182
|
* 2. Dotenv — `.env` file (when configured)
|
|
1096
1183
|
* 3. Env — `CLI_NAME_TOKEN`
|
|
1097
1184
|
*
|
|
1098
|
-
* Interactive
|
|
1185
|
+
* Interactive strategies (OAuth, device-code, token, custom) only run when the
|
|
1099
1186
|
* command handler explicitly calls `ctx.auth.login()`.
|
|
1100
1187
|
*
|
|
1101
|
-
* When `options.http` is provided, the middleware also creates HTTP
|
|
1102
|
-
* client(s) with automatic credential header injection and decorates
|
|
1103
|
-
* them onto `ctx[namespace]`.
|
|
1104
|
-
*
|
|
1105
1188
|
* @param options - Auth middleware configuration.
|
|
1106
|
-
* @returns A Middleware that decorates ctx.auth
|
|
1189
|
+
* @returns A Middleware that decorates ctx.auth.
|
|
1107
1190
|
*/
|
|
1108
1191
|
function createAuth(options) {
|
|
1109
|
-
const {
|
|
1192
|
+
const { strategies, validate } = options;
|
|
1110
1193
|
return middleware((ctx, next) => {
|
|
1111
1194
|
const cliName = ctx.meta.name;
|
|
1112
|
-
|
|
1195
|
+
decorateContext(ctx, "auth", createAuthContext({
|
|
1113
1196
|
cliName,
|
|
1114
1197
|
prompts: ctx.prompts,
|
|
1115
|
-
resolveCredential: () => resolveStoredCredential(cliName,
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
if (options.http !== void 0) normalizeHttpOptions(options.http).reduce((context, httpConfig) => {
|
|
1120
|
-
const client = createHttpClient({
|
|
1121
|
-
baseUrl: httpConfig.baseUrl,
|
|
1122
|
-
defaultHeaders: httpConfig.headers,
|
|
1123
|
-
resolveHeaders: () => credentialToHeaders(authContext.credential())
|
|
1124
|
-
});
|
|
1125
|
-
return decorateContext(context, httpConfig.namespace, client);
|
|
1126
|
-
}, ctx);
|
|
1198
|
+
resolveCredential: () => resolveStoredCredential(cliName, strategies),
|
|
1199
|
+
strategies,
|
|
1200
|
+
validate
|
|
1201
|
+
}));
|
|
1127
1202
|
return next();
|
|
1128
1203
|
});
|
|
1129
1204
|
}
|
|
1130
1205
|
/**
|
|
1131
|
-
* Auth middleware factory with
|
|
1206
|
+
* Auth middleware factory with strategy builder methods.
|
|
1132
1207
|
*
|
|
1133
|
-
* Use as `auth({
|
|
1208
|
+
* Use as `auth({ strategies: [...] })` to create middleware, or use
|
|
1134
1209
|
* the builder methods (`auth.env()`, `auth.oauth()`, etc.) to construct
|
|
1135
|
-
*
|
|
1210
|
+
* strategy configs with a cleaner API.
|
|
1136
1211
|
*/
|
|
1137
1212
|
const auth = Object.assign(createAuth, {
|
|
1138
1213
|
apiKey: buildToken,
|
|
@@ -1141,142 +1216,121 @@ const auth = Object.assign(createAuth, {
|
|
|
1141
1216
|
dotenv: buildDotenv,
|
|
1142
1217
|
env: buildEnv,
|
|
1143
1218
|
file: buildFile,
|
|
1219
|
+
headers: createAuthHeaders,
|
|
1144
1220
|
oauth: buildOAuth,
|
|
1221
|
+
require: createAuthRequire,
|
|
1145
1222
|
token: buildToken
|
|
1146
1223
|
});
|
|
1147
1224
|
/**
|
|
1148
|
-
* Build an env
|
|
1225
|
+
* Build an env strategy config.
|
|
1149
1226
|
*
|
|
1150
1227
|
* @private
|
|
1151
|
-
* @param options - Optional env
|
|
1228
|
+
* @param options - Optional env strategy options.
|
|
1152
1229
|
* @returns An EnvSourceConfig with `source: 'env'`.
|
|
1153
1230
|
*/
|
|
1154
1231
|
function buildEnv(options) {
|
|
1155
1232
|
return {
|
|
1156
|
-
|
|
1157
|
-
|
|
1233
|
+
...options,
|
|
1234
|
+
source: "env"
|
|
1158
1235
|
};
|
|
1159
1236
|
}
|
|
1160
1237
|
/**
|
|
1161
|
-
* Build a dotenv
|
|
1238
|
+
* Build a dotenv strategy config.
|
|
1162
1239
|
*
|
|
1163
1240
|
* @private
|
|
1164
|
-
* @param options - Optional dotenv
|
|
1241
|
+
* @param options - Optional dotenv strategy options.
|
|
1165
1242
|
* @returns A DotenvSourceConfig with `source: 'dotenv'`.
|
|
1166
1243
|
*/
|
|
1167
1244
|
function buildDotenv(options) {
|
|
1168
1245
|
return {
|
|
1169
|
-
|
|
1170
|
-
|
|
1246
|
+
...options,
|
|
1247
|
+
source: "dotenv"
|
|
1171
1248
|
};
|
|
1172
1249
|
}
|
|
1173
1250
|
/**
|
|
1174
|
-
* Build a file
|
|
1251
|
+
* Build a file strategy config.
|
|
1175
1252
|
*
|
|
1176
1253
|
* @private
|
|
1177
|
-
* @param options - Optional file
|
|
1254
|
+
* @param options - Optional file strategy options.
|
|
1178
1255
|
* @returns A FileSourceConfig with `source: 'file'`.
|
|
1179
1256
|
*/
|
|
1180
1257
|
function buildFile(options) {
|
|
1181
1258
|
return {
|
|
1182
|
-
|
|
1183
|
-
|
|
1259
|
+
...options,
|
|
1260
|
+
source: "file"
|
|
1184
1261
|
};
|
|
1185
1262
|
}
|
|
1186
1263
|
/**
|
|
1187
|
-
* Build an OAuth
|
|
1264
|
+
* Build an OAuth strategy config.
|
|
1188
1265
|
*
|
|
1189
1266
|
* @private
|
|
1190
|
-
* @param options - OAuth
|
|
1267
|
+
* @param options - OAuth strategy options (clientId, authUrl, tokenUrl required).
|
|
1191
1268
|
* @returns An OAuthSourceConfig with `source: 'oauth'`.
|
|
1192
1269
|
*/
|
|
1193
1270
|
function buildOAuth(options) {
|
|
1194
1271
|
return {
|
|
1195
|
-
|
|
1196
|
-
|
|
1272
|
+
...options,
|
|
1273
|
+
source: "oauth"
|
|
1197
1274
|
};
|
|
1198
1275
|
}
|
|
1199
1276
|
/**
|
|
1200
|
-
* Build a device code
|
|
1277
|
+
* Build a device code strategy config.
|
|
1201
1278
|
*
|
|
1202
1279
|
* @private
|
|
1203
|
-
* @param options - Device code
|
|
1280
|
+
* @param options - Device code strategy options (clientId, deviceAuthUrl, tokenUrl required).
|
|
1204
1281
|
* @returns A DeviceCodeSourceConfig with `source: 'device-code'`.
|
|
1205
1282
|
*/
|
|
1206
1283
|
function buildDeviceCode(options) {
|
|
1207
1284
|
return {
|
|
1208
|
-
|
|
1209
|
-
|
|
1285
|
+
...options,
|
|
1286
|
+
source: "device-code"
|
|
1210
1287
|
};
|
|
1211
1288
|
}
|
|
1212
1289
|
/**
|
|
1213
|
-
* Build a token
|
|
1290
|
+
* Build a token strategy config.
|
|
1214
1291
|
*
|
|
1215
1292
|
* Prompts the user for a token interactively. Aliased as `auth.apiKey()`.
|
|
1216
1293
|
*
|
|
1217
1294
|
* @private
|
|
1218
|
-
* @param options - Optional token
|
|
1295
|
+
* @param options - Optional token strategy options.
|
|
1219
1296
|
* @returns A TokenSourceConfig with `source: 'token'`.
|
|
1220
1297
|
*/
|
|
1221
1298
|
function buildToken(options) {
|
|
1222
1299
|
return {
|
|
1223
|
-
|
|
1224
|
-
|
|
1300
|
+
...options,
|
|
1301
|
+
source: "token"
|
|
1225
1302
|
};
|
|
1226
1303
|
}
|
|
1227
1304
|
/**
|
|
1228
|
-
* Build a custom
|
|
1305
|
+
* Build a custom strategy config from a strategy function.
|
|
1229
1306
|
*
|
|
1230
1307
|
* @private
|
|
1231
|
-
* @param
|
|
1308
|
+
* @param fn - The custom strategy function.
|
|
1232
1309
|
* @returns A CustomSourceConfig with `source: 'custom'`.
|
|
1233
1310
|
*/
|
|
1234
|
-
function buildCustom(
|
|
1311
|
+
function buildCustom(fn) {
|
|
1235
1312
|
return {
|
|
1236
|
-
resolver,
|
|
1313
|
+
resolver: fn,
|
|
1237
1314
|
source: "custom"
|
|
1238
1315
|
};
|
|
1239
1316
|
}
|
|
1240
1317
|
/**
|
|
1241
|
-
* Normalize the `http` option into an array of configs.
|
|
1242
|
-
*
|
|
1243
|
-
* @private
|
|
1244
|
-
* @param http - A single config or array of configs.
|
|
1245
|
-
* @returns An array of AuthHttpOptions.
|
|
1246
|
-
*/
|
|
1247
|
-
function normalizeHttpOptions(http) {
|
|
1248
|
-
if ("baseUrl" in http) return [http];
|
|
1249
|
-
return http;
|
|
1250
|
-
}
|
|
1251
|
-
/**
|
|
1252
|
-
* Convert a credential into auth headers, returning an empty record
|
|
1253
|
-
* when no credential is available.
|
|
1254
|
-
*
|
|
1255
|
-
* @private
|
|
1256
|
-
* @param credential - The credential or null.
|
|
1257
|
-
* @returns A record of auth headers.
|
|
1258
|
-
*/
|
|
1259
|
-
function credentialToHeaders(credential) {
|
|
1260
|
-
if (credential === null) return {};
|
|
1261
|
-
return buildAuthHeaders(credential);
|
|
1262
|
-
}
|
|
1263
|
-
/**
|
|
1264
1318
|
* Attempt to resolve a credential from stored (non-interactive) sources.
|
|
1265
1319
|
*
|
|
1266
1320
|
* Checks the file store first, then dotenv, then falls back to the
|
|
1267
|
-
* environment variable. Scans the
|
|
1321
|
+
* environment variable. Scans the strategy list for `file`, `dotenv`,
|
|
1268
1322
|
* and `env` source configs to respect user-configured overrides
|
|
1269
1323
|
* (e.g. a custom `tokenVar`, `dirName`, or dotenv `path`).
|
|
1270
1324
|
*
|
|
1271
1325
|
* @private
|
|
1272
1326
|
* @param cliName - The CLI name, used to derive paths and env var names.
|
|
1273
|
-
* @param
|
|
1327
|
+
* @param strategies - The configured strategy list for extracting overrides.
|
|
1274
1328
|
* @returns The resolved credential, or null.
|
|
1275
1329
|
*/
|
|
1276
|
-
function resolveStoredCredential(cliName,
|
|
1277
|
-
const fileConfig =
|
|
1278
|
-
const dotenvConfig =
|
|
1279
|
-
const envConfig =
|
|
1330
|
+
function resolveStoredCredential(cliName, strategies) {
|
|
1331
|
+
const fileConfig = findStrategyBySource(strategies, "file");
|
|
1332
|
+
const dotenvConfig = findStrategyBySource(strategies, "dotenv");
|
|
1333
|
+
const envConfig = findStrategyBySource(strategies, "env");
|
|
1280
1334
|
const defaultTokenVar = deriveTokenVar(cliName);
|
|
1281
1335
|
const fromFile = resolveFromFile({
|
|
1282
1336
|
dirName: withDefault(extractProp(fileConfig, "dirName"), `.${cliName}`),
|
|
@@ -1293,15 +1347,15 @@ function resolveStoredCredential(cliName, resolvers) {
|
|
|
1293
1347
|
return resolveFromEnv({ tokenVar: withDefault(extractProp(envConfig, "tokenVar"), defaultTokenVar) });
|
|
1294
1348
|
}
|
|
1295
1349
|
/**
|
|
1296
|
-
* Find the first
|
|
1350
|
+
* Find the first strategy config matching a given source type.
|
|
1297
1351
|
*
|
|
1298
1352
|
* @private
|
|
1299
|
-
* @param
|
|
1353
|
+
* @param strategies - The strategy config list.
|
|
1300
1354
|
* @param source - The source type to find.
|
|
1301
1355
|
* @returns The matching config, or undefined.
|
|
1302
1356
|
*/
|
|
1303
|
-
function
|
|
1304
|
-
return
|
|
1357
|
+
function findStrategyBySource(strategies, source) {
|
|
1358
|
+
return strategies.find((r) => r.source === source);
|
|
1305
1359
|
}
|
|
1306
1360
|
/**
|
|
1307
1361
|
* Safely extract a property from an optional config object.
|
|
@@ -1318,7 +1372,7 @@ function extractProp(config, key) {
|
|
|
1318
1372
|
if (config === void 0) return;
|
|
1319
1373
|
return config[key];
|
|
1320
1374
|
}
|
|
1321
|
-
|
|
1322
1375
|
//#endregion
|
|
1323
|
-
export { auth };
|
|
1376
|
+
export { auth, createAuthHeaders, createAuthRequire };
|
|
1377
|
+
|
|
1324
1378
|
//# sourceMappingURL=auth.js.map
|