summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-08-27 12:18:09 -0400
committerDax Raad <[email protected]>2025-08-27 12:18:09 -0400
commit0fbd7c84fd9f93f46eea2eec241a6fde07ce0d59 (patch)
tree4704e8ebce75e3c4e2588ebb3b27309ea184ea92
parent5c17ee52c5ad82dd759a777eb3ab613a00d27ddb (diff)
downloadopencode-0fbd7c84fd9f93f46eea2eec241a6fde07ce0d59.tar.gz
opencode-0fbd7c84fd9f93f46eea2eec241a6fde07ce0d59.zip
sdk update
-rw-r--r--bun.lock23
-rw-r--r--packages/plugin/package.json1
-rw-r--r--packages/sdk/js/package.json2
-rw-r--r--packages/sdk/js/src/client.ts4
-rw-r--r--packages/sdk/js/src/gen/client/client.gen.ts (renamed from packages/sdk/js/src/gen/client/client.ts)59
-rw-r--r--packages/sdk/js/src/gen/client/index.ts21
-rw-r--r--packages/sdk/js/src/gen/client/types.gen.ts (renamed from packages/sdk/js/src/gen/client/types.ts)67
-rw-r--r--packages/sdk/js/src/gen/client/utils.gen.ts (renamed from packages/sdk/js/src/gen/client/utils.ts)142
-rw-r--r--packages/sdk/js/src/gen/core/auth.gen.ts (renamed from packages/sdk/js/src/gen/core/auth.ts)2
-rw-r--r--packages/sdk/js/src/gen/core/bodySerializer.gen.ts (renamed from packages/sdk/js/src/gen/core/bodySerializer.ts)6
-rw-r--r--packages/sdk/js/src/gen/core/params.gen.ts (renamed from packages/sdk/js/src/gen/core/params.ts)2
-rw-r--r--packages/sdk/js/src/gen/core/pathSerializer.gen.ts (renamed from packages/sdk/js/src/gen/core/pathSerializer.ts)2
-rw-r--r--packages/sdk/js/src/gen/core/serverSentEvents.gen.ts210
-rw-r--r--packages/sdk/js/src/gen/core/types.gen.ts (renamed from packages/sdk/js/src/gen/core/types.ts)6
-rw-r--r--packages/sdk/js/src/gen/core/utils.gen.ts109
-rw-r--r--packages/sdk/js/src/gen/sdk.gen.ts2
16 files changed, 483 insertions, 175 deletions
diff --git a/bun.lock b/bun.lock
index 2cd807f31..62b2e88fc 100644
--- a/bun.lock
+++ b/bun.lock
@@ -26,7 +26,7 @@
},
"cloud/core": {
"name": "@opencode/cloud-core",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
"@aws-sdk/client-sts": "3.782.0",
"drizzle-orm": "0.41.0",
@@ -40,7 +40,7 @@
},
"cloud/function": {
"name": "@opencode/cloud-function",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
"@ai-sdk/anthropic": "2.0.0",
"@ai-sdk/openai": "2.0.2",
@@ -60,7 +60,7 @@
},
"cloud/web": {
"name": "@opencode/cloud-web",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
"@kobalte/core": "0.13.9",
"@openauthjs/solid": "0.0.0-20250322224806",
@@ -79,7 +79,7 @@
},
"packages/function": {
"name": "@opencode/function",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "22.0.0",
@@ -94,7 +94,7 @@
},
"packages/opencode": {
"name": "opencode",
- "version": "0.5.15",
+ "version": "0.5.28",
"bin": {
"opencode": "./bin/opencode",
},
@@ -144,21 +144,20 @@
},
"packages/plugin": {
"name": "@opencode-ai/plugin",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
"@opencode-ai/sdk": "workspace:*",
},
"devDependencies": {
- "@hey-api/openapi-ts": "0.81.0",
"@tsconfig/node22": "catalog:",
"typescript": "catalog:",
},
},
"packages/sdk/js": {
"name": "@opencode-ai/sdk",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
- "@hey-api/openapi-ts": "0.80.1",
+ "@hey-api/openapi-ts": "0.81.0",
},
"devDependencies": {
"@hey-api/openapi-ts": "0.80.1",
@@ -168,7 +167,7 @@
},
"packages/web": {
"name": "@opencode/web",
- "version": "0.5.15",
+ "version": "0.5.28",
"dependencies": {
"@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1",
@@ -495,7 +494,7 @@
"@hey-api/json-schema-ref-parser": ["@hey-api/[email protected]", "", { "dependencies": { "@jsdevtools/ono": "^7.1.3", "@types/json-schema": "^7.0.15", "js-yaml": "^4.1.0", "lodash": "^4.17.21" } }, "sha512-yktiFZoWPtEW8QKS65eqKwA5MTKp88CyiL8q72WynrBs/73SAaxlSWlA2zW/DZlywZ5hX1OYzrCC0wFdvO9c2w=="],
- "@hey-api/openapi-ts": ["@hey-api/[email protected]", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "js-yaml": "4.1.0", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-PoJukNBkUfHOoMDpN33bBETX49TUhy7Hu8Sa0jslOvFndvZ5VjQr4Nl/Dzjb9LG1Lp5HjybyTJMA6a1zYk/q6A=="],
+ "@hey-api/openapi-ts": ["@hey-api/[email protected]", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-AC478kg36vmmrseLZNFonZ/cmXXmDzW5yWz4PVg1S8ebJsRtVRJ/QU+mtnXfzf9avN2P0pz/AO4WAe4jyFY2gA=="],
"@hono/zod-validator": ["@hono/[email protected]", "", { "peerDependencies": { "hono": ">=3.9.0", "zod": "^3.19.1" } }, "sha512-1rrlBg+EpDPhzOV4hT9pxr5+xDVmKuz6YJl+la7VCwK6ass5ldyKm5fD+umJdV2zhHD6jROoCCv8NbTwyfhT0g=="],
@@ -3211,7 +3210,7 @@
"@openauthjs/solid/@openauthjs/openauth": ["@openauthjs/[email protected]", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-8+Bia559iffrZXfQ0LWXrVVVriochS88pDtB8indyQ1S+40MQgDBu8aBzKt+fgSrTmoQGCTT+wlOXgbjc9qIcw=="],
- "@opencode-ai/sdk/@hey-api/openapi-ts": ["@hey-api/[email protected]", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-AC478kg36vmmrseLZNFonZ/cmXXmDzW5yWz4PVg1S8ebJsRtVRJ/QU+mtnXfzf9avN2P0pz/AO4WAe4jyFY2gA=="],
+ "@opencode-ai/sdk/@hey-api/openapi-ts": ["@hey-api/[email protected]", "", { "dependencies": { "@hey-api/json-schema-ref-parser": "1.0.6", "ansi-colors": "4.1.3", "c12": "2.0.1", "color-support": "1.1.3", "commander": "13.0.0", "handlebars": "4.7.8", "js-yaml": "4.1.0", "open": "10.1.2", "semver": "7.7.2" }, "peerDependencies": { "typescript": "^5.5.3" }, "bin": { "openapi-ts": "bin/index.cjs" } }, "sha512-PoJukNBkUfHOoMDpN33bBETX49TUhy7Hu8Sa0jslOvFndvZ5VjQr4Nl/Dzjb9LG1Lp5HjybyTJMA6a1zYk/q6A=="],
"@opencode/cloud-web/solid-js": ["[email protected]", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw=="],
diff --git a/packages/plugin/package.json b/packages/plugin/package.json
index 9ef1a2a82..887b0a735 100644
--- a/packages/plugin/package.json
+++ b/packages/plugin/package.json
@@ -19,7 +19,6 @@
"@opencode-ai/sdk": "workspace:*"
},
"devDependencies": {
- "@hey-api/openapi-ts": "0.81.0",
"@tsconfig/node22": "catalog:",
"typescript": "catalog:"
}
diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json
index ad54199c3..3f9815017 100644
--- a/packages/sdk/js/package.json
+++ b/packages/sdk/js/package.json
@@ -29,6 +29,6 @@
"@tsconfig/node22": "catalog:"
},
"dependencies": {
- "@hey-api/openapi-ts": "0.80.1"
+ "@hey-api/openapi-ts": "0.81.0"
}
}
diff --git a/packages/sdk/js/src/client.ts b/packages/sdk/js/src/client.ts
index 8346fd8a2..29b9de906 100644
--- a/packages/sdk/js/src/client.ts
+++ b/packages/sdk/js/src/client.ts
@@ -1,8 +1,8 @@
export * from "./gen/types.gen.js"
export { type Config as OpencodeClientConfig, OpencodeClient }
-import { createClient } from "./gen/client/client.js"
-import { type Config } from "./gen/client/types.js"
+import { createClient } from "./gen/client/client.gen.js"
+import { type Config } from "./gen/client/types.gen.js"
import { OpencodeClient } from "./gen/sdk.gen.js"
export function createOpencodeClient(config?: Config) {
diff --git a/packages/sdk/js/src/gen/client/client.ts b/packages/sdk/js/src/gen/client/client.gen.ts
index 46a62694c..34a8d0bec 100644
--- a/packages/sdk/js/src/gen/client/client.ts
+++ b/packages/sdk/js/src/gen/client/client.gen.ts
@@ -1,4 +1,7 @@
-import type { Client, Config, RequestOptions } from "./types.js"
+// This file is auto-generated by @hey-api/openapi-ts
+
+import { createSseClient } from "../core/serverSentEvents.gen.js"
+import type { Client, Config, RequestOptions, ResolvedRequestOptions } from "./types.gen.js"
import {
buildUrl,
createConfig,
@@ -7,7 +10,7 @@ import {
mergeConfigs,
mergeHeaders,
setAuthParams,
-} from "./utils.js"
+} from "./utils.gen.js"
type ReqInit = Omit<RequestInit, "body" | "headers"> & {
body?: any
@@ -24,14 +27,15 @@ export const createClient = (config: Config = {}): Client => {
return getConfig()
}
- const interceptors = createInterceptors<Request, Response, unknown, RequestOptions>()
+ const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>()
- const request: Client["request"] = async (options) => {
+ const beforeRequest = async (options: RequestOptions) => {
const opts = {
..._config,
...options,
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
headers: mergeHeaders(_config.headers, options.headers),
+ serializedBody: undefined,
}
if (opts.security) {
@@ -46,18 +50,26 @@ export const createClient = (config: Config = {}): Client => {
}
if (opts.body && opts.bodySerializer) {
- opts.body = opts.bodySerializer(opts.body)
+ opts.serializedBody = opts.bodySerializer(opts.body)
}
// remove Content-Type header if body is empty to avoid sending invalid requests
- if (opts.body === undefined || opts.body === "") {
+ if (opts.serializedBody === undefined || opts.serializedBody === "") {
opts.headers.delete("Content-Type")
}
const url = buildUrl(opts)
+
+ return { opts, url }
+ }
+
+ const request: Client["request"] = async (options) => {
+ // @ts-expect-error
+ const { opts, url } = await beforeRequest(options)
const requestInit: ReqInit = {
redirect: "follow",
...opts,
+ body: opts.serializedBody,
}
let request = new Request(url, requestInit)
@@ -166,20 +178,35 @@ export const createClient = (config: Config = {}): Client => {
}
}
+ const makeMethod = (method: Required<Config>["method"]) => {
+ const fn = (options: RequestOptions) => request({ ...options, method })
+ fn.sse = async (options: RequestOptions) => {
+ const { opts, url } = await beforeRequest(options)
+ return createSseClient({
+ ...opts,
+ body: opts.body as BodyInit | null | undefined,
+ headers: opts.headers as unknown as Record<string, string>,
+ method,
+ url,
+ })
+ }
+ return fn
+ }
+
return {
buildUrl,
- connect: (options) => request({ ...options, method: "CONNECT" }),
- delete: (options) => request({ ...options, method: "DELETE" }),
- get: (options) => request({ ...options, method: "GET" }),
+ connect: makeMethod("CONNECT"),
+ delete: makeMethod("DELETE"),
+ get: makeMethod("GET"),
getConfig,
- head: (options) => request({ ...options, method: "HEAD" }),
+ head: makeMethod("HEAD"),
interceptors,
- options: (options) => request({ ...options, method: "OPTIONS" }),
- patch: (options) => request({ ...options, method: "PATCH" }),
- post: (options) => request({ ...options, method: "POST" }),
- put: (options) => request({ ...options, method: "PUT" }),
+ options: makeMethod("OPTIONS"),
+ patch: makeMethod("PATCH"),
+ post: makeMethod("POST"),
+ put: makeMethod("PUT"),
request,
setConfig,
- trace: (options) => request({ ...options, method: "TRACE" }),
- }
+ trace: makeMethod("TRACE"),
+ } as Client
}
diff --git a/packages/sdk/js/src/gen/client/index.ts b/packages/sdk/js/src/gen/client/index.ts
index ce89a34cc..06f21e3d8 100644
--- a/packages/sdk/js/src/gen/client/index.ts
+++ b/packages/sdk/js/src/gen/client/index.ts
@@ -1,8 +1,14 @@
-export type { Auth } from "../core/auth.js"
-export type { QuerySerializerOptions } from "../core/bodySerializer.js"
-export { formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer } from "../core/bodySerializer.js"
-export { buildClientParams } from "../core/params.js"
-export { createClient } from "./client.js"
+// This file is auto-generated by @hey-api/openapi-ts
+
+export type { Auth } from "../core/auth.gen.js"
+export type { QuerySerializerOptions } from "../core/bodySerializer.gen.js"
+export {
+ formDataBodySerializer,
+ jsonBodySerializer,
+ urlSearchParamsBodySerializer,
+} from "../core/bodySerializer.gen.js"
+export { buildClientParams } from "../core/params.gen.js"
+export { createClient } from "./client.gen.js"
export type {
Client,
ClientOptions,
@@ -12,7 +18,8 @@ export type {
OptionsLegacyParser,
RequestOptions,
RequestResult,
+ ResolvedRequestOptions,
ResponseStyle,
TDataShape,
-} from "./types.js"
-export { createConfig, mergeHeaders } from "./utils.js"
+} from "./types.gen.js"
+export { createConfig, mergeHeaders } from "./utils.gen.js"
diff --git a/packages/sdk/js/src/gen/client/types.ts b/packages/sdk/js/src/gen/client/types.gen.ts
index f3b116bae..db8e544cf 100644
--- a/packages/sdk/js/src/gen/client/types.ts
+++ b/packages/sdk/js/src/gen/client/types.gen.ts
@@ -1,6 +1,9 @@
-import type { Auth } from "../core/auth.js"
-import type { Client as CoreClient, Config as CoreConfig } from "../core/types.js"
-import type { Middleware } from "./utils.js"
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { Auth } from "../core/auth.gen.js"
+import type { ServerSentEventsOptions, ServerSentEventsResult } from "../core/serverSentEvents.gen.js"
+import type { Client as CoreClient, Config as CoreConfig } from "../core/types.gen.js"
+import type { Middleware } from "./utils.gen.js"
export type ResponseStyle = "data" | "fields"
@@ -49,13 +52,18 @@ export interface Config<T extends ClientOptions = ClientOptions>
}
export interface RequestOptions<
+ TData = unknown,
TResponseStyle extends ResponseStyle = "fields",
ThrowOnError extends boolean = boolean,
Url extends string = string,
> extends Config<{
- responseStyle: TResponseStyle
- throwOnError: ThrowOnError
- }> {
+ responseStyle: TResponseStyle
+ throwOnError: ThrowOnError
+ }>,
+ Pick<
+ ServerSentEventsOptions<TData>,
+ "onSseError" | "onSseEvent" | "sseDefaultRetryDelay" | "sseMaxRetryAttempts" | "sseMaxRetryDelay"
+ > {
/**
* Any body that you want to add to your request.
*
@@ -71,6 +79,14 @@ export interface RequestOptions<
url: Url
}
+export interface ResolvedRequestOptions<
+ TResponseStyle extends ResponseStyle = "fields",
+ ThrowOnError extends boolean = boolean,
+ Url extends string = string,
+> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> {
+ serializedBody?: string
+}
+
export type RequestResult<
TData = unknown,
TError = unknown,
@@ -112,23 +128,36 @@ export interface ClientOptions {
throwOnError?: boolean
}
-type MethodFn = <
+type MethodFnBase = <
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = "fields",
>(
- options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, "method">,
+ options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method">,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>
+type MethodFnServerSentEvents = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = "fields",
+>(
+ options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method">,
+) => Promise<ServerSentEventsResult<TData, TError>>
+
+type MethodFn = MethodFnBase & {
+ sse: MethodFnServerSentEvents
+}
+
type RequestFn = <
TData = unknown,
TError = unknown,
ThrowOnError extends boolean = false,
TResponseStyle extends ResponseStyle = "fields",
>(
- options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, "method"> &
- Pick<Required<RequestOptions<TResponseStyle, ThrowOnError>>, "method">,
+ options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, "method"> &
+ Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, "method">,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>
type BuildUrlFn = <
@@ -143,7 +172,7 @@ type BuildUrlFn = <
) => string
export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & {
- interceptors: Middleware<Request, Response, unknown, RequestOptions>
+ interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>
}
/**
@@ -171,8 +200,10 @@ type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>
export type Options<
TData extends TDataShape = TDataShape,
ThrowOnError extends boolean = boolean,
+ TResponse = unknown,
TResponseStyle extends ResponseStyle = "fields",
-> = OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, "body" | "path" | "query" | "url"> & Omit<TData, "url">
+> = OmitKeys<RequestOptions<TResponse, TResponseStyle, ThrowOnError>, "body" | "path" | "query" | "url"> &
+ Omit<TData, "url">
export type OptionsLegacyParser<
TData = unknown,
@@ -180,12 +211,12 @@ export type OptionsLegacyParser<
TResponseStyle extends ResponseStyle = "fields",
> = TData extends { body?: any }
? TData extends { headers?: any }
- ? OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, "body" | "headers" | "url"> & TData
- : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, "body" | "url"> &
+ ? OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "body" | "headers" | "url"> & TData
+ : OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "body" | "url"> &
TData &
- Pick<RequestOptions<TResponseStyle, ThrowOnError>, "headers">
+ Pick<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "headers">
: TData extends { headers?: any }
- ? OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, "headers" | "url"> &
+ ? OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "headers" | "url"> &
TData &
- Pick<RequestOptions<TResponseStyle, ThrowOnError>, "body">
- : OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, "url"> & TData
+ Pick<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "body">
+ : OmitKeys<RequestOptions<unknown, TResponseStyle, ThrowOnError>, "url"> & TData
diff --git a/packages/sdk/js/src/gen/client/utils.ts b/packages/sdk/js/src/gen/client/utils.gen.ts
index 84648c855..209bfbe8e 100644
--- a/packages/sdk/js/src/gen/client/utils.ts
+++ b/packages/sdk/js/src/gen/client/utils.gen.ts
@@ -1,84 +1,11 @@
-import { getAuthToken } from "../core/auth.js"
-import type { QuerySerializer, QuerySerializerOptions } from "../core/bodySerializer.js"
-import { jsonBodySerializer } from "../core/bodySerializer.js"
-import { serializeArrayParam, serializeObjectParam, serializePrimitiveParam } from "../core/pathSerializer.js"
-import type { Client, ClientOptions, Config, RequestOptions } from "./types.js"
-
-interface PathSerializer {
- path: Record<string, unknown>
- url: string
-}
-
-const PATH_PARAM_RE = /\{[^{}]+\}/g
-
-type ArrayStyle = "form" | "spaceDelimited" | "pipeDelimited"
-type MatrixStyle = "label" | "matrix" | "simple"
-type ArraySeparatorStyle = ArrayStyle | MatrixStyle
+// This file is auto-generated by @hey-api/openapi-ts
-const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
- let url = _url
- const matches = _url.match(PATH_PARAM_RE)
- if (matches) {
- for (const match of matches) {
- let explode = false
- let name = match.substring(1, match.length - 1)
- let style: ArraySeparatorStyle = "simple"
-
- if (name.endsWith("*")) {
- explode = true
- name = name.substring(0, name.length - 1)
- }
-
- if (name.startsWith(".")) {
- name = name.substring(1)
- style = "label"
- } else if (name.startsWith(";")) {
- name = name.substring(1)
- style = "matrix"
- }
-
- const value = path[name]
-
- if (value === undefined || value === null) {
- continue
- }
-
- if (Array.isArray(value)) {
- url = url.replace(match, serializeArrayParam({ explode, name, style, value }))
- continue
- }
-
- if (typeof value === "object") {
- url = url.replace(
- match,
- serializeObjectParam({
- explode,
- name,
- style,
- value: value as Record<string, unknown>,
- valueOnly: true,
- }),
- )
- continue
- }
-
- if (style === "matrix") {
- url = url.replace(
- match,
- `;${serializePrimitiveParam({
- name,
- value: value as string,
- })}`,
- )
- continue
- }
-
- const replaceValue = encodeURIComponent(style === "label" ? `.${value as string}` : (value as string))
- url = url.replace(match, replaceValue)
- }
- }
- return url
-}
+import { getAuthToken } from "../core/auth.gen.js"
+import type { QuerySerializerOptions } from "../core/bodySerializer.gen.js"
+import { jsonBodySerializer } from "../core/bodySerializer.gen.js"
+import { serializeArrayParam, serializeObjectParam, serializePrimitiveParam } from "../core/pathSerializer.gen.js"
+import { getUrl } from "../core/utils.gen.js"
+import type { Client, ClientOptions, Config, RequestOptions } from "./types.gen.js"
export const createQuerySerializer = <T = unknown>({ allowReserved, array, object }: QuerySerializerOptions = {}) => {
const querySerializer = (queryParams: T) => {
@@ -161,6 +88,21 @@ export const getParseAs = (contentType: string | null): Exclude<Config["parseAs"
return
}
+const checkForExistence = (
+ options: Pick<RequestOptions, "auth" | "query"> & {
+ headers: Headers
+ },
+ name?: string,
+): boolean => {
+ if (!name) {
+ return false
+ }
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
+ return true
+ }
+ return false
+}
+
export const setAuthParams = async ({
security,
...options
@@ -169,6 +111,10 @@ export const setAuthParams = async ({
headers: Headers
}) => {
for (const auth of security) {
+ if (checkForExistence(options, auth.name)) {
+ continue
+ }
+
const token = await getAuthToken(auth, options.auth)
if (!token) {
@@ -192,13 +138,11 @@ export const setAuthParams = async ({
options.headers.set(name, token)
break
}
-
- return
}
}
-export const buildUrl: Client["buildUrl"] = (options) => {
- const url = getUrl({
+export const buildUrl: Client["buildUrl"] = (options) =>
+ getUrl({
baseUrl: options.baseUrl as string,
path: options.path,
query: options.query,
@@ -208,36 +152,6 @@ export const buildUrl: Client["buildUrl"] = (options) => {
: createQuerySerializer(options.querySerializer),
url: options.url,
})
- return url
-}
-
-export const getUrl = ({
- baseUrl,
- path,
- query,
- querySerializer,
- url: _url,
-}: {
- baseUrl?: string
- path?: Record<string, unknown>
- query?: Record<string, unknown>
- querySerializer: QuerySerializer
- url: string
-}) => {
- const pathUrl = _url.startsWith("/") ? _url : `/${_url}`
- let url = (baseUrl ?? "") + pathUrl
- if (path) {
- url = defaultPathSerializer({ path, url })
- }
- let search = query ? querySerializer(query) : ""
- if (search.startsWith("?")) {
- search = search.substring(1)
- }
- if (search) {
- url += `?${search}`
- }
- return url
-}
export const mergeConfigs = (a: Config, b: Config): Config => {
const config = { ...a, ...b }
diff --git a/packages/sdk/js/src/gen/core/auth.ts b/packages/sdk/js/src/gen/core/auth.gen.ts
index e496d4557..bc7b230f4 100644
--- a/packages/sdk/js/src/gen/core/auth.ts
+++ b/packages/sdk/js/src/gen/core/auth.gen.ts
@@ -1,3 +1,5 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
export type AuthToken = string | undefined
export interface Auth {
diff --git a/packages/sdk/js/src/gen/core/bodySerializer.ts b/packages/sdk/js/src/gen/core/bodySerializer.gen.ts
index 8a4a13410..066061605 100644
--- a/packages/sdk/js/src/gen/core/bodySerializer.ts
+++ b/packages/sdk/js/src/gen/core/bodySerializer.gen.ts
@@ -1,4 +1,6 @@
-import type { ArrayStyle, ObjectStyle, SerializerOptions } from "./pathSerializer.js"
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { ArrayStyle, ObjectStyle, SerializerOptions } from "./pathSerializer.gen.js"
export type QuerySerializer = (query: Record<string, unknown>) => string
@@ -13,6 +15,8 @@ export interface QuerySerializerOptions {
const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => {
if (typeof value === "string" || value instanceof Blob) {
data.append(key, value)
+ } else if (value instanceof Date) {
+ data.append(key, value.toISOString())
} else {
data.append(key, JSON.stringify(value))
}
diff --git a/packages/sdk/js/src/gen/core/params.ts b/packages/sdk/js/src/gen/core/params.gen.ts
index 0a09619d1..68ad1a778 100644
--- a/packages/sdk/js/src/gen/core/params.ts
+++ b/packages/sdk/js/src/gen/core/params.gen.ts
@@ -1,3 +1,5 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
type Slot = "body" | "headers" | "path" | "query"
export type Field =
diff --git a/packages/sdk/js/src/gen/core/pathSerializer.ts b/packages/sdk/js/src/gen/core/pathSerializer.gen.ts
index 1e27c8d18..96be3bc5a 100644
--- a/packages/sdk/js/src/gen/core/pathSerializer.ts
+++ b/packages/sdk/js/src/gen/core/pathSerializer.gen.ts
@@ -1,3 +1,5 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {}
interface SerializePrimitiveOptions {
diff --git a/packages/sdk/js/src/gen/core/serverSentEvents.gen.ts b/packages/sdk/js/src/gen/core/serverSentEvents.gen.ts
new file mode 100644
index 000000000..8f7fac549
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/serverSentEvents.gen.ts
@@ -0,0 +1,210 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { Config } from "./types.gen.js"
+
+export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, "method"> &
+ Pick<Config, "method" | "responseTransformer" | "responseValidator"> & {
+ /**
+ * Callback invoked when a network or parsing error occurs during streaming.
+ *
+ * This option applies only if the endpoint returns a stream of events.
+ *
+ * @param error The error that occurred.
+ */
+ onSseError?: (error: unknown) => void
+ /**
+ * Callback invoked when an event is streamed from the server.
+ *
+ * This option applies only if the endpoint returns a stream of events.
+ *
+ * @param event Event streamed from the server.
+ * @returns Nothing (void).
+ */
+ onSseEvent?: (event: StreamEvent<TData>) => void
+ /**
+ * Default retry delay in milliseconds.
+ *
+ * This option applies only if the endpoint returns a stream of events.
+ *
+ * @default 3000
+ */
+ sseDefaultRetryDelay?: number
+ /**
+ * Maximum number of retry attempts before giving up.
+ */
+ sseMaxRetryAttempts?: number
+ /**
+ * Maximum retry delay in milliseconds.
+ *
+ * Applies only when exponential backoff is used.
+ *
+ * This option applies only if the endpoint returns a stream of events.
+ *
+ * @default 30000
+ */
+ sseMaxRetryDelay?: number
+ /**
+ * Optional sleep function for retry backoff.
+ *
+ * Defaults to using `setTimeout`.
+ */
+ sseSleepFn?: (ms: number) => Promise<void>
+ url: string
+ }
+
+export interface StreamEvent<TData = unknown> {
+ data: TData
+ event?: string
+ id?: string
+ retry?: number
+}
+
+export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
+ stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext>
+}
+
+export const createSseClient = <TData = unknown>({
+ onSseError,
+ onSseEvent,
+ responseTransformer,
+ responseValidator,
+ sseDefaultRetryDelay,
+ sseMaxRetryAttempts,
+ sseMaxRetryDelay,
+ sseSleepFn,
+ url,
+ ...options
+}: ServerSentEventsOptions): ServerSentEventsResult<TData> => {
+ let lastEventId: string | undefined
+
+ const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)))
+
+ const createStream = async function* () {
+ let retryDelay: number = sseDefaultRetryDelay ?? 3000
+ let attempt = 0
+ const signal = options.signal ?? new AbortController().signal
+
+ while (true) {
+ if (signal.aborted) break
+
+ attempt++
+
+ const headers =
+ options.headers instanceof Headers
+ ? options.headers
+ : new Headers(options.headers as Record<string, string> | undefined)
+
+ if (lastEventId !== undefined) {
+ headers.set("Last-Event-ID", lastEventId)
+ }
+
+ try {
+ const response = await fetch(url, { ...options, headers, signal })
+
+ if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`)
+
+ if (!response.body) throw new Error("No body in SSE response")
+
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader()
+
+ let buffer = ""
+
+ const abortHandler = () => {
+ try {
+ reader.cancel()
+ } catch {
+ // noop
+ }
+ }
+
+ signal.addEventListener("abort", abortHandler)
+
+ try {
+ while (true) {
+ const { done, value } = await reader.read()
+ if (done) break
+ buffer += value
+
+ const chunks = buffer.split("\n\n")
+ buffer = chunks.pop() ?? ""
+
+ for (const chunk of chunks) {
+ const lines = chunk.split("\n")
+ const dataLines: Array<string> = []
+ let eventName: string | undefined
+
+ for (const line of lines) {
+ if (line.startsWith("data:")) {
+ dataLines.push(line.replace(/^data:\s*/, ""))
+ } else if (line.startsWith("event:")) {
+ eventName = line.replace(/^event:\s*/, "")
+ } else if (line.startsWith("id:")) {
+ lastEventId = line.replace(/^id:\s*/, "")
+ } else if (line.startsWith("retry:")) {
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10)
+ if (!Number.isNaN(parsed)) {
+ retryDelay = parsed
+ }
+ }
+ }
+
+ let data: unknown
+ let parsedJson = false
+
+ if (dataLines.length) {
+ const rawData = dataLines.join("\n")
+ try {
+ data = JSON.parse(rawData)
+ parsedJson = true
+ } catch {
+ data = rawData
+ }
+ }
+
+ if (parsedJson) {
+ if (responseValidator) {
+ await responseValidator(data)
+ }
+
+ if (responseTransformer) {
+ data = await responseTransformer(data)
+ }
+ }
+
+ onSseEvent?.({
+ data,
+ event: eventName,
+ id: lastEventId,
+ retry: retryDelay,
+ })
+
+ if (dataLines.length) {
+ yield data as any
+ }
+ }
+ }
+ } finally {
+ signal.removeEventListener("abort", abortHandler)
+ reader.releaseLock()
+ }
+
+ break // exit loop on normal completion
+ } catch (error) {
+ // connection failed or aborted; retry after delay
+ onSseError?.(error)
+
+ if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
+ break // stop after firing error
+ }
+
+ // exponential backoff: double retry each attempt, cap at 30s
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000)
+ await sleep(backoff)
+ }
+ }
+ }
+
+ const stream = createStream()
+
+ return { stream }
+}
diff --git a/packages/sdk/js/src/gen/core/types.ts b/packages/sdk/js/src/gen/core/types.gen.ts
index 3a12e74c6..16408b2d0 100644
--- a/packages/sdk/js/src/gen/core/types.ts
+++ b/packages/sdk/js/src/gen/core/types.gen.ts
@@ -1,5 +1,7 @@
-import type { Auth, AuthToken } from "./auth.js"
-import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from "./bodySerializer.js"
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { Auth, AuthToken } from "./auth.gen.js"
+import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from "./bodySerializer.gen.js"
export interface Client<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never> {
/**
diff --git a/packages/sdk/js/src/gen/core/utils.gen.ts b/packages/sdk/js/src/gen/core/utils.gen.ts
new file mode 100644
index 000000000..be18c608a
--- /dev/null
+++ b/packages/sdk/js/src/gen/core/utils.gen.ts
@@ -0,0 +1,109 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { QuerySerializer } from "./bodySerializer.gen.js"
+import {
+ type ArraySeparatorStyle,
+ serializeArrayParam,
+ serializeObjectParam,
+ serializePrimitiveParam,
+} from "./pathSerializer.gen.js"
+
+export interface PathSerializer {
+ path: Record<string, unknown>
+ url: string
+}
+
+export const PATH_PARAM_RE = /\{[^{}]+\}/g
+
+export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
+ let url = _url
+ const matches = _url.match(PATH_PARAM_RE)
+ if (matches) {
+ for (const match of matches) {
+ let explode = false
+ let name = match.substring(1, match.length - 1)
+ let style: ArraySeparatorStyle = "simple"
+
+ if (name.endsWith("*")) {
+ explode = true
+ name = name.substring(0, name.length - 1)
+ }
+
+ if (name.startsWith(".")) {
+ name = name.substring(1)
+ style = "label"
+ } else if (name.startsWith(";")) {
+ name = name.substring(1)
+ style = "matrix"
+ }
+
+ const value = path[name]
+
+ if (value === undefined || value === null) {
+ continue
+ }
+
+ if (Array.isArray(value)) {
+ url = url.replace(match, serializeArrayParam({ explode, name, style, value }))
+ continue
+ }
+
+ if (typeof value === "object") {
+ url = url.replace(
+ match,
+ serializeObjectParam({
+ explode,
+ name,
+ style,
+ value: value as Record<string, unknown>,
+ valueOnly: true,
+ }),
+ )
+ continue
+ }
+
+ if (style === "matrix") {
+ url = url.replace(
+ match,
+ `;${serializePrimitiveParam({
+ name,
+ value: value as string,
+ })}`,
+ )
+ continue
+ }
+
+ const replaceValue = encodeURIComponent(style === "label" ? `.${value as string}` : (value as string))
+ url = url.replace(match, replaceValue)
+ }
+ }
+ return url
+}
+
+export const getUrl = ({
+ baseUrl,
+ path,
+ query,
+ querySerializer,
+ url: _url,
+}: {
+ baseUrl?: string
+ path?: Record<string, unknown>
+ query?: Record<string, unknown>
+ querySerializer: QuerySerializer
+ url: string
+}) => {
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`
+ let url = (baseUrl ?? "") + pathUrl
+ if (path) {
+ url = defaultPathSerializer({ path, url })
+ }
+ let search = query ? querySerializer(query) : ""
+ if (search.startsWith("?")) {
+ search = search.substring(1)
+ }
+ if (search) {
+ url += `?${search}`
+ }
+ return url
+}
diff --git a/packages/sdk/js/src/gen/sdk.gen.ts b/packages/sdk/js/src/gen/sdk.gen.ts
index b00216b83..f900c24f0 100644
--- a/packages/sdk/js/src/gen/sdk.gen.ts
+++ b/packages/sdk/js/src/gen/sdk.gen.ts
@@ -123,7 +123,7 @@ class Event extends _HeyApiClient {
* Get events
*/
public subscribe<ThrowOnError extends boolean = false>(options?: Options<EventSubscribeData, ThrowOnError>) {
- return (options?.client ?? this._client).get<EventSubscribeResponses, unknown, ThrowOnError>({
+ return (options?.client ?? this._client).get.sse<EventSubscribeResponses, unknown, ThrowOnError>({
url: "/event",
...options,
})