From 96c6ab2beb0fbe817c98c1a043549f461b8b3687 Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Fri, 24 Oct 2025 09:56:40 -0400 Subject: [PATCH 1/2] chore: update ESLint configuration to ignore openapi-client directory fix: update import path for OpenAPI client in clientConfig.ts chore: modify openapi-ts configuration to include client-axios plugin chore: bump package versions in package.json and pnpm-lock.yaml fix: update watcher script to use pnpm for generating client on file change --- .../app/openapi-client/client.gen.ts | 24 + .../app/openapi-client/client/client.gen.ts | 163 +++++ .../app/openapi-client/client/index.ts | 23 + .../app/openapi-client/client/types.gen.ts | 216 ++++++ .../app/openapi-client/client/utils.gen.ts | 209 ++++++ .../app/openapi-client/core/auth.gen.ts | 42 ++ .../openapi-client/core/bodySerializer.gen.ts | 92 +++ .../app/openapi-client/core/params.gen.ts | 153 +++++ .../openapi-client/core/pathSerializer.gen.ts | 181 +++++ .../core/serverSentEvents.gen.ts | 264 ++++++++ .../app/openapi-client/core/types.gen.ts | 118 ++++ .../app/openapi-client/core/utils.gen.ts | 143 ++++ nextjs-frontend/app/openapi-client/index.ts | 3 +- nextjs-frontend/app/openapi-client/sdk.gen.ts | 350 ++++++---- .../app/openapi-client/types.gen.ts | 636 ++++++++++++++++-- nextjs-frontend/eslint.config.mjs | 2 +- nextjs-frontend/lib/clientConfig.ts | 2 +- nextjs-frontend/openapi-ts.config.ts | 2 +- nextjs-frontend/package.json | 9 +- nextjs-frontend/pnpm-lock.yaml | 194 ++++-- nextjs-frontend/watcher.js | 2 +- 21 files changed, 2604 insertions(+), 224 deletions(-) create mode 100644 nextjs-frontend/app/openapi-client/client.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/client/client.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/client/index.ts create mode 100644 nextjs-frontend/app/openapi-client/client/types.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/client/utils.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/auth.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/bodySerializer.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/params.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/pathSerializer.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/serverSentEvents.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/types.gen.ts create mode 100644 nextjs-frontend/app/openapi-client/core/utils.gen.ts diff --git a/nextjs-frontend/app/openapi-client/client.gen.ts b/nextjs-frontend/app/openapi-client/client.gen.ts new file mode 100644 index 0000000..5c6d353 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/client.gen.ts @@ -0,0 +1,24 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { ClientOptions } from "./types.gen"; +import { + type ClientOptions as DefaultClientOptions, + type Config, + createClient, + createConfig, +} from "./client"; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = + ( + override?: Config, + ) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/nextjs-frontend/app/openapi-client/client/client.gen.ts b/nextjs-frontend/app/openapi-client/client/client.gen.ts new file mode 100644 index 0000000..ed1dae6 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/client/client.gen.ts @@ -0,0 +1,163 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { AxiosError, AxiosInstance, RawAxiosRequestHeaders } from "axios"; +import axios from "axios"; + +import { createSseClient } from "../core/serverSentEvents.gen"; +import type { HttpMethod } from "../core/types.gen"; +import { getValidRequestBody } from "../core/utils.gen"; +import type { Client, Config, RequestOptions } from "./types.gen"; +import { + buildUrl, + createConfig, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from "./utils.gen"; + +export const createClient = (config: Config = {}): Client => { + let _config = mergeConfigs(createConfig(), config); + + let instance: AxiosInstance; + + if (_config.axios && !("Axios" in _config.axios)) { + instance = _config.axios; + } else { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { auth, ...configWithoutAuth } = _config; + instance = axios.create(configWithoutAuth); + } + + const getConfig = (): Config => ({ ..._config }); + + const setConfig = (config: Config): Config => { + _config = mergeConfigs(_config, config); + instance.defaults = { + ...instance.defaults, + ..._config, + // @ts-expect-error + headers: mergeHeaders(instance.defaults.headers, _config.headers), + }; + return getConfig(); + }; + + const beforeRequest = async (options: RequestOptions) => { + const opts = { + ..._config, + ...options, + axios: options.axios ?? _config.axios ?? instance, + headers: mergeHeaders(_config.headers, options.headers), + }; + + if (opts.security) { + await setAuthParams({ + ...opts, + security: opts.security, + }); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.body = opts.bodySerializer(opts.body); + } + + const url = buildUrl(opts); + + return { opts, url }; + }; + + // @ts-expect-error + const request: Client["request"] = async (options) => { + // @ts-expect-error + const { opts, url } = await beforeRequest(options); + try { + // assign Axios here for consistency with fetch + const _axios = opts.axios!; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { auth, ...optsWithoutAuth } = opts; + const response = await _axios({ + ...optsWithoutAuth, + baseURL: opts.baseURL as string, + data: getValidRequestBody(opts), + headers: opts.headers as RawAxiosRequestHeaders, + // let `paramsSerializer()` handle query params if it exists + params: opts.paramsSerializer ? opts.query : undefined, + url, + }); + + let { data } = response; + + if (opts.responseType === "json") { + if (opts.responseValidator) { + await opts.responseValidator(data); + } + + if (opts.responseTransformer) { + data = await opts.responseTransformer(data); + } + } + + return { + ...response, + data: data ?? {}, + }; + } catch (error) { + const e = error as AxiosError; + if (opts.throwOnError) { + throw e; + } + // @ts-expect-error + e.error = e.response?.data ?? {}; + return e; + } + }; + + const makeMethodFn = + (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = + (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + headers: opts.headers as Record, + method, + // @ts-expect-error + signal: opts.signal, + url, + }); + }; + + return { + buildUrl, + connect: makeMethodFn("CONNECT"), + delete: makeMethodFn("DELETE"), + get: makeMethodFn("GET"), + getConfig, + head: makeMethodFn("HEAD"), + instance, + options: makeMethodFn("OPTIONS"), + patch: makeMethodFn("PATCH"), + post: makeMethodFn("POST"), + put: makeMethodFn("PUT"), + request, + setConfig, + sse: { + connect: makeSseFn("CONNECT"), + delete: makeSseFn("DELETE"), + get: makeSseFn("GET"), + head: makeSseFn("HEAD"), + options: makeSseFn("OPTIONS"), + patch: makeSseFn("PATCH"), + post: makeSseFn("POST"), + put: makeSseFn("PUT"), + trace: makeSseFn("TRACE"), + }, + trace: makeMethodFn("TRACE"), + } as Client; +}; diff --git a/nextjs-frontend/app/openapi-client/client/index.ts b/nextjs-frontend/app/openapi-client/client/index.ts new file mode 100644 index 0000000..cbf8d79 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/client/index.ts @@ -0,0 +1,23 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from "../core/auth.gen"; +export type { QuerySerializerOptions } from "../core/bodySerializer.gen"; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from "../core/bodySerializer.gen"; +export { buildClientParams } from "../core/params.gen"; +export { createClient } from "./client.gen"; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + OptionsLegacyParser, + RequestOptions, + RequestResult, + TDataShape, +} from "./types.gen"; +export { createConfig } from "./utils.gen"; diff --git a/nextjs-frontend/app/openapi-client/client/types.gen.ts b/nextjs-frontend/app/openapi-client/client/types.gen.ts new file mode 100644 index 0000000..0125b25 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/client/types.gen.ts @@ -0,0 +1,216 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { + AxiosError, + AxiosInstance, + AxiosRequestHeaders, + AxiosResponse, + AxiosStatic, + CreateAxiosDefaults, +} from "axios"; + +import type { Auth } from "../core/auth.gen"; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from "../core/serverSentEvents.gen"; +import type { + Client as CoreClient, + Config as CoreConfig, +} from "../core/types.gen"; + +export interface Config + extends Omit, + CoreConfig { + /** + * Axios implementation. You can use this option to provide either an + * `AxiosStatic` or an `AxiosInstance`. + * + * @default axios + */ + axios?: AxiosStatic | AxiosInstance; + /** + * Base URL for all requests made by this client. + */ + baseURL?: T["baseURL"]; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | AxiosRequestHeaders + | Record< + string, + | string + | number + | boolean + | (string | number | boolean)[] + | null + | undefined + | unknown + >; + /** + * Throw an error instead of returning it in the response? + * + * @default false + */ + throwOnError?: T["throwOnError"]; +} + +export interface RequestOptions< + TData = unknown, + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends Config<{ + throwOnError: ThrowOnError; + }>, + Pick< + ServerSentEventsOptions, + | "onSseError" + | "onSseEvent" + | "sseDefaultRetryDelay" + | "sseMaxRetryAttempts" + | "sseMaxRetryDelay" + > { + /** + * Any body that you want to add to your request. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} + */ + body?: unknown; + path?: Record; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ClientOptions { + baseURL?: string; + throwOnError?: boolean; +} + +export type RequestResult< + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = boolean, +> = ThrowOnError extends true + ? Promise< + AxiosResponse< + TData extends Record ? TData[keyof TData] : TData + > + > + : Promise< + | (AxiosResponse< + TData extends Record ? TData[keyof TData] : TData + > & { error: undefined }) + | (AxiosError< + TError extends Record ? TError[keyof TError] : TError + > & { + data: undefined; + error: TError extends Record + ? TError[keyof TError] + : TError; + }) + >; + +type MethodFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, +>( + options: Omit, "method">, +) => RequestResult; + +type SseFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, +>( + options: Omit, "method">, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, +>( + options: Omit, "method"> & + Pick>, "method">, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: Pick & Omit, "axios">, +) => string; + +export type Client = CoreClient< + RequestFn, + Config, + MethodFn, + BuildUrlFn, + SseFn +> & { + instance: AxiosInstance; +}; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, +> = OmitKeys< + RequestOptions, + "body" | "path" | "query" | "url" +> & + Omit; + +export type OptionsLegacyParser< + TData = unknown, + ThrowOnError extends boolean = boolean, +> = TData extends { body?: any } + ? TData extends { headers?: any } + ? OmitKeys< + RequestOptions, + "body" | "headers" | "url" + > & + TData + : OmitKeys, "body" | "url"> & + TData & + Pick, "headers"> + : TData extends { headers?: any } + ? OmitKeys, "headers" | "url"> & + TData & + Pick, "body"> + : OmitKeys, "url"> & TData; diff --git a/nextjs-frontend/app/openapi-client/client/utils.gen.ts b/nextjs-frontend/app/openapi-client/client/utils.gen.ts new file mode 100644 index 0000000..31e07ba --- /dev/null +++ b/nextjs-frontend/app/openapi-client/client/utils.gen.ts @@ -0,0 +1,209 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from "../core/auth.gen"; +import type { QuerySerializerOptions } from "../core/bodySerializer.gen"; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from "../core/pathSerializer.gen"; +import { getUrl } from "../core/utils.gen"; +import type { + Client, + ClientOptions, + Config, + RequestOptions, +} from "./types.gen"; + +export const createQuerySerializer = ({ + allowReserved, + array, + object, +}: QuerySerializerOptions = {}) => { + const querySerializer = (queryParams: T) => { + const search: string[] = []; + if (queryParams && typeof queryParams === "object") { + for (const name in queryParams) { + const value = queryParams[name]; + + if (value === undefined || value === null) { + continue; + } + + if (Array.isArray(value)) { + const serializedArray = serializeArrayParam({ + allowReserved, + explode: true, + name, + style: "form", + value, + ...array, + }); + if (serializedArray) search.push(serializedArray); + } else if (typeof value === "object") { + const serializedObject = serializeObjectParam({ + allowReserved, + explode: true, + name, + style: "deepObject", + value: value as Record, + ...object, + }); + if (serializedObject) search.push(serializedObject); + } else { + const serializedPrimitive = serializePrimitiveParam({ + allowReserved, + name, + value: value as string, + }); + if (serializedPrimitive) search.push(serializedPrimitive); + } + } + } + return search.join("&"); + }; + return querySerializer; +}; + +const checkForExistence = ( + options: Pick & { + headers: Record; + }, + name?: string, +): boolean => { + if (!name) { + return false; + } + if (name in options.headers || options.query?.[name]) { + return true; + } + if ( + "Cookie" in options.headers && + options.headers["Cookie"] && + typeof options.headers["Cookie"] === "string" + ) { + return options.headers["Cookie"].includes(`${name}=`); + } + return false; +}; + +export const setAuthParams = async ({ + security, + ...options +}: Pick, "security"> & + Pick & { + headers: Record; + }) => { + for (const auth of security) { + if (checkForExistence(options, auth.name)) { + continue; + } + const token = await getAuthToken(auth, options.auth); + + if (!token) { + continue; + } + + const name = auth.name ?? "Authorization"; + + switch (auth.in) { + case "query": + if (!options.query) { + options.query = {}; + } + options.query[name] = token; + break; + case "cookie": { + const value = `${name}=${token}`; + if ("Cookie" in options.headers && options.headers["Cookie"]) { + options.headers["Cookie"] = `${options.headers["Cookie"]}; ${value}`; + } else { + options.headers["Cookie"] = value; + } + break; + } + case "header": + default: + options.headers[name] = token; + break; + } + } +}; + +export const buildUrl: Client["buildUrl"] = (options) => + getUrl({ + baseUrl: options.baseURL as string, + path: options.path, + // let `paramsSerializer()` handle query params if it exists + query: !options.paramsSerializer ? options.query : undefined, + querySerializer: + typeof options.querySerializer === "function" + ? options.querySerializer + : createQuerySerializer(options.querySerializer), + url: options.url, + }); + +export const mergeConfigs = (a: Config, b: Config): Config => { + const config = { ...a, ...b }; + config.headers = mergeHeaders(a.headers, b.headers); + return config; +}; + +/** + * Special Axios headers keywords allowing to set headers by request method. + */ +export const axiosHeadersKeywords = [ + "common", + "delete", + "get", + "head", + "patch", + "post", + "put", +] as const; + +export const mergeHeaders = ( + ...headers: Array["headers"] | undefined> +): Record => { + const mergedHeaders: Record = {}; + for (const header of headers) { + if (!header || typeof header !== "object") { + continue; + } + + const iterator = Object.entries(header); + + for (const [key, value] of iterator) { + if ( + axiosHeadersKeywords.includes( + key as (typeof axiosHeadersKeywords)[number], + ) && + typeof value === "object" + ) { + mergedHeaders[key] = { + ...(mergedHeaders[key] as Record), + ...value, + }; + } else if (value === null) { + delete mergedHeaders[key]; + } else if (Array.isArray(value)) { + for (const v of value) { + // @ts-expect-error + mergedHeaders[key] = [...(mergedHeaders[key] ?? []), v as string]; + } + } else if (value !== undefined) { + // assume object headers are meant to be JSON stringified, i.e. their + // content value in OpenAPI specification is 'application/json' + mergedHeaders[key] = + typeof value === "object" ? JSON.stringify(value) : (value as string); + } + } + } + return mergedHeaders; +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...override, +}); diff --git a/nextjs-frontend/app/openapi-client/core/auth.gen.ts b/nextjs-frontend/app/openapi-client/core/auth.gen.ts new file mode 100644 index 0000000..3d74115 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/auth.gen.ts @@ -0,0 +1,42 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AuthToken = string | undefined; + +export interface Auth { + /** + * Which part of the request do we use to send the auth? + * + * @default 'header' + */ + in?: "header" | "query" | "cookie"; + /** + * Header or query parameter name. + * + * @default 'Authorization' + */ + name?: string; + scheme?: "basic" | "bearer"; + type: "apiKey" | "http"; +} + +export const getAuthToken = async ( + auth: Auth, + callback: ((auth: Auth) => Promise | AuthToken) | AuthToken, +): Promise => { + const token = + typeof callback === "function" ? await callback(auth) : callback; + + if (!token) { + return; + } + + if (auth.scheme === "bearer") { + return `Bearer ${token}`; + } + + if (auth.scheme === "basic") { + return `Basic ${btoa(token)}`; + } + + return token; +}; diff --git a/nextjs-frontend/app/openapi-client/core/bodySerializer.gen.ts b/nextjs-frontend/app/openapi-client/core/bodySerializer.gen.ts new file mode 100644 index 0000000..8f4ffc5 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/bodySerializer.gen.ts @@ -0,0 +1,92 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { + ArrayStyle, + ObjectStyle, + SerializerOptions, +} from "./pathSerializer.gen"; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: any) => any; + +export interface QuerySerializerOptions { + allowReserved?: boolean; + array?: SerializerOptions; + object?: SerializerOptions; +} + +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)); + } +}; + +const serializeUrlSearchParamsPair = ( + data: URLSearchParams, + key: string, + value: unknown, +): void => { + if (typeof value === "string") { + data.append(key, value); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +export const formDataBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): FormData => { + const data = new FormData(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeFormDataPair(data, key, v)); + } else { + serializeFormDataPair(data, key, value); + } + }); + + return data; + }, +}; + +export const jsonBodySerializer = { + bodySerializer: (body: T): string => + JSON.stringify(body, (_key, value) => + typeof value === "bigint" ? value.toString() : value, + ), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): string => { + const data = new URLSearchParams(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); + } else { + serializeUrlSearchParamsPair(data, key, value); + } + }); + + return data.toString(); + }, +}; diff --git a/nextjs-frontend/app/openapi-client/core/params.gen.ts b/nextjs-frontend/app/openapi-client/core/params.gen.ts new file mode 100644 index 0000000..6527557 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/params.gen.ts @@ -0,0 +1,153 @@ +// This file is auto-generated by @hey-api/openapi-ts + +type Slot = "body" | "headers" | "path" | "query"; + +export type Field = + | { + in: Exclude; + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If omitted, we use the same value as `key`. + */ + map?: string; + } + | { + in: Extract; + /** + * Key isn't required for bodies. + */ + key?: string; + map?: string; + }; + +export interface Fields { + allowExtra?: Partial>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $body_: "body", + $headers_: "headers", + $path_: "path", + $query_: "query", +}; +const extraPrefixes = Object.entries(extraPrefixesMap); + +type KeyMap = Map< + string, + { + in: Slot; + map?: string; + } +>; + +const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { + if (!map) { + map = new Map(); + } + + for (const config of fields) { + if ("in" in config) { + if (config.key) { + map.set(config.key, { + in: config.in, + map: config.map, + }); + } + } else if (config.args) { + buildKeyMap(config.args, map); + } + } + + return map; +}; + +interface Params { + body: unknown; + headers: Record; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === "object" && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = ( + args: ReadonlyArray, + fields: FieldsConfig, +) => { + const params: Params = { + body: {}, + headers: {}, + path: {}, + query: {}, + }; + + const map = buildKeyMap(fields); + + let config: FieldsConfig[number] | undefined; + + for (const [index, arg] of args.entries()) { + if (fields[index]) { + config = fields[index]; + } + + if (!config) { + continue; + } + + if ("in" in config) { + if (config.key) { + const field = map.get(config.key)!; + const name = field.map || config.key; + (params[field.in] as Record)[name] = arg; + } else { + params.body = arg; + } + } else { + for (const [key, value] of Object.entries(arg ?? {})) { + const field = map.get(key); + + if (field) { + const name = field.map || key; + (params[field.in] as Record)[name] = value; + } else { + const extra = extraPrefixes.find(([prefix]) => + key.startsWith(prefix), + ); + + if (extra) { + const [prefix, slot] = extra; + (params[slot] as Record)[ + key.slice(prefix.length) + ] = value; + } else { + for (const [slot, allowed] of Object.entries( + config.allowExtra ?? {}, + )) { + if (allowed) { + (params[slot as Slot] as Record)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/nextjs-frontend/app/openapi-client/core/pathSerializer.gen.ts b/nextjs-frontend/app/openapi-client/core/pathSerializer.gen.ts new file mode 100644 index 0000000..034aa68 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/pathSerializer.gen.ts @@ -0,0 +1,181 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions + extends SerializePrimitiveOptions, + SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @default true + */ + explode: boolean; + style: T; +} + +export type ArrayStyle = "form" | "spaceDelimited" | "pipeDelimited"; +export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; +type MatrixStyle = "label" | "matrix" | "simple"; +export type ObjectStyle = "form" | "deepObject"; +type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; + +interface SerializePrimitiveParam extends SerializePrimitiveOptions { + value: string; +} + +export const separatorArrayExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case "label": + return "."; + case "matrix": + return ";"; + case "simple": + return ","; + default: + return "&"; + } +}; + +export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case "form": + return ","; + case "pipeDelimited": + return "|"; + case "spaceDelimited": + return "%20"; + default: + return ","; + } +}; + +export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { + switch (style) { + case "label": + return "."; + case "matrix": + return ";"; + case "simple": + return ","; + default: + return "&"; + } +}; + +export const serializeArrayParam = ({ + allowReserved, + explode, + name, + style, + value, +}: SerializeOptions & { + value: unknown[]; +}) => { + if (!explode) { + const joinedValues = ( + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) + ).join(separatorArrayNoExplode(style)); + switch (style) { + case "label": + return `.${joinedValues}`; + case "matrix": + return `;${name}=${joinedValues}`; + case "simple": + return joinedValues; + default: + return `${name}=${joinedValues}`; + } + } + + const separator = separatorArrayExplode(style); + const joinedValues = value + .map((v) => { + if (style === "label" || style === "simple") { + return allowReserved ? v : encodeURIComponent(v as string); + } + + return serializePrimitiveParam({ + allowReserved, + name, + value: v as string, + }); + }) + .join(separator); + return style === "label" || style === "matrix" + ? separator + joinedValues + : joinedValues; +}; + +export const serializePrimitiveParam = ({ + allowReserved, + name, + value, +}: SerializePrimitiveParam) => { + if (value === undefined || value === null) { + return ""; + } + + if (typeof value === "object") { + throw new Error( + "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.", + ); + } + + return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; +}; + +export const serializeObjectParam = ({ + allowReserved, + explode, + name, + style, + value, + valueOnly, +}: SerializeOptions & { + value: Record | Date; + valueOnly?: boolean; +}) => { + if (value instanceof Date) { + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; + } + + if (style !== "deepObject" && !explode) { + let values: string[] = []; + Object.entries(value).forEach(([key, v]) => { + values = [ + ...values, + key, + allowReserved ? (v as string) : encodeURIComponent(v as string), + ]; + }); + const joinedValues = values.join(","); + switch (style) { + case "form": + return `${name}=${joinedValues}`; + case "label": + return `.${joinedValues}`; + case "matrix": + return `;${name}=${joinedValues}`; + default: + return joinedValues; + } + } + + const separator = separatorObjectExplode(style); + const joinedValues = Object.entries(value) + .map(([key, v]) => + serializePrimitiveParam({ + allowReserved, + name: style === "deepObject" ? `${name}[${key}]` : key, + value: v as string, + }), + ) + .join(separator); + return style === "label" || style === "matrix" + ? separator + joinedValues + : joinedValues; +}; diff --git a/nextjs-frontend/app/openapi-client/core/serverSentEvents.gen.ts b/nextjs-frontend/app/openapi-client/core/serverSentEvents.gen.ts new file mode 100644 index 0000000..06ae880 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/serverSentEvents.gen.ts @@ -0,0 +1,264 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from "./types.gen"; + +export type ServerSentEventsOptions = Omit< + RequestInit, + "method" +> & + Pick & { + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch; + /** + * Implementing clients can call request interceptors inside this hook. + */ + onRequest?: (url: string, init: RequestInit) => Promise; + /** + * 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) => void; + serializedBody?: RequestInit["body"]; + /** + * 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; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult< + TData = unknown, + TReturn = void, + TNext = unknown, +> = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export const createSseClient = ({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult => { + 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 | undefined); + + if (lastEventId !== undefined) { + headers.set("Last-Event-ID", lastEventId); + } + + try { + const requestInit: RequestInit = { + redirect: "follow", + ...options, + body: options.serializedBody, + headers, + signal, + }; + let request = new Request(url, requestInit); + if (onRequest) { + request = await onRequest(url, requestInit); + } + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = options.fetch ?? globalThis.fetch; + const response = await _fetch(request); + + 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 = []; + 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/nextjs-frontend/app/openapi-client/core/types.gen.ts b/nextjs-frontend/app/openapi-client/core/types.gen.ts new file mode 100644 index 0000000..6b23d10 --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/types.gen.ts @@ -0,0 +1,118 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from "./auth.gen"; +import type { + BodySerializer, + QuerySerializer, + QuerySerializerOptions, +} from "./bodySerializer.gen"; + +export type HttpMethod = + | "connect" + | "delete" + | "get" + | "head" + | "options" + | "patch" + | "post" + | "put" + | "trace"; + +export type Client< + RequestFn = never, + Config = unknown, + MethodFn = never, + BuildUrlFn = never, + SseFn = never, +> = { + /** + * Returns the final request URL. + */ + buildUrl: BuildUrlFn; + getConfig: () => Config; + request: RequestFn; + setConfig: (config: Config) => Config; +} & { + [K in HttpMethod]: MethodFn; +} & ([SseFn] extends [never] + ? { sse?: never } + : { sse: { [K in HttpMethod]: SseFn } }); + +export interface Config { + /** + * Auth token or a function returning auth token. The resolved value will be + * added to the request payload as defined by its `security` array. + */ + auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken; + /** + * A function for serializing request body parameter. By default, + * {@link JSON.stringify()} will be used. + */ + bodySerializer?: BodySerializer | null; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | RequestInit["headers"] + | Record< + string, + | string + | number + | boolean + | (string | number | boolean)[] + | null + | undefined + | unknown + >; + /** + * The request method. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} + */ + method?: Uppercase; + /** + * A function for serializing request query parameters. By default, arrays + * will be exploded in form style, objects will be exploded in deepObject + * style, and reserved characters are percent-encoded. + * + * This method will have no effect if the native `paramsSerializer()` Axios + * API function is used. + * + * {@link https://swagger.io/docs/specification/serialization/#query View examples} + */ + querySerializer?: QuerySerializer | QuerySerializerOptions; + /** + * A function validating request data. This is useful if you want to ensure + * the request conforms to the desired shape, so it can be safely sent to + * the server. + */ + requestValidator?: (data: unknown) => Promise; + /** + * A function transforming response data before it's returned. This is useful + * for post-processing data, e.g. converting ISO strings into Date objects. + */ + responseTransformer?: (data: unknown) => Promise; + /** + * A function validating response data. This is useful if you want to ensure + * the response conforms to the desired shape, so it can be safely passed to + * the transformers and returned to the user. + */ + responseValidator?: (data: unknown) => Promise; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true + ? never + : K]: T[K]; +}; diff --git a/nextjs-frontend/app/openapi-client/core/utils.gen.ts b/nextjs-frontend/app/openapi-client/core/utils.gen.ts new file mode 100644 index 0000000..80fbfff --- /dev/null +++ b/nextjs-frontend/app/openapi-client/core/utils.gen.ts @@ -0,0 +1,143 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from "./bodySerializer.gen"; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from "./pathSerializer.gen"; + +export interface PathSerializer { + path: Record; + 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, + 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; + query?: Record; + 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 function getValidRequestBody(options: { + body?: unknown; + bodySerializer?: BodySerializer | null; + serializedBody?: unknown; +}) { + const hasBody = options.body !== undefined; + const isSerializedBody = hasBody && options.bodySerializer; + + if (isSerializedBody) { + if ("serializedBody" in options) { + const hasSerializedBody = + options.serializedBody !== undefined && options.serializedBody !== ""; + + return hasSerializedBody ? options.serializedBody : null; + } + + // not all clients implement a serializedBody property (i.e. client-axios) + return options.body !== "" ? options.body : null; + } + + // plain/text body + if (hasBody) { + return options.body; + } + + // no body was provided + return undefined; +} diff --git a/nextjs-frontend/app/openapi-client/index.ts b/nextjs-frontend/app/openapi-client/index.ts index eae885d..a6d2363 100644 --- a/nextjs-frontend/app/openapi-client/index.ts +++ b/nextjs-frontend/app/openapi-client/index.ts @@ -1,3 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export * from "./sdk.gen"; + export * from "./types.gen"; +export * from "./sdk.gen"; diff --git a/nextjs-frontend/app/openapi-client/sdk.gen.ts b/nextjs-frontend/app/openapi-client/sdk.gen.ts index 89692d7..61c543e 100644 --- a/nextjs-frontend/app/openapi-client/sdk.gen.ts +++ b/nextjs-frontend/app/openapi-client/sdk.gen.ts @@ -1,77 +1,96 @@ // This file is auto-generated by @hey-api/openapi-ts import { - createClient, - createConfig, - type OptionsLegacyParser, + type Options as ClientOptions, + type Client, + type TDataShape, urlSearchParamsBodySerializer, -} from "@hey-api/client-axios"; +} from "./client"; import type { AuthJwtLoginData, - AuthJwtLoginError, - AuthJwtLoginResponse, - AuthJwtLogoutError, - AuthJwtLogoutResponse, + AuthJwtLoginResponses, + AuthJwtLoginErrors, + AuthJwtLogoutData, + AuthJwtLogoutResponses, + AuthJwtLogoutErrors, RegisterRegisterData, - RegisterRegisterError, - RegisterRegisterResponse, + RegisterRegisterResponses, + RegisterRegisterErrors, ResetForgotPasswordData, - ResetForgotPasswordError, - ResetForgotPasswordResponse, + ResetForgotPasswordResponses, + ResetForgotPasswordErrors, ResetResetPasswordData, - ResetResetPasswordError, - ResetResetPasswordResponse, + ResetResetPasswordResponses, + ResetResetPasswordErrors, VerifyRequestTokenData, - VerifyRequestTokenError, - VerifyRequestTokenResponse, + VerifyRequestTokenResponses, + VerifyRequestTokenErrors, VerifyVerifyData, - VerifyVerifyError, - VerifyVerifyResponse, - UsersCurrentUserError, - UsersCurrentUserResponse, + VerifyVerifyResponses, + VerifyVerifyErrors, + UsersCurrentUserData, + UsersCurrentUserResponses, + UsersCurrentUserErrors, UsersPatchCurrentUserData, - UsersPatchCurrentUserError, - UsersPatchCurrentUserResponse, + UsersPatchCurrentUserResponses, + UsersPatchCurrentUserErrors, + UsersDeleteUserData, + UsersDeleteUserResponses, + UsersDeleteUserErrors, UsersUserData, - UsersUserError, - UsersUserResponse, + UsersUserResponses, + UsersUserErrors, UsersPatchUserData, - UsersPatchUserError, - UsersPatchUserResponse, - UsersDeleteUserData, - UsersDeleteUserError, - UsersDeleteUserResponse, + UsersPatchUserResponses, + UsersPatchUserErrors, ReadItemData, - ReadItemError, - ReadItemResponse, + ReadItemResponses, + ReadItemErrors, CreateItemData, - CreateItemError, - CreateItemResponse, + CreateItemResponses, + CreateItemErrors, DeleteItemData, - DeleteItemError, - DeleteItemResponse, + DeleteItemResponses, + DeleteItemErrors, } from "./types.gen"; +import { client } from "./client.gen"; -export const client = createClient(createConfig()); +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, +> = ClientOptions & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; /** * Auth:Jwt.Login */ export const authJwtLogin = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - AuthJwtLoginResponse, - AuthJwtLoginError, + return (options.client ?? client).post< + AuthJwtLoginResponses, + AuthJwtLoginErrors, ThrowOnError >({ - ...options, ...urlSearchParamsBodySerializer, + responseType: "json", + url: "/auth/jwt/login", + ...options, headers: { "Content-Type": "application/x-www-form-urlencoded", - ...options?.headers, + ...options.headers, }, - url: "/auth/jwt/login", }); }; @@ -79,15 +98,22 @@ export const authJwtLogin = ( * Auth:Jwt.Logout */ export const authJwtLogout = ( - options?: OptionsLegacyParser, + options?: Options, ) => { return (options?.client ?? client).post< - AuthJwtLogoutResponse, - AuthJwtLogoutError, + AuthJwtLogoutResponses, + AuthJwtLogoutErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/auth/jwt/logout", + ...options, }); }; @@ -95,15 +121,20 @@ export const authJwtLogout = ( * Register:Register */ export const registerRegister = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - RegisterRegisterResponse, - RegisterRegisterError, + return (options.client ?? client).post< + RegisterRegisterResponses, + RegisterRegisterErrors, ThrowOnError >({ - ...options, + responseType: "json", url: "/auth/register", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -111,15 +142,20 @@ export const registerRegister = ( * Reset:Forgot Password */ export const resetForgotPassword = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - ResetForgotPasswordResponse, - ResetForgotPasswordError, + return (options.client ?? client).post< + ResetForgotPasswordResponses, + ResetForgotPasswordErrors, ThrowOnError >({ - ...options, + responseType: "json", url: "/auth/forgot-password", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -127,15 +163,20 @@ export const resetForgotPassword = ( * Reset:Reset Password */ export const resetResetPassword = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - ResetResetPasswordResponse, - ResetResetPasswordError, + return (options.client ?? client).post< + ResetResetPasswordResponses, + ResetResetPasswordErrors, ThrowOnError >({ - ...options, + responseType: "json", url: "/auth/reset-password", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -143,15 +184,20 @@ export const resetResetPassword = ( * Verify:Request-Token */ export const verifyRequestToken = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - VerifyRequestTokenResponse, - VerifyRequestTokenError, + return (options.client ?? client).post< + VerifyRequestTokenResponses, + VerifyRequestTokenErrors, ThrowOnError >({ - ...options, + responseType: "json", url: "/auth/request-verify-token", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -159,15 +205,20 @@ export const verifyRequestToken = ( * Verify:Verify */ export const verifyVerify = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - VerifyVerifyResponse, - VerifyVerifyError, + return (options.client ?? client).post< + VerifyVerifyResponses, + VerifyVerifyErrors, ThrowOnError >({ - ...options, + responseType: "json", url: "/auth/verify", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -175,15 +226,22 @@ export const verifyVerify = ( * Users:Current User */ export const usersCurrentUser = ( - options?: OptionsLegacyParser, + options?: Options, ) => { return (options?.client ?? client).get< - UsersCurrentUserResponse, - UsersCurrentUserError, + UsersCurrentUserResponses, + UsersCurrentUserErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/users/me", + ...options, }); }; @@ -191,63 +249,98 @@ export const usersCurrentUser = ( * Users:Patch Current User */ export const usersPatchCurrentUser = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).patch< - UsersPatchCurrentUserResponse, - UsersPatchCurrentUserError, + return (options.client ?? client).patch< + UsersPatchCurrentUserResponses, + UsersPatchCurrentUserErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/users/me", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; /** - * Users:User + * Users:Delete User */ -export const usersUser = ( - options: OptionsLegacyParser, +export const usersDeleteUser = ( + options: Options, ) => { - return (options?.client ?? client).get< - UsersUserResponse, - UsersUserError, + return (options.client ?? client).delete< + UsersDeleteUserResponses, + UsersDeleteUserErrors, ThrowOnError >({ - ...options, + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/users/{id}", + ...options, }); }; /** - * Users:Patch User + * Users:User */ -export const usersPatchUser = ( - options: OptionsLegacyParser, +export const usersUser = ( + options: Options, ) => { - return (options?.client ?? client).patch< - UsersPatchUserResponse, - UsersPatchUserError, + return (options.client ?? client).get< + UsersUserResponses, + UsersUserErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/users/{id}", + ...options, }); }; /** - * Users:Delete User + * Users:Patch User */ -export const usersDeleteUser = ( - options: OptionsLegacyParser, +export const usersPatchUser = ( + options: Options, ) => { - return (options?.client ?? client).delete< - UsersDeleteUserResponse, - UsersDeleteUserError, + return (options.client ?? client).patch< + UsersPatchUserResponses, + UsersPatchUserErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/users/{id}", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -255,15 +348,22 @@ export const usersDeleteUser = ( * Read Item */ export const readItem = ( - options?: OptionsLegacyParser, + options?: Options, ) => { return (options?.client ?? client).get< - ReadItemResponse, - ReadItemError, + ReadItemResponses, + ReadItemErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/items/", + ...options, }); }; @@ -271,15 +371,26 @@ export const readItem = ( * Create Item */ export const createItem = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).post< - CreateItemResponse, - CreateItemError, + return (options.client ?? client).post< + CreateItemResponses, + CreateItemErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/items/", + ...options, + headers: { + "Content-Type": "application/json", + ...options.headers, + }, }); }; @@ -287,14 +398,21 @@ export const createItem = ( * Delete Item */ export const deleteItem = ( - options: OptionsLegacyParser, + options: Options, ) => { - return (options?.client ?? client).delete< - DeleteItemResponse, - DeleteItemError, + return (options.client ?? client).delete< + DeleteItemResponses, + DeleteItemErrors, ThrowOnError >({ - ...options, + responseType: "json", + security: [ + { + scheme: "bearer", + type: "http", + }, + ], url: "/items/{item_id}", + ...options, }); }; diff --git a/nextjs-frontend/app/openapi-client/types.gen.ts b/nextjs-frontend/app/openapi-client/types.gen.ts index 6a55f1e..8a9ff89 100644 --- a/nextjs-frontend/app/openapi-client/types.gen.ts +++ b/nextjs-frontend/app/openapi-client/types.gen.ts @@ -1,28 +1,70 @@ // This file is auto-generated by @hey-api/openapi-ts +/** + * BearerResponse + */ export type BearerResponse = { + /** + * Access Token + */ access_token: string; + /** + * Token Type + */ token_type: string; }; -export type Body_auth_reset_forgot_password = { +/** + * Body_auth-reset:forgot_password + */ +export type BodyAuthResetForgotPassword = { + /** + * Email + */ email: string; }; -export type Body_auth_reset_reset_password = { +/** + * Body_auth-reset:reset_password + */ +export type BodyAuthResetResetPassword = { + /** + * Token + */ token: string; + /** + * Password + */ password: string; }; -export type Body_auth_verify_request_token = { +/** + * Body_auth-verify:request-token + */ +export type BodyAuthVerifyRequestToken = { + /** + * Email + */ email: string; }; -export type Body_auth_verify_verify = { +/** + * Body_auth-verify:verify + */ +export type BodyAuthVerifyVerify = { + /** + * Token + */ token: string; }; +/** + * ErrorModel + */ export type ErrorModel = { + /** + * Detail + */ detail: | string | { @@ -30,200 +72,682 @@ export type ErrorModel = { }; }; -export type HTTPValidationError = { +/** + * HTTPValidationError + */ +export type HttpValidationError = { + /** + * Detail + */ detail?: Array; }; +/** + * ItemCreate + */ export type ItemCreate = { + /** + * Name + */ name: string; + /** + * Description + */ description?: string | null; + /** + * Quantity + */ quantity?: number | null; }; +/** + * ItemRead + */ export type ItemRead = { + /** + * Name + */ name: string; + /** + * Description + */ description?: string | null; + /** + * Quantity + */ quantity?: number | null; + /** + * Id + */ id: string; + /** + * User Id + */ user_id: string; }; -export type login = { - grant_type?: string | null; - username: string; - password: string; - scope?: string; - client_id?: string | null; - client_secret?: string | null; -}; - -export type Page_ItemRead_ = { +/** + * Page[ItemRead] + */ +export type PageItemRead = { + /** + * Items + */ items: Array; + /** + * Total + */ total?: number | null; + /** + * Page + */ page: number | null; + /** + * Size + */ size: number | null; + /** + * Pages + */ pages?: number | null; }; +/** + * UserCreate + */ export type UserCreate = { + /** + * Email + */ email: string; + /** + * Password + */ password: string; + /** + * Is Active + */ is_active?: boolean | null; + /** + * Is Superuser + */ is_superuser?: boolean | null; + /** + * Is Verified + */ is_verified?: boolean | null; }; +/** + * UserRead + */ export type UserRead = { + /** + * Id + */ id: string; + /** + * Email + */ email: string; + /** + * Is Active + */ is_active?: boolean; + /** + * Is Superuser + */ is_superuser?: boolean; + /** + * Is Verified + */ is_verified?: boolean; }; +/** + * UserUpdate + */ export type UserUpdate = { + /** + * Password + */ password?: string | null; + /** + * Email + */ email?: string | null; + /** + * Is Active + */ is_active?: boolean | null; + /** + * Is Superuser + */ is_superuser?: boolean | null; + /** + * Is Verified + */ is_verified?: boolean | null; }; +/** + * ValidationError + */ export type ValidationError = { + /** + * Location + */ loc: Array; + /** + * Message + */ msg: string; + /** + * Error Type + */ type: string; }; +/** + * Body_auth-auth:jwt.login + */ +export type Login = { + /** + * Grant Type + */ + grant_type?: string | null; + /** + * Username + */ + username: string; + /** + * Password + */ + password: string; + /** + * Scope + */ + scope?: string; + /** + * Client Id + */ + client_id?: string | null; + /** + * Client Secret + */ + client_secret?: string | null; +}; + export type AuthJwtLoginData = { - body: login; + body: Login; + path?: never; + query?: never; + url: "/auth/jwt/login"; }; -export type AuthJwtLoginResponse = BearerResponse; +export type AuthJwtLoginErrors = { + /** + * Bad Request + */ + 400: ErrorModel; + /** + * Validation Error + */ + 422: HttpValidationError; +}; -export type AuthJwtLoginError = ErrorModel | HTTPValidationError; +export type AuthJwtLoginError = AuthJwtLoginErrors[keyof AuthJwtLoginErrors]; -export type AuthJwtLogoutResponse = unknown; +export type AuthJwtLoginResponses = { + /** + * Successful Response + */ + 200: BearerResponse; +}; + +export type AuthJwtLoginResponse = + AuthJwtLoginResponses[keyof AuthJwtLoginResponses]; + +export type AuthJwtLogoutData = { + body?: never; + path?: never; + query?: never; + url: "/auth/jwt/logout"; +}; + +export type AuthJwtLogoutErrors = { + /** + * Missing token or inactive user. + */ + 401: unknown; +}; -export type AuthJwtLogoutError = unknown; +export type AuthJwtLogoutResponses = { + /** + * Successful Response + */ + 200: unknown; +}; export type RegisterRegisterData = { body: UserCreate; + path?: never; + query?: never; + url: "/auth/register"; +}; + +export type RegisterRegisterErrors = { + /** + * Bad Request + */ + 400: ErrorModel; + /** + * Validation Error + */ + 422: HttpValidationError; }; -export type RegisterRegisterResponse = UserRead; +export type RegisterRegisterError = + RegisterRegisterErrors[keyof RegisterRegisterErrors]; -export type RegisterRegisterError = ErrorModel | HTTPValidationError; +export type RegisterRegisterResponses = { + /** + * Successful Response + */ + 201: UserRead; +}; + +export type RegisterRegisterResponse = + RegisterRegisterResponses[keyof RegisterRegisterResponses]; export type ResetForgotPasswordData = { - body: Body_auth_reset_forgot_password; + body: BodyAuthResetForgotPassword; + path?: never; + query?: never; + url: "/auth/forgot-password"; +}; + +export type ResetForgotPasswordErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; }; -export type ResetForgotPasswordResponse = unknown; +export type ResetForgotPasswordError = + ResetForgotPasswordErrors[keyof ResetForgotPasswordErrors]; -export type ResetForgotPasswordError = HTTPValidationError; +export type ResetForgotPasswordResponses = { + /** + * Successful Response + */ + 202: unknown; +}; export type ResetResetPasswordData = { - body: Body_auth_reset_reset_password; + body: BodyAuthResetResetPassword; + path?: never; + query?: never; + url: "/auth/reset-password"; +}; + +export type ResetResetPasswordErrors = { + /** + * Bad Request + */ + 400: ErrorModel; + /** + * Validation Error + */ + 422: HttpValidationError; }; -export type ResetResetPasswordResponse = unknown; +export type ResetResetPasswordError = + ResetResetPasswordErrors[keyof ResetResetPasswordErrors]; -export type ResetResetPasswordError = ErrorModel | HTTPValidationError; +export type ResetResetPasswordResponses = { + /** + * Successful Response + */ + 200: unknown; +}; export type VerifyRequestTokenData = { - body: Body_auth_verify_request_token; + body: BodyAuthVerifyRequestToken; + path?: never; + query?: never; + url: "/auth/request-verify-token"; }; -export type VerifyRequestTokenResponse = unknown; +export type VerifyRequestTokenErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; -export type VerifyRequestTokenError = HTTPValidationError; +export type VerifyRequestTokenError = + VerifyRequestTokenErrors[keyof VerifyRequestTokenErrors]; + +export type VerifyRequestTokenResponses = { + /** + * Successful Response + */ + 202: unknown; +}; export type VerifyVerifyData = { - body: Body_auth_verify_verify; + body: BodyAuthVerifyVerify; + path?: never; + query?: never; + url: "/auth/verify"; +}; + +export type VerifyVerifyErrors = { + /** + * Bad Request + */ + 400: ErrorModel; + /** + * Validation Error + */ + 422: HttpValidationError; }; -export type VerifyVerifyResponse = UserRead; +export type VerifyVerifyError = VerifyVerifyErrors[keyof VerifyVerifyErrors]; + +export type VerifyVerifyResponses = { + /** + * Successful Response + */ + 200: UserRead; +}; -export type VerifyVerifyError = ErrorModel | HTTPValidationError; +export type VerifyVerifyResponse = + VerifyVerifyResponses[keyof VerifyVerifyResponses]; -export type UsersCurrentUserResponse = UserRead; +export type UsersCurrentUserData = { + body?: never; + path?: never; + query?: never; + url: "/users/me"; +}; + +export type UsersCurrentUserErrors = { + /** + * Missing token or inactive user. + */ + 401: unknown; +}; + +export type UsersCurrentUserResponses = { + /** + * Successful Response + */ + 200: UserRead; +}; -export type UsersCurrentUserError = unknown; +export type UsersCurrentUserResponse = + UsersCurrentUserResponses[keyof UsersCurrentUserResponses]; export type UsersPatchCurrentUserData = { body: UserUpdate; + path?: never; + query?: never; + url: "/users/me"; }; -export type UsersPatchCurrentUserResponse = UserRead; +export type UsersPatchCurrentUserErrors = { + /** + * Bad Request + */ + 400: ErrorModel; + /** + * Missing token or inactive user. + */ + 401: unknown; + /** + * Validation Error + */ + 422: HttpValidationError; +}; export type UsersPatchCurrentUserError = - | ErrorModel - | unknown - | HTTPValidationError; + UsersPatchCurrentUserErrors[keyof UsersPatchCurrentUserErrors]; -export type UsersUserData = { +export type UsersPatchCurrentUserResponses = { + /** + * Successful Response + */ + 200: UserRead; +}; + +export type UsersPatchCurrentUserResponse = + UsersPatchCurrentUserResponses[keyof UsersPatchCurrentUserResponses]; + +export type UsersDeleteUserData = { + body?: never; path: { + /** + * Id + */ id: string; }; + query?: never; + url: "/users/{id}"; }; -export type UsersUserResponse = UserRead; +export type UsersDeleteUserErrors = { + /** + * Missing token or inactive user. + */ + 401: unknown; + /** + * Not a superuser. + */ + 403: unknown; + /** + * The user does not exist. + */ + 404: unknown; + /** + * Validation Error + */ + 422: HttpValidationError; +}; -export type UsersUserError = unknown | HTTPValidationError; +export type UsersDeleteUserError = + UsersDeleteUserErrors[keyof UsersDeleteUserErrors]; -export type UsersPatchUserData = { - body: UserUpdate; +export type UsersDeleteUserResponses = { + /** + * Successful Response + */ + 204: void; +}; + +export type UsersDeleteUserResponse = + UsersDeleteUserResponses[keyof UsersDeleteUserResponses]; + +export type UsersUserData = { + body?: never; path: { + /** + * Id + */ id: string; }; + query?: never; + url: "/users/{id}"; }; -export type UsersPatchUserResponse = UserRead; +export type UsersUserErrors = { + /** + * Missing token or inactive user. + */ + 401: unknown; + /** + * Not a superuser. + */ + 403: unknown; + /** + * The user does not exist. + */ + 404: unknown; + /** + * Validation Error + */ + 422: HttpValidationError; +}; -export type UsersPatchUserError = ErrorModel | unknown | HTTPValidationError; +export type UsersUserError = UsersUserErrors[keyof UsersUserErrors]; -export type UsersDeleteUserData = { +export type UsersUserResponses = { + /** + * Successful Response + */ + 200: UserRead; +}; + +export type UsersUserResponse = UsersUserResponses[keyof UsersUserResponses]; + +export type UsersPatchUserData = { + body: UserUpdate; path: { + /** + * Id + */ id: string; }; + query?: never; + url: "/users/{id}"; }; -export type UsersDeleteUserResponse = void; +export type UsersPatchUserErrors = { + /** + * Bad Request + */ + 400: ErrorModel; + /** + * Missing token or inactive user. + */ + 401: unknown; + /** + * Not a superuser. + */ + 403: unknown; + /** + * The user does not exist. + */ + 404: unknown; + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type UsersPatchUserError = + UsersPatchUserErrors[keyof UsersPatchUserErrors]; -export type UsersDeleteUserError = unknown | HTTPValidationError; +export type UsersPatchUserResponses = { + /** + * Successful Response + */ + 200: UserRead; +}; + +export type UsersPatchUserResponse = + UsersPatchUserResponses[keyof UsersPatchUserResponses]; export type ReadItemData = { + body?: never; + path?: never; query?: { /** + * Page * Page number */ page?: number; /** + * Size * Page size */ size?: number; }; + url: "/items/"; +}; + +export type ReadItemErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; }; -export type ReadItemResponse = Page_ItemRead_; +export type ReadItemError = ReadItemErrors[keyof ReadItemErrors]; + +export type ReadItemResponses = { + /** + * Successful Response + */ + 200: PageItemRead; +}; -export type ReadItemError = HTTPValidationError; +export type ReadItemResponse = ReadItemResponses[keyof ReadItemResponses]; export type CreateItemData = { body: ItemCreate; + path?: never; + query?: never; + url: "/items/"; }; -export type CreateItemResponse = ItemRead; +export type CreateItemErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type CreateItemError = CreateItemErrors[keyof CreateItemErrors]; + +export type CreateItemResponses = { + /** + * Successful Response + */ + 200: ItemRead; +}; -export type CreateItemError = HTTPValidationError; +export type CreateItemResponse = CreateItemResponses[keyof CreateItemResponses]; export type DeleteItemData = { + body?: never; path: { + /** + * Item Id + */ item_id: string; }; + query?: never; + url: "/items/{item_id}"; }; -export type DeleteItemResponse = unknown; +export type DeleteItemErrors = { + /** + * Validation Error + */ + 422: HttpValidationError; +}; + +export type DeleteItemError = DeleteItemErrors[keyof DeleteItemErrors]; -export type DeleteItemError = HTTPValidationError; +export type DeleteItemResponses = { + /** + * Successful Response + */ + 200: unknown; +}; + +export type ClientOptions = { + baseURL: `${string}://openapi.json` | (string & {}); +}; diff --git a/nextjs-frontend/eslint.config.mjs b/nextjs-frontend/eslint.config.mjs index d996e11..809669c 100644 --- a/nextjs-frontend/eslint.config.mjs +++ b/nextjs-frontend/eslint.config.mjs @@ -5,7 +5,7 @@ const compat = new FlatCompat({ }); const eslintConfig = [{ - ignores: ["node_modules/**", ".next/**", "out/**", "build/**", "next-env.d.ts"] + ignores: ["node_modules/**", ".next/**", "out/**", "build/**", "next-env.d.ts", "app/openapi-client/**"] }, ...compat.config({ extends: ["next/core-web-vitals", "next/typescript", "prettier"], rules: { "@typescript-eslint/no-empty-object-type": "off" }, diff --git a/nextjs-frontend/lib/clientConfig.ts b/nextjs-frontend/lib/clientConfig.ts index 7ffa09a..b177486 100644 --- a/nextjs-frontend/lib/clientConfig.ts +++ b/nextjs-frontend/lib/clientConfig.ts @@ -1,4 +1,4 @@ -import { client } from "@/app/openapi-client/sdk.gen"; +import { client } from "@/app/openapi-client/client.gen"; const configureClient = () => { const baseURL = process.env.API_BASE_URL; diff --git a/nextjs-frontend/openapi-ts.config.ts b/nextjs-frontend/openapi-ts.config.ts index 12d973a..4f72df9 100644 --- a/nextjs-frontend/openapi-ts.config.ts +++ b/nextjs-frontend/openapi-ts.config.ts @@ -6,11 +6,11 @@ config({ path: ".env.local" }); const openapiFile = process.env.OPENAPI_OUTPUT_FILE; export default defineConfig({ - client: "@hey-api/client-axios", input: openapiFile as string, output: { format: "prettier", lint: "eslint", path: "app/openapi-client", }, + plugins: ["@hey-api/client-axios"], }); diff --git a/nextjs-frontend/package.json b/nextjs-frontend/package.json index 9b16817..4b8d63e 100644 --- a/nextjs-frontend/package.json +++ b/nextjs-frontend/package.json @@ -1,6 +1,6 @@ { "name": "nextjs-frontend", - "version": "0.0.6", + "version": "0.0.7", "private": true, "scripts": { "dev": "next dev", @@ -16,8 +16,9 @@ }, "dependencies": { "@heroicons/react": "^2.2.0", - "@hey-api/client-axios": "^0.3.4", - "@hey-api/client-fetch": "^0.4.0", + "@hey-api/client-axios": "^0.9.1", + "@hey-api/client-fetch": "^0.13.1", + "axios": "^1.7.9", "@hookform/resolvers": "^3.9.1", "@radix-ui/react-avatar": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.2", @@ -42,7 +43,7 @@ "devDependencies": { "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.18.0", - "@hey-api/openapi-ts": "^0.60.1", + "@hey-api/openapi-ts": "^0.83.1", "@next/eslint-plugin-next": "15.5.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.1", diff --git a/nextjs-frontend/pnpm-lock.yaml b/nextjs-frontend/pnpm-lock.yaml index 4007e4e..1cdf213 100644 --- a/nextjs-frontend/pnpm-lock.yaml +++ b/nextjs-frontend/pnpm-lock.yaml @@ -12,11 +12,11 @@ importers: specifier: ^2.2.0 version: 2.2.0(react@19.1.1) '@hey-api/client-axios': - specifier: ^0.3.4 - version: 0.3.4(axios@1.7.9) + specifier: ^0.9.1 + version: 0.9.1(@hey-api/openapi-ts@0.83.1(typescript@5.6.3))(axios@1.7.9) '@hey-api/client-fetch': - specifier: ^0.4.0 - version: 0.4.3 + specifier: ^0.13.1 + version: 0.13.1(@hey-api/openapi-ts@0.83.1(typescript@5.6.3)) '@hookform/resolvers': specifier: ^3.9.1 version: 3.9.1(react-hook-form@7.54.0(react@19.1.1)) @@ -41,6 +41,9 @@ importers: '@radix-ui/react-tabs': specifier: ^1.1.1 version: 1.1.1(@types/react-dom@19.1.7(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + axios: + specifier: ^1.7.9 + version: 1.7.9 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -85,8 +88,8 @@ importers: specifier: ^9.18.0 version: 9.18.0 '@hey-api/openapi-ts': - specifier: ^0.60.1 - version: 0.60.1(typescript@5.6.3) + specifier: ^0.83.1 + version: 0.83.1(typescript@5.6.3) '@next/eslint-plugin-next': specifier: 15.5.0 version: 15.5.0 @@ -176,10 +179,6 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@apidevtools/json-schema-ref-parser@11.7.3': - resolution: {integrity: sha512-WApSdLdXEBb/1FUPca2lteASewEfpjEYJ8oXZP+0gExK5qSfsEKBKcA+WjY6Q4wvXwyv0+W6Kvc372pSceib9w==} - engines: {node: '>= 16'} - '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -406,20 +405,35 @@ packages: peerDependencies: react: '>= 16 || ^19.0.0-rc' - '@hey-api/client-axios@0.3.4': - resolution: {integrity: sha512-9jyZb1kicWZoZwlu/2XnwRDQJsrGi+ExBuSn3liT5slQ6uRSbN5HYqZr1YzRy4fbAkxY9S2vFbqfdHniqWgGGg==} + '@hey-api/client-axios@0.9.1': + resolution: {integrity: sha512-fvpOdnEz6tu5T2+IMNZW3g9mAZwaXavqpsvtapEZNtYxyYtQ+lQs9wJn/VPhZEvdXAXu8HPTCRpmfa0t1aRATA==} + deprecated: Starting with v0.73.0, this package is bundled directly inside @hey-api/openapi-ts. peerDependencies: + '@hey-api/openapi-ts': < 2 axios: '>= 1.0.0 < 2' - '@hey-api/client-fetch@0.4.3': - resolution: {integrity: sha512-Y0McgfJED/Iq6Tr8LgewFL+qrOpb87rUBUJkc6mLzxqTkqF52KcexYZPlKyjee0Qb/oUJOupFRpvUEWjH/339w==} + '@hey-api/client-fetch@0.13.1': + resolution: {integrity: sha512-29jBRYNdxVGlx5oewFgOrkulZckpIpBIRHth3uHFn1PrL2ucMy52FvWOY3U3dVx2go1Z3kUmMi6lr07iOpUqqA==} + deprecated: Starting with v0.73.0, this package is bundled directly inside @hey-api/openapi-ts. + peerDependencies: + '@hey-api/openapi-ts': < 2 + + '@hey-api/codegen-core@0.1.0': + resolution: {integrity: sha512-7B6B9Zuw4uQWoG5YwAwNC+UTz6ErAujqaQrJuMu/OgPkUHq+hl6zdKKi2MX/399vPYilo0IGBxQHmY1UfmTHsw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=22.10.0} + peerDependencies: + typescript: '>=5.5.3' + + '@hey-api/json-schema-ref-parser@1.1.0': + resolution: {integrity: sha512-+5eg9pgAAM9oSqJQuUtfTKbLz8yieFKN91myyXiLnprqFj8ROfxUKJLr9DKq/hGKyybKT1WxFSetDqCFm80pCA==} + engines: {node: '>= 16'} - '@hey-api/openapi-ts@0.60.1': - resolution: {integrity: sha512-W3fW6pjQ3rwRsmvp9+hDEStyedTWgNjd6PfdVOIegtPBKj3o4ThK3J14kXeqdH2tJXrudfLpXHRp43+ahi4QSg==} - engines: {node: ^18.0.0 || >=20.0.0} + '@hey-api/openapi-ts@0.83.1': + resolution: {integrity: sha512-AJIXDsXBLXS4uzhU+yVeNmD43uN6FYPcWpcid7Q0bA4JRXpI+6livOzUUMiuszt3NlgHy1gcf6x15W2xHNSoag==} + engines: {node: ^18.18.0 || ^20.9.0 || >=22.10.0} hasBin: true peerDependencies: - typescript: ^5.x + typescript: '>=5.5.3' '@hookform/resolvers@3.9.1': resolution: {integrity: sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug==} @@ -1591,6 +1605,10 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -1778,6 +1796,10 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + c12@2.0.1: resolution: {integrity: sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==} peerDependencies: @@ -1899,6 +1921,10 @@ packages: color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + color@4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -1907,8 +1933,8 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + commander@13.0.0: + resolution: {integrity: sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ==} engines: {node: '>=18'} commander@2.20.3: @@ -2035,10 +2061,22 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -2680,6 +2718,11 @@ packages: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2707,6 +2750,11 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -2769,6 +2817,10 @@ packages: resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} engines: {node: '>= 0.4'} + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -3310,6 +3362,10 @@ packages: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} + open@10.1.2: + resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} + engines: {node: '>=18'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -3669,6 +3725,10 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -4298,12 +4358,6 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@apidevtools/json-schema-ref-parser@11.7.3': - dependencies: - '@jsdevtools/ono': 7.1.3 - '@types/json-schema': 7.0.15 - js-yaml: 4.1.0 - '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -4567,18 +4621,37 @@ snapshots: dependencies: react: 19.1.1 - '@hey-api/client-axios@0.3.4(axios@1.7.9)': + '@hey-api/client-axios@0.9.1(@hey-api/openapi-ts@0.83.1(typescript@5.6.3))(axios@1.7.9)': dependencies: + '@hey-api/openapi-ts': 0.83.1(typescript@5.6.3) axios: 1.7.9 - '@hey-api/client-fetch@0.4.3': {} + '@hey-api/client-fetch@0.13.1(@hey-api/openapi-ts@0.83.1(typescript@5.6.3))': + dependencies: + '@hey-api/openapi-ts': 0.83.1(typescript@5.6.3) + + '@hey-api/codegen-core@0.1.0(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 + + '@hey-api/json-schema-ref-parser@1.1.0': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.0 + lodash: 4.17.21 - '@hey-api/openapi-ts@0.60.1(typescript@5.6.3)': + '@hey-api/openapi-ts@0.83.1(typescript@5.6.3)': dependencies: - '@apidevtools/json-schema-ref-parser': 11.7.3 + '@hey-api/codegen-core': 0.1.0(typescript@5.6.3) + '@hey-api/json-schema-ref-parser': 1.1.0 + ansi-colors: 4.1.3 c12: 2.0.1 - commander: 12.1.0 + color-support: 1.1.3 + commander: 13.0.0 handlebars: 4.7.8 + open: 10.1.2 + semver: 7.7.2 typescript: 5.6.3 transitivePeerDependencies: - magicast @@ -5802,6 +5875,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -6044,6 +6119,10 @@ snapshots: buffer-from@1.1.2: {} + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + c12@2.0.1: dependencies: chokidar: 4.0.1 @@ -6170,6 +6249,8 @@ snapshots: simple-swizzle: 0.2.2 optional: true + color-support@1.1.3: {} + color@4.2.3: dependencies: color-convert: 2.0.1 @@ -6180,7 +6261,7 @@ snapshots: dependencies: delayed-stream: 1.0.0 - commander@12.1.0: {} + commander@13.0.0: {} commander@2.20.3: {} @@ -6290,12 +6371,21 @@ snapshots: deepmerge@4.3.1: {} + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 + define-lazy-prop@3.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -6485,8 +6575,8 @@ snapshots: '@typescript-eslint/parser': 8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3) eslint: 9.18.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.18.0(jiti@2.4.2)) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.18.0(jiti@2.4.2)) eslint-plugin-react: 7.37.2(eslint@9.18.0(jiti@2.4.2)) eslint-plugin-react-hooks: 5.0.0(eslint@9.18.0(jiti@2.4.2)) @@ -6509,37 +6599,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.18.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.18.0 eslint: 9.18.0(jiti@2.4.2) - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3) eslint: 9.18.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.18.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0(jiti@2.4.2)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -6550,7 +6640,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.18.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.20.0(eslint@9.18.0(jiti@2.4.2))(typescript@5.6.3))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)))(eslint@9.18.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -7079,6 +7169,8 @@ snapshots: dependencies: has-tostringtag: 1.0.2 + is-docker@3.0.0: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.0.2: @@ -7099,6 +7191,10 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -7149,6 +7245,10 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + isarray@2.0.5: {} isexe@2.0.0: {} @@ -7885,6 +7985,13 @@ snapshots: dependencies: mimic-fn: 4.0.0 + open@10.1.2: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -8214,6 +8321,8 @@ snapshots: reusify@1.0.4: {} + run-applescript@7.1.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -8258,8 +8367,7 @@ snapshots: semver@7.6.3: {} - semver@7.7.2: - optional: true + semver@7.7.2: {} serialize-javascript@6.0.2: dependencies: diff --git a/nextjs-frontend/watcher.js b/nextjs-frontend/watcher.js index b351c59..90d0909 100644 --- a/nextjs-frontend/watcher.js +++ b/nextjs-frontend/watcher.js @@ -10,7 +10,7 @@ const openapiFile = process.env.OPENAPI_OUTPUT_FILE; // Watch the specific file for changes chokidar.watch(openapiFile).on("change", (path) => { console.log(`File ${path} has been modified. Running generate-client...`); - exec("npm run generate-client", (error, stdout, stderr) => { + exec("pnpm run generate-client", (error, stdout, stderr) => { if (error) { console.error(`Error: ${error.message}`); return; From 91db5461390ac7e16dc4a88eaead8bfd7aaaa0df Mon Sep 17 00:00:00 2001 From: Caio Carvalho Date: Fri, 24 Oct 2025 10:31:39 -0400 Subject: [PATCH 2/2] chore: update changelog for version 0.0.7 and upgrade @hey-api/openapi-ts to ^0.83.1 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5e6cf5..6fc75a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ frontend TypeScript client, `nextjs-frontend`. The backend and the frontend are versioned together, that is, they have the same version number. When you update the backend, you should also update the frontend to the same version. +## 0.0.7 October 24, 2025 {id="0.0.7"} + +- Upgrade @hey-api/openapi-ts version to ^0.83.1 + ## 0.0.6 September 1, 2025 {id="0.0.6"} - Upgrade Next.js version to 15.5.0