diff --git a/front/.gitignore b/front/.gitignore index a547bf3..3b0b403 100644 --- a/front/.gitignore +++ b/front/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +.env \ No newline at end of file diff --git a/front/src/core/api/Api.ts b/front/src/core/api/Api.ts new file mode 100644 index 0000000..ab58717 --- /dev/null +++ b/front/src/core/api/Api.ts @@ -0,0 +1,460 @@ +/* eslint-disable */ +/* tslint:disable */ +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +import { + ChangeRecordDto, + ChangeRecordViewModel, + SpendingGroupDto, + SpendingGroupViewModel, + SpendingPlanDto, + SpendingPlanViewModel, + UserDto, + UserLoginDTO, + UserViewModel, +} from "./data-contracts"; +import { ContentType, HttpClient, RequestParams } from "./http-client"; + +export class Api extends HttpClient { + /** + * No description + * + * @tags Auth + * @name AuthCreate + * @request POST:/api/Auth + * @response `200` `UserViewModel` Success + */ + authCreate = (data: UserLoginDTO, params: RequestParams = {}) => + this.request({ + path: `/api/Auth`, + method: "POST", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags Auth + * @name AuthRegisterCreate + * @request POST:/api/Auth/register + * @response `200` `UserViewModel` Success + */ + authRegisterCreate = (data: UserDto, params: RequestParams = {}) => + this.request({ + path: `/api/Auth/register`, + method: "POST", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags ChangeRecord + * @name ChangeRecordCreate + * @request POST:/api/ChangeRecord + * @response `200` `ChangeRecordViewModel` Success + */ + changeRecordCreate = (data: ChangeRecordDto, params: RequestParams = {}) => + this.request({ + path: `/api/ChangeRecord`, + method: "POST", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags ChangeRecord + * @name ChangeRecordList + * @request GET:/api/ChangeRecord + * @response `200` `(ChangeRecordViewModel)[]` Success + */ + changeRecordList = (params: RequestParams = {}) => + this.request({ + path: `/api/ChangeRecord`, + method: "GET", + format: "json", + ...params, + }); + /** + * No description + * + * @tags ChangeRecord + * @name ChangeRecordPartialUpdate + * @request PATCH:/api/ChangeRecord + * @response `200` `ChangeRecordViewModel` Success + */ + changeRecordPartialUpdate = (data: ChangeRecordDto, params: RequestParams = {}) => + this.request({ + path: `/api/ChangeRecord`, + method: "PATCH", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags ChangeRecord + * @name ChangeRecordDelete + * @request DELETE:/api/ChangeRecord + * @response `200` `void` Success + */ + changeRecordDelete = ( + query?: { + /** @format uuid */ + Id?: string; + /** @format uuid */ + SpendingGroupId?: string; + /** @format date-time */ + From?: string; + /** @format date-time */ + To?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/ChangeRecord`, + method: "DELETE", + query: query, + ...params, + }); + /** + * No description + * + * @tags ChangeRecord + * @name ChangeRecordFilterList + * @request GET:/api/ChangeRecord/filter + * @response `200` `(ChangeRecordViewModel)[]` Success + */ + changeRecordFilterList = ( + query?: { + /** @format uuid */ + Id?: string; + /** @format uuid */ + SpendingGroupId?: string; + /** @format date-time */ + From?: string; + /** @format date-time */ + To?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/ChangeRecord/filter`, + method: "GET", + query: query, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingGroup + * @name SpendingGroupDetail + * @request GET:/api/SpendingGroup/{id} + * @response `200` `SpendingGroupViewModel` Success + */ + spendingGroupDetail = ( + id: string, + query?: { + /** @format uuid */ + Id?: string; + Name?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/SpendingGroup/${id}`, + method: "GET", + query: query, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingGroup + * @name SpendingGroupList + * @request GET:/api/SpendingGroup + * @response `200` `(SpendingGroupViewModel)[]` Success + */ + spendingGroupList = (params: RequestParams = {}) => + this.request({ + path: `/api/SpendingGroup`, + method: "GET", + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingGroup + * @name SpendingGroupCreate + * @request POST:/api/SpendingGroup + * @response `200` `SpendingGroupViewModel` Success + */ + spendingGroupCreate = (data: SpendingGroupDto, params: RequestParams = {}) => + this.request({ + path: `/api/SpendingGroup`, + method: "POST", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingGroup + * @name SpendingGroupPartialUpdate + * @request PATCH:/api/SpendingGroup + * @response `200` `SpendingGroupViewModel` Success + */ + spendingGroupPartialUpdate = (data: SpendingGroupDto, params: RequestParams = {}) => + this.request({ + path: `/api/SpendingGroup`, + method: "PATCH", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingGroup + * @name SpendingGroupDelete + * @request DELETE:/api/SpendingGroup + * @response `200` `void` Success + */ + spendingGroupDelete = ( + query?: { + /** @format uuid */ + Id?: string; + Name?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/SpendingGroup`, + method: "DELETE", + query: query, + ...params, + }); + /** + * No description + * + * @tags SpendingGroup + * @name SpendingGroupFilterList + * @request GET:/api/SpendingGroup/filter + * @response `200` `(SpendingGroupViewModel)[]` Success + */ + spendingGroupFilterList = ( + query?: { + /** @format uuid */ + Id?: string; + Name?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/SpendingGroup/filter`, + method: "GET", + query: query, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingPlan + * @name SpendingPlanDetail + * @request GET:/api/SpendingPlan/{id} + * @response `200` `SpendingPlanViewModel` Success + */ + spendingPlanDetail = ( + id: string, + query?: { + /** @format uuid */ + Id?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/SpendingPlan/${id}`, + method: "GET", + query: query, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingPlan + * @name SpendingPlanList + * @request GET:/api/SpendingPlan + * @response `200` `(SpendingPlanViewModel)[]` Success + */ + spendingPlanList = (params: RequestParams = {}) => + this.request({ + path: `/api/SpendingPlan`, + method: "GET", + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingPlan + * @name SpendingPlanCreate + * @request POST:/api/SpendingPlan + * @response `200` `SpendingPlanViewModel` Success + */ + spendingPlanCreate = (data: SpendingPlanDto, params: RequestParams = {}) => + this.request({ + path: `/api/SpendingPlan`, + method: "POST", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingPlan + * @name SpendingPlanPartialUpdate + * @request PATCH:/api/SpendingPlan + * @response `200` `SpendingPlanViewModel` Success + */ + spendingPlanPartialUpdate = (data: SpendingPlanDto, params: RequestParams = {}) => + this.request({ + path: `/api/SpendingPlan`, + method: "PATCH", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags SpendingPlan + * @name SpendingPlanDelete + * @request DELETE:/api/SpendingPlan + * @response `200` `void` Success + */ + spendingPlanDelete = ( + query?: { + /** @format uuid */ + Id?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/SpendingPlan`, + method: "DELETE", + query: query, + ...params, + }); + /** + * No description + * + * @tags SpendingPlan + * @name SpendingPlanFilterList + * @request GET:/api/SpendingPlan/filter + * @response `200` `(SpendingPlanViewModel)[]` Success + */ + spendingPlanFilterList = ( + query?: { + /** @format uuid */ + Id?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/SpendingPlan/filter`, + method: "GET", + query: query, + format: "json", + ...params, + }); + /** + * No description + * + * @tags User + * @name UserList + * @request GET:/api/User + * @response `200` `UserViewModel` Success + */ + userList = ( + query?: { + /** @format uuid */ + Id?: string; + Name?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/User`, + method: "GET", + query: query, + format: "json", + ...params, + }); + /** + * No description + * + * @tags User + * @name UserPartialUpdate + * @request PATCH:/api/User + * @response `200` `UserViewModel` Success + */ + userPartialUpdate = (data: UserDto, params: RequestParams = {}) => + this.request({ + path: `/api/User`, + method: "PATCH", + body: data, + type: ContentType.Json, + format: "json", + ...params, + }); + /** + * No description + * + * @tags User + * @name UserDelete + * @request DELETE:/api/User + * @response `200` `UserViewModel` Success + */ + userDelete = ( + query?: { + /** @format uuid */ + Id?: string; + Name?: string; + }, + params: RequestParams = {}, + ) => + this.request({ + path: `/api/User`, + method: "DELETE", + query: query, + format: "json", + ...params, + }); +} diff --git a/front/src/core/api/data-contracts.ts b/front/src/core/api/data-contracts.ts new file mode 100644 index 0000000..1788da0 --- /dev/null +++ b/front/src/core/api/data-contracts.ts @@ -0,0 +1,96 @@ +/* eslint-disable */ +/* tslint:disable */ +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +export interface ChangeRecordDto { + /** @format uuid */ + id?: string; + /** @format uuid */ + userId?: string; + /** @format uuid */ + spendingGroupId?: string | null; + /** @format double */ + sum?: number; + /** @format date-time */ + changedAt?: string; +} + +export interface ChangeRecordViewModel { + /** @format uuid */ + id?: string; + /** @format double */ + sum?: number; + /** @format date-time */ + changedAt?: string; +} + +export interface SpendingGroupDto { + /** @format uuid */ + id?: string; + name?: string | null; + /** @format uuid */ + userId?: string; + changeRecords?: ChangeRecordDto[] | null; + spendingPlans?: SpendingPlanDto[] | null; +} + +export interface SpendingGroupViewModel { + /** @format uuid */ + id?: string; + name?: string | null; + changeRecords?: ChangeRecordViewModel[] | null; + spendingPlans?: SpendingPlanViewModel[] | null; +} + +export interface SpendingPlanDto { + /** @format uuid */ + id?: string; + /** @format uuid */ + spendingGroupId?: string; + /** @format double */ + sum?: number; + /** @format date-time */ + startAt?: string; + /** @format date-time */ + endAt?: string; +} + +export interface SpendingPlanViewModel { + /** @format uuid */ + id?: string; + /** @format date-time */ + startAt?: string; + /** @format date-time */ + endAt?: string; + /** @format double */ + sum?: number; +} + +export interface UserDto { + /** @format uuid */ + id?: string; + name?: string | null; + password?: string | null; + /** @format double */ + balance?: number; +} + +export interface UserLoginDTO { + name?: string | null; + password?: string | null; +} + +export interface UserViewModel { + /** @format uuid */ + id?: string; + name?: string | null; + /** @format double */ + balance?: number; +} diff --git a/front/src/core/api/http-client.ts b/front/src/core/api/http-client.ts new file mode 100644 index 0000000..db03d42 --- /dev/null +++ b/front/src/core/api/http-client.ts @@ -0,0 +1,220 @@ +/* eslint-disable */ +/* tslint:disable */ +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +export type QueryParamsType = Record; +export type ResponseFormat = keyof Omit; + +export interface FullRequestParams extends Omit { + /** set parameter to `true` for call `securityWorker` for this request */ + secure?: boolean; + /** request path */ + path: string; + /** content type of request body */ + type?: ContentType; + /** query params */ + query?: QueryParamsType; + /** format of response (i.e. response.json() -> format: "json") */ + format?: ResponseFormat; + /** request body */ + body?: unknown; + /** base url */ + baseUrl?: string; + /** request cancellation token */ + cancelToken?: CancelToken; +} + +export type RequestParams = Omit; + +export interface ApiConfig { + baseUrl?: string; + baseApiParams?: Omit; + securityWorker?: (securityData: SecurityDataType | null) => Promise | RequestParams | void; + customFetch?: typeof fetch; +} + +export interface HttpResponse extends Response { + data: D; + error: E; +} + +type CancelToken = Symbol | string | number; + +export enum ContentType { + Json = "application/json", + FormData = "multipart/form-data", + UrlEncoded = "application/x-www-form-urlencoded", + Text = "text/plain", +} + +export class HttpClient { + public baseUrl: string = ""; + private securityData: SecurityDataType | null = null; + private securityWorker?: ApiConfig["securityWorker"]; + private abortControllers = new Map(); + private customFetch = (...fetchParams: Parameters) => fetch(...fetchParams); + + private baseApiParams: RequestParams = { + credentials: "same-origin", + headers: {}, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + + constructor(apiConfig: ApiConfig = {}) { + Object.assign(this, apiConfig); + } + + public setSecurityData = (data: SecurityDataType | null) => { + this.securityData = data; + }; + + protected encodeQueryParam(key: string, value: any) { + const encodedKey = encodeURIComponent(key); + return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`; + } + + protected addQueryParam(query: QueryParamsType, key: string) { + return this.encodeQueryParam(key, query[key]); + } + + protected addArrayQueryParam(query: QueryParamsType, key: string) { + const value = query[key]; + return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); + } + + protected toQueryString(rawQuery?: QueryParamsType): string { + const query = rawQuery || {}; + const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]); + return keys + .map((key) => (Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key))) + .join("&"); + } + + protected addQueryParams(rawQuery?: QueryParamsType): string { + const queryString = this.toQueryString(rawQuery); + return queryString ? `?${queryString}` : ""; + } + + private contentFormatters: Record any> = { + [ContentType.Json]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input, + [ContentType.Text]: (input: any) => (input !== null && typeof input !== "string" ? JSON.stringify(input) : input), + [ContentType.FormData]: (input: any) => + Object.keys(input || {}).reduce((formData, key) => { + const property = input[key]; + formData.append( + key, + property instanceof Blob + ? property + : typeof property === "object" && property !== null + ? JSON.stringify(property) + : `${property}`, + ); + return formData; + }, new FormData()), + [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), + }; + + protected mergeRequestParams(params1: RequestParams, params2?: RequestParams): RequestParams { + return { + ...this.baseApiParams, + ...params1, + ...(params2 || {}), + headers: { + ...(this.baseApiParams.headers || {}), + ...(params1.headers || {}), + ...((params2 && params2.headers) || {}), + }, + }; + } + + protected createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => { + if (this.abortControllers.has(cancelToken)) { + const abortController = this.abortControllers.get(cancelToken); + if (abortController) { + return abortController.signal; + } + return void 0; + } + + const abortController = new AbortController(); + this.abortControllers.set(cancelToken, abortController); + return abortController.signal; + }; + + public abortRequest = (cancelToken: CancelToken) => { + const abortController = this.abortControllers.get(cancelToken); + + if (abortController) { + abortController.abort(); + this.abortControllers.delete(cancelToken); + } + }; + + public request = async ({ + body, + secure, + path, + type, + query, + format, + baseUrl, + cancelToken, + ...params + }: FullRequestParams): Promise> => { + const secureParams = + ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && + this.securityWorker && + (await this.securityWorker(this.securityData))) || + {}; + const requestParams = this.mergeRequestParams(params, secureParams); + const queryString = query && this.toQueryString(query); + const payloadFormatter = this.contentFormatters[type || ContentType.Json]; + const responseFormat = format || requestParams.format; + + return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, { + ...requestParams, + headers: { + ...(requestParams.headers || {}), + ...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}), + }, + signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null, + body: typeof body === "undefined" || body === null ? null : payloadFormatter(body), + }).then(async (response) => { + const r = response.clone() as HttpResponse; + r.data = null as unknown as T; + r.error = null as unknown as E; + + const data = !responseFormat + ? r + : await response[responseFormat]() + .then((data) => { + if (r.ok) { + r.data = data; + } else { + r.error = data; + } + return r; + }) + .catch((e) => { + r.error = e; + return r; + }); + + if (cancelToken) { + this.abortControllers.delete(cancelToken); + } + + if (!response.ok) throw data; + return data; + }); + }; +}