Skip to content

Commit

Permalink
Implemented route /v2/_catalog API functionality (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
keyskull authored Mar 4, 2024
1 parent 81a7219 commit 7e58b84
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/registry/r2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
FinishedUploadObject,
GetLayerResponse,
GetManifestResponse,
ListRepositoriesResponse,
PutManifestResponse,
Registry,
RegistryError,
Expand Down Expand Up @@ -130,6 +131,34 @@ export class R2Registry implements Registry {
return checkManifestResponse;
}

async listRepositories(limit?: number, last?: string): Promise<RegistryError | ListRepositoriesResponse> {
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;

Check failure on line 144 in src/registry/r2.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (20.x)

Property 'cursor' does not exist on type 'R2Objects'.

while (truncated) {
const next = await env.REGISTRY.list({
...options,
cursor: cursor,
});
r2Objects.objects.push(...next.objects);

truncated = next.truncated;
cursor = next.cursor

Check failure on line 154 in src/registry/r2.ts

View workflow job for this annotation

GitHub Actions / Unit Tests (20.x)

Property 'cursor' does not exist on type 'R2Objects'.
}

return {
repositories: r2Objects.delimitedPrefixes.map((name)=> name.endsWith('/') ? name.slice(0, -1) : name)
};
}

async putManifest(
name: string,
reference: string,
Expand Down
9 changes: 9 additions & 0 deletions src/registry/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export type CheckManifestResponse =
exists: false;
};

export type ListRepositoriesResponse =
{
repositories: string[];
}


// Response layerExists call
export type CheckLayerResponse =
| {
Expand Down Expand Up @@ -102,6 +108,9 @@ export interface Registry {
// checks whether the manifest exists in the registry
manifestExists(namespace: string, tag: string): Promise<CheckManifestResponse | RegistryError>;

// listing repositories in the registry
listRepositories(limit?: number, last?: string): Promise<ListRepositoriesResponse | RegistryError>;

// gets the manifest by namespace + digest
getManifest(namespace: string, digest: string): Promise<GetManifestResponse | RegistryError>;

Expand Down
11 changes: 11 additions & 0 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ v2Router.get("/", async (_req, _env: Env) => {
return new Response();
});

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()
);

return new Response(JSON.stringify(res));
});


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
Expand Down

0 comments on commit 7e58b84

Please sign in to comment.