@nocobase/database 1.7.0-beta.2 → 1.7.0-beta.20

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.
Files changed (32) hide show
  1. package/lib/belongs-to-array/belongs-to-array-repository.d.ts +2 -2
  2. package/lib/belongs-to-array/belongs-to-array-repository.js +6 -7
  3. package/lib/collection.js +13 -2
  4. package/lib/eager-loading/eager-loading-tree.js +20 -10
  5. package/lib/fields/datetime-no-tz-field.d.ts +1 -1
  6. package/lib/fields/datetime-no-tz-field.js +26 -25
  7. package/lib/fields/string-field.d.ts +4 -0
  8. package/lib/fields/string-field.js +8 -0
  9. package/lib/fields/text-field.d.ts +4 -0
  10. package/lib/fields/text-field.js +8 -0
  11. package/lib/index.d.ts +7 -6
  12. package/lib/index.js +13 -11
  13. package/lib/interfaces/index.d.ts +1 -0
  14. package/lib/interfaces/index.js +3 -1
  15. package/lib/interfaces/time-interface.d.ts +13 -0
  16. package/lib/interfaces/time-interface.js +65 -0
  17. package/lib/interfaces/utils.js +2 -1
  18. package/lib/mock-database.d.ts +2 -1
  19. package/lib/mock-database.js +14 -2
  20. package/lib/query-interface/mysql-query-interface.d.ts +1 -0
  21. package/lib/query-interface/mysql-query-interface.js +3 -0
  22. package/lib/query-interface/postgres-query-interface.d.ts +1 -0
  23. package/lib/query-interface/postgres-query-interface.js +3 -0
  24. package/lib/query-interface/query-interface.d.ts +1 -0
  25. package/lib/query-interface/query-interface.js +4 -0
  26. package/lib/query-interface/sqlite-query-interface.d.ts +1 -0
  27. package/lib/query-interface/sqlite-query-interface.js +3 -0
  28. package/lib/relation-repository/belongs-to-many-repository.js +1 -1
  29. package/lib/relation-repository/hasmany-repository.js +7 -1
  30. package/lib/relation-repository/multiple-relation-repository.d.ts +4 -1
  31. package/lib/relation-repository/multiple-relation-repository.js +2 -2
  32. package/package.json +6 -6
@@ -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: import("sequelize/types/utils").Literal;
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 left = queryInterface.quoteIdentifiers(`${this.as}.${targetField.columnName()}`);
91
- const right = queryInterface.quoteIdentifiers(`${this.source.collection.name}.${foreignField.columnName()}`);
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.sequelize.literal(`${left}=any(${right})`)
92
+ on: this.db.queryInterface.generateJoinOnForJSONArray(left, right)
94
93
  };
95
94
  }
