-v raises the CLI's log level per repeat; -q prints only fatal errors (closes #212)
check / check (push) Waiting to run
check / check (push) Waiting to run
Every line quak prints on stderr now goes through one log, in src/cli-log.ts, at one of six levels. The default, info, prints what quak printed before. -v adds each retry and the start and end of each refresh and ML data fetch; -vv adds each request with its result. -q prints only the line a failing command exits with, and is refused with -v. Both are program options. withRetry reports retries through a new onRetry, and ApiClient reports requests through a new onRequest; the CLI logs what they report. --json now changes stdout only, so backup and --json runs log their progress on stderr. Model: opus-5-5
This commit is contained in:
@@ -1222,3 +1222,65 @@ describe("ApiClient non-idempotent requests", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// `onRequest` hears of each request the client sends, as its response arrives
|
||||
// or as it fails. The CLI logs these with `-vv`. A retried request is reported
|
||||
// once for each attempt.
|
||||
describe("ApiClient onRequest", () => {
|
||||
it("reports each request with its status, or with the error it failed with", async () => {
|
||||
const refused = new TypeError("fetch failed");
|
||||
const { fetch } = scriptedFetch(
|
||||
refused,
|
||||
textResponse("unavailable", 503),
|
||||
jsonResponse({ collections: [] }),
|
||||
jsonResponse({}),
|
||||
streamResponse(new Uint8Array([1, 2, 3])),
|
||||
);
|
||||
const requests: unknown[] = [];
|
||||
const client = new ApiClient({
|
||||
fetch,
|
||||
retry: noWait,
|
||||
onRequest: (request) => requests.push(request),
|
||||
});
|
||||
|
||||
await client.getJSON("/collections/v2", { sinceTime: 0 });
|
||||
await client.postJSON("/users/logout", {});
|
||||
await readAll(await client.getFileStream(7));
|
||||
|
||||
const collections = "https://api.ente.io/collections/v2?sinceTime=0";
|
||||
expect(requests).toEqual([
|
||||
{ method: "GET", url: collections, error: refused },
|
||||
{ method: "GET", url: collections, status: 503 },
|
||||
{ method: "GET", url: collections, status: 200 },
|
||||
{
|
||||
method: "POST",
|
||||
url: "https://api.ente.io/users/logout",
|
||||
status: 200,
|
||||
},
|
||||
{
|
||||
method: "GET",
|
||||
url: "https://files.ente.io/?fileID=7",
|
||||
status: 200,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("reports a presigned upload without its query, which holds the upload's signature", async () => {
|
||||
const { fetch } = scriptedFetch(new Response(null, { status: 200 }));
|
||||
const requests: unknown[] = [];
|
||||
const client = new ApiClient({
|
||||
fetch,
|
||||
retry: noWait,
|
||||
onRequest: (request) => requests.push(request),
|
||||
});
|
||||
|
||||
await client.putFile(
|
||||
"https://s3.example/obj?X-Amz-Signature=abc",
|
||||
new Uint8Array([1, 2]),
|
||||
);
|
||||
|
||||
expect(requests).toEqual([
|
||||
{ method: "PUT", url: "https://s3.example/obj", status: 200 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user