diff --git a/src/clients/core.ts b/src/clients/core.ts index 4c35557..0a15359 100644 --- a/src/clients/core.ts +++ b/src/clients/core.ts @@ -1,6 +1,6 @@ import * as z from "zod/mini"; -import { request } from "../lib/request"; +import { NotFoundRequestError, request } from "../lib/request"; const PreviewSchema = z.object({ id: z.string(), @@ -24,11 +24,18 @@ export async function getPreviews(config: { "core/repository/preview_configs", getCoreBaseUrl(repo, host), ); - const response = await request(url, { - credentials: { "prismic-auth": token }, - schema: GetPreviewsResponseSchema, - }); - return response.results; + try { + const response = await request(url, { + credentials: { "prismic-auth": token }, + schema: GetPreviewsResponseSchema, + }); + return response.results; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function addPreview( @@ -41,15 +48,22 @@ export async function addPreview( ): Promise { const { repo, token, host } = config; const url = new URL("previews/new", getCoreBaseUrl(repo, host)); - await request(url, { - method: "POST", - body: { - name: previewConfig.name, - websiteURL: previewConfig.websiteURL, - resolverPath: previewConfig.resolverPath, - }, - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "POST", + body: { + name: previewConfig.name, + websiteURL: previewConfig.websiteURL, + resolverPath: previewConfig.resolverPath, + }, + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function removePreview( @@ -61,11 +75,18 @@ export async function removePreview( `previews/delete/${id}`, getCoreBaseUrl(repo, host), ); - await request(url, { - method: "POST", - body: {}, - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "POST", + body: {}, + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = "Preview not found"; + } + throw error; + } } const RepositoryResponseSchema = z.object({ @@ -79,11 +100,18 @@ export async function getSimulatorUrl(config: { }): Promise { const { repo, token, host } = config; const url = new URL("core/repository", getCoreBaseUrl(repo, host)); - const response = await request(url, { - credentials: { "prismic-auth": token }, - schema: RepositoryResponseSchema, - }); - return response.simulator_url; + try { + const response = await request(url, { + credentials: { "prismic-auth": token }, + schema: RepositoryResponseSchema, + }); + return response.simulator_url; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function setSimulatorUrl( @@ -92,11 +120,18 @@ export async function setSimulatorUrl( ): Promise { const { repo, token, host } = config; const url = new URL("core/repository", getCoreBaseUrl(repo, host)); - await request(url, { - method: "PATCH", - body: { simulator_url: simulatorUrl }, - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "PATCH", + body: { simulator_url: simulatorUrl }, + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } function getCoreBaseUrl(repo: string, host: string): URL { diff --git a/src/clients/custom-types.ts b/src/clients/custom-types.ts index 54db858..7be87d4 100644 --- a/src/clients/custom-types.ts +++ b/src/clients/custom-types.ts @@ -1,6 +1,6 @@ import type { CustomType, SharedSlice } from "@prismicio/types-internal/lib/customtypes"; -import { request } from "../lib/request"; +import { NotFoundRequestError, request } from "../lib/request"; export async function getCustomTypes(config: { repo: string; @@ -10,10 +10,17 @@ export async function getCustomTypes(config: { const { repo, token, host } = config; const customTypesServiceUrl = getCustomTypesServiceUrl(host); const url = new URL("customtypes", customTypesServiceUrl); - const response = await request(url, { - headers: { repository: repo, Authorization: `Bearer ${token}` }, - }); - return response; + try { + const response = await request(url, { + headers: { repository: repo, Authorization: `Bearer ${token}` }, + }); + return response; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function getSlices(config: { @@ -24,10 +31,17 @@ export async function getSlices(config: { const { repo, token, host } = config; const customTypesServiceUrl = getCustomTypesServiceUrl(host); const url = new URL("slices", customTypesServiceUrl); - const response = await request(url, { - headers: { repository: repo, Authorization: `Bearer ${token}` }, - }); - return response; + try { + const response = await request(url, { + headers: { repository: repo, Authorization: `Bearer ${token}` }, + }); + return response; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } function getCustomTypesServiceUrl(host: string): URL { diff --git a/src/clients/docs.ts b/src/clients/docs.ts index 5f7d3da..6b7eb58 100644 --- a/src/clients/docs.ts +++ b/src/clients/docs.ts @@ -1,7 +1,7 @@ import * as z from "zod/mini"; import { DEFAULT_PRISMIC_HOST, env } from "../env"; -import { request } from "../lib/request"; +import { NotFoundRequestError, request } from "../lib/request"; const DocsIndexEntrySchema = z.object({ path: z.string(), @@ -30,15 +30,29 @@ export async function getDocsIndex(): Promise { export async function getDocsPageIndex(path: string): Promise { const url = new URL(`api/index/${path}`, getDocsBaseUrl()); - return await request(url, { schema: DocsPageSchema }); + try { + return await request(url, { schema: DocsPageSchema }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Documentation page not found: ${path}`; + } + throw error; + } } export async function getDocsPageContent(path: string): Promise { const url = new URL(path, getDocsBaseUrl()); - return await request(url, { - headers: { Accept: "text/markdown" }, - schema: z.string(), - }); + try { + return await request(url, { + headers: { Accept: "text/markdown" }, + schema: z.string(), + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Page not found: ${path}`; + } + throw error; + } } function getDocsBaseUrl(): URL { diff --git a/src/clients/locale.ts b/src/clients/locale.ts index 41cf212..fb79ebb 100644 --- a/src/clients/locale.ts +++ b/src/clients/locale.ts @@ -1,6 +1,6 @@ import * as z from "zod/mini"; -import { request } from "../lib/request"; +import { NotFoundRequestError, request } from "../lib/request"; const LocaleSchema = z.object({ id: z.string(), @@ -19,11 +19,18 @@ export async function getLocales(config: { const { repo, token, host } = config; const url = new URL("repository/locales", getLocaleServiceUrl(host)); url.searchParams.set("repository", repo); - const response = await request(url, { - headers: { Authorization: `Bearer ${token}` }, - schema: z.object({ results: z.array(LocaleSchema) }), - }); - return response.results; + try { + const response = await request(url, { + headers: { Authorization: `Bearer ${token}` }, + schema: z.object({ results: z.array(LocaleSchema) }), + }); + return response.results; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function upsertLocale( @@ -33,17 +40,24 @@ export async function upsertLocale( const { repo, token, host } = config; const url = new URL("repository/locales", getLocaleServiceUrl(host)); url.searchParams.set("repository", repo); - const response = await request(url, { - method: "POST", - body: { - id: locale.id, - isMaster: locale.isMaster ?? false, - ...(locale.customName ? { customName: locale.customName } : {}), - }, - headers: { Authorization: `Bearer ${token}` }, - schema: LocaleSchema, - }); - return response; + try { + const response = await request(url, { + method: "POST", + body: { + id: locale.id, + isMaster: locale.isMaster ?? false, + ...(locale.customName ? { customName: locale.customName } : {}), + }, + headers: { Authorization: `Bearer ${token}` }, + schema: LocaleSchema, + }); + return response; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function removeLocale( diff --git a/src/clients/repository.ts b/src/clients/repository.ts index 9036818..351f465 100644 --- a/src/clients/repository.ts +++ b/src/clients/repository.ts @@ -1,6 +1,6 @@ import * as z from "zod/mini"; -import { request } from "../lib/request"; +import { NotFoundRequestError, request } from "../lib/request"; const RepositorySchema = z.object({ quotas: z.optional( @@ -20,14 +20,21 @@ export async function getRepository(config: { const { repo, token, host } = config; const url = getRepositoryServiceUrl(host); url.searchParams.set("repository", repo); - const response = await request(url, { - headers: { - Authorization: `Bearer ${token}`, - repository: repo, - }, - schema: RepositorySchema, - }); - return response; + try { + const response = await request(url, { + headers: { + Authorization: `Bearer ${token}`, + repository: repo, + }, + schema: RepositorySchema, + }); + return response; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } function getRepositoryServiceUrl(host: string): URL { diff --git a/src/clients/wroom.ts b/src/clients/wroom.ts index 69ab897..f148cdd 100644 --- a/src/clients/wroom.ts +++ b/src/clients/wroom.ts @@ -1,6 +1,6 @@ import * as z from "zod/mini"; -import { request } from "../lib/request"; +import { NotFoundRequestError, request } from "../lib/request"; const WebhookTriggersSchema = z.object({ documentsPublished: z.boolean(), @@ -33,11 +33,17 @@ export async function getWebhooks(config: { const { repo, token, host } = config; const wroomUrl = getWroomUrl(repo, host); const url = new URL("app/settings/webhooks", wroomUrl); - const response = await request(url, { - credentials: { "prismic-auth": token }, - schema: z.array(WebhookSchema), - }); - return response; + try { + return await request(url, { + credentials: { "prismic-auth": token }, + schema: z.array(WebhookSchema), + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function createWebhook( @@ -59,11 +65,18 @@ export async function createWebhook( body.set("releasesUpdated", webhookConfig.releasesUpdated.toString()); body.set("tagsCreated", webhookConfig.tagsCreated.toString()); body.set("tagsDeleted", webhookConfig.tagsDeleted.toString()); - await request(url, { - method: "POST", - body, - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "POST", + body, + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export async function updateWebhook( @@ -86,11 +99,18 @@ export async function updateWebhook( body.set("releasesUpdated", webhookConfig.releasesUpdated.toString()); body.set("tagsCreated", webhookConfig.tagsCreated.toString()); body.set("tagsDeleted", webhookConfig.tagsDeleted.toString()); - await request(url, { - method: "POST", - body, - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "POST", + body, + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = "Webhook not found"; + } + throw error; + } } export async function deleteWebhook( @@ -100,10 +120,17 @@ export async function deleteWebhook( const { repo, token, host } = config; const wroomUrl = getWroomUrl(repo, host); const url = new URL(`app/settings/webhooks/${id}/delete`, wroomUrl); - await request(url, { - method: "POST", - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "POST", + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = "Webhook not found"; + } + throw error; + } } const AccessTokenSchema = z.object({ @@ -140,10 +167,17 @@ export async function getOAuthApps(config: { host: string; }): Promise { const url = new URL("settings/security/contentapi", getWroomUrl(config.repo, config.host)); - return await request(url, { - credentials: { "prismic-auth": config.token }, - schema: z.array(OAuthAppSchema), - }); + try { + return await request(url, { + credentials: { "prismic-auth": config.token }, + schema: z.array(OAuthAppSchema), + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${config.repo}`; + } + throw error; + } } export async function createOAuthApp( @@ -151,12 +185,19 @@ export async function createOAuthApp( config: { repo: string; token: string | undefined; host: string }, ): Promise { const url = new URL("settings/security/oauthapp", getWroomUrl(config.repo, config.host)); - return await request(url, { - method: "POST", - body: { app_name: name }, - credentials: { "prismic-auth": config.token }, - schema: OAuthAppSchema, - }); + try { + return await request(url, { + method: "POST", + body: { app_name: name }, + credentials: { "prismic-auth": config.token }, + schema: OAuthAppSchema, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${config.repo}`; + } + throw error; + } } export async function createOAuthAuthorization( @@ -165,12 +206,19 @@ export async function createOAuthAuthorization( config: { repo: string; token: string | undefined; host: string }, ): Promise { const url = new URL("settings/security/authorizations", getWroomUrl(config.repo, config.host)); - return await request(url, { - method: "POST", - body: { app: appId, scope }, - credentials: { "prismic-auth": config.token }, - schema: AccessTokenSchema, - }); + try { + return await request(url, { + method: "POST", + body: { app: appId, scope }, + credentials: { "prismic-auth": config.token }, + schema: AccessTokenSchema, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${config.repo}`; + } + throw error; + } } export async function deleteOAuthAuthorization( @@ -181,10 +229,17 @@ export async function deleteOAuthAuthorization( `settings/security/authorizations/${encodeURIComponent(authId)}`, getWroomUrl(config.repo, config.host), ); - await request(url, { - method: "DELETE", - credentials: { "prismic-auth": config.token }, - }); + try { + await request(url, { + method: "DELETE", + credentials: { "prismic-auth": config.token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = "Token not found"; + } + throw error; + } } export async function getWriteTokens(config: { @@ -193,10 +248,17 @@ export async function getWriteTokens(config: { host: string; }): Promise { const url = new URL("settings/security/customtypesapi", getWroomUrl(config.repo, config.host)); - return await request(url, { - credentials: { "prismic-auth": config.token }, - schema: WriteTokensInfoSchema, - }); + try { + return await request(url, { + credentials: { "prismic-auth": config.token }, + schema: WriteTokensInfoSchema, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${config.repo}`; + } + throw error; + } } export async function createWriteToken( @@ -204,12 +266,19 @@ export async function createWriteToken( config: { repo: string; token: string | undefined; host: string }, ): Promise { const url = new URL("settings/security/token", getWroomUrl(config.repo, config.host)); - return await request(url, { - method: "POST", - body: { app_name: name }, - credentials: { "prismic-auth": config.token }, - schema: WriteTokenSchema, - }); + try { + return await request(url, { + method: "POST", + body: { app_name: name }, + credentials: { "prismic-auth": config.token }, + schema: WriteTokenSchema, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${config.repo}`; + } + throw error; + } } export async function deleteWriteToken( @@ -220,10 +289,17 @@ export async function deleteWriteToken( `settings/security/token/${encodeURIComponent(tokenValue)}`, getWroomUrl(config.repo, config.host), ); - await request(url, { - method: "DELETE", - credentials: { "prismic-auth": config.token }, - }); + try { + await request(url, { + method: "DELETE", + credentials: { "prismic-auth": config.token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Token not found: ${tokenValue}`; + } + throw error; + } } export async function checkIsDomainAvailable(config: { @@ -269,11 +345,18 @@ export async function getRepositoryAccess(config: { }): Promise { const { repo, token, host } = config; const url = new URL("syncState", getWroomUrl(repo, host)); - const response = await request(url, { - credentials: { "prismic-auth": token }, - schema: SyncStateSchema, - }); - return response.repository.api_access; + try { + const response = await request(url, { + credentials: { "prismic-auth": token }, + schema: SyncStateSchema, + }); + return response.repository.api_access; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } export type RepositoryAccessLevel = "private" | "public" | "open"; @@ -284,11 +367,18 @@ export async function setRepositoryAccess( ): Promise { const { repo, token, host } = config; const url = new URL("settings/security/apiaccess", getWroomUrl(repo, host)); - await request(url, { - method: "POST", - body: { api_access: level }, - credentials: { "prismic-auth": token }, - }); + try { + await request(url, { + method: "POST", + body: { api_access: level }, + credentials: { "prismic-auth": token }, + }); + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } const SetNameResponseSchema = z.object({ @@ -305,13 +395,20 @@ export async function setRepositoryName( const url = new URL("app/settings/repository", getWroomUrl(repo, host)); const formData = new FormData(); formData.set("displayname", name); - const response = await request(url, { - method: "POST", - body: formData, - credentials: { "prismic-auth": token }, - schema: SetNameResponseSchema, - }); - return response.repository.name; + try { + const response = await request(url, { + method: "POST", + body: formData, + credentials: { "prismic-auth": token }, + schema: SetNameResponseSchema, + }); + return response.repository.name; + } catch (error) { + if (error instanceof NotFoundRequestError) { + error.message = `Repository not found: ${repo}`; + } + throw error; + } } function getDashboardUrl(host: string): URL { diff --git a/src/commands/docs-list.ts b/src/commands/docs-list.ts index 9e3b54b..548f501 100644 --- a/src/commands/docs-list.ts +++ b/src/commands/docs-list.ts @@ -1,7 +1,7 @@ import { getDocsIndex, getDocsPageIndex } from "../clients/docs"; import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; -import { NotFoundRequestError, UnknownRequestError } from "../lib/request"; +import { UnknownRequestError } from "../lib/request"; import { formatTable } from "../lib/string"; const config = { @@ -31,9 +31,6 @@ export default createCommand(config, async ({ positionals, values }) => { try { entry = await getDocsPageIndex(path); } catch (error) { - if (error instanceof NotFoundRequestError) { - throw new CommandError(`Documentation page not found: ${path}`); - } if (error instanceof UnknownRequestError) { const message = await error.text(); throw new CommandError(`Failed to fetch documentation index: ${message}`); diff --git a/src/commands/docs-view.ts b/src/commands/docs-view.ts index c1b7a8a..ec22268 100644 --- a/src/commands/docs-view.ts +++ b/src/commands/docs-view.ts @@ -3,7 +3,7 @@ import GithubSlugger from "github-slugger"; import { getDocsPageContent } from "../clients/docs"; import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; -import { NotFoundRequestError, UnknownRequestError } from "../lib/request"; +import { UnknownRequestError } from "../lib/request"; const config = { name: "prismic docs view", @@ -35,9 +35,6 @@ export default createCommand(config, async ({ positionals, values }) => { try { markdown = await getDocsPageContent(path); } catch (error) { - if (error instanceof NotFoundRequestError) { - throw new CommandError(`Page not found: ${path}`); - } if (error instanceof UnknownRequestError) { const message = await error.text(); throw new CommandError(`Failed to fetch page: ${message}`); diff --git a/src/commands/init.ts b/src/commands/init.ts index 4a184bc..510ca22 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -16,7 +16,10 @@ import { DEFAULT_PRISMIC_HOST } from "../env"; import { openBrowser } from "../lib/browser"; import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { installDependencies } from "../lib/packageJson"; -import { ForbiddenRequestError, UnauthorizedRequestError } from "../lib/request"; +import { + ForbiddenRequestError, + UnauthorizedRequestError, +} from "../lib/request"; import { checkIsTypeBuilderEnabled, TypeBuilderRequiredError } from "../project"; import { syncCustomTypes, syncSlices } from "./sync"; diff --git a/src/commands/locale-list.ts b/src/commands/locale-list.ts index c235cef..5ef0983 100644 --- a/src/commands/locale-list.ts +++ b/src/commands/locale-list.ts @@ -1,7 +1,8 @@ import { getHost, getToken } from "../auth"; import { getLocales } from "../clients/locale"; -import { createCommand, type CommandConfig } from "../lib/command"; +import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; +import { UnknownRequestError } from "../lib/request"; import { formatTable } from "../lib/string"; import { getRepositoryName } from "../project"; @@ -25,7 +26,16 @@ export default createCommand(config, async ({ values }) => { const token = await getToken(); const host = await getHost(); - const locales = await getLocales({ repo, token, host }); + let locales; + try { + locales = await getLocales({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to list locales: ${message}`); + } + throw error; + } if (json) { console.info(stringify(locales)); diff --git a/src/commands/locale-set-master.ts b/src/commands/locale-set-master.ts index 49af790..1eb7380 100644 --- a/src/commands/locale-set-master.ts +++ b/src/commands/locale-set-master.ts @@ -27,7 +27,17 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const locales = await getLocales({ repo, token, host }); + let locales; + try { + locales = await getLocales({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to set master locale: ${message}`); + } + throw error; + } + const locale = locales.find((l) => l.id === code); if (!locale) { diff --git a/src/commands/preview-list.ts b/src/commands/preview-list.ts index bc6da3f..e7f9d25 100644 --- a/src/commands/preview-list.ts +++ b/src/commands/preview-list.ts @@ -1,7 +1,8 @@ import { getHost, getToken } from "../auth"; import { getPreviews, getSimulatorUrl } from "../clients/core"; -import { createCommand, type CommandConfig } from "../lib/command"; +import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; +import { UnknownRequestError } from "../lib/request"; import { formatTable } from "../lib/string"; import { getRepositoryName } from "../project"; @@ -25,10 +26,20 @@ export default createCommand(config, async ({ values }) => { const token = await getToken(); const host = await getHost(); - const [previews, simulatorUrl] = await Promise.all([ - getPreviews({ repo, token, host }), - getSimulatorUrl({ repo, token, host }), - ]); + let previews; + let simulatorUrl; + try { + [previews, simulatorUrl] = await Promise.all([ + getPreviews({ repo, token, host }), + getSimulatorUrl({ repo, token, host }), + ]); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to list previews: ${message}`); + } + throw error; + } if (json) { console.info( diff --git a/src/commands/preview-remove.ts b/src/commands/preview-remove.ts index 7b95c6a..6943c66 100644 --- a/src/commands/preview-remove.ts +++ b/src/commands/preview-remove.ts @@ -27,7 +27,17 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const previews = await getPreviews({ repo, token, host }); + let previews; + try { + previews = await getPreviews({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to remove preview: ${message}`); + } + throw error; + } + const preview = previews.find((p) => p.url === previewUrl); if (!preview) { throw new CommandError(`Preview not found: ${previewUrl}`); diff --git a/src/commands/token-create.ts b/src/commands/token-create.ts index 6c33a00..73e25c0 100644 --- a/src/commands/token-create.ts +++ b/src/commands/token-create.ts @@ -6,6 +6,7 @@ import { getOAuthApps, } from "../clients/wroom"; import { CommandError, createCommand, type CommandConfig } from "../lib/command"; +import { UnknownRequestError } from "../lib/request"; import { getRepositoryName } from "../project"; const CLI_APP_NAME = "Prismic CLI"; @@ -38,18 +39,26 @@ export default createCommand(config, async ({ values }) => { const token = await getToken(); const host = await getHost(); - if (write) { - const writeToken = await createWriteToken(CLI_APP_NAME, { repo, token, host }); - console.info(`Token created: ${writeToken.token}`); - } else { - const scope = allowReleases ? "master+releases" : "master"; + try { + if (write) { + const writeToken = await createWriteToken(CLI_APP_NAME, { repo, token, host }); + console.info(`Token created: ${writeToken.token}`); + } else { + const scope = allowReleases ? "master+releases" : "master"; - // Find or create the CLI OAuth app. - const apps = await getOAuthApps({ repo, token, host }); - let app = apps.find((a) => a.name === CLI_APP_NAME); - if (!app) app = await createOAuthApp(CLI_APP_NAME, { repo, token, host }); + // Find or create the CLI OAuth app. + const apps = await getOAuthApps({ repo, token, host }); + let app = apps.find((a) => a.name === CLI_APP_NAME); + if (!app) app = await createOAuthApp(CLI_APP_NAME, { repo, token, host }); - const accessToken = await createOAuthAuthorization(app.id, scope, { repo, token, host }); - console.info(`Token created: ${accessToken.token}`); + const accessToken = await createOAuthAuthorization(app.id, scope, { repo, token, host }); + console.info(`Token created: ${accessToken.token}`); + } + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to create token: ${message}`); + } + throw error; } }); diff --git a/src/commands/token-delete.ts b/src/commands/token-delete.ts index 20f8682..72b4a68 100644 --- a/src/commands/token-delete.ts +++ b/src/commands/token-delete.ts @@ -6,6 +6,7 @@ import { getWriteTokens, } from "../clients/wroom"; import { CommandError, createCommand, type CommandConfig } from "../lib/command"; +import { UnknownRequestError } from "../lib/request"; import { getRepositoryName } from "../project"; const config = { @@ -31,16 +32,34 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const [apps, writeTokensInfo] = await Promise.all([ - getOAuthApps({ repo, token, host }), - getWriteTokens({ repo, token, host }), - ]); + let apps; + let writeTokensInfo; + try { + [apps, writeTokensInfo] = await Promise.all([ + getOAuthApps({ repo, token, host }), + getWriteTokens({ repo, token, host }), + ]); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to delete token: ${message}`); + } + throw error; + } // Search access tokens const accessTokenAuths = apps.flatMap((app) => app.wroom_auths); const accessToken = accessTokenAuths.find((auth) => auth.token === tokenValue); if (accessToken) { - await deleteOAuthAuthorization(accessToken.id, { repo, token, host }); + try { + await deleteOAuthAuthorization(accessToken.id, { repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to delete token: ${message}`); + } + throw error; + } console.info("Token deleted"); return; } @@ -48,7 +67,15 @@ export default createCommand(config, async ({ positionals, values }) => { // Search write tokens const writeToken = writeTokensInfo.tokens.find((t) => t.token === tokenValue); if (writeToken) { - await deleteWriteToken(writeToken.token, { repo, token, host }); + try { + await deleteWriteToken(writeToken.token, { repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to delete token: ${message}`); + } + throw error; + } console.info("Token deleted"); return; } diff --git a/src/commands/token-list.ts b/src/commands/token-list.ts index 41386c2..7687e1b 100644 --- a/src/commands/token-list.ts +++ b/src/commands/token-list.ts @@ -1,7 +1,8 @@ import { getHost, getToken } from "../auth"; import { getOAuthApps, getWriteTokens } from "../clients/wroom"; -import { createCommand, type CommandConfig } from "../lib/command"; +import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; +import { UnknownRequestError } from "../lib/request"; import { formatTable } from "../lib/string"; import { getRepositoryName } from "../project"; @@ -25,10 +26,20 @@ export default createCommand(config, async ({ values }) => { const token = await getToken(); const host = await getHost(); - const [apps, writeTokensInfo] = await Promise.all([ - getOAuthApps({ repo, token, host }), - getWriteTokens({ repo, token, host }), - ]); + let apps; + let writeTokensInfo; + try { + [apps, writeTokensInfo] = await Promise.all([ + getOAuthApps({ repo, token, host }), + getWriteTokens({ repo, token, host }), + ]); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to list tokens: ${message}`); + } + throw error; + } const accessTokens = apps.flatMap((app) => app.wroom_auths.map((auth) => ({ diff --git a/src/commands/webhook-disable.ts b/src/commands/webhook-disable.ts index 060c882..ae7268a 100644 --- a/src/commands/webhook-disable.ts +++ b/src/commands/webhook-disable.ts @@ -26,7 +26,17 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const webhooks = await getWebhooks({ repo, token, host }); + let webhooks; + try { + webhooks = await getWebhooks({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to disable webhook: ${message}`); + } + throw error; + } + const webhook = webhooks.find((w) => w.config.url === webhookUrl); if (!webhook) { throw new CommandError(`Webhook not found: ${webhookUrl}`); diff --git a/src/commands/webhook-enable.ts b/src/commands/webhook-enable.ts index e14a77e..c2e58ff 100644 --- a/src/commands/webhook-enable.ts +++ b/src/commands/webhook-enable.ts @@ -26,7 +26,17 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const webhooks = await getWebhooks({ repo, token, host }); + let webhooks; + try { + webhooks = await getWebhooks({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to enable webhook: ${message}`); + } + throw error; + } + const webhook = webhooks.find((w) => w.config.url === webhookUrl); if (!webhook) { throw new CommandError(`Webhook not found: ${webhookUrl}`); diff --git a/src/commands/webhook-list.ts b/src/commands/webhook-list.ts index 2557d7a..09dfdf4 100644 --- a/src/commands/webhook-list.ts +++ b/src/commands/webhook-list.ts @@ -1,7 +1,8 @@ import { getHost, getToken } from "../auth"; import { getWebhooks } from "../clients/wroom"; -import { createCommand, type CommandConfig } from "../lib/command"; +import { CommandError, createCommand, type CommandConfig } from "../lib/command"; import { stringify } from "../lib/json"; +import { UnknownRequestError } from "../lib/request"; import { formatTable } from "../lib/string"; import { getRepositoryName } from "../project"; @@ -24,7 +25,16 @@ export default createCommand(config, async ({ values }) => { const token = await getToken(); const host = await getHost(); - const webhooks = await getWebhooks({ repo, token, host }); + let webhooks; + try { + webhooks = await getWebhooks({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to list webhooks: ${message}`); + } + throw error; + } if (json) { console.info(stringify(webhooks.map((webhook) => webhook.config))); diff --git a/src/commands/webhook-remove.ts b/src/commands/webhook-remove.ts index 22c1b56..6dd4323 100644 --- a/src/commands/webhook-remove.ts +++ b/src/commands/webhook-remove.ts @@ -26,7 +26,17 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const webhooks = await getWebhooks({ repo, token, host }); + let webhooks; + try { + webhooks = await getWebhooks({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to remove webhook: ${message}`); + } + throw error; + } + const webhook = webhooks.find((w) => w.config.url === webhookUrl); if (!webhook) { throw new CommandError(`Webhook not found: ${webhookUrl}`); diff --git a/src/commands/webhook-set-triggers.ts b/src/commands/webhook-set-triggers.ts index bb278b0..9f7111e 100644 --- a/src/commands/webhook-set-triggers.ts +++ b/src/commands/webhook-set-triggers.ts @@ -52,7 +52,17 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const webhooks = await getWebhooks({ repo, token, host }); + let webhooks; + try { + webhooks = await getWebhooks({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to update webhook triggers: ${message}`); + } + throw error; + } + const webhook = webhooks.find((w) => w.config.url === webhookUrl); if (!webhook) { throw new CommandError(`Webhook not found: ${webhookUrl}`); diff --git a/src/commands/webhook-view.ts b/src/commands/webhook-view.ts index ec38e16..99769f7 100644 --- a/src/commands/webhook-view.ts +++ b/src/commands/webhook-view.ts @@ -1,6 +1,7 @@ import { getHost, getToken } from "../auth"; import { getWebhooks, WEBHOOK_TRIGGERS } from "../clients/wroom"; import { CommandError, createCommand, type CommandConfig } from "../lib/command"; +import { UnknownRequestError } from "../lib/request"; import { getRepositoryName } from "../project"; const config = { @@ -25,7 +26,16 @@ export default createCommand(config, async ({ positionals, values }) => { const token = await getToken(); const host = await getHost(); - const webhooks = await getWebhooks({ repo, token, host }); + let webhooks; + try { + webhooks = await getWebhooks({ repo, token, host }); + } catch (error) { + if (error instanceof UnknownRequestError) { + const message = await error.text(); + throw new CommandError(`Failed to fetch webhook details: ${message}`); + } + throw error; + } const webhook = webhooks.find((webhook) => webhook.config.url === webhookUrl); if (!webhook) { diff --git a/src/index.ts b/src/index.ts index e7b022c..af1c3d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,11 @@ import webhook from "./commands/webhook"; import whoami from "./commands/whoami"; import { InvalidPrismicConfig, MissingPrismicConfig } from "./config"; import { CommandError, createCommandRouter } from "./lib/command"; -import { ForbiddenRequestError, UnauthorizedRequestError } from "./lib/request"; +import { + ForbiddenRequestError, + NotFoundRequestError, + UnauthorizedRequestError, +} from "./lib/request"; import { initSegment, segmentIdentify, @@ -183,6 +187,11 @@ async function main(): Promise { return; } + if (error instanceof NotFoundRequestError) { + console.error(error.message || "Not found. Verify the repository and any specified identifiers exist."); + return; + } + if (error instanceof InvalidPrismicConfig) { console.error(`${error.message} Run \`prismic init\` to re-create a config.`); return; diff --git a/src/lib/request.ts b/src/lib/request.ts index 04ba67a..f9c63ad 100644 --- a/src/lib/request.ts +++ b/src/lib/request.ts @@ -91,6 +91,11 @@ export class UnknownRequestError extends RequestError { } export class NotFoundRequestError extends RequestError { name = "NotFoundRequestError"; + + constructor(response: Response) { + super(response); + this.message = ""; + } } export class ForbiddenRequestError extends RequestError { name = "ForbiddenRequestError";