@nocobase/database 1.7.0-beta.12 → 1.7.0-beta.14
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/belongs-to-array/belongs-to-array-repository.d.ts +2 -2
- package/lib/belongs-to-array/belongs-to-array-repository.js +6 -7
- package/lib/eager-loading/eager-loading-tree.js +20 -10
- package/lib/fields/datetime-no-tz-field.d.ts +1 -1
- package/lib/fields/datetime-no-tz-field.js +26 -25
- package/lib/fields/string-field.d.ts +4 -0
- package/lib/fields/string-field.js +8 -0
- package/lib/fields/text-field.d.ts +4 -0
- package/lib/fields/text-field.js +8 -0
- package/lib/query-interface/mysql-query-interface.d.ts +1 -0
- package/lib/query-interface/mysql-query-interface.js +3 -0
- package/lib/query-interface/postgres-query-interface.d.ts +1 -0
- package/lib/query-interface/postgres-query-interface.js +3 -0
- package/lib/query-interface/query-interface.d.ts +1 -0
- package/lib/query-interface/query-interface.js +4 -0
- package/lib/query-interface/sqlite-query-interface.d.ts +1 -0
- package/lib/query-interface/sqlite-query-interface.js +3 -0
- package/lib/relation-repository/hasmany-repository.js +7 -1
- package/lib/relation-repository/multiple-relation-repository.d.ts +4 -1
- package/lib/relation-repository/multiple-relation-repository.js +2 -2
- package/package.json +4 -4
|
@@ -31,8 +31,8 @@ export declare class BelongsToArrayAssociation {
|
|
|
31
31
|
targetKey: string;
|
|
32
32
|
});
|
|
33
33
|
get target(): import("sequelize/types").ModelStatic<Model<any, any>>;
|
|
34
|
-
generateInclude(): {
|
|
35
|
-
on:
|
|
34
|
+
generateInclude(parentAs?: string): {
|
|
35
|
+
on: void;
|
|
36
36
|
};
|
|
37
37
|
update(instance: Model, value: any, options?: UpdateAssociationOptions): Promise<void>;
|
|
38
38
|
}
|
|
@@ -78,19 +78,18 @@ const _BelongsToArrayAssociation = class _BelongsToArrayAssociation {
|
|
|
78
78
|
get target() {
|
|
79
79
|
return this.db.getModel(this.targetName);
|
|
80
80
|
}
|
|
81
|
-
generateInclude() {
|
|
82
|
-
if (this.db.sequelize.getDialect() !== "postgres") {
|
|
83
|
-
throw new Error("Filtering by many to many (array) associations is only supported on postgres");
|
|
84
|
-
}
|
|
81
|
+
generateInclude(parentAs) {
|
|
85
82
|
const targetCollection = this.db.getCollection(this.targetName);
|
|
86
83
|
const targetField = targetCollection.getField(this.targetKey);
|
|
87
84
|
const sourceCollection = this.db.getCollection(this.source.name);
|
|
88
85
|
const foreignField = sourceCollection.getField(this.foreignKey);
|
|
89
86
|
const queryInterface = this.db.sequelize.getQueryInterface();
|
|
90
|
-
const
|
|
91
|
-
const
|
|
87
|
+
const asLeft = parentAs ? `${parentAs}->${this.as}` : this.as;
|
|
88
|
+
const asRight = parentAs || this.source.collection.name;
|
|
89
|
+
const left = queryInterface.quoteIdentifiers(`${asLeft}.${targetField.columnName()}`);
|
|
90
|
+
const right = queryInterface.quoteIdentifiers(`${asRight}.${foreignField.columnName()}`);
|
|
92
91
|
return {
|
|
93
|
-
on: this.db.
|
|
92
|
+
on: this.db.queryInterface.generateJoinOnForJSONArray(left, right)
|
|
94
93
|
};
|
|
95
94
|
}
|
|
96
95
|
async update(instance, value, options = {}) {
|
|
@@ -85,6 +85,25 @@ const queryParentSQL = /* @__PURE__ */ __name((options) => {
|
|
|
85
85
|
)
|
|
86
86
|
SELECT ${q(targetKeyField)} AS ${q(targetKey)}, ${q(foreignKeyField)} AS ${q(foreignKey)} FROM cte`;
|
|
87
87
|
}, "queryParentSQL");
|
|
88
|
+
const processIncludes = /* @__PURE__ */ __name((includes, model, parentAs = "") => {
|
|
89
|
+
includes.forEach((include, index) => {
|
|
90
|
+
const association = model.associations[include.association];
|
|
91
|
+
if (association == null ? void 0 : association.generateInclude) {
|
|
92
|
+
includes[index] = {
|
|
93
|
+
...include,
|
|
94
|
+
...association.generateInclude(parentAs)
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (include.include && Array.isArray(include.include) && include.include.length > 0) {
|
|
98
|
+
const nextModel = association == null ? void 0 : association.target;
|
|
99
|
+
if (!nextModel) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
processIncludes(include.include, nextModel, parentAs ? `${parentAs}->${association.as}` : association.as);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return includes;
|
|
106
|
+
}, "processIncludes");
|
|
88
107
|
const _EagerLoadingTree = class _EagerLoadingTree {
|
|
89
108
|
root;
|
|
90
109
|
db;
|
|
@@ -208,22 +227,13 @@ const _EagerLoadingTree = class _EagerLoadingTree {
|
|
|
208
227
|
if (!primaryKeyField) {
|
|
209
228
|
throw new Error(`Model ${node.model.name} does not have primary key`);
|
|
210
229
|
}
|
|
211
|
-
includeForFilter.forEach((include, index) => {
|
|
212
|
-
const association = node.model.associations[include.association];
|
|
213
|
-
if ((association == null ? void 0 : association.associationType) == "BelongsToArray") {
|
|
214
|
-
includeForFilter[index] = {
|
|
215
|
-
...include,
|
|
216
|
-
...association.generateInclude()
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
230
|
const ids2 = (await node.model.findAll({
|
|
221
231
|
...this.rootQueryOptions,
|
|
222
232
|
includeIgnoreAttributes: false,
|
|
223
233
|
attributes: [primaryKeyField],
|
|
224
234
|
group: `${node.model.name}.${primaryKeyField}`,
|
|
225
235
|
transaction,
|
|
226
|
-
include: includeForFilter
|
|
236
|
+
include: processIncludes(includeForFilter, node.model)
|
|
227
237
|
})).map((row) => {
|
|
228
238
|
return { row, pk: row[primaryKeyField] };
|
|
229
239
|
});
|
|
@@ -13,7 +13,7 @@ declare class DatetimeNoTzTypeMySQL extends DataTypes.ABSTRACT {
|
|
|
13
13
|
}
|
|
14
14
|
export declare class DatetimeNoTzField extends Field {
|
|
15
15
|
get dataType(): typeof DatetimeNoTzTypeMySQL;
|
|
16
|
-
|
|
16
|
+
beforeSave: (instance: any, options: any) => Promise<void>;
|
|
17
17
|
additionalSequelizeOptions(): {};
|
|
18
18
|
bind(): void;
|
|
19
19
|
unbind(): void;
|
|
@@ -61,48 +61,49 @@ const _DatetimeNoTzField = class _DatetimeNoTzField extends import_field.Field {
|
|
|
61
61
|
if (this.database.isMySQLCompatibleDialect()) {
|
|
62
62
|
return DatetimeNoTzTypeMySQL;
|
|
63
63
|
}
|
|
64
|
-
return import_sequelize.DataTypes.
|
|
64
|
+
return import_sequelize.DataTypes.DATE;
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
beforeSave = /* @__PURE__ */ __name(async (instance, options) => {
|
|
67
67
|
const { name, defaultToCurrentTime, onUpdateToCurrentTime } = this.options;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
};
|
|
79
|
-
}
|
|
68
|
+
const value = instance.get(name);
|
|
69
|
+
if (!value && instance.isNewRecord && defaultToCurrentTime) {
|
|
70
|
+
instance.set(name, /* @__PURE__ */ new Date());
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (onUpdateToCurrentTime) {
|
|
74
|
+
instance.set(name, /* @__PURE__ */ new Date());
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}, "beforeSave");
|
|
80
78
|
additionalSequelizeOptions() {
|
|
81
79
|
const { name } = this.options;
|
|
82
80
|
const timezone = this.database.options.rawTimezone || "+00:00";
|
|
83
81
|
const isPg = this.database.inDialect("postgres");
|
|
82
|
+
const isMySQLCompatibleDialect = this.database.isMySQLCompatibleDialect();
|
|
84
83
|
return {
|
|
85
84
|
get() {
|
|
86
85
|
const val = this.getDataValue(name);
|
|
87
86
|
if (val instanceof Date) {
|
|
88
|
-
|
|
89
|
-
return (0, import_moment.default)(val).format("YYYY-MM-DD HH:mm:ss");
|
|
90
|
-
}
|
|
91
|
-
const momentVal = (0, import_moment.default)(val).utcOffset(timezone);
|
|
87
|
+
const momentVal = (0, import_moment.default)(val);
|
|
92
88
|
return momentVal.format("YYYY-MM-DD HH:mm:ss");
|
|
93
89
|
}
|
|
94
90
|
return val;
|
|
95
91
|
},
|
|
96
92
|
set(val) {
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
if (val == null) {
|
|
94
|
+
return this.setDataValue(name, null);
|
|
95
|
+
}
|
|
96
|
+
const dateOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
97
|
+
const momentVal = (0, import_moment.default)(val);
|
|
98
|
+
if (typeof val === "string" && isIso8601(val) || val instanceof Date) {
|
|
99
|
+
momentVal.utcOffset(timezone);
|
|
100
|
+
momentVal.utcOffset(-dateOffset, true);
|
|
100
101
|
}
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
val = momentVal.format("YYYY-MM-DD HH:mm:ss");
|
|
102
|
+
if (isMySQLCompatibleDialect) {
|
|
103
|
+
momentVal.millisecond(0);
|
|
104
104
|
}
|
|
105
|
-
|
|
105
|
+
const date = momentVal.toDate();
|
|
106
|
+
return this.setDataValue(name, date);
|
|
106
107
|
}
|
|
107
108
|
};
|
|
108
109
|
}
|
|
@@ -10,8 +10,12 @@ import { DataTypes } from 'sequelize';
|
|
|
10
10
|
import { BaseColumnFieldOptions, Field } from './field';
|
|
11
11
|
export declare class StringField extends Field {
|
|
12
12
|
get dataType(): DataTypes.StringDataTypeConstructor | DataTypes.StringDataType;
|
|
13
|
+
additionalSequelizeOptions(): {
|
|
14
|
+
set(value: any): void;
|
|
15
|
+
};
|
|
13
16
|
}
|
|
14
17
|
export interface StringFieldOptions extends BaseColumnFieldOptions {
|
|
15
18
|
type: 'string';
|
|
16
19
|
length?: number;
|
|
20
|
+
trim?: boolean;
|
|
17
21
|
}
|
|
@@ -39,6 +39,14 @@ const _StringField = class _StringField extends import_field.Field {
|
|
|
39
39
|
}
|
|
40
40
|
return import_sequelize.DataTypes.STRING;
|
|
41
41
|
}
|
|
42
|
+
additionalSequelizeOptions() {
|
|
43
|
+
const { name, trim } = this.options;
|
|
44
|
+
return {
|
|
45
|
+
set(value) {
|
|
46
|
+
this.setDataValue(name, trim ? value == null ? void 0 : value.trim() : value);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
42
50
|
};
|
|
43
51
|
__name(_StringField, "StringField");
|
|
44
52
|
let StringField = _StringField;
|
|
@@ -11,8 +11,12 @@ import { BaseColumnFieldOptions, Field } from './field';
|
|
|
11
11
|
export declare class TextField extends Field {
|
|
12
12
|
get dataType(): DataTypes.TextDataTypeConstructor | DataTypes.TextDataType;
|
|
13
13
|
init(): void;
|
|
14
|
+
additionalSequelizeOptions(): {
|
|
15
|
+
set(value: any): void;
|
|
16
|
+
};
|
|
14
17
|
}
|
|
15
18
|
export interface TextFieldOptions extends BaseColumnFieldOptions {
|
|
16
19
|
type: 'text';
|
|
17
20
|
length?: 'tiny' | 'medium' | 'long';
|
|
21
|
+
trim?: boolean;
|
|
18
22
|
}
|
package/lib/fields/text-field.js
CHANGED
|
@@ -44,6 +44,14 @@ const _TextField = class _TextField extends import_field.Field {
|
|
|
44
44
|
this.options.defaultValue = null;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
additionalSequelizeOptions() {
|
|
48
|
+
const { name, trim } = this.options;
|
|
49
|
+
return {
|
|
50
|
+
set(value) {
|
|
51
|
+
this.setDataValue(name, trim ? value == null ? void 0 : value.trim() : value);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
47
55
|
};
|
|
48
56
|
__name(_TextField, "TextField");
|
|
49
57
|
let TextField = _TextField;
|
|
@@ -129,6 +129,9 @@ const _MysqlQueryInterface = class _MysqlQueryInterface extends import_query_int
|
|
|
129
129
|
await this.db.sequelize.query(sql, { transaction });
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
+
generateJoinOnForJSONArray(left, right) {
|
|
133
|
+
return this.db.sequelize.literal(`JSON_CONTAINS(${right}, JSON_ARRAY(${left}))`);
|
|
134
|
+
}
|
|
132
135
|
};
|
|
133
136
|
__name(_MysqlQueryInterface, "MysqlQueryInterface");
|
|
134
137
|
let MysqlQueryInterface = _MysqlQueryInterface;
|
|
@@ -202,6 +202,9 @@ $BODY$
|
|
|
202
202
|
);
|
|
203
203
|
return res[0]["show_create_table"];
|
|
204
204
|
}
|
|
205
|
+
generateJoinOnForJSONArray(left, right) {
|
|
206
|
+
return this.db.sequelize.literal(`${left}=any(${right})`);
|
|
207
|
+
}
|
|
205
208
|
};
|
|
206
209
|
__name(_PostgresQueryInterface, "PostgresQueryInterface");
|
|
207
210
|
let PostgresQueryInterface = _PostgresQueryInterface;
|
|
@@ -57,6 +57,10 @@ const _QueryInterface = class _QueryInterface {
|
|
|
57
57
|
quoteIdentifier(identifier) {
|
|
58
58
|
return this.db.sequelize.getQueryInterface().queryGenerator.quoteIdentifier(identifier);
|
|
59
59
|
}
|
|
60
|
+
generateJoinOnForJSONArray(left, right) {
|
|
61
|
+
const dialect = this.db.sequelize.getDialect();
|
|
62
|
+
throw new Error(`Filtering by many to many (array) associations is not supported on ${dialect}`);
|
|
63
|
+
}
|
|
60
64
|
};
|
|
61
65
|
__name(_QueryInterface, "QueryInterface");
|
|
62
66
|
let QueryInterface = _QueryInterface;
|
|
@@ -136,6 +136,9 @@ const _SqliteQueryInterface = class _SqliteQueryInterface extends import_query_i
|
|
|
136
136
|
WHERE name = '${tableName}';`;
|
|
137
137
|
await this.db.sequelize.query(sql, { transaction });
|
|
138
138
|
}
|
|
139
|
+
generateJoinOnForJSONArray(left, right) {
|
|
140
|
+
return this.db.sequelize.literal(`${left} in (SELECT value from json_each(${right}))`);
|
|
141
|
+
}
|
|
139
142
|
};
|
|
140
143
|
__name(_SqliteQueryInterface, "SqliteQueryInterface");
|
|
141
144
|
let SqliteQueryInterface = _SqliteQueryInterface;
|
|
@@ -80,7 +80,13 @@ const _HasManyRepository = class _HasManyRepository extends import_multiple_rela
|
|
|
80
80
|
if (options && options["filter"]) {
|
|
81
81
|
const filterResult = this.parseFilter(options["filter"], options);
|
|
82
82
|
if (filterResult.include && filterResult.include.length > 0) {
|
|
83
|
-
return await this.destroyByFilter(
|
|
83
|
+
return await this.destroyByFilter(
|
|
84
|
+
{
|
|
85
|
+
filter: options["filter"],
|
|
86
|
+
filterByTk: options["filterByTk"]
|
|
87
|
+
},
|
|
88
|
+
transaction2
|
|
89
|
+
);
|
|
84
90
|
}
|
|
85
91
|
where.push(filterResult.where);
|
|
86
92
|
}
|
|
@@ -18,7 +18,10 @@ export declare abstract class MultipleRelationRepository extends RelationReposit
|
|
|
18
18
|
remove(options: TargetKey | TargetKey[] | AssociatedOptions): Promise<void>;
|
|
19
19
|
update(options?: UpdateOptions): Promise<any>;
|
|
20
20
|
destroy(options?: TargetKey | DestroyOptions): Promise<boolean>;
|
|
21
|
-
protected destroyByFilter(
|
|
21
|
+
protected destroyByFilter(options: {
|
|
22
|
+
filter?: Filter;
|
|
23
|
+
filterByTk?: TargetKey | TargetKey[];
|
|
24
|
+
}, transaction?: Transaction): Promise<boolean>;
|
|
22
25
|
protected filterHasInclude(filter: Filter, options?: any): boolean;
|
|
23
26
|
protected accessors(): MultiAssociationAccessors;
|
|
24
27
|
updateOrCreate(options: FirstOrCreateOptions): Promise<any>;
|
|
@@ -174,9 +174,9 @@ const _MultipleRelationRepository = class _MultipleRelationRepository extends im
|
|
|
174
174
|
async destroy(options) {
|
|
175
175
|
return false;
|
|
176
176
|
}
|
|
177
|
-
async destroyByFilter(
|
|
177
|
+
async destroyByFilter(options, transaction2) {
|
|
178
178
|
const instances = await this.find({
|
|
179
|
-
|
|
179
|
+
...options,
|
|
180
180
|
transaction: transaction2
|
|
181
181
|
});
|
|
182
182
|
return await this.destroy({
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "1.7.0-beta.
|
|
3
|
+
"version": "1.7.0-beta.14",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"license": "AGPL-3.0",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@nocobase/logger": "1.7.0-beta.
|
|
10
|
-
"@nocobase/utils": "1.7.0-beta.
|
|
9
|
+
"@nocobase/logger": "1.7.0-beta.14",
|
|
10
|
+
"@nocobase/utils": "1.7.0-beta.14",
|
|
11
11
|
"async-mutex": "^0.3.2",
|
|
12
12
|
"chalk": "^4.1.1",
|
|
13
13
|
"cron-parser": "4.4.0",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
39
39
|
"directory": "packages/database"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "9e557ad4739803ca87d54f279c90ff69511ccdee"
|
|
42
42
|
}
|