chore: better service method types based on `paths` object
continuous-integration/drone/pr Build is passing Details

Addresses #3199
This commit is contained in:
WofWca 2023-03-22 19:33:22 +04:00
parent 96e2c81b7e
commit 058951f1fd
35 changed files with 336 additions and 215 deletions

View File

@ -6,7 +6,7 @@ import AbstractModel from '@/models/abstractModel'
import type {IAbstract} from '@/modelTypes/IAbstract'
import type {Right} from '@/constants/rights'
interface Paths {
interface PathsAll {
create : string
get : string
getAll : string
@ -14,6 +14,7 @@ interface Paths {
delete : string
reset?: string
}
type PathsGeneric = Partial<PathsAll>;
function convertObject(o: Record<string, unknown>) {
if (o instanceof Date) {
@ -40,7 +41,39 @@ function prepareParams(params: Record<string, unknown | unknown[]>) {
return objectToSnakeCase(params)
}
export default abstract class AbstractService<Model extends IAbstract = IAbstract> {
type VarsFromPathTemplate<P extends string> = P extends `${string}{${infer FirstKey}}${infer Rest}`
? [FirstKey, ...VarsFromPathTemplate<Rest>]
: [];
/**
* @example
* type T = ReplacerDictFromPath<'/teams/{teamId}/members/{username}'>;
* const dict: T = {
* teamId: 1,
* username: 'demo',
* }
*/
type ReplacerDictFromPath<P extends string> = Record<
VarsFromPathTemplate<P>[number],
string | number
>
type ReplacerDictOrNeverFromPath<P extends string | undefined | null> =
P extends string
? ReplacerDictFromPath<P>
: never;
/**
* Prohibit the use of `string` as values, i.e. require a more concrete type:
* string literal or template literal.
*/
type EnsureConst<T extends Record<string, string>> = {
[P in keyof T]: string extends T[P] ? never : T[P];
};
export default abstract class AbstractService<
Model extends IAbstract = IAbstract,
// Not sure if the default value makes sense here. Put it only because a non-optional
// param can't go after an optional one.
P extends PathsGeneric = EnsureConst<PathsGeneric>,
> {
/////////////////////////////
// Initial variable definitions
@ -49,13 +82,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
http
loading = false
uploadProgress = 0
paths: Paths = {
create: '',
get: '',
getAll: '',
update: '',
delete: '',
}
paths: P
// This contains the total number of pages and the number of results for the current page
totalPages = 0
resultCount = 0
@ -68,7 +95,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
* The abstract constructor.
* @param [paths] An object with all paths.
*/
constructor(paths : Partial<Paths> = {}) {
constructor(paths : EnsureConst<P> = ({} as const)) {
this.http = AuthenticatedHTTPFactory()
// Set the interceptors to process every request
@ -96,7 +123,7 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
return config
})
Object.assign(this.paths, paths)
this.paths = { ...paths } as P
}
/**
@ -267,8 +294,13 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
* @param model The model to use. The request path is built using the values from the model.
* @param params Optional query parameters
*/
get(model : Model, params = {}) {
if (this.paths.get === '') {
// TODO refactor: if `paths.get` is undefined, it's better if `get()` method
// is undefined as well, instead of just returning `never`.
get<T extends P['get']>(
model : ReplacerDictOrNeverFromPath<T>,
params = {},
): Promise<T extends string ? Model : never> {
if (!this.paths.get) {
throw new Error('This model is not able to get data.')
}
@ -279,7 +311,11 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
* This is a more abstract implementation which only does a get request.
* Services which need more flexibility can use this.
*/
async getM(url : string, model : Model = new AbstractModel({}), params: Record<string, unknown> = {}) {
async getM<T extends string>(
url : T,
model : ReplacerDictFromPath<T>,
params: Record<string, unknown> = {},
) {
const cancel = this.setLoading()
model = this.beforeGet(model)
@ -312,8 +348,14 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
* @param params Optional query parameters
* @param page The page to get
*/
async getAll(model : Model = new AbstractModel({}), params = {}, page = 1): Promise<Model[]> {
if (this.paths.getAll === '') {
// TODO refactor: ensure that if `ReplacerDict` is an empty object type then you
// can't pass an arbitrary object literal as `model`.
async getAll<T extends P['getAll']>(
model : ReplacerDictOrNeverFromPath<T> = new AbstractModel({}),
params = {},
page = 1,
): Promise<T extends string ? Model[] : never> {
if (!this.paths.getAll) {
throw new Error('This model is not able to get data.')
}
@ -342,8 +384,10 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
* Performs a put request to the url specified before
* @returns {Promise<any | never>}
*/
async create(model : Model) {
if (this.paths.create === '') {
async create<T extends P['create']>(
model : Model & ReplacerDictOrNeverFromPath<T>,
): Promise<T extends string ? Model : never> {
if (!this.paths.create) {
throw new Error('This model is not able to create data.')
}
@ -384,8 +428,10 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
/**
* Performs a post request to the update url
*/
update(model : Model) {
if (this.paths.update === '') {
update<T extends P['update']>(
model : Model & ReplacerDictOrNeverFromPath<T>,
): Promise<T extends string ? Model : never> {
if (!this.paths.update) {
throw new Error('This model is not able to update data.')
}
@ -396,8 +442,10 @@ export default abstract class AbstractService<Model extends IAbstract = IAbstrac
/**
* Performs a delete request to the update url
*/
async delete(model : Model) {
if (this.paths.delete === '') {
async delete<T extends P['delete']>(
model : ReplacerDictOrNeverFromPath<T>,
) {
if (!this.paths.delete) {
throw new Error('This model is not able to delete data.')
}

View File

@ -5,13 +5,15 @@ import type { IAttachment } from '@/modelTypes/IAttachment'
import {downloadBlob} from '@/helpers/downloadBlob'
export default class AttachmentService extends AbstractService<IAttachment> {
const paths = {
create: '/tasks/{taskId}/attachments',
getAll: '/tasks/{taskId}/attachments',
delete: '/tasks/{taskId}/attachments/{id}',
} as const
export default class AttachmentService extends AbstractService<IAttachment, typeof paths> {
constructor() {
super({
create: '/tasks/{taskId}/attachments',
getAll: '/tasks/{taskId}/attachments',
delete: '/tasks/{taskId}/attachments/{id}',
})
super(paths)
}
processModel(model: IAttachment) {

View File

@ -2,13 +2,15 @@ import AbstractService from './abstractService'
import AvatarModel from '@/models/avatar'
import type { IAvatar } from '@/modelTypes/IAvatar'
export default class AvatarService extends AbstractService<IAvatar> {
const paths = {
get: '/user/settings/avatar',
update: '/user/settings/avatar',
create: '/user/settings/avatar/upload',
} as const
export default class AvatarService extends AbstractService<IAvatar, typeof paths> {
constructor() {
super({
get: '/user/settings/avatar',
update: '/user/settings/avatar',
create: '/user/settings/avatar/upload',
})
super(paths)
}
modelFactory(data: Partial<IAvatar>) {

View File

@ -3,12 +3,14 @@ import BackgroundImageModel from '../models/backgroundImage'
import ProjectModel from '@/models/project'
import type { IBackgroundImage } from '@/modelTypes/IBackgroundImage'
export default class BackgroundUnsplashService extends AbstractService<IBackgroundImage> {
const paths = {
getAll: '/backgrounds/unsplash/search',
update: '/projects/{projectId}/backgrounds/unsplash',
} as const
export default class BackgroundUnsplashService extends AbstractService<IBackgroundImage, typeof paths> {
constructor() {
super({
getAll: '/backgrounds/unsplash/search',
update: '/projects/{projectId}/backgrounds/unsplash',
})
super(paths)
}
modelFactory(data: Partial<IBackgroundImage>) {

View File

@ -4,11 +4,13 @@ import ProjectModel from '@/models/project'
import type { IProject } from '@/modelTypes/IProject'
import type { IFile } from '@/modelTypes/IFile'
export default class BackgroundUploadService extends AbstractService {
const paths = {
create: '/projects/{projectId}/backgrounds/upload',
} as const
export default class BackgroundUploadService extends AbstractService<IProject, typeof paths> {
constructor() {
super({
create: '/projects/{projectId}/backgrounds/upload',
})
super(paths)
}
useCreateInterceptor() {

View File

@ -3,14 +3,16 @@ import BucketModel from '../models/bucket'
import TaskService from '@/services/task'
import type { IBucket } from '@/modelTypes/IBucket'
export default class BucketService extends AbstractService<IBucket> {
const paths = {
getAll: '/projects/{projectId}/buckets',
create: '/projects/{projectId}/buckets',
update: '/projects/{projectId}/buckets/{id}',
delete: '/projects/{projectId}/buckets/{id}',
} as const
export default class BucketService extends AbstractService<IBucket, typeof paths> {
constructor() {
super({
getAll: '/projects/{projectId}/buckets',
create: '/projects/{projectId}/buckets',
update: '/projects/{projectId}/buckets/{id}',
delete: '/projects/{projectId}/buckets/{id}',
})
super(paths)
}
modelFactory(data: Partial<IBucket>) {

View File

@ -2,13 +2,15 @@ import CaldavTokenModel from '@/models/caldavToken'
import type {ICaldavToken} from '@/modelTypes/ICaldavToken'
import AbstractService from './abstractService'
export default class CaldavTokenService extends AbstractService<ICaldavToken> {
const paths = {
getAll: '/user/settings/token/caldav',
create: '/user/settings/token/caldav',
delete: '/user/settings/token/caldav/{id}',
} as const
export default class CaldavTokenService extends AbstractService<ICaldavToken, typeof paths> {
constructor() {
super({
getAll: '/user/settings/token/caldav',
create: '/user/settings/token/caldav',
delete: '/user/settings/token/caldav/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -1,9 +1,12 @@
import type { IAbstract } from '@/modelTypes/IAbstract'
import AbstractService from './abstractService'
export default class EmailUpdateService extends AbstractService {
const paths = {
update: '/user/settings/email',
} as const
export default class EmailUpdateService extends AbstractService<IAbstract, typeof paths> {
constructor() {
super({
update: '/user/settings/email',
})
super(paths)
}
}

View File

@ -3,15 +3,17 @@ import LabelModel from '@/models/label'
import type {ILabel} from '@/modelTypes/ILabel'
import {colorFromHex} from '@/helpers/color/colorFromHex'
export default class LabelService extends AbstractService<ILabel> {
const paths = {
create: '/labels',
getAll: '/labels',
get: '/labels/{id}',
update: '/labels/{id}',
delete: '/labels/{id}',
} as const
export default class LabelService extends AbstractService<ILabel, typeof paths> {
constructor() {
super({
create: '/labels',
getAll: '/labels',
get: '/labels/{id}',
update: '/labels/{id}',
delete: '/labels/{id}',
})
super(paths)
}
processModel(label) {

View File

@ -2,13 +2,15 @@ import AbstractService from './abstractService'
import LabelTask from '@/models/labelTask'
import type {ILabelTask} from '@/modelTypes/ILabelTask'
export default class LabelTaskService extends AbstractService<ILabelTask> {
const paths = {
create: '/tasks/{taskId}/labels',
getAll: '/tasks/{taskId}/labels',
delete: '/tasks/{taskId}/labels/{labelId}',
} as const
export default class LabelTaskService extends AbstractService<ILabelTask, typeof paths> {
constructor() {
super({
create: '/tasks/{taskId}/labels',
getAll: '/tasks/{taskId}/labels',
delete: '/tasks/{taskId}/labels/{labelId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,14 +2,16 @@ import AbstractService from './abstractService'
import LinkShareModel from '@/models/linkShare'
import type {ILinkShare} from '@/modelTypes/ILinkShare'
export default class LinkShareService extends AbstractService<ILinkShare> {
const paths = {
getAll: '/projects/{projectId}/shares',
get: '/projects/{projectId}/shares/{id}',
create: '/projects/{projectId}/shares',
delete: '/projects/{projectId}/shares/{id}',
} as const
export default class LinkShareService extends AbstractService<ILinkShare, typeof paths> {
constructor() {
super({
getAll: '/projects/{projectId}/shares',
get: '/projects/{projectId}/shares/{id}',
create: '/projects/{projectId}/shares',
delete: '/projects/{projectId}/shares/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,14 +2,18 @@ import AbstractService from '../abstractService'
export type MigrationConfig = { code: string }
type Paths = {
update: `/migration/${string}/migrate`
}
// This service builds on top of the abstract service and basically just hides away method names.
// It enables migration services to be created with minimal overhead and even better method names.
export default class AbstractMigrationService extends AbstractService<MigrationConfig> {
export default class AbstractMigrationService extends AbstractService<MigrationConfig, Paths> {
serviceUrlKey = ''
constructor(serviceUrlKey: string) {
super({
update: '/migration/' + serviceUrlKey + '/migrate',
update: `/migration/${serviceUrlKey}/migrate`,
})
this.serviceUrlKey = serviceUrlKey
}

View File

@ -3,15 +3,17 @@ import NamespaceModel from '../models/namespace'
import type {INamespace} from '@/modelTypes/INamespace'
import {colorFromHex} from '@/helpers/color/colorFromHex'
export default class NamespaceService extends AbstractService<INamespace> {
const paths = {
create: '/namespaces',
get: '/namespaces/{id}',
getAll: '/namespaces',
update: '/namespaces/{id}',
delete: '/namespaces/{id}',
} as const
export default class NamespaceService extends AbstractService<INamespace, typeof paths> {
constructor() {
super({
create: '/namespaces',
get: '/namespaces/{id}',
getAll: '/namespaces',
update: '/namespaces/{id}',
delete: '/namespaces/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,12 +2,14 @@ import AbstractService from '@/services/abstractService'
import NotificationModel from '@/models/notification'
import type {INotification} from '@/modelTypes/INotification'
export default class NotificationService extends AbstractService<INotification> {
const paths = {
getAll: '/notifications',
update: '/notifications/{id}',
} as const
export default class NotificationService extends AbstractService<INotification, typeof paths> {
constructor() {
super({
getAll: '/notifications',
update: '/notifications/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,10 +2,11 @@ import AbstractService from './abstractService'
import PasswordResetModel from '@/models/passwordReset'
import type {IPasswordReset} from '@/modelTypes/IPasswordReset'
export default class PasswordResetService extends AbstractService<IPasswordReset> {
const paths = {} as const
export default class PasswordResetService extends AbstractService<IPasswordReset, typeof paths> {
constructor() {
super({})
super(paths)
this.paths = {
reset: '/user/password/reset',
requestReset: '/user/password/token',

View File

@ -1,10 +1,12 @@
import AbstractService from './abstractService'
import type {IPasswordUpdate} from '@/modelTypes/IPasswordUpdate'
export default class PasswordUpdateService extends AbstractService<IPasswordUpdate> {
const paths = {
update: '/user/password',
} as const
export default class PasswordUpdateService extends AbstractService<IPasswordUpdate, typeof paths> {
constructor() {
super({
update: '/user/password',
})
super(paths)
}
}

View File

@ -4,15 +4,17 @@ import type {IProject} from '@/modelTypes/IProject'
import TaskService from './task'
import {colorFromHex} from '@/helpers/color/colorFromHex'
export default class ProjectService extends AbstractService<IProject> {
const paths = {
create: '/namespaces/{namespaceId}/projects',
get: '/projects/{id}',
getAll: '/projects',
update: '/projects/{id}',
delete: '/projects/{id}',
} as const
export default class ProjectService extends AbstractService<IProject, typeof paths> {
constructor() {
super({
create: '/namespaces/{namespaceId}/projects',
get: '/projects/{id}',
getAll: '/projects',
update: '/projects/{id}',
delete: '/projects/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,11 +2,13 @@ import AbstractService from './abstractService'
import projectDuplicateModel from '@/models/projectDuplicateModel'
import type {IProjectDuplicate} from '@/modelTypes/IProjectDuplicate'
export default class ProjectDuplicateService extends AbstractService<IProjectDuplicate> {
const paths = {
create: '/projects/{projectId}/duplicate',
} as const
export default class ProjectDuplicateService extends AbstractService<IProjectDuplicate, typeof paths> {
constructor() {
super({
create: '/projects/{projectId}/duplicate',
})
super(paths)
}
beforeCreate(model) {

View File

@ -1,11 +1,13 @@
import AbstractService from './abstractService'
import UserModel from '../models/user'
export default class ProjectUserService extends AbstractService {
const paths = {
getAll: '/projects/{projectId}/projectusers',
} as const
export default class ProjectUserService extends AbstractService<UserModel, typeof paths> {
constructor() {
super({
getAll: '/projects/{projectId}/projectusers',
})
super(paths)
}
modelFactory(data) {

View File

@ -43,14 +43,16 @@ export function isSavedFilter(project: IProject) {
return getSavedFilterIdFromProjectId(project.id) > 0
}
export default class SavedFilterService extends AbstractService<ISavedFilter> {
const paths = {
get: '/filters/{id}',
create: '/filters',
update: '/filters/{id}',
delete: '/filters/{id}',
} as const
export default class SavedFilterService extends AbstractService<ISavedFilter, typeof paths> {
constructor() {
super({
get: '/filters/{id}',
create: '/filters',
update: '/filters/{id}',
delete: '/filters/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,12 +2,14 @@ import AbstractService from '@/services/abstractService'
import SubscriptionModel from '@/models/subscription'
import type {ISubscription} from '@/modelTypes/ISubscription'
export default class SubscriptionService extends AbstractService<ISubscription> {
const paths = {
create: '/subscriptions/{entity}/{entityId}',
delete: '/subscriptions/{entity}/{entityId}',
} as const
export default class SubscriptionService extends AbstractService<ISubscription, typeof paths> {
constructor() {
super({
create: '/subscriptions/{entity}/{entityId}',
delete: '/subscriptions/{entity}/{entityId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -15,15 +15,17 @@ const parseDate = date => {
return null
}
export default class TaskService extends AbstractService<ITask> {
const paths = {
create: '/projects/{projectId}',
getAll: '/tasks/all',
get: '/tasks/{id}',
update: '/tasks/{id}',
delete: '/tasks/{id}',
} as const
export default class TaskService extends AbstractService<ITask, typeof paths> {
constructor() {
super({
create: '/projects/{projectId}',
getAll: '/tasks/all',
get: '/tasks/{id}',
update: '/tasks/{id}',
delete: '/tasks/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,12 +2,14 @@ import AbstractService from './abstractService'
import TaskAssigneeModel from '@/models/taskAssignee'
import type {ITaskAssignee} from '@/modelTypes/ITaskAssignee'
export default class TaskAssigneeService extends AbstractService<ITaskAssignee> {
const paths = {
create: '/tasks/{taskId}/assignees',
delete: '/tasks/{taskId}/assignees/{userId}',
} as const
export default class TaskAssigneeService extends AbstractService<ITaskAssignee, typeof paths> {
constructor() {
super({
create: '/tasks/{taskId}/assignees',
delete: '/tasks/{taskId}/assignees/{userId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -14,11 +14,13 @@ export interface GetAllTasksParams {
filter_include_nulls: boolean,
}
export default class TaskCollectionService extends AbstractService<ITask> {
const paths = {
getAll: '/projects/{projectId}/tasks',
} as const
export default class TaskCollectionService extends AbstractService<ITask, typeof paths> {
constructor() {
super({
getAll: '/projects/{projectId}/tasks',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,15 +2,17 @@ import AbstractService from './abstractService'
import TaskCommentModel from '@/models/taskComment'
import type {ITaskComment} from '@/modelTypes/ITaskComment'
export default class TaskCommentService extends AbstractService<ITaskComment> {
const paths = {
create: '/tasks/{taskId}/comments',
getAll: '/tasks/{taskId}/comments',
get: '/tasks/{taskId}/comments/{id}',
update: '/tasks/{taskId}/comments/{id}',
delete: '/tasks/{taskId}/comments/{id}',
} as const
export default class TaskCommentService extends AbstractService<ITaskComment, typeof paths> {
constructor() {
super({
create: '/tasks/{taskId}/comments',
getAll: '/tasks/{taskId}/comments',
get: '/tasks/{taskId}/comments/{id}',
update: '/tasks/{taskId}/comments/{id}',
delete: '/tasks/{taskId}/comments/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,12 +2,14 @@ import AbstractService from './abstractService'
import TaskRelationModel from '@/models/taskRelation'
import type {ITaskRelation} from '@/modelTypes/ITaskRelation'
export default class TaskRelationService extends AbstractService<ITaskRelation> {
const paths = {
create: '/tasks/{taskId}/relations',
delete: '/tasks/{taskId}/relations/{relationKind}/{otherTaskId}',
} as const
export default class TaskRelationService extends AbstractService<ITaskRelation, typeof paths> {
constructor() {
super({
create: '/tasks/{taskId}/relations',
delete: '/tasks/{taskId}/relations/{relationKind}/{otherTaskId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,15 +2,17 @@ import AbstractService from './abstractService'
import TeamModel from '@/models/team'
import type {ITeam} from '@/modelTypes/ITeam'
export default class TeamService extends AbstractService<ITeam> {
const paths = {
create: '/teams',
get: '/teams/{id}',
getAll: '/teams',
update: '/teams/{id}',
delete: '/teams/{id}',
} as const
export default class TeamService extends AbstractService<ITeam, typeof paths> {
constructor() {
super({
create: '/teams',
get: '/teams/{id}',
getAll: '/teams',
update: '/teams/{id}',
delete: '/teams/{id}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,13 +2,15 @@ import AbstractService from './abstractService'
import TeamMemberModel from '@/models/teamMember'
import type {ITeamMember} from '@/modelTypes/ITeamMember'
export default class TeamMemberService extends AbstractService<ITeamMember> {
const paths = {
create: '/teams/{teamId}/members',
delete: '/teams/{teamId}/members/{username}',
update: '/teams/{teamId}/members/{username}/admin',
} as const
export default class TeamMemberService extends AbstractService<ITeamMember, typeof paths> {
constructor() {
super({
create: '/teams/{teamId}/members',
delete: '/teams/{teamId}/members/{username}',
update: '/teams/{teamId}/members/{username}/admin',
})
super(paths)
}
modelFactory(data) {

View File

@ -3,14 +3,16 @@ import TeamNamespaceModel from '@/models/teamNamespace'
import type {ITeamNamespace} from '@/modelTypes/ITeamNamespace'
import TeamModel from '@/models/team'
export default class TeamNamespaceService extends AbstractService<ITeamNamespace> {
const paths = {
create: '/namespaces/{namespaceId}/teams',
getAll: '/namespaces/{namespaceId}/teams',
update: '/namespaces/{namespaceId}/teams/{teamId}',
delete: '/namespaces/{namespaceId}/teams/{teamId}',
} as const
export default class TeamNamespaceService extends AbstractService<ITeamNamespace, typeof paths> {
constructor() {
super({
create: '/namespaces/{namespaceId}/teams',
getAll: '/namespaces/{namespaceId}/teams',
update: '/namespaces/{namespaceId}/teams/{teamId}',
delete: '/namespaces/{namespaceId}/teams/{teamId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -3,14 +3,16 @@ import TeamProjectModel from '@/models/teamProject'
import type {ITeamProject} from '@/modelTypes/ITeamProject'
import TeamModel from '@/models/team'
export default class TeamProjectService extends AbstractService<ITeamProject> {
const paths = {
create: '/projects/{projectId}/teams',
getAll: '/projects/{projectId}/teams',
update: '/projects/{projectId}/teams/{teamId}',
delete: '/projects/{projectId}/teams/{teamId}',
} as const
export default class TeamProjectService extends AbstractService<ITeamProject, typeof paths> {
constructor() {
super({
create: '/projects/{projectId}/teams',
getAll: '/projects/{projectId}/teams',
update: '/projects/{projectId}/teams/{teamId}',
delete: '/projects/{projectId}/teams/{teamId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -2,13 +2,18 @@ import AbstractService from './abstractService'
import TotpModel from '@/models/totp'
import type {ITotp} from '@/modelTypes/ITotp'
export default class TotpService extends AbstractService<ITotp> {
urlPrefix = '/user/settings/totp'
const urlPrefix = '/user/settings/totp' as const
type Paths = {
get: typeof urlPrefix
}
export default class TotpService extends AbstractService<ITotp, Paths> {
urlPrefix = urlPrefix
constructor() {
super({})
this.paths.get = this.urlPrefix
super({
get: urlPrefix,
})
}
modelFactory(data) {

View File

@ -2,11 +2,13 @@ import AbstractService from './abstractService'
import UserModel from '@/models/user'
import type {IUser} from '@/modelTypes/IUser'
export default class UserService extends AbstractService<IUser> {
const paths = {
getAll: '/users',
} as const
export default class UserService extends AbstractService<IUser, typeof paths> {
constructor() {
super({
getAll: '/users',
})
super(paths)
}
modelFactory(data) {

View File

@ -3,14 +3,16 @@ import UserNamespaceModel from '@/models/userNamespace'
import type {IUserNamespace} from '@/modelTypes/IUserNamespace'
import UserModel from '@/models/user'
export default class UserNamespaceService extends AbstractService<IUserNamespace> {
const paths = {
create: '/namespaces/{namespaceId}/users',
getAll: '/namespaces/{namespaceId}/users',
update: '/namespaces/{namespaceId}/users/{userId}',
delete: '/namespaces/{namespaceId}/users/{userId}',
} as const
export default class UserNamespaceService extends AbstractService<IUserNamespace, typeof paths> {
constructor() {
super({
create: '/namespaces/{namespaceId}/users',
getAll: '/namespaces/{namespaceId}/users',
update: '/namespaces/{namespaceId}/users/{userId}',
delete: '/namespaces/{namespaceId}/users/{userId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -3,14 +3,16 @@ import UserProjectModel from '@/models/userProject'
import type {IUserProject} from '@/modelTypes/IUserProject'
import UserModel from '@/models/user'
export default class UserProjectService extends AbstractService<IUserProject> {
const paths = {
create: '/projects/{projectId}/users',
getAll: '/projects/{projectId}/users',
update: '/projects/{projectId}/users/{userId}',
delete: '/projects/{projectId}/users/{userId}',
} as const
export default class UserProjectService extends AbstractService<IUserProject, typeof paths> {
constructor() {
super({
create: '/projects/{projectId}/users',
getAll: '/projects/{projectId}/users',
update: '/projects/{projectId}/users/{userId}',
delete: '/projects/{projectId}/users/{userId}',
})
super(paths)
}
modelFactory(data) {

View File

@ -1,10 +1,12 @@
import type {IUserSettings} from '@/modelTypes/IUserSettings'
import AbstractService from './abstractService'
export default class UserSettingsService extends AbstractService<IUserSettings> {
const paths = {
update: '/user/settings/general',
} as const
export default class UserSettingsService extends AbstractService<IUserSettings, typeof paths> {
constructor() {
super({
update: '/user/settings/general',
})
super(paths)
}
}