-
-
-
+
\ No newline at end of file
diff --git a/src/chongming-web/src/api/generated/client.gen.ts b/src/chongming-web/src/api/generated/client.gen.ts
new file mode 100644
index 0000000..67d2030
--- /dev/null
+++ b/src/chongming-web/src/api/generated/client.gen.ts
@@ -0,0 +1,16 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import { type ClientOptions, type Config, createClient, createConfig } from './client';
+import type { ClientOptions as ClientOptions2 } from './types.gen';
+
+/**
+ * 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({ baseUrl: 'http://127.0.0.1:8000' }));
diff --git a/src/chongming-web/src/api/generated/client/client.gen.ts b/src/chongming-web/src/api/generated/client/client.gen.ts
new file mode 100644
index 0000000..9ec9ad8
--- /dev/null
+++ b/src/chongming-web/src/api/generated/client/client.gen.ts
@@ -0,0 +1,298 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import { createSseClient } from '../core/serverSentEvents.gen';
+import type { HttpMethod } from '../core/types.gen';
+import { getValidRequestBody } from '../core/utils.gen';
+import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen';
+import {
+ buildUrl,
+ createConfig,
+ createInterceptors,
+ getParseAs,
+ mergeConfigs,
+ mergeHeaders,
+ setAuthParams,
+} from './utils.gen';
+
+type ReqInit = Omit & {
+ body?: any;
+ headers: ReturnType;
+};
+
+export const createClient = (config: Config = {}): Client => {
+ let _config = mergeConfigs(createConfig(), config);
+
+ const getConfig = (): Config => ({ ..._config });
+
+ const setConfig = (config: Config): Config => {
+ _config = mergeConfigs(_config, config);
+ return getConfig();
+ };
+
+ const interceptors = createInterceptors();
+
+ const beforeRequest = async <
+ TData = unknown,
+ TResponseStyle extends 'data' | 'fields' = 'fields',
+ ThrowOnError extends boolean = boolean,
+ Url extends string = string,
+ >(
+ options: RequestOptions,
+ ) => {
+ const opts = {
+ ..._config,
+ ...options,
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
+ headers: mergeHeaders(_config.headers, options.headers),
+ serializedBody: undefined as string | undefined,
+ };
+
+ if (opts.security) {
+ await setAuthParams({
+ ...opts,
+ security: opts.security,
+ });
+ }
+
+ if (opts.requestValidator) {
+ await opts.requestValidator(opts);
+ }
+
+ if (opts.body !== undefined && opts.bodySerializer) {
+ opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined;
+ }
+
+ // remove Content-Type header if body is empty to avoid sending invalid requests
+ if (opts.body === undefined || opts.serializedBody === '') {
+ opts.headers.delete('Content-Type');
+ }
+
+ const resolvedOpts = opts as typeof opts &
+ ResolvedRequestOptions;
+ const url = buildUrl(resolvedOpts);
+
+ return { opts: resolvedOpts, url };
+ };
+
+ const request: Client['request'] = async (options) => {
+ const { opts, url } = await beforeRequest(options);
+ const requestInit: ReqInit = {
+ redirect: 'follow',
+ ...opts,
+ body: getValidRequestBody(opts),
+ };
+
+ let request = new Request(url, requestInit);
+
+ for (const fn of interceptors.request.fns) {
+ if (fn) {
+ request = await fn(request, opts);
+ }
+ }
+
+ // fetch must be assigned here, otherwise it would throw the error:
+ // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
+ const _fetch = opts.fetch!;
+ let response: Response;
+
+ try {
+ response = await _fetch(request);
+ } catch (error) {
+ // Handle fetch exceptions (AbortError, network errors, etc.)
+ let finalError = error;
+
+ for (const fn of interceptors.error.fns) {
+ if (fn) {
+ finalError = (await fn(error, undefined as any, request, opts)) as unknown;
+ }
+ }
+
+ finalError = finalError || ({} as unknown);
+
+ if (opts.throwOnError) {
+ throw finalError;
+ }
+
+ // Return error response
+ return opts.responseStyle === 'data'
+ ? undefined
+ : {
+ error: finalError,
+ request,
+ response: undefined as any,
+ };
+ }
+
+ for (const fn of interceptors.response.fns) {
+ if (fn) {
+ response = await fn(response, request, opts);
+ }
+ }
+
+ const result = {
+ request,
+ response,
+ };
+
+ if (response.ok) {
+ const parseAs =
+ (opts.parseAs === 'auto'
+ ? getParseAs(response.headers.get('Content-Type'))
+ : opts.parseAs) ?? 'json';
+
+ if (response.status === 204 || response.headers.get('Content-Length') === '0') {
+ let emptyData: any;
+ switch (parseAs) {
+ case 'arrayBuffer':
+ case 'blob':
+ case 'text':
+ emptyData = await response[parseAs]();
+ break;
+ case 'formData':
+ emptyData = new FormData();
+ break;
+ case 'stream':
+ emptyData = response.body;
+ break;
+ case 'json':
+ default:
+ emptyData = {};
+ break;
+ }
+ return opts.responseStyle === 'data'
+ ? emptyData
+ : {
+ data: emptyData,
+ ...result,
+ };
+ }
+
+ let data: any;
+ switch (parseAs) {
+ case 'arrayBuffer':
+ case 'blob':
+ case 'formData':
+ case 'text':
+ data = await response[parseAs]();
+ break;
+ case 'json': {
+ // Some servers return 200 with no Content-Length and empty body.
+ // response.json() would throw; read as text and parse if non-empty.
+ const text = await response.text();
+ data = text ? JSON.parse(text) : {};
+ break;
+ }
+ case 'stream':
+ return opts.responseStyle === 'data'
+ ? response.body
+ : {
+ data: response.body,
+ ...result,
+ };
+ }
+
+ if (parseAs === 'json') {
+ if (opts.responseValidator) {
+ await opts.responseValidator(data);
+ }
+
+ if (opts.responseTransformer) {
+ data = await opts.responseTransformer(data);
+ }
+ }
+
+ return opts.responseStyle === 'data'
+ ? data
+ : {
+ data,
+ ...result,
+ };
+ }
+
+ const textError = await response.text();
+ let jsonError: unknown;
+
+ try {
+ jsonError = JSON.parse(textError);
+ } catch {
+ // noop
+ }
+
+ const error = jsonError ?? textError;
+ let finalError = error;
+
+ for (const fn of interceptors.error.fns) {
+ if (fn) {
+ finalError = (await fn(error, response, request, opts)) as string;
+ }
+ }
+
+ finalError = finalError || ({} as string);
+
+ if (opts.throwOnError) {
+ throw finalError;
+ }
+
+ // TODO: we probably want to return error and improve types
+ return opts.responseStyle === 'data'
+ ? undefined
+ : {
+ error: finalError,
+ ...result,
+ };
+ };
+
+ 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 unknown as Record,
+ method,
+ onRequest: async (url, init) => {
+ let request = new Request(url, init);
+ for (const fn of interceptors.request.fns) {
+ if (fn) {
+ request = await fn(request, opts);
+ }
+ }
+ return request;
+ },
+ serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined,
+ url,
+ });
+ };
+
+ const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options });
+
+ return {
+ buildUrl: _buildUrl,
+ connect: makeMethodFn('CONNECT'),
+ delete: makeMethodFn('DELETE'),
+ get: makeMethodFn('GET'),
+ getConfig,
+ head: makeMethodFn('HEAD'),
+ interceptors,
+ 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/src/chongming-web/src/api/generated/client/index.ts b/src/chongming-web/src/api/generated/client/index.ts
new file mode 100644
index 0000000..b295ede
--- /dev/null
+++ b/src/chongming-web/src/api/generated/client/index.ts
@@ -0,0 +1,25 @@
+// 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 { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
+export { createClient } from './client.gen';
+export type {
+ Client,
+ ClientOptions,
+ Config,
+ CreateClientConfig,
+ Options,
+ RequestOptions,
+ RequestResult,
+ ResolvedRequestOptions,
+ ResponseStyle,
+ TDataShape,
+} from './types.gen';
+export { createConfig, mergeHeaders } from './utils.gen';
diff --git a/src/chongming-web/src/api/generated/client/types.gen.ts b/src/chongming-web/src/api/generated/client/types.gen.ts
new file mode 100644
index 0000000..c80695b
--- /dev/null
+++ b/src/chongming-web/src/api/generated/client/types.gen.ts
@@ -0,0 +1,215 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+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';
+import type { Middleware } from './utils.gen';
+
+export type ResponseStyle = 'data' | 'fields';
+
+export interface Config
+ extends Omit, CoreConfig {
+ /**
+ * Base URL for all requests made by this client.
+ */
+ baseUrl?: T['baseUrl'];
+ /**
+ * Fetch API implementation. You can use this option to provide a custom
+ * fetch instance.
+ *
+ * @default globalThis.fetch
+ */
+ fetch?: typeof fetch;
+ /**
+ * Please don't use the Fetch client for Next.js applications. The `next`
+ * options won't have any effect.
+ *
+ * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
+ */
+ next?: never;
+ /**
+ * Return the response data parsed in a specified format. By default, `auto`
+ * will infer the appropriate method from the `Content-Type` response header.
+ * You can override this behavior with any of the {@link Body} methods.
+ * Select `stream` if you don't want to parse response data at all.
+ *
+ * @default 'auto'
+ */
+ parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
+ /**
+ * Should we return only data or multiple fields (data, error, response, etc.)?
+ *
+ * @default 'fields'
+ */
+ responseStyle?: ResponseStyle;
+ /**
+ * Throw an error instead of returning it in the response?
+ *
+ * @default false
+ */
+ throwOnError?: T['throwOnError'];
+}
+
+export interface RequestOptions<
+ TData = unknown,
+ TResponseStyle extends ResponseStyle = 'fields',
+ ThrowOnError extends boolean = boolean,
+ Url extends string = string,
+>
+ extends
+ Config<{
+ responseStyle: TResponseStyle;
+ throwOnError: ThrowOnError;
+ }>,
+ Pick<
+ ServerSentEventsOptions,
+ | 'onRequest'
+ | '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 ResolvedRequestOptions<
+ TResponseStyle extends ResponseStyle = 'fields',
+ ThrowOnError extends boolean = boolean,
+ Url extends string = string,
+> extends RequestOptions {
+ headers: Headers;
+ serializedBody?: string;
+}
+
+export type RequestResult<
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = boolean,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = ThrowOnError extends true
+ ? Promise<
+ TResponseStyle extends 'data'
+ ? TData extends Record
+ ? TData[keyof TData]
+ : TData
+ : {
+ data: TData extends Record ? TData[keyof TData] : TData;
+ request: Request;
+ response: Response;
+ }
+ >
+ : Promise<
+ TResponseStyle extends 'data'
+ ? (TData extends Record ? TData[keyof TData] : TData) | undefined
+ : (
+ | {
+ data: TData extends Record ? TData[keyof TData] : TData;
+ error: undefined;
+ }
+ | {
+ data: undefined;
+ error: TError extends Record ? TError[keyof TError] : TError;
+ }
+ ) & {
+ request: Request;
+ response: Response;
+ }
+ >;
+
+export interface ClientOptions {
+ baseUrl?: string;
+ responseStyle?: ResponseStyle;
+ throwOnError?: boolean;
+}
+
+type MethodFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit, 'method'>,
+) => RequestResult;
+
+type SseFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit, 'method'>,
+) => Promise>;
+
+type RequestFn = <
+ TData = unknown,
+ TError = unknown,
+ ThrowOnError extends boolean = false,
+ TResponseStyle extends ResponseStyle = 'fields',
+>(
+ options: Omit, 'method'> &
+ Pick>, 'method'>,
+) => RequestResult;
+
+type BuildUrlFn = <
+ TData extends {
+ body?: unknown;
+ path?: Record;
+ query?: Record;
+ url: string;
+ },
+>(
+ options: TData & Options,
+) => string;
+
+export type Client = CoreClient & {
+ interceptors: Middleware;
+};
+
+/**
+ * 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,
+ TResponseStyle extends ResponseStyle = 'fields',
+> = OmitKeys<
+ RequestOptions,
+ 'body' | 'path' | 'query' | 'url'
+> &
+ ([TData] extends [never] ? unknown : Omit);
diff --git a/src/chongming-web/src/api/generated/client/utils.gen.ts b/src/chongming-web/src/api/generated/client/utils.gen.ts
new file mode 100644
index 0000000..5162192
--- /dev/null
+++ b/src/chongming-web/src/api/generated/client/utils.gen.ts
@@ -0,0 +1,316 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import { getAuthToken } from '../core/auth.gen';
+import type { QuerySerializerOptions } from '../core/bodySerializer.gen';
+import { jsonBodySerializer } 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 = ({
+ parameters = {},
+ ...args
+}: 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;
+ }
+
+ const options = parameters[name] || args;
+
+ if (Array.isArray(value)) {
+ const serializedArray = serializeArrayParam({
+ allowReserved: options.allowReserved,
+ explode: true,
+ name,
+ style: 'form',
+ value,
+ ...options.array,
+ });
+ if (serializedArray) search.push(serializedArray);
+ } else if (typeof value === 'object') {
+ const serializedObject = serializeObjectParam({
+ allowReserved: options.allowReserved,
+ explode: true,
+ name,
+ style: 'deepObject',
+ value: value as Record,
+ ...options.object,
+ });
+ if (serializedObject) search.push(serializedObject);
+ } else {
+ const serializedPrimitive = serializePrimitiveParam({
+ allowReserved: options.allowReserved,
+ name,
+ value: value as string,
+ });
+ if (serializedPrimitive) search.push(serializedPrimitive);
+ }
+ }
+ }
+ return search.join('&');
+ };
+ return querySerializer;
+};
+
+/**
+ * Infers parseAs value from provided Content-Type header.
+ */
+export const getParseAs = (contentType: string | null): Exclude => {
+ if (!contentType) {
+ // If no Content-Type header is provided, the best we can do is return the raw response body,
+ // which is effectively the same as the 'stream' option.
+ return 'stream';
+ }
+
+ const cleanContent = contentType.split(';')[0]?.trim();
+
+ if (!cleanContent) {
+ return;
+ }
+
+ if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {
+ return 'json';
+ }
+
+ if (cleanContent === 'multipart/form-data') {
+ return 'formData';
+ }
+
+ if (
+ ['application/', 'audio/', 'image/', 'video/'].some((type) => cleanContent.startsWith(type))
+ ) {
+ return 'blob';
+ }
+
+ if (cleanContent.startsWith('text/')) {
+ return 'text';
+ }
+
+ return;
+};
+
+const checkForExistence = (
+ options: Pick & {
+ headers: Headers;
+ },
+ name?: string,
+): boolean => {
+ if (!name) {
+ return false;
+ }
+ if (
+ options.headers.has(name) ||
+ options.query?.[name] ||
+ options.headers.get('Cookie')?.includes(`${name}=`)
+ ) {
+ return true;
+ }
+ return false;
+};
+
+export const setAuthParams = async ({
+ security,
+ ...options
+}: Pick, 'security'> &
+ Pick & {
+ headers: Headers;
+ }) => {
+ 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':
+ options.headers.append('Cookie', `${name}=${token}`);
+ break;
+ case 'header':
+ default:
+ options.headers.set(name, token);
+ break;
+ }
+ }
+};
+
+export const buildUrl: Client['buildUrl'] = (options) =>
+ getUrl({
+ baseUrl: options.baseUrl as string,
+ path: options.path,
+ query: options.query,
+ 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 };
+ if (config.baseUrl?.endsWith('/')) {
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
+ }
+ config.headers = mergeHeaders(a.headers, b.headers);
+ return config;
+};
+
+const headersEntries = (headers: Headers): Array<[string, string]> => {
+ const entries: Array<[string, string]> = [];
+ headers.forEach((value, key) => {
+ entries.push([key, value]);
+ });
+ return entries;
+};
+
+export const mergeHeaders = (
+ ...headers: Array['headers'] | undefined>
+): Headers => {
+ const mergedHeaders = new Headers();
+ for (const header of headers) {
+ if (!header) {
+ continue;
+ }
+
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
+
+ for (const [key, value] of iterator) {
+ if (value === null) {
+ mergedHeaders.delete(key);
+ } else if (Array.isArray(value)) {
+ for (const v of value) {
+ mergedHeaders.append(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.set(
+ key,
+ typeof value === 'object' ? JSON.stringify(value) : (value as string),
+ );
+ }
+ }
+ }
+ return mergedHeaders;
+};
+
+type ErrInterceptor = (
+ error: Err,
+ response: Res,
+ request: Req,
+ options: Options,
+) => Err | Promise;
+
+type ReqInterceptor = (request: Req, options: Options) => Req | Promise;
+
+type ResInterceptor = (
+ response: Res,
+ request: Req,
+ options: Options,
+) => Res | Promise;
+
+class Interceptors {
+ fns: Array = [];
+
+ clear(): void {
+ this.fns = [];
+ }
+
+ eject(id: number | Interceptor): void {
+ const index = this.getInterceptorIndex(id);
+ if (this.fns[index]) {
+ this.fns[index] = null;
+ }
+ }
+
+ exists(id: number | Interceptor): boolean {
+ const index = this.getInterceptorIndex(id);
+ return Boolean(this.fns[index]);
+ }
+
+ getInterceptorIndex(id: number | Interceptor): number {
+ if (typeof id === 'number') {
+ return this.fns[id] ? id : -1;
+ }
+ return this.fns.indexOf(id);
+ }
+
+ update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false {
+ const index = this.getInterceptorIndex(id);
+ if (this.fns[index]) {
+ this.fns[index] = fn;
+ return id;
+ }
+ return false;
+ }
+
+ use(fn: Interceptor): number {
+ this.fns.push(fn);
+ return this.fns.length - 1;
+ }
+}
+
+export interface Middleware {
+ error: Interceptors>;
+ request: Interceptors>;
+ response: Interceptors>;
+}
+
+export const createInterceptors = (): Middleware<
+ Req,
+ Res,
+ Err,
+ Options
+> => ({
+ error: new Interceptors>(),
+ request: new Interceptors>(),
+ response: new Interceptors>(),
+});
+
+const defaultQuerySerializer = createQuerySerializer({
+ allowReserved: false,
+ array: {
+ explode: true,
+ style: 'form',
+ },
+ object: {
+ explode: true,
+ style: 'deepObject',
+ },
+});
+
+const defaultHeaders = {
+ 'Content-Type': 'application/json',
+};
+
+export const createConfig = (
+ override: Config & T> = {},
+): Config & T> => ({
+ ...jsonBodySerializer,
+ headers: defaultHeaders,
+ parseAs: 'auto',
+ querySerializer: defaultQuerySerializer,
+ ...override,
+});
diff --git a/src/chongming-web/src/api/generated/core/ApiError.ts b/src/chongming-web/src/api/generated/core/ApiError.ts
deleted file mode 100644
index ec7b16a..0000000
--- a/src/chongming-web/src/api/generated/core/ApiError.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import type { ApiRequestOptions } from './ApiRequestOptions';
-import type { ApiResult } from './ApiResult';
-
-export class ApiError extends Error {
- public readonly url: string;
- public readonly status: number;
- public readonly statusText: string;
- public readonly body: any;
- public readonly request: ApiRequestOptions;
-
- constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
- super(message);
-
- this.name = 'ApiError';
- this.url = response.url;
- this.status = response.status;
- this.statusText = response.statusText;
- this.body = response.body;
- this.request = request;
- }
-}
diff --git a/src/chongming-web/src/api/generated/core/ApiRequestOptions.ts b/src/chongming-web/src/api/generated/core/ApiRequestOptions.ts
deleted file mode 100644
index 93143c3..0000000
--- a/src/chongming-web/src/api/generated/core/ApiRequestOptions.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type ApiRequestOptions = {
- readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH';
- readonly url: string;
- readonly path?: Record;
- readonly cookies?: Record;
- readonly headers?: Record;
- readonly query?: Record;
- readonly formData?: Record;
- readonly body?: any;
- readonly mediaType?: string;
- readonly responseHeader?: string;
- readonly errors?: Record;
-};
diff --git a/src/chongming-web/src/api/generated/core/ApiResult.ts b/src/chongming-web/src/api/generated/core/ApiResult.ts
deleted file mode 100644
index ee1126e..0000000
--- a/src/chongming-web/src/api/generated/core/ApiResult.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type ApiResult = {
- readonly url: string;
- readonly ok: boolean;
- readonly status: number;
- readonly statusText: string;
- readonly body: any;
-};
diff --git a/src/chongming-web/src/api/generated/core/CancelablePromise.ts b/src/chongming-web/src/api/generated/core/CancelablePromise.ts
deleted file mode 100644
index d70de92..0000000
--- a/src/chongming-web/src/api/generated/core/CancelablePromise.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export class CancelError extends Error {
-
- constructor(message: string) {
- super(message);
- this.name = 'CancelError';
- }
-
- public get isCancelled(): boolean {
- return true;
- }
-}
-
-export interface OnCancel {
- readonly isResolved: boolean;
- readonly isRejected: boolean;
- readonly isCancelled: boolean;
-
- (cancelHandler: () => void): void;
-}
-
-export class CancelablePromise implements Promise {
- #isResolved: boolean;
- #isRejected: boolean;
- #isCancelled: boolean;
- readonly #cancelHandlers: (() => void)[];
- readonly #promise: Promise;
- #resolve?: (value: T | PromiseLike) => void;
- #reject?: (reason?: any) => void;
-
- constructor(
- executor: (
- resolve: (value: T | PromiseLike) => void,
- reject: (reason?: any) => void,
- onCancel: OnCancel
- ) => void
- ) {
- this.#isResolved = false;
- this.#isRejected = false;
- this.#isCancelled = false;
- this.#cancelHandlers = [];
- this.#promise = new Promise((resolve, reject) => {
- this.#resolve = resolve;
- this.#reject = reject;
-
- const onResolve = (value: T | PromiseLike): void => {
- if (this.#isResolved || this.#isRejected || this.#isCancelled) {
- return;
- }
- this.#isResolved = true;
- if (this.#resolve) this.#resolve(value);
- };
-
- const onReject = (reason?: any): void => {
- if (this.#isResolved || this.#isRejected || this.#isCancelled) {
- return;
- }
- this.#isRejected = true;
- if (this.#reject) this.#reject(reason);
- };
-
- const onCancel = (cancelHandler: () => void): void => {
- if (this.#isResolved || this.#isRejected || this.#isCancelled) {
- return;
- }
- this.#cancelHandlers.push(cancelHandler);
- };
-
- Object.defineProperty(onCancel, 'isResolved', {
- get: (): boolean => this.#isResolved,
- });
-
- Object.defineProperty(onCancel, 'isRejected', {
- get: (): boolean => this.#isRejected,
- });
-
- Object.defineProperty(onCancel, 'isCancelled', {
- get: (): boolean => this.#isCancelled,
- });
-
- return executor(onResolve, onReject, onCancel as OnCancel);
- });
- }
-
- get [Symbol.toStringTag]() {
- return "Cancellable Promise";
- }
-
- public then(
- onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null,
- onRejected?: ((reason: any) => TResult2 | PromiseLike) | null
- ): Promise {
- return this.#promise.then(onFulfilled, onRejected);
- }
-
- public catch(
- onRejected?: ((reason: any) => TResult | PromiseLike) | null
- ): Promise {
- return this.#promise.catch(onRejected);
- }
-
- public finally(onFinally?: (() => void) | null): Promise {
- return this.#promise.finally(onFinally);
- }
-
- public cancel(): void {
- if (this.#isResolved || this.#isRejected || this.#isCancelled) {
- return;
- }
- this.#isCancelled = true;
- if (this.#cancelHandlers.length) {
- try {
- for (const cancelHandler of this.#cancelHandlers) {
- cancelHandler();
- }
- } catch (error) {
- console.warn('Cancellation threw an error', error);
- return;
- }
- }
- this.#cancelHandlers.length = 0;
- if (this.#reject) this.#reject(new CancelError('Request aborted'));
- }
-
- public get isCancelled(): boolean {
- return this.#isCancelled;
- }
-}
diff --git a/src/chongming-web/src/api/generated/core/OpenAPI.ts b/src/chongming-web/src/api/generated/core/OpenAPI.ts
deleted file mode 100644
index 414d47e..0000000
--- a/src/chongming-web/src/api/generated/core/OpenAPI.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import type { ApiRequestOptions } from './ApiRequestOptions';
-
-type Resolver = (options: ApiRequestOptions) => Promise;
-type Headers = Record;
-
-export type OpenAPIConfig = {
- BASE: string;
- VERSION: string;
- WITH_CREDENTIALS: boolean;
- CREDENTIALS: 'include' | 'omit' | 'same-origin';
- TOKEN?: string | Resolver | undefined;
- USERNAME?: string | Resolver | undefined;
- PASSWORD?: string | Resolver | undefined;
- HEADERS?: Headers | Resolver | undefined;
- ENCODE_PATH?: ((path: string) => string) | undefined;
-};
-
-export const OpenAPI: OpenAPIConfig = {
- BASE: '',
- VERSION: 'chongming',
- WITH_CREDENTIALS: false,
- CREDENTIALS: 'include',
- TOKEN: undefined,
- USERNAME: undefined,
- PASSWORD: undefined,
- HEADERS: undefined,
- ENCODE_PATH: undefined,
-};
diff --git a/src/chongming-web/src/api/generated/core/auth.gen.ts b/src/chongming-web/src/api/generated/core/auth.gen.ts
new file mode 100644
index 0000000..3ebf994
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/auth.gen.ts
@@ -0,0 +1,41 @@
+// 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/src/chongming-web/src/api/generated/core/bodySerializer.gen.ts b/src/chongming-web/src/api/generated/core/bodySerializer.gen.ts
new file mode 100644
index 0000000..67daca6
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/bodySerializer.gen.ts
@@ -0,0 +1,82 @@
+// 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: unknown) => unknown;
+
+type QuerySerializerOptionsObject = {
+ allowReserved?: boolean;
+ array?: Partial>;
+ object?: Partial>;
+};
+
+export type QuerySerializerOptions = QuerySerializerOptionsObject & {
+ /**
+ * Per-parameter serialization overrides. When provided, these settings
+ * override the global array/object settings for specific parameter names.
+ */
+ parameters?: Record;
+};
+
+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: (body: unknown): FormData => {
+ const data = new FormData();
+
+ Object.entries(body as Record).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: unknown): string =>
+ JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),
+};
+
+export const urlSearchParamsBodySerializer = {
+ bodySerializer: (body: unknown): string => {
+ const data = new URLSearchParams();
+
+ Object.entries(body as Record).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/src/chongming-web/src/api/generated/core/params.gen.ts b/src/chongming-web/src/api/generated/core/params.gen.ts
new file mode 100644
index 0000000..7955601
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/params.gen.ts
@@ -0,0 +1,169 @@
+// 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;
+ }
+ | {
+ /**
+ * 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 `in` is omitted, `map` aliases `key` to the transport layer.
+ */
+ map: Slot;
+ };
+
+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;
+ }
+ | {
+ in?: never;
+ map: Slot;
+ }
+>;
+
+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 ('key' in config) {
+ map.set(config.key, {
+ 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' && !Array.isArray(value) && !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;
+ if (field.in) {
+ (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) {
+ if (field.in) {
+ const name = field.map || key;
+ (params[field.in] as Record)[name] = value;
+ } else {
+ params[field.map] = 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 if ('allowExtra' in config && config.allowExtra) {
+ 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/src/chongming-web/src/api/generated/core/pathSerializer.gen.ts b/src/chongming-web/src/api/generated/core/pathSerializer.gen.ts
new file mode 100644
index 0000000..994b284
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/pathSerializer.gen.ts
@@ -0,0 +1,171 @@
+// 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/src/chongming-web/src/api/generated/core/queryKeySerializer.gen.ts b/src/chongming-web/src/api/generated/core/queryKeySerializer.gen.ts
new file mode 100644
index 0000000..5000df6
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/queryKeySerializer.gen.ts
@@ -0,0 +1,117 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+/**
+ * JSON-friendly union that mirrors what Pinia Colada can hash.
+ */
+export type JsonValue =
+ | null
+ | string
+ | number
+ | boolean
+ | JsonValue[]
+ | { [key: string]: JsonValue };
+
+/**
+ * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes.
+ */
+export const queryKeyJsonReplacer = (_key: string, value: unknown) => {
+ if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
+ return undefined;
+ }
+ if (typeof value === 'bigint') {
+ return value.toString();
+ }
+ if (value instanceof Date) {
+ return value.toISOString();
+ }
+ return value;
+};
+
+/**
+ * Safely stringifies a value and parses it back into a JsonValue.
+ */
+export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => {
+ try {
+ const json = JSON.stringify(input, queryKeyJsonReplacer);
+ if (json === undefined) {
+ return undefined;
+ }
+ return JSON.parse(json) as JsonValue;
+ } catch {
+ return undefined;
+ }
+};
+
+/**
+ * Detects plain objects (including objects with a null prototype).
+ */
+const isPlainObject = (value: unknown): value is Record => {
+ if (value === null || typeof value !== 'object') {
+ return false;
+ }
+ const prototype = Object.getPrototypeOf(value as object);
+ return prototype === Object.prototype || prototype === null;
+};
+
+/**
+ * Turns URLSearchParams into a sorted JSON object for deterministic keys.
+ */
+const serializeSearchParams = (params: URLSearchParams): JsonValue => {
+ const entries = Array.from(params.entries()).sort(([a], [b]) => a.localeCompare(b));
+ const result: Record = {};
+
+ for (const [key, value] of entries) {
+ const existing = result[key];
+ if (existing === undefined) {
+ result[key] = value;
+ continue;
+ }
+
+ if (Array.isArray(existing)) {
+ (existing as string[]).push(value);
+ } else {
+ result[key] = [existing, value];
+ }
+ }
+
+ return result;
+};
+
+/**
+ * Normalizes any accepted value into a JSON-friendly shape for query keys.
+ */
+export const serializeQueryKeyValue = (value: unknown): JsonValue | undefined => {
+ if (value === null) {
+ return null;
+ }
+
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
+ return value;
+ }
+
+ if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
+ return undefined;
+ }
+
+ if (typeof value === 'bigint') {
+ return value.toString();
+ }
+
+ if (value instanceof Date) {
+ return value.toISOString();
+ }
+
+ if (Array.isArray(value)) {
+ return stringifyToJsonValue(value);
+ }
+
+ if (typeof URLSearchParams !== 'undefined' && value instanceof URLSearchParams) {
+ return serializeSearchParams(value);
+ }
+
+ if (isPlainObject(value)) {
+ return stringifyToJsonValue(value);
+ }
+
+ return undefined;
+};
diff --git a/src/chongming-web/src/api/generated/core/request.ts b/src/chongming-web/src/api/generated/core/request.ts
deleted file mode 100644
index f83d711..0000000
--- a/src/chongming-web/src/api/generated/core/request.ts
+++ /dev/null
@@ -1,322 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import { ApiError } from './ApiError';
-import type { ApiRequestOptions } from './ApiRequestOptions';
-import type { ApiResult } from './ApiResult';
-import { CancelablePromise } from './CancelablePromise';
-import type { OnCancel } from './CancelablePromise';
-import type { OpenAPIConfig } from './OpenAPI';
-
-export const isDefined = (value: T | null | undefined): value is Exclude => {
- return value !== undefined && value !== null;
-};
-
-export const isString = (value: any): value is string => {
- return typeof value === 'string';
-};
-
-export const isStringWithValue = (value: any): value is string => {
- return isString(value) && value !== '';
-};
-
-export const isBlob = (value: any): value is Blob => {
- return (
- typeof value === 'object' &&
- typeof value.type === 'string' &&
- typeof value.stream === 'function' &&
- typeof value.arrayBuffer === 'function' &&
- typeof value.constructor === 'function' &&
- typeof value.constructor.name === 'string' &&
- /^(Blob|File)$/.test(value.constructor.name) &&
- /^(Blob|File)$/.test(value[Symbol.toStringTag])
- );
-};
-
-export const isFormData = (value: any): value is FormData => {
- return value instanceof FormData;
-};
-
-export const base64 = (str: string): string => {
- try {
- return btoa(str);
- } catch (err) {
- // @ts-ignore
- return Buffer.from(str).toString('base64');
- }
-};
-
-export const getQueryString = (params: Record): string => {
- const qs: string[] = [];
-
- const append = (key: string, value: any) => {
- qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
- };
-
- const process = (key: string, value: any) => {
- if (isDefined(value)) {
- if (Array.isArray(value)) {
- value.forEach(v => {
- process(key, v);
- });
- } else if (typeof value === 'object') {
- Object.entries(value).forEach(([k, v]) => {
- process(`${key}[${k}]`, v);
- });
- } else {
- append(key, value);
- }
- }
- };
-
- Object.entries(params).forEach(([key, value]) => {
- process(key, value);
- });
-
- if (qs.length > 0) {
- return `?${qs.join('&')}`;
- }
-
- return '';
-};
-
-const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
- const encoder = config.ENCODE_PATH || encodeURI;
-
- const path = options.url
- .replace('{api-version}', config.VERSION)
- .replace(/{(.*?)}/g, (substring: string, group: string) => {
- if (options.path?.hasOwnProperty(group)) {
- return encoder(String(options.path[group]));
- }
- return substring;
- });
-
- const url = `${config.BASE}${path}`;
- if (options.query) {
- return `${url}${getQueryString(options.query)}`;
- }
- return url;
-};
-
-export const getFormData = (options: ApiRequestOptions): FormData | undefined => {
- if (options.formData) {
- const formData = new FormData();
-
- const process = (key: string, value: any) => {
- if (isString(value) || isBlob(value)) {
- formData.append(key, value);
- } else {
- formData.append(key, JSON.stringify(value));
- }
- };
-
- Object.entries(options.formData)
- .filter(([_, value]) => isDefined(value))
- .forEach(([key, value]) => {
- if (Array.isArray(value)) {
- value.forEach(v => process(key, v));
- } else {
- process(key, value);
- }
- });
-
- return formData;
- }
- return undefined;
-};
-
-type Resolver = (options: ApiRequestOptions) => Promise;
-
-export const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => {
- if (typeof resolver === 'function') {
- return (resolver as Resolver)(options);
- }
- return resolver;
-};
-
-export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => {
- const [token, username, password, additionalHeaders] = await Promise.all([
- resolve(options, config.TOKEN),
- resolve(options, config.USERNAME),
- resolve(options, config.PASSWORD),
- resolve(options, config.HEADERS),
- ]);
-
- const headers = Object.entries({
- Accept: 'application/json',
- ...additionalHeaders,
- ...options.headers,
- })
- .filter(([_, value]) => isDefined(value))
- .reduce((headers, [key, value]) => ({
- ...headers,
- [key]: String(value),
- }), {} as Record);
-
- if (isStringWithValue(token)) {
- headers['Authorization'] = `Bearer ${token}`;
- }
-
- if (isStringWithValue(username) && isStringWithValue(password)) {
- const credentials = base64(`${username}:${password}`);
- headers['Authorization'] = `Basic ${credentials}`;
- }
-
- if (options.body !== undefined) {
- if (options.mediaType) {
- headers['Content-Type'] = options.mediaType;
- } else if (isBlob(options.body)) {
- headers['Content-Type'] = options.body.type || 'application/octet-stream';
- } else if (isString(options.body)) {
- headers['Content-Type'] = 'text/plain';
- } else if (!isFormData(options.body)) {
- headers['Content-Type'] = 'application/json';
- }
- }
-
- return new Headers(headers);
-};
-
-export const getRequestBody = (options: ApiRequestOptions): any => {
- if (options.body !== undefined) {
- if (options.mediaType?.includes('/json')) {
- return JSON.stringify(options.body)
- } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) {
- return options.body;
- } else {
- return JSON.stringify(options.body);
- }
- }
- return undefined;
-};
-
-export const sendRequest = async (
- config: OpenAPIConfig,
- options: ApiRequestOptions,
- url: string,
- body: any,
- formData: FormData | undefined,
- headers: Headers,
- onCancel: OnCancel
-): Promise => {
- const controller = new AbortController();
-
- const request: RequestInit = {
- headers,
- body: body ?? formData,
- method: options.method,
- signal: controller.signal,
- };
-
- if (config.WITH_CREDENTIALS) {
- request.credentials = config.CREDENTIALS;
- }
-
- onCancel(() => controller.abort());
-
- return await fetch(url, request);
-};
-
-export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => {
- if (responseHeader) {
- const content = response.headers.get(responseHeader);
- if (isString(content)) {
- return content;
- }
- }
- return undefined;
-};
-
-export const getResponseBody = async (response: Response): Promise => {
- if (response.status !== 204) {
- try {
- const contentType = response.headers.get('Content-Type');
- if (contentType) {
- const jsonTypes = ['application/json', 'application/problem+json']
- const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
- if (isJSON) {
- return await response.json();
- } else {
- return await response.text();
- }
- }
- } catch (error) {
- console.error(error);
- }
- }
- return undefined;
-};
-
-export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
- const errors: Record = {
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 403: 'Forbidden',
- 404: 'Not Found',
- 500: 'Internal Server Error',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- ...options.errors,
- }
-
- const error = errors[result.status];
- if (error) {
- throw new ApiError(options, result, error);
- }
-
- if (!result.ok) {
- const errorStatus = result.status ?? 'unknown';
- const errorStatusText = result.statusText ?? 'unknown';
- const errorBody = (() => {
- try {
- return JSON.stringify(result.body, null, 2);
- } catch (e) {
- return undefined;
- }
- })();
-
- throw new ApiError(options, result,
- `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}`
- );
- }
-};
-
-/**
- * Request method
- * @param config The OpenAPI configuration object
- * @param options The request options from the service
- * @returns CancelablePromise
- * @throws ApiError
- */
-export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => {
- return new CancelablePromise(async (resolve, reject, onCancel) => {
- try {
- const url = getUrl(config, options);
- const formData = getFormData(options);
- const body = getRequestBody(options);
- const headers = await getHeaders(config, options);
-
- if (!onCancel.isCancelled) {
- const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
- const responseBody = await getResponseBody(response);
- const responseHeader = getResponseHeader(response, options.responseHeader);
-
- const result: ApiResult = {
- url,
- ok: response.ok,
- status: response.status,
- statusText: response.statusText,
- body: responseHeader ?? responseBody,
- };
-
- catchErrorCodes(options, result);
-
- resolve(result.body);
- }
- } catch (error) {
- reject(error);
- }
- });
-};
diff --git a/src/chongming-web/src/api/generated/core/serverSentEvents.gen.ts b/src/chongming-web/src/api/generated/core/serverSentEvents.gen.ts
new file mode 100644
index 0000000..ddf3c4d
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/serverSentEvents.gen.ts
@@ -0,0 +1,242 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import type { Config } from './types.gen';
+
+export type ServerSentEventsOptions = Omit &
+ 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 = {
+ stream: AsyncGenerator<
+ TData extends Record ? TData[keyof TData] : TData,
+ TReturn,
+ TNext
+ >;
+};
+
+export function 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;
+ buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings
+
+ 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/src/chongming-web/src/api/generated/core/types.gen.ts b/src/chongming-web/src/api/generated/core/types.gen.ts
new file mode 100644
index 0000000..9efe71d
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/types.gen.ts
@@ -0,0 +1,104 @@
+// 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/src/chongming-web/src/api/generated/core/utils.gen.ts b/src/chongming-web/src/api/generated/core/utils.gen.ts
new file mode 100644
index 0000000..9a4fec7
--- /dev/null
+++ b/src/chongming-web/src/api/generated/core/utils.gen.ts
@@ -0,0 +1,140 @@
+// 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/src/chongming-web/src/api/generated/index.ts b/src/chongming-web/src/api/generated/index.ts
index 0747deb..b2e5c2a 100644
--- a/src/chongming-web/src/api/generated/index.ts
+++ b/src/chongming-web/src/api/generated/index.ts
@@ -1,24 +1,4 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export { ApiError } from './core/ApiError';
-export { CancelablePromise, CancelError } from './core/CancelablePromise';
-export { OpenAPI } from './core/OpenAPI';
-export type { OpenAPIConfig } from './core/OpenAPI';
+// This file is auto-generated by @hey-api/openapi-ts
-export type { HTTPValidationError } from './models/HTTPValidationError';
-export type { RefreshTokenResponse } from './models/RefreshTokenResponse';
-export type { TaskRequest } from './models/TaskRequest';
-export type { TodoCreate } from './models/TodoCreate';
-export type { TodoRead } from './models/TodoRead';
-export type { TodoUpdate } from './models/TodoUpdate';
-export type { TokenResponse } from './models/TokenResponse';
-export type { UserCreate } from './models/UserCreate';
-export type { UserLogin } from './models/UserLogin';
-export type { UserRead } from './models/UserRead';
-export type { ValidationError } from './models/ValidationError';
-
-export { AuthenticationService } from './services/AuthenticationService';
-export { DefaultService } from './services/DefaultService';
-export { TodoService } from './services/TodoService';
+export { createTodoApiV1TodosPost, deleteTodoApiV1TodosTodoIdDelete, getCurrentUserInfoApiV1AuthMeGet, getSessionsApiV1AuthSessionsGet, loginApiV1AuthLoginPost, logoutAllApiV1AuthLogoutAllPost, logoutApiV1AuthLogoutPost, type Options, readTodoApiV1TodosTodoIdGet, readTodosApiV1TodosGet, refreshTokenApiV1AuthRefreshPost, registerApiV1AuthRegisterPost, rootGet, updateTodoApiV1TodosTodoIdPatch, uploadImageApiV1UploadImagePost } from './sdk.gen';
+export type { BodyUploadImageApiV1UploadImagePost, ClientOptions, CreateTodoApiV1TodosPostData, CreateTodoApiV1TodosPostError, CreateTodoApiV1TodosPostErrors, CreateTodoApiV1TodosPostResponse, CreateTodoApiV1TodosPostResponses, DeleteTodoApiV1TodosTodoIdDeleteData, DeleteTodoApiV1TodosTodoIdDeleteError, DeleteTodoApiV1TodosTodoIdDeleteErrors, DeleteTodoApiV1TodosTodoIdDeleteResponses, Detail, GetCurrentUserInfoApiV1AuthMeGetData, GetCurrentUserInfoApiV1AuthMeGetError, GetCurrentUserInfoApiV1AuthMeGetErrors, GetCurrentUserInfoApiV1AuthMeGetResponse, GetCurrentUserInfoApiV1AuthMeGetResponses, GetSessionsApiV1AuthSessionsGetData, GetSessionsApiV1AuthSessionsGetResponses, HttpError, HttpValidationError, LoginApiV1AuthLoginPostData, LoginApiV1AuthLoginPostError, LoginApiV1AuthLoginPostErrors, LoginApiV1AuthLoginPostResponse, LoginApiV1AuthLoginPostResponses, LogoutAllApiV1AuthLogoutAllPostData, LogoutAllApiV1AuthLogoutAllPostResponse, LogoutAllApiV1AuthLogoutAllPostResponses, LogoutApiV1AuthLogoutPostData, LogoutApiV1AuthLogoutPostResponse, LogoutApiV1AuthLogoutPostResponses, ReadTodoApiV1TodosTodoIdGetData, ReadTodoApiV1TodosTodoIdGetError, ReadTodoApiV1TodosTodoIdGetErrors, ReadTodoApiV1TodosTodoIdGetResponse, ReadTodoApiV1TodosTodoIdGetResponses, ReadTodosApiV1TodosGetData, ReadTodosApiV1TodosGetError, ReadTodosApiV1TodosGetErrors, ReadTodosApiV1TodosGetResponse, ReadTodosApiV1TodosGetResponses, RefreshTokenApiV1AuthRefreshPostData, RefreshTokenApiV1AuthRefreshPostError, RefreshTokenApiV1AuthRefreshPostErrors, RefreshTokenApiV1AuthRefreshPostResponse, RefreshTokenApiV1AuthRefreshPostResponses, RefreshTokenResponse, RegisterApiV1AuthRegisterPostData, RegisterApiV1AuthRegisterPostError, RegisterApiV1AuthRegisterPostErrors, RegisterApiV1AuthRegisterPostResponse, RegisterApiV1AuthRegisterPostResponses, RootGetData, RootGetResponses, TodoCreate, TodoRead, TodoUpdate, TokenResponse, UpdateTodoApiV1TodosTodoIdPatchData, UpdateTodoApiV1TodosTodoIdPatchError, UpdateTodoApiV1TodosTodoIdPatchErrors, UpdateTodoApiV1TodosTodoIdPatchResponse, UpdateTodoApiV1TodosTodoIdPatchResponses, UploadImageApiV1UploadImagePostData, UploadImageApiV1UploadImagePostError, UploadImageApiV1UploadImagePostErrors, UploadImageApiV1UploadImagePostResponse, UploadImageApiV1UploadImagePostResponses, UploadResponse, UserCreate, UserLogin, Userlogout, UserRead, ValidationError } from './types.gen';
diff --git a/src/chongming-web/src/api/generated/models/HTTPValidationError.ts b/src/chongming-web/src/api/generated/models/HTTPValidationError.ts
deleted file mode 100644
index f9b1a79..0000000
--- a/src/chongming-web/src/api/generated/models/HTTPValidationError.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import type { ValidationError } from './ValidationError';
-export type HTTPValidationError = {
- detail?: Array;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/RefreshTokenResponse.ts b/src/chongming-web/src/api/generated/models/RefreshTokenResponse.ts
deleted file mode 100644
index 289ca28..0000000
--- a/src/chongming-web/src/api/generated/models/RefreshTokenResponse.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-/**
- * 刷新 Token 响应模型
- */
-export type RefreshTokenResponse = {
- access_token: string;
- token_type?: string;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/TaskRequest.ts b/src/chongming-web/src/api/generated/models/TaskRequest.ts
deleted file mode 100644
index 5d1a601..0000000
--- a/src/chongming-web/src/api/generated/models/TaskRequest.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type TaskRequest = {
- task_name: string;
- interval: number;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/TodoCreate.ts b/src/chongming-web/src/api/generated/models/TodoCreate.ts
deleted file mode 100644
index 9e0630c..0000000
--- a/src/chongming-web/src/api/generated/models/TodoCreate.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type TodoCreate = {
- title: string;
- description?: (string | null);
- completed?: boolean;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/TodoRead.ts b/src/chongming-web/src/api/generated/models/TodoRead.ts
deleted file mode 100644
index 2c88da7..0000000
--- a/src/chongming-web/src/api/generated/models/TodoRead.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type TodoRead = {
- title: string;
- description?: (string | null);
- completed?: boolean;
- id: number;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/TodoUpdate.ts b/src/chongming-web/src/api/generated/models/TodoUpdate.ts
deleted file mode 100644
index b6cf6c2..0000000
--- a/src/chongming-web/src/api/generated/models/TodoUpdate.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type TodoUpdate = {
- title?: (string | null);
- description?: (string | null);
- completed?: (boolean | null);
-};
-
diff --git a/src/chongming-web/src/api/generated/models/TokenResponse.ts b/src/chongming-web/src/api/generated/models/TokenResponse.ts
deleted file mode 100644
index 38ad91a..0000000
--- a/src/chongming-web/src/api/generated/models/TokenResponse.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-/**
- * Token 响应模型
- */
-export type TokenResponse = {
- access_token: string;
- refresh_token: string;
- token_type?: string;
- expires_in: number;
- refresh_expires_in: number;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/UserCreate.ts b/src/chongming-web/src/api/generated/models/UserCreate.ts
deleted file mode 100644
index 7d269db..0000000
--- a/src/chongming-web/src/api/generated/models/UserCreate.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-/**
- * 用户创建模型
- */
-export type UserCreate = {
- email: string;
- username?: (string | null);
- full_name?: (string | null);
- is_active?: boolean;
- is_superuser?: boolean;
- created_at?: (string | null);
- password: string;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/UserLogin.ts b/src/chongming-web/src/api/generated/models/UserLogin.ts
deleted file mode 100644
index 717d42c..0000000
--- a/src/chongming-web/src/api/generated/models/UserLogin.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type UserLogin = {
- email: string;
- password: string;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/UserRead.ts b/src/chongming-web/src/api/generated/models/UserRead.ts
deleted file mode 100644
index e802a49..0000000
--- a/src/chongming-web/src/api/generated/models/UserRead.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-/**
- * 用户读取模型
- */
-export type UserRead = {
- email: string;
- username?: (string | null);
- full_name?: (string | null);
- is_active?: boolean;
- is_superuser?: boolean;
- created_at?: (string | null);
- id: number;
-};
-
diff --git a/src/chongming-web/src/api/generated/models/ValidationError.ts b/src/chongming-web/src/api/generated/models/ValidationError.ts
deleted file mode 100644
index de2cbd7..0000000
--- a/src/chongming-web/src/api/generated/models/ValidationError.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-export type ValidationError = {
- loc: Array<(string | number)>;
- msg: string;
- type: string;
- input?: any;
- ctx?: Record;
-};
-
diff --git a/src/chongming-web/src/api/generated/sdk.gen.ts b/src/chongming-web/src/api/generated/sdk.gen.ts
new file mode 100644
index 0000000..863f1ed
--- /dev/null
+++ b/src/chongming-web/src/api/generated/sdk.gen.ts
@@ -0,0 +1,166 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+import { type Client, formDataBodySerializer, type Options as Options2, type TDataShape } from './client';
+import { client } from './client.gen';
+import type { CreateTodoApiV1TodosPostData, CreateTodoApiV1TodosPostErrors, CreateTodoApiV1TodosPostResponses, DeleteTodoApiV1TodosTodoIdDeleteData, DeleteTodoApiV1TodosTodoIdDeleteErrors, DeleteTodoApiV1TodosTodoIdDeleteResponses, GetCurrentUserInfoApiV1AuthMeGetData, GetCurrentUserInfoApiV1AuthMeGetErrors, GetCurrentUserInfoApiV1AuthMeGetResponses, GetSessionsApiV1AuthSessionsGetData, GetSessionsApiV1AuthSessionsGetResponses, LoginApiV1AuthLoginPostData, LoginApiV1AuthLoginPostErrors, LoginApiV1AuthLoginPostResponses, LogoutAllApiV1AuthLogoutAllPostData, LogoutAllApiV1AuthLogoutAllPostResponses, LogoutApiV1AuthLogoutPostData, LogoutApiV1AuthLogoutPostResponses, ReadTodoApiV1TodosTodoIdGetData, ReadTodoApiV1TodosTodoIdGetErrors, ReadTodoApiV1TodosTodoIdGetResponses, ReadTodosApiV1TodosGetData, ReadTodosApiV1TodosGetErrors, ReadTodosApiV1TodosGetResponses, RefreshTokenApiV1AuthRefreshPostData, RefreshTokenApiV1AuthRefreshPostErrors, RefreshTokenApiV1AuthRefreshPostResponses, RegisterApiV1AuthRegisterPostData, RegisterApiV1AuthRegisterPostErrors, RegisterApiV1AuthRegisterPostResponses, RootGetData, RootGetResponses, UpdateTodoApiV1TodosTodoIdPatchData, UpdateTodoApiV1TodosTodoIdPatchErrors, UpdateTodoApiV1TodosTodoIdPatchResponses, UploadImageApiV1UploadImagePostData, UploadImageApiV1UploadImagePostErrors, UploadImageApiV1UploadImagePostResponses } from './types.gen';
+
+export type Options = Options2 & {
+ /**
+ * 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;
+};
+
+/**
+ * Read Todos
+ */
+export const readTodosApiV1TodosGet = (options?: Options) => (options?.client ?? client).get({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/todos/',
+ ...options
+});
+
+/**
+ * Create Todo
+ */
+export const createTodoApiV1TodosPost = (options: Options) => (options.client ?? client).post({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/todos/',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+});
+
+/**
+ * Delete Todo
+ */
+export const deleteTodoApiV1TodosTodoIdDelete = (options: Options) => (options.client ?? client).delete({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/todos/{todo_id}',
+ ...options
+});
+
+/**
+ * Read Todo
+ */
+export const readTodoApiV1TodosTodoIdGet = (options: Options) => (options.client ?? client).get({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/todos/{todo_id}',
+ ...options
+});
+
+/**
+ * Update Todo
+ */
+export const updateTodoApiV1TodosTodoIdPatch = (options: Options) => (options.client ?? client).patch({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/todos/{todo_id}',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+});
+
+/**
+ * Register
+ */
+export const registerApiV1AuthRegisterPost = (options: Options) => (options.client ?? client).post({
+ url: '/api/v1/auth/register',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+});
+
+/**
+ * Login
+ */
+export const loginApiV1AuthLoginPost = (options: Options) => (options.client ?? client).post({
+ url: '/api/v1/auth/login',
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...options.headers
+ }
+});
+
+/**
+ * 刷新访问令牌
+ */
+export const refreshTokenApiV1AuthRefreshPost = (options?: Options) => (options?.client ?? client).post({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/auth/refresh',
+ ...options
+});
+
+/**
+ * Logout
+ */
+export const logoutApiV1AuthLogoutPost = (options?: Options) => (options?.client ?? client).post({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/auth/logout',
+ ...options
+});
+
+/**
+ * 登出所有设备
+ */
+export const logoutAllApiV1AuthLogoutAllPost = (options?: Options) => (options?.client ?? client).post({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/auth/logout-all',
+ ...options
+});
+
+/**
+ * 获取用户会话
+ *
+ * 获取用户的所有活跃会话
+ */
+export const getSessionsApiV1AuthSessionsGet = (options?: Options) => (options?.client ?? client).get({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/auth/sessions',
+ ...options
+});
+
+/**
+ * 获取当前用户信息
+ *
+ * 获取当前登录用户的信息
+ */
+export const getCurrentUserInfoApiV1AuthMeGet = (options?: Options) => (options?.client ?? client).get({
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/auth/me',
+ ...options
+});
+
+/**
+ * Upload Image
+ */
+export const uploadImageApiV1UploadImagePost = (options: Options) => (options.client ?? client).post({
+ ...formDataBodySerializer,
+ security: [{ scheme: 'bearer', type: 'http' }],
+ url: '/api/v1/upload/image',
+ ...options,
+ headers: {
+ 'Content-Type': null,
+ ...options.headers
+ }
+});
+
+/**
+ * 根路径
+ *
+ * 根路径,返回应用信息
+ */
+export const rootGet = (options?: Options) => (options?.client ?? client).get({ url: '/', ...options });
diff --git a/src/chongming-web/src/api/generated/services/AuthenticationService.ts b/src/chongming-web/src/api/generated/services/AuthenticationService.ts
deleted file mode 100644
index 8c666d6..0000000
--- a/src/chongming-web/src/api/generated/services/AuthenticationService.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import type { RefreshTokenResponse } from '../models/RefreshTokenResponse';
-import type { TokenResponse } from '../models/TokenResponse';
-import type { UserCreate } from '../models/UserCreate';
-import type { UserLogin } from '../models/UserLogin';
-import type { UserRead } from '../models/UserRead';
-import type { CancelablePromise } from '../core/CancelablePromise';
-import { OpenAPI } from '../core/OpenAPI';
-import { request as __request } from '../core/request';
-export class AuthenticationService {
- /**
- * Register
- * @param requestBody
- * @returns UserRead Successful Response
- * @throws ApiError
- */
- public static registerApiV1AuthRegisterPost(
- requestBody: UserCreate,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/api/v1/auth/register',
- body: requestBody,
- mediaType: 'application/json',
- errors: {
- 422: `Validation Error`,
- },
- });
- }
- /**
- * Login
- * @param requestBody
- * @returns TokenResponse Successful Response
- * @throws ApiError
- */
- public static loginApiV1AuthLoginPost(
- requestBody: UserLogin,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/api/v1/auth/login',
- body: requestBody,
- mediaType: 'application/json',
- errors: {
- 422: `Validation Error`,
- },
- });
- }
- /**
- * 刷新访问令牌
- * @returns RefreshTokenResponse Successful Response
- * @throws ApiError
- */
- public static refreshTokenApiV1AuthRefreshPost(): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/api/v1/auth/refresh',
- });
- }
- /**
- * Logout
- * @returns any Successful Response
- * @throws ApiError
- */
- public static logoutApiV1AuthLogoutPost(): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/api/v1/auth/logout',
- });
- }
- /**
- * 登出所有设备
- * @returns any Successful Response
- * @throws ApiError
- */
- public static logoutAllApiV1AuthLogoutAllPost(): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/api/v1/auth/logout-all',
- });
- }
- /**
- * 获取用户会话
- * 获取用户的所有活跃会话
- * @returns any Successful Response
- * @throws ApiError
- */
- public static getSessionsApiV1AuthSessionsGet(): CancelablePromise {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/api/v1/auth/sessions',
- });
- }
- /**
- * 获取当前用户信息
- * 获取当前登录用户的信息
- * @returns UserRead Successful Response
- * @throws ApiError
- */
- public static getCurrentUserInfoApiV1AuthMeGet(): CancelablePromise {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/api/v1/auth/me',
- });
- }
-}
diff --git a/src/chongming-web/src/api/generated/services/DefaultService.ts b/src/chongming-web/src/api/generated/services/DefaultService.ts
deleted file mode 100644
index ae257e0..0000000
--- a/src/chongming-web/src/api/generated/services/DefaultService.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import type { TaskRequest } from '../models/TaskRequest';
-import type { CancelablePromise } from '../core/CancelablePromise';
-import { OpenAPI } from '../core/OpenAPI';
-import { request as __request } from '../core/request';
-export class DefaultService {
- /**
- * 根路径
- * 根路径,返回应用信息
- * @returns any Successful Response
- * @throws ApiError
- */
- public static rootGet(): CancelablePromise {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/',
- });
- }
- /**
- * Add Task
- * 添加定时任务接口
- * @param requestBody
- * @returns any Successful Response
- * @throws ApiError
- */
- public static addTaskSchedulePost(
- requestBody: TaskRequest,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/schedule',
- body: requestBody,
- mediaType: 'application/json',
- errors: {
- 422: `Validation Error`,
- },
- });
- }
-}
diff --git a/src/chongming-web/src/api/generated/services/TodoService.ts b/src/chongming-web/src/api/generated/services/TodoService.ts
deleted file mode 100644
index d2f5b71..0000000
--- a/src/chongming-web/src/api/generated/services/TodoService.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-/* generated using openapi-typescript-codegen -- do not edit */
-/* istanbul ignore file */
-/* tslint:disable */
-/* eslint-disable */
-import type { TodoCreate } from '../models/TodoCreate';
-import type { TodoRead } from '../models/TodoRead';
-import type { TodoUpdate } from '../models/TodoUpdate';
-import type { CancelablePromise } from '../core/CancelablePromise';
-import { OpenAPI } from '../core/OpenAPI';
-import { request as __request } from '../core/request';
-export class TodoService {
- /**
- * Create Todo
- * @param requestBody
- * @returns TodoRead Successful Response
- * @throws ApiError
- */
- public static createTodoApiV1TodosPost(
- requestBody: TodoCreate,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'POST',
- url: '/api/v1/todos/',
- body: requestBody,
- mediaType: 'application/json',
- errors: {
- 422: `Validation Error`,
- },
- });
- }
- /**
- * Read Todos
- * @param offset
- * @param limit
- * @returns TodoRead Successful Response
- * @throws ApiError
- */
- public static readTodosApiV1TodosGet(
- offset?: number,
- limit: number = 100,
- ): CancelablePromise> {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/api/v1/todos/',
- query: {
- 'offset': offset,
- 'limit': limit,
- },
- errors: {
- 422: `Validation Error`,
- },
- });
- }
- /**
- * Read Todo
- * @param todoId
- * @returns TodoRead Successful Response
- * @throws ApiError
- */
- public static readTodoApiV1TodosTodoIdGet(
- todoId: number,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/api/v1/todos/{todo_id}',
- path: {
- 'todo_id': todoId,
- },
- errors: {
- 422: `Validation Error`,
- },
- });
- }
- /**
- * Update Todo
- * @param todoId
- * @param requestBody
- * @returns TodoRead Successful Response
- * @throws ApiError
- */
- public static updateTodoApiV1TodosTodoIdPatch(
- todoId: number,
- requestBody: TodoUpdate,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'PATCH',
- url: '/api/v1/todos/{todo_id}',
- path: {
- 'todo_id': todoId,
- },
- body: requestBody,
- mediaType: 'application/json',
- errors: {
- 422: `Validation Error`,
- },
- });
- }
- /**
- * Delete Todo
- * @param todoId
- * @returns any Successful Response
- * @throws ApiError
- */
- public static deleteTodoApiV1TodosTodoIdDelete(
- todoId: number,
- ): CancelablePromise {
- return __request(OpenAPI, {
- method: 'DELETE',
- url: '/api/v1/todos/{todo_id}',
- path: {
- 'todo_id': todoId,
- },
- errors: {
- 422: `Validation Error`,
- },
- });
- }
-}
diff --git a/src/chongming-web/src/api/generated/types.gen.ts b/src/chongming-web/src/api/generated/types.gen.ts
new file mode 100644
index 0000000..209a857
--- /dev/null
+++ b/src/chongming-web/src/api/generated/types.gen.ts
@@ -0,0 +1,644 @@
+// This file is auto-generated by @hey-api/openapi-ts
+
+export type ClientOptions = {
+ baseUrl: 'http://127.0.0.1:8000' | (string & {});
+};
+
+/**
+ * Body_upload_image_api_v1_upload_image_post
+ */
+export type BodyUploadImageApiV1UploadImagePost = {
+ /**
+ * File
+ */
+ file: Blob | File;
+};
+
+/**
+ * Detail
+ */
+export type Detail = {
+ /**
+ * Message
+ */
+ message: string;
+ /**
+ * Code
+ */
+ code: number;
+};
+
+/**
+ * HTTPError
+ */
+export type HttpError = {
+ detail?: Detail | null;
+};
+
+/**
+ * HTTPValidationError
+ */
+export type HttpValidationError = {
+ /**
+ * Detail
+ */
+ detail?: Array;
+};
+
+/**
+ * RefreshTokenResponse
+ *
+ * 刷新 Token 响应模型
+ */
+export type RefreshTokenResponse = {
+ /**
+ * Access Token
+ */
+ access_token: string;
+ /**
+ * Token Type
+ */
+ token_type?: string;
+};
+
+/**
+ * TodoCreate
+ */
+export type TodoCreate = {
+ /**
+ * Title
+ */
+ title: string;
+ /**
+ * Description
+ */
+ description?: string | null;
+ /**
+ * Completed
+ */
+ completed?: boolean;
+};
+
+/**
+ * TodoRead
+ */
+export type TodoRead = {
+ /**
+ * Title
+ */
+ title: string;
+ /**
+ * Description
+ */
+ description?: string | null;
+ /**
+ * Completed
+ */
+ completed?: boolean;
+ /**
+ * Id
+ */
+ id: number;
+};
+
+/**
+ * TodoUpdate
+ */
+export type TodoUpdate = {
+ /**
+ * Title
+ */
+ title?: string | null;
+ /**
+ * Description
+ */
+ description?: string | null;
+ /**
+ * Completed
+ */
+ completed?: boolean | null;
+};
+
+/**
+ * TokenResponse
+ *
+ * Token 响应模型
+ */
+export type TokenResponse = {
+ /**
+ * Access Token
+ */
+ access_token: string;
+ /**
+ * Refresh Token
+ */
+ refresh_token: string;
+ /**
+ * Token Type
+ */
+ token_type?: string;
+ /**
+ * Expires In
+ */
+ expires_in: number;
+ /**
+ * Refresh Expires In
+ */
+ refresh_expires_in: number;
+};
+
+/**
+ * UploadResponse
+ */
+export type UploadResponse = {
+ /**
+ * Url
+ */
+ url: string;
+ /**
+ * Filename
+ */
+ filename: string;
+ /**
+ * File Type
+ */
+ file_type: string;
+};
+
+/**
+ * UserCreate
+ *
+ * 用户创建模型
+ */
+export type UserCreate = {
+ /**
+ * Email
+ */
+ email: string;
+ /**
+ * Username
+ */
+ username?: string | null;
+ /**
+ * Full Name
+ */
+ full_name?: string | null;
+ /**
+ * Is Active
+ */
+ is_active?: boolean;
+ /**
+ * Is Superuser
+ */
+ is_superuser?: boolean;
+ /**
+ * Created At
+ */
+ created_at?: string | null;
+ /**
+ * Password
+ */
+ password: string;
+};
+
+/**
+ * UserLogin
+ */
+export type UserLogin = {
+ /**
+ * Email
+ */
+ email: string;
+ /**
+ * Password
+ */
+ password: string;
+};
+
+/**
+ * UserRead
+ *
+ * 用户读取模型
+ */
+export type UserRead = {
+ /**
+ * Email
+ */
+ email: string;
+ /**
+ * Username
+ */
+ username?: string | null;
+ /**
+ * Full Name
+ */
+ full_name?: string | null;
+ /**
+ * Is Active
+ */
+ is_active?: boolean;
+ /**
+ * Is Superuser
+ */
+ is_superuser?: boolean;
+ /**
+ * Created At
+ */
+ created_at?: string | null;
+ /**
+ * Id
+ */
+ id: string;
+};
+
+/**
+ * Userlogout
+ */
+export type Userlogout = {
+ /**
+ * Code
+ */
+ code?: number;
+ /**
+ * Message
+ */
+ message?: string;
+};
+
+/**
+ * ValidationError
+ */
+export type ValidationError = {
+ /**
+ * Location
+ */
+ loc: Array;
+ /**
+ * Message
+ */
+ msg: string;
+ /**
+ * Error Type
+ */
+ type: string;
+ /**
+ * Input
+ */
+ input?: unknown;
+ /**
+ * Context
+ */
+ ctx?: {
+ [key: string]: unknown;
+ };
+};
+
+export type ReadTodosApiV1TodosGetData = {
+ body?: never;
+ path?: never;
+ query?: {
+ /**
+ * Offset
+ */
+ offset?: number;
+ /**
+ * Limit
+ */
+ limit?: number;
+ };
+ url: '/api/v1/todos/';
+};
+
+export type ReadTodosApiV1TodosGetErrors = {
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type ReadTodosApiV1TodosGetError = ReadTodosApiV1TodosGetErrors[keyof ReadTodosApiV1TodosGetErrors];
+
+export type ReadTodosApiV1TodosGetResponses = {
+ /**
+ * Response Read Todos Api V1 Todos Get
+ *
+ * Successful Response
+ */
+ 200: Array;
+};
+
+export type ReadTodosApiV1TodosGetResponse = ReadTodosApiV1TodosGetResponses[keyof ReadTodosApiV1TodosGetResponses];
+
+export type CreateTodoApiV1TodosPostData = {
+ body: TodoCreate;
+ path?: never;
+ query?: never;
+ url: '/api/v1/todos/';
+};
+
+export type CreateTodoApiV1TodosPostErrors = {
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type CreateTodoApiV1TodosPostError = CreateTodoApiV1TodosPostErrors[keyof CreateTodoApiV1TodosPostErrors];
+
+export type CreateTodoApiV1TodosPostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: TodoRead;
+};
+
+export type CreateTodoApiV1TodosPostResponse = CreateTodoApiV1TodosPostResponses[keyof CreateTodoApiV1TodosPostResponses];
+
+export type DeleteTodoApiV1TodosTodoIdDeleteData = {
+ body?: never;
+ path: {
+ /**
+ * Todo Id
+ */
+ todo_id: number;
+ };
+ query?: never;
+ url: '/api/v1/todos/{todo_id}';
+};
+
+export type DeleteTodoApiV1TodosTodoIdDeleteErrors = {
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type DeleteTodoApiV1TodosTodoIdDeleteError = DeleteTodoApiV1TodosTodoIdDeleteErrors[keyof DeleteTodoApiV1TodosTodoIdDeleteErrors];
+
+export type DeleteTodoApiV1TodosTodoIdDeleteResponses = {
+ /**
+ * Successful Response
+ */
+ 200: unknown;
+};
+
+export type ReadTodoApiV1TodosTodoIdGetData = {
+ body?: never;
+ path: {
+ /**
+ * Todo Id
+ */
+ todo_id: number;
+ };
+ query?: never;
+ url: '/api/v1/todos/{todo_id}';
+};
+
+export type ReadTodoApiV1TodosTodoIdGetErrors = {
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type ReadTodoApiV1TodosTodoIdGetError = ReadTodoApiV1TodosTodoIdGetErrors[keyof ReadTodoApiV1TodosTodoIdGetErrors];
+
+export type ReadTodoApiV1TodosTodoIdGetResponses = {
+ /**
+ * Successful Response
+ */
+ 200: TodoRead;
+};
+
+export type ReadTodoApiV1TodosTodoIdGetResponse = ReadTodoApiV1TodosTodoIdGetResponses[keyof ReadTodoApiV1TodosTodoIdGetResponses];
+
+export type UpdateTodoApiV1TodosTodoIdPatchData = {
+ body: TodoUpdate;
+ path: {
+ /**
+ * Todo Id
+ */
+ todo_id: number;
+ };
+ query?: never;
+ url: '/api/v1/todos/{todo_id}';
+};
+
+export type UpdateTodoApiV1TodosTodoIdPatchErrors = {
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type UpdateTodoApiV1TodosTodoIdPatchError = UpdateTodoApiV1TodosTodoIdPatchErrors[keyof UpdateTodoApiV1TodosTodoIdPatchErrors];
+
+export type UpdateTodoApiV1TodosTodoIdPatchResponses = {
+ /**
+ * Successful Response
+ */
+ 200: TodoRead;
+};
+
+export type UpdateTodoApiV1TodosTodoIdPatchResponse = UpdateTodoApiV1TodosTodoIdPatchResponses[keyof UpdateTodoApiV1TodosTodoIdPatchResponses];
+
+export type RegisterApiV1AuthRegisterPostData = {
+ body: UserCreate;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/register';
+};
+
+export type RegisterApiV1AuthRegisterPostErrors = {
+ /**
+ * 邮箱已被注册
+ */
+ 400: HttpError;
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type RegisterApiV1AuthRegisterPostError = RegisterApiV1AuthRegisterPostErrors[keyof RegisterApiV1AuthRegisterPostErrors];
+
+export type RegisterApiV1AuthRegisterPostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: UserRead;
+};
+
+export type RegisterApiV1AuthRegisterPostResponse = RegisterApiV1AuthRegisterPostResponses[keyof RegisterApiV1AuthRegisterPostResponses];
+
+export type LoginApiV1AuthLoginPostData = {
+ body: UserLogin;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/login';
+};
+
+export type LoginApiV1AuthLoginPostErrors = {
+ /**
+ * 邮箱不存在
+ */
+ 400: HttpError;
+ /**
+ * 密码错误
+ */
+ 401: HttpError;
+ /**
+ * 用户被禁用
+ */
+ 402: HttpError;
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type LoginApiV1AuthLoginPostError = LoginApiV1AuthLoginPostErrors[keyof LoginApiV1AuthLoginPostErrors];
+
+export type LoginApiV1AuthLoginPostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: TokenResponse;
+};
+
+export type LoginApiV1AuthLoginPostResponse = LoginApiV1AuthLoginPostResponses[keyof LoginApiV1AuthLoginPostResponses];
+
+export type RefreshTokenApiV1AuthRefreshPostData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/refresh';
+};
+
+export type RefreshTokenApiV1AuthRefreshPostErrors = {
+ /**
+ * 无效的刷新令牌
+ */
+ 401: HttpError;
+};
+
+export type RefreshTokenApiV1AuthRefreshPostError = RefreshTokenApiV1AuthRefreshPostErrors[keyof RefreshTokenApiV1AuthRefreshPostErrors];
+
+export type RefreshTokenApiV1AuthRefreshPostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: RefreshTokenResponse;
+};
+
+export type RefreshTokenApiV1AuthRefreshPostResponse = RefreshTokenApiV1AuthRefreshPostResponses[keyof RefreshTokenApiV1AuthRefreshPostResponses];
+
+export type LogoutApiV1AuthLogoutPostData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/logout';
+};
+
+export type LogoutApiV1AuthLogoutPostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: Userlogout;
+};
+
+export type LogoutApiV1AuthLogoutPostResponse = LogoutApiV1AuthLogoutPostResponses[keyof LogoutApiV1AuthLogoutPostResponses];
+
+export type LogoutAllApiV1AuthLogoutAllPostData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/logout-all';
+};
+
+export type LogoutAllApiV1AuthLogoutAllPostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: Userlogout;
+};
+
+export type LogoutAllApiV1AuthLogoutAllPostResponse = LogoutAllApiV1AuthLogoutAllPostResponses[keyof LogoutAllApiV1AuthLogoutAllPostResponses];
+
+export type GetSessionsApiV1AuthSessionsGetData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/sessions';
+};
+
+export type GetSessionsApiV1AuthSessionsGetResponses = {
+ /**
+ * Successful Response
+ */
+ 200: unknown;
+};
+
+export type GetCurrentUserInfoApiV1AuthMeGetData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/api/v1/auth/me';
+};
+
+export type GetCurrentUserInfoApiV1AuthMeGetErrors = {
+ /**
+ * 用户不存在
+ */
+ 404: HttpError;
+};
+
+export type GetCurrentUserInfoApiV1AuthMeGetError = GetCurrentUserInfoApiV1AuthMeGetErrors[keyof GetCurrentUserInfoApiV1AuthMeGetErrors];
+
+export type GetCurrentUserInfoApiV1AuthMeGetResponses = {
+ /**
+ * Successful Response
+ */
+ 200: UserRead;
+};
+
+export type GetCurrentUserInfoApiV1AuthMeGetResponse = GetCurrentUserInfoApiV1AuthMeGetResponses[keyof GetCurrentUserInfoApiV1AuthMeGetResponses];
+
+export type UploadImageApiV1UploadImagePostData = {
+ body: BodyUploadImageApiV1UploadImagePost;
+ path?: never;
+ query?: never;
+ url: '/api/v1/upload/image';
+};
+
+export type UploadImageApiV1UploadImagePostErrors = {
+ /**
+ * Validation Error
+ */
+ 422: HttpValidationError;
+};
+
+export type UploadImageApiV1UploadImagePostError = UploadImageApiV1UploadImagePostErrors[keyof UploadImageApiV1UploadImagePostErrors];
+
+export type UploadImageApiV1UploadImagePostResponses = {
+ /**
+ * Successful Response
+ */
+ 200: UploadResponse;
+};
+
+export type UploadImageApiV1UploadImagePostResponse = UploadImageApiV1UploadImagePostResponses[keyof UploadImageApiV1UploadImagePostResponses];
+
+export type RootGetData = {
+ body?: never;
+ path?: never;
+ query?: never;
+ url: '/';
+};
+
+export type RootGetResponses = {
+ /**
+ * Successful Response
+ */
+ 200: unknown;
+};
diff --git a/src/chongming-web/src/assets/base.css b/src/chongming-web/src/assets/base.css
deleted file mode 100644
index 8816868..0000000
--- a/src/chongming-web/src/assets/base.css
+++ /dev/null
@@ -1,86 +0,0 @@
-/* color palette from */
-:root {
- --vt-c-white: #ffffff;
- --vt-c-white-soft: #f8f8f8;
- --vt-c-white-mute: #f2f2f2;
-
- --vt-c-black: #181818;
- --vt-c-black-soft: #222222;
- --vt-c-black-mute: #282828;
-
- --vt-c-indigo: #2c3e50;
-
- --vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
- --vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
- --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
- --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
-
- --vt-c-text-light-1: var(--vt-c-indigo);
- --vt-c-text-light-2: rgba(60, 60, 60, 0.66);
- --vt-c-text-dark-1: var(--vt-c-white);
- --vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
-}
-
-/* semantic color variables for this project */
-:root {
- --color-background: var(--vt-c-white);
- --color-background-soft: var(--vt-c-white-soft);
- --color-background-mute: var(--vt-c-white-mute);
-
- --color-border: var(--vt-c-divider-light-2);
- --color-border-hover: var(--vt-c-divider-light-1);
-
- --color-heading: var(--vt-c-text-light-1);
- --color-text: var(--vt-c-text-light-1);
-
- --section-gap: 160px;
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --color-background: var(--vt-c-black);
- --color-background-soft: var(--vt-c-black-soft);
- --color-background-mute: var(--vt-c-black-mute);
-
- --color-border: var(--vt-c-divider-dark-2);
- --color-border-hover: var(--vt-c-divider-dark-1);
-
- --color-heading: var(--vt-c-text-dark-1);
- --color-text: var(--vt-c-text-dark-2);
- }
-}
-
-*,
-*::before,
-*::after {
- box-sizing: border-box;
- margin: 0;
- font-weight: normal;
-}
-
-body {
- min-height: 100vh;
- color: var(--color-text);
- background: var(--color-background);
- transition:
- color 0.5s,
- background-color 0.5s;
- line-height: 1.6;
- font-family:
- Inter,
- -apple-system,
- BlinkMacSystemFont,
- 'Segoe UI',
- Roboto,
- Oxygen,
- Ubuntu,
- Cantarell,
- 'Fira Sans',
- 'Droid Sans',
- 'Helvetica Neue',
- sans-serif;
- font-size: 15px;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
diff --git a/src/chongming-web/src/assets/main.css b/src/chongming-web/src/assets/main.css
deleted file mode 100644
index 36fb845..0000000
--- a/src/chongming-web/src/assets/main.css
+++ /dev/null
@@ -1,35 +0,0 @@
-@import './base.css';
-
-#app {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- font-weight: normal;
-}
-
-a,
-.green {
- text-decoration: none;
- color: hsla(160, 100%, 37%, 1);
- transition: 0.4s;
- padding: 3px;
-}
-
-@media (hover: hover) {
- a:hover {
- background-color: hsla(160, 100%, 37%, 0.2);
- }
-}
-
-@media (min-width: 1024px) {
- body {
- display: flex;
- place-items: center;
- }
-
- #app {
- display: grid;
- grid-template-columns: 1fr 1fr;
- padding: 0 2rem;
- }
-}
diff --git a/src/chongming-web/src/components/HelloWorld.vue b/src/chongming-web/src/components/HelloWorld.vue
deleted file mode 100644
index d174cf8..0000000
--- a/src/chongming-web/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
{{ msg }}
-
- You’ve successfully created a project with
- Vite +
- Vue 3. What's next?
-
-
-
-
-
diff --git a/src/chongming-web/src/components/TheWelcome.vue b/src/chongming-web/src/components/TheWelcome.vue
deleted file mode 100644
index 8b731d9..0000000
--- a/src/chongming-web/src/components/TheWelcome.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
-
-
- Documentation
-
- Vue’s
- official documentation
- provides you with all information you need to get started.
-
-
-
-
-
-
- Tooling
-
- This project is served and bundled with
- Vite. The
- recommended IDE setup is
- VSCode
- +
- Vue - Official. If you need to test your components and web pages, check out
- Vitest
- and
- Cypress
- /
- Playwright.
-
-
-
- More instructions are available in
- README.md.
-
-
-
-
-
-
- Ecosystem
-
- Get official tools and libraries for your project:
- Pinia,
- Vue Router,
- Vue Test Utils, and
- Vue Dev Tools. If
- you need more resources, we suggest paying
- Awesome Vue
- a visit.
-
-
-
-
-
-
- Community
-
- Got stuck? Ask your question on
- Vue Land
- (our official Discord server), or
- StackOverflow. You should also follow the official
- @vuejs.org
- Bluesky account or the
- @vuejs
- X account for latest news in the Vue world.
-
-
-
-
-
-
- Support Vue
-
- As an independent project, Vue relies on community backing for its sustainability. You can help
- us by
- becoming a sponsor.
-
-
diff --git a/src/chongming-web/src/components/WelcomeItem.vue b/src/chongming-web/src/components/WelcomeItem.vue
deleted file mode 100644
index 6d7086a..0000000
--- a/src/chongming-web/src/components/WelcomeItem.vue
+++ /dev/null
@@ -1,87 +0,0 @@
-
-