chore(hey-api): enable validator and upgrade [BE-13103] (#2919)

This commit is contained in:
Chaim Lev-Ari
2026-07-02 10:15:20 +07:00
committed by GitHub
parent a62177ce06
commit f6a4d6a0bb
15 changed files with 14509 additions and 10315 deletions
@@ -3,6 +3,7 @@
import { createClientConfig } from '@/react/portainer/services/axios/configure-hey-api';
import {
type Client,
type ClientOptions,
type Config,
createClient,
@@ -22,6 +23,8 @@ export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (
override?: Config<ClientOptions & T>
) => Config<Required<ClientOptions> & T>;
export const client = createClient(
createClientConfig(createConfig<ClientOptions2>({ throwOnError: true }))
export const client: Client = createClient(
createClientConfig(
createConfig<ClientOptions2>({ baseURL: 'api', throwOnError: true })
)
);
@@ -9,6 +9,8 @@ export {
} from '../core/bodySerializer.gen';
export { buildClientParams } from '../core/params.gen';
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
export type { ServerSentEventsResult } from '../core/serverSentEvents.gen';
export type { ClientMeta } from '../core/types.gen';
export { createClient } from './client.gen';
export type {
Client,
@@ -18,8 +18,8 @@ import type {
export const createQuerySerializer = <T = unknown>({
parameters = {},
...args
}: QuerySerializerOptions = {}) => {
const querySerializer = (queryParams: T) => {
}: QuerySerializerOptions = {}): ((queryParams: T) => string) => {
const querySerializer = (queryParams: T): string => {
const search: string[] = [];
if (queryParams && typeof queryParams === 'object') {
for (const name in queryParams) {
@@ -9,6 +9,13 @@ export interface Auth {
* @default 'header'
*/
in?: 'header' | 'query' | 'cookie';
/**
* A unique identifier for the security scheme.
*
* Defined only when there are multiple security schemes whose `Auth`
* shape would otherwise be identical.
*/
key?: string;
/**
* Header or query parameter name.
*
@@ -62,7 +62,7 @@ type KeyMap = Map<
}
>;
const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
function buildKeyMap(fields: FieldsConfig, map?: KeyMap): KeyMap {
if (!map) {
map = new Map();
}
@@ -85,17 +85,18 @@ const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
}
return map;
};
}
interface Params {
body: unknown;
body?: unknown;
headers: Record<string, unknown>;
path: Record<string, unknown>;
query: Record<string, unknown>;
}
const stripEmptySlots = (params: Params) => {
function stripEmptySlots(params: Params): void {
for (const [slot, value] of Object.entries(params)) {
if (slot === 'body') continue;
if (
value &&
typeof value === 'object' &&
@@ -105,14 +106,13 @@ const stripEmptySlots = (params: Params) => {
delete params[slot as Slot];
}
}
};
}
export const buildClientParams = (
export function buildClientParams(
args: ReadonlyArray<unknown>,
fields: FieldsConfig
) => {
): Params {
const params: Params = {
body: Object.create(null),
headers: Object.create(null),
path: Object.create(null),
query: Object.create(null),
@@ -120,6 +120,15 @@ export const buildClientParams = (
const map = buildKeyMap(fields);
function writeSlot(slot: Slot, key: string, value: unknown): void {
let record = params[slot] as Record<string, unknown> | undefined;
if (record === undefined) {
record = Object.create(null) as Record<string, unknown>;
params[slot] = record;
}
record[key] = value;
}
let config: FieldsConfig[number] | undefined;
for (const [index, arg] of args.entries()) {
@@ -136,7 +145,7 @@ export const buildClientParams = (
const field = map.get(config.key)!;
const name = field.map || config.key;
if (field.in) {
(params[field.in] as Record<string, unknown>)[name] = arg;
writeSlot(field.in, name, arg);
}
} else {
params.body = arg;
@@ -148,7 +157,7 @@ export const buildClientParams = (
if (field) {
if (field.in) {
const name = field.map || key;
(params[field.in] as Record<string, unknown>)[name] = value;
writeSlot(field.in, name, value);
} else {
params[field.map] = value;
}
@@ -159,13 +168,11 @@ export const buildClientParams = (
if (extra) {
const [prefix, slot] = extra;
(params[slot] as Record<string, unknown>)[
key.slice(prefix.length)
] = value;
writeSlot(slot, key.slice(prefix.length), value);
} else if ('allowExtra' in config && config.allowExtra) {
for (const [slot, allowed] of Object.entries(config.allowExtra)) {
if (allowed) {
(params[slot as Slot] as Record<string, unknown>)[key] = value;
writeSlot(slot as Slot, key, value);
break;
}
}
@@ -178,4 +185,4 @@ export const buildClientParams = (
stripEmptySlots(params);
return params;
};
}
@@ -26,7 +26,9 @@ interface SerializePrimitiveParam extends SerializePrimitiveOptions {
value: string;
}
export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
export const separatorArrayExplode = (
style: ArraySeparatorStyle
): '.' | ';' | ',' | '&' => {
switch (style) {
case 'label':
return '.';
@@ -39,7 +41,9 @@ export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
}
};
export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
export const separatorArrayNoExplode = (
style: ArraySeparatorStyle
): ',' | '|' | '%20' => {
switch (style) {
case 'form':
return ',';
@@ -52,7 +56,9 @@ export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
}
};
export const separatorObjectExplode = (style: ObjectSeparatorStyle) => {
export const separatorObjectExplode = (
style: ObjectSeparatorStyle
): '.' | ';' | ',' | '&' => {
switch (style) {
case 'label':
return '.';
@@ -73,7 +79,7 @@ export const serializeArrayParam = ({
value,
}: SerializeOptions<ArraySeparatorStyle> & {
value: unknown[];
}) => {
}): string => {
if (!explode) {
const joinedValues = (
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
@@ -113,7 +119,7 @@ export const serializePrimitiveParam = ({
allowReserved,
name,
value,
}: SerializePrimitiveParam) => {
}: SerializePrimitiveParam): string => {
if (value === undefined || value === null) {
return '';
}
@@ -137,7 +143,7 @@ export const serializeObjectParam = ({
}: SerializeOptions<ObjectSeparatorStyle> & {
value: Record<string, unknown> | Date;
valueOnly?: boolean;
}) => {
}): string => {
if (value instanceof Date) {
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
}
@@ -14,7 +14,10 @@ export type JsonValue =
/**
* 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
): unknown | undefined => {
if (
value === undefined ||
typeof value === 'function' ||
@@ -103,6 +103,12 @@ export interface Config {
responseValidator?: (data: unknown) => Promise<unknown>;
}
/**
* Arbitrary metadata passed through the `meta` request option.
*/
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface ClientMeta {}
type IsExactlyNeverOrNeverUndefined<T> = [T] extends [never]
? true
: [T] extends [never | undefined]
@@ -13,9 +13,12 @@ export interface PathSerializer {
url: string;
}
export const PATH_PARAM_RE = /\{[^{}]+\}/g;
export const PATH_PARAM_RE: RegExp = /\{[^{}]+\}/g;
export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
export const defaultPathSerializer = ({
path,
url: _url,
}: PathSerializer): string => {
let url = _url;
const matches = _url.match(PATH_PARAM_RE);
if (matches) {
@@ -97,7 +100,7 @@ export const getUrl = ({
query?: Record<string, unknown>;
querySerializer: QuerySerializer;
url: string;
}) => {
}): string => {
const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
let url = (baseUrl ?? '') + pathUrl;
if (path) {
@@ -117,7 +120,7 @@ export function getValidRequestBody(options: {
body?: unknown;
bodySerializer?: BodySerializer | null;
serializedBody?: unknown;
}) {
}): unknown {
const hasBody = options.body !== undefined;
const isSerializedBody = hasBody && options.bodySerializer;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -22,7 +22,7 @@ export default defineConfig({
},
{
name: '@hey-api/sdk',
// validator: true, TODO revert in BE-13103
validator: true,
},
{
name: '@hey-api/client-axios',
+1 -1
View File
@@ -152,7 +152,7 @@
"@eslint-community/eslint-plugin-eslint-comments": "^4.7.2",
"@eslint/eslintrc": "^3.3.5",
"@eslint/js": "^10.0.1",
"@hey-api/openapi-ts": "0.97.3",
"@hey-api/openapi-ts": "0.99.0",
"@simbathesailor/use-what-changed": "^2.0.0",
"@storybook/addon-docs": "10.4.2",
"@storybook/addon-links": "10.4.2",
+45 -30
View File
@@ -368,8 +368,8 @@ importers:
specifier: ^10.0.1
version: 10.0.1(eslint@9.39.4(jiti@2.7.0))
'@hey-api/openapi-ts':
specifier: 0.97.3
version: 0.97.3(magicast@0.5.2)(typescript@6.0.2)
specifier: 0.99.0
version: 0.99.0(magicast@0.5.2)(typescript@6.0.2)
'@simbathesailor/use-what-changed':
specifier: ^2.0.0
version: 2.0.0(react@17.0.2)
@@ -1658,24 +1658,24 @@ packages:
'@floating-ui/utils@0.2.11':
resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==}
'@hey-api/codegen-core@0.8.2':
resolution: {integrity: sha512-R2NMf3wq97rh1mjz33WJQU8svz3F0RYUjvx/QzXucjpSqQ3O5huTdDjErG4fMxSr1X+X56NuDrqtGfHmo1TRUQ==}
engines: {node: '>=22.13.0'}
'@hey-api/codegen-core@0.9.1':
resolution: {integrity: sha512-s97jL1dgTMuiMHv2BZ1X4Tgd99Mf9GOvGdNqNcGwIMmnR+PgYNoraj4Zvp134MKsNCap/m7k0r0vKKnl56pj4w==}
engines: {node: '>=22.18.0'}
'@hey-api/json-schema-ref-parser@1.4.2':
resolution: {integrity: sha512-ZhCFSKI2ipZHEbgmtUHdyddvRU3wJ4elgCfYUC7T7hZa4EivSrVflTQf2w+v3TuaYxR1Y2V2kq3otqTttrrK8Q==}
engines: {node: '>=22.13.0'}
'@hey-api/json-schema-ref-parser@1.4.4':
resolution: {integrity: sha512-otmd+zCxbYVBIp/mlMTnGkvlNYLkVKgs3VOIq0kSnenhB1+fRwLPQIeSwyWM6E51oXhUedkYjVsVpkVexeuJOA==}
engines: {node: '>=22.18.0'}
'@hey-api/openapi-ts@0.97.3':
resolution: {integrity: sha512-4sR6/E/POuy7aPZW9DDjhObzZCq7eSJWiW0+epXeKNczoTWEwdOyWFy9Ca/CnXYlZ3oJsrv0ZD0OO+YuczT7CA==}
engines: {node: '>=22.13.0'}
'@hey-api/openapi-ts@0.99.0':
resolution: {integrity: sha512-SePU/5oEWWkvUBYmvzdYRctseoLuskyhs4ET0RvLIcmzc8yLQoA2R+KtBIQ8bPsoSUB0m4E5SmBnl6aGSA0szQ==}
engines: {node: '>=22.18.0'}
hasBin: true
peerDependencies:
typescript: '>=5.5.3 || >=6.0.0 || 6.0.1-rc'
'@hey-api/shared@0.4.5':
resolution: {integrity: sha512-au4eHpBXAe1du0iMp6ESYuEaMS2jsoEyrbcT246btRhI9rMeQFEs7ZjtcMGXGsxhpaR38A8cPGNHx7QOrWAdMw==}
engines: {node: '>=22.13.0'}
'@hey-api/shared@0.5.0':
resolution: {integrity: sha512-JN/j4Ebh4cJGYIQ5cwWuqe7GeSUyQoz7oC51WqyhKOcrejK6DKZMDkshc5d1eKTRuRL+rjozuRcoUaZZn2DGPw==}
engines: {node: '>=22.18.0'}
'@hey-api/spec-types@0.2.0':
resolution: {integrity: sha512-ibQ8Is7evMavzr8GNyJCcTg975d8DpaMUyLmOrQ85UBdy1l6t1KuRAwgChAbesJsIlNV6gjmlXruWyegDX18Fg==}
@@ -4414,9 +4414,9 @@ packages:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
commander@14.0.3:
resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
engines: {node: '>=20'}
commander@15.0.0:
resolution: {integrity: sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==}
engines: {node: '>=22.12.0'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@@ -5945,6 +5945,10 @@ packages:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true
js-yaml@4.2.0:
resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==}
hasBin: true
jsdom@24.1.3:
resolution: {integrity: sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==}
engines: {node: '>=18'}
@@ -7620,6 +7624,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
semver@7.8.4:
resolution: {integrity: sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==}
engines: {node: '>=10'}
hasBin: true
send@0.19.2:
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
engines: {node: '>= 0.8.0'}
@@ -9999,7 +10008,7 @@ snapshots:
'@floating-ui/utils@0.2.11': {}
'@hey-api/codegen-core@0.8.2(magicast@0.5.2)':
'@hey-api/codegen-core@0.9.1(magicast@0.5.2)':
dependencies:
'@hey-api/types': 0.1.4
ansi-colors: 4.1.3
@@ -10008,38 +10017,38 @@ snapshots:
transitivePeerDependencies:
- magicast
'@hey-api/json-schema-ref-parser@1.4.2':
'@hey-api/json-schema-ref-parser@1.4.4':
dependencies:
'@jsdevtools/ono': 7.1.3
'@types/json-schema': 7.0.15
js-yaml: 4.1.1
js-yaml: 4.2.0
'@hey-api/openapi-ts@0.97.3(magicast@0.5.2)(typescript@6.0.2)':
'@hey-api/openapi-ts@0.99.0(magicast@0.5.2)(typescript@6.0.2)':
dependencies:
'@hey-api/codegen-core': 0.8.2(magicast@0.5.2)
'@hey-api/json-schema-ref-parser': 1.4.2
'@hey-api/shared': 0.4.5(magicast@0.5.2)
'@hey-api/codegen-core': 0.9.1(magicast@0.5.2)
'@hey-api/json-schema-ref-parser': 1.4.4
'@hey-api/shared': 0.5.0(magicast@0.5.2)
'@hey-api/spec-types': 0.2.0
'@hey-api/types': 0.1.4
'@lukeed/ms': 2.0.2
ansi-colors: 4.1.3
color-support: 1.1.3
commander: 14.0.3
commander: 15.0.0
get-tsconfig: 4.14.0
typescript: 6.0.2
transitivePeerDependencies:
- magicast
'@hey-api/shared@0.4.5(magicast@0.5.2)':
'@hey-api/shared@0.5.0(magicast@0.5.2)':
dependencies:
'@hey-api/codegen-core': 0.8.2(magicast@0.5.2)
'@hey-api/json-schema-ref-parser': 1.4.2
'@hey-api/codegen-core': 0.9.1(magicast@0.5.2)
'@hey-api/json-schema-ref-parser': 1.4.4
'@hey-api/spec-types': 0.2.0
'@hey-api/types': 0.1.4
ansi-colors: 4.1.3
cross-spawn: 7.0.6
open: 11.0.0
semver: 7.7.4
semver: 7.8.4
transitivePeerDependencies:
- magicast
@@ -12910,7 +12919,7 @@ snapshots:
commander@12.1.0: {}
commander@14.0.3: {}
commander@15.0.0: {}
commander@2.20.3: {}
@@ -14668,6 +14677,10 @@ snapshots:
dependencies:
argparse: 2.0.1
js-yaml@4.2.0:
dependencies:
argparse: 2.0.1
jsdom@24.1.3:
dependencies:
cssstyle: 4.0.1
@@ -16464,6 +16477,8 @@ snapshots:
semver@7.7.4: {}
semver@7.8.4: {}
send@0.19.2:
dependencies:
debug: 2.6.9