@getrouter/getrouter-cli 0.1.8 → 0.1.9
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/dist/bin.mjs +12 -8
- package/package.json +1 -1
- package/src/cmd/auth.ts +1 -1
- package/src/core/api/client.ts +3 -0
- package/src/core/http/request.ts +9 -3
- package/tests/http/request.test.ts +30 -0
package/dist/bin.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { randomInt } from "node:crypto";
|
|
|
8
8
|
import prompts from "prompts";
|
|
9
9
|
|
|
10
10
|
//#region package.json
|
|
11
|
-
var version = "0.1.
|
|
11
|
+
var version = "0.1.9";
|
|
12
12
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/generated/router/dashboard/v1/index.ts
|
|
@@ -369,12 +369,15 @@ const shouldRetryResponse = (error) => {
|
|
|
369
369
|
if (typeof error === "object" && error !== null && "status" in error && typeof error.status === "number") return isServerError(error.status);
|
|
370
370
|
return error instanceof TypeError;
|
|
371
371
|
};
|
|
372
|
-
const requestJson = async ({ path: path$1, method, body, fetchImpl, maxRetries = 3, _retrySleep }) => {
|
|
372
|
+
const requestJson = async ({ path: path$1, method, body, fetchImpl, maxRetries = 3, includeAuth = true, _retrySleep }) => {
|
|
373
373
|
return withRetry(async () => {
|
|
374
|
-
const auth = readAuth()
|
|
374
|
+
const auth = includeAuth ? readAuth() : {
|
|
375
|
+
accessToken: void 0,
|
|
376
|
+
refreshToken: void 0
|
|
377
|
+
};
|
|
375
378
|
const url = buildApiUrl(path$1);
|
|
376
|
-
let res = await doFetch(url, method, buildHeaders(auth.accessToken), body, fetchImpl);
|
|
377
|
-
if (res.status === 401 && auth.refreshToken) {
|
|
379
|
+
let res = await doFetch(url, method, includeAuth ? buildHeaders(auth.accessToken) : buildHeaders(), body, fetchImpl);
|
|
380
|
+
if (includeAuth && res.status === 401 && auth.refreshToken) {
|
|
378
381
|
const refreshed = await refreshAccessToken({ fetchImpl });
|
|
379
382
|
if (refreshed?.accessToken) res = await doFetch(url, method, buildHeaders(refreshed.accessToken), body, fetchImpl);
|
|
380
383
|
}
|
|
@@ -389,7 +392,7 @@ const requestJson = async ({ path: path$1, method, body, fetchImpl, maxRetries =
|
|
|
389
392
|
|
|
390
393
|
//#endregion
|
|
391
394
|
//#region src/core/api/client.ts
|
|
392
|
-
const createApiClients = ({ fetchImpl, clients }) => {
|
|
395
|
+
const createApiClients = ({ fetchImpl, clients, includeAuth = true }) => {
|
|
393
396
|
const factories = clients ?? {
|
|
394
397
|
createConsumerServiceClient,
|
|
395
398
|
createAuthServiceClient,
|
|
@@ -402,7 +405,8 @@ const createApiClients = ({ fetchImpl, clients }) => {
|
|
|
402
405
|
path: path$1,
|
|
403
406
|
method,
|
|
404
407
|
body: body ? JSON.parse(body) : void 0,
|
|
405
|
-
fetchImpl
|
|
408
|
+
fetchImpl,
|
|
409
|
+
includeAuth
|
|
406
410
|
});
|
|
407
411
|
};
|
|
408
412
|
return {
|
|
@@ -505,7 +509,7 @@ const pollAuthorize = async ({ authorize, code, timeoutMs = 300 * 1e3, initialDe
|
|
|
505
509
|
//#region src/cmd/auth.ts
|
|
506
510
|
const registerAuthCommands = (program) => {
|
|
507
511
|
program.command("login").description("Login with device flow").action(async () => {
|
|
508
|
-
const { authService } = createApiClients({});
|
|
512
|
+
const { authService } = createApiClients({ includeAuth: false });
|
|
509
513
|
const authCode = generateAuthCode();
|
|
510
514
|
const url = buildLoginUrl(authCode);
|
|
511
515
|
console.log("🔐 To authenticate, visit:");
|
package/package.json
CHANGED
package/src/cmd/auth.ts
CHANGED
|
@@ -14,7 +14,7 @@ export const registerAuthCommands = (program: Command) => {
|
|
|
14
14
|
.command("login")
|
|
15
15
|
.description("Login with device flow")
|
|
16
16
|
.action(async () => {
|
|
17
|
-
const { authService } = createApiClients({});
|
|
17
|
+
const { authService } = createApiClients({ includeAuth: false });
|
|
18
18
|
const authCode = generateAuthCode();
|
|
19
19
|
const url = buildLoginUrl(authCode);
|
|
20
20
|
console.log("🔐 To authenticate, visit:");
|
package/src/core/api/client.ts
CHANGED
|
@@ -46,9 +46,11 @@ export type ApiClients = {
|
|
|
46
46
|
export const createApiClients = ({
|
|
47
47
|
fetchImpl,
|
|
48
48
|
clients,
|
|
49
|
+
includeAuth = true,
|
|
49
50
|
}: {
|
|
50
51
|
fetchImpl?: typeof fetch;
|
|
51
52
|
clients?: ClientFactories;
|
|
53
|
+
includeAuth?: boolean;
|
|
52
54
|
}): ApiClients => {
|
|
53
55
|
const factories =
|
|
54
56
|
clients ??
|
|
@@ -66,6 +68,7 @@ export const createApiClients = ({
|
|
|
66
68
|
method,
|
|
67
69
|
body: body ? JSON.parse(body) : undefined,
|
|
68
70
|
fetchImpl,
|
|
71
|
+
includeAuth,
|
|
69
72
|
});
|
|
70
73
|
};
|
|
71
74
|
|
package/src/core/http/request.ts
CHANGED
|
@@ -10,6 +10,7 @@ type RequestInput = {
|
|
|
10
10
|
body?: unknown;
|
|
11
11
|
fetchImpl?: typeof fetch;
|
|
12
12
|
maxRetries?: number;
|
|
13
|
+
includeAuth?: boolean;
|
|
13
14
|
/** For testing: override the sleep function used for retry delays */
|
|
14
15
|
_retrySleep?: (ms: number) => Promise<void>;
|
|
15
16
|
};
|
|
@@ -63,18 +64,23 @@ export const requestJson = async <T = unknown>({
|
|
|
63
64
|
body,
|
|
64
65
|
fetchImpl,
|
|
65
66
|
maxRetries = 3,
|
|
67
|
+
includeAuth = true,
|
|
66
68
|
_retrySleep,
|
|
67
69
|
}: RequestInput): Promise<T> => {
|
|
68
70
|
return withRetry(
|
|
69
71
|
async () => {
|
|
70
|
-
const auth =
|
|
72
|
+
const auth = includeAuth
|
|
73
|
+
? readAuth()
|
|
74
|
+
: { accessToken: undefined, refreshToken: undefined };
|
|
71
75
|
const url = buildApiUrl(path);
|
|
72
|
-
const headers =
|
|
76
|
+
const headers = includeAuth
|
|
77
|
+
? buildHeaders(auth.accessToken)
|
|
78
|
+
: buildHeaders();
|
|
73
79
|
|
|
74
80
|
let res = await doFetch(url, method, headers, body, fetchImpl);
|
|
75
81
|
|
|
76
82
|
// On 401, attempt token refresh and retry once
|
|
77
|
-
if (res.status === 401 && auth.refreshToken) {
|
|
83
|
+
if (includeAuth && res.status === 401 && auth.refreshToken) {
|
|
78
84
|
const refreshed = await refreshAccessToken({ fetchImpl });
|
|
79
85
|
if (refreshed?.accessToken) {
|
|
80
86
|
const newHeaders = buildHeaders(refreshed.accessToken);
|
|
@@ -51,6 +51,36 @@ describe("requestJson", () => {
|
|
|
51
51
|
expect(headers.Cookie).toBe("access_token=t");
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
it("skips auth headers when includeAuth is false", async () => {
|
|
55
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "getrouter-"));
|
|
56
|
+
process.env.GETROUTER_CONFIG_DIR = dir;
|
|
57
|
+
fs.writeFileSync(
|
|
58
|
+
path.join(dir, "auth.json"),
|
|
59
|
+
JSON.stringify({ accessToken: "t" }),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const fetchSpy = vi.fn(
|
|
63
|
+
async (_input: RequestInfo | URL, _init?: RequestInit) =>
|
|
64
|
+
({
|
|
65
|
+
ok: true,
|
|
66
|
+
json: async () => ({ ok: true }),
|
|
67
|
+
}) as Response,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
await requestJson({
|
|
71
|
+
path: "/v1/test",
|
|
72
|
+
method: "GET",
|
|
73
|
+
fetchImpl: fetchSpy as unknown as typeof fetch,
|
|
74
|
+
includeAuth: false,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const call = fetchSpy.mock.calls[0] as Parameters<typeof fetch> | undefined;
|
|
78
|
+
const init = call?.[1];
|
|
79
|
+
const headers = (init?.headers ?? {}) as Record<string, string>;
|
|
80
|
+
expect(headers.Authorization).toBeUndefined();
|
|
81
|
+
expect(headers.Cookie).toBeUndefined();
|
|
82
|
+
});
|
|
83
|
+
|
|
54
84
|
it("uses GETROUTER_AUTH_COOKIE when set", async () => {
|
|
55
85
|
process.env.GETROUTER_AUTH_COOKIE = "router_auth";
|
|
56
86
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "getrouter-"));
|