Refactor TypeScript RPC codebase and API structure
- Simplified error handling in `getFieldInfo` and `getFieldTsInfo` functions. - Removed unused `getSourceInfo` function and its references. - Updated `getStruct` method in `TSStruct` to eliminate source info retrieval. - Cleaned up `TSSouces` population logic by commenting out unnecessary debug statements. - Adjusted TypeScript source generation to use type imports instead of default imports. - Consolidated API endpoints into dedicated files for better organization (admin, systemUtils, users). - Introduced new types for API responses and requests to enhance type safety. - Removed redundant code and comments from generated API files. - Updated frontend components to reflect new API structure and types. - Ensured consistent naming conventions and type usage across the codebase.
This commit is contained in:
parent
3461395eb3
commit
b260daffed
|
|
@ -1,9 +1,10 @@
|
||||||
import { api } from "./api.ts";
|
import { api } from "./api";
|
||||||
import { Nullable } from "./apiTypes.ts";
|
import type { Nullable } from "./apiTypes.ts";
|
||||||
import * as users from "./users.ts";
|
import type * as users from "./users.ts";
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=admin.ListUsersRequest; response=users.[]User
|
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=admin.ListUsersRequest; response=users.[]User
|
||||||
// internal/admin/routes.go Line: 12
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/admin/routes.go Line: 13
|
||||||
export const listUsers = async (
|
export const listUsers = async (
|
||||||
data: ListUsersRequest,
|
data: ListUsersRequest,
|
||||||
): Promise<{ data: users.User[]; error: Nullable<string> }> => {
|
): Promise<{ data: users.User[]; error: Nullable<string> }> => {
|
||||||
|
|
@ -14,7 +15,8 @@ export const listUsers = async (
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/admin/users/:uuid/block; name=blockUser; method=PUT; request=admin.BlockUserRequest; response=users.User
|
// Typescript: TSEndpoint= path=/admin/users/:uuid/block; name=blockUser; method=PUT; request=admin.BlockUserRequest; response=users.User
|
||||||
// internal/admin/routes.go Line: 16
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/admin/routes.go Line: 17
|
||||||
export const blockUser = async (
|
export const blockUser = async (
|
||||||
data: BlockUserRequest,
|
data: BlockUserRequest,
|
||||||
): Promise<{ data: users.User; error: Nullable<string> }> => {
|
): Promise<{ data: users.User; error: Nullable<string> }> => {
|
||||||
|
|
@ -24,11 +26,11 @@ export const blockUser = async (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface BlockUserRequest {
|
|
||||||
action: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ListUsersRequest {
|
export interface ListUsersRequest {
|
||||||
page: number;
|
page: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BlockUserRequest {
|
||||||
|
action: string;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
// This file was generated by github.com/millevolte/ts-rpc
|
// This file was generated by github.com/millevolte/ts-rpc
|
||||||
//
|
//
|
||||||
// Apr 14, 2026 21:39:07 UTC
|
// Apr 26, 2026 14:23:26 UTC
|
||||||
//
|
//
|
||||||
|
|
||||||
export interface ApiRestResponse {
|
export interface ApiRestResponse {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// API Declarations
|
// API Declarations
|
||||||
export type Nullable<T> = T | null;
|
|
||||||
|
|
||||||
export type Record<K extends string | number | symbol, T> = { [P in K]: T };
|
export type Record<K extends string | number | symbol, T> = { [P in K]: T };
|
||||||
|
|
||||||
|
export type Nullable<T> = T | null;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,22 @@
|
||||||
import { api } from "./api.ts";
|
import { api } from "./api";
|
||||||
import { Nullable } from "./apiTypes.ts";
|
import type { Nullable } from "./apiTypes.ts";
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/health; name=health; method=GET; response=string
|
||||||
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/systemUtils/routes.go Line: 39
|
||||||
|
export const health = async (): Promise<{
|
||||||
|
data: string;
|
||||||
|
error: Nullable<string>;
|
||||||
|
}> => {
|
||||||
|
return (await api.GET("/health")) as {
|
||||||
|
data: string;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET; response=string
|
// Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET; response=string
|
||||||
// internal/systemUtils/routes.go Line: 41
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/systemUtils/routes.go Line: 42
|
||||||
export const metrics = async (): Promise<{
|
export const metrics = async (): Promise<{
|
||||||
data: string;
|
data: string;
|
||||||
error: Nullable<string>;
|
error: Nullable<string>;
|
||||||
|
|
@ -14,7 +28,8 @@ export const metrics = async (): Promise<{
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/maildebug; name=mailDebug; method=GET; response=[]MailDebugItem
|
// Typescript: TSEndpoint= path=/maildebug; name=mailDebug; method=GET; response=[]MailDebugItem
|
||||||
// internal/systemUtils/routes.go Line: 53
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/systemUtils/routes.go Line: 54
|
||||||
export const mailDebug = async (): Promise<{
|
export const mailDebug = async (): Promise<{
|
||||||
data: MailDebugItem[];
|
data: MailDebugItem[];
|
||||||
error: Nullable<string>;
|
error: Nullable<string>;
|
||||||
|
|
@ -25,18 +40,6 @@ export const mailDebug = async (): Promise<{
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/health; name=health; method=GET; response=string
|
|
||||||
// internal/systemUtils/routes.go Line: 38
|
|
||||||
export const health = async (): Promise<{
|
|
||||||
data: string;
|
|
||||||
error: Nullable<string>;
|
|
||||||
}> => {
|
|
||||||
return (await api.GET("/health")) as {
|
|
||||||
data: string;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface MailDebugItem {
|
export interface MailDebugItem {
|
||||||
name: string;
|
name: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { api } from "./api.ts";
|
import { api } from "./api";
|
||||||
import { Nullable } from "./apiTypes.ts";
|
import type { Nullable } from "./apiTypes.ts";
|
||||||
import * as responses from "./responses.ts";
|
import type * as responses from "./responses.ts";
|
||||||
import * as tokens from "./tokens.ts";
|
import type * as tokens from "./tokens.ts";
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair
|
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair
|
||||||
// internal/user/routes.go Line: 46
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 47
|
||||||
export const refresh = async (
|
export const refresh = async (
|
||||||
data: RefreshRequest,
|
data: RefreshRequest,
|
||||||
): Promise<{ data: tokens.TokenPair; error: Nullable<string> }> => {
|
): Promise<{ data: tokens.TokenPair; error: Nullable<string> }> => {
|
||||||
|
|
@ -14,61 +15,9 @@ export const refresh = async (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST; request=users.ResetPasswordRequest; response=responses.SimpleResponse
|
|
||||||
// internal/user/routes.go Line: 55
|
|
||||||
export const resetPassword = async (
|
|
||||||
data: ResetPasswordRequest,
|
|
||||||
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/password/reset", data)) as {
|
|
||||||
data: responses.SimpleResponse;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=users.User
|
|
||||||
// internal/user/routes.go Line: 27
|
|
||||||
export const getUser = async (
|
|
||||||
uuid: string,
|
|
||||||
): Promise<{ data: User; error: Nullable<string> }> => {
|
|
||||||
return (await api.GET(`/users/${uuid}`)) as {
|
|
||||||
data: User;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/me; name=me; method=GET; response=users.User
|
|
||||||
// internal/user/routes.go Line: 39
|
|
||||||
export const me = async (): Promise<{
|
|
||||||
data: User;
|
|
||||||
error: Nullable<string>;
|
|
||||||
}> => {
|
|
||||||
return (await api.GET("/auth/me")) as { data: User; error: Nullable<string> };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=users.UserCreateInput; response=users.User
|
|
||||||
// internal/user/routes.go Line: 49
|
|
||||||
export const register = async (
|
|
||||||
data: UserCreateInput,
|
|
||||||
): Promise<{ data: User; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/register", data)) as {
|
|
||||||
data: User;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=users.ForgotPasswordRequest; response=responses.SimpleResponse
|
|
||||||
// internal/user/routes.go Line: 52
|
|
||||||
export const forgotPassword = async (
|
|
||||||
data: ForgotPasswordRequest,
|
|
||||||
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/password/forgot", data)) as {
|
|
||||||
data: responses.SimpleResponse;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User
|
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User
|
||||||
// internal/user/routes.go Line: 33
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 34
|
||||||
export const updateUser = async (
|
export const updateUser = async (
|
||||||
data: UpdateUserRequest,
|
data: UpdateUserRequest,
|
||||||
): Promise<{ data: User; error: Nullable<string> }> => {
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
|
@ -78,30 +27,43 @@ export const updateUser = async (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=deleteUser; method=DELETE; response=responses.SimpleResponse
|
// Typescript: TSEndpoint= path=/auth/me; name=me; method=GET; response=users.User
|
||||||
// internal/user/routes.go Line: 36
|
|
||||||
export const deleteUser = async (
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 40
|
||||||
uuid: string,
|
export const me = async (): Promise<{
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
}> => {
|
||||||
|
return (await api.GET("/auth/me")) as { data: User; error: Nullable<string> };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=users.ForgotPasswordRequest; response=responses.SimpleResponse
|
||||||
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 53
|
||||||
|
export const forgotPassword = async (
|
||||||
|
data: ForgotPasswordRequest,
|
||||||
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
return (await api.DELETE(`/users/${uuid}`)) as {
|
return (await api.POST("/auth/password/forgot", data)) as {
|
||||||
data: responses.SimpleResponse;
|
data: responses.SimpleResponse;
|
||||||
error: Nullable<string>;
|
error: Nullable<string>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/login; name=login; method=POST; request=users.LoginRequest; response=tokens.TokenPair
|
// Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST; request=users.ResetPasswordRequest; response=responses.SimpleResponse
|
||||||
// internal/user/routes.go Line: 43
|
|
||||||
export const login = async (
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 56
|
||||||
data: LoginRequest,
|
export const resetPassword = async (
|
||||||
): Promise<{ data: tokens.TokenPair; error: Nullable<string> }> => {
|
data: ResetPasswordRequest,
|
||||||
return (await api.POST("/auth/login", data)) as {
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
data: tokens.TokenPair;
|
return (await api.POST("/auth/password/reset", data)) as {
|
||||||
|
data: responses.SimpleResponse;
|
||||||
error: Nullable<string>;
|
error: Nullable<string>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/valid; name=validToken; method=POST; request=string; response=responses.SimpleResponse
|
// Typescript: TSEndpoint= path=/auth/password/valid; name=validToken; method=POST; request=string; response=responses.SimpleResponse
|
||||||
// internal/user/routes.go Line: 58
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 59
|
||||||
export const validToken = async (
|
export const validToken = async (
|
||||||
data: string,
|
data: string,
|
||||||
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
|
|
@ -111,10 +73,47 @@ export const validToken = async (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=users.UserCreateInput; response=users.User
|
// Typescript: TSEndpoint= path=/users/:uuid; name=deleteUser; method=DELETE; response=responses.SimpleResponse
|
||||||
// internal/user/routes.go Line: 30
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 37
|
||||||
|
export const deleteUser = async (
|
||||||
|
uuid: string,
|
||||||
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
|
return (await api.DELETE(`/users/${uuid}`)) as {
|
||||||
|
data: responses.SimpleResponse;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=users.User
|
||||||
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 28
|
||||||
|
export const getUser = async (
|
||||||
|
uuid: string,
|
||||||
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
return (await api.GET(`/users/${uuid}`)) as {
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=users.UserCreateRequest; response=users.User
|
||||||
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 50
|
||||||
|
export const register = async (
|
||||||
|
data: UserCreateRequest,
|
||||||
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/register", data)) as {
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=users.UserCreateRequest; response=users.User
|
||||||
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 31
|
||||||
export const createUser = async (
|
export const createUser = async (
|
||||||
data: UserCreateInput,
|
data: UserCreateRequest,
|
||||||
): Promise<{ data: User; error: Nullable<string> }> => {
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
return (await api.POST("/users", data)) as {
|
return (await api.POST("/users", data)) as {
|
||||||
data: User;
|
data: User;
|
||||||
|
|
@ -122,8 +121,28 @@ export const createUser = async (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface RefreshRequest {
|
// Typescript: TSEndpoint= path=/auth/login; name=login; method=POST; request=users.LoginRequest; response=tokens.TokenPair
|
||||||
refresh_token: string;
|
|
||||||
|
// /Users/fabio/CODE/omnimed/go-quasar-partial-ssr/backend/internal/user/routes.go Line: 44
|
||||||
|
export const login = async (
|
||||||
|
data: LoginRequest,
|
||||||
|
): Promise<{ data: tokens.TokenPair; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/login", data)) as {
|
||||||
|
data: tokens.TokenPair;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface UpdateUserRequest {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
roles: UserRoles;
|
||||||
|
status: UserStatus;
|
||||||
|
types: UserTypes;
|
||||||
|
avatar: Nullable<string>;
|
||||||
|
details: Nullable<UserDetails>;
|
||||||
|
preferences: Nullable<UserPreferences>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
|
|
@ -142,16 +161,13 @@ export interface User {
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserCreateInput {
|
export interface ForgotPasswordRequest {
|
||||||
name: string;
|
|
||||||
email: string;
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResetPasswordRequest {
|
||||||
|
token: string;
|
||||||
password: string;
|
password: string;
|
||||||
roles: UserRoles;
|
|
||||||
status: UserStatus;
|
|
||||||
types: UserTypes;
|
|
||||||
avatar: Nullable<string>;
|
|
||||||
details: Nullable<UserDetails>;
|
|
||||||
preferences: Nullable<UserPreferences>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserPreferences {
|
export interface UserPreferences {
|
||||||
|
|
@ -169,11 +185,7 @@ export interface UserPreferences {
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ForgotPasswordRequest {
|
export interface UserCreateRequest {
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateUserRequest {
|
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
|
@ -201,37 +213,20 @@ export interface UserDetails {
|
||||||
zipCode: string;
|
zipCode: string;
|
||||||
country: string;
|
country: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
createdAt: Date;
|
createdAt: Nullable<Date>;
|
||||||
updatedAt: Date;
|
updatedAt: Nullable<Date>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserProfile {
|
export interface RefreshRequest {
|
||||||
id: number;
|
refresh_token: string;
|
||||||
email: string;
|
|
||||||
name: string;
|
|
||||||
roles: UserRoles;
|
|
||||||
types: UserTypes;
|
|
||||||
status: UserStatus;
|
|
||||||
activatedAt: Date;
|
|
||||||
uuid: string;
|
|
||||||
details: Nullable<UserDetails>;
|
|
||||||
preferences: Nullable<UserPreferences>;
|
|
||||||
avatar: Nullable<string>;
|
|
||||||
createdAt: Date;
|
|
||||||
updatedAt: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ResetPasswordRequest {
|
|
||||||
token: string;
|
|
||||||
password: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserRoles = string[];
|
export type UserRoles = string[];
|
||||||
|
|
||||||
export type UserTypes = string[];
|
|
||||||
|
|
||||||
export type UserStatus = (typeof EnumUserStatus)[keyof typeof EnumUserStatus];
|
export type UserStatus = (typeof EnumUserStatus)[keyof typeof EnumUserStatus];
|
||||||
|
|
||||||
|
export type UserTypes = string[];
|
||||||
|
|
||||||
export const EnumUserStatus = {
|
export const EnumUserStatus = {
|
||||||
UserStatusPending: "pending",
|
UserStatusPending: "pending",
|
||||||
UserStatusActive: "active",
|
UserStatusActive: "active",
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ require (
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
golang.org/x/crypto v0.48.0
|
golang.org/x/crypto v0.50.0
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
gorm.io/driver/sqlite v1.6.0
|
gorm.io/driver/sqlite v1.6.0
|
||||||
gorm.io/gorm v1.31.1
|
gorm.io/gorm v1.31.1
|
||||||
|
|
@ -45,9 +45,11 @@ require (
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.69.0 // indirect
|
github.com/valyala/fasthttp v1.69.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||||
golang.org/x/net v0.50.0 // indirect
|
golang.org/x/mod v0.35.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/net v0.53.0 // indirect
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
golang.org/x/sync v0.20.0 // indirect
|
||||||
golang.org/x/text v0.34.0 // indirect
|
golang.org/x/sys v0.43.0 // indirect
|
||||||
|
golang.org/x/text v0.36.0 // indirect
|
||||||
|
golang.org/x/tools v0.44.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.8 // indirect
|
google.golang.org/protobuf v1.36.8 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -101,15 +101,29 @@ go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
|
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||||
|
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||||
|
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||||
|
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
||||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
|
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||||
|
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
|
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||||
|
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
|
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||||
|
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||||
|
golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
|
||||||
|
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
|
||||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,8 @@ func (ac *AdminController) BlockUser(c fiber.Ctx) error {
|
||||||
default:
|
default:
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "invalid action")
|
return fiber.NewError(fiber.StatusBadRequest, "invalid action")
|
||||||
}
|
}
|
||||||
u.UpdatedAt = time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
|
u.UpdatedAt = &now
|
||||||
|
|
||||||
if err := db.Save(&u).Error; err != nil {
|
if err := db.Save(&u).Error; err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "failed to update user status")
|
return fiber.NewError(fiber.StatusInternalServerError, "failed to update user status")
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ func SeedUsers(db *gorm.DB, n int) ([]users.User, []Credential, error) {
|
||||||
Language: gofakeit.Language(),
|
Language: gofakeit.Language(),
|
||||||
},
|
},
|
||||||
Avatar: nil,
|
Avatar: nil,
|
||||||
CreatedAt: now,
|
CreatedAt: &now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: &now,
|
||||||
ActivatedAt: func() *time.Time {
|
ActivatedAt: func() *time.Time {
|
||||||
ts := now
|
ts := now
|
||||||
return &ts
|
return &ts
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,6 @@ func NewUserController(tockenService *tokens.TockenService) *UserController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type UpdateUserRequest struct {
|
|
||||||
Name string `json:"name" validate:"required,min=1,max=255"`
|
|
||||||
Email string `json:"email" validate:"required,email"`
|
|
||||||
Password string `json:"password" validate:"omitempty,min=8,max=128"`
|
|
||||||
Roles UserRoles `json:"roles"`
|
|
||||||
Status UserStatus `json:"status"`
|
|
||||||
Types UserTypes `json:"types"`
|
|
||||||
Avatar *string `json:"avatar"`
|
|
||||||
Details *UserDetails `json:"details"`
|
|
||||||
Preferences *UserPreferences `json:"preferences"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUser returns a single user by UUID.
|
// GetUser returns a single user by UUID.
|
||||||
func (uc *UserController) GetUser(c fiber.Ctx) error {
|
func (uc *UserController) GetUser(c fiber.Ctx) error {
|
||||||
user, err := loadUserByUUID(c)
|
user, err := loadUserByUUID(c)
|
||||||
|
|
@ -55,7 +42,7 @@ func (uc *UserController) GetUser(c fiber.Ctx) error {
|
||||||
|
|
||||||
// CreateUser creates a user together with optional details and preferences.
|
// CreateUser creates a user together with optional details and preferences.
|
||||||
func (uc *UserController) CreateUser(c fiber.Ctx) error {
|
func (uc *UserController) CreateUser(c fiber.Ctx) error {
|
||||||
var req UserCreateInput
|
var req UserCreateRequest
|
||||||
if err := c.Bind().Body(&req); err != nil {
|
if err := c.Bind().Body(&req); err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
|
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
|
||||||
}
|
}
|
||||||
|
|
@ -107,8 +94,8 @@ func (uc *UserController) CreateUser(c fiber.Ctx) error {
|
||||||
UUID: uuid.NewString(),
|
UUID: uuid.NewString(),
|
||||||
Details: req.Details,
|
Details: req.Details,
|
||||||
Preferences: req.Preferences,
|
Preferences: req.Preferences,
|
||||||
CreatedAt: now,
|
CreatedAt: &now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: &now,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Create(&user).Error; err != nil {
|
if err := db.Create(&user).Error; err != nil {
|
||||||
|
|
@ -155,7 +142,7 @@ func (uc *UserController) UpdateUser(c fiber.Ctx) error {
|
||||||
user.Name = req.Name
|
user.Name = req.Name
|
||||||
user.Email = req.Email
|
user.Email = req.Email
|
||||||
user.Avatar = req.Avatar
|
user.Avatar = req.Avatar
|
||||||
user.UpdatedAt = now
|
user.UpdatedAt = &now
|
||||||
if req.Status != "" {
|
if req.Status != "" {
|
||||||
user.Status = req.Status
|
user.Status = req.Status
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +264,7 @@ func (uc *UserController) Login(c fiber.Ctx) error {
|
||||||
|
|
||||||
// Register creates a new user with optional roles/types/preferences.
|
// Register creates a new user with optional roles/types/preferences.
|
||||||
func (uc *UserController) Register(c fiber.Ctx) error {
|
func (uc *UserController) Register(c fiber.Ctx) error {
|
||||||
var req UserCreateInput
|
var req UserCreateRequest
|
||||||
if err := c.Bind().Body(&req); err != nil {
|
if err := c.Bind().Body(&req); err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
|
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
|
||||||
}
|
}
|
||||||
|
|
@ -342,8 +329,8 @@ func (uc *UserController) Register(c fiber.Ctx) error {
|
||||||
Language: req.Preferences.Language,
|
Language: req.Preferences.Language,
|
||||||
}
|
}
|
||||||
}(),
|
}(),
|
||||||
CreatedAt: now,
|
CreatedAt: &now,
|
||||||
UpdatedAt: now,
|
UpdatedAt: &now,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Create(&user).Error; err != nil {
|
if err := db.Create(&user).Error; err != nil {
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserRoles is stored as JSON array of strings.
|
// UserRoles is stored as JSON array of strings.
|
||||||
|
|
||||||
// Typescript: type
|
|
||||||
type UserRoles []string
|
type UserRoles []string
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `json:"id" gorm:"primaryKey"`
|
ID int `json:"id" gorm:"primaryKey"`
|
||||||
Email string `json:"email" gorm:"uniqueIndex;size:255"`
|
Email string `json:"email" gorm:"uniqueIndex;size:255"`
|
||||||
|
|
@ -25,32 +22,15 @@ type User struct {
|
||||||
Details *UserDetails `json:"details" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
|
Details *UserDetails `json:"details" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
|
||||||
Preferences *UserPreferences `json:"preferences" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
|
Preferences *UserPreferences `json:"preferences" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
|
||||||
Avatar *string `json:"avatar" gorm:"size:512"`
|
Avatar *string `json:"avatar" gorm:"size:512"`
|
||||||
CreatedAt time.Time `json:"createdAt" ts:"type=Date"`
|
CreatedAt *time.Time `json:"createdAt" ts:"type=Date"`
|
||||||
UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"`
|
UpdatedAt *time.Time `json:"updatedAt" ts:"type=Date"`
|
||||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index" ts:"type=Date"`
|
DeletedAt *gorm.DeletedAt `json:"-" gorm:"index" ts:"type=Date"`
|
||||||
}
|
|
||||||
|
|
||||||
// UserCreateInput captures the minimal payload to create a user.
|
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type UserCreateInput struct {
|
|
||||||
Name string `json:"name" validate:"required,min=1,max=255"`
|
|
||||||
Email string `json:"email" validate:"required,email"`
|
|
||||||
Password string `json:"password" validate:"required,min=8,max=128"`
|
|
||||||
Roles UserRoles `json:"roles"`
|
|
||||||
Status UserStatus `json:"status"`
|
|
||||||
Types UserTypes `json:"types"`
|
|
||||||
Avatar *string `json:"avatar"`
|
|
||||||
Details *UserDetails `json:"details" `
|
|
||||||
Preferences *UserPreferences `json:"preferences" `
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserTypes is stored as JSON array (e.g. ["internal","external"]).
|
// UserTypes is stored as JSON array (e.g. ["internal","external"]).
|
||||||
type UserTypes []string
|
type UserTypes []string
|
||||||
|
|
||||||
// UserProfile is the safe full representation of a user returned by CRUD endpoints.
|
// UserProfile is the safe full representation of a user returned by CRUD endpoints.
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type UserProfile struct {
|
type UserProfile struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
|
@ -63,8 +43,8 @@ type UserProfile struct {
|
||||||
Details *UserDetails `json:"details"`
|
Details *UserDetails `json:"details"`
|
||||||
Preferences *UserPreferences `json:"preferences"`
|
Preferences *UserPreferences `json:"preferences"`
|
||||||
Avatar *string `json:"avatar"`
|
Avatar *string `json:"avatar"`
|
||||||
CreatedAt time.Time `json:"createdAt" ts:"type=Date"`
|
CreatedAt *time.Time `json:"createdAt" ts:"type=Date"`
|
||||||
UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"`
|
UpdatedAt *time.Time `json:"updatedAt" ts:"type=Date"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToUserProfile maps a User to a full response without exposing the password hash.
|
// ToUserProfile maps a User to a full response without exposing the password hash.
|
||||||
|
|
@ -91,7 +71,6 @@ func ToUserProfile(u *User) UserProfile {
|
||||||
|
|
||||||
// UserPreferences holds per-user settings stored as JSON.
|
// UserPreferences holds per-user settings stored as JSON.
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type UserPreferences struct {
|
type UserPreferences struct {
|
||||||
ID int `json:"id" gorm:"primaryKey"`
|
ID int `json:"id" gorm:"primaryKey"`
|
||||||
UserID int `json:"userId" gorm:"index"`
|
UserID int `json:"userId" gorm:"index"`
|
||||||
|
|
@ -109,7 +88,6 @@ type UserPreferences struct {
|
||||||
|
|
||||||
// UserDetails holds optional profile data.
|
// UserDetails holds optional profile data.
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type UserDetails struct {
|
type UserDetails struct {
|
||||||
ID int `json:"id" gorm:"primaryKey"`
|
ID int `json:"id" gorm:"primaryKey"`
|
||||||
UserID int `json:"userId" gorm:"index"`
|
UserID int `json:"userId" gorm:"index"`
|
||||||
|
|
@ -121,8 +99,8 @@ type UserDetails struct {
|
||||||
ZipCode string `json:"zipCode"`
|
ZipCode string `json:"zipCode"`
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
CreatedAt time.Time `json:"createdAt" ts:"type=Date"`
|
CreatedAt time.Time `json:"createdAt" ts:"type=Nullable<Date>"`
|
||||||
UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"`
|
UpdatedAt time.Time `json:"updatedAt" ts:"type=Nullable<Date>"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserDetails holds optional profile data.
|
// UserDetails holds optional profile data.
|
||||||
|
|
@ -164,24 +142,46 @@ const (
|
||||||
UserStatusDisabled UserStatus = "disabled"
|
UserStatusDisabled UserStatus = "disabled"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type LoginRequest struct {
|
type LoginRequest struct {
|
||||||
Username string `json:"username" validate:"required,email"`
|
Username string `json:"username" validate:"required,email"`
|
||||||
Password string `json:"password" validate:"required,min=8,max=128"`
|
Password string `json:"password" validate:"required,min=8,max=128"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type RefreshRequest struct {
|
type RefreshRequest struct {
|
||||||
RefreshToken string `json:"refresh_token"`
|
RefreshToken string `json:"refresh_token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type ForgotPasswordRequest struct {
|
type ForgotPasswordRequest struct {
|
||||||
Email string `json:"email" validate:"required,email"`
|
Email string `json:"email" validate:"required,email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typescript: interface
|
|
||||||
type ResetPasswordRequest struct {
|
type ResetPasswordRequest struct {
|
||||||
Token string `json:"token" validate:"required,min=20,max=255"`
|
Token string `json:"token" validate:"required,min=20,max=255"`
|
||||||
Password string `json:"password" validate:"required,min=8,max=128"`
|
Password string `json:"password" validate:"required,min=8,max=128"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UpdateUserRequest struct {
|
||||||
|
Name string `json:"name" validate:"required,min=1,max=255"`
|
||||||
|
Email string `json:"email" validate:"required,email"`
|
||||||
|
Password string `json:"password" validate:"omitempty,min=8,max=128"`
|
||||||
|
Roles UserRoles `json:"roles"`
|
||||||
|
Status UserStatus `json:"status"`
|
||||||
|
Types UserTypes `json:"types"`
|
||||||
|
Avatar *string `json:"avatar"`
|
||||||
|
Details *UserDetails `json:"details"`
|
||||||
|
Preferences *UserPreferences `json:"preferences"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserCreateRequest captures the minimal payload to create a user.
|
||||||
|
|
||||||
|
type UserCreateRequest struct {
|
||||||
|
Name string `json:"name" validate:"required,min=1,max=255"`
|
||||||
|
Email string `json:"email" validate:"required,email"`
|
||||||
|
Password string `json:"password" validate:"required,min=8,max=128"`
|
||||||
|
Roles UserRoles `json:"roles"`
|
||||||
|
Status UserStatus `json:"status"`
|
||||||
|
Types UserTypes `json:"types"`
|
||||||
|
Avatar *string `json:"avatar"`
|
||||||
|
Details *UserDetails `json:"details" `
|
||||||
|
Preferences *UserPreferences `json:"preferences" `
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func RegisterUserRoutes(app *fiber.App) {
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=users.User
|
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=users.User
|
||||||
app.Get("/users/:uuid", tockenService.Middleware(), userController.GetUser)
|
app.Get("/users/:uuid", tockenService.Middleware(), userController.GetUser)
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=users.UserCreateInput; response=users.User
|
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=users.UserCreateRequest; response=users.User
|
||||||
app.Post("/users", tockenService.Middleware(), userController.CreateUser)
|
app.Post("/users", tockenService.Middleware(), userController.CreateUser)
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User
|
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User
|
||||||
|
|
@ -46,7 +46,7 @@ func RegisterUserRoutes(app *fiber.App) {
|
||||||
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair
|
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair
|
||||||
app.Post("/auth/refresh", authRateLimiter, userController.Refresh)
|
app.Post("/auth/refresh", authRateLimiter, userController.Refresh)
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=users.UserCreateInput; response=users.User
|
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=users.UserCreateRequest; response=users.User
|
||||||
app.Post("/auth/register", authRateLimiter, userController.Register)
|
app.Post("/auth/register", authRateLimiter, userController.Register)
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=users.ForgotPasswordRequest; response=responses.SimpleResponse
|
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=users.ForgotPasswordRequest; response=responses.SimpleResponse
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,6 @@ func (t *TSFiles) Save() error {
|
||||||
return fmt.Errorf("TS Files not initialized")
|
return fmt.Errorf("TS Files not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range *t {
|
|
||||||
fmt.Printf("file: %s\nsource:\n%s\n\n", k, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, source := range *t {
|
for name, source := range *t {
|
||||||
formatted, err := formatJS(source)
|
formatted, err := formatJS(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func ParseEndpoint(source string, file string, line int) TSEndpoint {
|
||||||
endpoint.Request = strings.Trim(t[1], " ")
|
endpoint.Request = strings.Trim(t[1], " ")
|
||||||
case "response":
|
case "response":
|
||||||
n++
|
n++
|
||||||
endpoint.Response = strings.Trim(t[1], " ")
|
endpoint.Response = strings.Trim(t[1], " \n")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
exitOnError(fmt.Errorf("wrong endpoint props: %s", s))
|
exitOnError(fmt.Errorf("wrong endpoint props: %s", s))
|
||||||
|
|
@ -85,11 +85,6 @@ type tplData struct {
|
||||||
|
|
||||||
func (e *TSEndpoint) VerifyTypes(info TSInfo, p string) {
|
func (e *TSEndpoint) VerifyTypes(info TSInfo, p string) {
|
||||||
kind := ""
|
kind := ""
|
||||||
|
|
||||||
if e.Name == "listUsers" {
|
|
||||||
fmt.Println("endpoint request", e.Request)
|
|
||||||
}
|
|
||||||
|
|
||||||
a := strings.Split(e.Request, ".")
|
a := strings.Split(e.Request, ".")
|
||||||
if e.Request != "" {
|
if e.Request != "" {
|
||||||
if len(a) == 2 {
|
if len(a) == 2 {
|
||||||
|
|
@ -159,7 +154,7 @@ func (e *TSEndpoint) VerifyTypes(info TSInfo, p string) {
|
||||||
allreadyImported := slices.Contains(e.Imports[a[0]], strings.Trim(a[1], "[]*"))
|
allreadyImported := slices.Contains(e.Imports[a[0]], strings.Trim(a[1], "[]*"))
|
||||||
if !allreadyImported {
|
if !allreadyImported {
|
||||||
e.Imports[a[0]] = append(e.Imports[a[0]], strings.Trim(a[1], "[]*"))
|
e.Imports[a[0]] = append(e.Imports[a[0]], strings.Trim(a[1], "[]*"))
|
||||||
fmt.Printf("endpoint %s response import: %s.%s\n", e.Name, a[0], a[1])
|
//fmt.Printf("endpoint %s response import: %s.%s\n", e.Name, a[0], a[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info.setTypescript(a[0], a[1], true)
|
info.setTypescript(a[0], a[1], true)
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,16 @@
|
||||||
package tsrpc
|
package tsrpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/doc"
|
"go/doc"
|
||||||
"go/parser"
|
"io"
|
||||||
"go/token"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TSInfoPakage struct {
|
type TSInfoPakage struct {
|
||||||
|
|
@ -29,7 +30,6 @@ type TSInfoPakage struct {
|
||||||
type TSDec struct {
|
type TSDec struct {
|
||||||
Name string
|
Name string
|
||||||
Value string
|
Value string
|
||||||
SourceInfo string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TSType struct {
|
type TSType struct {
|
||||||
|
|
@ -38,7 +38,6 @@ type TSType struct {
|
||||||
TsType string
|
TsType string
|
||||||
Typescript bool
|
Typescript bool
|
||||||
dependOn bool
|
dependOn bool
|
||||||
SourceInfo string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TSInfo struct {
|
type TSInfo struct {
|
||||||
|
|
@ -128,7 +127,7 @@ func (ts TSInfo) find(p string, n string) bool {
|
||||||
|
|
||||||
// popola TsInfo con tutte le definizioni dei tipi
|
// popola TsInfo con tutte le definizioni dei tipi
|
||||||
|
|
||||||
func (i *TSInfo) getConst(p string, c *doc.Value, src []TSSourceFile) {
|
func (i *TSInfo) getConst(p string, c *doc.Value) {
|
||||||
var isTypescript = strings.HasPrefix(c.Doc, "Typescript:")
|
var isTypescript = strings.HasPrefix(c.Doc, "Typescript:")
|
||||||
if isTypescript {
|
if isTypescript {
|
||||||
command := strings.TrimPrefix(c.Doc, "Typescript:")
|
command := strings.TrimPrefix(c.Doc, "Typescript:")
|
||||||
|
|
@ -150,7 +149,7 @@ func (i *TSInfo) getConst(p string, c *doc.Value, src []TSSourceFile) {
|
||||||
be, ok := v.Values[0].(*ast.BinaryExpr)
|
be, ok := v.Values[0].(*ast.BinaryExpr)
|
||||||
if ok {
|
if ok {
|
||||||
x := be.X.(*ast.BasicLit)
|
x := be.X.(*ast.BasicLit)
|
||||||
exitOnError(fmt.Errorf("enum binary expression not implemented %s %s %s AT: %s", x.Value, be.Op.String(), be.Y, getSourceInfo(int(x.ValuePos), src)))
|
exitOnError(fmt.Errorf("enum binary expression not implemented %s %s %s", x.Value, be.Op.String(), be.Y))
|
||||||
}
|
}
|
||||||
ident, ok := v.Values[0].(*ast.Ident)
|
ident, ok := v.Values[0].(*ast.Ident)
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -177,11 +176,10 @@ func (i *TSInfo) getConst(p string, c *doc.Value, src []TSSourceFile) {
|
||||||
i.Packages[p].enums[enumName] = enum
|
i.Packages[p].enums[enumName] = enum
|
||||||
t1 := TSType{
|
t1 := TSType{
|
||||||
Name: enumName,
|
Name: enumName,
|
||||||
Typescript: true,
|
Typescript: false,
|
||||||
Type: "",
|
Type: "",
|
||||||
TsType: fmt.Sprintf("typeof Enum%s[keyof typeof Enum%s] ", enumName, enumName), //getFieldTsInfo(expr.Type),
|
TsType: fmt.Sprintf("typeof Enum%s[keyof typeof Enum%s] ", enumName, enumName), //getFieldTsInfo(expr.Type),
|
||||||
dependOn: false,
|
dependOn: false,
|
||||||
SourceInfo: "",
|
|
||||||
}
|
}
|
||||||
i.Packages[p].types[enumName] = t1
|
i.Packages[p].types[enumName] = t1
|
||||||
}
|
}
|
||||||
|
|
@ -204,32 +202,10 @@ func (i *TSInfo) getConst(p string, c *doc.Value, src []TSSourceFile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *TSInfo) getType(p string, t *doc.Type, src []TSSourceFile) {
|
func (i *TSInfo) getType(p string, t *doc.Type) {
|
||||||
var isType = t.Decl.Tok == token.TYPE && t.Doc == ""
|
|
||||||
var isTypescript = strings.HasPrefix(t.Doc, "Typescript:")
|
|
||||||
command := ""
|
|
||||||
param := ""
|
|
||||||
if isTypescript {
|
|
||||||
//fmt.Println(t.Doc)
|
|
||||||
command = strings.TrimPrefix(t.Doc, "Typescript:")
|
|
||||||
command = strings.TrimSpace(command)
|
|
||||||
command = strings.Trim(command, "\n")
|
|
||||||
|
|
||||||
if strings.Contains(command, "=") {
|
|
||||||
a := strings.Split(command, "=")
|
|
||||||
if len(a) == 2 {
|
|
||||||
param = a[1]
|
|
||||||
}
|
|
||||||
command = strings.Trim(a[0], " ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isType {
|
|
||||||
//fmt.Println(t.Doc)
|
|
||||||
command = "interface"
|
|
||||||
}
|
|
||||||
for _, spec := range t.Decl.Specs {
|
for _, spec := range t.Decl.Specs {
|
||||||
if len(t.Consts) > 0 {
|
if len(t.Consts) > 0 {
|
||||||
i.getConst(p, t.Consts[0], src)
|
i.getConst(p, t.Consts[0])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch spec.(type) {
|
switch spec.(type) {
|
||||||
|
|
@ -237,32 +213,28 @@ func (i *TSInfo) getType(p string, t *doc.Type, src []TSSourceFile) {
|
||||||
typeSpec := spec.(*ast.TypeSpec)
|
typeSpec := spec.(*ast.TypeSpec)
|
||||||
switch typeSpec.Type.(type) {
|
switch typeSpec.Type.(type) {
|
||||||
case *ast.StructType:
|
case *ast.StructType:
|
||||||
if (isTypescript || isType) && command != "interface" {
|
// if isType && command != "interface" {
|
||||||
exitOnError(fmt.Errorf("mismatch delaration for interface %s AT: %s", t.Doc, getSourceInfo(int(typeSpec.Name.NamePos), src)))
|
// exitOnError(fmt.Errorf("mismatch delaration for interface %s AT: %s", t.Doc, getSourceInfo(int(typeSpec.Name.NamePos), src)))
|
||||||
}
|
// }
|
||||||
v := TSStruct{
|
v := TSStruct{
|
||||||
Name: typeSpec.Name.Name,
|
Name: typeSpec.Name.Name,
|
||||||
Typescript: isTypescript,
|
Typescript: false,
|
||||||
Fields: []TSSField{},
|
Fields: []TSSField{},
|
||||||
SourceInfo: getSourceInfo(int(typeSpec.Name.NamePos), src),
|
SourceInfo: "",
|
||||||
}
|
}
|
||||||
v.getStruct(typeSpec, src)
|
v.getStruct(typeSpec)
|
||||||
i.Packages[p].structs[typeSpec.Name.Name] = v
|
i.Packages[p].structs[typeSpec.Name.Name] = v
|
||||||
default:
|
default:
|
||||||
if isTypescript && command != "type" {
|
// if isType && command != "interface" {
|
||||||
exitOnError(fmt.Errorf("mismatch delaration for type %s AT: %s", t.Doc, getSourceInfo(int(typeSpec.Name.NamePos), src)))
|
// exitOnError(fmt.Errorf("mismatch delaration for interface %s AT: %s", t.Doc, getSourceInfo(int(typeSpec.Name.NamePos), src)))
|
||||||
}
|
// }
|
||||||
tsInfo := getFieldTsInfo(typeSpec.Type)
|
tsInfo := getFieldTsInfo(typeSpec.Type)
|
||||||
if command == "type" && param != "" {
|
|
||||||
tsInfo = param
|
|
||||||
}
|
|
||||||
t := TSType{
|
t := TSType{
|
||||||
Name: typeSpec.Name.Name,
|
Name: typeSpec.Name.Name,
|
||||||
Typescript: isTypescript,
|
Typescript: false,
|
||||||
Type: getFieldInfo(typeSpec.Type),
|
Type: getFieldInfo(typeSpec.Type),
|
||||||
TsType: tsInfo,
|
TsType: tsInfo,
|
||||||
dependOn: toBeImported(typeSpec.Type),
|
dependOn: toBeImported(typeSpec.Type),
|
||||||
SourceInfo: getSourceInfo(int(typeSpec.Name.NamePos), src),
|
|
||||||
}
|
}
|
||||||
//fmt.Printf("Type found: %s Type: %s TsType: %s AT: %s\n", t.Name, t.Type, t.TsType, t.SourceInfo)
|
//fmt.Printf("Type found: %s Type: %s TsType: %s AT: %s\n", t.Name, t.Type, t.TsType, t.SourceInfo)
|
||||||
i.Packages[p].types[typeSpec.Name.Name] = t
|
i.Packages[p].types[typeSpec.Name.Name] = t
|
||||||
|
|
@ -271,53 +243,35 @@ func (i *TSInfo) getType(p string, t *doc.Type, src []TSSourceFile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *TSInfo) Populate(path string) {
|
func parseTypescriptDeclarations(n string, pkg TSInfoPakage) {
|
||||||
i.Packages = make(map[string]TSInfoPakage)
|
f, err := os.OpenFile(n, os.O_RDONLY, os.ModePerm)
|
||||||
err := filepath.Walk(path,
|
|
||||||
func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
log.Fatalf("open file error: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if info.IsDir() {
|
defer f.Close()
|
||||||
fset := token.NewFileSet()
|
l := 1
|
||||||
packages, err := parser.ParseDir(fset, path, nil, parser.ParseComments)
|
dat := ""
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
exitOnError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for pkg, f := range packages {
|
|
||||||
if _, ok := i.Packages[pkg]; !ok {
|
|
||||||
i.Packages[pkg] = TSInfoPakage{structs: make(map[string]TSStruct), types: make(map[string]TSType), enums: make(map[string]TSEnum), consts: make(map[string]TSConst), decs: make(map[string]TSDec), endpoints: make(map[string]TSEndpoint)}
|
|
||||||
}
|
|
||||||
if pkg == "typescript" || pkg == "tsrpc" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var src = []TSSourceFile{}
|
|
||||||
for n := range f.Files {
|
|
||||||
|
|
||||||
dat, err := os.ReadFile(n)
|
|
||||||
if err == nil {
|
|
||||||
lines := []TSSourceLine{}
|
lines := []TSSourceLine{}
|
||||||
pos := 0
|
rd := bufio.NewReader(f)
|
||||||
line := 1
|
for {
|
||||||
for p, k := range dat {
|
line, err := rd.ReadString('\n')
|
||||||
if string(k) == "\n" {
|
if err != nil {
|
||||||
l := TSSourceLine{
|
if err == io.EOF {
|
||||||
Pos: pos,
|
break
|
||||||
End: p,
|
|
||||||
Line: line,
|
|
||||||
Source: string(dat[pos:p]),
|
|
||||||
}
|
}
|
||||||
lines = append(lines, l)
|
|
||||||
pos = p + 1
|
|
||||||
line++
|
|
||||||
if strings.Contains(l.Source, "// Typescript:") {
|
|
||||||
|
|
||||||
if strings.Contains(l.Source, "TStype=") {
|
log.Fatalf("read file line error: %v", err)
|
||||||
p := strings.Index(l.Source, "TStype=")
|
return
|
||||||
s := strings.Trim(l.Source[p+len("TStype="):], " ")
|
}
|
||||||
|
lines = append(lines, TSSourceLine{Pos: l, End: l + len(line), Line: l, Source: line})
|
||||||
|
l++
|
||||||
|
dat += line
|
||||||
|
|
||||||
|
if strings.Contains(line, "// Typescript:") {
|
||||||
|
if strings.Contains(line, "TStype=") {
|
||||||
|
p := strings.Index(line, "TStype=")
|
||||||
|
s := strings.Trim(line[p+len("TStype="):], " ")
|
||||||
a := strings.Split(s, "=")
|
a := strings.Split(s, "=")
|
||||||
if len(a) == 2 {
|
if len(a) == 2 {
|
||||||
t := TSType{
|
t := TSType{
|
||||||
|
|
@ -326,105 +280,149 @@ func (i *TSInfo) Populate(path string) {
|
||||||
Type: "UserDefined",
|
Type: "UserDefined",
|
||||||
TsType: strings.Trim(a[1], " "),
|
TsType: strings.Trim(a[1], " "),
|
||||||
dependOn: false,
|
dependOn: false,
|
||||||
SourceInfo: getSourceInfo(int(l.Pos), src),
|
|
||||||
}
|
}
|
||||||
i.Packages[pkg].types[strings.Trim(a[0], " ")] = t
|
pkg.types[strings.Trim(a[0], " ")] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if strings.Contains(l.Source, "TSDeclaration=") {
|
if strings.Contains(line, "TSDeclaration=") {
|
||||||
p := strings.Index(l.Source, "TSDeclaration=")
|
p := strings.Index(line, "TSDeclaration=")
|
||||||
s := strings.Trim(l.Source[p+len("TSDeclaration="):], " ")
|
s := strings.Trim(line[p+len("TSDeclaration="):], " ")
|
||||||
a := strings.Split(s, "=")
|
a := strings.Split(s, "=")
|
||||||
if len(a) == 2 {
|
if len(a) == 2 {
|
||||||
t := TSDec{
|
t := TSDec{
|
||||||
Name: strings.Trim(a[0], " "),
|
Name: strings.Trim(a[0], " "),
|
||||||
Value: strings.Trim(a[1], " "),
|
Value: strings.Trim(a[1], " "),
|
||||||
SourceInfo: getSourceInfo(int(l.Pos), src),
|
|
||||||
}
|
}
|
||||||
i.Packages[pkg].decs[strings.Trim(a[0], " ")] = t
|
pkg.decs[strings.Trim(a[0], " ")] = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(l.Source, "TSEndpoint= ") {
|
if strings.Contains(line, "TSEndpoint= ") {
|
||||||
e := ParseEndpoint(l.Source, n, l.Line)
|
e := ParseEndpoint(line, n, l)
|
||||||
if _, ok := i.Packages[pkg].endpoints[e.Name]; ok {
|
if _, ok := pkg.endpoints[e.Name]; ok {
|
||||||
exitOnError(fmt.Errorf("enpoint name %s allready in use: %s", e.Name, l.Source))
|
exitOnError(fmt.Errorf("enpoint name %s allready in use: %s", e.Name, line))
|
||||||
}
|
}
|
||||||
pkg_info := i.Packages[pkg]
|
pkg_info := pkg
|
||||||
pkg_info.endpoints[e.Name] = e
|
pkg_info.endpoints[e.Name] = e
|
||||||
pkg_info.imports = e.Imports
|
pkg_info.imports = e.Imports
|
||||||
pkg_info.isUsed = true
|
pkg_info.isUsed = true
|
||||||
i.Packages[pkg] = pkg_info
|
pkg = pkg_info
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s := TSSourceFile{
|
|
||||||
Name: n,
|
|
||||||
Source: string(dat),
|
|
||||||
Len: len(dat),
|
|
||||||
Lines: lines,
|
|
||||||
}
|
|
||||||
src = append(src, s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p := doc.New(f, "./", 0)
|
}
|
||||||
|
|
||||||
for _, t := range p.Types {
|
|
||||||
i.getType(pkg, t, src)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range p.Consts {
|
func (i *TSInfo) Populate(path string) {
|
||||||
i.getConst(pkg, c, src)
|
i.Packages = make(map[string]TSInfoPakage)
|
||||||
|
cfg := &packages.Config{
|
||||||
|
Mode: packages.NeedName |
|
||||||
|
packages.NeedFiles |
|
||||||
|
packages.NeedCompiledGoFiles |
|
||||||
|
packages.NeedSyntax,
|
||||||
|
Dir: path,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
pkgs, err := packages.Load(cfg, "./...")
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
if packages.PrintErrors(pkgs) > 0 {
|
||||||
|
log.Fatal("package loading failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ts *TSInfo) findAvailableStruct(n string) (TSStruct, bool) {
|
//to get line info for endpoints and typescript declarations
|
||||||
|
for _, loadedPkg := range pkgs {
|
||||||
|
pkg := loadedPkg.Name
|
||||||
|
// skip packages
|
||||||
|
if pkg == "typescript" || pkg == "tsrpc" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// initialize package info if not exists
|
||||||
|
if _, ok := i.Packages[pkg]; !ok {
|
||||||
|
i.Packages[pkg] = TSInfoPakage{structs: make(map[string]TSStruct), types: make(map[string]TSType), enums: make(map[string]TSEnum), consts: make(map[string]TSConst), decs: make(map[string]TSDec), endpoints: make(map[string]TSEndpoint)}
|
||||||
|
}
|
||||||
|
// start parsing files
|
||||||
|
for _, n := range loadedPkg.CompiledGoFiles {
|
||||||
|
// search for declarative // Typescript: declarations and endpoints
|
||||||
|
parseTypescriptDeclarations(n, i.Packages[pkg])
|
||||||
|
}
|
||||||
|
// parse doc to get all types and consts
|
||||||
|
docPkg, err := doc.NewFromFiles(loadedPkg.Fset, loadedPkg.Syntax, loadedPkg.PkgPath)
|
||||||
|
if err != nil {
|
||||||
|
exitOnError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, t := range docPkg.Types {
|
||||||
|
i.getType(pkg, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range docPkg.Consts {
|
||||||
|
i.getConst(pkg, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ts *TSInfo) findAvailableStruct(pkg string, n string, deep int) (int, bool) {
|
||||||
a := strings.Split(n, ".")
|
a := strings.Split(n, ".")
|
||||||
|
if n == "" || IsNativeType(n) {
|
||||||
|
return deep, true
|
||||||
|
}
|
||||||
|
|
||||||
|
deep++
|
||||||
|
if deep > 10 {
|
||||||
|
exitOnError(fmt.Errorf("too much deep for struct %s", n))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(a) == 1 {
|
||||||
|
n = strings.TrimPrefix(n, "[]")
|
||||||
|
n = strings.TrimPrefix(n, "*")
|
||||||
|
if _, ok := ts.Packages[pkg].structs[n]; ok {
|
||||||
|
s := ts.Packages[pkg].structs[n]
|
||||||
|
s.Typescript = true
|
||||||
|
ts.Packages[pkg].structs[n] = s // write back
|
||||||
|
for _, v := range s.Fields {
|
||||||
|
deep, _ = ts.findAvailableStruct(pkg, v.Type, deep)
|
||||||
|
}
|
||||||
|
deep--
|
||||||
|
return deep, true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if len(a) == 2 {
|
if len(a) == 2 {
|
||||||
a[1] = strings.TrimPrefix(a[1], "[]")
|
a[1] = strings.TrimPrefix(a[1], "[]")
|
||||||
a[1] = strings.TrimPrefix(a[1], "*")
|
a[1] = strings.TrimPrefix(a[1], "*")
|
||||||
if _, ok := ts.Packages[a[0]]; ok {
|
if _, ok := ts.Packages[a[0]]; ok {
|
||||||
if _, ok := ts.Packages[a[0]].structs[a[1]]; ok {
|
if _, ok := ts.Packages[a[0]].structs[a[1]]; ok {
|
||||||
return ts.Packages[a[0]].structs[a[1]], true
|
s := ts.Packages[a[0]].structs[a[1]]
|
||||||
|
if s.Typescript {
|
||||||
|
deep--
|
||||||
|
return deep, true
|
||||||
|
}
|
||||||
|
s.Typescript = true
|
||||||
|
ts.Packages[a[0]].structs[a[1]] = s // write back
|
||||||
|
for _, v := range s.Fields {
|
||||||
|
ts.findAvailableStruct(pkg, v.Type, deep)
|
||||||
|
}
|
||||||
|
deep--
|
||||||
|
return deep, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(a) == 1 {
|
|
||||||
n = strings.TrimPrefix(n, "[]")
|
|
||||||
n = strings.TrimPrefix(n, "*")
|
|
||||||
for p := range ts.Packages {
|
|
||||||
if _, ok := ts.Packages[p].structs[n]; ok {
|
|
||||||
return ts.Packages[p].structs[n], true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n == "" || IsNativeType(n) {
|
|
||||||
return TSStruct{}, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSStruct{}, false
|
return deep, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *TSInfo) TestEndpoints() {
|
func (i *TSInfo) TestEndpoints() {
|
||||||
for p := range i.Packages {
|
for p := range i.Packages {
|
||||||
for _, v1 := range i.Packages[p].endpoints {
|
for _, v1 := range i.Packages[p].endpoints {
|
||||||
_, f := i.findAvailableStruct(v1.Request)
|
_, f := i.findAvailableStruct(p, v1.Request, 0)
|
||||||
if !f {
|
if !f {
|
||||||
fmt.Printf("??Endpoint: request %s not found\n", v1.Request)
|
fmt.Printf("??Endpoint: request %s not found\n", v1.Request)
|
||||||
}
|
}
|
||||||
_, f = i.findAvailableStruct(v1.Response)
|
_, f = i.findAvailableStruct(p, v1.Response, 0)
|
||||||
if !f {
|
if !f {
|
||||||
fmt.Printf("??Endpoint: response %s not found\n", v1.Response)
|
fmt.Printf("??Endpoint: response %s not found\n", v1.Response)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,7 @@ func getFieldInfo(t ast.Expr) string {
|
||||||
case *ast.InterfaceType:
|
case *ast.InterfaceType:
|
||||||
result = "interface{}"
|
result = "interface{}"
|
||||||
default:
|
default:
|
||||||
f := fmt.Sprintf("this go type: %T is not evaluated", ft)
|
exitOnError(fmt.Errorf("this go type: %T is not evaluated", ft))
|
||||||
fmt.Println(f)
|
|
||||||
//exitOnError(fmt.Errorf("this go type: %T is not evaluated", ft))
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
@ -104,25 +102,12 @@ func getFieldTsInfo(t ast.Expr) string {
|
||||||
case *ast.FuncType:
|
case *ast.FuncType:
|
||||||
fmt.Println("*ast.FuncType found, skipping...")
|
fmt.Println("*ast.FuncType found, skipping...")
|
||||||
default:
|
default:
|
||||||
//f := fmt.Sprintf("getFieldTsInfo can't evaluate type: %T %T", t, ft)
|
|
||||||
//fmt.Println(f)
|
|
||||||
exitOnError(fmt.Errorf("getFieldTsInfo can't evaluate type: %T %T", t, ft))
|
exitOnError(fmt.Errorf("getFieldTsInfo can't evaluate type: %T %T", t, ft))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSourceInfo(pos int, src []TSSourceFile) string {
|
func (s *TSStruct) getStruct(ts *ast.TypeSpec) {
|
||||||
for _, v := range src {
|
|
||||||
for _, l := range v.Lines {
|
|
||||||
if pos >= l.Pos && pos <= l.End {
|
|
||||||
return fmt.Sprintf("%s Line: %d", v.Name, l.Line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TSStruct) getStruct(ts *ast.TypeSpec, src []TSSourceFile) {
|
|
||||||
if st, ok := ts.Type.(*ast.StructType); ok {
|
if st, ok := ts.Type.(*ast.StructType); ok {
|
||||||
for _, field := range st.Fields.List {
|
for _, field := range st.Fields.List {
|
||||||
|
|
||||||
|
|
@ -148,7 +133,7 @@ func (s *TSStruct) getStruct(ts *ast.TypeSpec, src []TSSourceFile) {
|
||||||
Type: getFieldInfo(field.Type),
|
Type: getFieldInfo(field.Type),
|
||||||
TsType: tsType,
|
TsType: tsType,
|
||||||
DependOn: toBeImported(field.Type),
|
DependOn: toBeImported(field.Type),
|
||||||
SourceInfo: getSourceInfo(int(field.Type.Pos()), src),
|
SourceInfo: "",
|
||||||
}
|
}
|
||||||
s.Fields = append(s.Fields, f)
|
s.Fields = append(s.Fields, f)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -160,7 +145,7 @@ func (s *TSStruct) getStruct(ts *ast.TypeSpec, src []TSSourceFile) {
|
||||||
Type: getFieldInfo(field.Type),
|
Type: getFieldInfo(field.Type),
|
||||||
TsType: tsType,
|
TsType: tsType,
|
||||||
DependOn: toBeImported(field.Type),
|
DependOn: toBeImported(field.Type),
|
||||||
SourceInfo: getSourceInfo(int(field.Type.Pos()), src),
|
SourceInfo: "",
|
||||||
}
|
}
|
||||||
s.Fields = append(s.Fields, f)
|
s.Fields = append(s.Fields, f)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -172,11 +157,9 @@ func (s *TSStruct) getStruct(ts *ast.TypeSpec, src []TSSourceFile) {
|
||||||
Type: se.Name,
|
Type: se.Name,
|
||||||
TsType: tsType,
|
TsType: tsType,
|
||||||
DependOn: false,
|
DependOn: false,
|
||||||
SourceInfo: getSourceInfo(int(field.Type.Pos()), src),
|
SourceInfo: "",
|
||||||
}
|
}
|
||||||
s.Fields = append(s.Fields, f)
|
s.Fields = append(s.Fields, f)
|
||||||
|
|
||||||
fmt.Println(f)
|
|
||||||
} else {
|
} else {
|
||||||
exitOnError(fmt.Errorf("this typescript type: %T is not evaluated", field.Type))
|
exitOnError(fmt.Errorf("this typescript type: %T is not evaluated", field.Type))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ type TSModule struct {
|
||||||
GTypes map[string]string
|
GTypes map[string]string
|
||||||
Endpoints map[string]string
|
Endpoints map[string]string
|
||||||
Imports map[string][]string
|
Imports map[string][]string
|
||||||
Source string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TSOutputSources []string
|
type TSOutputSources []string
|
||||||
|
|
@ -222,7 +221,7 @@ func (ts *TSSouces) Populate(info TSInfo) {
|
||||||
for p := range info.Packages {
|
for p := range info.Packages {
|
||||||
ts.ensurePackage(p)
|
ts.ensurePackage(p)
|
||||||
|
|
||||||
ts.Errors = append(ts.Errors, fmt.Sprintf("Process pakage %s\n", p))
|
// ts.Errors = append(ts.Errors, fmt.Sprintf("Process pakage %s\n", p))
|
||||||
|
|
||||||
for _, st := range info.Packages[p].structs {
|
for _, st := range info.Packages[p].structs {
|
||||||
if st.Typescript {
|
if st.Typescript {
|
||||||
|
|
@ -259,30 +258,6 @@ func (ts *TSSouces) Populate(info TSInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, e := range info.Packages[p].endpoints {
|
for _, e := range info.Packages[p].endpoints {
|
||||||
|
|
||||||
/* if e.Request != "" {
|
|
||||||
a := strings.Split(e.Request, ".")
|
|
||||||
if len(a) == 2 {
|
|
||||||
s, d, err := structToTs(info, a[0], a[1])
|
|
||||||
if err != nil {
|
|
||||||
ts.Errors = append(ts.Errors, err.Error())
|
|
||||||
}
|
|
||||||
fmt.Println(s, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.Response != "" {
|
|
||||||
a := strings.Split(e.Response, ".")
|
|
||||||
if len(a) == 2 {
|
|
||||||
s, d, err := structToTs(info, a[0], a[1])
|
|
||||||
if err != nil {
|
|
||||||
ts.Errors = append(ts.Errors, err.Error())
|
|
||||||
}
|
|
||||||
fmt.Println(s, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
} */
|
|
||||||
responseAndRequest := ""
|
responseAndRequest := ""
|
||||||
|
|
||||||
if e.Request != "" {
|
if e.Request != "" {
|
||||||
|
|
@ -303,10 +278,6 @@ func (ts *TSSouces) Populate(info TSInfo) {
|
||||||
}
|
}
|
||||||
pkg.Endpoints[e.Name] = e.ToTs()
|
pkg.Endpoints[e.Name] = e.ToTs()
|
||||||
ts.Pakages[p] = pkg
|
ts.Pakages[p] = pkg
|
||||||
if p == "users" {
|
|
||||||
fmt.Printf("endpoint %s imports: %v\n", e.Name, pkg.Imports)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,6 @@ func GetTSSource() error {
|
||||||
tsFiles.Add("apiTypes.ts", tsIndexSource)
|
tsFiles.Add("apiTypes.ts", tsIndexSource)
|
||||||
|
|
||||||
for p := range tsSourcesData.Pakages {
|
for p := range tsSourcesData.Pakages {
|
||||||
if p == "users" {
|
|
||||||
fmt.Println("users package")
|
|
||||||
}
|
|
||||||
source := ""
|
source := ""
|
||||||
for _, v1 := range tsSourcesData.Pakages[p].Endpoints {
|
for _, v1 := range tsSourcesData.Pakages[p].Endpoints {
|
||||||
source += fmt.Sprintln(v1)
|
source += fmt.Sprintln(v1)
|
||||||
|
|
@ -90,7 +87,7 @@ func GetTSSource() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if found {
|
if found {
|
||||||
tmp += "import { api } from './api.ts'\n"
|
tmp += "import { api } from './api'\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tsApiDeclarations) > 0 {
|
if len(tsApiDeclarations) > 0 {
|
||||||
|
|
@ -108,20 +105,19 @@ func GetTSSource() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(decs) > 0 {
|
if len(decs) > 0 {
|
||||||
TSApiDeclarations := "import { "
|
TSApiDeclarations := "import type { "
|
||||||
for _, d := range decs {
|
for _, d := range decs {
|
||||||
TSApiDeclarations += d + ", "
|
TSApiDeclarations += d + ", "
|
||||||
}
|
}
|
||||||
TSApiDeclarations = TSApiDeclarations[:len(TSApiDeclarations)-2]
|
TSApiDeclarations = TSApiDeclarations[:len(TSApiDeclarations)-2]
|
||||||
TSApiDeclarations += " } from './apiTypes.ts'\n"
|
TSApiDeclarations += " } from './apiTypes.ts'\n"
|
||||||
fmt.Println("tsApiDeclarations", TSApiDeclarations)
|
|
||||||
tmp += TSApiDeclarations
|
tmp += TSApiDeclarations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imports := ""
|
imports := ""
|
||||||
for f := range tsSourcesData.Pakages[p].Imports {
|
for f := range tsSourcesData.Pakages[p].Imports {
|
||||||
imports += "import * as " + f + " from './" + f + ".ts'\n"
|
imports += "import type * as " + f + " from './" + f + ".ts'\n"
|
||||||
}
|
}
|
||||||
tmp += imports
|
tmp += imports
|
||||||
tmp += source
|
tmp += source
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { api } from "./api";
|
||||||
|
import type { Nullable } from "./apiTypes.ts";
|
||||||
|
import type * as users from "./users.ts";
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/admin/users/:uuid/block; name=blockUser; method=PUT; request=admin.BlockUserRequest; response=users.User
|
||||||
|
// internal/admin/routes.go Line: 16
|
||||||
|
export const blockUser = async (
|
||||||
|
data: BlockUserRequest,
|
||||||
|
): Promise<{ data: users.User; error: Nullable<string> }> => {
|
||||||
|
return (await api.PUT("/admin/users/:uuid/block", data)) as {
|
||||||
|
data: users.User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=admin.ListUsersRequest; response=users.[]User
|
||||||
|
// internal/admin/routes.go Line: 12
|
||||||
|
export const listUsers = async (
|
||||||
|
data: ListUsersRequest,
|
||||||
|
): Promise<{ data: users.User[]; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/admin/users", data)) as {
|
||||||
|
data: users.User[];
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface BlockUserRequest {
|
||||||
|
action: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListUsersRequest {
|
||||||
|
page: number;
|
||||||
|
pageSize: number;
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
// This file was generated by github.com/millevolte/ts-rpc
|
// This file was generated by github.com/millevolte/ts-rpc
|
||||||
//
|
//
|
||||||
// Apr 05, 2026 17:08:11 UTC
|
// Apr 15, 2026 18:49:19 UTC
|
||||||
//
|
//
|
||||||
|
|
||||||
export interface ApiRestResponse {
|
export interface ApiRestResponse {
|
||||||
|
|
@ -273,341 +273,4 @@ export default class Api {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const api = new Api("http://localhost:3000");
|
export const api = new Api("http://localhost:3000");
|
||||||
|
|
||||||
// Global Declarations
|
|
||||||
export type Nullable<T> = T | null;
|
|
||||||
|
|
||||||
export type Record<K extends string | number | symbol, T> = { [P in K]: T };
|
|
||||||
|
|
||||||
//
|
|
||||||
// package model
|
|
||||||
//
|
|
||||||
|
|
||||||
export interface RefreshRequest {
|
|
||||||
refresh_token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TokenPair {
|
|
||||||
access_token: string;
|
|
||||||
refresh_token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ForgotPasswordRequest {
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LoginRequest {
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ResetPasswordRequest {
|
|
||||||
token: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// package controllers
|
|
||||||
//
|
|
||||||
|
|
||||||
export interface BlockUserRequest {
|
|
||||||
action: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ListUsersRequest {
|
|
||||||
page: number;
|
|
||||||
pageSize: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SimpleResponse {
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateUserRequest {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
roles: models.UserRoles;
|
|
||||||
status: models.UserStatus;
|
|
||||||
types: models.UserTypes;
|
|
||||||
avatar: Nullable<string>;
|
|
||||||
details: Nullable<models.UserDetailsShort>;
|
|
||||||
preferences: Nullable<models.UserPreferencesShort>;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// package routes
|
|
||||||
//
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET; response=string
|
|
||||||
// internal/http/routes/system_routes.go Line: 37
|
|
||||||
export const metrics = async (): Promise<{
|
|
||||||
data: string;
|
|
||||||
error: Nullable<string>;
|
|
||||||
}> => {
|
|
||||||
return (await api.GET("/metrics")) as {
|
|
||||||
data: string;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/maildebug; name=mailDebug; method=GET; response=routes.[]MailDebugItem
|
|
||||||
// internal/http/routes/system_routes.go Line: 48
|
|
||||||
export const mailDebug = async (): Promise<{
|
|
||||||
data: MailDebugItem[];
|
|
||||||
error: Nullable<string>;
|
|
||||||
}> => {
|
|
||||||
return (await api.GET("/maildebug")) as {
|
|
||||||
data: MailDebugItem[];
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=models.UserProfile
|
|
||||||
// internal/http/routes/user_routes.go Line: 13
|
|
||||||
export const getUser = async (
|
|
||||||
uuid: string,
|
|
||||||
): Promise<{ data: UserProfile; error: Nullable<string> }> => {
|
|
||||||
return (await api.GET(`/users/${uuid}`)) as {
|
|
||||||
data: UserProfile;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=controllers.UpdateUserRequest; response=models.UserProfile
|
|
||||||
// internal/http/routes/user_routes.go Line: 19
|
|
||||||
|
|
||||||
export const updateUser = async (
|
|
||||||
data: UpdateUserRequest,
|
|
||||||
): Promise<{ data: UserProfile; error: Nullable<string> }> => {
|
|
||||||
return (await api.PUT("/users/:uuid", data)) as {
|
|
||||||
data: UserProfile;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=controllers.ListUsersRequest; response=models.[]UserShort
|
|
||||||
// internal/http/routes/admin_routes.go Line: 12
|
|
||||||
|
|
||||||
export const listUsers = async (
|
|
||||||
data: ListUsersRequest,
|
|
||||||
): Promise<{ data: UserShort[]; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/admin/users", data)) as {
|
|
||||||
data: UserShort[];
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/admin/users/:uuid/block; name=blockUser; method=PUT; request=controllers.BlockUserRequest; response=models.UserShort
|
|
||||||
// internal/http/routes/admin_routes.go Line: 15
|
|
||||||
|
|
||||||
export const blockUser = async (
|
|
||||||
data: BlockUserRequest,
|
|
||||||
): Promise<{ data: UserShort; error: Nullable<string> }> => {
|
|
||||||
return (await api.PUT("/admin/users/:uuid/block", data)) as {
|
|
||||||
data: UserShort;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=models.UserCreateInput; response=models.UserProfile
|
|
||||||
// internal/http/routes/user_routes.go Line: 16
|
|
||||||
|
|
||||||
export const createUser = async (
|
|
||||||
data: UserCreateInput,
|
|
||||||
): Promise<{ data: UserProfile; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/users", data)) as {
|
|
||||||
data: UserProfile;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/users/:uuid; name=deleteUser; method=DELETE; response=controllers.SimpleResponse
|
|
||||||
// internal/http/routes/user_routes.go Line: 22
|
|
||||||
|
|
||||||
export const deleteUser = async (
|
|
||||||
uuid: string,
|
|
||||||
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
|
|
||||||
return (await api.DELETE(`/users/${uuid}`)) as {
|
|
||||||
data: SimpleResponse;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/health; name=health; method=GET; response=string
|
|
||||||
// internal/http/routes/system_routes.go Line: 34
|
|
||||||
export const health = async (): Promise<{
|
|
||||||
data: string;
|
|
||||||
error: Nullable<string>;
|
|
||||||
}> => {
|
|
||||||
return (await api.GET("/health")) as {
|
|
||||||
data: string;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface FormRequest {
|
|
||||||
req: string;
|
|
||||||
count: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FormResponse {
|
|
||||||
test: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MailDebugItem {
|
|
||||||
name: string;
|
|
||||||
content: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// package endpoint
|
|
||||||
//
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=model.ForgotPasswordRequest; response=controllers.SimpleResponse
|
|
||||||
// internal/auth/endpoint/routes.go Line: 34
|
|
||||||
|
|
||||||
export const forgotPassword = async (
|
|
||||||
data: ForgotPasswordRequest,
|
|
||||||
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/password/forgot", data)) as {
|
|
||||||
data: SimpleResponse;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST; request=model.ResetPasswordRequest; response=controllers.SimpleResponse
|
|
||||||
// internal/auth/endpoint/routes.go Line: 37
|
|
||||||
|
|
||||||
export const resetPassword = async (
|
|
||||||
data: ResetPasswordRequest,
|
|
||||||
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/password/reset", data)) as {
|
|
||||||
data: SimpleResponse;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/password/valid; name=validToken; method=POST; request=string; response=controllers.SimpleResponse
|
|
||||||
// internal/auth/endpoint/routes.go Line: 40
|
|
||||||
|
|
||||||
export const validToken = async (
|
|
||||||
data: string,
|
|
||||||
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/password/valid", data)) as {
|
|
||||||
data: SimpleResponse;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/login; name=login; method=POST; request=model.LoginRequest; response=model.TokenPair
|
|
||||||
// internal/auth/endpoint/routes.go Line: 22
|
|
||||||
|
|
||||||
export const login = async (
|
|
||||||
data: LoginRequest,
|
|
||||||
): Promise<{ data: TokenPair; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/login", data)) as {
|
|
||||||
data: TokenPair;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=model.RefreshRequest; response=model.TokenPair
|
|
||||||
// internal/auth/endpoint/routes.go Line: 25
|
|
||||||
|
|
||||||
export const refresh = async (
|
|
||||||
data: RefreshRequest,
|
|
||||||
): Promise<{ data: TokenPair; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/refresh", data)) as {
|
|
||||||
data: TokenPair;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/me; name=me; method=GET; response=models.UserShort
|
|
||||||
// internal/auth/endpoint/routes.go Line: 28
|
|
||||||
export const me = async (): Promise<{
|
|
||||||
data: UserShort;
|
|
||||||
error: Nullable<string>;
|
|
||||||
}> => {
|
|
||||||
return (await api.GET("/auth/me")) as {
|
|
||||||
data: UserShort;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=models.UserCreateInput; response=models.UserShort
|
|
||||||
// internal/auth/endpoint/routes.go Line: 31
|
|
||||||
|
|
||||||
export const register = async (
|
|
||||||
data: UserCreateInput,
|
|
||||||
): Promise<{ data: UserShort; error: Nullable<string> }> => {
|
|
||||||
return (await api.POST("/auth/register", data)) as {
|
|
||||||
data: UserShort;
|
|
||||||
error: Nullable<string>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// package models
|
|
||||||
//
|
|
||||||
|
|
||||||
export interface UserCreateInput {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
roles: UserRoles;
|
|
||||||
status: UserStatus;
|
|
||||||
types: UserTypes;
|
|
||||||
avatar: Nullable<string>;
|
|
||||||
details: Nullable<UserDetailsShort>;
|
|
||||||
preferences: Nullable<UserPreferencesShort>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserDetailsShort {
|
|
||||||
title: string;
|
|
||||||
firstName: string;
|
|
||||||
lastName: string;
|
|
||||||
address: string;
|
|
||||||
city: string;
|
|
||||||
zipCode: string;
|
|
||||||
country: string;
|
|
||||||
phone: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserPreferencesShort {
|
|
||||||
useIdle: boolean;
|
|
||||||
idleTimeout: number;
|
|
||||||
useIdlePassword: boolean;
|
|
||||||
idlePin: string;
|
|
||||||
useDirectLogin: boolean;
|
|
||||||
useQuadcodeLogin: boolean;
|
|
||||||
sendNoticesMail: boolean;
|
|
||||||
language: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserShort {
|
|
||||||
email: string;
|
|
||||||
name: string;
|
|
||||||
roles: UserRoles;
|
|
||||||
status: UserStatus;
|
|
||||||
uuid: string;
|
|
||||||
details: Nullable<UserDetailsShort>;
|
|
||||||
preferences: Nullable<UserPreferencesShort>;
|
|
||||||
avatar: Nullable<string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UserRoles = string[];
|
|
||||||
|
|
||||||
export type UserStatus = (typeof EnumUserStatus)[keyof typeof EnumUserStatus];
|
|
||||||
|
|
||||||
export type UserTypes = string[];
|
|
||||||
|
|
||||||
export type UsersShort = UserShort[];
|
|
||||||
|
|
||||||
export const EnumUserStatus = {
|
|
||||||
UserStatusPending: "pending",
|
|
||||||
UserStatusActive: "active",
|
|
||||||
UserStatusDisabled: "disabled",
|
|
||||||
} as const;
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
// API Declarations
|
||||||
|
export type Nullable<T> = T | null;
|
||||||
|
|
||||||
|
export type Record<K extends string | number | symbol, T> = { [P in K]: T };
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
export interface SimpleResponse {
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { api } from "./api";
|
||||||
|
import type { Nullable } from "./apiTypes.ts";
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/health; name=health; method=GET; response=string
|
||||||
|
// internal/systemUtils/routes.go Line: 38
|
||||||
|
export const health = async (): Promise<{
|
||||||
|
data: string;
|
||||||
|
error: Nullable<string>;
|
||||||
|
}> => {
|
||||||
|
return (await api.GET("/health")) as {
|
||||||
|
data: string;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET; response=string
|
||||||
|
// internal/systemUtils/routes.go Line: 41
|
||||||
|
export const metrics = async (): Promise<{
|
||||||
|
data: string;
|
||||||
|
error: Nullable<string>;
|
||||||
|
}> => {
|
||||||
|
return (await api.GET("/metrics")) as {
|
||||||
|
data: string;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/maildebug; name=mailDebug; method=GET; response=[]MailDebugItem
|
||||||
|
// internal/systemUtils/routes.go Line: 53
|
||||||
|
export const mailDebug = async (): Promise<{
|
||||||
|
data: MailDebugItem[];
|
||||||
|
error: Nullable<string>;
|
||||||
|
}> => {
|
||||||
|
return (await api.GET("/maildebug")) as {
|
||||||
|
data: MailDebugItem[];
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface MailDebugItem {
|
||||||
|
name: string;
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface TokenPair {
|
||||||
|
access_token: string;
|
||||||
|
refresh_token: string;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,239 @@
|
||||||
|
import { api } from "./api";
|
||||||
|
import type { Nullable } from "./apiTypes.ts";
|
||||||
|
import type * as tokens from "./tokens.ts";
|
||||||
|
import type * as responses from "./responses.ts";
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/password/valid; name=validToken; method=POST; request=string; response=responses.SimpleResponse
|
||||||
|
// internal/user/routes.go Line: 58
|
||||||
|
export const validToken = async (
|
||||||
|
data: string,
|
||||||
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/password/valid", data)) as {
|
||||||
|
data: responses.SimpleResponse;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=users.UpdateUserRequest; response=users.User
|
||||||
|
// internal/user/routes.go Line: 33
|
||||||
|
export const updateUser = async (
|
||||||
|
data: UpdateUserRequest,
|
||||||
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
return (await api.PUT("/users/:uuid", data)) as {
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/users/:uuid; name=deleteUser; method=DELETE; response=responses.SimpleResponse
|
||||||
|
// internal/user/routes.go Line: 36
|
||||||
|
export const deleteUser = async (
|
||||||
|
uuid: string,
|
||||||
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
|
return (await api.DELETE(`/users/${uuid}`)) as {
|
||||||
|
data: responses.SimpleResponse;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=users.UserCreateRequest; response=users.User
|
||||||
|
// internal/user/routes.go Line: 49
|
||||||
|
export const register = async (
|
||||||
|
data: UserCreateRequest,
|
||||||
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/register", data)) as {
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=users.ForgotPasswordRequest; response=responses.SimpleResponse
|
||||||
|
// internal/user/routes.go Line: 52
|
||||||
|
export const forgotPassword = async (
|
||||||
|
data: ForgotPasswordRequest,
|
||||||
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/password/forgot", data)) as {
|
||||||
|
data: responses.SimpleResponse;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=users.UserCreateRequest; response=users.User
|
||||||
|
// internal/user/routes.go Line: 30
|
||||||
|
export const createUser = async (
|
||||||
|
data: UserCreateRequest,
|
||||||
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/users", data)) as {
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=users.RefreshRequest; response=tokens.TokenPair
|
||||||
|
// internal/user/routes.go Line: 46
|
||||||
|
export const refresh = async (
|
||||||
|
data: RefreshRequest,
|
||||||
|
): Promise<{ data: tokens.TokenPair; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/refresh", data)) as {
|
||||||
|
data: tokens.TokenPair;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=users.User
|
||||||
|
// internal/user/routes.go Line: 27
|
||||||
|
export const getUser = async (
|
||||||
|
uuid: string,
|
||||||
|
): Promise<{ data: User; error: Nullable<string> }> => {
|
||||||
|
return (await api.GET(`/users/${uuid}`)) as {
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/me; name=me; method=GET; response=users.User
|
||||||
|
// internal/user/routes.go Line: 39
|
||||||
|
export const me = async (): Promise<{
|
||||||
|
data: User;
|
||||||
|
error: Nullable<string>;
|
||||||
|
}> => {
|
||||||
|
return (await api.GET("/auth/me")) as { data: User; error: Nullable<string> };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/login; name=login; method=POST; request=users.LoginRequest; response=tokens.TokenPair
|
||||||
|
// internal/user/routes.go Line: 43
|
||||||
|
export const login = async (
|
||||||
|
data: LoginRequest,
|
||||||
|
): Promise<{ data: tokens.TokenPair; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/login", data)) as {
|
||||||
|
data: tokens.TokenPair;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST; request=users.ResetPasswordRequest; response=responses.SimpleResponse
|
||||||
|
// internal/user/routes.go Line: 55
|
||||||
|
export const resetPassword = async (
|
||||||
|
data: ResetPasswordRequest,
|
||||||
|
): Promise<{ data: responses.SimpleResponse; error: Nullable<string> }> => {
|
||||||
|
return (await api.POST("/auth/password/reset", data)) as {
|
||||||
|
data: responses.SimpleResponse;
|
||||||
|
error: Nullable<string>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface LoginRequest {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RefreshRequest {
|
||||||
|
refresh_token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
id: number;
|
||||||
|
email: string;
|
||||||
|
name: string;
|
||||||
|
roles: UserRoles;
|
||||||
|
types: UserTypes;
|
||||||
|
status: UserStatus;
|
||||||
|
activatedAt: Date;
|
||||||
|
uuid: string;
|
||||||
|
details: Nullable<UserDetails>;
|
||||||
|
preferences: Nullable<UserPreferences>;
|
||||||
|
avatar: Nullable<string>;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ForgotPasswordRequest {
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResetPasswordRequest {
|
||||||
|
token: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateUserRequest {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
roles: UserRoles;
|
||||||
|
status: UserStatus;
|
||||||
|
types: UserTypes;
|
||||||
|
avatar: Nullable<string>;
|
||||||
|
details: Nullable<UserDetails>;
|
||||||
|
preferences: Nullable<UserPreferences>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserCreateRequest {
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
roles: UserRoles;
|
||||||
|
status: UserStatus;
|
||||||
|
types: UserTypes;
|
||||||
|
avatar: Nullable<string>;
|
||||||
|
details: Nullable<UserDetails>;
|
||||||
|
preferences: Nullable<UserPreferences>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserDetails {
|
||||||
|
id: number;
|
||||||
|
userId: number;
|
||||||
|
title: string;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
address: string;
|
||||||
|
city: string;
|
||||||
|
zipCode: string;
|
||||||
|
country: string;
|
||||||
|
phone: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserPreferences {
|
||||||
|
id: number;
|
||||||
|
userId: number;
|
||||||
|
useIdle: boolean;
|
||||||
|
idleTimeout: number;
|
||||||
|
useIdlePassword: boolean;
|
||||||
|
idlePin: string;
|
||||||
|
useDirectLogin: boolean;
|
||||||
|
useQuadcodeLogin: boolean;
|
||||||
|
sendNoticesMail: boolean;
|
||||||
|
language: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfile {
|
||||||
|
id: number;
|
||||||
|
email: string;
|
||||||
|
name: string;
|
||||||
|
roles: UserRoles;
|
||||||
|
types: UserTypes;
|
||||||
|
status: UserStatus;
|
||||||
|
activatedAt: Date;
|
||||||
|
uuid: string;
|
||||||
|
details: Nullable<UserDetails>;
|
||||||
|
preferences: Nullable<UserPreferences>;
|
||||||
|
avatar: Nullable<string>;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UserTypes = string[];
|
||||||
|
|
||||||
|
export type UserRoles = string[];
|
||||||
|
|
||||||
|
export type UserStatus = (typeof EnumUserStatus)[keyof typeof EnumUserStatus];
|
||||||
|
|
||||||
|
export const EnumUserStatus = {
|
||||||
|
UserStatusPending: "pending",
|
||||||
|
UserStatusActive: "active",
|
||||||
|
UserStatusDisabled: "disabled",
|
||||||
|
} as const;
|
||||||
|
|
@ -108,14 +108,14 @@ import { computed, onMounted, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import LogoUrl from 'src/assets/home/logo.png';
|
import LogoUrl from 'src/assets/home/logo.png';
|
||||||
import { me, type UserShort } from 'src/api/api';
|
import { me, type User } from 'src/api/users';
|
||||||
import { usePreferencesStore, type LanguageCode } from 'src/stores/preferences-store';
|
import { usePreferencesStore, type LanguageCode } from 'src/stores/preferences-store';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const preferencesStore = usePreferencesStore();
|
const preferencesStore = usePreferencesStore();
|
||||||
const currentUser = ref<UserShort | null>(null);
|
const currentUser = ref<User | null>(null);
|
||||||
const model = computed({
|
const model = computed({
|
||||||
get: () => preferencesStore.language,
|
get: () => preferencesStore.language,
|
||||||
set: (language: LanguageCode) => {
|
set: (language: LanguageCode) => {
|
||||||
|
|
|
||||||
|
|
@ -509,21 +509,24 @@ import VuePictureCropper from 'vue-picture-cropper';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
blockUser,
|
blockUser,
|
||||||
createUser,
|
|
||||||
getUser,
|
|
||||||
listUsers,
|
listUsers,
|
||||||
updateUser,
|
|
||||||
EnumUserStatus,
|
|
||||||
type BlockUserRequest,
|
type BlockUserRequest,
|
||||||
type ListUsersRequest,
|
type ListUsersRequest,
|
||||||
|
}from 'src/api/admin';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createUser,
|
||||||
|
getUser,
|
||||||
|
updateUser,
|
||||||
|
EnumUserStatus,
|
||||||
type UpdateUserRequest,
|
type UpdateUserRequest,
|
||||||
type UserCreateInput,
|
type UserCreateRequest,
|
||||||
type UserDetailsShort,
|
|
||||||
type UserPreferencesShort,
|
|
||||||
type UserProfile,
|
type UserProfile,
|
||||||
type UserShort,
|
type User,
|
||||||
type UserStatus,
|
type UserStatus,
|
||||||
} from 'src/api/api';
|
type UserDetails,
|
||||||
|
type UserPreferences,
|
||||||
|
} from 'src/api/users';
|
||||||
|
|
||||||
type DialogMode = 'create' | 'edit' | 'view';
|
type DialogMode = 'create' | 'edit' | 'view';
|
||||||
|
|
||||||
|
|
@ -536,8 +539,8 @@ interface UserFormState {
|
||||||
roles: string[];
|
roles: string[];
|
||||||
types: string[];
|
types: string[];
|
||||||
avatar: string;
|
avatar: string;
|
||||||
details: UserDetailsShort;
|
details: UserDetails;
|
||||||
preferences: UserPreferencesShort;
|
preferences: UserPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
@ -550,7 +553,7 @@ const avatarDialogOpen = ref(false);
|
||||||
const dialogMode = ref<DialogMode>('create');
|
const dialogMode = ref<DialogMode>('create');
|
||||||
const editorTab = ref<'account' | 'details' | 'preferences'>('account');
|
const editorTab = ref<'account' | 'details' | 'preferences'>('account');
|
||||||
const filter = ref('');
|
const filter = ref('');
|
||||||
const rows = ref<UserShort[]>([]);
|
const rows = ref<User[]>([]);
|
||||||
const detailsEnabled = ref(true);
|
const detailsEnabled = ref(true);
|
||||||
const preferencesEnabled = ref(true);
|
const preferencesEnabled = ref(true);
|
||||||
const passwordDialogUserUuid = ref('');
|
const passwordDialogUserUuid = ref('');
|
||||||
|
|
@ -593,7 +596,7 @@ const avatarPresetMode = {
|
||||||
height: 320,
|
height: 320,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const columns: QTableColumn<UserShort>[] = [
|
const columns: QTableColumn<User>[] = [
|
||||||
{ name: 'name', label: 'Utente', field: 'name', align: 'left', sortable: true },
|
{ name: 'name', label: 'Utente', field: 'name', align: 'left', sortable: true },
|
||||||
{ name: 'status', label: 'Status', field: 'status', align: 'left', sortable: true },
|
{ name: 'status', label: 'Status', field: 'status', align: 'left', sortable: true },
|
||||||
{ name: 'roles', label: 'Roles', field: (row) => row.roles.join(', '), align: 'left' },
|
{ name: 'roles', label: 'Roles', field: (row) => row.roles.join(', '), align: 'left' },
|
||||||
|
|
@ -608,7 +611,7 @@ const passwordForm = reactive({
|
||||||
confirmPassword: '',
|
confirmPassword: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const payload = computed<UserCreateInput | UpdateUserRequest>(() => ({
|
const payload = computed<UserCreateRequest | UpdateUserRequest>(() => ({
|
||||||
name: form.name.trim(),
|
name: form.name.trim(),
|
||||||
email: form.email.trim(),
|
email: form.email.trim(),
|
||||||
password: dialogMode.value === 'create' ? form.password : '',
|
password: dialogMode.value === 'create' ? form.password : '',
|
||||||
|
|
@ -643,6 +646,10 @@ function emptyForm(): UserFormState {
|
||||||
zipCode: '',
|
zipCode: '',
|
||||||
country: '',
|
country: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
|
id: 0,
|
||||||
|
userId: 0,
|
||||||
|
createdAt: undefined,
|
||||||
|
updatedAt: undefined
|
||||||
},
|
},
|
||||||
preferences: {
|
preferences: {
|
||||||
useIdle: false,
|
useIdle: false,
|
||||||
|
|
@ -653,6 +660,10 @@ function emptyForm(): UserFormState {
|
||||||
useQuadcodeLogin: false,
|
useQuadcodeLogin: false,
|
||||||
sendNoticesMail: false,
|
sendNoticesMail: false,
|
||||||
language: 'it',
|
language: 'it',
|
||||||
|
id: 0,
|
||||||
|
userId: 0,
|
||||||
|
createdAt: undefined,
|
||||||
|
updatedAt: undefined
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -955,7 +966,7 @@ async function saveUser(): Promise<void> {
|
||||||
saving.value = true;
|
saving.value = true;
|
||||||
try {
|
try {
|
||||||
if (dialogMode.value === 'create') {
|
if (dialogMode.value === 'create') {
|
||||||
const response = await createUser(payload.value as UserCreateInput);
|
const response = await createUser(payload.value as UserCreateRequest);
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
throw new Error(response.error);
|
throw new Error(response.error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -124,16 +124,22 @@
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import {
|
import {
|
||||||
forgotPassword,
|
forgotPassword,
|
||||||
health,
|
|
||||||
listUsers,
|
|
||||||
login,
|
login,
|
||||||
me,
|
me,
|
||||||
metrics,
|
|
||||||
refresh,
|
refresh,
|
||||||
register,
|
register,
|
||||||
resetPassword,
|
resetPassword,
|
||||||
} from 'src/api/api';
|
type UserCreateRequest,
|
||||||
import type { UserCreateInput } from 'src/api/api';
|
} from 'src/api/users';
|
||||||
|
|
||||||
|
import {
|
||||||
|
health,
|
||||||
|
metrics,
|
||||||
|
} from 'src/api/systemUtils';
|
||||||
|
|
||||||
|
import {
|
||||||
|
listUsers,
|
||||||
|
} from 'src/api/admin';
|
||||||
|
|
||||||
type Method = 'GET' | 'POST';
|
type Method = 'GET' | 'POST';
|
||||||
type FieldType = 'text' | 'password' | 'number' | 'textarea';
|
type FieldType = 'text' | 'password' | 'number' | 'textarea';
|
||||||
|
|
@ -385,7 +391,7 @@ const endpoints: EndpointConfig[] = [
|
||||||
details: '',
|
details: '',
|
||||||
preferences: '',
|
preferences: '',
|
||||||
},
|
},
|
||||||
call: (payload) => register(payload as UserCreateInput),
|
call: (payload) => register(payload as UserCreateRequest),
|
||||||
buildPayload: (form) => ({
|
buildPayload: (form) => ({
|
||||||
name: String(form.name ?? ''),
|
name: String(form.name ?? ''),
|
||||||
email: String(form.email ?? ''),
|
email: String(form.email ?? ''),
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { login } from 'src/api/api';
|
import { login } from 'src/api/users';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { mailDebug, type MailDebugItem } from 'src/api/api';
|
import { mailDebug, type MailDebugItem } from 'src/api/systemUtils';
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { forgotPassword } from 'src/api/api';
|
import { forgotPassword } from 'src/api/users';
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { resetPassword } from 'src/api/api';
|
import { resetPassword } from 'src/api/users';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
|
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { EnumUserStatus, register, type UserCreateInput } from 'src/api/api';
|
import { EnumUserStatus, register, type UserCreateRequest } from 'src/api/users';
|
||||||
|
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
@ -107,7 +107,7 @@ async function submit(): Promise<void> {
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const payload: UserCreateInput = {
|
const payload: UserCreateRequest = {
|
||||||
name: `${form.firstName.trim()} ${form.lastName.trim()}`.trim(),
|
name: `${form.firstName.trim()} ${form.lastName.trim()}`.trim(),
|
||||||
email: form.email.trim(),
|
email: form.email.trim(),
|
||||||
password: form.password,
|
password: form.password,
|
||||||
|
|
@ -124,6 +124,10 @@ async function submit(): Promise<void> {
|
||||||
zipCode: '',
|
zipCode: '',
|
||||||
country: '',
|
country: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
|
id: 0,
|
||||||
|
userId: 0,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date(),
|
||||||
},
|
},
|
||||||
preferences: null,
|
preferences: null,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue