Skip to content

Commit

Permalink
feat(package): export a root error type (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-bot committed Sep 25, 2023
1 parent e6030fa commit 51d8d60
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 14 deletions.
24 changes: 15 additions & 9 deletions src/core.ts
@@ -1,6 +1,12 @@
import { VERSION } from './version';
import { Stream } from './streaming';
import { APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError } from './error';
import {
AnthropicError,
APIError,
APIConnectionError,
APIConnectionTimeoutError,
APIUserAbortError,
} from './error';
import {
kind as shimsKind,
type Readable,
Expand Down Expand Up @@ -440,7 +446,7 @@ export abstract class APIClient {
if (value === null) {
return `${encodeURIComponent(key)}=`;
}
throw new Error(
throw new AnthropicError(
`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`,
);
})
Expand Down Expand Up @@ -599,7 +605,7 @@ export abstract class AbstractPage<Item> implements AsyncIterable<Item> {
async getNextPage(): Promise<this> {
const nextInfo = this.nextPageInfo();
if (!nextInfo) {
throw new Error(
throw new AnthropicError(
'No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.',
);
}
Expand Down Expand Up @@ -925,10 +931,10 @@ export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve

const validatePositiveInteger = (name: string, n: unknown): number => {
if (typeof n !== 'number' || !Number.isInteger(n)) {
throw new Error(`${name} must be an integer`);
throw new AnthropicError(`${name} must be an integer`);
}
if (n < 0) {
throw new Error(`${name} must be a positive integer`);
throw new AnthropicError(`${name} must be a positive integer`);
}
return n;
};
Expand All @@ -939,7 +945,7 @@ export const castToError = (err: any): Error => {
};

export const ensurePresent = <T>(value: T | null | undefined): T => {
if (value == null) throw new Error(`Expected a value to be given but received ${value} instead.`);
if (value == null) throw new AnthropicError(`Expected a value to be given but received ${value} instead.`);
return value;
};

Expand All @@ -962,14 +968,14 @@ export const coerceInteger = (value: unknown): number => {
if (typeof value === 'number') return Math.round(value);
if (typeof value === 'string') return parseInt(value, 10);

throw new Error(`Could not coerce ${value} (type: ${typeof value}) into a number`);
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
};

export const coerceFloat = (value: unknown): number => {
if (typeof value === 'number') return value;
if (typeof value === 'string') return parseFloat(value);

throw new Error(`Could not coerce ${value} (type: ${typeof value}) into a number`);
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
};

export const coerceBoolean = (value: unknown): boolean => {
Expand Down Expand Up @@ -1073,5 +1079,5 @@ export const toBase64 = (str: string | null | undefined): string => {
return btoa(str);
}

throw new Error('Cannot generate b64 string; Expected `Buffer` or `btoa` to be defined');
throw new AnthropicError('Cannot generate b64 string; Expected `Buffer` or `btoa` to be defined');
};
4 changes: 3 additions & 1 deletion src/error.ts
Expand Up @@ -2,7 +2,9 @@

import { castToError, Headers } from './core';

export class APIError extends Error {
export class AnthropicError extends Error {}

export class APIError extends AnthropicError {
readonly status: number | undefined;
readonly headers: Headers | undefined;
readonly error: Object | undefined;
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Expand Up @@ -178,6 +178,7 @@ export class Anthropic extends Core.APIClient {
static HUMAN_PROMPT = '\n\nHuman:';
static AI_PROMPT = '\n\nAssistant:';

static AnthropicError = Errors.AnthropicError;
static APIError = Errors.APIError;
static APIConnectionError = Errors.APIConnectionError;
static APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;
Expand All @@ -195,6 +196,7 @@ export class Anthropic extends Core.APIClient {
export const { HUMAN_PROMPT, AI_PROMPT } = Anthropic;

export const {
AnthropicError,
APIError,
APIConnectionError,
APIConnectionTimeoutError,
Expand Down
9 changes: 5 additions & 4 deletions src/streaming.ts
@@ -1,4 +1,5 @@
import { type Response } from './_shims/index';
import { AnthropicError } from './error';

import { safeJSON, createResponseHeaders } from '@anthropic-ai/sdk/core';
import { APIError } from '@anthropic-ai/sdk/error';
Expand Down Expand Up @@ -26,7 +27,7 @@ export class Stream<Item> implements AsyncIterable<Item> {
private async *iterMessages(): AsyncGenerator<ServerSentEvent, void, unknown> {
if (!this.response.body) {
this.controller.abort();
throw new Error(`Attempted to iterate over a response with no body`);
throw new AnthropicError(`Attempted to iterate over a response with no body`);
}
const lineDecoder = new LineDecoder();

Expand Down Expand Up @@ -211,7 +212,7 @@ class LineDecoder {
return Buffer.from(bytes).toString();
}

throw new Error(
throw new AnthropicError(
`Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.`,
);
}
Expand All @@ -223,14 +224,14 @@ class LineDecoder {
return this.textDecoder.decode(bytes);
}

throw new Error(
throw new AnthropicError(
`Unexpected: received non-Uint8Array/ArrayBuffer (${
(bytes as any).constructor.name
}) in a web platform. Please report this error.`,
);
}

throw new Error(
throw new AnthropicError(
`Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`,
);
}
Expand Down

0 comments on commit 51d8d60

Please sign in to comment.