From 27c00a816598dda7d5b0043db55151165fd47960 Mon Sep 17 00:00:00 2001 From: Gabi Villalonga Simon Date: Mon, 4 Mar 2024 10:18:42 +0000 Subject: [PATCH] fix: type errors and lints in listManifests --- src/registry/http.ts | 5 +++++ src/registry/r2.ts | 24 ++++++++++-------------- src/registry/registry.ts | 9 ++++----- src/router.ts | 23 +++++++++++++---------- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/registry/http.ts b/src/registry/http.ts index d602adf..9949cc0 100644 --- a/src/registry/http.ts +++ b/src/registry/http.ts @@ -7,6 +7,7 @@ import { FinishedUploadObject, GetLayerResponse, GetManifestResponse, + ListRepositoriesResponse, PutManifestResponse, Registry, RegistryConfiguration, @@ -467,6 +468,10 @@ export class RegistryHTTPClient implements Registry { ): Promise { throw new Error("unimplemented"); } + + async listRepositories(_limit?: number, _last?: string): Promise { + throw new Error("unimplemented"); + } } // AuthType defined the supported auth types diff --git a/src/registry/r2.ts b/src/registry/r2.ts index d2acc43..5f95c36 100644 --- a/src/registry/r2.ts +++ b/src/registry/r2.ts @@ -132,30 +132,26 @@ export class R2Registry implements Registry { } async listRepositories(limit?: number, last?: string): Promise { - const env = this.env; const options = { limit: limit ? limit : 1000, delimiter: "/", startAfter: last, - } - const r2Objects = (await env.REGISTRY.list(options)); - - let truncated = r2Objects.truncated; - let cursor = truncated ? r2Objects.cursor : undefined; - - while (truncated) { - const next = await env.REGISTRY.list({ + }; + let r2Objects = await this.env.REGISTRY.list(options); + const objects = r2Objects.objects; + let cursor = r2Objects.truncated ? r2Objects.cursor : undefined; + while (r2Objects.truncated && objects.length < options.limit) { + const next = await this.env.REGISTRY.list({ ...options, cursor: cursor, }); - r2Objects.objects.push(...next.objects); - - truncated = next.truncated; - cursor = next.cursor + objects.push(...next.objects); + r2Objects = next; } return { - repositories: r2Objects.delimitedPrefixes.map((name)=> name.endsWith('/') ? name.slice(0, -1) : name) + repositories: r2Objects.delimitedPrefixes.map((name) => (name.endsWith("/") ? name.slice(0, -1) : name)), + cursor: r2Objects.truncated ? r2Objects.cursor : undefined, }; } diff --git a/src/registry/registry.ts b/src/registry/registry.ts index e115bd6..49643a6 100644 --- a/src/registry/registry.ts +++ b/src/registry/registry.ts @@ -43,11 +43,10 @@ export type CheckManifestResponse = exists: false; }; -export type ListRepositoriesResponse = - { - repositories: string[]; - } - +export type ListRepositoriesResponse = { + repositories: string[]; + cursor?: string; +}; // Response layerExists call export type CheckLayerResponse = diff --git a/src/router.ts b/src/router.ts index 2eabac6..4934e86 100644 --- a/src/router.ts +++ b/src/router.ts @@ -27,15 +27,18 @@ v2Router.get("/", async (_req, _env: Env) => { v2Router.get("/_catalog", async (req, env: Env) => { const { n, last } = req.query; - const res = await env.REGISTRY_CLIENT.listRepositories( - n ? parseInt(n?.toString()) : undefined, - last?.toString() - ); + const res = await env.REGISTRY_CLIENT.listRepositories(n ? parseInt(n?.toString()) : undefined, last?.toString()); + if ("response" in res) { + return res.response; + } - return new Response(JSON.stringify(res)); + return new Response(JSON.stringify(res), { + headers: { + Link: `${req.url}/?last=${res.cursor ?? ""}; rel=next`, + }, + }); }); - v2Router.delete("/:name+/manifests/:reference", async (req, env: Env) => { // deleting a manifest works by retrieving the """main""" manifest that its key is a sha, // and then going through every tag and removing it @@ -49,17 +52,17 @@ v2Router.delete("/:name+/manifests/:reference", async (req, env: Env) => { // // If somehow we need to remove by paginating, we accept a last query param - const { last } = req.query; + const { last, limit } = req.query; const { name, reference } = req.params; // Reference is ALWAYS a sha256 const manifest = await env.REGISTRY.head(`${name}/manifests/${reference}`); if (manifest === null) { return new Response(JSON.stringify(ManifestUnknownError), { status: 404 }); } - + const limitInt = parseInt(limit?.toString() ?? "1000", 10); const tags = await env.REGISTRY.list({ prefix: `${name}/manifests`, - limit: 1000, + limit: isNaN(limitInt) ? 1000 : limitInt, startAfter: last?.toString(), }); for (const tag of tags.objects) { @@ -76,7 +79,7 @@ v2Router.delete("/:name+/manifests/:reference", async (req, env: Env) => { return new Response(JSON.stringify(ManifestTagsListTooBigError), { status: 400, headers: { - "Link": `${req.url}/last=${tags.objects[tags.objects.length - 1]}; rel=next`, + "Link": `${req.url}/?last=${tags.truncated ? tags.cursor : ""}; rel=next`, "Content-Type": "application/json", }, });