96
95
  async update(instance, value, options = {}) {
package/lib/collection.js CHANGED
@@ -287,9 +287,20 @@ const _Collection = class _Collection extends import_events.EventEmitter {
287
287
  if (!field) {
288
288
  return;
289
289
  }
290
- if (options.type !== field.type) {
291
- throw new Error(`fields with same column must be of the same type ${JSON.stringify(options)}`);
290
+ if (options.type === field.type) {
291
+ return;
292
+ }
293
+ const isContextTypeMatch = /* @__PURE__ */ __name((data, dataType) => {
294
+ var _a, _b;
295
+ return [(_a = data.dataType) == null ? void 0 : _a.key, (_b = data.type) == null ? void 0 : _b.toUpperCase()].includes(dataType == null ? void 0 : dataType.toUpperCase());
296
+ }, "isContextTypeMatch");
297
+ if (options.type === "context" && isContextTypeMatch(field, options.dataType)) {
298
+ return;
299
+ }
300
+ if (field.type === "context" && isContextTypeMatch(options, field.dataType.key)) {
301
+ return;
292
302
  }
303
+ throw new Error(`fields with same column must be of the same type ${JSON.stringify(options)}`);
293
304
  }
294
305
  /**
295
306
  * @internal
@@ -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
- init(): void;
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.STRING;
64
+ return import_sequelize.DataTypes.DATE;
65
65
  }
66
- init() {
66
+ beforeSave = /* @__PURE__ */ __name(async (instance, options) => {
67
67
  const { name, defaultToCurrentTime, onUpdateToCurrentTime } = this.options;
68
- this.beforeSave = async (instance, options) => {
69
- const value = instance.get(name);
70
- if (!value && instance.isNewRecord && defaultToCurrentTime) {
71
- instance.set(name, /* @__PURE__ */ new Date());
72
- return;
73
- }
74
- if (onUpdateToCurrentTime) {
75
- instance.set(name, /* @__PURE__ */ new Date());
76
- return;
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
- if (isPg) {
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 (typeof val === "string" && isIso8601(val)) {
98
- const momentVal = (0, import_moment.default)(val).utcOffset(timezone);
99
- val = momentVal.format("YYYY-MM-DD HH:mm:ss");
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 (val && val instanceof Date) {
102
- const momentVal = (0, import_moment.default)(val).utcOffset(timezone);
103
- val = momentVal.format("YYYY-MM-DD HH:mm:ss");
102
+ if (isMySQLCompatibleDialect) {
103
+ momentVal.millisecond(0);
104
104
  }
105
- return this.setDataValue(name, val);
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
  }
@@ -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;
package/lib/index.d.ts CHANGED
@@ -7,16 +7,20 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
  export { BaseError, BelongsToGetAssociationMixin, DataTypes, fn, HasManyCountAssociationsMixin, HasManyCreateAssociationMixin, HasManyGetAssociationsMixin, literal, ModelStatic, Op, SyncOptions, Transaction, UniqueConstraintError, ValidationError, ValidationErrorItem, where, } from 'sequelize';
10
+ export * from './belongs-to-array/belongs-to-array-repository';
10
11
  export * from './collection';
11
12
  export * from './collection-group-manager';
12
13
  export * from './collection-importer';
13
14
  export * from './database';
14
15
  export { Database as default } from './database';
16
+ export * from './dialects';
15
17
  export * from './field-repository/array-field-repository';
16
18
  export * from './fields';
17
19
  export * from './filter-match';
18
20
  export { default as FilterParser } from './filter-parser';
21
+ export * from './helpers';
19
22
  export * from './inherited-collection';
23
+ export * from './interfaces';
20
24
  export * from './magic-attribute-model';
21
25
  export * from './migration';
22
26
  export * from './mock-database';
@@ -24,17 +28,14 @@ export * from './model';
24
28
  export * from './relation-repository/belongs-to-many-repository';
25
29
  export * from './relation-repository/belongs-to-repository';
26
30
  export * from './relation-repository/hasmany-repository';
31
+ export * from './relation-repository/hasone-repository';
27
32
  export * from './relation-repository/multiple-relation-repository';
28
33
  export * from './relation-repository/single-relation-repository';
29
- export * from './belongs-to-array/belongs-to-array-repository';
30
34
  export * from './repository';
35
+ export { default as sqlParser, SQLParserTypes } from './sql-parser';
31
36
  export * from './update-associations';
32
37
  export { snakeCase } from './utils';
33
38
  export * from './value-parsers';
34
39
  export * from './view-collection';
35
- export * from './view/view-inference';
36
- export * from './helpers';
37
- export { default as sqlParser, SQLParserTypes } from './sql-parser';
38
- export * from './interfaces';
39
40
  export { default as fieldTypeMap } from './view/field-type-map';
40
- export * from './dialects';
41
+ export * from './view/view-inference';
package/lib/index.js CHANGED
@@ -62,16 +62,20 @@ __export(src_exports, {
62
62
  });
63
63
  module.exports = __toCommonJS(src_exports);
64
64
  var import_sequelize = require("sequelize");
65
+ __reExport(src_exports, require("./belongs-to-array/belongs-to-array-repository"), module.exports);
65
66
  __reExport(src_exports, require("./collection"), module.exports);
66
67
  __reExport(src_exports, require("./collection-group-manager"), module.exports);
67
68
  __reExport(src_exports, require("./collection-importer"), module.exports);
68
69
  __reExport(src_exports, require("./database"), module.exports);
69
70
  var import_database = require("./database");
71
+ __reExport(src_exports, require("./dialects"), module.exports);
70
72
  __reExport(src_exports, require("./field-repository/array-field-repository"), module.exports);
71
73
  __reExport(src_exports, require("./fields"), module.exports);
72
74
  __reExport(src_exports, require("./filter-match"), module.exports);
73
75
  var import_filter_parser = __toESM(require("./filter-parser"));
76
+ __reExport(src_exports, require("./helpers"), module.exports);
74
77
  __reExport(src_exports, require("./inherited-collection"), module.exports);
78
+ __reExport(src_exports, require("./interfaces"), module.exports);
75
79
  __reExport(src_exports, require("./magic-attribute-model"), module.exports);
76
80
  __reExport(src_exports, require("./migration"), module.exports);
77
81
  __reExport(src_exports, require("./mock-database"), module.exports);
@@ -79,20 +83,17 @@ __reExport(src_exports, require("./model"), module.exports);
79
83
  __reExport(src_exports, require("./relation-repository/belongs-to-many-repository"), module.exports);
80
84
  __reExport(src_exports, require("./relation-repository/belongs-to-repository"), module.exports);
81
85
  __reExport(src_exports, require("./relation-repository/hasmany-repository"), module.exports);
86
+ __reExport(src_exports, require("./relation-repository/hasone-repository"), module.exports);
82
87
  __reExport(src_exports, require("./relation-repository/multiple-relation-repository"), module.exports);
83
88
  __reExport(src_exports, require("./relation-repository/single-relation-repository"), module.exports);
84
- __reExport(src_exports, require("./belongs-to-array/belongs-to-array-repository"), module.exports);
85
89
  __reExport(src_exports, require("./repository"), module.exports);
90
+ var import_sql_parser = __toESM(require("./sql-parser"));
86
91
  __reExport(src_exports, require("./update-associations"), module.exports);
87
92
  var import_utils = require("./utils");
88
93
  __reExport(src_exports, require("./value-parsers"), module.exports);
89
94
  __reExport(src_exports, require("./view-collection"), module.exports);
90
- __reExport(src_exports, require("./view/view-inference"), module.exports);
91
- __reExport(src_exports, require("./helpers"), module.exports);
92
- var import_sql_parser = __toESM(require("./sql-parser"));
93
- __reExport(src_exports, require("./interfaces"), module.exports);
94
95
  var import_field_type_map = __toESM(require("./view/field-type-map"));
95
- __reExport(src_exports, require("./dialects"), module.exports);
96
+ __reExport(src_exports, require("./view/view-inference"), module.exports);
96
97
  // Annotate the CommonJS export names for ESM import in node:
97
98
  0 && (module.exports = {
98
99
  BaseError,
@@ -116,14 +117,18 @@ __reExport(src_exports, require("./dialects"), module.exports);
116
117
  snakeCase,
117
118
  sqlParser,
118
119
  where,
120
+ ...require("./belongs-to-array/belongs-to-array-repository"),
119
121
  ...require("./collection"),
120
122
  ...require("./collection-group-manager"),
121
123
  ...require("./collection-importer"),
122
124
  ...require("./database"),
125
+ ...require("./dialects"),
123
126
  ...require("./field-repository/array-field-repository"),
124
127
  ...require("./fields"),
125
128
  ...require("./filter-match"),
129
+ ...require("./helpers"),
126
130
  ...require("./inherited-collection"),
131
+ ...require("./interfaces"),
127
132
  ...require("./magic-attribute-model"),
128
133
  ...require("./migration"),
129
134
  ...require("./mock-database"),
@@ -131,15 +136,12 @@ __reExport(src_exports, require("./dialects"), module.exports);
131
136
  ...require("./relation-repository/belongs-to-many-repository"),
132
137
  ...require("./relation-repository/belongs-to-repository"),
133
138
  ...require("./relation-repository/hasmany-repository"),
139
+ ...require("./relation-repository/hasone-repository"),
134
140
  ...require("./relation-repository/multiple-relation-repository"),
135
141
  ...require("./relation-repository/single-relation-repository"),
136
- ...require("./belongs-to-array/belongs-to-array-repository"),
137
142
  ...require("./repository"),
138
143
  ...require("./update-associations"),
139
144
  ...require("./value-parsers"),
140
145
  ...require("./view-collection"),
141
- ...require("./view/view-inference"),
142
- ...require("./helpers"),
143
- ...require("./interfaces"),
144
- ...require("./dialects")
146
+ ...require("./view/view-inference")
145
147
  });
@@ -14,3 +14,4 @@ export * from './datetime-interface';
14
14
  export * from './datetime-no-tz-interface';
15
15
  export * from './boolean-interface';
16
16
  export * from './date-interface';
17
+ export * from './time-interface';
@@ -31,6 +31,7 @@ __reExport(interfaces_exports, require("./datetime-interface"), module.exports);
31
31
  __reExport(interfaces_exports, require("./datetime-no-tz-interface"), module.exports);
32
32
  __reExport(interfaces_exports, require("./boolean-interface"), module.exports);
33
33
  __reExport(interfaces_exports, require("./date-interface"), module.exports);
34
+ __reExport(interfaces_exports, require("./time-interface"), module.exports);
34
35
  // Annotate the CommonJS export names for ESM import in node:
35
36
  0 && (module.exports = {
36
37
  ...require("./base-interface"),
@@ -40,5 +41,6 @@ __reExport(interfaces_exports, require("./date-interface"), module.exports);
40
41
  ...require("./datetime-interface"),
41
42
  ...require("./datetime-no-tz-interface"),
42
43
  ...require("./boolean-interface"),
43
- ...require("./date-interface")
44
+ ...require("./date-interface"),
45
+ ...require("./time-interface")
44
46
  });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { BaseInterface } from './base-interface';
10
+ export declare class TimeInterface extends BaseInterface {
11
+ toValue(value: any, ctx?: any): any;
12
+ validate(value: any): boolean;
13
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
17
+ var __export = (target, all) => {
18
+ for (var name in all)
19
+ __defProp(target, name, { get: all[name], enumerable: true });
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (let key of __getOwnPropNames(from))
24
+ if (!__hasOwnProp.call(to, key) && key !== except)
25
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
26
+ }
27
+ return to;
28
+ };
29
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
30
+ // If the importer is in node compatibility mode or this is not an ESM
31
+ // file that has been converted to a CommonJS file using a Babel-
32
+ // compatible transform (i.e. "__esModule" has not been set), then set
33
+ // "default" to the CommonJS "module.exports" for node compatibility.
34
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
35
+ mod
36
+ ));
37
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
38
+ var time_interface_exports = {};
39
+ __export(time_interface_exports, {
40
+ TimeInterface: () => TimeInterface
41
+ });
42
+ module.exports = __toCommonJS(time_interface_exports);
43
+ var import_dayjs = __toESM(require("dayjs"));
44
+ var import_utc = __toESM(require("dayjs/plugin/utc"));
45
+ var import_base_interface = require("./base-interface");
46
+ import_dayjs.default.extend(import_utc.default);
47
+ const _TimeInterface = class _TimeInterface extends import_base_interface.BaseInterface {
48
+ toValue(value, ctx) {
49
+ if (this.validate(value)) {
50
+ const result = import_dayjs.default.utc(value).format("HH:mm:ss");
51
+ return result;
52
+ }
53
+ return value;
54
+ }
55
+ validate(value) {
56
+ const result = (0, import_dayjs.default)(value).isValid();
57
+ return result;
58
+ }
59
+ };
60
+ __name(_TimeInterface, "TimeInterface");
61
+ let TimeInterface = _TimeInterface;
62
+ // Annotate the CommonJS export names for ESM import in node:
63
+ 0 && (module.exports = {
64
+ TimeInterface
65
+ });
@@ -62,7 +62,8 @@ const interfaces = {
62
62
  obo: import_one_belongs_to_one_interface.OneBelongsToOneInterface,
63
63
  o2m: import_one_to_many_interface.OneToManyInterface,
64
64
  m2o: import_many_to_one_interface.ManyToOneInterface,
65
- m2m: import_many_to_many_interface.ManyToManyInterface
65
+ m2m: import_many_to_many_interface.ManyToManyInterface,
66
+ time: import_index.TimeInterface
66
67
  };
67
68
  function registerInterfaces(db) {
68
69
  for (const [interfaceName, type] of Object.entries(interfaces)) {
@@ -6,7 +6,7 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Database, IDatabaseOptions } from './database';
9
+ import { Database, IDatabaseOptions } from '@nocobase/database';
10
10
  export declare class MockDatabase extends Database {
11
11
  constructor(options: IDatabaseOptions);
12
12
  }
@@ -29,5 +29,6 @@ export declare function getConfigByEnv(): {
29
29
  dialectOptions: {};
30
30
  };
31
31
  declare function customLogger(queryString: any, queryObject: any): void;
32
+ export declare function createMockDatabase(options?: IDatabaseOptions): Promise<MockDatabase>;
32
33
  export declare function mockDatabase(options?: IDatabaseOptions): MockDatabase;
33
34
  export {};
@@ -38,15 +38,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
38
38
  var mock_database_exports = {};
39
39
  __export(mock_database_exports, {
40
40
  MockDatabase: () => MockDatabase,
41
+ createMockDatabase: () => createMockDatabase,
41
42
  getConfigByEnv: () => getConfigByEnv,
42
43
  mockDatabase: () => mockDatabase
43
44
  });
44
45
  module.exports = __toCommonJS(mock_database_exports);
46
+ var import_database = require("@nocobase/database");
45
47
  var import_utils = require("@nocobase/utils");
46
48
  var import_nanoid = require("nanoid");
47
49
  var import_node_fetch = __toESM(require("node-fetch"));
48
50
  var import_path = __toESM(require("path"));
49
- var import_database = require("./database");
50
51
  /* istanbul ignore file -- @preserve */
51
52
  const _MockDatabase = class _MockDatabase extends import_database.Database {
52
53
  constructor(options) {
@@ -91,8 +92,18 @@ function customLogger(queryString, queryObject) {
91
92
  }
92
93
  }
93
94
  __name(customLogger, "customLogger");
95
+ async function createMockDatabase(options = {}) {
96
+ try {
97
+ const { runPluginStaticImports } = await import("@nocobase/server");
98
+ await runPluginStaticImports();
99
+ } catch (error) {
100
+ }
101
+ return mockDatabase(options);
102
+ }
103
+ __name(createMockDatabase, "createMockDatabase");
94
104
  function mockDatabase(options = {}) {
95
105
  const dbOptions = (0, import_utils.merge)(getConfigByEnv(), options);
106
+ let db;
96
107
  if (process.env["DB_TEST_PREFIX"]) {
97
108
  let configKey = "database";
98
109
  if (dbOptions.dialect === "sqlite") {
@@ -124,13 +135,14 @@ function mockDatabase(options = {}) {
124
135
  };
125
136
  }
126
137
  }
127
- const db = new MockDatabase(dbOptions);
138
+ db = new MockDatabase(dbOptions);
128
139
  return db;
129
140
  }
130
141
  __name(mockDatabase, "mockDatabase");
131
142
  // Annotate the CommonJS export names for ESM import in node:
132
143
  0 && (module.exports = {
133
144
  MockDatabase,
145
+ createMockDatabase,
134
146
  getConfigByEnv,
135
147
  mockDatabase
136
148
  });
@@ -41,4 +41,5 @@ export default class MysqlQueryInterface extends QueryInterface {
41
41
  currentVal: number;
42
42
  transaction?: Transaction;
43
43
  }): Promise<void>;
44
+ generateJoinOnForJSONArray(left: string, right: string): import("sequelize/types/utils").Literal;
44
45
  }
@@ -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;
@@ -38,4 +38,5 @@ export default class PostgresQueryInterface extends QueryInterface {
38
38
  };
39
39
  }>;
40
40
  showTableDefinition(tableInfo: TableInfo): Promise<any>;
41
+ generateJoinOnForJSONArray(left: string, right: string): import("sequelize/types/utils").Literal;
41
42
  }
@@ -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;
@@ -49,4 +49,5 @@ export default abstract class QueryInterface {
49
49
  transaction?: Transaction;
50
50
  }): Promise<void>;
51
51
  quoteIdentifier(identifier: string): any;
52
+ generateJoinOnForJSONArray(left: string, right: string): void;
52
53
  }
@@ -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;
@@ -41,4 +41,5 @@ export default class SqliteQueryInterface extends QueryInterface {
41
41
  currentVal: number;
42
42
  transaction?: Transaction;
43
43
  }): Promise<void>;
44
+ generateJoinOnForJSONArray(left: string, right: string): import("sequelize/types/utils").Literal;
44
45
  }
