@domain.js/main 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.eslintrc.js +67 -0
  2. package/.husky/pre-commit +7 -0
  3. package/.test/test.ts +13 -0
  4. package/.test/test2.js +45 -0
  5. package/.travis.yml +8 -0
  6. package/.vscode/settings.json +3 -0
  7. package/README.md +6 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/index.js +221 -0
  10. package/dist/deps/aes/index.d.ts +4 -0
  11. package/dist/deps/aes/index.js +16 -0
  12. package/dist/deps/axios/index.d.ts +22 -0
  13. package/dist/deps/axios/index.js +56 -0
  14. package/dist/deps/cache/After.d.ts +3 -0
  15. package/dist/deps/cache/After.js +28 -0
  16. package/dist/deps/cache/Before.d.ts +4 -0
  17. package/dist/deps/cache/Before.js +16 -0
  18. package/dist/deps/cache/Define.d.ts +28 -0
  19. package/dist/deps/cache/Define.js +2 -0
  20. package/dist/deps/cache/index.d.ts +5 -0
  21. package/dist/deps/cache/index.js +50 -0
  22. package/dist/deps/checker/index.d.ts +11 -0
  23. package/dist/deps/checker/index.js +25 -0
  24. package/dist/deps/cia/errors.d.ts +6 -0
  25. package/dist/deps/cia/errors.js +36 -0
  26. package/dist/deps/cia/index.d.ts +53 -0
  27. package/dist/deps/cia/index.js +291 -0
  28. package/dist/deps/counter/index.d.ts +16 -0
  29. package/dist/deps/counter/index.js +16 -0
  30. package/dist/deps/cron/index.d.ts +33 -0
  31. package/dist/deps/cron/index.js +98 -0
  32. package/dist/deps/defines.d.ts +35 -0
  33. package/dist/deps/defines.js +36 -0
  34. package/dist/deps/graceful/index.d.ts +14 -0
  35. package/dist/deps/graceful/index.js +115 -0
  36. package/dist/deps/hash/index.d.ts +17 -0
  37. package/dist/deps/hash/index.js +17 -0
  38. package/dist/deps/logger/index.d.ts +14 -0
  39. package/dist/deps/logger/index.js +100 -0
  40. package/dist/deps/parallel/index.d.ts +34 -0
  41. package/dist/deps/parallel/index.js +93 -0
  42. package/dist/deps/redis/index.d.ts +6 -0
  43. package/dist/deps/redis/index.js +9 -0
  44. package/dist/deps/rest/Before.d.ts +5 -0
  45. package/dist/deps/rest/Before.js +9 -0
  46. package/dist/deps/rest/defines.d.ts +50 -0
  47. package/dist/deps/rest/defines.js +2 -0
  48. package/dist/deps/rest/index.d.ts +34 -0
  49. package/dist/deps/rest/index.js +79 -0
  50. package/dist/deps/rest/stats.d.ts +6 -0
  51. package/dist/deps/rest/stats.js +155 -0
  52. package/dist/deps/rest/utils.d.ts +23 -0
  53. package/dist/deps/rest/utils.js +419 -0
  54. package/dist/deps/schema/index.d.ts +11 -0
  55. package/dist/deps/schema/index.js +39 -0
  56. package/dist/deps/sequelize/index.d.ts +11 -0
  57. package/dist/deps/sequelize/index.js +17 -0
  58. package/dist/deps/signer/index.d.ts +20 -0
  59. package/dist/deps/signer/index.js +36 -0
  60. package/dist/dm/dm.d.ts +21 -0
  61. package/dist/dm/dm.js +57 -0
  62. package/dist/dm/index.d.ts +12 -0
  63. package/dist/dm/index.js +56 -0
  64. package/dist/http/index.d.ts +12 -0
  65. package/dist/http/index.js +34 -0
  66. package/dist/http/router.d.ts +23 -0
  67. package/dist/http/router.js +215 -0
  68. package/dist/http/utils.d.ts +29 -0
  69. package/dist/http/utils.js +185 -0
  70. package/dist/index.d.ts +65 -0
  71. package/dist/index.js +18 -0
  72. package/dist/utils/index.d.ts +36 -0
  73. package/dist/utils/index.js +84 -0
  74. package/jest.config.js +6 -0
  75. package/package.json +79 -0
  76. package/tsconfig.json +13 -0
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Deps = exports.Main = void 0;
4
+ const process = require("process");
5
+ function Graceful(info) {
6
+ let exiting = false; // 是否正在退出
7
+ const callbacks = [];
8
+ const counter = ((count = 0) => {
9
+ const decr = () => {
10
+ count -= 1;
11
+ };
12
+ const incr = () => {
13
+ count += 1;
14
+ };
15
+ const get = () => count;
16
+ return { incr, decr, get };
17
+ })(0);
18
+ const exitHandle = async () => {
19
+ info("process exiting start");
20
+ if (exiting) {
21
+ info("process exiting..., wait please");
22
+ return;
23
+ }
24
+ exiting = true;
25
+ // 执行事件回调函数
26
+ for (const cb of callbacks) {
27
+ info("process exiting, callback running");
28
+ counter.incr();
29
+ try {
30
+ const ret = cb();
31
+ if (ret && ret.then && ret.catch) {
32
+ ret
33
+ .then(() => {
34
+ counter.decr();
35
+ })
36
+ .catch(() => {
37
+ counter.decr();
38
+ });
39
+ }
40
+ else {
41
+ counter.decr();
42
+ }
43
+ }
44
+ catch (e) {
45
+ info("process exiting, callback running faid", e);
46
+ counter.decr();
47
+ }
48
+ }
49
+ // 每秒一次去检测是否所有函数执行都已完毕,可以退出
50
+ const timer = setInterval(() => {
51
+ info(`process exit check count: ${counter.get()}`);
52
+ if (counter.get() > 0)
53
+ return;
54
+ info("process exit check success, process exited");
55
+ clearInterval(timer);
56
+ process.exit(0);
57
+ }, 1000);
58
+ };
59
+ process.on("SIGTERM", exitHandle);
60
+ process.on("SIGINT", exitHandle);
61
+ /**
62
+ * addListen function be called when process exit
63
+ * @param listenner
64
+ */
65
+ const exit = (listenner) => {
66
+ callbacks.push(listenner);
67
+ };
68
+ function runner(fn) {
69
+ return (...args) => {
70
+ // 当前状态正在退出,阻止执行函数
71
+ if (exiting)
72
+ throw Error("process exiting...");
73
+ counter.incr();
74
+ try {
75
+ const res = fn(...args);
76
+ counter.decr();
77
+ return res;
78
+ }
79
+ catch (e) {
80
+ counter.decr();
81
+ throw e;
82
+ }
83
+ };
84
+ }
85
+ function runnerAsync(fn) {
86
+ return async (...args) => {
87
+ // 当前状态正在退出,阻止执行函数
88
+ if (exiting)
89
+ throw Error("process exiting");
90
+ counter.incr();
91
+ try {
92
+ const res = await fn(...args);
93
+ counter.decr();
94
+ return res;
95
+ }
96
+ catch (e) {
97
+ counter.decr();
98
+ throw e;
99
+ }
100
+ };
101
+ }
102
+ const enabled = () => Boolean(!exiting);
103
+ return {
104
+ runner,
105
+ runnerAsync,
106
+ enabled,
107
+ exit,
108
+ };
109
+ }
110
+ function Main(cnf, deps) {
111
+ const { logger } = deps;
112
+ return Graceful(logger.info);
113
+ }
114
+ exports.Main = Main;
115
+ exports.Deps = ["logger"];
@@ -0,0 +1,17 @@
1
+ import { Redis } from "ioredis";
2
+ interface Cnf {
3
+ hash: {
4
+ key: string;
5
+ };
6
+ }
7
+ interface Deps {
8
+ redis: Pick<Redis, "hget" | "hset" | "hdel" | "hincrby">;
9
+ }
10
+ export declare function Main(cnf: Cnf, deps: Deps): {
11
+ get: (key: string) => Promise<number>;
12
+ set: (key: string, value: string) => Promise<number>;
13
+ del: (key: string) => Promise<number>;
14
+ incr: (key: string, step?: number) => Promise<number>;
15
+ };
16
+ export declare const Deps: string[];
17
+ export {};
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Deps = exports.Main = void 0;
4
+ function Main(cnf, deps) {
5
+ const { hash: { key: REDIS_KEY }, } = cnf;
6
+ const { redis } = deps;
7
+ const get = async (key) => {
8
+ const num = await redis.hget(REDIS_KEY, key);
9
+ return Number(num) | 0;
10
+ };
11
+ const set = (key, value) => redis.hset(REDIS_KEY, key, value);
12
+ const del = (key) => redis.hdel(REDIS_KEY, key);
13
+ const incr = (key, step = 1) => redis.hincrby(REDIS_KEY, key, step);
14
+ return { get, set, del, incr };
15
+ }
16
+ exports.Main = Main;
17
+ exports.Deps = ["redis"];
@@ -0,0 +1,14 @@
1
+ interface Cnf {
2
+ logger: {
3
+ clientId: string;
4
+ errorLogPath: string;
5
+ infoLogPath: string;
6
+ ignoreErrors?: [string | number];
7
+ };
8
+ }
9
+ export declare function Main(cnf: Cnf): {
10
+ error: (e: any, extra?: any) => void;
11
+ info: (message: string, extra?: any) => void;
12
+ logger: <T extends (...args: any[]) => any>(fn: T, name: string, isAsync?: boolean, transform?: (x: ReturnType<T>) => any, errorHandler?: (e: any) => string, argsHandler?: (arg: Parameters<T>) => string) => T;
13
+ };
14
+ export {};
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Main = void 0;
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ const _ = require("lodash");
7
+ const uuid_1 = require("uuid");
8
+ const date = (offset = 0) => new Date(Date.now() + (offset | 0)).toISOString();
9
+ function Main(cnf) {
10
+ const { logger: { errorLogPath, infoLogPath, ignoreErrors, clientId }, } = cnf;
11
+ const makeDir = _.memoize((dir) => {
12
+ if (!fs.existsSync(dir))
13
+ fs.mkdirSync(dir);
14
+ });
15
+ const ignores = new Set(ignoreErrors);
16
+ const error = (e, extra) => {
17
+ if (!e) {
18
+ console.trace("Logger.error but error is null or undefined");
19
+ return;
20
+ }
21
+ const time = date();
22
+ const today = time.split("T")[0];
23
+ const code = e.code || "unknown";
24
+ // 忽略某些错误
25
+ if (ignores.has(code))
26
+ return;
27
+ const dir = path.resolve(errorLogPath, today);
28
+ makeDir(dir);
29
+ const file = path.resolve(dir, `${code}.err`);
30
+ const content = [time, clientId, e.message];
31
+ if (e.data)
32
+ content.push(JSON.stringify(e.data));
33
+ if (extra != null)
34
+ content.push(JSON.stringify(extra));
35
+ if (e.stack)
36
+ content.push(JSON.stringify(e.stack));
37
+ try {
38
+ fs.appendFileSync(file, `${content.join("\t")}\n`);
39
+ }
40
+ catch (err) {
41
+ console.error("Logger.error appendFileSync faid: %o", err);
42
+ }
43
+ };
44
+ const info = (message, extra) => {
45
+ const time = date();
46
+ const today = time.split("T")[0];
47
+ const dir = path.resolve(infoLogPath, today);
48
+ makeDir(dir);
49
+ const file = path.resolve(dir, "info.log");
50
+ const content = [time, clientId, message];
51
+ if (extra != null)
52
+ content.push(JSON.stringify(extra));
53
+ try {
54
+ fs.appendFileSync(file, `${content.join("\t")}\n`);
55
+ }
56
+ catch (e) {
57
+ console.error("Logger.info appendFileSync faid: %o", e);
58
+ }
59
+ };
60
+ const logger = (fn, name, isAsync = false, transform = (x) => x, errorHandler = (e) => (e instanceof Error ? e.message : ""), argsHandler = JSON.stringify) => {
61
+ if (isAsync) {
62
+ const handler = {
63
+ async apply(fn, me, args) {
64
+ const callId = (0, uuid_1.v4)();
65
+ try {
66
+ info(`Begin: ${name}\t${callId}\t${argsHandler(args)}`);
67
+ const startedAt = Date.now();
68
+ const res = await Reflect.apply(fn, me, args);
69
+ info(`Completed: ${name}\t${callId}\t${Date.now() - startedAt}ms\t${JSON.stringify(transform(res))}`);
70
+ return res;
71
+ }
72
+ catch (e) {
73
+ info(`Error: ${name}\t${callId}\t${errorHandler(e)}`, e instanceof Error && e.stack);
74
+ throw e;
75
+ }
76
+ },
77
+ };
78
+ return new Proxy(fn, handler);
79
+ }
80
+ const handler = {
81
+ apply(fn, me, args) {
82
+ const callId = (0, uuid_1.v4)();
83
+ try {
84
+ info(`Begin: ${name}\t${callId}\t${argsHandler(args)}`);
85
+ const startedAt = Date.now();
86
+ const res = Reflect.apply(fn, me, args);
87
+ info(`Completed: ${name}\t${callId}\t${Date.now() - startedAt}ms\t${JSON.stringify(transform(res))}`);
88
+ return res;
89
+ }
90
+ catch (e) {
91
+ info(`Error: ${name}\t${callId}\t${errorHandler(e)}`, e instanceof Error && e.stack);
92
+ throw e;
93
+ }
94
+ },
95
+ };
96
+ return new Proxy(fn, handler);
97
+ };
98
+ return { error, info, logger };
99
+ }
100
+ exports.Main = Main;
@@ -0,0 +1,34 @@
1
+ import { Redis } from "ioredis";
2
+ import { Main as Logger } from "../logger";
3
+ import { Main as Graceful } from "../graceful";
4
+ import * as utils from "../../utils";
5
+ interface Cnf {
6
+ parallel: {
7
+ key: string;
8
+ defaultErrorFn(path: string, minMS?: number): void;
9
+ };
10
+ }
11
+ interface Deps {
12
+ logger: {
13
+ info: ReturnType<typeof Logger>["info"];
14
+ error: ReturnType<typeof Logger>["error"];
15
+ };
16
+ graceful: {
17
+ exit: ReturnType<typeof Graceful>["exit"];
18
+ };
19
+ utils: {
20
+ sleep: typeof utils.sleep;
21
+ };
22
+ redis: Pick<Redis, "get" | "set" | "del" | "expire" | "exists">;
23
+ }
24
+ export interface Option {
25
+ path: string;
26
+ keyFn?(...args: any[]): string;
27
+ minMS?: number;
28
+ errorFn?: Function;
29
+ needWaitMS?: number;
30
+ neverReturn?: boolean;
31
+ }
32
+ export declare function Main(cnf: Cnf, deps: Deps): <F extends (...args: any[]) => any>(method: F, opt: Option) => (...args: Parameters<F>) => Promise<ReturnType<F>>;
33
+ export declare const Deps: string[];
34
+ export {};
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Deps = exports.Main = void 0;
4
+ const async = require("async");
5
+ function Main(cnf, deps) {
6
+ const { parallel: { key: KEY, defaultErrorFn }, } = cnf;
7
+ const { logger, graceful, utils: { sleep }, redis, } = deps;
8
+ // 存放当前处于执行中的 key
9
+ const doings = new Set();
10
+ let exiting = false;
11
+ // 退出时候做的处理
12
+ const onExit = async () => {
13
+ exiting = true;
14
+ logger.info("graceful.onExit parallel start", [...doings]);
15
+ await async.eachLimit([...doings], 10, async (key) => {
16
+ doings.delete(key);
17
+ await redis.del(key);
18
+ logger.info(`graceful.onExit parallel del: ${key}`);
19
+ });
20
+ logger.info("graceful.onExit parallel end");
21
+ };
22
+ const delay = async () => {
23
+ if (!doings.size)
24
+ return;
25
+ logger.info("start parallel delay keys: %o", doings);
26
+ await async.eachLimit([...doings], 10, async (key) => {
27
+ // 延长 300 秒
28
+ await redis.expire(key, 300);
29
+ });
30
+ logger.info("end parallel delay keys: %o", doings);
31
+ };
32
+ async.forever(async () => {
33
+ try {
34
+ await sleep(100 * 1000);
35
+ await delay();
36
+ }
37
+ catch (e) {
38
+ logger.error(e);
39
+ }
40
+ }, logger.error);
41
+ /* 将 method 函数处理为有并发控制功能的函数 */
42
+ function control(method, opt) {
43
+ const { path, keyFn = () => opt.path, minMS = 0, errorFn = defaultErrorFn, needWaitMS = 0, neverReturn = false, } = opt;
44
+ const error = (errorFn || defaultErrorFn)(path, minMS);
45
+ const end = async (key, startAt) => {
46
+ const timing = Date.now() - startAt; // 执行总用时毫秒数
47
+ const remainMS = minMS - timing; // 计算和最小耗时的差值毫秒数
48
+ if (remainMS > 0) {
49
+ await redis.expire(key, (remainMS / 1000) | 0);
50
+ }
51
+ else {
52
+ await redis.del(key);
53
+ }
54
+ doings.delete(key);
55
+ };
56
+ const paralleled = async (...args) => {
57
+ if (exiting)
58
+ throw Error("process exiting");
59
+ const key = `${KEY}::${keyFn(path, ...args)}`;
60
+ const ok = await redis.set(key, Date.now(), "EX", 300, "NX");
61
+ if (exiting) {
62
+ await redis.del(key);
63
+ throw Error("process exiting");
64
+ }
65
+ if (!ok) {
66
+ // 不需要等待,则直接抛出异常
67
+ if (!needWaitMS)
68
+ throw error;
69
+ // 需要等待
70
+ await async.whilst(async () => Boolean(await redis.exists(key)), async () => sleep(needWaitMS));
71
+ return paralleled(...args);
72
+ }
73
+ const startAt = Date.now(); // 执行开始毫秒数
74
+ doings.add(key);
75
+ try {
76
+ const res = await method(...args);
77
+ if (!neverReturn)
78
+ await end(key, startAt);
79
+ return res;
80
+ }
81
+ catch (e) {
82
+ await end(key, startAt);
83
+ throw e;
84
+ }
85
+ };
86
+ return paralleled;
87
+ }
88
+ // 进程退出时候的处理
89
+ graceful.exit(onExit);
90
+ return control;
91
+ }
92
+ exports.Main = Main;
93
+ exports.Deps = ["logger", "graceful", "redis", "utils"];
@@ -0,0 +1,6 @@
1
+ import * as Redis from "ioredis";
2
+ interface Cnf {
3
+ redis: Redis.RedisOptions;
4
+ }
5
+ export declare function Main(cnf: Cnf): Redis.Redis;
6
+ export {};
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Main = void 0;
4
+ const Redis = require("ioredis");
5
+ function Main(cnf) {
6
+ const { redis } = cnf;
7
+ return new Redis(redis);
8
+ }
9
+ exports.Main = Main;
@@ -0,0 +1,5 @@
1
+ import { Utils } from "./utils";
2
+ declare type Cnf = Parameters<typeof Utils>[0];
3
+ declare type Deps = Parameters<typeof Utils>[1];
4
+ export declare function Before(cnf: Cnf, deps: Deps): [Cnf, Deps, ReturnType<typeof Utils>];
5
+ export {};
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Before = void 0;
4
+ const utils_1 = require("./utils");
5
+ function Before(cnf, deps) {
6
+ const utils = (0, utils_1.Utils)(cnf, deps);
7
+ return [cnf, deps, utils];
8
+ }
9
+ exports.Before = Before;
@@ -0,0 +1,50 @@
1
+ import * as Sequelize from "sequelize";
2
+ export interface Params {
3
+ [propName: string]: any;
4
+ }
5
+ export declare type TModel = typeof Sequelize.Model & {
6
+ filterAttrs?: string[];
7
+ writableCols?: string[];
8
+ editableCols?: string[];
9
+ allowIncludeCols?: string[];
10
+ onlyAdminCols?: string[];
11
+ pagination?: {
12
+ maxResults: number;
13
+ maxStartIndex: number;
14
+ maxResultsLimit: number;
15
+ };
16
+ sort?: {
17
+ default: string;
18
+ allow: string[];
19
+ defaultDirection?: "DESC" | "ASC";
20
+ };
21
+ includes?: {
22
+ [k: string]: {
23
+ as: string;
24
+ required: boolean;
25
+ model: TModel;
26
+ };
27
+ };
28
+ searchCols?: {
29
+ [k: string]: {
30
+ op: "=" | "LIKE";
31
+ match: string[];
32
+ };
33
+ };
34
+ stats?: {
35
+ dimensions?: Record<string, string>;
36
+ metrics: Record<string, string>;
37
+ pagination?: {
38
+ maxResults: number;
39
+ maxStartIndex: number;
40
+ maxResultsLimit: number;
41
+ };
42
+ };
43
+ unique?: string[];
44
+ };
45
+ export declare type ModelExtraAtts = Omit<TModel, keyof typeof Sequelize.Model>;
46
+ export interface Include {
47
+ as: string;
48
+ required: boolean;
49
+ model: TModel;
50
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,34 @@
1
+ import * as Sequelize from "sequelize";
2
+ import { TModel, Params } from "./defines";
3
+ import { Stats } from "./stats";
4
+ import { Utils } from "./utils";
5
+ export { Before } from "./Before";
6
+ declare type Cnf = Parameters<typeof Utils>[0] & Parameters<typeof Stats>[0];
7
+ declare type Deps = Parameters<typeof Utils>[1] & Parameters<typeof Stats>[1];
8
+ declare type UserId = string | number;
9
+ export interface CreatorAndClientIp {
10
+ creatorId: UserId;
11
+ clientIp: string;
12
+ }
13
+ export declare function Main(cnf: Cnf, deps: Deps, utils: ReturnType<typeof Utils>): {
14
+ modify: (Model: TModel, model: Sequelize.Model<any, any>, params: Params, isAdmin?: boolean, _cols?: string[] | undefined) => Promise<Sequelize.Model<any, any>>;
15
+ add: (Model: TModel, params: Params, isAdmin: boolean | undefined, _cols: string[] | undefined, { creatorId, clientIp }: CreatorAndClientIp) => Promise<any>;
16
+ remove: (model: Sequelize.Model, deletorId: UserId) => Promise<void | Sequelize.Model<any, any>>;
17
+ list: (Model: TModel, params: Params, allowAttrs?: string[] | undefined, toJSON?: boolean | undefined) => Promise<{
18
+ count: number;
19
+ rows: any;
20
+ }>;
21
+ stats: (Model: TModel, params: Params, where: any, conf?: {
22
+ dimensions?: Record<string, string> | undefined;
23
+ metrics: Record<string, string>;
24
+ pagination?: {
25
+ maxResults: number;
26
+ maxStartIndex: number;
27
+ maxResultsLimit: number;
28
+ } | undefined;
29
+ } | undefined) => Promise<{
30
+ count: number;
31
+ rows: any;
32
+ }>;
33
+ };
34
+ export declare const Deps: string[];
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Deps = exports.Main = exports.Before = void 0;
4
+ const _ = require("lodash");
5
+ const stats_1 = require("./stats");
6
+ var Before_1 = require("./Before");
7
+ Object.defineProperty(exports, "Before", { enumerable: true, get: function () { return Before_1.Before; } });
8
+ function Main(cnf, deps, utils) {
9
+ const { errors } = deps;
10
+ const { findAllOpts, pickParams } = utils;
11
+ const modify = (Model, model, params, isAdmin = false, _cols) => {
12
+ const cols = _cols || Model.editableCols || Model.writableCols || [];
13
+ const attr = pickParams(params, cols, Model, isAdmin);
14
+ // 避免id 被篡改,强制删除id属性
15
+ if (attr.id)
16
+ delete attr.id;
17
+ Object.assign(model, attr);
18
+ return model.save();
19
+ };
20
+ const add = async (Model, params, isAdmin = false, _cols, { creatorId, clientIp }) => {
21
+ const cols = _cols || Model.writableCols || [];
22
+ const attr = pickParams(params, cols, Model, isAdmin);
23
+ if (Model.rawAttributes.creatorId)
24
+ attr.creatorId = creatorId;
25
+ if (Model.rawAttributes.clientIp)
26
+ attr.clientIp = clientIp;
27
+ // 如果没有设置唯一属性且开启回收站, 则直接添加
28
+ if (!(Model.unique && Model.rawAttributes.isDeleted))
29
+ return Model.create(attr);
30
+ // 如果设置了唯一属性,且开启了回收站功能
31
+ // 则判断是否需要执行恢复操作
32
+ const where = _.pick(attr, Model.unique);
33
+ // 根据条件查找资源
34
+ const model = await Model.findOne({ where });
35
+ // 资源不存在
36
+ if (!model)
37
+ return Model.create(attr);
38
+ // 资源存在但是并非已删除的,抛出资源重复添加的error
39
+ if (model.isDeleted === "no")
40
+ throw errors.resourceDuplicateAdd(where);
41
+ // 资源存在,恢复
42
+ model.isDeleted = "no";
43
+ Object.assign(model, attr);
44
+ return model.save();
45
+ };
46
+ const TRASH_OPT = Object.freeze({ fields: ["isDeleted", "deletorId"] });
47
+ const remove = async (model, deletorId) => {
48
+ // 未开启回收站,直接删除
49
+ if (!model.isDeleted)
50
+ return model.destroy();
51
+ // 这里不做字段是否存在的判断,无所谓
52
+ model.deletorId = deletorId;
53
+ model.isDeleted = "yes";
54
+ // 丢进垃圾桶
55
+ return model.save(TRASH_OPT);
56
+ };
57
+ // count条件所需属性
58
+ const COUNT_OPT = Object.freeze(["where", "include"]);
59
+ const list = async (Model, params, allowAttrs, toJSON) => {
60
+ const opt = findAllOpts(Model, params);
61
+ const { _ignoreTotal } = params;
62
+ // 提高查询速度
63
+ let count = 0;
64
+ if (_ignoreTotal !== "yes")
65
+ count = await Model.count(_.pick(opt, COUNT_OPT));
66
+ if (Array.isArray(allowAttrs) && allowAttrs.length)
67
+ opt.attributes = allowAttrs;
68
+ const rows = await Model.findAll(opt);
69
+ if (toJSON) {
70
+ for (let i = 0; i < rows.length; i += 1) {
71
+ rows[i] = rows[i].toJSON();
72
+ }
73
+ }
74
+ return { count, rows };
75
+ };
76
+ return { modify, add, remove, list, stats: (0, stats_1.Stats)(cnf, deps, utils) };
77
+ }
78
+ exports.Main = Main;
79
+ exports.Deps = ["errors"];
@@ -0,0 +1,6 @@
1
+ import { Params, ModelExtraAtts, TModel } from "./defines";
2
+ import { Utils } from "./utils";
3
+ export declare function Stats(cnf: {}, deps: {}, utils: ReturnType<typeof Utils>): (Model: TModel, params: Params, where: any, conf?: ModelExtraAtts["stats"]) => Promise<{
4
+ count: number;
5
+ rows: any;
6
+ }>;