Upgraded npm packages for latest security updates (#7183)

This commit is contained in:
Zane
2026-02-12 10:13:25 -08:00
committed by GitHub
parent dd98e8757b
commit 4cd39afbbe
13 changed files with 1386 additions and 1608 deletions
+1270 -1338
View File
File diff suppressed because it is too large Load Diff
+34 -34
View File
@@ -51,24 +51,24 @@
"@radix-ui/react-select": "^2.2.6", "@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/themes": "^3.2.1", "@radix-ui/themes": "^3.3.0",
"@tanstack/react-form": "^1.27.7", "@tanstack/react-form": "^1.28.0",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"compare-versions": "^6.1.1", "compare-versions": "^6.1.1",
"cors": "^2.8.5", "cors": "^2.8.6",
"cronstrue": "^3.9.0", "cronstrue": "^3.12.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"dotenv": "^17.2.3", "dotenv": "^17.2.4",
"electron-log": "^5.4.3", "electron-log": "^5.4.3",
"electron-squirrel-startup": "^1.0.1", "electron-squirrel-startup": "^1.0.1",
"electron-updater": "^6.7.3", "electron-updater": "^6.7.3",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"express": "^5.2.1", "express": "^5.2.1",
"katex": "^0.16.27", "katex": "^0.16.28",
"lodash": "^4.17.23", "lodash": "^4.17.23",
"lucide-react": "^0.562.0", "lucide-react": "^0.563.0",
"qrcode.react": "^4.2.0", "qrcode.react": "^4.2.0",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4", "react-dom": "^19.2.4",
@@ -84,66 +84,66 @@
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"shell-quote": "^1.8.3", "shell-quote": "^1.8.3",
"split-type": "^0.3.4", "split-type": "^0.3.4",
"swr": "^2.3.8", "swr": "^2.4.0",
"tailwind-merge": "^3.4.0", "tailwind-merge": "^3.4.0",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"tw-animate-css": "^1.4.0", "tw-animate-css": "^1.4.0",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.1.0",
"uuid": "^13.0.0", "uuid": "^13.0.0",
"zod": "^3.25.76" "zod": "^3.25.76"
}, },
"devDependencies": { "devDependencies": {
"@electron-forge/cli": "^7.10.2", "@electron-forge/cli": "^7.11.1",
"@electron-forge/maker-deb": "^7.10.2", "@electron-forge/maker-deb": "^7.11.1",
"@electron-forge/maker-flatpak": "^7.10.2", "@electron-forge/maker-flatpak": "^7.11.1",
"@electron-forge/maker-rpm": "^7.10.2", "@electron-forge/maker-rpm": "^7.11.1",
"@electron-forge/maker-squirrel": "^7.10.2", "@electron-forge/maker-squirrel": "^7.11.1",
"@electron-forge/maker-zip": "^7.10.2", "@electron-forge/maker-zip": "^7.11.1",
"@electron-forge/plugin-auto-unpack-natives": "^7.10.2", "@electron-forge/plugin-auto-unpack-natives": "^7.11.1",
"@electron-forge/plugin-fuses": "^7.10.2", "@electron-forge/plugin-fuses": "^7.11.1",
"@electron-forge/plugin-vite": "^7.10.2", "@electron-forge/plugin-vite": "^7.11.1",
"@electron/fuses": "^1.8.0", "@electron/fuses": "^1.8.0",
"@electron/remote": "^2.1.3", "@electron/remote": "^2.1.3",
"@eslint/js": "^9.39.2", "@eslint/js": "^9.39.2",
"@hey-api/openapi-ts": "^0.90.3", "@hey-api/openapi-ts": "^0.92.3",
"@modelcontextprotocol/sdk": "^1.25.2", "@modelcontextprotocol/sdk": "^1.26.0",
"@playwright/test": "^1.57.0", "@playwright/test": "^1.58.2",
"@tailwindcss/line-clamp": "^0.4.4", "@tailwindcss/line-clamp": "^0.4.4",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
"@testing-library/jest-dom": "^6.9.1", "@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.1", "@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1", "@testing-library/user-event": "^14.6.1",
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
"@types/electron-squirrel-startup": "^1.0.2", "@types/electron-squirrel-startup": "^1.0.2",
"@types/express": "^5.0.6", "@types/express": "^5.0.6",
"@types/lodash": "^4.17.23", "@types/lodash": "^4.17.23",
"@types/react": "^19.2.10", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@types/react-syntax-highlighter": "^15.5.13", "@types/react-syntax-highlighter": "^15.5.13",
"@types/shell-quote": "^1.7.5", "@types/shell-quote": "^1.7.5",
"@types/yauzl": "^2.10.3", "@types/yauzl": "^2.10.3",
"@typescript-eslint/eslint-plugin": "^8.53.0", "@typescript-eslint/eslint-plugin": "^8.55.0",
"@typescript-eslint/parser": "^8.53.0", "@typescript-eslint/parser": "^8.55.0",
"@vitejs/plugin-react": "^5.1.2", "@vitejs/plugin-react": "^5.1.4",
"@vitest/coverage-v8": "^4.0.17", "@vitest/coverage-v8": "^4.0.18",
"@vitest/ui": "^4.0.17", "@vitest/ui": "^4.0.18",
"autoprefixer": "^10.4.23", "autoprefixer": "^10.4.24",
"electron": "^40.1.0", "electron": "^40.4.0",
"electron-devtools-installer": "^4.0.0", "electron-devtools-installer": "^4.0.0",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"jsdom": "^27.4.0", "jsdom": "^28.0.0",
"knip": "^5.80.2", "knip": "^5.83.1",
"lint-staged": "^16.2.7", "lint-staged": "^16.2.7",
"postcss": "^8.5.6", "postcss": "^8.5.6",
"prettier": "^3.7.4", "prettier": "^3.8.1",
"tailwindcss": "^4.1.18", "tailwindcss": "^4.1.18",
"typescript": "~5.9.3", "typescript": "~5.9.3",
"vite": "^7.3.1", "vite": "^7.3.1",
"vitest": "^4.0.17" "vitest": "^4.0.18"
}, },
"keywords": [], "keywords": [],
"license": "Apache-2.0", "license": "Apache-2.0",
+32 -49
View File
@@ -3,12 +3,7 @@
import { createSseClient } from '../core/serverSentEvents.gen'; import { createSseClient } from '../core/serverSentEvents.gen';
import type { HttpMethod } from '../core/types.gen'; import type { HttpMethod } from '../core/types.gen';
import { getValidRequestBody } from '../core/utils.gen'; import { getValidRequestBody } from '../core/utils.gen';
import type { import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
Client,
Config,
RequestOptions,
ResolvedRequestOptions,
} from './types.gen';
import { import {
buildUrl, buildUrl,
createConfig, createConfig,
@@ -34,12 +29,7 @@ export const createClient = (config: Config = {}): Client => {
return getConfig(); return getConfig();
}; };
const interceptors = createInterceptors< const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>();
Request,
Response,
unknown,
ResolvedRequestOptions
>();
const beforeRequest = async (options: RequestOptions) => { const beforeRequest = async (options: RequestOptions) => {
const opts = { const opts = {
@@ -105,12 +95,7 @@ export const createClient = (config: Config = {}): Client => {
for (const fn of interceptors.error.fns) { for (const fn of interceptors.error.fns) {
if (fn) { if (fn) {
finalError = (await fn( finalError = (await fn(error, undefined as any, request, opts)) as unknown;
error,
undefined as any,
request,
opts,
)) as unknown;
} }
} }
@@ -147,10 +132,7 @@ export const createClient = (config: Config = {}): Client => {
? getParseAs(response.headers.get('Content-Type')) ? getParseAs(response.headers.get('Content-Type'))
: opts.parseAs) ?? 'json'; : opts.parseAs) ?? 'json';
if ( if (response.status === 204 || response.headers.get('Content-Length') === '0') {
response.status === 204 ||
response.headers.get('Content-Length') === '0'
) {
let emptyData: any; let emptyData: any;
switch (parseAs) { switch (parseAs) {
case 'arrayBuffer': case 'arrayBuffer':
@@ -182,10 +164,16 @@ export const createClient = (config: Config = {}): Client => {
case 'arrayBuffer': case 'arrayBuffer':
case 'blob': case 'blob':
case 'formData': case 'formData':
case 'json':
case 'text': case 'text':
data = await response[parseAs](); data = await response[parseAs]();
break; break;
case 'json': {
// Some servers return 200 with no Content-Length and empty body.
// response.json() would throw; read as text and parse if non-empty.
const text = await response.text();
data = text ? JSON.parse(text) : {};
break;
}
case 'stream': case 'stream':
return opts.responseStyle === 'data' return opts.responseStyle === 'data'
? response.body ? response.body
@@ -246,34 +234,29 @@ export const createClient = (config: Config = {}): Client => {
}; };
}; };
const makeMethodFn = const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
(method: Uppercase<HttpMethod>) => (options: RequestOptions) => request({ ...options, method });
request({ ...options, method });
const makeSseFn = const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
(method: Uppercase<HttpMethod>) => async (options: RequestOptions) => { const { opts, url } = await beforeRequest(options);
const { opts, url } = await beforeRequest(options); return createSseClient({
return createSseClient({ ...opts,
...opts, body: opts.body as BodyInit | null | undefined,
body: opts.body as BodyInit | null | undefined, headers: opts.headers as unknown as Record<string, string>,
headers: opts.headers as unknown as Record<string, string>, method,
method, onRequest: async (url, init) => {
onRequest: async (url, init) => { let request = new Request(url, init);
let request = new Request(url, init); for (const fn of interceptors.request.fns) {
for (const fn of interceptors.request.fns) { if (fn) {
if (fn) { request = await fn(request, opts);
request = await fn(request, opts);
}
} }
return request; }
}, return request;
serializedBody: getValidRequestBody(opts) as },
| BodyInit serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,
| null url,
| undefined, });
url, };
});
};
return { return {
buildUrl, buildUrl,
+12 -40
View File
@@ -5,17 +5,13 @@ import type {
ServerSentEventsOptions, ServerSentEventsOptions,
ServerSentEventsResult, ServerSentEventsResult,
} from '../core/serverSentEvents.gen'; } from '../core/serverSentEvents.gen';
import type { import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen';
Client as CoreClient,
Config as CoreConfig,
} from '../core/types.gen';
import type { Middleware } from './utils.gen'; import type { Middleware } from './utils.gen';
export type ResponseStyle = 'data' | 'fields'; export type ResponseStyle = 'data' | 'fields';
export interface Config<T extends ClientOptions = ClientOptions> export interface Config<T extends ClientOptions = ClientOptions>
extends Omit<RequestInit, 'body' | 'headers' | 'method'>, extends Omit<RequestInit, 'body' | 'headers' | 'method'>, CoreConfig {
CoreConfig {
/** /**
* Base URL for all requests made by this client. * Base URL for all requests made by this client.
*/ */
@@ -42,14 +38,7 @@ export interface Config<T extends ClientOptions = ClientOptions>
* *
* @default 'auto' * @default 'auto'
*/ */
parseAs?: parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
| 'arrayBuffer'
| 'auto'
| 'blob'
| 'formData'
| 'json'
| 'stream'
| 'text';
/** /**
* Should we return only data or multiple fields (data, error, response, etc.)? * Should we return only data or multiple fields (data, error, response, etc.)?
* *
@@ -69,7 +58,9 @@ export interface RequestOptions<
TResponseStyle extends ResponseStyle = 'fields', TResponseStyle extends ResponseStyle = 'fields',
ThrowOnError extends boolean = boolean, ThrowOnError extends boolean = boolean,
Url extends string = string, Url extends string = string,
> extends Config<{ >
extends
Config<{
responseStyle: TResponseStyle; responseStyle: TResponseStyle;
throwOnError: ThrowOnError; throwOnError: ThrowOnError;
}>, }>,
@@ -116,32 +107,22 @@ export type RequestResult<
? TData[keyof TData] ? TData[keyof TData]
: TData : TData
: { : {
data: TData extends Record<string, unknown> data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
? TData[keyof TData]
: TData;
request: Request; request: Request;
response: Response; response: Response;
} }
> >
: Promise< : Promise<
TResponseStyle extends 'data' TResponseStyle extends 'data'
? ? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined
| (TData extends Record<string, unknown>
? TData[keyof TData]
: TData)
| undefined
: ( : (
| { | {
data: TData extends Record<string, unknown> data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
? TData[keyof TData]
: TData;
error: undefined; error: undefined;
} }
| { | {
data: undefined; data: undefined;
error: TError extends Record<string, unknown> error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
? TError[keyof TError]
: TError;
} }
) & { ) & {
request: Request; request: Request;
@@ -180,10 +161,7 @@ type RequestFn = <
TResponseStyle extends ResponseStyle = 'fields', TResponseStyle extends ResponseStyle = 'fields',
>( >(
options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> & options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> &
Pick< Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>,
Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>,
'method'
>,
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>; ) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
type BuildUrlFn = < type BuildUrlFn = <
@@ -197,13 +175,7 @@ type BuildUrlFn = <
options: TData & Options<TData>, options: TData & Options<TData>,
) => string; ) => string;
export type Client = CoreClient< export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
RequestFn,
Config,
MethodFn,
BuildUrlFn,
SseFn
> & {
interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>; interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>;
}; };
+6 -22
View File
@@ -65,9 +65,7 @@ export const createQuerySerializer = <T = unknown>({
/** /**
* Infers parseAs value from provided Content-Type header. * Infers parseAs value from provided Content-Type header.
*/ */
export const getParseAs = ( export const getParseAs = (contentType: string | null): Exclude<Config['parseAs'], 'auto'> => {
contentType: string | null,
): Exclude<Config['parseAs'], 'auto'> => {
if (!contentType) { if (!contentType) {
// If no Content-Type header is provided, the best we can do is return the raw response body, // If no Content-Type header is provided, the best we can do is return the raw response body,
// which is effectively the same as the 'stream' option. // which is effectively the same as the 'stream' option.
@@ -80,10 +78,7 @@ export const getParseAs = (
return; return;
} }
if ( if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {
cleanContent.startsWith('application/json') ||
cleanContent.endsWith('+json')
) {
return 'json'; return 'json';
} }
@@ -92,9 +87,7 @@ export const getParseAs = (
} }
if ( if (
['application/', 'audio/', 'image/', 'video/'].some((type) => ['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))
cleanContent.startsWith(type),
)
) { ) {
return 'blob'; return 'blob';
} }
@@ -201,10 +194,7 @@ export const mergeHeaders = (
continue; continue;
} }
const iterator = const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
header instanceof Headers
? headersEntries(header)
: Object.entries(header);
for (const [key, value] of iterator) { for (const [key, value] of iterator) {
if (value === null) { if (value === null) {
@@ -233,10 +223,7 @@ type ErrInterceptor<Err, Res, Req, Options> = (
options: Options, options: Options,
) => Err | Promise<Err>; ) => Err | Promise<Err>;
type ReqInterceptor<Req, Options> = ( type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
request: Req,
options: Options,
) => Req | Promise<Req>;
type ResInterceptor<Res, Req, Options> = ( type ResInterceptor<Res, Req, Options> = (
response: Res, response: Res,
@@ -270,10 +257,7 @@ class Interceptors<Interceptor> {
return this.fns.indexOf(id); return this.fns.indexOf(id);
} }
update( update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false {
id: number | Interceptor,
fn: Interceptor,
): number | Interceptor | false {
const index = this.getInterceptorIndex(id); const index = this.getInterceptorIndex(id);
if (this.fns[index]) { if (this.fns[index]) {
this.fns[index] = fn; this.fns[index] = fn;
+1 -2
View File
@@ -23,8 +23,7 @@ export const getAuthToken = async (
auth: Auth, auth: Auth,
callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken, callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
): Promise<string | undefined> => { ): Promise<string | undefined> => {
const token = const token = typeof callback === 'function' ? await callback(auth) : callback;
typeof callback === 'function' ? await callback(auth) : callback;
if (!token) { if (!token) {
return; return;
+5 -21
View File
@@ -1,10 +1,6 @@
// This file is auto-generated by @hey-api/openapi-ts // This file is auto-generated by @hey-api/openapi-ts
import type { import type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerializer.gen';
ArrayStyle,
ObjectStyle,
SerializerOptions,
} from './pathSerializer.gen';
export type QuerySerializer = (query: Record<string, unknown>) => string; export type QuerySerializer = (query: Record<string, unknown>) => string;
@@ -24,11 +20,7 @@ export type QuerySerializerOptions = QuerySerializerOptionsObject & {
parameters?: Record<string, QuerySerializerOptionsObject>; parameters?: Record<string, QuerySerializerOptionsObject>;
}; };
const serializeFormDataPair = ( const serializeFormDataPair = (data: FormData, key: string, value: unknown): void => {
data: FormData,
key: string,
value: unknown,
): void => {
if (typeof value === 'string' || value instanceof Blob) { if (typeof value === 'string' || value instanceof Blob) {
data.append(key, value); data.append(key, value);
} else if (value instanceof Date) { } else if (value instanceof Date) {
@@ -38,11 +30,7 @@ const serializeFormDataPair = (
} }
}; };
const serializeUrlSearchParamsPair = ( const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: unknown): void => {
data: URLSearchParams,
key: string,
value: unknown,
): void => {
if (typeof value === 'string') { if (typeof value === 'string') {
data.append(key, value); data.append(key, value);
} else { } else {
@@ -73,15 +61,11 @@ export const formDataBodySerializer = {
export const jsonBodySerializer = { export const jsonBodySerializer = {
bodySerializer: <T>(body: T): string => bodySerializer: <T>(body: T): string =>
JSON.stringify(body, (_key, value) => JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),
typeof value === 'bigint' ? value.toString() : value,
),
}; };
export const urlSearchParamsBodySerializer = { export const urlSearchParamsBodySerializer = {
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>( bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(body: T): string => {
body: T,
): string => {
const data = new URLSearchParams(); const data = new URLSearchParams();
Object.entries(body).forEach(([key, value]) => { Object.entries(body).forEach(([key, value]) => {
+3 -10
View File
@@ -102,10 +102,7 @@ const stripEmptySlots = (params: Params) => {
} }
}; };
export const buildClientParams = ( export const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => {
args: ReadonlyArray<unknown>,
fields: FieldsConfig,
) => {
const params: Params = { const params: Params = {
body: {}, body: {},
headers: {}, headers: {},
@@ -148,15 +145,11 @@ export const buildClientParams = (
params[field.map] = value; params[field.map] = value;
} }
} else { } else {
const extra = extraPrefixes.find(([prefix]) => const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix));
key.startsWith(prefix),
);
if (extra) { if (extra) {
const [prefix, slot] = extra; const [prefix, slot] = extra;
(params[slot] as Record<string, unknown>)[ (params[slot] as Record<string, unknown>)[key.slice(prefix.length)] = value;
key.slice(prefix.length)
] = value;
} else if ('allowExtra' in config && config.allowExtra) { } else if ('allowExtra' in config && config.allowExtra) {
for (const [slot, allowed] of Object.entries(config.allowExtra)) { for (const [slot, allowed] of Object.entries(config.allowExtra)) {
if (allowed) { if (allowed) {
+4 -14
View File
@@ -1,8 +1,6 @@
// This file is auto-generated by @hey-api/openapi-ts // This file is auto-generated by @hey-api/openapi-ts
interface SerializeOptions<T> interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {}
extends SerializePrimitiveOptions,
SerializerOptions<T> {}
interface SerializePrimitiveOptions { interface SerializePrimitiveOptions {
allowReserved?: boolean; allowReserved?: boolean;
@@ -105,9 +103,7 @@ export const serializeArrayParam = ({
}); });
}) })
.join(separator); .join(separator);
return style === 'label' || style === 'matrix' return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
? separator + joinedValues
: joinedValues;
}; };
export const serializePrimitiveParam = ({ export const serializePrimitiveParam = ({
@@ -146,11 +142,7 @@ export const serializeObjectParam = ({
if (style !== 'deepObject' && !explode) { if (style !== 'deepObject' && !explode) {
let values: string[] = []; let values: string[] = [];
Object.entries(value).forEach(([key, v]) => { Object.entries(value).forEach(([key, v]) => {
values = [ values = [...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string)];
...values,
key,
allowReserved ? (v as string) : encodeURIComponent(v as string),
];
}); });
const joinedValues = values.join(','); const joinedValues = values.join(',');
switch (style) { switch (style) {
@@ -175,7 +167,5 @@ export const serializeObjectParam = ({
}), }),
) )
.join(separator); .join(separator);
return style === 'label' || style === 'matrix' return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
? separator + joinedValues
: joinedValues;
}; };
@@ -15,11 +15,7 @@ export type JsonValue =
* Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
*/ */
export const queryKeyJsonReplacer = (_key: string, value: unknown) => { export const queryKeyJsonReplacer = (_key: string, value: unknown) => {
if ( if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
value === undefined ||
typeof value === 'function' ||
typeof value === 'symbol'
) {
return undefined; return undefined;
} }
if (typeof value === 'bigint') { if (typeof value === 'bigint') {
@@ -61,9 +57,7 @@ const isPlainObject = (value: unknown): value is Record<string, unknown> => {
* Turns URLSearchParams into a sorted JSON object for deterministic keys. * Turns URLSearchParams into a sorted JSON object for deterministic keys.
*/ */
const serializeSearchParams = (params: URLSearchParams): JsonValue => { const serializeSearchParams = (params: URLSearchParams): JsonValue => {
const entries = Array.from(params.entries()).sort(([a], [b]) => const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b));
a.localeCompare(b),
);
const result: Record<string, JsonValue> = {}; const result: Record<string, JsonValue> = {};
for (const [key, value] of entries) { for (const [key, value] of entries) {
@@ -86,26 +80,16 @@ const serializeSearchParams = (params: URLSearchParams): JsonValue => {
/** /**
* Normalizes any accepted value into a JSON-friendly shape for query keys. * Normalizes any accepted value into a JSON-friendly shape for query keys.
*/ */
export const serializeQueryKeyValue = ( export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => {
value: unknown,
): JsonValue | undefined => {
if (value === null) { if (value === null) {
return null; return null;
} }
if ( if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean'
) {
return value; return value;
} }
if ( if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
value === undefined ||
typeof value === 'function' ||
typeof value === 'symbol'
) {
return undefined; return undefined;
} }
@@ -121,10 +105,7 @@ export const serializeQueryKeyValue = (
return stringifyToJsonValue(value); return stringifyToJsonValue(value);
} }
if ( if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) {
typeof URLSearchParams !== 'undefined' &&
value instanceof URLSearchParams
) {
return serializeSearchParams(value); return serializeSearchParams(value);
} }
@@ -2,10 +2,7 @@
import type { Config } from './types.gen'; import type { Config } from './types.gen';
export type ServerSentEventsOptions<TData = unknown> = Omit< export type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> &
RequestInit,
'method'
> &
Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & { Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & {
/** /**
* Fetch API implementation. You can use this option to provide a custom * Fetch API implementation. You can use this option to provide a custom
@@ -74,11 +71,7 @@ export interface StreamEvent<TData = unknown> {
retry?: number; retry?: number;
} }
export type ServerSentEventsResult< export type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
TData = unknown,
TReturn = void,
TNext = unknown,
> = {
stream: AsyncGenerator< stream: AsyncGenerator<
TData extends Record<string, unknown> ? TData[keyof TData] : TData, TData extends Record<string, unknown> ? TData[keyof TData] : TData,
TReturn, TReturn,
@@ -101,9 +94,7 @@ export const createSseClient = <TData = unknown>({
}: ServerSentEventsOptions): ServerSentEventsResult<TData> => { }: ServerSentEventsOptions): ServerSentEventsResult<TData> => {
let lastEventId: string | undefined; let lastEventId: string | undefined;
const sleep = const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
sseSleepFn ??
((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
const createStream = async function* () { const createStream = async function* () {
let retryDelay: number = sseDefaultRetryDelay ?? 3000; let retryDelay: number = sseDefaultRetryDelay ?? 3000;
@@ -141,16 +132,11 @@ export const createSseClient = <TData = unknown>({
const _fetch = options.fetch ?? globalThis.fetch; const _fetch = options.fetch ?? globalThis.fetch;
const response = await _fetch(request); const response = await _fetch(request);
if (!response.ok) if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
throw new Error(
`SSE failed: ${response.status} ${response.statusText}`,
);
if (!response.body) throw new Error('No body in SSE response'); if (!response.body) throw new Error('No body in SSE response');
const reader = response.body const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
.pipeThrough(new TextDecoderStream())
.getReader();
let buffer = ''; let buffer = '';
@@ -188,10 +174,7 @@ export const createSseClient = <TData = unknown>({
} else if (line.startsWith('id:')) { } else if (line.startsWith('id:')) {
lastEventId = line.replace(/^id:\s*/, ''); lastEventId = line.replace(/^id:\s*/, '');
} else if (line.startsWith('retry:')) { } else if (line.startsWith('retry:')) {
const parsed = Number.parseInt( const parsed = Number.parseInt(line.replace(/^retry:\s*/, ''), 10);
line.replace(/^retry:\s*/, ''),
10,
);
if (!Number.isNaN(parsed)) { if (!Number.isNaN(parsed)) {
retryDelay = parsed; retryDelay = parsed;
} }
@@ -243,18 +226,12 @@ export const createSseClient = <TData = unknown>({
// connection failed or aborted; retry after delay // connection failed or aborted; retry after delay
onSseError?.(error); onSseError?.(error);
if ( if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
sseMaxRetryAttempts !== undefined &&
attempt >= sseMaxRetryAttempts
) {
break; // stop after firing error break; // stop after firing error
} }
// exponential backoff: double retry each attempt, cap at 30s // exponential backoff: double retry each attempt, cap at 30s
const backoff = Math.min( const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
retryDelay * 2 ** (attempt - 1),
sseMaxRetryDelay ?? 30000,
);
await sleep(backoff); await sleep(backoff);
} }
} }
+4 -18
View File
@@ -1,11 +1,7 @@
// This file is auto-generated by @hey-api/openapi-ts // This file is auto-generated by @hey-api/openapi-ts
import type { Auth, AuthToken } from './auth.gen'; import type { Auth, AuthToken } from './auth.gen';
import type { import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen';
BodySerializer,
QuerySerializer,
QuerySerializerOptions,
} from './bodySerializer.gen';
export type HttpMethod = export type HttpMethod =
| 'connect' | 'connect'
@@ -34,9 +30,7 @@ export type Client<
setConfig: (config: Config) => Config; setConfig: (config: Config) => Config;
} & { } & {
[K in HttpMethod]: MethodFn; [K in HttpMethod]: MethodFn;
} & ([SseFn] extends [never] } & ([SseFn] extends [never] ? { sse?: never } : { sse: { [K in HttpMethod]: SseFn } });
? { sse?: never }
: { sse: { [K in HttpMethod]: SseFn } });
export interface Config { export interface Config {
/** /**
@@ -59,13 +53,7 @@ export interface Config {
| RequestInit['headers'] | RequestInit['headers']
| Record< | Record<
string, string,
| string string | number | boolean | (string | number | boolean)[] | null | undefined | unknown
| number
| boolean
| (string | number | boolean)[]
| null
| undefined
| unknown
>; >;
/** /**
* The request method. * The request method.
@@ -112,7 +100,5 @@ type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never]
: false; : false;
export type OmitNever<T extends Record<string, unknown>> = { export type OmitNever<T extends Record<string, unknown>> = {
[K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true [K in keyof T as IsExactlyNeverOrNeverUndefined<T[K]> extends true ? never : K]: T[K];
? never
: K]: T[K];
}; };
+1 -4
View File
@@ -44,10 +44,7 @@ export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
} }
if (Array.isArray(value)) { if (Array.isArray(value)) {
url = url.replace( url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
match,
serializeArrayParam({ explode, name, style, value }),
);
continue; continue;
} }