diff --git a/src/commands/repo-list.ts b/src/commands/repo-list.ts index ac4b464e..801d623e 100644 --- a/src/commands/repo-list.ts +++ b/src/commands/repo-list.ts @@ -1,7 +1,7 @@ import { getCredentials } from "../auth"; import { createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; -import { getRepositories } from "../lib/prismic/clients/legacy-user"; +import { getRepositories } from "../lib/prismic/clients/user"; import { formatTable } from "../lib/string"; const config = { diff --git a/src/lib/prismic/clients/legacy-user.ts b/src/lib/prismic/clients/legacy-user.ts deleted file mode 100644 index a3743602..00000000 --- a/src/lib/prismic/clients/legacy-user.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as z from "zod/mini"; - -import { request } from "../../request"; - -const RepositoriesSchema = z.array( - z.object({ - domain: z.string(), - name: z.optional(z.string()), - // A role is a string (e.g. "Owner") for repositories with a single - // role, or a record of locale to role (e.g. { "de-de": "Writer" }) - // for repositories with locale-scoped roles. - role: z.optional(z.union([z.string(), z.record(z.string(), z.string())])), - }), -); -type Repositories = z.infer; - -export async function getRepositories(config: { - token: string | undefined; - host: string; -}): Promise { - const url = new URL("repositories", `https://user-service.${config.host}/`); - return request(url, { - credentials: { "prismic-auth": config.token }, - schema: RepositoriesSchema, - unknownErrorMessage: "Failed to load your repositories", - }); -} diff --git a/src/lib/prismic/clients/user.ts b/src/lib/prismic/clients/user.ts index 308f5c9d..af4c2252 100644 --- a/src/lib/prismic/clients/user.ts +++ b/src/lib/prismic/clients/user.ts @@ -9,6 +9,19 @@ const ProfileSchema = z.object({ }); export type Profile = z.infer; +// A role is a string (e.g. "Owner") for a repository with one role, or a +// record of locale to role (e.g. { "de-de": "Writer" }) when roles are +// locale-scoped. A Write API token sends a string role, or omits it. +const RepositorySchema = z.object({ + domain: z.string(), + name: z.optional(z.string()), + role: z.optional(z.union([z.string(), z.record(z.string(), z.string())])), +}); + +const RepositoryListSchema = z.object({ + repositories: z.array(RepositorySchema), +}); + export async function getProfile(config: { token: string | undefined; host: string; @@ -20,3 +33,16 @@ export async function getProfile(config: { unknownErrorMessage: "Failed to load your profile", }); } + +export async function getRepositories(config: { + token: string | undefined; + host: string; +}): Promise[]> { + const url = new URL("user/repositories", `https://api.internal.${config.host}/`); + const response = await request(url, { + headers: { Authorization: `Bearer ${config.token}` }, + schema: RepositoryListSchema, + unknownErrorMessage: "Failed to load your repositories", + }); + return response.repositories; +} diff --git a/test/repo-list.test.ts b/test/repo-list.test.ts index 1b18ad5b..a3357723 100644 --- a/test/repo-list.test.ts +++ b/test/repo-list.test.ts @@ -18,3 +18,25 @@ it("lists repositories as JSON", async ({ expect, prismic, repo }) => { const parsed = JSON.parse(stdout); expect(parsed).toEqual(expect.arrayContaining([expect.objectContaining({ domain: repo })])); }); + +it("lists the one repository a Write API token can write to", async ({ + expect, + prismic, + repo, + host, + writeToken, +}) => { + const { stdout, stderr, exitCode } = await prismic("repo", ["list", "--json"], { + nodeOptions: { env: { PRISMIC_TOKEN: writeToken } }, + }); + expect(exitCode, stderr).toBe(0); + const parsed: unknown = JSON.parse(stdout); + expect(parsed).toEqual([ + { + domain: repo, + name: expect.any(String), + role: expect.any(String), + url: `https://${repo}.${host}/`, + }, + ]); +});