mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 04:10:32 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
77
packages/server/src/modules/Settings/ModelSettings.ts
Normal file
77
packages/server/src/modules/Settings/ModelSettings.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { get } from 'lodash';
|
||||
import {
|
||||
IModelMeta,
|
||||
IModelMetaField,
|
||||
IModelMetaDefaultSort,
|
||||
} from '@/interfaces/Model';
|
||||
|
||||
const defaultModelMeta = {
|
||||
fields: {},
|
||||
fields2: {},
|
||||
};
|
||||
|
||||
export const ModelSettings = (Model) =>
|
||||
class extends Model {
|
||||
/**
|
||||
*
|
||||
* @returns {IModelMeta}
|
||||
*/
|
||||
static get meta(): IModelMeta {
|
||||
throw new Error('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsed meta merged with default emta.
|
||||
* @returns {IModelMeta}
|
||||
*/
|
||||
static get parsedMeta(): IModelMeta {
|
||||
return {
|
||||
...defaultModelMeta,
|
||||
...this.meta,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve specific model field meta of the given field key.
|
||||
* @param {string} key
|
||||
* @returns {IModelMetaField}
|
||||
*/
|
||||
public static getField(key: string, attribute?: string): IModelMetaField {
|
||||
const field = get(this.meta.fields, key);
|
||||
|
||||
return attribute ? get(field, attribute) : field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specific model meta.
|
||||
* @param {string} key
|
||||
* @returns
|
||||
*/
|
||||
public static getMeta(key?: string) {
|
||||
return key ? get(this.parsedMeta, key) : this.parsedMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the model meta fields.
|
||||
* @return {{ [key: string]: IModelMetaField }}
|
||||
*/
|
||||
public static get fields(): { [key: string]: IModelMetaField } {
|
||||
return this.getMeta('fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the model default sort settings.
|
||||
* @return {IModelMetaDefaultSort}
|
||||
*/
|
||||
public static get defaultSort(): IModelMetaDefaultSort {
|
||||
return this.getMeta('defaultSort');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default filter field key.
|
||||
* @return {string}
|
||||
*/
|
||||
public static get defaultFilterField(): string {
|
||||
return this.getMeta('defaultFilterField');
|
||||
}
|
||||
};
|
||||
24
packages/server/src/modules/Settings/Settings.controller.ts
Normal file
24
packages/server/src/modules/Settings/Settings.controller.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Body, Controller, Get, Post, Put } from '@nestjs/common';
|
||||
import { SettingsApplicationService } from './SettingsApplication.service';
|
||||
import { ISettingsDTO } from './Settings.types';
|
||||
import { ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@Controller('settings')
|
||||
@ApiTags('settings')
|
||||
export class SettingsController {
|
||||
constructor(
|
||||
private readonly settingsApplicationService: SettingsApplicationService,
|
||||
) {}
|
||||
|
||||
@Put('')
|
||||
@ApiOperation({ summary: 'Save the given settings.' })
|
||||
async saveSettings(@Body() settingsDTO: ISettingsDTO) {
|
||||
return this.settingsApplicationService.saveSettings(settingsDTO);
|
||||
}
|
||||
|
||||
@Get('')
|
||||
@ApiOperation({ summary: 'Retrieves the settings.' })
|
||||
async getSettings() {
|
||||
return this.settingsApplicationService.getSettings();
|
||||
}
|
||||
}
|
||||
39
packages/server/src/modules/Settings/Settings.module.ts
Normal file
39
packages/server/src/modules/Settings/Settings.module.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { SettingRepository } from './repositories/Setting.repository';
|
||||
import { SettingsStore } from './SettingsStore';
|
||||
import { SettingsApplicationService } from './SettingsApplication.service';
|
||||
import { SaveSettingsService } from './commands/SaveSettings.service';
|
||||
import { SettingsController } from './Settings.controller';
|
||||
import { SETTINGS_PROVIDER } from './Settings.types';
|
||||
import { GetSettingsService } from './queries/GetSettings.service';
|
||||
import { ClsModule } from 'nestjs-cls';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [
|
||||
ClsModule.forFeatureAsync({
|
||||
provide: SETTINGS_PROVIDER,
|
||||
inject: [SettingRepository],
|
||||
useFactory: (settingRepository: SettingRepository) => async () => {
|
||||
const settings = new SettingsStore(settingRepository);
|
||||
|
||||
// Load settings from database.
|
||||
await settings.load();
|
||||
|
||||
return settings;
|
||||
},
|
||||
global: true,
|
||||
strict: true,
|
||||
type: 'function',
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
SettingRepository,
|
||||
GetSettingsService,
|
||||
SettingsApplicationService,
|
||||
SaveSettingsService,
|
||||
],
|
||||
exports: [SettingRepository],
|
||||
controllers: [SettingsController],
|
||||
})
|
||||
export class SettingsModule {}
|
||||
17
packages/server/src/modules/Settings/Settings.types.ts
Normal file
17
packages/server/src/modules/Settings/Settings.types.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
export interface IOptionDTO {
|
||||
key: string;
|
||||
value: string;
|
||||
group: string;
|
||||
}
|
||||
|
||||
export interface ISettingsDTO {
|
||||
options: IOptionDTO[];
|
||||
}
|
||||
|
||||
|
||||
export const SETTINGS_PROVIDER = 'SETTINGS';
|
||||
|
||||
export enum PreferencesAction {
|
||||
Mutate = 'Mutate'
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SaveSettingsService } from './commands/SaveSettings.service';
|
||||
import { ISettingsDTO } from './Settings.types';
|
||||
import { GetSettingsService } from './queries/GetSettings.service';
|
||||
|
||||
@Injectable()
|
||||
export class SettingsApplicationService {
|
||||
constructor(
|
||||
private readonly saveSettingsService: SaveSettingsService,
|
||||
private readonly getSettingsService: GetSettingsService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Saves the given settings.
|
||||
* @param {ISettingsDTO} settingsDTO
|
||||
*/
|
||||
public async saveSettings(settingsDTO: ISettingsDTO) {
|
||||
return this.saveSettingsService.saveSettings(settingsDTO);
|
||||
}
|
||||
|
||||
public async getSettings() {
|
||||
return this.getSettingsService.execute();
|
||||
}
|
||||
}
|
||||
17
packages/server/src/modules/Settings/SettingsStore.ts
Normal file
17
packages/server/src/modules/Settings/SettingsStore.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { EntityRepository } from '@/common/repository/EntityRepository';
|
||||
import { SettingsOptions } from '@/constants/metable-options';
|
||||
import { MetableDBStore } from '../Metable/MetableStoreDB';
|
||||
|
||||
export class SettingsStore extends MetableDBStore {
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {number} tenantId
|
||||
*/
|
||||
constructor(repository: EntityRepository, config: any = SettingsOptions) {
|
||||
super(config);
|
||||
|
||||
this.setExtraColumns(['group']);
|
||||
this.setRepository(repository);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { pick } from 'lodash';
|
||||
import { SettingsStore } from '../SettingsStore';
|
||||
import { IOptionDTO, ISettingsDTO, SETTINGS_PROVIDER } from '../Settings.types';
|
||||
|
||||
@Injectable()
|
||||
export class SaveSettingsService {
|
||||
constructor(
|
||||
@Inject(SETTINGS_PROVIDER)
|
||||
private readonly settingsStore: () => SettingsStore,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Saves the given settings.
|
||||
* @param {ISettingsDTO} settingsDTO
|
||||
*/
|
||||
public async saveSettings(settingsDTO: ISettingsDTO) {
|
||||
const settingsStore = await this.settingsStore();
|
||||
const notDefinedOptions = await this.validateNotDefinedSettings(
|
||||
settingsDTO.options,
|
||||
);
|
||||
const errorReasons: { type: string; code: number; keys: any[] }[] = [];
|
||||
if (notDefinedOptions.length) {
|
||||
errorReasons.push({
|
||||
type: 'OPTIONS.KEY.NOT.DEFINED',
|
||||
code: 200,
|
||||
keys: notDefinedOptions.map((o) => ({ ...pick(o, ['key', 'group']) })),
|
||||
});
|
||||
}
|
||||
if (errorReasons.length) {
|
||||
throw new Error(JSON.stringify(errorReasons));
|
||||
}
|
||||
settingsDTO.options.forEach((option: IOptionDTO) => {
|
||||
settingsStore.set({ ...option });
|
||||
});
|
||||
await settingsStore.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given options is defined or either not.
|
||||
* @param {Array} options
|
||||
* @return {Boolean}
|
||||
*/
|
||||
private async validateNotDefinedSettings(options) {
|
||||
const notDefined = [];
|
||||
const settingStore = await this.settingsStore();
|
||||
|
||||
options.forEach((option) => {
|
||||
const setting = settingStore.config.getMetaConfig(
|
||||
option.key,
|
||||
option.group,
|
||||
);
|
||||
|
||||
if (!setting) {
|
||||
notDefined.push(option);
|
||||
}
|
||||
});
|
||||
return notDefined;
|
||||
}
|
||||
}
|
||||
22
packages/server/src/modules/Settings/models/Setting.ts
Normal file
22
packages/server/src/modules/Settings/models/Setting.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { BaseModel } from '@/models/Model';
|
||||
// import TenantModel from 'models/TenantModel';
|
||||
// import Auth from './Auth';
|
||||
|
||||
export class Setting extends BaseModel {
|
||||
/**
|
||||
* Table name
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra metadata query to query with the current authenticate user.
|
||||
* @param {Object} query
|
||||
*/
|
||||
// static extraMetadataQuery(query) {
|
||||
// if (Auth.isLogged()) {
|
||||
// query.where('user_id', Auth.userId());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { SettingsStore } from '../SettingsStore';
|
||||
import { SETTINGS_PROVIDER } from '../Settings.types';
|
||||
|
||||
@Injectable()
|
||||
export class GetSettingsService {
|
||||
constructor(
|
||||
@Inject(SETTINGS_PROVIDER)
|
||||
private readonly settingsStore: () => SettingsStore,
|
||||
) {}
|
||||
|
||||
public async execute() {
|
||||
return (await this.settingsStore()).all();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { TenantRepository } from '@/common/repository/TenantRepository';
|
||||
import { TENANCY_DB_CONNECTION } from '@/modules/Tenancy/TenancyDB/TenancyDB.constants';
|
||||
import { Setting } from '../models/Setting';
|
||||
|
||||
@Injectable()
|
||||
export class SettingRepository extends TenantRepository {
|
||||
constructor(
|
||||
@Inject(TENANCY_DB_CONNECTION)
|
||||
private readonly tenantKnex: () => Knex,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the repository's model.
|
||||
*/
|
||||
get model(): typeof Setting {
|
||||
return Setting.bindKnex(this.tenantKnex());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user