UNPKG

@anthropic-ai/sdk

Version:
142 lines (115 loc) • 4.63 kB
import { AnthropicError } from '../../core/error'; // https://url.spec.whatwg.org/#url-scheme-string const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; export const isAbsoluteURL = (url: string): boolean => { return startsWithSchemeRegexp.test(url); }; export let isArray = (val: unknown): val is unknown[] => ((isArray = Array.isArray), isArray(val)); export let isReadonlyArray = isArray as (val: unknown) => val is readonly unknown[]; /** Returns an object if the given value isn't an object, otherwise returns as-is */ export function maybeObj(x: unknown): object { if (typeof x !== 'object') { return {}; } return x ?? {}; } // https://stackoverflow.com/a/34491287 export function isEmptyObj(obj: Object | null | undefined): boolean { if (!obj) return true; for (const _k in obj) return false; return true; } // https://eslint.org/docs/latest/rules/no-prototype-builtins export function hasOwn<T extends object = object>(obj: T, key: PropertyKey): key is keyof T { return Object.prototype.hasOwnProperty.call(obj, key); } export function isObj(obj: unknown): obj is Record<string, unknown> { return obj != null && typeof obj === 'object' && !Array.isArray(obj); } export const ensurePresent = <T>(value: T | null | undefined): T => { if (value == null) { throw new AnthropicError(`Expected a value to be given but received ${value} instead.`); } return value; }; export const validatePositiveInteger = (name: string, n: unknown): number => { if (typeof n !== 'number' || !Number.isInteger(n)) { throw new AnthropicError(`${name} must be an integer`); } if (n < 0) { throw new AnthropicError(`${name} must be a positive integer`); } return n; }; export const CREDENTIAL_OPTIONS = ['apiKey', 'authToken', 'credentials', 'config', 'profile'] as const; export type CredentialOption = (typeof CREDENTIAL_OPTIONS)[number]; export type PlatformCredentials = { /** The first-party credential options the platform client takes. It rejects the rest. */ accepts: readonly CredentialOption[]; unsupportedOptionMessage: (option: CredentialOption) => string; }; /** * Throws when `options` holds a first-party credential option that a platform * client does not accept, so that a new one is rejected until the client opts * in. `null` passes, because the base `withOptions` fills the credential * options it clears with `null`. */ export const rejectUnsupportedCredentials = (options: object, platform: PlatformCredentials): void => { for (const name of CREDENTIAL_OPTIONS) { if (!platform.accepts.includes(name) && (options as Record<string, unknown>)[name] != null) { throw new AnthropicError(platform.unsupportedOptionMessage(name)); } } }; export const coerceInteger = (value: unknown): number => { if (typeof value === 'number') return Math.round(value); if (typeof value === 'string') return parseInt(value, 10); 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 AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`); }; export const coerceBoolean = (value: unknown): boolean => { if (typeof value === 'boolean') return value; if (typeof value === 'string') return value === 'true'; return Boolean(value); }; export const maybeCoerceInteger = (value: unknown): number | undefined => { if (value == null) { return undefined; } return coerceInteger(value); }; export const maybeCoerceFloat = (value: unknown): number | undefined => { if (value == null) { return undefined; } return coerceFloat(value); }; export const maybeCoerceBoolean = (value: unknown): boolean | undefined => { if (value == null) { return undefined; } return coerceBoolean(value); }; export const safeJSON = (text: string) => { try { return JSON.parse(text); } catch (err) { return undefined; } }; // Gets a value from an object, deletes the key, and returns the value (or undefined if not found) export const pop = <T extends Record<string, any>, K extends string>(obj: T, key: K): T[K] => { const value = obj[key]; delete obj[key]; return value; }; /** * Compile-time exhaustiveness check: passing a value here only type-checks once every * member of its union has been handled. Does nothing at runtime, so unknown values from a * newer API version fall through instead of throwing. */ export function checkNever(_value: never): void {}