@midwayjs/tags 3.0.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.
- package/README.md +9 -0
- package/dist/configuration.d.ts +4 -0
- package/dist/configuration.js +34 -0
- package/dist/dialect/index.d.ts +3 -0
- package/dist/dialect/index.js +19 -0
- package/dist/dialect/memory.d.ts +27 -0
- package/dist/dialect/memory.js +245 -0
- package/dist/dialect/mysql.d.ts +38 -0
- package/dist/dialect/mysql.js +352 -0
- package/dist/error.d.ts +7 -0
- package/dist/error.js +11 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +24 -0
- package/dist/interface.d.ts +84 -0
- package/dist/interface.js +17 -0
- package/dist/manager.d.ts +10 -0
- package/dist/manager.js +52 -0
- package/dist/service.d.ts +16 -0
- package/dist/service.js +69 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.js +60 -0
- package/index.d.ts +9 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.TagsConfiguration = void 0;
|
|
10
|
+
const core_1 = require("@midwayjs/core");
|
|
11
|
+
const manager_1 = require("./manager");
|
|
12
|
+
let TagsConfiguration = class TagsConfiguration {
|
|
13
|
+
async onReady(container) {
|
|
14
|
+
await container.getAsync(manager_1.TagServiceFactory);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
TagsConfiguration = __decorate([
|
|
18
|
+
(0, core_1.Configuration)({
|
|
19
|
+
namespace: 'tags',
|
|
20
|
+
importConfigs: [
|
|
21
|
+
{
|
|
22
|
+
default: {
|
|
23
|
+
tags: {
|
|
24
|
+
default: {
|
|
25
|
+
dialectType: 'memory',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
})
|
|
32
|
+
], TagsConfiguration);
|
|
33
|
+
exports.TagsConfiguration = TagsConfiguration;
|
|
34
|
+
//# sourceMappingURL=configuration.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./memory"), exports);
|
|
18
|
+
__exportStar(require("./mysql"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ITagDialectInstance } from '..';
|
|
2
|
+
import { ITagBindOptions, ITagDefine, ITagDialect, ITagItem, ITagListInstanceOptions, ITagListInstanceTagsOptions, ITagListResult, ITagOperResult, ITagSearchOptions, ITagUnBindOptions } from '../interface';
|
|
3
|
+
interface MemoryInstanceStore {
|
|
4
|
+
tagStore: Map<string | number, ITagItem>;
|
|
5
|
+
tagRelationStore: Map<`${number}-${number}`, boolean>;
|
|
6
|
+
}
|
|
7
|
+
export declare class MemoryDialect implements ITagDialect {
|
|
8
|
+
private tagStore;
|
|
9
|
+
ready(): Promise<void>;
|
|
10
|
+
getInstance(group: string): ITagDialectInstance;
|
|
11
|
+
}
|
|
12
|
+
export declare class MemoryDialectInstance implements ITagDialectInstance {
|
|
13
|
+
private tagIndex;
|
|
14
|
+
private tagStore;
|
|
15
|
+
private tagRelationStore;
|
|
16
|
+
constructor(stores: MemoryInstanceStore);
|
|
17
|
+
new(tagDefine: ITagDefine): Promise<ITagOperResult>;
|
|
18
|
+
remove(tagIdOrName: number): Promise<ITagOperResult>;
|
|
19
|
+
update(tagIdOrName: number, params: Partial<ITagDefine>): Promise<ITagOperResult>;
|
|
20
|
+
list(listOptions?: ITagSearchOptions): Promise<ITagListResult<ITagItem>>;
|
|
21
|
+
bind(bindOptions?: ITagBindOptions): Promise<ITagOperResult>;
|
|
22
|
+
unbind(unbindOptions: ITagUnBindOptions): Promise<ITagOperResult>;
|
|
23
|
+
listObjects(listOptions?: ITagListInstanceOptions): Promise<ITagListResult<number>>;
|
|
24
|
+
listObjectTags(listOptions?: ITagListInstanceTagsOptions): Promise<ITagListResult<ITagItem>>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryDialectInstance = exports.MemoryDialect = void 0;
|
|
4
|
+
const error_1 = require("../error");
|
|
5
|
+
const interface_1 = require("../interface");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
class MemoryDialect {
|
|
8
|
+
constructor() {
|
|
9
|
+
// store tag information
|
|
10
|
+
this.tagStore = new Map();
|
|
11
|
+
}
|
|
12
|
+
async ready() { }
|
|
13
|
+
getInstance(group) {
|
|
14
|
+
let instanceStores = this.tagStore.get(group);
|
|
15
|
+
if (!instanceStores) {
|
|
16
|
+
instanceStores = {
|
|
17
|
+
tagStore: new Map(),
|
|
18
|
+
tagRelationStore: new Map(),
|
|
19
|
+
};
|
|
20
|
+
this.tagStore.set(group, instanceStores);
|
|
21
|
+
}
|
|
22
|
+
return new MemoryDialectInstance(instanceStores);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.MemoryDialect = MemoryDialect;
|
|
26
|
+
class MemoryDialectInstance {
|
|
27
|
+
constructor(stores) {
|
|
28
|
+
this.tagIndex = 0;
|
|
29
|
+
this.tagStore = stores.tagStore;
|
|
30
|
+
this.tagRelationStore = stores.tagRelationStore;
|
|
31
|
+
}
|
|
32
|
+
async new(tagDefine) {
|
|
33
|
+
const existTagItem = this.tagStore.get(tagDefine.name);
|
|
34
|
+
if (existTagItem) {
|
|
35
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.EXISTS, {
|
|
36
|
+
id: existTagItem.id,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const tagId = ++this.tagIndex;
|
|
40
|
+
const tagItem = {
|
|
41
|
+
...tagDefine,
|
|
42
|
+
id: tagId,
|
|
43
|
+
createAt: Date.now(),
|
|
44
|
+
updateAt: Date.now(),
|
|
45
|
+
};
|
|
46
|
+
this.tagStore.set(tagId, tagItem);
|
|
47
|
+
this.tagStore.set(tagItem.name, tagItem);
|
|
48
|
+
return (0, utils_1.success)({
|
|
49
|
+
id: tagId,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async remove(tagIdOrName) {
|
|
53
|
+
const tagItem = this.tagStore.get(tagIdOrName);
|
|
54
|
+
if (!tagItem) {
|
|
55
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, { id: tagIdOrName });
|
|
56
|
+
}
|
|
57
|
+
const { list: allObjectId } = await this.listObjects({
|
|
58
|
+
tags: [tagItem.id],
|
|
59
|
+
pageSize: Infinity,
|
|
60
|
+
});
|
|
61
|
+
for (const objectId of allObjectId) {
|
|
62
|
+
this.tagRelationStore.delete(`${tagItem.id}-${objectId}`);
|
|
63
|
+
}
|
|
64
|
+
this.tagStore.delete(tagItem.name);
|
|
65
|
+
this.tagStore.delete(tagItem.id);
|
|
66
|
+
return (0, utils_1.success)({ id: tagItem.id });
|
|
67
|
+
}
|
|
68
|
+
async update(tagIdOrName, params) {
|
|
69
|
+
const tagItem = this.tagStore.get(tagIdOrName);
|
|
70
|
+
if (!tagItem) {
|
|
71
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, { id: tagIdOrName });
|
|
72
|
+
}
|
|
73
|
+
Object.assign(tagItem, {
|
|
74
|
+
...params,
|
|
75
|
+
id: tagItem.id,
|
|
76
|
+
});
|
|
77
|
+
return (0, utils_1.success)({ id: tagItem.id });
|
|
78
|
+
}
|
|
79
|
+
async list(listOptions) {
|
|
80
|
+
const { page, pageSize, tags = [], count } = listOptions;
|
|
81
|
+
const { limit: start, end } = (0, utils_1.getPageOpions)(page, pageSize);
|
|
82
|
+
let matchedItemIndex = 0;
|
|
83
|
+
const result = [];
|
|
84
|
+
for (let i = 0; i <= this.tagIndex; i++) {
|
|
85
|
+
const tagItem = this.tagStore.get(i);
|
|
86
|
+
if (!tagItem) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const matched = tags.length
|
|
90
|
+
? !!tags.find(matchItem => {
|
|
91
|
+
if (typeof matchItem === 'string') {
|
|
92
|
+
const { matchStart, matchEnd, text } = (0, utils_1.formatMatchLike)(matchItem);
|
|
93
|
+
if (matchEnd && matchStart) {
|
|
94
|
+
return tagItem.name.includes(text);
|
|
95
|
+
}
|
|
96
|
+
else if (matchStart) {
|
|
97
|
+
return tagItem.name.startsWith(text);
|
|
98
|
+
}
|
|
99
|
+
else if (matchEnd) {
|
|
100
|
+
return tagItem.name.endsWith(text);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return tagItem.name === text;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return tagItem.id === matchItem;
|
|
107
|
+
})
|
|
108
|
+
: true;
|
|
109
|
+
if (matched) {
|
|
110
|
+
if (matchedItemIndex >= start && matchedItemIndex < end) {
|
|
111
|
+
result.push(tagItem);
|
|
112
|
+
if (!count && result.length === pageSize) {
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
matchedItemIndex++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const returnResult = {
|
|
120
|
+
list: result,
|
|
121
|
+
};
|
|
122
|
+
if (count) {
|
|
123
|
+
returnResult.total = matchedItemIndex;
|
|
124
|
+
}
|
|
125
|
+
return returnResult;
|
|
126
|
+
}
|
|
127
|
+
async bind(bindOptions) {
|
|
128
|
+
let tagList = [];
|
|
129
|
+
try {
|
|
130
|
+
tagList = await Promise.all(bindOptions.tags.map(async (tag) => {
|
|
131
|
+
let tagItem = this.tagStore.get(tag);
|
|
132
|
+
if (!tagItem) {
|
|
133
|
+
if (typeof tag === 'string' && bindOptions.autoCreateTag) {
|
|
134
|
+
const newTag = await this.new({
|
|
135
|
+
name: tag,
|
|
136
|
+
desc: 'auto create',
|
|
137
|
+
});
|
|
138
|
+
tagItem = this.tagStore.get(newTag.id);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
throw (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, { id: [tag] });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return tagItem;
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
return e;
|
|
149
|
+
}
|
|
150
|
+
for (const tagItem of tagList) {
|
|
151
|
+
this.tagRelationStore.set(`${tagItem.id}-${bindOptions.objectId}`, true);
|
|
152
|
+
}
|
|
153
|
+
return (0, utils_1.success)();
|
|
154
|
+
}
|
|
155
|
+
async unbind(unbindOptions) {
|
|
156
|
+
for (const tag of unbindOptions.tags) {
|
|
157
|
+
const tagItem = this.tagStore.get(tag);
|
|
158
|
+
if (tagItem) {
|
|
159
|
+
this.tagRelationStore.delete(`${tagItem.id}-${unbindOptions.objectId}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return (0, utils_1.success)();
|
|
163
|
+
}
|
|
164
|
+
async listObjects(listOptions) {
|
|
165
|
+
const { page, pageSize, tags = [], count, type = interface_1.MATCH_TYPE.Or, } = listOptions;
|
|
166
|
+
const { limit: start, end } = (0, utils_1.getPageOpions)(page, pageSize);
|
|
167
|
+
let matchedItemIndex = 0;
|
|
168
|
+
const result = [];
|
|
169
|
+
const resultIdMap = {};
|
|
170
|
+
for (const [relative] of this.tagRelationStore) {
|
|
171
|
+
const [tagId, relaObjectId] = relative.split('-');
|
|
172
|
+
if (resultIdMap[relaObjectId] &&
|
|
173
|
+
resultIdMap[relaObjectId].length === tags.length) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const tagItem = this.tagStore.get(+tagId);
|
|
177
|
+
if (!tagItem) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const matched = tags.length
|
|
181
|
+
? !!tags.find(matchItem => {
|
|
182
|
+
if (typeof matchItem === 'string') {
|
|
183
|
+
return tagItem.name === matchItem;
|
|
184
|
+
}
|
|
185
|
+
return tagItem.id === matchItem;
|
|
186
|
+
})
|
|
187
|
+
: true;
|
|
188
|
+
if (matched) {
|
|
189
|
+
if (!resultIdMap[relaObjectId]) {
|
|
190
|
+
resultIdMap[relaObjectId] = [];
|
|
191
|
+
}
|
|
192
|
+
resultIdMap[relaObjectId].push(tagItem.id);
|
|
193
|
+
if ((type === interface_1.MATCH_TYPE.And &&
|
|
194
|
+
resultIdMap[relaObjectId].length === tags.length) ||
|
|
195
|
+
(type === interface_1.MATCH_TYPE.Or && resultIdMap[relaObjectId].length === 1)) {
|
|
196
|
+
if (matchedItemIndex >= start && matchedItemIndex < end) {
|
|
197
|
+
result.push(+relaObjectId);
|
|
198
|
+
}
|
|
199
|
+
matchedItemIndex++;
|
|
200
|
+
}
|
|
201
|
+
if (!count && result.length === pageSize) {
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const returnResult = {
|
|
207
|
+
list: result,
|
|
208
|
+
};
|
|
209
|
+
if (count) {
|
|
210
|
+
returnResult.total = matchedItemIndex;
|
|
211
|
+
}
|
|
212
|
+
return returnResult;
|
|
213
|
+
}
|
|
214
|
+
async listObjectTags(listOptions) {
|
|
215
|
+
const { page, pageSize, objectId, count } = listOptions;
|
|
216
|
+
const { limit: start, end } = (0, utils_1.getPageOpions)(page, pageSize);
|
|
217
|
+
let matchedItemIndex = 0;
|
|
218
|
+
const result = [];
|
|
219
|
+
const resultIdMap = {};
|
|
220
|
+
for (const [relative] of this.tagRelationStore) {
|
|
221
|
+
const [tagId, relaObjectId] = relative.split('-');
|
|
222
|
+
if (+relaObjectId !== objectId) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const tagItem = this.tagStore.get(+tagId);
|
|
226
|
+
if (!tagItem || resultIdMap[tagId]) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
resultIdMap[tagId] = true;
|
|
230
|
+
if (matchedItemIndex >= start && matchedItemIndex < end) {
|
|
231
|
+
result.push(tagItem);
|
|
232
|
+
}
|
|
233
|
+
matchedItemIndex++;
|
|
234
|
+
}
|
|
235
|
+
const returnResult = {
|
|
236
|
+
list: result,
|
|
237
|
+
};
|
|
238
|
+
if (count) {
|
|
239
|
+
returnResult.total = matchedItemIndex;
|
|
240
|
+
}
|
|
241
|
+
return returnResult;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
exports.MemoryDialectInstance = MemoryDialectInstance;
|
|
245
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IMysqlQuery, ITagBindOptions, ITagDefine, ITagDialect, ITagDialectInstance, ITagItem, ITagListInstanceOptions, ITagListInstanceTagsOptions, ITagListResult, ITagMysqlDialectOption, ITagOperResult, ITagSearchOptions, ITagUnBindOptions } from '../interface';
|
|
2
|
+
export declare enum MysqlTableName {
|
|
3
|
+
Tag = "tag",
|
|
4
|
+
Relationship = "relationship"
|
|
5
|
+
}
|
|
6
|
+
export declare class MysqlDialect implements ITagDialect {
|
|
7
|
+
private dialectOptions;
|
|
8
|
+
private name;
|
|
9
|
+
private query;
|
|
10
|
+
constructor(dialect: ITagMysqlDialectOption);
|
|
11
|
+
ready(): Promise<void>;
|
|
12
|
+
getInstance(group: string): ITagDialectInstance;
|
|
13
|
+
private buildTableName;
|
|
14
|
+
private syncTable;
|
|
15
|
+
private checkOrCreateTable;
|
|
16
|
+
}
|
|
17
|
+
interface MysqlDialectInstanceOptions {
|
|
18
|
+
group: string;
|
|
19
|
+
getTableName: (str: string) => string;
|
|
20
|
+
query: IMysqlQuery;
|
|
21
|
+
}
|
|
22
|
+
export declare class MysqlDialectInstance implements ITagDialectInstance {
|
|
23
|
+
private group;
|
|
24
|
+
private query;
|
|
25
|
+
private buildTableName;
|
|
26
|
+
constructor(options: MysqlDialectInstanceOptions);
|
|
27
|
+
new(tagDefine: ITagDefine): Promise<ITagOperResult>;
|
|
28
|
+
remove(tagIdOrName: number): Promise<ITagOperResult>;
|
|
29
|
+
update(tagIdOrName: number, params: Partial<ITagDefine>): Promise<ITagOperResult>;
|
|
30
|
+
list(listOptions?: ITagSearchOptions): Promise<ITagListResult<ITagItem>>;
|
|
31
|
+
bind(bindOptions?: ITagBindOptions): Promise<ITagOperResult>;
|
|
32
|
+
unbind(unbindOptions: ITagUnBindOptions): Promise<ITagOperResult>;
|
|
33
|
+
listObjects(listOptions?: ITagListInstanceOptions): Promise<ITagListResult<number>>;
|
|
34
|
+
listObjectTags(listOptions?: ITagListInstanceTagsOptions): Promise<ITagListResult<ITagItem>>;
|
|
35
|
+
private getTags;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=mysql.d.ts.map
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MysqlDialectInstance = exports.MysqlDialect = exports.MysqlTableName = void 0;
|
|
4
|
+
const error_1 = require("../error");
|
|
5
|
+
const interface_1 = require("../interface");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
var MysqlTableName;
|
|
8
|
+
(function (MysqlTableName) {
|
|
9
|
+
MysqlTableName["Tag"] = "tag";
|
|
10
|
+
MysqlTableName["Relationship"] = "relationship";
|
|
11
|
+
})(MysqlTableName = exports.MysqlTableName || (exports.MysqlTableName = {}));
|
|
12
|
+
class MysqlDialect {
|
|
13
|
+
constructor(dialect) {
|
|
14
|
+
this.name = 'tags';
|
|
15
|
+
this.dialectOptions = dialect;
|
|
16
|
+
this.query = this.dialectOptions.instance.query;
|
|
17
|
+
}
|
|
18
|
+
async ready() {
|
|
19
|
+
if (this.dialectOptions.sync) {
|
|
20
|
+
await this.syncTable();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
getInstance(group) {
|
|
24
|
+
return new MysqlDialectInstance({
|
|
25
|
+
group,
|
|
26
|
+
query: this.dialectOptions.instance.query,
|
|
27
|
+
getTableName: this.buildTableName.bind(this),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
buildTableName(tableName) {
|
|
31
|
+
const tableNameList = this.dialectOptions.tablePrefix
|
|
32
|
+
? [this.dialectOptions.tablePrefix, this.name]
|
|
33
|
+
: [this.name];
|
|
34
|
+
return tableNameList
|
|
35
|
+
.concat(tableName)
|
|
36
|
+
.join(this.dialectOptions.tableSeparator || '_');
|
|
37
|
+
}
|
|
38
|
+
async syncTable() {
|
|
39
|
+
// tag table
|
|
40
|
+
await this.checkOrCreateTable(this.buildTableName(MysqlTableName.Tag), [
|
|
41
|
+
'`group` varchar(32) NULL,',
|
|
42
|
+
'`name` varchar(32) NULL,',
|
|
43
|
+
'`descri` varchar(128) NULL,',
|
|
44
|
+
]);
|
|
45
|
+
// relationship table
|
|
46
|
+
await this.checkOrCreateTable(this.buildTableName(MysqlTableName.Relationship), ['`tid` BIGINT unsigned NOT NULL,', '`oid` BIGINT unsigned NOT NULL,']);
|
|
47
|
+
}
|
|
48
|
+
async checkOrCreateTable(tableName, tableColumn) {
|
|
49
|
+
const [raws] = await this.query(`SHOW TABLES LIKE '${tableName}'`);
|
|
50
|
+
if (raws.length) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const createSql = `CREATE TABLE \`${tableName}\` (
|
|
54
|
+
\`id\` BIGINT unsigned NOT NULL AUTO_INCREMENT,
|
|
55
|
+
${tableColumn.join('\n')}
|
|
56
|
+
\`created_at\` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
|
57
|
+
\`update_at\` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
|
|
58
|
+
PRIMARY KEY (id)
|
|
59
|
+
);`;
|
|
60
|
+
await this.query(createSql);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.MysqlDialect = MysqlDialect;
|
|
64
|
+
class MysqlDialectInstance {
|
|
65
|
+
constructor(options) {
|
|
66
|
+
this.group = options.group;
|
|
67
|
+
this.query = options.query;
|
|
68
|
+
this.buildTableName = options.getTableName;
|
|
69
|
+
}
|
|
70
|
+
async new(tagDefine) {
|
|
71
|
+
const { ids: [existTagId], } = await this.getTags(tagDefine.name);
|
|
72
|
+
if (existTagId) {
|
|
73
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.EXISTS, {
|
|
74
|
+
id: existTagId,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const sql = `insert into ${this.buildTableName(MysqlTableName.Tag)} (\`group\`, \`name\`, \`descri\`) values (?, ?, ?)`;
|
|
78
|
+
const [raws] = await this.query(sql, [
|
|
79
|
+
this.group,
|
|
80
|
+
tagDefine.name,
|
|
81
|
+
tagDefine.desc,
|
|
82
|
+
]);
|
|
83
|
+
if (!raws.insertId) {
|
|
84
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.OPER_ERROR);
|
|
85
|
+
}
|
|
86
|
+
return (0, utils_1.success)({
|
|
87
|
+
id: raws.insertId,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async remove(tagIdOrName) {
|
|
91
|
+
const { ids: [existTagId], } = await this.getTags(tagIdOrName);
|
|
92
|
+
if (!existTagId) {
|
|
93
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, { id: tagIdOrName });
|
|
94
|
+
}
|
|
95
|
+
// 先删除 object tag,
|
|
96
|
+
const removeRelationshipSql = `delete from ${this.buildTableName(MysqlTableName.Relationship)} where tid = ${existTagId}`;
|
|
97
|
+
await this.query(removeRelationshipSql);
|
|
98
|
+
const sql = `delete from ${this.buildTableName(MysqlTableName.Tag)} where id = ${existTagId}`;
|
|
99
|
+
const [raws] = await this.query(sql);
|
|
100
|
+
if (raws.affectedRows !== 1) {
|
|
101
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.OPER_ERROR);
|
|
102
|
+
}
|
|
103
|
+
return (0, utils_1.success)({ id: existTagId });
|
|
104
|
+
}
|
|
105
|
+
async update(tagIdOrName, params) {
|
|
106
|
+
const { ids: [existTagId], } = await this.getTags(tagIdOrName);
|
|
107
|
+
if (!existTagId) {
|
|
108
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, { id: tagIdOrName });
|
|
109
|
+
}
|
|
110
|
+
const fields = [];
|
|
111
|
+
const placeholders = [];
|
|
112
|
+
Object.keys(params).forEach(key => {
|
|
113
|
+
if (key === 'group' || key === 'id') {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
let updateKey = key;
|
|
117
|
+
if (key === 'desc') {
|
|
118
|
+
updateKey = 'descri';
|
|
119
|
+
}
|
|
120
|
+
fields.push(`\`${updateKey}\` = ?`);
|
|
121
|
+
placeholders.push(params[key]);
|
|
122
|
+
});
|
|
123
|
+
const sql = `update ${this.buildTableName(MysqlTableName.Tag)} set ${fields.join(', ')} where id = ${existTagId}`;
|
|
124
|
+
const [raws] = await this.query(sql, placeholders);
|
|
125
|
+
if (raws.affectedRows !== 1) {
|
|
126
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.OPER_ERROR);
|
|
127
|
+
}
|
|
128
|
+
return (0, utils_1.success)({
|
|
129
|
+
id: existTagId,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async list(listOptions) {
|
|
133
|
+
const { page, pageSize, tags = [], count } = listOptions;
|
|
134
|
+
const { limit, offset } = (0, utils_1.getPageOpions)(page, pageSize);
|
|
135
|
+
const idList = [];
|
|
136
|
+
const nameList = [];
|
|
137
|
+
const placeholder = [this.group];
|
|
138
|
+
for (const matchItem of tags) {
|
|
139
|
+
if (typeof matchItem === 'number') {
|
|
140
|
+
idList.push(matchItem);
|
|
141
|
+
}
|
|
142
|
+
else if (typeof matchItem === 'string') {
|
|
143
|
+
nameList.push(matchItem);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const condition = [
|
|
147
|
+
idList.length ? `id in (${idList.join()})` : '',
|
|
148
|
+
...nameList.map((name) => {
|
|
149
|
+
const { matchStart, matchEnd, text } = (0, utils_1.formatMatchLike)(name);
|
|
150
|
+
if (matchStart && matchEnd) {
|
|
151
|
+
placeholder.push(text);
|
|
152
|
+
return '`name` = ?';
|
|
153
|
+
}
|
|
154
|
+
placeholder.push(name);
|
|
155
|
+
return '`name` like ?';
|
|
156
|
+
}),
|
|
157
|
+
]
|
|
158
|
+
.filter(v => !!v)
|
|
159
|
+
.join(' or ');
|
|
160
|
+
const selectSql = `select * from ${this.buildTableName(MysqlTableName.Tag)} where \`group\` = ?${condition ? ` and (${condition})` : ''} limit ${limit},${offset}`;
|
|
161
|
+
const queryPromise = [this.query(selectSql, placeholder)];
|
|
162
|
+
if (count) {
|
|
163
|
+
const countSql = `select count(id) as total from ${this.buildTableName(MysqlTableName.Tag)} where \`group\` = ?${condition ? ` and (${condition})` : ''}`;
|
|
164
|
+
queryPromise.push(this.query(countSql, placeholder));
|
|
165
|
+
}
|
|
166
|
+
const [selectRes, countRes] = await Promise.all(queryPromise).then(resultList => {
|
|
167
|
+
return resultList.map(([raws]) => {
|
|
168
|
+
return raws;
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
const returnResult = {
|
|
172
|
+
list: selectRes.map(item => {
|
|
173
|
+
item.desc = item.descri;
|
|
174
|
+
delete item.descri;
|
|
175
|
+
return item;
|
|
176
|
+
}),
|
|
177
|
+
};
|
|
178
|
+
if (count) {
|
|
179
|
+
returnResult.total = countRes[0].total;
|
|
180
|
+
}
|
|
181
|
+
return returnResult;
|
|
182
|
+
}
|
|
183
|
+
async bind(bindOptions) {
|
|
184
|
+
const { tags, objectId, autoCreateTag } = bindOptions;
|
|
185
|
+
const { ids, notExists } = await this.getTags(tags);
|
|
186
|
+
if (notExists.id.length) {
|
|
187
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, {
|
|
188
|
+
id: notExists.id,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
if (notExists.name.length) {
|
|
192
|
+
if (!autoCreateTag) {
|
|
193
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.NOT_EXISTS, {
|
|
194
|
+
id: notExists.name,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
const newTagIds = await Promise.all(notExists.name.map(async (tag) => {
|
|
198
|
+
const { id } = await this.new({
|
|
199
|
+
name: tag,
|
|
200
|
+
desc: 'auto creat',
|
|
201
|
+
});
|
|
202
|
+
return id;
|
|
203
|
+
}));
|
|
204
|
+
ids.push(...newTagIds);
|
|
205
|
+
}
|
|
206
|
+
await Promise.all(ids.map(async (tagId) => {
|
|
207
|
+
// TODO: 简单事务,检测是否存在关系
|
|
208
|
+
await this.query(`insert into ${this.buildTableName(MysqlTableName.Relationship)} (\`tid\`, \`oid\`) values (?, ?)`, [tagId, objectId]);
|
|
209
|
+
}));
|
|
210
|
+
return (0, utils_1.success)();
|
|
211
|
+
}
|
|
212
|
+
async unbind(unbindOptions) {
|
|
213
|
+
var _a;
|
|
214
|
+
let removeRelationshipSql = `delete from ${this.buildTableName(MysqlTableName.Relationship)} where oid = ${unbindOptions.objectId}`;
|
|
215
|
+
if ((_a = unbindOptions.tags) === null || _a === void 0 ? void 0 : _a.length) {
|
|
216
|
+
const { ids } = await this.getTags(unbindOptions.tags);
|
|
217
|
+
removeRelationshipSql += ` and tid in (${ids.join(',')})`;
|
|
218
|
+
}
|
|
219
|
+
await this.query(removeRelationshipSql);
|
|
220
|
+
return (0, utils_1.success)();
|
|
221
|
+
}
|
|
222
|
+
async listObjects(listOptions) {
|
|
223
|
+
const { page, pageSize, tags = [], count, type = interface_1.MATCH_TYPE.Or, } = listOptions;
|
|
224
|
+
const { limit, offset } = (0, utils_1.getPageOpions)(page, pageSize);
|
|
225
|
+
const { ids, notExists } = await this.getTags(tags);
|
|
226
|
+
if (notExists.all.length) {
|
|
227
|
+
return {
|
|
228
|
+
list: [],
|
|
229
|
+
total: 0,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
let sql = '';
|
|
233
|
+
let countSql = '';
|
|
234
|
+
if (tags.length === 1) {
|
|
235
|
+
// for more high performance
|
|
236
|
+
const sqlBase = `FROM ${this.buildTableName(MysqlTableName.Relationship)} where tid = ${ids[0]}`;
|
|
237
|
+
sql = `SELECT oid ${sqlBase} limit ${limit},${offset}`;
|
|
238
|
+
countSql = `SELECT count(*) as total ${sqlBase}`;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
if (type === interface_1.MATCH_TYPE.Or) {
|
|
242
|
+
const sqlBase = `FROM ${this.buildTableName(MysqlTableName.Relationship)} where tid in (${ids.join(',')})`;
|
|
243
|
+
sql = `SELECT distinct oid ${sqlBase} limit ${limit},${offset}`;
|
|
244
|
+
countSql = `SELECT count(distinct oid) as total ${sqlBase}`;
|
|
245
|
+
}
|
|
246
|
+
else if (type === interface_1.MATCH_TYPE.And) {
|
|
247
|
+
sql = `SELECT oid FROM ${this.buildTableName(MysqlTableName.Relationship)} where tid in (${ids.join(',')}) group by oid HAVING COUNT(*) = ${ids.length} limit ${limit},${offset}`;
|
|
248
|
+
countSql = `SELECT count(*) as total FROM (SELECT oid FROM ${this.buildTableName(MysqlTableName.Relationship)} where tid in (${ids.join(',')}) group by oid HAVING COUNT(*) = ${ids.length}) as list`;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const queryPromises = [];
|
|
252
|
+
queryPromises.push(this.query(sql));
|
|
253
|
+
if (count) {
|
|
254
|
+
queryPromises.push(this.query(countSql));
|
|
255
|
+
}
|
|
256
|
+
const [selectRes, countRes] = await Promise.all(queryPromises).then(resultList => {
|
|
257
|
+
return resultList.map(([raws]) => {
|
|
258
|
+
return raws;
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
const returnResult = {
|
|
262
|
+
list: selectRes.map(item => {
|
|
263
|
+
return item.oid;
|
|
264
|
+
}),
|
|
265
|
+
};
|
|
266
|
+
if (count) {
|
|
267
|
+
returnResult.total = countRes[0].total;
|
|
268
|
+
}
|
|
269
|
+
return returnResult;
|
|
270
|
+
}
|
|
271
|
+
async listObjectTags(listOptions) {
|
|
272
|
+
const { page, pageSize, objectId, count } = listOptions;
|
|
273
|
+
const { limit, offset } = (0, utils_1.getPageOpions)(page, pageSize);
|
|
274
|
+
const sql = `select tid from ${this.buildTableName(MysqlTableName.Relationship)} where oid = ? limit ${limit},${offset}`;
|
|
275
|
+
const queryPromises = [this.query(sql, [objectId])];
|
|
276
|
+
if (count) {
|
|
277
|
+
const sql = `select count(tid) as total from ${this.buildTableName(MysqlTableName.Relationship)} where oid = ?`;
|
|
278
|
+
queryPromises.push(this.query(sql, [objectId]));
|
|
279
|
+
}
|
|
280
|
+
const [tagIdList, countRes] = await Promise.all(queryPromises).then(resultList => {
|
|
281
|
+
return resultList.map(([raws]) => {
|
|
282
|
+
return raws;
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
let tagList = [];
|
|
286
|
+
if (tagIdList.length) {
|
|
287
|
+
const { list } = await this.list({
|
|
288
|
+
tags: tagIdList.map(raw => raw.tid),
|
|
289
|
+
});
|
|
290
|
+
tagList = list;
|
|
291
|
+
}
|
|
292
|
+
const returnResult = {
|
|
293
|
+
list: tagList,
|
|
294
|
+
};
|
|
295
|
+
if (count) {
|
|
296
|
+
returnResult.total = countRes[0].total;
|
|
297
|
+
}
|
|
298
|
+
return returnResult;
|
|
299
|
+
}
|
|
300
|
+
async getTags(tagIdOrName) {
|
|
301
|
+
const tags = [].concat(tagIdOrName);
|
|
302
|
+
const idList = [];
|
|
303
|
+
const nameList = [];
|
|
304
|
+
const placeholder = [this.group];
|
|
305
|
+
const keyMap = new Map();
|
|
306
|
+
for (const tag of tags) {
|
|
307
|
+
keyMap.set(tag, true);
|
|
308
|
+
if (typeof tag === 'number') {
|
|
309
|
+
idList.push(tag);
|
|
310
|
+
}
|
|
311
|
+
else if (typeof tag === 'string') {
|
|
312
|
+
nameList.push('`name` = ?');
|
|
313
|
+
placeholder.push(tag);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const condition = [
|
|
317
|
+
idList.length ? `id in (${idList.join()})` : '',
|
|
318
|
+
...nameList,
|
|
319
|
+
]
|
|
320
|
+
.filter(v => !!v)
|
|
321
|
+
.join(' or ');
|
|
322
|
+
const sql = `select id,name from ${this.buildTableName(MysqlTableName.Tag)} where \`group\` = ?${condition ? ` and (${condition})` : ''}`;
|
|
323
|
+
const [raws] = await this.query(sql, placeholder);
|
|
324
|
+
const tagIds = raws.map(raw => {
|
|
325
|
+
keyMap.delete(raw.id);
|
|
326
|
+
keyMap.delete(raw.name);
|
|
327
|
+
return raw.id;
|
|
328
|
+
});
|
|
329
|
+
const notExists = {
|
|
330
|
+
id: [],
|
|
331
|
+
name: [],
|
|
332
|
+
all: [],
|
|
333
|
+
};
|
|
334
|
+
const notExistKeys = keyMap.keys();
|
|
335
|
+
for (const key of notExistKeys) {
|
|
336
|
+
notExists.all.push(key);
|
|
337
|
+
if (typeof key === 'number') {
|
|
338
|
+
notExists.id.push(key);
|
|
339
|
+
}
|
|
340
|
+
else if (typeof key === 'string') {
|
|
341
|
+
notExists.name.push(key);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
notExists.all;
|
|
345
|
+
return {
|
|
346
|
+
ids: tagIds,
|
|
347
|
+
notExists,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
exports.MysqlDialectInstance = MysqlDialectInstance;
|
|
352
|
+
//# sourceMappingURL=mysql.js.map
|
package/dist/error.d.ts
ADDED
package/dist/error.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TAG_ERROR = void 0;
|
|
4
|
+
var TAG_ERROR;
|
|
5
|
+
(function (TAG_ERROR) {
|
|
6
|
+
TAG_ERROR["EXISTS"] = "tag already exists";
|
|
7
|
+
TAG_ERROR["NOT_EXISTS"] = "tag does not exist";
|
|
8
|
+
TAG_ERROR["MISSING_PARAMETERS"] = "missing parameters";
|
|
9
|
+
TAG_ERROR["OPER_ERROR"] = "operation error";
|
|
10
|
+
})(TAG_ERROR = exports.TAG_ERROR || (exports.TAG_ERROR = {}));
|
|
11
|
+
//# sourceMappingURL=error.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.Configuration = void 0;
|
|
18
|
+
var configuration_1 = require("./configuration");
|
|
19
|
+
Object.defineProperty(exports, "Configuration", { enumerable: true, get: function () { return configuration_1.TagsConfiguration; } });
|
|
20
|
+
__exportStar(require("./manager"), exports);
|
|
21
|
+
__exportStar(require("./service"), exports);
|
|
22
|
+
__exportStar(require("./interface"), exports);
|
|
23
|
+
__exportStar(require("./error"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export interface ITagServiceInitOptions {
|
|
2
|
+
group: string;
|
|
3
|
+
dialect?: ITagDialect;
|
|
4
|
+
}
|
|
5
|
+
export type ITagDialectOption = {
|
|
6
|
+
dialectType: 'memory';
|
|
7
|
+
} | ITagMysqlDialectOption | ITagUserDialect;
|
|
8
|
+
export interface ITagUserDialect {
|
|
9
|
+
dialectType: string;
|
|
10
|
+
dialect: ITagDialect;
|
|
11
|
+
}
|
|
12
|
+
export type IMysqlQuery = (sql: string, placeholder?: any[]) => [any, any];
|
|
13
|
+
export interface ITagMysqlDialectOption {
|
|
14
|
+
dialectType: 'mysql';
|
|
15
|
+
sync?: boolean;
|
|
16
|
+
tablePrefix?: string;
|
|
17
|
+
tableSeparator?: string;
|
|
18
|
+
instance: {
|
|
19
|
+
query: IMysqlQuery;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface ITagDefine {
|
|
23
|
+
name: string;
|
|
24
|
+
desc?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ITagItem extends ITagDefine {
|
|
27
|
+
id: number;
|
|
28
|
+
createAt: number;
|
|
29
|
+
updateAt: number;
|
|
30
|
+
}
|
|
31
|
+
export declare abstract class ITagDialect {
|
|
32
|
+
abstract ready(): Promise<void>;
|
|
33
|
+
abstract getInstance(instanceName: string): ITagDialectInstance;
|
|
34
|
+
}
|
|
35
|
+
export declare abstract class ITagDialectInstance {
|
|
36
|
+
abstract new(tagDefine: ITagDefine): Promise<ITagOperResult>;
|
|
37
|
+
abstract remove(tagIdOrName: number | string): Promise<ITagOperResult>;
|
|
38
|
+
abstract update(tagIdOrName: number | string, params: Partial<ITagDefine>): Promise<ITagOperResult>;
|
|
39
|
+
abstract list(listOptions?: ITagSearchOptions): Promise<ITagListResult<ITagItem>>;
|
|
40
|
+
abstract bind(bindOptions: ITagBindOptions): Promise<ITagOperResult>;
|
|
41
|
+
abstract unbind(unbindOptions: ITagUnBindOptions): Promise<ITagOperResult>;
|
|
42
|
+
abstract listObjects(listOptions?: ITagListInstanceOptions): Promise<ITagListResult<number>>;
|
|
43
|
+
abstract listObjectTags(listOptions?: ITagListInstanceTagsOptions): Promise<ITagListResult<ITagItem>>;
|
|
44
|
+
}
|
|
45
|
+
export interface ITagOperResult {
|
|
46
|
+
success: boolean;
|
|
47
|
+
message: string;
|
|
48
|
+
id?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface ITagListResult<ListType> {
|
|
51
|
+
list: ListType[];
|
|
52
|
+
total?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface ITagSearchOptions extends ITagPages {
|
|
55
|
+
tags?: Array<number | string>;
|
|
56
|
+
type?: MATCH_TYPE;
|
|
57
|
+
}
|
|
58
|
+
export interface ITagPages {
|
|
59
|
+
count?: boolean;
|
|
60
|
+
pageSize?: number;
|
|
61
|
+
page?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface ITagBindOptions extends ITagInstance {
|
|
64
|
+
tags: Array<number | string>;
|
|
65
|
+
autoCreateTag?: boolean;
|
|
66
|
+
}
|
|
67
|
+
export interface ITagUnBindOptions extends ITagInstance {
|
|
68
|
+
tags: Array<number | string>;
|
|
69
|
+
}
|
|
70
|
+
export interface ITagListInstanceTagsOptions extends ITagInstance, ITagPages {
|
|
71
|
+
}
|
|
72
|
+
export interface ITagInstance {
|
|
73
|
+
objectId: number;
|
|
74
|
+
}
|
|
75
|
+
export declare enum MATCH_TYPE {
|
|
76
|
+
And = "and",
|
|
77
|
+
Or = "or"
|
|
78
|
+
}
|
|
79
|
+
export interface ITagListInstanceOptions extends ITagPages {
|
|
80
|
+
tags?: Array<string | number>;
|
|
81
|
+
count?: boolean;
|
|
82
|
+
type?: MATCH_TYPE;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=interface.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MATCH_TYPE = exports.ITagDialectInstance = exports.ITagDialect = void 0;
|
|
4
|
+
class ITagDialect {
|
|
5
|
+
}
|
|
6
|
+
exports.ITagDialect = ITagDialect;
|
|
7
|
+
class ITagDialectInstance {
|
|
8
|
+
}
|
|
9
|
+
exports.ITagDialectInstance = ITagDialectInstance;
|
|
10
|
+
var MATCH_TYPE;
|
|
11
|
+
(function (MATCH_TYPE) {
|
|
12
|
+
// 交集
|
|
13
|
+
MATCH_TYPE["And"] = "and";
|
|
14
|
+
// 并集
|
|
15
|
+
MATCH_TYPE["Or"] = "or";
|
|
16
|
+
})(MATCH_TYPE = exports.MATCH_TYPE || (exports.MATCH_TYPE = {}));
|
|
17
|
+
//# sourceMappingURL=interface.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ServiceFactory, ServiceFactoryConfigOption } from '@midwayjs/core';
|
|
2
|
+
import { ITagDialectOption } from './interface';
|
|
3
|
+
import { TagClient } from './service';
|
|
4
|
+
export declare class TagServiceFactory extends ServiceFactory<TagClient> {
|
|
5
|
+
tags: ServiceFactoryConfigOption<ITagDialectOption>;
|
|
6
|
+
init(): Promise<void>;
|
|
7
|
+
createClient(config: ITagDialectOption, name: string): Promise<TagClient>;
|
|
8
|
+
getName(): string;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=manager.d.ts.map
|
package/dist/manager.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TagServiceFactory = void 0;
|
|
13
|
+
const core_1 = require("@midwayjs/core");
|
|
14
|
+
const dialect_1 = require("./dialect");
|
|
15
|
+
const service_1 = require("./service");
|
|
16
|
+
let TagServiceFactory = class TagServiceFactory extends core_1.ServiceFactory {
|
|
17
|
+
async init() {
|
|
18
|
+
await this.initClients(this.tags);
|
|
19
|
+
}
|
|
20
|
+
async createClient(config, name) {
|
|
21
|
+
let dialect;
|
|
22
|
+
if (config.dialect) {
|
|
23
|
+
dialect = config.dialect;
|
|
24
|
+
}
|
|
25
|
+
else if (config.dialectType === 'mysql') {
|
|
26
|
+
dialect = new dialect_1.MysqlDialect(config);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
dialect = new dialect_1.MemoryDialect();
|
|
30
|
+
}
|
|
31
|
+
await dialect.ready();
|
|
32
|
+
return new service_1.TagClient(dialect, name);
|
|
33
|
+
}
|
|
34
|
+
getName() {
|
|
35
|
+
return 'tags';
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, core_1.Config)('tags'),
|
|
40
|
+
__metadata("design:type", Object)
|
|
41
|
+
], TagServiceFactory.prototype, "tags", void 0);
|
|
42
|
+
__decorate([
|
|
43
|
+
(0, core_1.Init)(),
|
|
44
|
+
__metadata("design:type", Function),
|
|
45
|
+
__metadata("design:paramtypes", []),
|
|
46
|
+
__metadata("design:returntype", Promise)
|
|
47
|
+
], TagServiceFactory.prototype, "init", null);
|
|
48
|
+
TagServiceFactory = __decorate([
|
|
49
|
+
(0, core_1.Singleton)()
|
|
50
|
+
], TagServiceFactory);
|
|
51
|
+
exports.TagServiceFactory = TagServiceFactory;
|
|
52
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ITagBindOptions, ITagDefine, ITagDialect, ITagItem, ITagListInstanceOptions, ITagListInstanceTagsOptions, ITagListResult, ITagOperResult, ITagSearchOptions, ITagUnBindOptions } from './interface';
|
|
2
|
+
export * from './interface';
|
|
3
|
+
export * from './error';
|
|
4
|
+
export declare class TagClient {
|
|
5
|
+
private dialect;
|
|
6
|
+
constructor(dialect: ITagDialect, tagGroup: string);
|
|
7
|
+
new(tagDefine: ITagDefine): Promise<ITagOperResult>;
|
|
8
|
+
remove(tagIdOrName: number | string): Promise<ITagOperResult>;
|
|
9
|
+
update(tagIdOrName: number | string, params: Partial<ITagDefine>): Promise<ITagOperResult>;
|
|
10
|
+
list(listOptions?: ITagSearchOptions): Promise<ITagListResult<ITagItem>>;
|
|
11
|
+
bind(bindOptions: ITagBindOptions): Promise<ITagOperResult>;
|
|
12
|
+
unbind(unbindOptions: ITagUnBindOptions): Promise<ITagOperResult>;
|
|
13
|
+
listObjects(listOptions?: ITagListInstanceOptions): Promise<ITagListResult<number>>;
|
|
14
|
+
listObjectTags(listOptions?: ITagListInstanceTagsOptions): Promise<ITagListResult<ITagItem>>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=service.d.ts.map
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.TagClient = void 0;
|
|
18
|
+
const error_1 = require("./error");
|
|
19
|
+
const utils_1 = require("./utils");
|
|
20
|
+
__exportStar(require("./interface"), exports);
|
|
21
|
+
__exportStar(require("./error"), exports);
|
|
22
|
+
class TagClient {
|
|
23
|
+
constructor(dialect, tagGroup) {
|
|
24
|
+
this.dialect = dialect.getInstance(tagGroup);
|
|
25
|
+
}
|
|
26
|
+
async new(tagDefine) {
|
|
27
|
+
return this.dialect.new(tagDefine);
|
|
28
|
+
}
|
|
29
|
+
async remove(tagIdOrName) {
|
|
30
|
+
return this.dialect.remove(tagIdOrName);
|
|
31
|
+
}
|
|
32
|
+
async update(tagIdOrName, params) {
|
|
33
|
+
return this.dialect.update(tagIdOrName, params);
|
|
34
|
+
}
|
|
35
|
+
async list(listOptions) {
|
|
36
|
+
return this.dialect.list({
|
|
37
|
+
page: 1,
|
|
38
|
+
pageSize: 20,
|
|
39
|
+
...listOptions,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async bind(bindOptions) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (!((_a = bindOptions.tags) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
45
|
+
return (0, utils_1.error)(error_1.TAG_ERROR.MISSING_PARAMETERS, { need: 'tags' });
|
|
46
|
+
}
|
|
47
|
+
return this.dialect.bind(bindOptions);
|
|
48
|
+
}
|
|
49
|
+
async unbind(unbindOptions) {
|
|
50
|
+
return this.dialect.unbind(unbindOptions);
|
|
51
|
+
}
|
|
52
|
+
async listObjects(listOptions) {
|
|
53
|
+
return this.dialect.listObjects({
|
|
54
|
+
page: 1,
|
|
55
|
+
pageSize: 20,
|
|
56
|
+
tags: [],
|
|
57
|
+
...listOptions,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async listObjectTags(listOptions) {
|
|
61
|
+
return this.dialect.listObjectTags({
|
|
62
|
+
page: 1,
|
|
63
|
+
pageSize: 20,
|
|
64
|
+
...listOptions,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.TagClient = TagClient;
|
|
69
|
+
//# sourceMappingURL=service.js.map
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const success: (data?: any, message?: string) => any;
|
|
2
|
+
export declare const error: (message: string, data?: any) => any;
|
|
3
|
+
export declare const getPageOpions: (page?: number, pageSize?: number) => {
|
|
4
|
+
limit: number;
|
|
5
|
+
offset: number;
|
|
6
|
+
end: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const formatMatchLike: (matchItem: string) => {
|
|
9
|
+
matchEnd: boolean;
|
|
10
|
+
matchStart: boolean;
|
|
11
|
+
text: string;
|
|
12
|
+
stashedText: string;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatMatchLike = exports.getPageOpions = exports.error = exports.success = void 0;
|
|
4
|
+
const success = (data = {}, message = 'success') => {
|
|
5
|
+
return {
|
|
6
|
+
success: true,
|
|
7
|
+
message,
|
|
8
|
+
...data,
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
exports.success = success;
|
|
12
|
+
const error = (message, data) => {
|
|
13
|
+
return {
|
|
14
|
+
success: false,
|
|
15
|
+
message,
|
|
16
|
+
...data,
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
exports.error = error;
|
|
20
|
+
const getPageOpions = (page = 1, pageSize = 20) => {
|
|
21
|
+
if (page === 1 && pageSize === Infinity) {
|
|
22
|
+
return {
|
|
23
|
+
limit: 0,
|
|
24
|
+
offset: Infinity,
|
|
25
|
+
end: Infinity,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const pageSizeNumber = +pageSize;
|
|
29
|
+
const start = (+page - 1) * pageSizeNumber;
|
|
30
|
+
const end = start + pageSizeNumber;
|
|
31
|
+
return {
|
|
32
|
+
limit: start,
|
|
33
|
+
offset: pageSizeNumber,
|
|
34
|
+
end,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
exports.getPageOpions = getPageOpions;
|
|
38
|
+
const formatMatchLike = (matchItem) => {
|
|
39
|
+
let matchItemText = matchItem;
|
|
40
|
+
let matchStart = true;
|
|
41
|
+
let matchEnd = true;
|
|
42
|
+
// xxx% macth start with xxx
|
|
43
|
+
if (matchItem.endsWith('%')) {
|
|
44
|
+
matchEnd = false;
|
|
45
|
+
matchItemText = matchItemText.slice(0, -1);
|
|
46
|
+
}
|
|
47
|
+
// %xxx macth end with xxx
|
|
48
|
+
if (matchItem.startsWith('%')) {
|
|
49
|
+
matchStart = false;
|
|
50
|
+
matchItemText = matchItemText.slice(1);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
matchEnd,
|
|
54
|
+
matchStart,
|
|
55
|
+
text: matchItemText,
|
|
56
|
+
stashedText: matchItem.replace(/'/g, ''),
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
exports.formatMatchLike = formatMatchLike;
|
|
60
|
+
//# sourceMappingURL=utils.js.map
|
package/index.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@midwayjs/tags",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Midway Tag System",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"typings": "index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand",
|
|
10
|
+
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit",
|
|
11
|
+
"ci": "npm run test"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/**/*.js",
|
|
17
|
+
"dist/**/*.d.ts",
|
|
18
|
+
"index.d.ts"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=12"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@midwayjs/core": "^3.11.0",
|
|
26
|
+
"@midwayjs/express": "^3.11.0",
|
|
27
|
+
"@midwayjs/faas": "^3.11.0",
|
|
28
|
+
"@midwayjs/koa": "^3.11.0",
|
|
29
|
+
"@midwayjs/mock": "^3.11.0",
|
|
30
|
+
"@midwayjs/serverless-app": "^3.11.0",
|
|
31
|
+
"@midwayjs/web": "^3.11.0",
|
|
32
|
+
"mysql2": "^2.3.3"
|
|
33
|
+
}
|
|
34
|
+
}
|