@@ -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;
@@ -56,7 +56,7 @@ var import_relation_repository = require("./relation-repository");
56
56
  const _BelongsToManyRepository = class _BelongsToManyRepository extends import_multiple_relation_repository.MultipleRelationRepository {
57
57
  async aggregate(options) {
58
58
  const targetRepository = this.targetCollection.repository;
59
- const sourceModel = await this.getSourceModel();
59
+ const sourceModel = await this.getSourceModel(await this.getTransaction(options));
60
60
  const association = this.association;
61
61
  return await targetRepository.aggregate({
62
62
  ...options,
@@ -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(options["filter"], transaction2);
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(filter: Filter, transaction?: Transaction): Promise<boolean>;
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(filter, transaction2) {
177
+ async destroyByFilter(options, transaction2) {
178
178
  const instances = await this.find({
179
- filter,
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.2",
3
+ "version": "1.7.0-beta.20",
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.2",
10
- "@nocobase/utils": "1.7.0-beta.2",
9
+ "@nocobase/logger": "1.7.0-beta.20",
10
+ "@nocobase/utils": "1.7.0-beta.20",
11
11
  "async-mutex": "^0.3.2",
12
12
  "chalk": "^4.1.1",
13
13
  "cron-parser": "4.4.0",
@@ -20,12 +20,12 @@
20
20
  "graphlib": "^2.1.8",
21
21
  "lodash": "^4.17.21",
22
22
  "mathjs": "^10.6.1",
23
- "nanoid": "^3.3.6",
23
+ "nanoid": "^3.3.11",
24
24
  "node-fetch": "^2.6.7",
25
25
  "node-sql-parser": "^4.18.0",
26
26
  "qs": "^6.11.2",
27
27
  "safe-json-stringify": "^1.2.0",
28
- "semver": "^7.3.7",
28
+ "semver": "^7.7.1",
29
29
  "sequelize": "^6.26.0",
30
30
  "umzug": "^3.1.1",
31
31
  "uuid": "^9.0.1"
@@ -38,5 +38,5 @@
38
38
  "url": "git+https://github.com/nocobase/nocobase.git",
39
39
  "directory": "packages/database"
40
40
  },
41
- "gitHead": "58b206bdfca521e79a69989ca55dd19075dca523"
41
+ "gitHead": "178910a2afe33bd4850e2519507d32b631a380fc"
42
42
  }