Skip to content

Commit

Permalink
fix: support expired preview token API error
Browse files Browse the repository at this point in the history
  • Loading branch information
angeloashmore committed Oct 10, 2023
1 parent 163d03e commit 66c33d0
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 6 deletions.
24 changes: 18 additions & 6 deletions src/createClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type { PrismicDocument } from "./types/value/document";
import { ForbiddenError } from "./errors/ForbiddenError";
import { NotFoundError } from "./errors/NotFoundError";
import { ParsingError } from "./errors/ParsingError";
import { PreviewTokenExpiredError } from "./errors/PreviewTokenExpired";
import { PrismicError } from "./errors/PrismicError";
import { RefExpiredError } from "./errors/RefExpiredError";
import { RefNotFoundError } from "./errors/RefNotFoundError";
Expand Down Expand Up @@ -1912,15 +1913,26 @@ export class Client<TDocuments extends PrismicDocument = PrismicDocument> {
// - Incorrect repository name (this response has an empty body)
// - Ref does not exist
case 404: {
if (res.json && res.json.type === "api_notfound_error") {
if (res.json === undefined) {
throw new NotFoundError(
`Prismic repository not found. Check that "${this.endpoint}" is pointing to the correct repository.`,
url,
undefined,
);
}

if (res.json.type === "api_notfound_error") {
throw new RefNotFoundError(res.json.message, url, res.json);
}

throw new NotFoundError(
`Prismic repository not found. Check that "${this.endpoint}" is pointing to the correct repository.`,
url,
undefined, // res.json is empty
);
if (
res.json.type === "api_security_error" &&
/preview token.*expired/i.test(res.json.message)
) {
throw new PreviewTokenExpiredError(res.json.message, url, res.json);
}

throw new NotFoundError(res.json.message, url, res.json);
}

// Gone
Expand Down
12 changes: 12 additions & 0 deletions src/errors/PreviewTokenExpired.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ForbiddenError } from "./ForbiddenError";

type PreviewTokenExpiredErrorAPIResponse = {
type: "api_security_error";
message: string;
};

// This error extends `ForbiddenError` for backwards compatibility.
// TODO: Extend this error from `PrismicError` in v8.
export class PreviewTokenExpiredError<
TResponse = PreviewTokenExpiredErrorAPIResponse,
> extends ForbiddenError<TResponse> {}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export { ForbiddenError } from "./errors/ForbiddenError";
export { NotFoundError } from "./errors/NotFoundError";
export { RefNotFoundError } from "./errors/RefNotFoundError";
export { RefExpiredError } from "./errors/RefExpiredError";
export { PreviewTokenExpiredError } from "./errors/PreviewTokenExpired";
export { ParsingError } from "./errors/ParsingError";

//=============================================================================
Expand Down
54 changes: 54 additions & 0 deletions test/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,60 @@ it("throws RefExpiredError if ref is expired", async (ctx) => {
);
});

it("throws PreviewTokenExpiredError if preview token is expired", async (ctx) => {
const queryResponse = {
type: "api_security_error",
message: "This preview token has expired",
oauth_initiate: "https://qwerty.prismic.io/auth",
oauth_token: "https://qwerty.prismic.io/auth/token",
};

mockPrismicRestAPIV2({ ctx });

const client = createTestClient();

const queryEndpoint = new URL(
"./documents/search",
`${client.endpoint}/`,
).toString();

ctx.server.use(
msw.rest.get(queryEndpoint, (_req, res, ctx) => {
return res(ctx.status(404), ctx.json(queryResponse));
}),
);

await expect(() => client.get()).rejects.toThrowError(queryResponse.message);
await expect(() => client.get()).rejects.toThrowError(
prismic.PreviewTokenExpiredError,
);
});

it("throws NotFoundError if the 404 error is unknown", async (ctx) => {
const queryResponse = {
type: "unknown_type",
message: "message",
};

mockPrismicRestAPIV2({ ctx });

const client = createTestClient();

const queryEndpoint = new URL(
"./documents/search",
`${client.endpoint}/`,
).toString();

ctx.server.use(
msw.rest.get(queryEndpoint, (_req, res, ctx) => {
return res(ctx.status(404), ctx.json(queryResponse));
}),
);

await expect(() => client.get()).rejects.toThrowError(queryResponse.message);
await expect(() => client.get()).rejects.toThrowError(prismic.NotFoundError);
});

it("retries after `retry-after` milliseconds if response code is 429", async (ctx) => {
const retryAfter = 200; // ms
/**
Expand Down

0 comments on commit 66c33d0

Please sign in to comment.