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
3 changes: 2 additions & 1 deletion TODOLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
- [x] 用户组
- [ ] 权限
- [x] 默认用户组
- [ ] 上传到指定Categroy
- [x] 上传到指定Categroy
- [x] 上传时追加Catogroy
- [ ] 整顿collectin info的goods 列表
- [ ] Token 使用日志显示
- [ ] Good 下载次数统计
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"author": "AryloYeung <arylo.open@gmail.com>",
"license": "MIT",
"devDependencies": {
"@nestjs/testing": "^4.5.1",
"@nestjs/testing": "4.5.2",
"@types/basic-auth": "^1.1.2",
"@types/bunyan": "^1.8.4",
"@types/connect-redis": "0.0.7",
Expand Down Expand Up @@ -67,8 +67,8 @@
"typescript": "^2.6.1"
},
"dependencies": {
"@nestjs/common": "^4.5.1",
"@nestjs/core": "^4.5.1",
"@nestjs/common": "4.5.2",
"@nestjs/core": "4.5.2",
"@nestjs/swagger": "^1.1.3",
"basic-auth": "^2.0.0",
"body-parser": "^1.18.2",
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { isDevelopment } from "./modules/common/helper/env";
const bootstrap = async () => {
const server = initExpress();

const app = await NestFactory.create(ApplicationModule, server, { });
const app = await NestFactory.create(ApplicationModule, server);
app.useGlobalPipes(new ValidationPipe());

if (isDevelopment) {
Expand Down
2 changes: 1 addition & 1 deletion src/models/Categroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { reduce, includes, difference } from "lodash";
import { MongoError } from "mongodb";
import Cache = require("schedule-cache");

const cache = Cache.create(`${Date.now()}${Math.random()}`);
export const cache = Cache.create(`${Date.now()}${Math.random()}`);

export const FLAG = "categories";
export type CategoryDoc = IDoc<ICategory>;
Expand Down
133 changes: 42 additions & 91 deletions src/models/Regexp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,37 @@ export const cache = Cache.create(`${Date.now()}${Math.random()}`);

const Definition: SchemaDefinition = {
name: { type: String, required: true, unique: true },
value: { type: String, required: true, unique: true },
value: { type: String, required: true },
link: {
type: SchemaTypes.ObjectId,
ref: CF
}
},
hidden: { type: Boolean, default: false }
};

export interface IRegexp extends IDocRaw {
name: string;
value: string;
link: ObjectId | ICategory;
hidden: boolean;
}

export interface IRegexpsRaw extends IRegexp {
link: ICategory;
}

export interface IRegexpDoc {
name: string;
value: string;
link?: ObjectId;
hidden?: boolean;
}

export type RegexpDoc = IDoc<IRegexp>;

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

// region static methods
RegexpSchema.static("countRegexps", async (perNum = 1) => {
const FLAG = `page_count_${perNum}`;
if (cache.get(FLAG)) {
return cache.get(FLAG);
}
cache.put(FLAG, Math.ceil((await Model.count({ }).exec()) / perNum));
return cache.get(FLAG);
});

RegexpSchema.static(
"addRegexp",
(name: string, value: string, link?: ObjectId) => {
Expand All @@ -52,66 +52,14 @@ RegexpSchema.static(
if (link) {
obj.link = link;
}
return Model.create(obj).then((result) => {
cache.clear();
return result;
});
return Model.create(obj);
}
);

RegexpSchema.static("removeRegexp", (id: ObjectId) => {
return Model.findByIdAndRemove(id).exec();
});

RegexpSchema.static("link", (id: ObjectId, linkId: ObjectId | false) => {
if (!linkId) {
return Model.findByIdAndUpdate(id, {
"$unset": { link: 0 }
}).exec();
} else {
return Model.findByIdAndUpdate(
id, { link: linkId }, { runValidators: true }
).exec();
}
});

RegexpSchema.static("list", (perNum = DEF_PER_COUNT, page = 1) => {
const FLAG_LIST = `list_${perNum}_${page}`;
if (cache.get(FLAG_LIST)) {
return cache.get(FLAG_LIST);
}
cache.put(
FLAG_LIST,
Model.find({ })
.skip((page - 1) * perNum).limit(perNum)
.populate("link").exec()
);
return cache.get(FLAG_LIST);
});

RegexpSchema.static("discern", (name: string) => {
const FLAG_DISCER_LIST = "discern";
let p: Promise<RegexpDoc[]>;
if (cache.get(FLAG_DISCER_LIST)) {
p = cache.get(FLAG_DISCER_LIST);
} else {
p = Model.find({ link: { $exists: true } })
.populate("link")
.exec();
cache.put(FLAG_DISCER_LIST, p);
}
return p.then((result) => {
const list = [ ];
result.forEach((item) => {
const obj = item.toObject();
const reg = new RegExp(obj.value);
if (reg.test(name)) {
list.push(obj.link);
}
});
return list;
});
});
// endregion static methods

export const FLAG = "regexps";
Expand All @@ -127,52 +75,35 @@ interface IRegexpModel<T extends RegexpDoc> extends M<T> {
* @return {Promise}
*/
removeRegexp(id: ObjectId): Promise<T>;
/**
* 规则关联
* @return {Promise}
*/
link(id: ObjectId, linkId: ObjectId | false): Promise<T>;
/**
* 规则列表
* @param perNum {number} 每页数量
* @param page {number} 页数
* @return {Promise}
*/
list(perNum?: number, page?: number): Promise<T[]>;
/**
* 根据规则进行识别
* @return {Promise}
*/
discern(filename: string): Promise<ICategory[]>;
/**
* 返回总页数
*/
countRegexps(perNum?: number): Promise<number>;
}

// region Validators
RegexpSchema.path("name").validate({
isAsync: true,
validator: async (value, respond) => {
const result = await Model.findOne({ name: value }).exec();
return !result;
return respond(!result);
},
message: "The name is exist"
});

RegexpSchema.path("value").validate({
isAsync: true,
validator: (value, respond) => {
return isRegExp(value);
return respond(isRegExp(value));
},
message: "The value isnt Regexp"
});

RegexpSchema.path("value").validate({
isAsync: true,
validator: async (value, respond) => {
const result = await Model.findOne({ value: value }).exec();
return !result;
validator: async function ValueExistValidator(value, respond) {
if (this && this.hidden) {
return respond(true);
}
const result =
await Model.findOne({ value: value, hidden: false }).exec();
return respond(!result);
},
message: "The value is exist"
});
Expand All @@ -181,10 +112,30 @@ RegexpSchema.path("link").validate({
isAsync: true,
validator: async (value, respond) => {
const result = await CM.findById(value).exec();
return !!result;
return respond(!!result);
},
message: "The Category ID is not exist"
});

RegexpSchema.path("hidden").validate({
isAsync: true,
validator: async function hiddenExistValidator(value, respond) {
if (!value) { // hidden === false
return respond(true);
}
if (!this.isNew) { // hidden === Old Value
const id = this.getQuery()._id;
const col = await Model.findById(id).exec();
if (col.toObject().hidden === value) {
return respond(true);
}
}
const result =
await Model.findOne({ value: this.value, hidden: value }).exec();
respond(result ? false : true);
},
message: "Only one active item with every value"
});
// endregion Validators

for (const method of MODIFY_MOTHODS) {
Expand Down
7 changes: 5 additions & 2 deletions src/modules/common/pipes/regexp-count-check.pipe.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import {
Pipe, PipeTransform, ArgumentMetadata, BadRequestException
} from "@nestjs/common";
import { Model as RegexpModel } from "@models/Regexp";
import { isArray } from "util";
import fs = require("fs-extra");
import { RegexpsService } from "@services/regexps";

type File = Express.Multer.File;

@Pipe()
export class RegexpCountCheckPipe implements PipeTransform<File | File[]> {

private readonly regexpSvr = new RegexpsService();

public async transform(value: File | File[], metadata: ArgumentMetadata) {
const regexpCount = (await RegexpModel.list()).length;
const regexpCount = await this.regexpSvr.count();
if (regexpCount !== 0) {
return value;
}
Expand Down
34 changes: 34 additions & 0 deletions src/modules/common/pipes/to-array.pipe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Pipe, PipeTransform, ArgumentMetadata } from "@nestjs/common";
import { isObject, isArray } from "util";

@Pipe()
export class ToArrayPipe implements PipeTransform<any> {

private readonly properties: string[];
constructor(...properties: string[]) {
this.properties = properties;
}

public async transform(value: any, metadata: ArgumentMetadata) {
if (!value || isArray(value)) {
return value;
}
if (this.properties.length === 0) {
if (isObject(value)) {
for (const key of Object.keys(value)) {
value[key] = [ value[key] ];
}
} else {
return [ value ];
}
} else {
for (const property of this.properties) {
if (!value[property] || isArray(value[property])) {
continue;
}
value[property] = [ value[property] ];
}
}
return value;
}
}
58 changes: 58 additions & 0 deletions src/modules/common/services/categories.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Component } from "@nestjs/common";
import { ObjectId } from "@models/common";
import { Model as CategoriesModel, cache } from "@models/Categroy";
import { isFunction } from "util";

interface IIdMap {
[parentId: string]: ObjectId[];
}

@Component()
export class CategoriesService {

private loadAndCache(FLAG: string, value: () => any, time?: number) {
const c = cache.get(FLAG);
if (c) {
return c;
}
const val = value();
cache.put(FLAG, val, time);
return val;
}

private async getIdMap() {
// { parentId: childrenIds }
const map: IIdMap = { };
const docs = await CategoriesModel.find().select("_id pid").exec();
docs.forEach((doc) => {
const category = doc.toObject();
let index;
if (!category.pid) {
index = "*";
} else {
index = category.pid.toString();
}
if (!map[index]) {
map[index] = [ ];
}
map[index].push(category._id.toString());
});
return map;
}

public async getChildrenIds(pid: ObjectId) {
const map: IIdMap = await this.loadAndCache("IdMap", () => {
return this.getIdMap();
});
const ids: ObjectId[] = [ ];
const childrenIds = map[pid.toString()];
if (childrenIds) {
ids.push(...childrenIds);
for (const id of childrenIds) {
ids.push(...(await this.getChildrenIds(id)));
}
}
return ids;
}

}
Loading