@tachybase/plugin-field-sequence 0.23.8
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.
- package/.turbo/turbo-build.log +12 -0
- package/README.md +9 -0
- package/README.zh-CN.md +9 -0
- package/client.d.ts +2 -0
- package/client.js +1 -0
- package/dist/client/SequenceFieldProvider.d.ts +2 -0
- package/dist/client/index.d.ts +5 -0
- package/dist/client/index.js +19 -0
- package/dist/client/locale/index.d.ts +3 -0
- package/dist/client/sequence.d.ts +259 -0
- package/dist/externalVersion.js +13 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +39 -0
- package/dist/locale/en-US.json +24 -0
- package/dist/locale/es-ES.json +24 -0
- package/dist/locale/fr-FR.json +24 -0
- package/dist/locale/ko_KR.json +24 -0
- package/dist/locale/pt-BR.json +24 -0
- package/dist/locale/zh-CN.json +25 -0
- package/dist/node_modules/cron-parser/LICENSE +21 -0
- package/dist/node_modules/cron-parser/lib/date.js +252 -0
- package/dist/node_modules/cron-parser/lib/expression.js +1002 -0
- package/dist/node_modules/cron-parser/lib/field_compactor.js +70 -0
- package/dist/node_modules/cron-parser/lib/field_stringify.js +58 -0
- package/dist/node_modules/cron-parser/lib/parser.js +1 -0
- package/dist/node_modules/cron-parser/package.json +1 -0
- package/dist/node_modules/cron-parser/types/common.d.ts +131 -0
- package/dist/node_modules/cron-parser/types/index.d.ts +45 -0
- package/dist/node_modules/cron-parser/types/ts3/index.d.ts +28 -0
- package/dist/server/Plugin.d.ts +8 -0
- package/dist/server/Plugin.js +124 -0
- package/dist/server/collections/sequences.d.ts +2 -0
- package/dist/server/collections/sequences.js +87 -0
- package/dist/server/fields/field-sequence.d.ts +38 -0
- package/dist/server/fields/field-sequence.js +386 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +39 -0
- package/dist/server/migrations/20221207022250-sequence-field-key.d.ts +6 -0
- package/dist/server/migrations/20221207022250-sequence-field-key.js +85 -0
- package/package.json +36 -0
- package/server.d.ts +2 -0
- package/server.js +1 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var Plugin_exports = {};
|
|
29
|
+
__export(Plugin_exports, {
|
|
30
|
+
default: () => SequenceFieldPlugin
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(Plugin_exports);
|
|
33
|
+
var import_crypto = require("crypto");
|
|
34
|
+
var import_path = __toESM(require("path"));
|
|
35
|
+
var import_util = require("util");
|
|
36
|
+
var import_server = require("@tachybase/server");
|
|
37
|
+
var import_utils = require("@tachybase/utils");
|
|
38
|
+
var import_field_sequence = require("./fields/field-sequence");
|
|
39
|
+
const asyncRandomInt = (0, import_util.promisify)(import_crypto.randomInt);
|
|
40
|
+
class SequenceFieldPlugin extends import_server.Plugin {
|
|
41
|
+
patternTypes = new import_utils.Registry();
|
|
42
|
+
async load() {
|
|
43
|
+
const { app, db, options } = this;
|
|
44
|
+
db.registerFieldTypes({
|
|
45
|
+
sequence: import_field_sequence.SequenceField
|
|
46
|
+
});
|
|
47
|
+
db.addMigrations({
|
|
48
|
+
namespace: "field-sequence",
|
|
49
|
+
directory: import_path.default.resolve(__dirname, "migrations"),
|
|
50
|
+
context: {
|
|
51
|
+
plugin: this
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
await this.importCollections(import_path.default.resolve(__dirname, "collections"));
|
|
55
|
+
db.on("fields.beforeSave", async (field, { transaction }) => {
|
|
56
|
+
if (field.get("type") !== "sequence") {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const patterns = (field.get("patterns") || []).filter((p) => p.type === "integer");
|
|
60
|
+
if (!patterns.length) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const SequenceRepo = db.getRepository("sequences");
|
|
64
|
+
await patterns.reduce(
|
|
65
|
+
(promise, p) => promise.then(async () => {
|
|
66
|
+
var _a;
|
|
67
|
+
if (((_a = p.options) == null ? void 0 : _a.key) == null) {
|
|
68
|
+
Object.assign(p, {
|
|
69
|
+
options: {
|
|
70
|
+
...p.options,
|
|
71
|
+
key: await asyncRandomInt(1 << 16)
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}),
|
|
76
|
+
Promise.resolve()
|
|
77
|
+
);
|
|
78
|
+
const sequences = await SequenceRepo.find({
|
|
79
|
+
filter: {
|
|
80
|
+
field: field.get("name"),
|
|
81
|
+
collection: field.get("collectionName"),
|
|
82
|
+
key: patterns.map((p) => p.options.key)
|
|
83
|
+
},
|
|
84
|
+
transaction
|
|
85
|
+
});
|
|
86
|
+
await patterns.reduce(
|
|
87
|
+
(promise, p) => promise.then(async () => {
|
|
88
|
+
if (!sequences.find((s) => s.get("key") === p.options.key)) {
|
|
89
|
+
await SequenceRepo.create({
|
|
90
|
+
values: {
|
|
91
|
+
field: field.get("name"),
|
|
92
|
+
collection: field.get("collectionName"),
|
|
93
|
+
key: p.options.key
|
|
94
|
+
},
|
|
95
|
+
transaction
|
|
96
|
+
});
|
|
97
|
+
await field.load({ transaction });
|
|
98
|
+
}
|
|
99
|
+
}),
|
|
100
|
+
Promise.resolve()
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
db.on("fields.afterDestroy", async (field, { transaction }) => {
|
|
104
|
+
if (field.get("type") !== "sequence") {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const patterns = (field.get("patterns") || []).filter((p) => p.type === "integer");
|
|
108
|
+
if (!patterns.length) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const SequenceRepo = db.getRepository("sequences");
|
|
112
|
+
await SequenceRepo.destroy({
|
|
113
|
+
filter: {
|
|
114
|
+
field: field.get("name"),
|
|
115
|
+
collection: field.get("collectionName"),
|
|
116
|
+
key: patterns.map((p) => p.key)
|
|
117
|
+
},
|
|
118
|
+
transaction
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async install() {
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var sequences_exports = {};
|
|
19
|
+
__export(sequences_exports, {
|
|
20
|
+
default: () => sequences_default
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(sequences_exports);
|
|
23
|
+
var import_database = require("@tachybase/database");
|
|
24
|
+
var sequences_default = (0, import_database.defineCollection)({
|
|
25
|
+
dumpRules: {
|
|
26
|
+
group: "required",
|
|
27
|
+
async delayRestore(restorer) {
|
|
28
|
+
const app = restorer.app;
|
|
29
|
+
const importedCollections = restorer.importedCollections;
|
|
30
|
+
const sequenceFields = importedCollections.map((collection) => {
|
|
31
|
+
const collectionInstance = app.db.getCollection(collection);
|
|
32
|
+
if (!collectionInstance) throw new Error(`Collection ${collection} not found`);
|
|
33
|
+
return [...collectionInstance.fields.values()].filter((field) => field.type === "sequence");
|
|
34
|
+
}).flat().filter(Boolean);
|
|
35
|
+
const sequencesAttributes = sequenceFields.map((field) => {
|
|
36
|
+
const patterns = field.get("patterns");
|
|
37
|
+
return patterns.map((pattern) => {
|
|
38
|
+
return {
|
|
39
|
+
collection: field.collection.name,
|
|
40
|
+
field: field.name,
|
|
41
|
+
key: pattern.options.key
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
}).flat().filter((attr) => attr.collection && attr.field && attr.key);
|
|
45
|
+
if (sequencesAttributes.length > 0) {
|
|
46
|
+
await app.db.getRepository("sequences").destroy({
|
|
47
|
+
filter: {
|
|
48
|
+
$or: sequencesAttributes
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
await restorer.importCollection({
|
|
53
|
+
name: "sequences",
|
|
54
|
+
clear: false,
|
|
55
|
+
rowCondition(row) {
|
|
56
|
+
return sequencesAttributes.some((attributes) => {
|
|
57
|
+
return row.collection === attributes.collection && row.field === attributes.field && row.key === attributes.key;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
name: "sequences",
|
|
64
|
+
shared: true,
|
|
65
|
+
fields: [
|
|
66
|
+
{
|
|
67
|
+
name: "collection",
|
|
68
|
+
type: "string"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "field",
|
|
72
|
+
type: "string"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "key",
|
|
76
|
+
type: "integer"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "current",
|
|
80
|
+
type: "bigInt"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "lastGeneratedAt",
|
|
84
|
+
type: "date"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BaseColumnFieldOptions, DataTypes, Field, FieldContext, Model, Transactionable } from '@tachybase/database';
|
|
2
|
+
import { Registry } from '@tachybase/utils';
|
|
3
|
+
export interface Pattern {
|
|
4
|
+
validate?(options: any): string | null;
|
|
5
|
+
generate(this: SequenceField, instance: Model, opts: {
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}, options: Transactionable): Promise<string> | string;
|
|
8
|
+
batchGenerate(this: SequenceField, instances: Model[], values: string[], opts: {
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}, options: Transactionable): Promise<void> | void;
|
|
11
|
+
getLength(options: any): number;
|
|
12
|
+
getMatcher(options: any): string;
|
|
13
|
+
update?(this: SequenceField, instance: Model, value: string, options: any, transactionable: Transactionable): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare const sequencePatterns: Registry<Pattern>;
|
|
16
|
+
interface PatternConfig {
|
|
17
|
+
type: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
options?: any;
|
|
20
|
+
}
|
|
21
|
+
export interface SequenceFieldOptions extends BaseColumnFieldOptions {
|
|
22
|
+
type: 'sequence';
|
|
23
|
+
patterns: PatternConfig[];
|
|
24
|
+
}
|
|
25
|
+
export declare class SequenceField extends Field {
|
|
26
|
+
matcher: RegExp;
|
|
27
|
+
get dataType(): DataTypes.StringDataTypeConstructor;
|
|
28
|
+
constructor(options: SequenceFieldOptions, context: FieldContext);
|
|
29
|
+
validate: (instance: Model) => void;
|
|
30
|
+
setValue: (instance: Model, options: any) => Promise<void>;
|
|
31
|
+
setGroupValue: (instances: Model[], options: any) => Promise<void>;
|
|
32
|
+
cleanHook: (_: any, options: any) => void;
|
|
33
|
+
match(value: any): RegExpMatchArray;
|
|
34
|
+
update(instance: Model, options: any): Promise<void>;
|
|
35
|
+
bind(): void;
|
|
36
|
+
unbind(): void;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var field_sequence_exports = {};
|
|
29
|
+
__export(field_sequence_exports, {
|
|
30
|
+
SequenceField: () => SequenceField,
|
|
31
|
+
sequencePatterns: () => sequencePatterns
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(field_sequence_exports);
|
|
34
|
+
var import_database = require("@tachybase/database");
|
|
35
|
+
var import_utils = require("@tachybase/utils");
|
|
36
|
+
var import_cron_parser = __toESM(require("cron-parser"));
|
|
37
|
+
var import_dayjs = __toESM(require("dayjs"));
|
|
38
|
+
var import_lodash = __toESM(require("lodash"));
|
|
39
|
+
const sequencePatterns = new import_utils.Registry();
|
|
40
|
+
sequencePatterns.register("string", {
|
|
41
|
+
validate(options) {
|
|
42
|
+
if (!(options == null ? void 0 : options.value)) {
|
|
43
|
+
return "options.value should be configured as a non-empty string";
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
},
|
|
47
|
+
generate(instance, options) {
|
|
48
|
+
return options.value;
|
|
49
|
+
},
|
|
50
|
+
batchGenerate(instances, values, options) {
|
|
51
|
+
instances.forEach((instance, i) => {
|
|
52
|
+
values[i] = options.value;
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
getLength(options) {
|
|
56
|
+
return options.value.length;
|
|
57
|
+
},
|
|
58
|
+
getMatcher(options) {
|
|
59
|
+
return import_lodash.default.escapeRegExp(options.value);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
sequencePatterns.register("integer", {
|
|
63
|
+
// validate(options) {
|
|
64
|
+
// if (!options?.key) {
|
|
65
|
+
// return 'options.key should be configured as an integer';
|
|
66
|
+
// }
|
|
67
|
+
// return null;
|
|
68
|
+
// },
|
|
69
|
+
async generate(instance, options, { transaction }) {
|
|
70
|
+
const recordTime = instance.get("createdAt") ?? /* @__PURE__ */ new Date();
|
|
71
|
+
const { digits = 1, start = 0, base = 10, cycle, key } = options;
|
|
72
|
+
const { repository: SeqRepo, model: SeqModel } = this.database.getCollection("sequences");
|
|
73
|
+
const lastSeq = await SeqRepo.findOne({
|
|
74
|
+
filter: {
|
|
75
|
+
collection: this.collection.name,
|
|
76
|
+
field: this.name,
|
|
77
|
+
key
|
|
78
|
+
},
|
|
79
|
+
transaction
|
|
80
|
+
}) || SeqModel.build({
|
|
81
|
+
collection: this.collection.name,
|
|
82
|
+
field: this.name,
|
|
83
|
+
key
|
|
84
|
+
});
|
|
85
|
+
let next = start;
|
|
86
|
+
if (lastSeq.get("current") != null) {
|
|
87
|
+
next = Math.max(lastSeq.get("current") + 1, start);
|
|
88
|
+
const max = Math.pow(base, digits) - 1;
|
|
89
|
+
if (next > max) {
|
|
90
|
+
next = start;
|
|
91
|
+
}
|
|
92
|
+
if (cycle) {
|
|
93
|
+
const interval = import_cron_parser.default.parseExpression(cycle, { currentDate: lastSeq.get("lastGeneratedAt") });
|
|
94
|
+
const nextTime = interval.next();
|
|
95
|
+
if (recordTime.getTime() >= nextTime.getTime()) {
|
|
96
|
+
next = start;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
lastSeq.set({
|
|
101
|
+
current: next,
|
|
102
|
+
lastGeneratedAt: recordTime
|
|
103
|
+
});
|
|
104
|
+
await lastSeq.save({ transaction });
|
|
105
|
+
return next.toString(base).padStart(digits, "0");
|
|
106
|
+
},
|
|
107
|
+
getLength({ digits = 1 } = {}) {
|
|
108
|
+
return digits;
|
|
109
|
+
},
|
|
110
|
+
getMatcher(options = {}) {
|
|
111
|
+
const { digits = 1, base = 10 } = options;
|
|
112
|
+
const chars = "0123456789abcdefghijklmnopqrstuvwxyz".slice(0, base);
|
|
113
|
+
return `[${chars}]{${digits}}`;
|
|
114
|
+
},
|
|
115
|
+
async batchGenerate(instances, values, options, { transaction }) {
|
|
116
|
+
const { name, patterns } = this.options;
|
|
117
|
+
const { digits = 1, start = 0, base = 10, cycle, key } = options;
|
|
118
|
+
const { repository: SeqRepo, model: SeqModel } = this.database.getCollection("sequences");
|
|
119
|
+
const lastSeq = await SeqRepo.findOne({
|
|
120
|
+
filter: {
|
|
121
|
+
collection: this.collection.name,
|
|
122
|
+
field: this.name,
|
|
123
|
+
key
|
|
124
|
+
},
|
|
125
|
+
transaction
|
|
126
|
+
}) || SeqModel.build({
|
|
127
|
+
collection: this.collection.name,
|
|
128
|
+
field: this.name,
|
|
129
|
+
key
|
|
130
|
+
});
|
|
131
|
+
instances.forEach((instance, i) => {
|
|
132
|
+
const recordTime = instance.get("createdAt") ?? /* @__PURE__ */ new Date();
|
|
133
|
+
const value = instance.get(name);
|
|
134
|
+
if (value != null && this.options.inputable) {
|
|
135
|
+
const matcher = this.match(value);
|
|
136
|
+
if (matcher) {
|
|
137
|
+
const patternIndex = patterns.indexOf(options);
|
|
138
|
+
const number = Number.parseInt(matcher[patternIndex + 1], base);
|
|
139
|
+
if (lastSeq.get("current") == null) {
|
|
140
|
+
lastSeq.set({
|
|
141
|
+
current: number,
|
|
142
|
+
lastGeneratedAt: recordTime
|
|
143
|
+
});
|
|
144
|
+
} else {
|
|
145
|
+
if (number > lastSeq.get("current")) {
|
|
146
|
+
lastSeq.set({
|
|
147
|
+
current: number,
|
|
148
|
+
lastGeneratedAt: recordTime
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
let next = start;
|
|
155
|
+
if (lastSeq.get("current") != null) {
|
|
156
|
+
next = Math.max(lastSeq.get("current") + 1, start);
|
|
157
|
+
const max = Math.pow(base, digits) - 1;
|
|
158
|
+
if (next > max) {
|
|
159
|
+
next = start;
|
|
160
|
+
}
|
|
161
|
+
if (cycle) {
|
|
162
|
+
const interval = import_cron_parser.default.parseExpression(cycle, { currentDate: lastSeq.get("lastGeneratedAt") });
|
|
163
|
+
const nextTime = interval.next();
|
|
164
|
+
if (recordTime.getTime() >= nextTime.getTime()) {
|
|
165
|
+
next = start;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
lastSeq.set({
|
|
170
|
+
current: next,
|
|
171
|
+
lastGeneratedAt: recordTime
|
|
172
|
+
});
|
|
173
|
+
values[i] = next.toString(base).padStart(digits, "0");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
await lastSeq.save({ transaction });
|
|
177
|
+
},
|
|
178
|
+
async update(instance, value, options, { transaction }) {
|
|
179
|
+
const recordTime = instance.get("createdAt") ?? /* @__PURE__ */ new Date();
|
|
180
|
+
const { digits = 1, start = 0, base = 10, cycle, key } = options;
|
|
181
|
+
const SeqRepo = this.database.getRepository("sequences");
|
|
182
|
+
const lastSeq = await SeqRepo.findOne({
|
|
183
|
+
filter: {
|
|
184
|
+
collection: this.collection.name,
|
|
185
|
+
field: this.name,
|
|
186
|
+
key
|
|
187
|
+
},
|
|
188
|
+
transaction
|
|
189
|
+
});
|
|
190
|
+
const current = Number.parseInt(value, base);
|
|
191
|
+
if (!lastSeq) {
|
|
192
|
+
return SeqRepo.create({
|
|
193
|
+
values: {
|
|
194
|
+
collection: this.collection.name,
|
|
195
|
+
field: this.name,
|
|
196
|
+
key,
|
|
197
|
+
current,
|
|
198
|
+
lastGeneratedAt: recordTime
|
|
199
|
+
},
|
|
200
|
+
transaction
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (lastSeq.get("current") == null) {
|
|
204
|
+
return lastSeq.update(
|
|
205
|
+
{
|
|
206
|
+
current,
|
|
207
|
+
lastGeneratedAt: recordTime
|
|
208
|
+
},
|
|
209
|
+
{ transaction }
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if (cycle) {
|
|
213
|
+
const interval = import_cron_parser.default.parseExpression(cycle, { currentDate: lastSeq.get("lastGeneratedAt") });
|
|
214
|
+
const nextTime = interval.next();
|
|
215
|
+
if (recordTime.getTime() >= nextTime.getTime()) {
|
|
216
|
+
lastSeq.set({
|
|
217
|
+
current,
|
|
218
|
+
lastGeneratedAt: recordTime
|
|
219
|
+
});
|
|
220
|
+
} else {
|
|
221
|
+
if (current > lastSeq.get("current")) {
|
|
222
|
+
lastSeq.set({
|
|
223
|
+
current,
|
|
224
|
+
lastGeneratedAt: recordTime
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
if (current > lastSeq.get("current")) {
|
|
230
|
+
lastSeq.set({
|
|
231
|
+
current,
|
|
232
|
+
lastGeneratedAt: recordTime
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return lastSeq.save({ transaction });
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
sequencePatterns.register("date", {
|
|
240
|
+
generate(instance, options) {
|
|
241
|
+
return (0, import_dayjs.default)(instance.get((options == null ? void 0 : options.field) ?? "createdAt")).format((options == null ? void 0 : options.format) ?? "YYYYMMDD");
|
|
242
|
+
},
|
|
243
|
+
batchGenerate(instances, values, options) {
|
|
244
|
+
const { field, inputable } = options;
|
|
245
|
+
instances.forEach((instance, i) => {
|
|
246
|
+
if (!inputable || instance.get(field ?? "createdAt") == null) {
|
|
247
|
+
values[i] = sequencePatterns.get("date").generate.call(this, instance, options);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
},
|
|
251
|
+
getLength(options) {
|
|
252
|
+
var _a;
|
|
253
|
+
return ((_a = options.format) == null ? void 0 : _a.length) ?? 8;
|
|
254
|
+
},
|
|
255
|
+
getMatcher(options = {}) {
|
|
256
|
+
var _a;
|
|
257
|
+
return `.{${((_a = options == null ? void 0 : options.format) == null ? void 0 : _a.length) ?? 8}}`;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
class SequenceField extends import_database.Field {
|
|
261
|
+
matcher;
|
|
262
|
+
get dataType() {
|
|
263
|
+
return import_database.DataTypes.STRING;
|
|
264
|
+
}
|
|
265
|
+
constructor(options, context) {
|
|
266
|
+
super(options, context);
|
|
267
|
+
if (!options.patterns || !options.patterns.length) {
|
|
268
|
+
throw new Error("at least one pattern should be defined for sequence type");
|
|
269
|
+
}
|
|
270
|
+
options.patterns.forEach((pattern) => {
|
|
271
|
+
const P = sequencePatterns.get(pattern.type);
|
|
272
|
+
if (!P) {
|
|
273
|
+
throw new Error(`pattern type ${pattern.type} is not registered`);
|
|
274
|
+
}
|
|
275
|
+
if (P.validate) {
|
|
276
|
+
const error = P.validate(pattern.options);
|
|
277
|
+
if (error) {
|
|
278
|
+
throw new Error(error);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
const patterns = options.patterns.map(({ type, options: options2 }) => sequencePatterns.get(type).getMatcher(options2));
|
|
283
|
+
this.matcher = new RegExp(`^${patterns.map((p) => `(${p})`).join("")}$`, "i");
|
|
284
|
+
}
|
|
285
|
+
validate = (instance) => {
|
|
286
|
+
const { name, inputable, match } = this.options;
|
|
287
|
+
const value = instance.get(name);
|
|
288
|
+
if (value != null && inputable && match && !this.match(value)) {
|
|
289
|
+
throw new import_database.ValidationError("sequence pattern not match", [
|
|
290
|
+
new import_database.ValidationErrorItem(
|
|
291
|
+
`input value of ${name} field not match the sequence pattern (${this.matcher.toString()}) which is required`,
|
|
292
|
+
"validation error",
|
|
293
|
+
// NOTE: type should only be this which in sequelize enum set
|
|
294
|
+
name,
|
|
295
|
+
value,
|
|
296
|
+
instance,
|
|
297
|
+
"sequence_pattern_not_match",
|
|
298
|
+
name,
|
|
299
|
+
[]
|
|
300
|
+
)
|
|
301
|
+
]);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
setValue = async (instance, options) => {
|
|
305
|
+
var _a;
|
|
306
|
+
if ((_a = options.skipIndividualHooks) == null ? void 0 : _a.has(`${this.collection.name}.beforeCreate.${this.name}`)) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const { name, patterns, inputable } = this.options;
|
|
310
|
+
const value = instance.get(name);
|
|
311
|
+
if (value != null && inputable) {
|
|
312
|
+
return this.update(instance, options);
|
|
313
|
+
}
|
|
314
|
+
const results = await patterns.reduce(
|
|
315
|
+
(promise, p) => promise.then(async (result) => {
|
|
316
|
+
const item = await sequencePatterns.get(p.type).generate.call(this, instance, p.options, options);
|
|
317
|
+
return result.concat(item);
|
|
318
|
+
}),
|
|
319
|
+
Promise.resolve([])
|
|
320
|
+
);
|
|
321
|
+
instance.set(name, results.join(""));
|
|
322
|
+
};
|
|
323
|
+
setGroupValue = async (instances, options) => {
|
|
324
|
+
if (!instances.length) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (!options.skipIndividualHooks) {
|
|
328
|
+
options.skipIndividualHooks = /* @__PURE__ */ new Set();
|
|
329
|
+
}
|
|
330
|
+
options.skipIndividualHooks.add(`${this.collection.name}.beforeCreate.${this.name}`);
|
|
331
|
+
const { name, patterns, inputable } = this.options;
|
|
332
|
+
const array = Array(patterns.length).fill(null).map(() => Array(instances.length));
|
|
333
|
+
await patterns.reduce(
|
|
334
|
+
(promise, p, i) => promise.then(
|
|
335
|
+
() => sequencePatterns.get(p.type).batchGenerate.call(this, instances, array[i], p.options ?? {}, options)
|
|
336
|
+
),
|
|
337
|
+
Promise.resolve()
|
|
338
|
+
);
|
|
339
|
+
instances.forEach((instance, i) => {
|
|
340
|
+
const value = instance.get(name);
|
|
341
|
+
if (!inputable || value == null) {
|
|
342
|
+
instance.set(this.name, array.map((a) => a[i]).join(""));
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
cleanHook = (_, options) => {
|
|
347
|
+
options.skipIndividualHooks.delete(`${this.collection.name}.beforeCreate.${this.name}`);
|
|
348
|
+
};
|
|
349
|
+
match(value) {
|
|
350
|
+
return typeof value === "string" ? value.match(this.matcher) : null;
|
|
351
|
+
}
|
|
352
|
+
async update(instance, options) {
|
|
353
|
+
const { name, patterns } = this.options;
|
|
354
|
+
const matched = this.match(instance.get(name));
|
|
355
|
+
if (matched) {
|
|
356
|
+
await matched.slice(1).map((_, i) => sequencePatterns.get(patterns[i].type).update).reduce(
|
|
357
|
+
(promise, update, i) => promise.then(() => {
|
|
358
|
+
if (!update) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
return update.call(this, instance, matched[i + 1], patterns[i].options, options);
|
|
362
|
+
}),
|
|
363
|
+
Promise.resolve()
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
bind() {
|
|
368
|
+
super.bind();
|
|
369
|
+
this.on("beforeValidate", this.validate);
|
|
370
|
+
this.on("beforeCreate", this.setValue);
|
|
371
|
+
this.on("beforeBulkCreate", this.setGroupValue);
|
|
372
|
+
this.on("afterBulkCreate", this.cleanHook);
|
|
373
|
+
}
|
|
374
|
+
unbind() {
|
|
375
|
+
super.unbind();
|
|
376
|
+
this.off("beforeValidate", this.validate);
|
|
377
|
+
this.off("beforeCreate", this.setValue);
|
|
378
|
+
this.off("beforeBulkCreate", this.setGroupValue);
|
|
379
|
+
this.off("afterBulkCreate", this.cleanHook);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
383
|
+
0 && (module.exports = {
|
|
384
|
+
SequenceField,
|
|
385
|
+
sequencePatterns
|
|
386
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var server_exports = {};
|
|
30
|
+
__export(server_exports, {
|
|
31
|
+
default: () => import_Plugin.default
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(server_exports);
|
|
34
|
+
__reExport(server_exports, require("./fields/field-sequence"), module.exports);
|
|
35
|
+
var import_Plugin = __toESM(require("./Plugin"));
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
...require("./fields/field-sequence")
|
|
39
|
+
});
|