@nocobase/database 0.9.0-alpha.2 → 0.9.1-alpha.1
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/lib/collection-importer.js +1 -1
- package/lib/collection.d.ts +7 -1
- package/lib/collection.js +135 -61
- package/lib/database-utils/index.d.ts +8 -0
- package/lib/database-utils/index.js +59 -0
- package/lib/database.d.ts +26 -3
- package/lib/database.js +224 -61
- package/lib/fields/array-field.d.ts +1 -1
- package/lib/fields/array-field.js +2 -2
- package/lib/fields/belongs-to-many-field.js +1 -2
- package/lib/fields/field.d.ts +1 -0
- package/lib/fields/field.js +37 -15
- package/lib/fields/has-one-field.d.ts +1 -1
- package/lib/fields/has-one-field.js +9 -5
- package/lib/fields/number-field.d.ts +9 -6
- package/lib/fields/number-field.js +8 -6
- package/lib/fields/sort-field.js +15 -1
- package/lib/index.d.ts +6 -4
- package/lib/index.js +59 -36
- package/lib/mock-database.d.ts +2 -0
- package/lib/mock-database.js +3 -1
- package/lib/model.js +10 -1
- package/lib/options-parser.js +3 -0
- package/lib/relation-repository/belongs-to-many-repository.js +4 -2
- package/lib/repository.js +5 -2
- package/lib/sync-runner.d.ts +1 -1
- package/lib/sync-runner.js +28 -18
- package/lib/types.d.ts +7 -1
- package/lib/update-associations.js +17 -3
- package/lib/update-guard.d.ts +1 -0
- package/lib/update-guard.js +6 -0
- package/lib/utils.d.ts +5 -0
- package/lib/utils.js +68 -0
- package/lib/value-parsers/array-value-parser.d.ts +8 -0
- package/lib/value-parsers/array-value-parser.js +76 -0
- package/lib/value-parsers/base-value-parser.d.ts +12 -0
- package/lib/value-parsers/base-value-parser.js +59 -0
- package/lib/value-parsers/boolean-value-parser.d.ts +4 -0
- package/lib/value-parsers/boolean-value-parser.js +46 -0
- package/lib/value-parsers/date-value-parser.d.ts +5 -0
- package/lib/value-parsers/date-value-parser.js +91 -0
- package/lib/value-parsers/index.d.ts +12 -0
- package/lib/value-parsers/index.js +102 -0
- package/lib/value-parsers/json-value-parser.d.ts +4 -0
- package/lib/value-parsers/json-value-parser.js +37 -0
- package/lib/value-parsers/number-value-parser.d.ts +4 -0
- package/lib/value-parsers/number-value-parser.js +49 -0
- package/lib/value-parsers/string-value-parser.d.ts +8 -0
- package/lib/value-parsers/string-value-parser.js +76 -0
- package/lib/value-parsers/to-many-value-parser.d.ts +13 -0
- package/lib/value-parsers/to-many-value-parser.js +169 -0
- package/lib/value-parsers/to-one-value-parser.d.ts +4 -0
- package/lib/value-parsers/to-one-value-parser.js +49 -0
- package/package.json +4 -3
- package/src/__tests__/bigint.test.ts +1 -1
- package/src/__tests__/collection-importer.test.ts +13 -1
- package/src/__tests__/collection.test.ts +19 -9
- package/src/__tests__/database.test.ts +32 -0
- package/src/__tests__/fields/sort-field.test.ts +23 -0
- package/src/__tests__/inhertits/collection-inherits.test.ts +7 -5
- package/src/__tests__/percent2float.test.ts +14 -0
- package/src/__tests__/postgres/schema.test.ts +120 -0
- package/src/__tests__/underscored-options.test.ts +207 -0
- package/src/__tests__/update-associations-through.test.ts +73 -0
- package/src/__tests__/value-parsers/base.test.ts +20 -0
- package/src/__tests__/value-parsers/date.test.ts +67 -0
- package/src/__tests__/value-parsers/number.test.ts +46 -0
- package/src/__tests__/value-parsers/to-many.test.ts +206 -0
- package/src/__tests__/value-parsers/to-one.test.ts +60 -0
- package/src/collection-importer.ts +2 -2
- package/src/collection.ts +97 -15
- package/src/database-utils/index.ts +38 -0
- package/src/database.ts +171 -33
- package/src/fields/array-field.ts +1 -1
- package/src/fields/belongs-to-field.ts +1 -1
- package/src/fields/belongs-to-many-field.ts +0 -1
- package/src/fields/field.ts +45 -16
- package/src/fields/has-many-field.ts +1 -1
- package/src/fields/has-one-field.ts +11 -7
- package/src/fields/number-field.ts +10 -6
- package/src/fields/sort-field.ts +13 -1
- package/src/index.ts +7 -4
- package/src/inherited-collection.ts +1 -0
- package/src/mock-database.ts +3 -1
- package/src/model.ts +11 -2
- package/src/options-parser.ts +5 -0
- package/src/relation-repository/belongs-to-many-repository.ts +4 -2
- package/src/repository.ts +8 -3
- package/src/sync-runner.ts +33 -19
- package/src/types.ts +12 -1
- package/src/update-associations.ts +12 -5
- package/src/update-guard.ts +6 -0
- package/src/utils.ts +94 -0
- package/src/value-parsers/array-value-parser.ts +30 -0
- package/src/value-parsers/base-value-parser.ts +40 -0
- package/src/value-parsers/boolean-value-parser.ts +29 -0
- package/src/value-parsers/date-value-parser.ts +38 -0
- package/src/value-parsers/index.ts +46 -0
- package/src/value-parsers/json-value-parser.ts +19 -0
- package/src/value-parsers/number-value-parser.ts +29 -0
- package/src/value-parsers/string-value-parser.ts +31 -0
- package/src/value-parsers/to-many-value-parser.ts +85 -0
- package/src/value-parsers/to-one-value-parser.ts +20 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.StringValueParser = void 0;
|
|
7
|
+
|
|
8
|
+
var _baseValueParser = require("./base-value-parser");
|
|
9
|
+
|
|
10
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
11
|
+
|
|
12
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
13
|
+
|
|
14
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
15
|
+
|
|
16
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
17
|
+
|
|
18
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
19
|
+
|
|
20
|
+
class StringValueParser extends _baseValueParser.BaseValueParser {
|
|
21
|
+
setValue(value) {
|
|
22
|
+
var _this = this;
|
|
23
|
+
|
|
24
|
+
return _asyncToGenerator(function* () {
|
|
25
|
+
const _this$getOptions = _this.getOptions(),
|
|
26
|
+
map = _this$getOptions.map,
|
|
27
|
+
set = _this$getOptions.set;
|
|
28
|
+
|
|
29
|
+
if (set.size > 0) {
|
|
30
|
+
if (map.has(value)) {
|
|
31
|
+
value = map.get(value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (set.has(value)) {
|
|
35
|
+
_this.value = value;
|
|
36
|
+
} else {
|
|
37
|
+
_this.errors.push(`No matching option found - ${JSON.stringify(value)}`);
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
_this.value = value;
|
|
41
|
+
}
|
|
42
|
+
})();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getOptions() {
|
|
46
|
+
var _this$field$options, _this$field$options$u;
|
|
47
|
+
|
|
48
|
+
const options = ((_this$field$options = this.field.options) === null || _this$field$options === void 0 ? void 0 : (_this$field$options$u = _this$field$options['uiSchema']) === null || _this$field$options$u === void 0 ? void 0 : _this$field$options$u.enum) || [];
|
|
49
|
+
const map = new Map();
|
|
50
|
+
const set = new Set();
|
|
51
|
+
|
|
52
|
+
var _iterator = _createForOfIteratorHelper(options),
|
|
53
|
+
_step;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
57
|
+
const option = _step.value;
|
|
58
|
+
set.add(option.value);
|
|
59
|
+
set.add(option.label);
|
|
60
|
+
map.set(option.label, option.value);
|
|
61
|
+
}
|
|
62
|
+
} catch (err) {
|
|
63
|
+
_iterator.e(err);
|
|
64
|
+
} finally {
|
|
65
|
+
_iterator.f();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
map,
|
|
70
|
+
set
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
exports.StringValueParser = StringValueParser;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseValueParser } from './base-value-parser';
|
|
2
|
+
export declare class ToManyValueParser extends BaseValueParser {
|
|
3
|
+
setAccessors: {
|
|
4
|
+
attachment: string;
|
|
5
|
+
chinaRegion: string;
|
|
6
|
+
};
|
|
7
|
+
setAttachments(value: any): Promise<void>;
|
|
8
|
+
setChinaRegion(value: any): Promise<void>;
|
|
9
|
+
setAssociations(value: any): Promise<void>;
|
|
10
|
+
setValue(value: any): Promise<void>;
|
|
11
|
+
getInterface(): string;
|
|
12
|
+
isInterface(name: string): boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ToManyValueParser = void 0;
|
|
7
|
+
|
|
8
|
+
function _path() {
|
|
9
|
+
const data = require("path");
|
|
10
|
+
|
|
11
|
+
_path = function _path() {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var _baseValueParser = require("./base-value-parser");
|
|
19
|
+
|
|
20
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
21
|
+
|
|
22
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
23
|
+
|
|
24
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
25
|
+
|
|
26
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
27
|
+
|
|
28
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
29
|
+
|
|
30
|
+
class ToManyValueParser extends _baseValueParser.BaseValueParser {
|
|
31
|
+
constructor(...args) {
|
|
32
|
+
super(...args);
|
|
33
|
+
this.setAccessors = {
|
|
34
|
+
attachment: 'setAttachments',
|
|
35
|
+
chinaRegion: 'setChinaRegion'
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setAttachments(value) {
|
|
40
|
+
var _this = this;
|
|
41
|
+
|
|
42
|
+
return _asyncToGenerator(function* () {
|
|
43
|
+
_this.value = _this.toArr(value).map(url => {
|
|
44
|
+
return {
|
|
45
|
+
title: (0, _path().basename)(url),
|
|
46
|
+
extname: (0, _path().extname)(url),
|
|
47
|
+
filename: (0, _path().basename)(url),
|
|
48
|
+
url
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
})();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setChinaRegion(value) {
|
|
55
|
+
var _this2 = this;
|
|
56
|
+
|
|
57
|
+
return _asyncToGenerator(function* () {
|
|
58
|
+
const repository = _this2.field.database.getRepository(_this2.field.target);
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const values = [];
|
|
62
|
+
|
|
63
|
+
const names = _this2.toArr(value, '/');
|
|
64
|
+
|
|
65
|
+
let parentCode = null;
|
|
66
|
+
|
|
67
|
+
var _iterator = _createForOfIteratorHelper(names),
|
|
68
|
+
_step;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
72
|
+
const name = _step.value;
|
|
73
|
+
const instance = yield repository.findOne({
|
|
74
|
+
filter: {
|
|
75
|
+
name: name.trim(),
|
|
76
|
+
parentCode
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (!instance) {
|
|
81
|
+
throw new Error(`"${value}" does not exist`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
parentCode = instance.get('code');
|
|
85
|
+
values.push(parentCode);
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
_iterator.e(err);
|
|
89
|
+
} finally {
|
|
90
|
+
_iterator.f();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (values.length !== names.length) {
|
|
94
|
+
throw new Error(`"${value}" does not exist`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_this2.value = values;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
_this2.errors.push(error.message);
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setAssociations(value) {
|
|
105
|
+
var _this3 = this;
|
|
106
|
+
|
|
107
|
+
return _asyncToGenerator(function* () {
|
|
108
|
+
var _this3$ctx, _this3$ctx$column;
|
|
109
|
+
|
|
110
|
+
const dataIndex = ((_this3$ctx = _this3.ctx) === null || _this3$ctx === void 0 ? void 0 : (_this3$ctx$column = _this3$ctx.column) === null || _this3$ctx$column === void 0 ? void 0 : _this3$ctx$column.dataIndex) || [];
|
|
111
|
+
|
|
112
|
+
if (Array.isArray(dataIndex) && dataIndex.length < 2) {
|
|
113
|
+
_this3.errors.push(`data index invalid`);
|
|
114
|
+
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const key = _this3.ctx.column.dataIndex[1];
|
|
119
|
+
|
|
120
|
+
const repository = _this3.field.database.getRepository(_this3.field.target);
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
_this3.value = yield Promise.all(_this3.toArr(value).map( /*#__PURE__*/function () {
|
|
124
|
+
var _ref = _asyncToGenerator(function* (v) {
|
|
125
|
+
const instance = yield repository.findOne({
|
|
126
|
+
filter: {
|
|
127
|
+
[key]: v
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (!instance) {
|
|
132
|
+
throw new Error(`"${v}" does not exist`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return instance.get(_this3.field.targetKey || 'id');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return function (_x) {
|
|
139
|
+
return _ref.apply(this, arguments);
|
|
140
|
+
};
|
|
141
|
+
}()));
|
|
142
|
+
} catch (error) {
|
|
143
|
+
_this3.errors.push(error.message);
|
|
144
|
+
}
|
|
145
|
+
})();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
setValue(value) {
|
|
149
|
+
var _this4 = this;
|
|
150
|
+
|
|
151
|
+
return _asyncToGenerator(function* () {
|
|
152
|
+
const setAccessor = _this4.setAccessors[_this4.getInterface()] || 'setAssociations';
|
|
153
|
+
yield _this4[setAccessor](value);
|
|
154
|
+
})();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
getInterface() {
|
|
158
|
+
var _this$field, _this$field$options;
|
|
159
|
+
|
|
160
|
+
return (_this$field = this.field) === null || _this$field === void 0 ? void 0 : (_this$field$options = _this$field.options) === null || _this$field$options === void 0 ? void 0 : _this$field$options.interface;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
isInterface(name) {
|
|
164
|
+
return this.getInterface() === name;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
exports.ToManyValueParser = ToManyValueParser;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ToOneValueParser = void 0;
|
|
7
|
+
|
|
8
|
+
var _baseValueParser = require("./base-value-parser");
|
|
9
|
+
|
|
10
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
11
|
+
|
|
12
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
13
|
+
|
|
14
|
+
class ToOneValueParser extends _baseValueParser.BaseValueParser {
|
|
15
|
+
setValue(value) {
|
|
16
|
+
var _this = this;
|
|
17
|
+
|
|
18
|
+
return _asyncToGenerator(function* () {
|
|
19
|
+
var _this$ctx, _this$ctx$column;
|
|
20
|
+
|
|
21
|
+
const dataIndex = ((_this$ctx = _this.ctx) === null || _this$ctx === void 0 ? void 0 : (_this$ctx$column = _this$ctx.column) === null || _this$ctx$column === void 0 ? void 0 : _this$ctx$column.dataIndex) || [];
|
|
22
|
+
|
|
23
|
+
if (Array.isArray(dataIndex) && dataIndex.length < 2) {
|
|
24
|
+
_this.errors.push(`data index invalid`);
|
|
25
|
+
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const key = _this.ctx.column.dataIndex[1];
|
|
30
|
+
|
|
31
|
+
const repository = _this.field.database.getRepository(_this.field.target);
|
|
32
|
+
|
|
33
|
+
const instance = yield repository.findOne({
|
|
34
|
+
filter: {
|
|
35
|
+
[key]: _this.trim(value)
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (instance) {
|
|
40
|
+
_this.value = instance.get(_this.field.targetKey || 'id');
|
|
41
|
+
} else {
|
|
42
|
+
_this.errors.push(`"${value}" does not exist`);
|
|
43
|
+
}
|
|
44
|
+
})();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.ToOneValueParser = ToOneValueParser;
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1-alpha.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@nocobase/utils": "0.9.
|
|
9
|
+
"@nocobase/utils": "0.9.1-alpha.1",
|
|
10
10
|
"async-mutex": "^0.3.2",
|
|
11
11
|
"cron-parser": "4.4.0",
|
|
12
12
|
"deepmerge": "^4.2.2",
|
|
13
|
+
"excel-date-to-js": "^1.1.5",
|
|
13
14
|
"flat": "^5.0.2",
|
|
14
15
|
"glob": "^7.1.6",
|
|
15
16
|
"mathjs": "^10.6.1",
|
|
@@ -26,5 +27,5 @@
|
|
|
26
27
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
27
28
|
"directory": "packages/database"
|
|
28
29
|
},
|
|
29
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "56cb184b00dc383b853015d525bf6e79dea92169"
|
|
30
31
|
}
|
|
@@ -43,6 +43,6 @@ excludeSqlite()('collection', () => {
|
|
|
43
43
|
|
|
44
44
|
const profileTableInfo = await db.sequelize.getQueryInterface().describeTable(profile.model.tableName);
|
|
45
45
|
|
|
46
|
-
expect(profileTableInfo['userId'].type).toBe('BIGINT');
|
|
46
|
+
expect(profileTableInfo[profile.model.rawAttributes['userId'].field].type).toBe('BIGINT');
|
|
47
47
|
});
|
|
48
48
|
});
|
|
@@ -7,7 +7,19 @@ describe('collection importer', () => {
|
|
|
7
7
|
const reader = new ImporterReader(path.resolve(__dirname, './fixtures/collections'));
|
|
8
8
|
|
|
9
9
|
const modules = await reader.read();
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
const posts = modules.find((m) => m.name === 'posts');
|
|
12
|
+
|
|
13
|
+
expect(posts).toMatchObject({
|
|
14
|
+
name: 'posts',
|
|
15
|
+
fields: [{ type: 'string', name: 'title' }],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
posts.schema = 'test';
|
|
19
|
+
|
|
20
|
+
const modules2 = await reader.read();
|
|
21
|
+
const posts2 = modules2.find((m) => m.name === 'posts');
|
|
22
|
+
expect(posts2.schema).toBeFalsy();
|
|
11
23
|
});
|
|
12
24
|
|
|
13
25
|
test('extend', async () => {
|
|
@@ -8,9 +8,7 @@ describe('collection', () => {
|
|
|
8
8
|
let db: Database;
|
|
9
9
|
|
|
10
10
|
beforeEach(async () => {
|
|
11
|
-
db = mockDatabase(
|
|
12
|
-
logging: console.log,
|
|
13
|
-
});
|
|
11
|
+
db = mockDatabase();
|
|
14
12
|
|
|
15
13
|
await db.clean({ drop: true });
|
|
16
14
|
});
|
|
@@ -240,9 +238,15 @@ describe('collection sync', () => {
|
|
|
240
238
|
await collection.sync();
|
|
241
239
|
const tableFields = await (<any>collection.model).queryInterface.describeTable(`${db.getTablePrefix()}users`);
|
|
242
240
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
if (db.options.underscored) {
|
|
242
|
+
expect(tableFields).toHaveProperty('first_name');
|
|
243
|
+
expect(tableFields).toHaveProperty('last_name');
|
|
244
|
+
expect(tableFields).toHaveProperty('age');
|
|
245
|
+
} else {
|
|
246
|
+
expect(tableFields).toHaveProperty('firstName');
|
|
247
|
+
expect(tableFields).toHaveProperty('lastName');
|
|
248
|
+
expect(tableFields).toHaveProperty('age');
|
|
249
|
+
}
|
|
246
250
|
});
|
|
247
251
|
|
|
248
252
|
test('sync with association not exists', async () => {
|
|
@@ -290,9 +294,15 @@ describe('collection sync', () => {
|
|
|
290
294
|
|
|
291
295
|
const model = collection.model;
|
|
292
296
|
await collection.sync();
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
297
|
+
if (db.options.underscored) {
|
|
298
|
+
const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}posts_tags`);
|
|
299
|
+
expect(tableFields['post_id']).toBeDefined();
|
|
300
|
+
expect(tableFields['tag_id']).toBeDefined();
|
|
301
|
+
} else {
|
|
302
|
+
const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}postsTags`);
|
|
303
|
+
expect(tableFields['postId']).toBeDefined();
|
|
304
|
+
expect(tableFields['tagId']).toBeDefined();
|
|
305
|
+
}
|
|
296
306
|
});
|
|
297
307
|
|
|
298
308
|
test('limit table name length', async () => {
|
|
@@ -285,4 +285,36 @@ describe('database', () => {
|
|
|
285
285
|
test.customMethod();
|
|
286
286
|
expect(test.get('abc')).toBe('abc');
|
|
287
287
|
});
|
|
288
|
+
|
|
289
|
+
test('getFieldByPath', () => {
|
|
290
|
+
db.collection({
|
|
291
|
+
name: 'users',
|
|
292
|
+
fields: [{ type: 'hasMany', name: 'p', target: 'posts' }],
|
|
293
|
+
});
|
|
294
|
+
db.collection({
|
|
295
|
+
name: 'comments',
|
|
296
|
+
fields: [{ type: 'string', name: 'title' }],
|
|
297
|
+
});
|
|
298
|
+
db.collection({
|
|
299
|
+
name: 'posts',
|
|
300
|
+
fields: [
|
|
301
|
+
{ type: 'hasMany', name: 'c', target: 'comments' },
|
|
302
|
+
{ type: 'belongsToMany', name: 't', target: 'tags' },
|
|
303
|
+
],
|
|
304
|
+
});
|
|
305
|
+
db.collection({
|
|
306
|
+
name: 'tags',
|
|
307
|
+
fields: [{ type: 'string', name: 'title' }],
|
|
308
|
+
});
|
|
309
|
+
const f1 = db.getFieldByPath('users.p.t');
|
|
310
|
+
const f2 = db.getFieldByPath('users.p.c');
|
|
311
|
+
const f3 = db.getFieldByPath('users.p');
|
|
312
|
+
expect(f1.name).toBe('t');
|
|
313
|
+
expect(f2.name).toBe('c');
|
|
314
|
+
expect(f3.name).toBe('p');
|
|
315
|
+
expect(db.getFieldByPath('users.d')).toBeNull;
|
|
316
|
+
expect(db.getFieldByPath('users.d.e')).toBeNull;
|
|
317
|
+
expect(db.getFieldByPath('users.p.f')).toBeNull;
|
|
318
|
+
expect(db.getFieldByPath('users.p.c.j')).toBeNull;
|
|
319
|
+
});
|
|
288
320
|
});
|
|
@@ -17,6 +17,29 @@ describe('string field', () => {
|
|
|
17
17
|
await db.close();
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
+
it('should init sorted value by createdAt when primaryKey not exists', async () => {
|
|
21
|
+
const Test = db.collection({
|
|
22
|
+
autoGenId: false,
|
|
23
|
+
name: 'tests',
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
await db.sync();
|
|
27
|
+
await Test.repository.create({
|
|
28
|
+
values: [{}, {}, {}],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// add sort field
|
|
32
|
+
Test.setField('sort', { type: 'sort' });
|
|
33
|
+
|
|
34
|
+
let err;
|
|
35
|
+
try {
|
|
36
|
+
await db.sync();
|
|
37
|
+
} catch (e) {
|
|
38
|
+
err = e;
|
|
39
|
+
}
|
|
40
|
+
expect(err).toBeFalsy();
|
|
41
|
+
});
|
|
42
|
+
|
|
20
43
|
it('sort', async () => {
|
|
21
44
|
const Test = db.collection({
|
|
22
45
|
name: 'tests',
|
|
@@ -886,11 +886,13 @@ pgOnly()('collection inherits', () => {
|
|
|
886
886
|
|
|
887
887
|
const studentTableInfo = await db.sequelize.getQueryInterface().describeTable(student.model.tableName);
|
|
888
888
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
expect(studentTableInfo
|
|
892
|
-
expect(studentTableInfo
|
|
893
|
-
expect(studentTableInfo
|
|
889
|
+
const getField = (name) => student.model.rawAttributes[name].field;
|
|
890
|
+
|
|
891
|
+
expect(studentTableInfo[getField('score')]).toBeDefined();
|
|
892
|
+
expect(studentTableInfo[getField('name')]).toBeDefined();
|
|
893
|
+
expect(studentTableInfo[getField('id')]).toBeDefined();
|
|
894
|
+
expect(studentTableInfo[getField('createdAt')]).toBeDefined();
|
|
895
|
+
expect(studentTableInfo[getField('updatedAt')]).toBeDefined();
|
|
894
896
|
});
|
|
895
897
|
|
|
896
898
|
it('should get parent fields', async () => {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { percent2float } from '../utils';
|
|
2
|
+
|
|
3
|
+
describe('percent2float', () => {
|
|
4
|
+
it('should be NaN', () => {
|
|
5
|
+
expect(percent2float('123')).toBe(NaN);
|
|
6
|
+
expect(percent2float('3a')).toBe(NaN);
|
|
7
|
+
expect(percent2float('3a%')).toBe(NaN);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should be a floating point number', () => {
|
|
11
|
+
expect(percent2float('123%')).toBe(1.23);
|
|
12
|
+
expect(percent2float('22.5507%')).toBe(0.225507); // not 0.22550699999999999
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { mockDatabase } from '../index';
|
|
2
|
+
import { Database } from '../../database';
|
|
3
|
+
import { randomStr } from '@nocobase/test';
|
|
4
|
+
|
|
5
|
+
describe('auth', () => {
|
|
6
|
+
let db: Database;
|
|
7
|
+
afterEach(async () => {
|
|
8
|
+
if (db) {
|
|
9
|
+
await db.close();
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should auto create schema on prepare when schema missing', async () => {
|
|
14
|
+
const schemaName = randomStr();
|
|
15
|
+
|
|
16
|
+
db = mockDatabase({
|
|
17
|
+
schema: schemaName,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!db.inDialect('postgres')) return;
|
|
21
|
+
|
|
22
|
+
const querySchemaExists = async () =>
|
|
23
|
+
await db.sequelize.query(
|
|
24
|
+
`SELECT schema_name
|
|
25
|
+
FROM information_schema.schemata
|
|
26
|
+
WHERE schema_name = '${schemaName}';`,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
expect((await querySchemaExists())[0].length).toEqual(0);
|
|
30
|
+
await db.prepare();
|
|
31
|
+
expect((await querySchemaExists())[0].length).toEqual(1);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('postgres schema', () => {
|
|
36
|
+
let db: Database;
|
|
37
|
+
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
db = mockDatabase({
|
|
40
|
+
schema: 'test_schema',
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (!db.inDialect('postgres')) return;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterEach(async () => {
|
|
47
|
+
if (db.inDialect('postgres')) {
|
|
48
|
+
await db.sequelize.query(`DROP SCHEMA IF EXISTS ${db.options.schema} CASCADE;`);
|
|
49
|
+
}
|
|
50
|
+
await db.close();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should drop all tables in schemas', async () => {
|
|
54
|
+
if (!db.inDialect('postgres')) return;
|
|
55
|
+
|
|
56
|
+
const collection = db.collection({
|
|
57
|
+
name: 'test',
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await db.sync();
|
|
61
|
+
|
|
62
|
+
await db.clean({ drop: true });
|
|
63
|
+
|
|
64
|
+
const tableInfo = await db.sequelize.query(
|
|
65
|
+
`SELECT *
|
|
66
|
+
FROM information_schema.tables
|
|
67
|
+
where table_schema = '${db.options.schema}'`,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
expect(tableInfo[0].length).toEqual(0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should support database schema option', async () => {
|
|
74
|
+
if (!db.inDialect('postgres')) return;
|
|
75
|
+
|
|
76
|
+
await db.clean({ drop: true });
|
|
77
|
+
|
|
78
|
+
const tableInfo = await db.sequelize.query(
|
|
79
|
+
`SELECT *
|
|
80
|
+
FROM information_schema.tables
|
|
81
|
+
where table_schema = '${db.options.schema}'`,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(tableInfo[0].length).toEqual(0);
|
|
85
|
+
|
|
86
|
+
const collection = db.collection({
|
|
87
|
+
name: 'test',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await db.sync();
|
|
91
|
+
|
|
92
|
+
const newTableInfo = await db.sequelize.query(
|
|
93
|
+
`SELECT *
|
|
94
|
+
FROM information_schema.tables
|
|
95
|
+
where table_schema = '${db.options.schema}'`,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
expect(newTableInfo[0].find((item) => item['table_name'] == collection.model.tableName)).toBeTruthy();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should update schema options', async () => {
|
|
102
|
+
if (!db.inDialect('postgres')) return;
|
|
103
|
+
|
|
104
|
+
await db.clean({ drop: true });
|
|
105
|
+
|
|
106
|
+
const collection = db.collection({
|
|
107
|
+
name: 'test',
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await db.sync();
|
|
111
|
+
|
|
112
|
+
collection.updateOptions({
|
|
113
|
+
...collection.options,
|
|
114
|
+
schema: 'test',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// @ts-ignore
|
|
118
|
+
expect(collection.model._schema).toEqual('test');
|
|
119
|
+
});
|
|
120
|
+
});
|