Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"clean": "rimraf dist tmp",
"tsc": "tsc -P .",
"tsc": "tsc --locale zh-cn --pretty -P .",
"build": "npm run clean && npm run tsc",
"prestart": "npm run build",
"start-svr": "node -r tsconfig-paths/register index.js",
Expand Down
19 changes: 17 additions & 2 deletions src/models/System.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import { model, SchemaDefinition, Model as M } from "mongoose";
import { Base, IDoc, IDocRaw } from "./common";
import { Base, IDoc, IDocRaw, MODIFY_MOTHODS } from "./common";
import { config } from "@utils/config";
import keyv = require("keyv");

import { isTest } from "../modules/common/helper/env";

export const cache = new keyv({
uri: isTest ? undefined : config.redis.url,
namespace: "System"
});

const Definition: SchemaDefinition = {
key: { type: String, required: true },
Expand All @@ -13,8 +22,14 @@ export interface ISystem extends IDocRaw {

const SystemSchema = new Base(Definition).createSchema();

export const Flag = "sys";
export const Flag = "system";

export type SystemDoc = IDoc<ISystem>;

for (const method of MODIFY_MOTHODS) {
SystemSchema.post(method, () => {
cache.clear();
});
}

export const Model: M<SystemDoc> = model(Flag, SystemSchema);
46 changes: 42 additions & 4 deletions src/modules/common/services/base.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,26 @@ abstract class ModelService<D extends IDocRaw> {
}
}

protected runBeforeAll() {
return Promise.resolve(this.beforeAll());
}

protected beforeAll(): Promise<any> {
return Promise.resolve({ });
}

private runBeforeEach() {
return Promise.resolve(this.beforeEach());
}

protected beforeEach(): Promise<any> {
return Promise.resolve({ });
}

public async create(obj: object) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
try {
return await this.model.create(obj);
} catch (error) {
Expand All @@ -45,6 +63,8 @@ abstract class ModelService<D extends IDocRaw> {

public async delete(cond: object) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
try {
return await this.model.findOneAndRemove(cond).exec();
} catch (error) {
Expand All @@ -54,6 +74,8 @@ abstract class ModelService<D extends IDocRaw> {

public async deleteById(id: ObjectId) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
try {
return await this.model.findByIdAndRemove(id).exec();
} catch (error) {
Expand All @@ -65,6 +87,8 @@ abstract class ModelService<D extends IDocRaw> {
id: ObjectId, ctx: object, opts = this.DEF_UPDATE_OPTIONS
) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
const options = Object.assign({ }, this.DEF_UPDATE_OPTIONS, opts);
try {
return await this.model.update({ _id: id }, ctx, options).exec();
Expand All @@ -73,8 +97,10 @@ abstract class ModelService<D extends IDocRaw> {
}
}

protected find(cond: object, opts?: IGetOptions) {
protected async find(cond: object, opts?: IGetOptions) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
const p = this.model.find(cond);
return this.documentQueryProcess(p, opts).exec();
}
Expand All @@ -85,8 +111,10 @@ abstract class ModelService<D extends IDocRaw> {
});
}

protected findOne(cond: object, opts?: IGetOptions) {
protected async findOne(cond: object, opts?: IGetOptions) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
const p = this.model.findOne(cond);
return this.documentQueryProcess(p, opts).exec();
}
Expand All @@ -97,8 +125,10 @@ abstract class ModelService<D extends IDocRaw> {
});
}

protected findById(id: ObjectId, opts?: IGetOptions) {
protected async findById(id: ObjectId, opts?: IGetOptions) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
const p = this.model.findById(id);
return this.documentQueryProcess(p, opts).exec();
}
Expand All @@ -109,8 +139,10 @@ abstract class ModelService<D extends IDocRaw> {
});
}

protected total(cond: object = { }) {
protected async total(cond: object = { }) {
this.checkModel();
await this.beforeAll();
await this.beforeEach();
return this.model.count(cond).exec();
}

Expand Down Expand Up @@ -170,6 +202,12 @@ export abstract class BaseService<D extends IDocRaw = IDocRaw> extends ModelServ
return val;
}

protected runBeforeAll() {
return this.loadAndCache("_RunBeforeAll_", () => {
return super.runBeforeAll();
});
}

protected DEF_PER_OBJ = UtilService.DEF_PER_OBJ;

/**
Expand Down
15 changes: 8 additions & 7 deletions src/modules/common/services/regexps.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ export class RegexpsService extends BaseService<IRegexp> {
super();
this.setCache(cache);
this.setModel(RegexpsModel);
}

protected async beforeAll() {
// Update
setTimeout(() => {
// Add Hidden Label
RegexpsModel.update(
{ hidden: { $exists: false } }, { hidden: false },
{ multi: true }
).exec();
}, 3000);
// Add Hidden Label
await RegexpsModel.update(
{ hidden: { $exists: false } }, { hidden: false },
{ multi: true }
).exec();
}

/**
Expand Down
185 changes: 161 additions & 24 deletions src/modules/common/services/system.service.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,185 @@
import { Component, BadRequestException } from "@nestjs/common";
import { ObjectId } from "@models/common";
import { Model as SystemModel } from "@models/System";
import { Model as SystemModel, cache, ISystem } from "@models/System";
import { Model as UsergroupsModel } from "@models/Usergroup";
import { BaseService, IGetOptions } from "@services/base";
import { isURL } from "validator";
import * as typescript from "typescript";

import { systemLogger } from "../helper/log";

export enum DEFAULTS {
USERGROUP_FLAG = "DEFAULT_USERGROUP",
GOOD_URL_FLAG = "DEFAULT_GOOD_URL",
COLLECTION_URL_FLAG = "DEFAULT_COLLECTION_URL"
}

@Component()
export class SystemService {
export class SystemService extends BaseService<ISystem> {

constructor() {
super();
super.setCache(cache);
super.setModel(SystemModel);
}

private readonly DEFAULTS_MAPS = {
[DEFAULTS.USERGROUP_FLAG]: {
get: this.getDefaultUsergroup.name,
set: this.setDefaultUsergroup.name
},
[DEFAULTS.GOOD_URL_FLAG]: {
get: this.getDefaultGoodUrl.name,
set: this.setDefaultGoodUrl.name
},
[DEFAULTS.COLLECTION_URL_FLAG]: {
get: this.getDefaultCollectionUrl.name,
set: this.setDefaultCollectionUrl.name
}
};

private async checkUsergroupId(gid: ObjectId) {
const doc = await UsergroupsModel.findById(gid).exec();
/* istanbul ignore if */
if (!doc) {
throw new BadRequestException("The ID isnt a Usergroup ID");
}
return true;
}

