diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index f361f090..01b89512 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: f42cb8e6-e2ce-4565-b975-5a9f38b94d5a management: - docChecksum: 251a87fb7643cd585e4ddf956bb1ae1f - docVersion: 1.1.23 - speakeasyVersion: 1.555.3 - generationVersion: 2.620.2 - releaseVersion: 0.25.0 - configChecksum: 3cf3f043a49108bf9cbc7c2f2476b151 + docChecksum: 7c9084aa5b0e10020a8f9e2954f0637a + docVersion: 1.1.25 + speakeasyVersion: 1.568.1 + generationVersion: 2.634.1 + releaseVersion: 0.25.1 + configChecksum: 0197c95e1e5ef91e7b26f9b0cdfe33ef repoURL: https://github.com/Unstructured-IO/unstructured-js-client.git repoSubDirectory: . installationURL: https://github.com/Unstructured-IO/unstructured-js-client @@ -15,8 +15,8 @@ features: typescript: acceptHeaders: 2.81.2 additionalDependencies: 0.1.0 - constsAndDefaults: 0.1.11 - core: 3.21.10 + constsAndDefaults: 0.1.12 + core: 3.21.11 defaultEnabledRetries: 0.1.0 enumUnions: 0.1.0 envVarSecurityUsage: 0.1.2 @@ -32,7 +32,7 @@ features: retries: 2.83.0 sdkHooks: 0.3.0 serverIDs: 2.81.2 - unions: 2.85.8 + unions: 2.85.11 uploadStreams: 0.1.0 generatedFiles: - .gitattributes @@ -100,9 +100,11 @@ generatedFiles: - src/sdk/models/errors/httpclienterrors.ts - src/sdk/models/errors/httpvalidationerror.ts - src/sdk/models/errors/index.ts + - src/sdk/models/errors/responsevalidationerror.ts - src/sdk/models/errors/sdkerror.ts - src/sdk/models/errors/sdkvalidationerror.ts - src/sdk/models/errors/servererror.ts + - src/sdk/models/errors/unstructuredclienterror.ts - src/sdk/models/operations/index.ts - src/sdk/models/operations/partition.ts - src/sdk/models/shared/index.ts diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index a314bfdc..a761b091 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,21 +1,21 @@ -speakeasyVersion: 1.555.3 +speakeasyVersion: 1.568.1 sources: my-source: sourceNamespace: my-source - sourceRevisionDigest: sha256:8eb1828e2c067201a3e864721b453543815bbbb71fb160723bb331bb01e4d9aa - sourceBlobDigest: sha256:614c15b826e255f33812df0a7bb989a7bfb194167fa111162594664c04c2c5f4 + sourceRevisionDigest: sha256:594365bf5284e8d4e6602a17b0cacdd329dff7dcb7b1deb59777c08127b1743d + sourceBlobDigest: sha256:f4c50c20ad68fa323d17d43c86d87f2ecc0d7c90c837ff57f9e05812e494f982 tags: - latest - - speakeasy-sdk-regen-1749083555 - - 1.1.23 + - speakeasy-sdk-regen-1749947818 + - 1.1.25 targets: unstructed-typescript: source: my-source sourceNamespace: my-source - sourceRevisionDigest: sha256:8eb1828e2c067201a3e864721b453543815bbbb71fb160723bb331bb01e4d9aa - sourceBlobDigest: sha256:614c15b826e255f33812df0a7bb989a7bfb194167fa111162594664c04c2c5f4 + sourceRevisionDigest: sha256:594365bf5284e8d4e6602a17b0cacdd329dff7dcb7b1deb59777c08127b1743d + sourceBlobDigest: sha256:f4c50c20ad68fa323d17d43c86d87f2ecc0d7c90c837ff57f9e05812e494f982 codeSamplesNamespace: my-source-typescript-code-samples - codeSamplesRevisionDigest: sha256:145ca0fb688e7d825c8f66ba00ecfee5a960ce4ad2c9a07c0e7683306d0b92e2 + codeSamplesRevisionDigest: sha256:ed0de85af2807af3b8511f78ce04c3da0687d34ce8d73068430ffd80a7b2e479 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/RELEASES.md b/RELEASES.md index 194b4b56..720d1eb8 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -614,4 +614,14 @@ Based on: ### Generated - [typescript v0.25.0] . ### Releases -- [NPM v0.25.0] https://www.npmjs.com/package/unstructured-client/v/0.25.0 - . \ No newline at end of file +- [NPM v0.25.0] https://www.npmjs.com/package/unstructured-client/v/0.25.0 - . + +## 2025-06-24 00:32:46 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.568.1 (2.634.1) https://github.com/speakeasy-api/speakeasy +### Generated +- [typescript v0.25.1] . +### Releases +- [NPM v0.25.1] https://www.npmjs.com/package/unstructured-client/v/0.25.1 - . \ No newline at end of file diff --git a/gen.yaml b/gen.yaml index ad5ca0af..8923f1ca 100644 --- a/gen.yaml +++ b/gen.yaml @@ -14,7 +14,7 @@ generation: oAuth2ClientCredentialsEnabled: false oAuth2PasswordEnabled: false typescript: - version: 0.25.0 + version: 0.25.1 additionalDependencies: dependencies: async: ^3.2.5 @@ -25,7 +25,9 @@ typescript: peerDependencies: {} additionalPackageJSON: {} author: Unstructured + baseErrorName: UnstructuredClientError clientServerStatusCodesAsErrors: true + constFieldsAlwaysOptional: true defaultErrorName: SDKError enableCustomCodeRegions: false enableMCPServer: true diff --git a/jsr.json b/jsr.json index d9bb297e..f72d1bab 100644 --- a/jsr.json +++ b/jsr.json @@ -2,7 +2,7 @@ { "name": "unstructured-client", - "version": "0.25.0", + "version": "0.25.1", "exports": { ".": "./src/index.ts", "./sdk/models/errors": "./src/sdk/models/errors/index.ts", diff --git a/package-lock.json b/package-lock.json index f5bbd3b4..c718e41e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "unstructured-client", - "version": "0.25.0", + "version": "0.25.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "unstructured-client", - "version": "0.25.0", + "version": "0.25.1", "dependencies": { "async": "^3.2.5", "pdf-lib": "^1.17.1" diff --git a/package.json b/package.json index 7acf62a4..26122a75 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unstructured-client", - "version": "0.25.0", + "version": "0.25.1", "author": "Unstructured", "type": "module", "bin": { diff --git a/src/funcs/generalPartition.ts b/src/funcs/generalPartition.ts index 47898d0c..38d19649 100644 --- a/src/funcs/generalPartition.ts +++ b/src/funcs/generalPartition.ts @@ -4,7 +4,10 @@ import { UnstructuredClientCore } from "../core.js"; import { appendForm, encodeSimple } from "../lib/encodings.js"; -import { readableStreamToArrayBuffer } from "../lib/files.js"; +import { + getContentTypeFromFileName, + readableStreamToArrayBuffer, +} from "../lib/files.js"; import * as M from "../lib/matchers.js"; import { compactMap } from "../lib/primitives.js"; import { safeParse } from "../lib/schemas.js"; @@ -19,8 +22,9 @@ import { UnexpectedClientError, } from "../sdk/models/errors/httpclienterrors.js"; import * as errors from "../sdk/models/errors/index.js"; -import { SDKError } from "../sdk/models/errors/sdkerror.js"; +import { ResponseValidationError } from "../sdk/models/errors/responsevalidationerror.js"; import { SDKValidationError } from "../sdk/models/errors/sdkvalidationerror.js"; +import { UnstructuredClientError } from "../sdk/models/errors/unstructuredclienterror.js"; import * as operations from "../sdk/models/operations/index.js"; import { APICall, APIPromise } from "../sdk/types/async.js"; import { isBlobLike } from "../sdk/types/blobs.js"; @@ -47,13 +51,14 @@ export function generalPartition( operations.PartitionResponse, | errors.HTTPValidationError | errors.ServerError - | SDKError - | SDKValidationError - | UnexpectedClientError - | InvalidRequestError + | UnstructuredClientError + | ResponseValidationError + | ConnectionError | RequestAbortedError | RequestTimeoutError - | ConnectionError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError > > { return new APIPromise($do( @@ -73,13 +78,14 @@ async function $do( operations.PartitionResponse, | errors.HTTPValidationError | errors.ServerError - | SDKError - | SDKValidationError - | UnexpectedClientError - | InvalidRequestError + | UnstructuredClientError + | ResponseValidationError + | ConnectionError | RequestAbortedError | RequestTimeoutError - | ConnectionError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError >, APICall, ] @@ -101,14 +107,25 @@ async function $do( const buffer = await readableStreamToArrayBuffer( payload.partition_parameters.files.content, ); - const blob = new Blob([buffer], { type: "application/octet-stream" }); - appendForm(body, "files", blob); + const contentType = + getContentTypeFromFileName(payload.partition_parameters.files.fileName) + || "application/octet-stream"; + const blob = new Blob([buffer], { type: contentType }); + appendForm( + body, + "files", + blob, + payload.partition_parameters.files.fileName, + ); } else { + const contentType = + getContentTypeFromFileName(payload.partition_parameters.files.fileName) + || "application/octet-stream"; appendForm( body, "files", new Blob([payload.partition_parameters.files.content], { - type: "application/octet-stream", + type: contentType, }), payload.partition_parameters.files.fileName, ); @@ -415,13 +432,14 @@ async function $do( operations.PartitionResponse, | errors.HTTPValidationError | errors.ServerError - | SDKError - | SDKValidationError - | UnexpectedClientError - | InvalidRequestError + | UnstructuredClientError + | ResponseValidationError + | ConnectionError | RequestAbortedError | RequestTimeoutError - | ConnectionError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError >( M.json(200, operations.PartitionResponse$inboundSchema), M.text(200, operations.PartitionResponse$inboundSchema, { @@ -430,7 +448,7 @@ async function $do( M.jsonErr(422, errors.HTTPValidationError$inboundSchema), M.fail("4XX"), M.jsonErr("5XX", errors.ServerError$inboundSchema), - )(response, { extraFields: responseFields }); + )(response, req, { extraFields: responseFields }); if (!result.ok) { return [result, { status: "complete", request: req, response }]; } diff --git a/src/lib/config.ts b/src/lib/config.ts index e3b81918..0d782145 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -67,9 +67,9 @@ export function serverURLFromOptions(options: SDKOptions): URL | null { export const SDK_METADATA = { language: "typescript", - openapiDocVersion: "1.1.23", - sdkVersion: "0.25.0", - genVersion: "2.620.2", + openapiDocVersion: "1.1.25", + sdkVersion: "0.25.1", + genVersion: "2.634.1", userAgent: - "speakeasy-sdk/typescript 0.25.0 2.620.2 1.1.23 unstructured-client", + "speakeasy-sdk/typescript 0.25.1 2.634.1 1.1.25 unstructured-client", } as const; diff --git a/src/lib/files.ts b/src/lib/files.ts index 59d15f09..0344cd04 100644 --- a/src/lib/files.ts +++ b/src/lib/files.ts @@ -38,3 +38,45 @@ export async function readableStreamToArrayBuffer( return concatenatedChunks.buffer as ArrayBuffer; } + +/** + * Determines the MIME content type based on a file's extension. + * Returns null if the extension is not recognized. + */ +export function getContentTypeFromFileName(fileName: string): string | null { + if (!fileName) return null; + + const ext = fileName.toLowerCase().split(".").pop(); + if (!ext) return null; + + const mimeTypes: Record = { + json: "application/json", + xml: "application/xml", + html: "text/html", + htm: "text/html", + txt: "text/plain", + csv: "text/csv", + pdf: "application/pdf", + png: "image/png", + jpg: "image/jpeg", + jpeg: "image/jpeg", + gif: "image/gif", + svg: "image/svg+xml", + js: "application/javascript", + css: "text/css", + zip: "application/zip", + tar: "application/x-tar", + gz: "application/gzip", + mp4: "video/mp4", + mp3: "audio/mpeg", + wav: "audio/wav", + webp: "image/webp", + ico: "image/x-icon", + woff: "font/woff", + woff2: "font/woff2", + ttf: "font/ttf", + otf: "font/otf", + }; + + return mimeTypes[ext] || null; +} diff --git a/src/lib/matchers.ts b/src/lib/matchers.ts index 7deb609f..41b6095f 100644 --- a/src/lib/matchers.ts +++ b/src/lib/matchers.ts @@ -2,12 +2,11 @@ * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. */ +import { ResponseValidationError } from "../sdk/models/errors/responsevalidationerror.js"; import { SDKError } from "../sdk/models/errors/sdkerror.js"; -import { SDKValidationError } from "../sdk/models/errors/sdkvalidationerror.js"; -import { Result } from "../sdk/types/fp.js"; +import { ERR, OK, Result } from "../sdk/types/fp.js"; import { matchResponse, matchStatusCode, StatusCodePredicate } from "./http.js"; import { isPlainObject } from "./is-plain-object.js"; -import { safeParse } from "./schemas.js"; export type Encoding = | "jsonl" @@ -176,17 +175,19 @@ export type MatchedError = Matchers extends Matcher[] : never; export type MatchFunc = ( response: Response, + request: Request, options?: { resultKey?: string; extraFields?: Record }, ) => Promise<[result: Result, raw: unknown]>; export function match( ...matchers: Array> -): MatchFunc { +): MatchFunc { return async function matchFunc( response: Response, + request: Request, options?: { resultKey?: string; extraFields?: Record }, ): Promise< - [result: Result, raw: unknown] + [result: Result, raw: unknown] > { let raw: unknown; let matcher: Matcher | undefined; @@ -205,21 +206,22 @@ export function match( } if (!matcher) { - const responseBody = await response.text(); return [{ ok: false, - error: new SDKError( - "Unexpected API response status or content-type", + error: new SDKError("Unexpected Status or Content-Type", { response, - responseBody, - ), - }, responseBody]; + request, + body: await response.text().catch(() => ""), + }), + }, raw]; } const encoding = matcher.enc; + let body = ""; switch (encoding) { case "json": - raw = await response.json(); + body = await response.text(); + raw = JSON.parse(body); break; case "jsonl": raw = response.body; @@ -231,16 +233,19 @@ export function match( raw = response.body; break; case "text": - raw = await response.text(); + body = await response.text(); + raw = body; break; case "sse": raw = response.body; break; case "nil": - raw = await discardResponseBody(response); + body = await response.text(); + raw = undefined; break; case "fail": - raw = await response.text(); + body = await response.text(); + raw = body; break; default: encoding satisfies never; @@ -250,11 +255,7 @@ export function match( if (matcher.enc === "fail") { return [{ ok: false, - error: new SDKError( - "API error occurred", - response, - typeof raw === "string" ? raw : "", - ), + error: new SDKError("API error occurred", { request, response, body }), }, raw]; } @@ -266,6 +267,9 @@ export function match( ...options?.extraFields, ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null), ...(isPlainObject(raw) ? raw : null), + request$: request, + response$: response, + body$: body, }; } else if (resultKey) { data = { @@ -284,18 +288,20 @@ export function match( } if ("err" in matcher) { - const result = safeParse( + const result = safeParseResponse( data, (v: unknown) => matcher.schema.parse(v), "Response validation failed", + { request, response, body }, ); return [result.ok ? { ok: false, error: result.value } : result, raw]; } else { return [ - safeParse( + safeParseResponse( data, (v: unknown) => matcher.schema.parse(v), "Response validation failed", + { request, response, body }, ), raw, ]; @@ -318,25 +324,22 @@ export function unpackHeaders(headers: Headers): Record { return out; } -/** - * Discards the response body to free up resources. - * - * To learn why this is need, see the undici docs: - * https://undici.nodejs.org/#/?id=garbage-collection - */ -export async function discardResponseBody(res: Response) { - const reader = res.body?.getReader(); - if (reader == null) { - return; - } - +function safeParseResponse( + rawValue: Inp, + fn: (value: Inp) => Out, + errorMessage: string, + httpMeta: { response: Response; request: Request; body: string }, +): Result { try { - let done = false; - while (!done) { - const res = await reader.read(); - done = res.done; - } - } finally { - reader.releaseLock(); + return OK(fn(rawValue)); + } catch (err) { + return ERR( + new ResponseValidationError(errorMessage, { + cause: err, + rawValue, + rawMessage: errorMessage, + ...httpMeta, + }), + ); } } diff --git a/src/lib/security.ts b/src/lib/security.ts index 68fc1337..fc066ae2 100644 --- a/src/lib/security.ts +++ b/src/lib/security.ts @@ -6,8 +6,8 @@ import * as shared from "../sdk/models/shared/index.js"; type OAuth2PasswordFlow = { username: string; - password?: string | undefined; - clientID: string; + password: string; + clientID?: string | undefined; clientSecret?: string | undefined; tokenURL: string; }; diff --git a/src/mcp-server/mcp-server.ts b/src/mcp-server/mcp-server.ts index ee3ca4e9..7b825ff6 100644 --- a/src/mcp-server/mcp-server.ts +++ b/src/mcp-server/mcp-server.ts @@ -19,7 +19,7 @@ const routes = buildRouteMap({ export const app = buildApplication(routes, { name: "mcp", versionInfo: { - currentVersion: "0.25.0", + currentVersion: "0.25.1", }, }); diff --git a/src/mcp-server/server.ts b/src/mcp-server/server.ts index 2d798435..4207fe2d 100644 --- a/src/mcp-server/server.ts +++ b/src/mcp-server/server.ts @@ -27,7 +27,7 @@ export function createMCPServer(deps: { }) { const server = new McpServer({ name: "UnstructuredClient", - version: "0.25.0", + version: "0.25.1", }); const client = new UnstructuredClientCore({ diff --git a/src/sdk/models/errors/httpvalidationerror.ts b/src/sdk/models/errors/httpvalidationerror.ts index 089d6466..1e3ada7b 100644 --- a/src/sdk/models/errors/httpvalidationerror.ts +++ b/src/sdk/models/errors/httpvalidationerror.ts @@ -7,6 +7,7 @@ import { safeParse } from "../../../lib/schemas.js"; import { Result as SafeParseResult } from "../../types/fp.js"; import * as shared from "../shared/index.js"; import { SDKValidationError } from "./sdkvalidationerror.js"; +import { UnstructuredClientError } from "./unstructuredclienterror.js"; export type Detail = Array | string; @@ -14,19 +15,21 @@ export type HTTPValidationErrorData = { detail?: Array | string | undefined; }; -export class HTTPValidationError extends Error { +export class HTTPValidationError extends UnstructuredClientError { detail?: Array | string | undefined; /** The original data that was passed to this error instance. */ data$: HTTPValidationErrorData; - constructor(err: HTTPValidationErrorData) { + constructor( + err: HTTPValidationErrorData, + httpMeta: { response: Response; request: Request; body: string }, + ) { const message = "message" in err && typeof err.message === "string" ? err.message : `API error occurred: ${JSON.stringify(err)}`; - super(message); + super(message, httpMeta); this.data$ = err; - if (err.detail != null) this.detail = err.detail; this.name = "HTTPValidationError"; @@ -82,9 +85,16 @@ export const HTTPValidationError$inboundSchema: z.ZodType< > = z.object({ detail: z.union([z.array(shared.ValidationError$inboundSchema), z.string()]) .optional(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), }) .transform((v) => { - return new HTTPValidationError(v); + return new HTTPValidationError(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); }); /** @internal */ diff --git a/src/sdk/models/errors/index.ts b/src/sdk/models/errors/index.ts index 44b0eef9..f58ecbf4 100644 --- a/src/sdk/models/errors/index.ts +++ b/src/sdk/models/errors/index.ts @@ -4,6 +4,7 @@ export * from "./httpclienterrors.js"; export * from "./httpvalidationerror.js"; +export * from "./responsevalidationerror.js"; export * from "./sdkerror.js"; export * from "./sdkvalidationerror.js"; export * from "./servererror.js"; diff --git a/src/sdk/models/errors/responsevalidationerror.ts b/src/sdk/models/errors/responsevalidationerror.ts new file mode 100644 index 00000000..944fb9a2 --- /dev/null +++ b/src/sdk/models/errors/responsevalidationerror.ts @@ -0,0 +1,50 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod"; +import { formatZodError } from "./sdkvalidationerror.js"; +import { UnstructuredClientError } from "./unstructuredclienterror.js"; + +export class ResponseValidationError extends UnstructuredClientError { + /** + * The raw value that failed validation. + */ + public readonly rawValue: unknown; + + /** + * The raw message that failed validation. + */ + public readonly rawMessage: unknown; + + constructor( + message: string, + extra: { + response: Response; + request: Request; + body: string; + cause: unknown; + rawValue: unknown; + rawMessage: unknown; + }, + ) { + super(message, extra); + this.name = "ResponseValidationError"; + this.cause = extra.cause; + this.rawValue = extra.rawValue; + this.rawMessage = extra.rawMessage; + } + + /** + * Return a pretty-formatted error message if the underlying validation error + * is a ZodError or some other recognized error type, otherwise return the + * default error message. + */ + public pretty(): string { + if (this.cause instanceof z.ZodError) { + return `${this.rawMessage}\n${formatZodError(this.cause)}`; + } else { + return this.toString(); + } + } +} diff --git a/src/sdk/models/errors/sdkerror.ts b/src/sdk/models/errors/sdkerror.ts index ba47f662..3a92258a 100644 --- a/src/sdk/models/errors/sdkerror.ts +++ b/src/sdk/models/errors/sdkerror.ts @@ -2,41 +2,33 @@ * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. */ -export class SDKError extends Error { - /** - * HTTP status code - */ - public readonly statusCode: number; - /** - * HTTP content type - */ - public readonly contentType: string; - /** - * HTTP body - */ - public readonly body: string; - /** - * Raw response - */ - public readonly rawResponse: Response; +import { UnstructuredClientError } from "./unstructuredclienterror.js"; +/** The fallback error class if no more specific error class is matched */ +export class SDKError extends UnstructuredClientError { constructor( message: string, - rawResponse: Response, - body: string = "", + httpMeta: { + response: Response; + request: Request; + body: string; + }, ) { - const statusCode = rawResponse.status; - const contentType = rawResponse.headers.get("content-type") || ""; - const bodyString = body.length > 0 ? `\n${body}` : ""; - super( - `${message}: Status ${statusCode} Content-Type ${contentType} Body ${bodyString}`, - ); - - this.body = body; - this.rawResponse = rawResponse; - this.statusCode = statusCode; - this.contentType = contentType; - + if (message) { + message += `: `; + } + message += `Status ${httpMeta.response.status}`; + const contentType = httpMeta.response.headers.get("content-type") || `""`; + if (contentType !== "application/json") { + message += ` Content-Type ${ + contentType.includes(" ") ? `"${contentType}"` : contentType + }`; + } + const body = httpMeta.body || `""`; + message += body.length > 100 ? "\n" : " "; + message += `Body ${body}`; + message = message.trim(); + super(message, httpMeta); this.name = "SDKError"; } } diff --git a/src/sdk/models/errors/sdkvalidationerror.ts b/src/sdk/models/errors/sdkvalidationerror.ts index 16929b9e..37face8a 100644 --- a/src/sdk/models/errors/sdkvalidationerror.ts +++ b/src/sdk/models/errors/sdkvalidationerror.ts @@ -15,6 +15,18 @@ export class SDKValidationError extends Error { */ public readonly rawMessage: unknown; + // Allows for backwards compatibility for `instanceof` checks of `ResponseValidationError` + static override [Symbol.hasInstance]( + instance: unknown, + ): instance is SDKValidationError { + if (!(instance instanceof Error)) return false; + if (!("rawValue" in instance)) return false; + if (!("rawMessage" in instance)) return false; + if (!("pretty" in instance)) return false; + if (typeof instance.pretty !== "function") return false; + return true; + } + constructor(message: string, cause: unknown, rawValue: unknown) { super(`${message}: ${cause}`); this.name = "SDKValidationError"; diff --git a/src/sdk/models/errors/servererror.ts b/src/sdk/models/errors/servererror.ts index 3b80a19b..d6460277 100644 --- a/src/sdk/models/errors/servererror.ts +++ b/src/sdk/models/errors/servererror.ts @@ -3,24 +3,27 @@ */ import * as z from "zod"; +import { UnstructuredClientError } from "./unstructuredclienterror.js"; export type ServerErrorData = { detail?: string | undefined; }; -export class ServerError extends Error { +export class ServerError extends UnstructuredClientError { detail?: string | undefined; /** The original data that was passed to this error instance. */ data$: ServerErrorData; - constructor(err: ServerErrorData) { + constructor( + err: ServerErrorData, + httpMeta: { response: Response; request: Request; body: string }, + ) { const message = "message" in err && typeof err.message === "string" ? err.message : `API error occurred: ${JSON.stringify(err)}`; - super(message); + super(message, httpMeta); this.data$ = err; - if (err.detail != null) this.detail = err.detail; this.name = "ServerError"; @@ -34,9 +37,16 @@ export const ServerError$inboundSchema: z.ZodType< unknown > = z.object({ detail: z.string().optional(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), }) .transform((v) => { - return new ServerError(v); + return new ServerError(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); }); /** @internal */ diff --git a/src/sdk/models/errors/unstructuredclienterror.ts b/src/sdk/models/errors/unstructuredclienterror.ts new file mode 100644 index 00000000..9ac7584a --- /dev/null +++ b/src/sdk/models/errors/unstructuredclienterror.ts @@ -0,0 +1,35 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/** The base class for all HTTP error responses */ +export class UnstructuredClientError extends Error { + /** HTTP status code */ + public readonly statusCode: number; + /** HTTP body */ + public readonly body: string; + /** HTTP headers */ + public readonly headers: Headers; + /** HTTP content type */ + public readonly contentType: string; + /** Raw response */ + public readonly rawResponse: Response; + + constructor( + message: string, + httpMeta: { + response: Response; + request: Request; + body: string; + }, + ) { + super(message); + this.statusCode = httpMeta.response.status; + this.body = httpMeta.body; + this.headers = httpMeta.response.headers; + this.contentType = httpMeta.response.headers.get("content-type") || ""; + this.rawResponse = httpMeta.response; + + this.name = "UnstructuredClientError"; + } +} diff --git a/src/sdk/types/constdatetime.ts b/src/sdk/types/constdatetime.ts index c0a4409c..eeff4dde 100644 --- a/src/sdk/types/constdatetime.ts +++ b/src/sdk/types/constdatetime.ts @@ -11,5 +11,5 @@ export function constDateTime( return ( typeof v === "string" && new Date(v).getTime() === new Date(val).getTime() ); - }, `Value must be equivelant to ${val}`); + }, `Value must be equivalent to ${val}`); } diff --git a/test/integration/SplitPdfHook.test.ts b/test/integration/SplitPdfHook.test.ts index cea78367..909e01e4 100644 --- a/test/integration/SplitPdfHook.test.ts +++ b/test/integration/SplitPdfHook.test.ts @@ -128,27 +128,6 @@ describe("SplitPdfHook integration tests check splitted file is same as not spli description: "not PDF file", strategy: Strategy.Fast, }, - { - filename: "test/data/fake.doc", - expectedOk: false, - requestsLimit: 1, - description: "fake PDF file (wrong content)", - strategy: Strategy.Fast, - }, - { - filename: "test/data/fake.doc", - expectedOk: false, - requestsLimit: 2, - description: "fake PDF file (wrong content)", - strategy: Strategy.Fast, - }, - { - filename: "test/data/fake.doc", - expectedOk: false, - requestsLimit: 5, - description: "fake PDF file (wrong content)", - strategy: Strategy.Fast, - }, ])( "for request limit $requestsLimit and $description", async ({ filename, expectedOk, requestsLimit, strategy }) => {