@nocobase/database 0.7.4-alpha.7 → 0.7.6-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.d.ts +7 -2
- package/lib/collection.js +20 -8
- package/lib/database.d.ts +2 -2
- package/lib/database.js +30 -6
- package/lib/decorators/must-have-filter-decorator.d.ts +2 -0
- package/lib/decorators/must-have-filter-decorator.js +25 -0
- package/lib/{transaction-decorator.d.ts → decorators/transaction-decorator.d.ts} +0 -0
- package/lib/{transaction-decorator.js → decorators/transaction-decorator.js} +1 -4
- package/lib/errors/identifier-error.d.ts +3 -0
- package/lib/errors/identifier-error.js +16 -0
- package/lib/fields/belongs-to-field.js +9 -0
- package/lib/fields/belongs-to-many-field.js +10 -0
- package/lib/fields/date-field.d.ts +1 -1
- package/lib/fields/date-field.js +1 -1
- package/lib/fields/field.d.ts +1 -1
- package/lib/fields/field.js +2 -3
- package/lib/fields/formula-field.d.ts +5 -5
- package/lib/fields/formula-field.js +123 -110
- package/lib/fields/has-many-field.js +9 -0
- package/lib/fields/has-one-field.js +9 -0
- package/lib/fields/index.d.ts +3 -1
- package/lib/fields/index.js +34 -1
- package/lib/fields/number-field.d.ts +6 -0
- package/lib/fields/number-field.js +10 -1
- package/lib/fields/radio-field.d.ts +3 -1
- package/lib/fields/radio-field.js +14 -11
- package/lib/fields/sequence-field.d.ts +31 -0
- package/lib/fields/sequence-field.js +299 -0
- package/lib/fields/sort-field.d.ts +4 -4
- package/lib/fields/sort-field.js +93 -80
- package/lib/filter-parser.js +10 -2
- package/lib/index.d.ts +1 -1
- package/lib/index.js +7 -0
- package/lib/magic-attribute-model.d.ts +1 -0
- package/lib/magic-attribute-model.js +207 -6
- package/lib/mock-database.js +1 -1
- package/lib/model.d.ts +5 -0
- package/lib/model.js +48 -6
- package/lib/operators/array.js +17 -9
- package/lib/operators/ne.d.ts +4 -0
- package/lib/operators/ne.js +3 -1
- package/lib/relation-repository/belongs-to-many-repository.js +6 -0
- package/lib/relation-repository/multiple-relation-repository.js +32 -9
- package/lib/relation-repository/relation-repository.js +7 -1
- package/lib/relation-repository/single-relation-repository.js +28 -0
- package/lib/repository.d.ts +6 -3
- package/lib/repository.js +42 -9
- package/lib/update-associations.js +48 -71
- package/lib/utils.d.ts +9 -0
- package/lib/utils.js +126 -0
- package/package.json +5 -3
- package/src/__tests__/collection.test.ts +47 -0
- package/src/__tests__/database.test.ts +2 -0
- package/src/__tests__/field-options/inddex.test.ts +43 -0
- package/src/__tests__/fields/array.test.ts +66 -0
- package/src/__tests__/fields/belongs-to-field.test.ts +35 -0
- package/src/__tests__/fields/belongs-to-many-field.test.ts +45 -0
- package/src/__tests__/fields/has-many-field.test.ts +22 -0
- package/src/__tests__/fields/has-one-field.test.ts +21 -0
- package/src/__tests__/fields/sequence-field.test.ts +455 -0
- package/src/__tests__/magic-attribute-model.test.ts +24 -0
- package/src/__tests__/model.changedWithAssociations.test.ts +46 -0
- package/src/__tests__/operator/ne.test.ts +12 -0
- package/src/__tests__/relation-repository/appends.test.ts +64 -0
- package/src/__tests__/relation-repository/belongs-to-many-repository.test.ts +23 -0
- package/src/__tests__/relation-repository/has-many-repository.test.ts +20 -0
- package/src/__tests__/relation-repository/hasone-repository.test.ts +68 -1
- package/src/__tests__/repository/find.test.ts +35 -0
- package/src/__tests__/repository/update.test.ts +35 -0
- package/src/__tests__/repository.test.ts +15 -0
- package/src/collection.ts +28 -13
- package/src/database.ts +18 -6
- package/src/decorators/must-have-filter-decorator.ts +17 -0
- package/src/{transaction-decorator.ts → decorators/transaction-decorator.ts} +1 -2
- package/src/errors/identifier-error.ts +6 -0
- package/src/fields/belongs-to-field.ts +9 -0
- package/src/fields/belongs-to-many-field.ts +15 -0
- package/src/fields/date-field.ts +1 -1
- package/src/fields/field.ts +3 -3
- package/src/fields/formula-field.ts +13 -13
- package/src/fields/has-many-field.ts +10 -0
- package/src/fields/has-one-field.ts +13 -0
- package/src/fields/index.ts +5 -2
- package/src/fields/number-field.ts +10 -0
- package/src/fields/radio-field.ts +22 -24
- package/src/fields/sequence-field.ts +200 -0
- package/src/fields/sort-field.ts +9 -9
- package/src/filter-parser.ts +6 -5
- package/src/index.ts +1 -1
- package/src/magic-attribute-model.ts +188 -6
- package/src/mock-database.ts +1 -1
- package/src/model.ts +34 -1
- package/src/operators/array.ts +17 -10
- package/src/operators/ne.ts +10 -6
- package/src/relation-repository/belongs-to-many-repository.ts +4 -0
- package/src/relation-repository/multiple-relation-repository.ts +26 -11
- package/src/relation-repository/relation-repository.ts +5 -1
- package/src/relation-repository/single-relation-repository.ts +27 -1
- package/src/repository.ts +40 -10
- package/src/update-associations.ts +41 -53
- package/src/utils.ts +71 -0
package/lib/utils.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.checkIdentifier = checkIdentifier;
|
|
7
|
+
exports.handleAppendsQuery = handleAppendsQuery;
|
|
8
|
+
exports.md5 = md5;
|
|
9
|
+
|
|
10
|
+
function _crypto() {
|
|
11
|
+
const data = _interopRequireDefault(require("crypto"));
|
|
12
|
+
|
|
13
|
+
_crypto = function _crypto() {
|
|
14
|
+
return data;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
var _identifierError = require("./errors/identifier-error");
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
25
|
+
|
|
26
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
27
|
+
|
|
28
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
29
|
+
|
|
30
|
+
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; } } }; }
|
|
31
|
+
|
|
32
|
+
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); }
|
|
33
|
+
|
|
34
|
+
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; }
|
|
35
|
+
|
|
36
|
+
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); } }
|
|
37
|
+
|
|
38
|
+
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); }); }; }
|
|
39
|
+
|
|
40
|
+
function handleAppendsQuery(_x) {
|
|
41
|
+
return _handleAppendsQuery.apply(this, arguments);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function _handleAppendsQuery() {
|
|
45
|
+
_handleAppendsQuery = _asyncToGenerator(function* (options) {
|
|
46
|
+
const templateModel = options.templateModel,
|
|
47
|
+
queryPromises = options.queryPromises;
|
|
48
|
+
const primaryKey = templateModel.constructor.primaryKeyAttribute;
|
|
49
|
+
const results = yield Promise.all(queryPromises);
|
|
50
|
+
let rows;
|
|
51
|
+
|
|
52
|
+
var _iterator = _createForOfIteratorHelper(results),
|
|
53
|
+
_step;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
57
|
+
const appendedResult = _step.value;
|
|
58
|
+
|
|
59
|
+
if (!rows) {
|
|
60
|
+
rows = appendedResult.rows;
|
|
61
|
+
|
|
62
|
+
if (rows.length == 0) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const modelOptions = templateModel['_options'];
|
|
67
|
+
|
|
68
|
+
var _iterator2 = _createForOfIteratorHelper(rows),
|
|
69
|
+
_step2;
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
73
|
+
const row = _step2.value;
|
|
74
|
+
row['_options'] = _objectSpread(_objectSpread({}, row['_options']), {}, {
|
|
75
|
+
include: modelOptions['include'],
|
|
76
|
+
includeNames: modelOptions['includeNames'],
|
|
77
|
+
includeMap: modelOptions['includeMap']
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
} catch (err) {
|
|
81
|
+
_iterator2.e(err);
|
|
82
|
+
} finally {
|
|
83
|
+
_iterator2.f();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (let i = 0; i < appendedResult.rows.length; i++) {
|
|
90
|
+
const appendingRow = appendedResult.rows[i];
|
|
91
|
+
const key = appendedResult.include.association;
|
|
92
|
+
const val = appendingRow.get(key);
|
|
93
|
+
const rowKey = appendingRow.get(primaryKey);
|
|
94
|
+
const targetIndex = rows.findIndex(row => row.get(primaryKey) === rowKey);
|
|
95
|
+
|
|
96
|
+
if (targetIndex === -1) {
|
|
97
|
+
throw new Error('target row not found');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
rows[targetIndex].set(key, val, {
|
|
101
|
+
raw: true
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
_iterator.e(err);
|
|
107
|
+
} finally {
|
|
108
|
+
_iterator.f();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return rows;
|
|
112
|
+
});
|
|
113
|
+
return _handleAppendsQuery.apply(this, arguments);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function md5(value) {
|
|
117
|
+
return _crypto().default.createHash('md5').update(value).digest('hex');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const MAX_IDENTIFIER_LENGTH = 63;
|
|
121
|
+
|
|
122
|
+
function checkIdentifier(value) {
|
|
123
|
+
if (value.length > MAX_IDENTIFIER_LENGTH) {
|
|
124
|
+
throw new _identifierError.IdentifierError(`Identifier ${value} is too long`);
|
|
125
|
+
}
|
|
126
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6-alpha.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -12,12 +12,14 @@
|
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@nocobase/utils": "0.7.
|
|
15
|
+
"@nocobase/utils": "0.7.6-alpha.1",
|
|
16
16
|
"async-mutex": "^0.3.2",
|
|
17
|
+
"cron-parser": "4.4.0",
|
|
17
18
|
"deepmerge": "^4.2.2",
|
|
18
19
|
"flat": "^5.0.2",
|
|
19
20
|
"glob": "^7.1.6",
|
|
20
21
|
"mathjs": "^10.6.1",
|
|
22
|
+
"moment": "2.x",
|
|
21
23
|
"semver": "^7.3.7",
|
|
22
24
|
"sequelize": "^6.9.0",
|
|
23
25
|
"umzug": "^3.1.1"
|
|
@@ -30,5 +32,5 @@
|
|
|
30
32
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
31
33
|
"directory": "packages/database"
|
|
32
34
|
},
|
|
33
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "f20ce011a9ac516dc6aec110979f063a0e63f923"
|
|
34
36
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Collection } from '../collection';
|
|
2
2
|
import { Database } from '../database';
|
|
3
3
|
import { mockDatabase } from './index';
|
|
4
|
+
import { IdentifierError } from '../errors/identifier-error';
|
|
4
5
|
|
|
5
6
|
describe('collection', () => {
|
|
6
7
|
let db: Database;
|
|
@@ -258,4 +259,50 @@ describe('collection sync', () => {
|
|
|
258
259
|
expect(tableFields['postId']).toBeDefined();
|
|
259
260
|
expect(tableFields['tagId']).toBeDefined();
|
|
260
261
|
});
|
|
262
|
+
|
|
263
|
+
test('limit table name length', async () => {
|
|
264
|
+
const longName =
|
|
265
|
+
'this_is_a_very_long_table_name_that_should_be_truncated_this_is_a_very_long_table_name_that_should_be_truncated';
|
|
266
|
+
|
|
267
|
+
let error;
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const collection = new Collection(
|
|
271
|
+
{
|
|
272
|
+
name: longName,
|
|
273
|
+
fields: [{ type: 'string', name: 'test' }],
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
database: db,
|
|
277
|
+
},
|
|
278
|
+
);
|
|
279
|
+
} catch (e) {
|
|
280
|
+
error = e;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test('limit field name length', async () => {
|
|
287
|
+
const longFieldName =
|
|
288
|
+
'this_is_a_very_long_field_name_that_should_be_truncated_this_is_a_very_long_field_name_that_should_be_truncated';
|
|
289
|
+
|
|
290
|
+
let error;
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
const collection = new Collection(
|
|
294
|
+
{
|
|
295
|
+
name: 'test',
|
|
296
|
+
fields: [{ type: 'string', name: longFieldName }],
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
database: db,
|
|
300
|
+
},
|
|
301
|
+
);
|
|
302
|
+
} catch (e) {
|
|
303
|
+
error = e;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
307
|
+
});
|
|
261
308
|
});
|
|
@@ -268,8 +268,10 @@ describe('database', () => {
|
|
|
268
268
|
});
|
|
269
269
|
|
|
270
270
|
await Test.sync();
|
|
271
|
+
expect(Test.model.prototype).toBeInstanceOf(CustomModel);
|
|
271
272
|
|
|
272
273
|
const test = await Test.model.create<any>();
|
|
274
|
+
expect(test).toBeInstanceOf(CustomModel);
|
|
273
275
|
test.customMethod();
|
|
274
276
|
expect(test.get('abc')).toBe('abc');
|
|
275
277
|
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mockDatabase } from '../';
|
|
2
|
+
import { Database } from '../../database';
|
|
3
|
+
import { md5 } from '../../utils';
|
|
4
|
+
|
|
5
|
+
describe('index field options', () => {
|
|
6
|
+
let db: Database;
|
|
7
|
+
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
db = mockDatabase();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(async () => {
|
|
13
|
+
await db.close();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('case 1', async () => {
|
|
17
|
+
const t1 = 't1234567890223456789032345678904234567890523456789';
|
|
18
|
+
const f1 = 'f1234567890223456789032345678904234567890523456789062345678901';
|
|
19
|
+
const f2 = 'f1234567890223456789032345678904234567890523456789062345678902';
|
|
20
|
+
db.collection({
|
|
21
|
+
name: t1,
|
|
22
|
+
fields: [
|
|
23
|
+
{
|
|
24
|
+
type: 'string',
|
|
25
|
+
name: f1,
|
|
26
|
+
index: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: 'string',
|
|
30
|
+
name: f2,
|
|
31
|
+
index: true,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
await db.sync();
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
const indexes = db.getModel(t1)._indexes;
|
|
38
|
+
const index1 = indexes.find((item) => item.fields.includes(f1));
|
|
39
|
+
const index2 = indexes.find((item) => item.fields.includes(f2));
|
|
40
|
+
expect('i_' + md5(db.getTablePrefix() + `${t1}_${f1}`)).toBe(index1.name);
|
|
41
|
+
expect('i_' + md5(db.getTablePrefix() + `${t1}_${f2}`)).toBe(index2.name);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { mockDatabase } from '../';
|
|
2
|
+
import { Database } from '../../database';
|
|
3
|
+
|
|
4
|
+
describe('array field', () => {
|
|
5
|
+
let db: Database;
|
|
6
|
+
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
db = mockDatabase();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await db.close();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should not be ambiguous', async () => {
|
|
16
|
+
db.collection({
|
|
17
|
+
name: 'a',
|
|
18
|
+
fields: [
|
|
19
|
+
{
|
|
20
|
+
type: 'array',
|
|
21
|
+
name: 'arr',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'belongsToMany',
|
|
25
|
+
name: 'b',
|
|
26
|
+
target: 'b',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
db.collection({
|
|
31
|
+
name: 'b',
|
|
32
|
+
fields: [
|
|
33
|
+
{
|
|
34
|
+
type: 'array',
|
|
35
|
+
name: 'arr',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
await db.sync();
|
|
40
|
+
const repository = db.getRepository('a');
|
|
41
|
+
await repository.find({
|
|
42
|
+
filter: {
|
|
43
|
+
'arr.$match': ['aa'],
|
|
44
|
+
},
|
|
45
|
+
appends: ['b'],
|
|
46
|
+
});
|
|
47
|
+
await repository.find({
|
|
48
|
+
filter: {
|
|
49
|
+
'arr.$notMatch': ['aa'],
|
|
50
|
+
},
|
|
51
|
+
appends: ['b'],
|
|
52
|
+
});
|
|
53
|
+
await repository.find({
|
|
54
|
+
filter: {
|
|
55
|
+
'arr.$anyOf': ['aa'],
|
|
56
|
+
},
|
|
57
|
+
appends: ['b'],
|
|
58
|
+
});
|
|
59
|
+
await repository.find({
|
|
60
|
+
filter: {
|
|
61
|
+
'arr.$noneOf': ['aa'],
|
|
62
|
+
},
|
|
63
|
+
appends: ['b'],
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Database } from '../../database';
|
|
2
2
|
import { mockDatabase } from '../';
|
|
3
|
+
import { IdentifierError } from '../../errors/identifier-error';
|
|
3
4
|
|
|
4
5
|
describe('belongs to field', () => {
|
|
5
6
|
let db: Database;
|
|
@@ -28,12 +29,16 @@ describe('belongs to field', () => {
|
|
|
28
29
|
{ type: 'belongsTo', name: 'post' },
|
|
29
30
|
],
|
|
30
31
|
});
|
|
32
|
+
|
|
31
33
|
expect(Comment.model.associations.post).toBeUndefined();
|
|
34
|
+
|
|
32
35
|
const Post = db.collection({
|
|
33
36
|
name: 'posts',
|
|
34
37
|
fields: [{ type: 'string', name: 'title' }],
|
|
35
38
|
});
|
|
39
|
+
|
|
36
40
|
const association = Comment.model.associations.post;
|
|
41
|
+
|
|
37
42
|
expect(Comment.model.associations.post).toBeDefined();
|
|
38
43
|
expect(association.foreignKey).toBe('postId');
|
|
39
44
|
// @ts-ignore
|
|
@@ -77,11 +82,41 @@ describe('belongs to field', () => {
|
|
|
77
82
|
const association = Comment.model.associations.post;
|
|
78
83
|
expect(association).toBeDefined();
|
|
79
84
|
expect(association.foreignKey).toBe('postKey');
|
|
85
|
+
|
|
80
86
|
// @ts-ignore
|
|
81
87
|
expect(association.targetKey).toBe('key');
|
|
82
88
|
expect(Comment.model.rawAttributes['postKey']).toBeDefined();
|
|
83
89
|
});
|
|
84
90
|
|
|
91
|
+
it('should throw error when foreignKey is too long', async () => {
|
|
92
|
+
const Post = db.collection({
|
|
93
|
+
name: 'posts',
|
|
94
|
+
fields: [{ type: 'string', name: 'key', unique: true }],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const longForeignKey = 'a'.repeat(128);
|
|
98
|
+
|
|
99
|
+
let error;
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const Comment = db.collection({
|
|
103
|
+
name: 'comments1',
|
|
104
|
+
fields: [
|
|
105
|
+
{
|
|
106
|
+
type: 'belongsTo',
|
|
107
|
+
name: 'post',
|
|
108
|
+
targetKey: 'key',
|
|
109
|
+
foreignKey: longForeignKey,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
} catch (e) {
|
|
114
|
+
error = e;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
118
|
+
});
|
|
119
|
+
|
|
85
120
|
it('custom name and target', async () => {
|
|
86
121
|
const Comment = db.collection({
|
|
87
122
|
name: 'comments',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mockDatabase } from '../';
|
|
2
2
|
import { Database } from '../../database';
|
|
3
|
+
import { IdentifierError } from '../../errors/identifier-error';
|
|
3
4
|
|
|
4
5
|
describe('belongs to many field', () => {
|
|
5
6
|
let db: Database;
|
|
@@ -58,4 +59,48 @@ describe('belongs to many field', () => {
|
|
|
58
59
|
expect(PostTag.model.rawAttributes['postId']).toBeDefined();
|
|
59
60
|
expect(PostTag.model.rawAttributes['tagId']).toBeDefined();
|
|
60
61
|
});
|
|
62
|
+
|
|
63
|
+
it('should throw error when foreignKey is too long', async () => {
|
|
64
|
+
const Post = db.collection({
|
|
65
|
+
name: 'posts',
|
|
66
|
+
fields: [
|
|
67
|
+
{ type: 'string', name: 'name' },
|
|
68
|
+
{ type: 'belongsToMany', name: 'tags', foreignKey: 'a'.repeat(128) },
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
let error;
|
|
73
|
+
try {
|
|
74
|
+
const Tag = db.collection({
|
|
75
|
+
name: 'tags',
|
|
76
|
+
fields: [{ type: 'string', name: 'name' }],
|
|
77
|
+
});
|
|
78
|
+
} catch (e) {
|
|
79
|
+
error = e;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should throw error when through is too long', async () => {
|
|
86
|
+
const Post = db.collection({
|
|
87
|
+
name: 'posts',
|
|
88
|
+
fields: [
|
|
89
|
+
{ type: 'string', name: 'name' },
|
|
90
|
+
{ type: 'belongsToMany', name: 'tags', through: 'a'.repeat(128) },
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
let error;
|
|
95
|
+
try {
|
|
96
|
+
const Tag = db.collection({
|
|
97
|
+
name: 'tags',
|
|
98
|
+
fields: [{ type: 'string', name: 'name' }],
|
|
99
|
+
});
|
|
100
|
+
} catch (e) {
|
|
101
|
+
error = e;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
105
|
+
});
|
|
61
106
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Database } from '../../database';
|
|
2
2
|
import { mockDatabase } from '../';
|
|
3
3
|
import { makeWatchHost } from 'ts-loader/dist/servicesHost';
|
|
4
|
+
import { IdentifierError } from '../../errors/identifier-error';
|
|
4
5
|
|
|
5
6
|
describe('has many field', () => {
|
|
6
7
|
let db: Database;
|
|
@@ -149,4 +150,25 @@ describe('has many field', () => {
|
|
|
149
150
|
Comment.removeField('post');
|
|
150
151
|
expect(Comment.model.rawAttributes.postId).toBeUndefined();
|
|
151
152
|
});
|
|
153
|
+
|
|
154
|
+
it('should throw error when foreignKey is too long', async () => {
|
|
155
|
+
const longForeignKey = 'a'.repeat(64);
|
|
156
|
+
|
|
157
|
+
const Post = db.collection({
|
|
158
|
+
name: 'posts',
|
|
159
|
+
fields: [{ type: 'hasMany', name: 'comments', foreignKey: longForeignKey }],
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
let error;
|
|
163
|
+
try {
|
|
164
|
+
const Comment = db.collection({
|
|
165
|
+
name: 'comments',
|
|
166
|
+
fields: [{ type: 'belongsTo', name: 'post' }],
|
|
167
|
+
});
|
|
168
|
+
} catch (e) {
|
|
169
|
+
error = e;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
173
|
+
});
|
|
152
174
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Database } from '../../database';
|
|
2
2
|
import { mockDatabase } from '../';
|
|
3
|
+
import { IdentifierError } from '../../errors/identifier-error';
|
|
3
4
|
|
|
4
5
|
describe('has many field', () => {
|
|
5
6
|
let db: Database;
|
|
@@ -64,4 +65,24 @@ describe('has many field', () => {
|
|
|
64
65
|
Profile.removeField('user');
|
|
65
66
|
expect(Profile.model.rawAttributes.userId).toBeUndefined();
|
|
66
67
|
});
|
|
68
|
+
|
|
69
|
+
it('should throw error when foreignKey is too long', async () => {
|
|
70
|
+
const longForeignKey = 'a'.repeat(128);
|
|
71
|
+
|
|
72
|
+
const User = db.collection({
|
|
73
|
+
name: 'users',
|
|
74
|
+
fields: [{ type: 'hasOne', name: 'profile', foreignKey: longForeignKey }],
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
let error;
|
|
78
|
+
try {
|
|
79
|
+
const Profile = db.collection({
|
|
80
|
+
name: 'profiles',
|
|
81
|
+
fields: [{ type: 'belongsTo', name: 'user' }],
|
|
82
|
+
});
|
|
83
|
+
} catch (e) {
|
|
84
|
+
error = e;
|
|
85
|
+
}
|
|
86
|
+
expect(error).toBeInstanceOf(IdentifierError);
|
|
87
|
+
});
|
|
67
88
|
});
|