private async checkUrl(url: string) {
if (!isURL(url)) {
throw new BadRequestException("URL Parse Fail");
}
return true;
}

public static DEFAULT_USERGROUP_FLAG = "DEFAULT_USERGROUP";
private setValue(key: string, value: string) {
try {
return SystemModel.findOneAndUpdate(
{ key: key }, { value: value }, { upsert: true }
).exec();
} catch (error) {
throw new BadRequestException(error.toString());
}
}

// region Default Usergroup ID
/**
* Get Default Usergroup ID
* @returns Usergroup ID
*/
public async getDefaultUsergroup(): Promise<ObjectId> {
let gid: any = await SystemModel.findOne({
key: SystemService.DEFAULT_USERGROUP_FLAG
}).exec();
/* istanbul ignore if */
if (!gid) {
systemLogger.warn(`Miss ${SystemService.DEFAULT_USERGROUP_FLAG}`);
gid = (await UsergroupsModel.findOne().exec())._id;
this.setDefaultUsergroup(gid);
}
return gid;
public getDefaultUsergroup() {
const FLAG = DEFAULTS.USERGROUP_FLAG;
return this.loadAndCache(FLAG, async () => {
const obj = await this.findObject({ key: FLAG });
let gid = obj.value;
/* istanbul ignore if */
if (!gid) {
systemLogger.warn(`Miss ${FLAG}`);
gid = (await UsergroupsModel.findOne().exec())._id;
this.setDefaultUsergroup(gid);
}
return gid;
});
}

/**
* Set Default Usergroup ID
* @param gid Usergroup ID
*/
public async setDefaultUsergroup(gid: ObjectId) {
const doc = await UsergroupsModel.findById(gid).exec();
/* istanbul ignore if */
if (!doc) {
throw new BadRequestException("The ID isnt a Usergroup ID");
await this.checkUsergroupId(gid);
return await this.setValue(DEFAULTS.USERGROUP_FLAG, gid.toString());
}
// endregion Default Usergroup ID

// region Default Urls
public getDefaultGoodUrl() {
const FLAG = DEFAULTS.GOOD_URL_FLAG;
return this.loadAndCache(FLAG, async () => {
const obj = await this.findObject({ key: FLAG });
return obj ? obj.value : "";
});
}

public setDefaultGoodUrl(url: string) {
if (url.length !== 0) {
if (!url.includes("{{gid}}")) {
throw new BadRequestException("Url must include `{{gid}}`");
}
this.checkUrl(url);
}
return this.setValue(DEFAULTS.GOOD_URL_FLAG, url);
}

public getDefaultCollectionUrl() {
const FLAG = DEFAULTS.COLLECTION_URL_FLAG;
return this.loadAndCache(FLAG, async () => {
const obj = await this.findObject({ key: FLAG });
return obj ? obj.value : "";
});
}

public setDefaultCollectionUrl(url: string) {
if (url.length !== 0) {
if (!url.includes("{{cid}}")) {
throw new BadRequestException("Url must include `{{cid}}`");
}
this.checkUrl(url);
}
return this.setValue(DEFAULTS.COLLECTION_URL_FLAG, url);
}
// endregion Default Urls

public get() {
return this.loadAndCache("get", async () => {
const objs: Array<{ key: string, value: string }> =
await this.findObjects({ }, { select: "key value -_id" });
const keys = objs.reduce((arr, item) => {
arr.push(item.key);
return arr;
}, [ ]);
if (objs.length === Object.keys(DEFAULTS).length) {
return objs;
}
for (const k of Object.keys(DEFAULTS)) {
if (!!~keys.indexOf(DEFAULTS[k])) {
continue;
}
const key = DEFAULTS[k];
objs.push({
key, value: await this[this.DEFAULTS_MAPS[key].get]()
});
}
return objs;
});
}

public set(key: DEFAULTS, value: any) {
switch (key) {
case DEFAULTS.USERGROUP_FLAG:
return this[this.DEFAULTS_MAPS[key].set](value);
case DEFAULTS.GOOD_URL_FLAG:
return this[this.DEFAULTS_MAPS[key].set](value);
case DEFAULTS.COLLECTION_URL_FLAG:
return this[this.DEFAULTS_MAPS[key].set](value);
}
return SystemModel
.findOneAndUpdate(
{ key: SystemService.DEFAULT_USERGROUP_FLAG }, { value: gid },
{ upsert: true }
)
.exec();
throw new BadRequestException("What do you want to set up");
}

public async info() {
return {
version: {
typescript: typescript.version,
api: require("../../../../package.json").version,
node: process.versions
},
env: {
system: process.env,
service: await this.get()
}
};
}

}
Loading