@nocobase/database 1.3.38-beta → 1.4.0-alpha

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 (53) hide show
  1. package/lib/collection.d.ts +3 -2
  2. package/lib/collection.js +6 -0
  3. package/lib/database.d.ts +11 -23
  4. package/lib/database.js +21 -42
  5. package/lib/dialects/base-dialect.d.ts +20 -0
  6. package/lib/dialects/base-dialect.js +75 -0
  7. package/lib/dialects/index.d.ts +9 -0
  8. package/lib/dialects/index.js +30 -0
  9. package/lib/dialects/mariadb-dialect.d.ts +17 -0
  10. package/lib/dialects/mariadb-dialect.js +54 -0
  11. package/lib/dialects/mysql-dialect.d.ts +17 -0
  12. package/lib/dialects/mysql-dialect.js +54 -0
  13. package/lib/dialects/postgres-dialect.d.ts +18 -0
  14. package/lib/dialects/postgres-dialect.js +77 -0
  15. package/lib/dialects/sqlite-dialect.d.ts +17 -0
  16. package/lib/dialects/sqlite-dialect.js +51 -0
  17. package/lib/fields/date-field.d.ts +7 -2
  18. package/lib/fields/date-field.js +89 -0
  19. package/lib/fields/date-only-field.d.ts +15 -0
  20. package/lib/fields/date-only-field.js +45 -0
  21. package/lib/fields/datetime-field.d.ts +15 -0
  22. package/lib/fields/datetime-field.js +41 -0
  23. package/lib/fields/datetime-no-tz-field.d.ts +24 -0
  24. package/lib/fields/datetime-no-tz-field.js +128 -0
  25. package/lib/fields/datetime-tz-field.d.ts +15 -0
  26. package/lib/fields/datetime-tz-field.js +41 -0
  27. package/lib/fields/field.d.ts +1 -1
  28. package/lib/fields/field.js +3 -2
  29. package/lib/fields/index.d.ts +10 -1
  30. package/lib/fields/index.js +11 -1
  31. package/lib/fields/unix-timestamp-field.d.ts +22 -0
  32. package/lib/fields/unix-timestamp-field.js +94 -0
  33. package/lib/helpers.d.ts +2 -1
  34. package/lib/helpers.js +16 -49
  35. package/lib/index.d.ts +1 -0
  36. package/lib/index.js +3 -1
  37. package/lib/model.d.ts +1 -0
  38. package/lib/model.js +12 -0
  39. package/lib/operators/date.js +66 -24
  40. package/lib/options-parser.d.ts +1 -0
  41. package/lib/options-parser.js +32 -9
  42. package/lib/query-interface/query-interface-builder.js +3 -0
  43. package/lib/relation-repository/hasmany-repository.js +8 -11
  44. package/lib/relation-repository/multiple-relation-repository.d.ts +1 -0
  45. package/lib/relation-repository/multiple-relation-repository.js +11 -3
  46. package/lib/relation-repository/relation-repository.d.ts +6 -3
  47. package/lib/relation-repository/relation-repository.js +27 -4
  48. package/lib/repository.d.ts +5 -2
  49. package/lib/repository.js +27 -16
  50. package/lib/update-associations.d.ts +2 -1
  51. package/lib/view/field-type-map.d.ts +2 -2
  52. package/lib/view/field-type-map.js +17 -17
  53. package/package.json +4 -4
@@ -0,0 +1,94 @@
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 __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var unix_timestamp_field_exports = {};
29
+ __export(unix_timestamp_field_exports, {
30
+ UnixTimestampField: () => UnixTimestampField
31
+ });
32
+ module.exports = __toCommonJS(unix_timestamp_field_exports);
33
+ var import_sequelize = require("sequelize");
34
+ var import_date_field = require("./date-field");
35
+ const _UnixTimestampField = class _UnixTimestampField extends import_date_field.DateField {
36
+ get dataType() {
37
+ return import_sequelize.DataTypes.BIGINT;
38
+ }
39
+ dateToValue(val) {
40
+ var _a, _b, _c, _d, _e;
41
+ if (val === null || val === void 0) {
42
+ return val;
43
+ }
44
+ let { accuracy } = this.options;
45
+ if ((_c = (_b = (_a = this.options) == null ? void 0 : _a.uiSchema) == null ? void 0 : _b["x-component-props"]) == null ? void 0 : _c.accuracy) {
46
+ accuracy = (_e = (_d = this.options) == null ? void 0 : _d.uiSchema["x-component-props"]) == null ? void 0 : _e.accuracy;
47
+ }
48
+ if (!accuracy) {
49
+ accuracy = "second";
50
+ }
51
+ let rationalNumber = 1e3;
52
+ if (accuracy === "millisecond") {
53
+ rationalNumber = 1;
54
+ }
55
+ return Math.floor(new Date(val).getTime() / rationalNumber);
56
+ }
57
+ additionalSequelizeOptions() {
58
+ var _a, _b, _c, _d, _e;
59
+ const { name } = this.options;
60
+ let { accuracy } = this.options;
61
+ if ((_c = (_b = (_a = this.options) == null ? void 0 : _a.uiSchema) == null ? void 0 : _b["x-component-props"]) == null ? void 0 : _c.accuracy) {
62
+ accuracy = (_e = (_d = this.options) == null ? void 0 : _d.uiSchema["x-component-props"]) == null ? void 0 : _e.accuracy;
63
+ }
64
+ if (!accuracy) {
65
+ accuracy = "second";
66
+ }
67
+ let rationalNumber = 1e3;
68
+ if (accuracy === "millisecond") {
69
+ rationalNumber = 1;
70
+ }
71
+ return {
72
+ get() {
73
+ const value = this.getDataValue(name);
74
+ if (value === null || value === void 0) {
75
+ return value;
76
+ }
77
+ return new Date(value * rationalNumber);
78
+ },
79
+ set(value) {
80
+ if (value === null || value === void 0) {
81
+ this.setDataValue(name, value);
82
+ } else {
83
+ this.setDataValue(name, Math.floor(new Date(value).getTime() / rationalNumber));
84
+ }
85
+ }
86
+ };
87
+ }
88
+ };
89
+ __name(_UnixTimestampField, "UnixTimestampField");
90
+ let UnixTimestampField = _UnixTimestampField;
91
+ // Annotate the CommonJS export names for ESM import in node:
92
+ 0 && (module.exports = {
93
+ UnixTimestampField
94
+ });
package/lib/helpers.d.ts CHANGED
@@ -8,4 +8,5 @@
8
8
  */
9
9
  import { Database, IDatabaseOptions } from './database';
10
10
  export declare function parseDatabaseOptionsFromEnv(): Promise<IDatabaseOptions>;
11
- export declare function checkDatabaseVersion(db: Database): Promise<boolean>;
11
+ export declare function checkDatabaseVersion(db: Database): Promise<void>;
12
+ export declare function registerDialects(): void;
package/lib/helpers.js CHANGED
@@ -38,11 +38,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
38
38
  var helpers_exports = {};
39
39
  __export(helpers_exports, {
40
40
  checkDatabaseVersion: () => checkDatabaseVersion,
41
- parseDatabaseOptionsFromEnv: () => parseDatabaseOptionsFromEnv
41
+ parseDatabaseOptionsFromEnv: () => parseDatabaseOptionsFromEnv,
42
+ registerDialects: () => registerDialects
42
43
  });
43
44
  module.exports = __toCommonJS(helpers_exports);
45
+ var import_database = require("./database");
44
46
  var import_fs = __toESM(require("fs"));
45
- var import_semver = __toESM(require("semver"));
47
+ var import_mysql_dialect = require("./dialects/mysql-dialect");
48
+ var import_sqlite_dialect = require("./dialects/sqlite-dialect");
49
+ var import_mariadb_dialect = require("./dialects/mariadb-dialect");
50
+ var import_postgres_dialect = require("./dialects/postgres-dialect");
46
51
  /* istanbul ignore file -- @preserve */
47
52
  function getEnvValue(key, defaultValue) {
48
53
  return process.env[key] || defaultValue;
@@ -121,57 +126,19 @@ function customLogger(queryString, queryObject) {
121
126
  }
122
127
  }
123
128
  __name(customLogger, "customLogger");
124
- const dialectVersionAccessors = {
125
- sqlite: {
126
- sql: "select sqlite_version() as version",
127
- get: /* @__PURE__ */ __name((v) => v, "get"),
128
- version: "3.x"
129
- },
130
- mysql: {
131
- sql: "select version() as version",
132
- get: /* @__PURE__ */ __name((v) => {
133
- const m = /([\d+.]+)/.exec(v);
134
- return m[0];
135
- }, "get"),
136
- version: ">=8.0.17"
137
- },
138
- mariadb: {
139
- sql: "select version() as version",
140
- get: /* @__PURE__ */ __name((v) => {
141
- const m = /([\d+.]+)/.exec(v);
142
- return m[0];
143
- }, "get"),
144
- version: ">=10.9"
145
- },
146
- postgres: {
147
- sql: "select version() as version",
148
- get: /* @__PURE__ */ __name((v) => {
149
- const m = /([\d+.]+)/.exec(v);
150
- return import_semver.default.minVersion(m[0]).version;
151
- }, "get"),
152
- version: ">=10"
153
- }
154
- };
155
129
  async function checkDatabaseVersion(db) {
156
- var _a;
157
- const dialect = db.sequelize.getDialect();
158
- const accessor = dialectVersionAccessors[dialect];
159
- if (!accessor) {
160
- throw new Error(`unsupported dialect ${dialect}`);
161
- }
162
- const result = await db.sequelize.query(accessor.sql, {
163
- type: "SELECT"
164
- });
165
- const version = accessor.get((_a = result == null ? void 0 : result[0]) == null ? void 0 : _a.version);
166
- const versionResult = import_semver.default.satisfies(version, accessor.version);
167
- if (!versionResult) {
168
- throw new Error(`to use ${dialect}, please ensure the version is ${accessor.version}`);
169
- }
170
- return true;
130
+ await db.dialect.checkDatabaseVersion(db);
171
131
  }
172
132
  __name(checkDatabaseVersion, "checkDatabaseVersion");
133
+ function registerDialects() {
134
+ [import_sqlite_dialect.SqliteDialect, import_mysql_dialect.MysqlDialect, import_mariadb_dialect.MariadbDialect, import_postgres_dialect.PostgresDialect].forEach((dialect) => {
135
+ import_database.Database.registerDialect(dialect);
136
+ });
137
+ }
138
+ __name(registerDialects, "registerDialects");
173
139
  // Annotate the CommonJS export names for ESM import in node:
174
140
  0 && (module.exports = {
175
141
  checkDatabaseVersion,
176
- parseDatabaseOptionsFromEnv
142
+ parseDatabaseOptionsFromEnv,
143
+ registerDialects
177
144
  });
package/lib/index.d.ts CHANGED
@@ -37,3 +37,4 @@ export * from './helpers';
37
37
  export { default as sqlParser, SQLParserTypes } from './sql-parser';
38
38
  export * from './interfaces';
39
39
  export { default as fieldTypeMap } from './view/field-type-map';
40
+ export * from './dialects';
package/lib/index.js CHANGED
@@ -92,6 +92,7 @@ __reExport(src_exports, require("./helpers"), module.exports);
92
92
  var import_sql_parser = __toESM(require("./sql-parser"));
93
93
  __reExport(src_exports, require("./interfaces"), module.exports);
94
94
  var import_field_type_map = __toESM(require("./view/field-type-map"));
95
+ __reExport(src_exports, require("./dialects"), module.exports);
95
96
  // Annotate the CommonJS export names for ESM import in node:
96
97
  0 && (module.exports = {
97
98
  BaseError,
@@ -139,5 +140,6 @@ var import_field_type_map = __toESM(require("./view/field-type-map"));
139
140
  ...require("./view-collection"),
140
141
  ...require("./view/view-inference"),
141
142
  ...require("./helpers"),
142
- ...require("./interfaces")
143
+ ...require("./interfaces"),
144
+ ...require("./dialects")
143
145
  });
package/lib/model.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare class Model<TModelAttributes extends {} = any, TCreationAttribute
20
20
  protected _previousDataValuesWithAssociations: {};
21
21
  get db(): Database;
22
22
  static sync(options: any): Promise<any>;
23
+ static callSetters(values: any, options: any): {};
23
24
  toChangedWithAssociations(): void;
24
25
  changedWithAssociations(key?: string, value?: any): boolean | unknown[] | this;
25
26
  clearChangedWithAssociations(): void;
package/lib/model.js CHANGED
@@ -56,6 +56,18 @@ const _Model = class _Model extends import_sequelize.Model {
56
56
  const runner = new import_sync_runner.SyncRunner(this);
57
57
  return await runner.runSync(options);
58
58
  }
59
+ static callSetters(values, options) {
60
+ const result = {};
61
+ for (const key of Object.keys(values)) {
62
+ const field = this.collection.getField(key);
63
+ if (field && field.setter) {
64
+ result[key] = field.setter.call(field, values[key], options, values, key);
65
+ } else {
66
+ result[key] = values[key];
67
+ }
68
+ }
69
+ return result;
70
+ }
59
71
  // TODO
60
72
  toChangedWithAssociations() {
61
73
  this._changedWithAssociations = /* @__PURE__ */ new Set([...this._changedWithAssociations, ...this._changed]);
@@ -7,9 +7,11 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
+ var __create = Object.create;
10
11
  var __defProp = Object.defineProperty;
11
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
13
  var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
13
15
  var __hasOwnProp = Object.prototype.hasOwnProperty;
14
16
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
17
  var __export = (target, all) => {
@@ -24,6 +26,14 @@ var __copyProps = (to, from, except, desc) => {
24
26
  }
25
27
  return to;
26
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
+ ));
27
37
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
38
  var date_exports = {};
29
39
  __export(date_exports, {
@@ -32,116 +42,148 @@ __export(date_exports, {
32
42
  module.exports = __toCommonJS(date_exports);
33
43
  var import_utils = require("@nocobase/utils");
34
44
  var import_sequelize = require("sequelize");
45
+ var import_moment = __toESM(require("moment"));
35
46
  function isDate(input) {
36
47
  return input instanceof Date || Object.prototype.toString.call(input) === "[object Date]";
37
48
  }
38
49
  __name(isDate, "isDate");
39
- const toDate = /* @__PURE__ */ __name((date) => {
40
- if (isDate(date)) {
41
- return date;
50
+ const toDate = /* @__PURE__ */ __name((date, options = {}) => {
51
+ const { ctx } = options;
52
+ let val = isDate(date) ? date : new Date(date);
53
+ const field = ctx.db.getFieldByPath(ctx.fieldPath);
54
+ if (!field) {
55
+ return val;
42
56
  }
43
- return new Date(date);
57
+ if (field.constructor.name === "UnixTimestampField") {
58
+ val = field.dateToValue(val);
59
+ }
60
+ if (field.constructor.name === "DatetimeNoTzField") {
61
+ val = (0, import_moment.default)(val).utcOffset("+00:00").format("YYYY-MM-DD HH:mm:ss");
62
+ }
63
+ if (field.constructor.name === "DateOnlyField") {
64
+ val = (0, import_moment.default)(val).format("YYYY-MM-DD HH:mm:ss");
65
+ }
66
+ const eventObj = {
67
+ val,
68
+ fieldType: field.type
69
+ };
70
+ ctx.db.emit("filterToDate", eventObj);
71
+ return eventObj.val;
44
72
  }, "toDate");
73
+ function parseDateTimezone(ctx) {
74
+ const field = ctx.db.getFieldByPath(ctx.fieldPath);
75
+ if (!field) {
76
+ return ctx.db.options.timezone;
77
+ }
78
+ if (field.constructor.name === "DatetimeNoTzField") {
79
+ return "+00:00";
80
+ }
81
+ if (field.constructor.name === "DateOnlyField") {
82
+ return "+00:00";
83
+ }
84
+ return ctx.db.options.timezone;
85
+ }
86
+ __name(parseDateTimezone, "parseDateTimezone");
45
87
  var date_default = {
46
88
  $dateOn(value, ctx) {
47
89
  const r = (0, import_utils.parseDate)(value, {
48
- timezone: ctx.db.options.timezone
90
+ timezone: parseDateTimezone(ctx)
49
91
  });
50
92
  if (typeof r === "string") {
51
93
  return {
52
- [import_sequelize.Op.eq]: toDate(r)
94
+ [import_sequelize.Op.eq]: toDate(r, { ctx })
53
95
  };
54
96
  }
55
97
  if (Array.isArray(r)) {
56
98
  return {
57
- [import_sequelize.Op.and]: [{ [import_sequelize.Op.gte]: toDate(r[0]) }, { [import_sequelize.Op.lt]: toDate(r[1]) }]
99
+ [import_sequelize.Op.and]: [{ [import_sequelize.Op.gte]: toDate(r[0], { ctx }) }, { [import_sequelize.Op.lt]: toDate(r[1], { ctx }) }]
58
100
  };
59
101
  }
60
102
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
61
103
  },
62
104
  $dateNotOn(value, ctx) {
63
105
  const r = (0, import_utils.parseDate)(value, {
64
- timezone: ctx.db.options.timezone
106
+ timezone: parseDateTimezone(ctx)
65
107
  });
66
108
  if (typeof r === "string") {
67
109
  return {
68
- [import_sequelize.Op.ne]: toDate(r)
110
+ [import_sequelize.Op.ne]: toDate(r, { ctx })
69
111
  };
70
112
  }
71
113
  if (Array.isArray(r)) {
72
114
  return {
73
- [import_sequelize.Op.or]: [{ [import_sequelize.Op.lt]: toDate(r[0]) }, { [import_sequelize.Op.gte]: toDate(r[1]) }]
115
+ [import_sequelize.Op.or]: [{ [import_sequelize.Op.lt]: toDate(r[0], { ctx }) }, { [import_sequelize.Op.gte]: toDate(r[1], { ctx }) }]
74
116
  };
75
117
  }
76
118
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
77
119
  },
78
120
  $dateBefore(value, ctx) {
79
121
  const r = (0, import_utils.parseDate)(value, {
80
- timezone: ctx.db.options.timezone
122
+ timezone: parseDateTimezone(ctx)
81
123
  });
82
124
  if (typeof r === "string") {
83
125
  return {
84
- [import_sequelize.Op.lt]: toDate(r)
126
+ [import_sequelize.Op.lt]: toDate(r, { ctx })
85
127
  };
86
128
  } else if (Array.isArray(r)) {
87
129
  return {
88
- [import_sequelize.Op.lt]: toDate(r[0])
130
+ [import_sequelize.Op.lt]: toDate(r[0], { ctx })
89
131
  };
90
132
  }
91
133
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
92
134
  },
93
135
  $dateNotBefore(value, ctx) {
94
136
  const r = (0, import_utils.parseDate)(value, {
95
- timezone: ctx.db.options.timezone
137
+ timezone: parseDateTimezone(ctx)
96
138
  });
97
139
  if (typeof r === "string") {
98
140
  return {
99
- [import_sequelize.Op.gte]: toDate(r)
141
+ [import_sequelize.Op.gte]: toDate(r, { ctx })
100
142
  };
101
143
  } else if (Array.isArray(r)) {
102
144
  return {
103
- [import_sequelize.Op.gte]: toDate(r[0])
145
+ [import_sequelize.Op.gte]: toDate(r[0], { ctx })
104
146
  };
105
147
  }
106
148
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
107
149
  },
108
150
  $dateAfter(value, ctx) {
109
151
  const r = (0, import_utils.parseDate)(value, {
110
- timezone: ctx.db.options.timezone
152
+ timezone: parseDateTimezone(ctx)
111
153
  });
112
154
  if (typeof r === "string") {
113
155
  return {
114
- [import_sequelize.Op.gt]: toDate(r)
156
+ [import_sequelize.Op.gt]: toDate(r, { ctx })
115
157
  };
116
158
  } else if (Array.isArray(r)) {
117
159
  return {
118
- [import_sequelize.Op.gte]: toDate(r[1])
160
+ [import_sequelize.Op.gte]: toDate(r[1], { ctx })
119
161
  };
120
162
  }
121
163
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
122
164
  },
123
165
  $dateNotAfter(value, ctx) {
124
166
  const r = (0, import_utils.parseDate)(value, {
125
- timezone: ctx.db.options.timezone
167
+ timezone: parseDateTimezone(ctx)
126
168
  });
127
169
  if (typeof r === "string") {
128
170
  return {
129
- [import_sequelize.Op.lte]: toDate(r)
171
+ [import_sequelize.Op.lte]: toDate(r, { ctx })
130
172
  };
131
173
  } else if (Array.isArray(r)) {
132
174
  return {
133
- [import_sequelize.Op.lt]: toDate(r[1])
175
+ [import_sequelize.Op.lt]: toDate(r[1], { ctx })
134
176
  };
135
177
  }
136
178
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
137
179
  },
138
180
  $dateBetween(value, ctx) {
139
181
  const r = (0, import_utils.parseDate)(value, {
140
- timezone: ctx.db.options.timezone
182
+ timezone: parseDateTimezone(ctx)
141
183
  });
142
184
  if (r) {
143
185
  return {
144
- [import_sequelize.Op.and]: [{ [import_sequelize.Op.gte]: toDate(r[0]) }, { [import_sequelize.Op.lt]: toDate(r[1]) }]
186
+ [import_sequelize.Op.and]: [{ [import_sequelize.Op.gte]: toDate(r[0], { ctx }) }, { [import_sequelize.Op.lt]: toDate(r[1], { ctx }) }]
145
187
  };
146
188
  }
147
189
  throw new Error(`Invalid Date ${JSON.stringify(value)}`);
@@ -26,6 +26,7 @@ export declare class OptionsParser {
26
26
  static appendInheritInspectAttribute(include: any, collection: any): any;
27
27
  isAssociation(key: string): boolean;
28
28
  isAssociationPath(path: string): boolean;
29
+ filterByTkToWhereOption(): {};
29
30
  toSequelizeParams(): any;
30
31
  /**
31
32
  * parser sort options
@@ -90,17 +90,34 @@ const _OptionsParser = class _OptionsParser {
90
90
  isAssociationPath(path) {
91
91
  return this.isAssociation(path.split(".")[0]);
92
92
  }
93
+ filterByTkToWhereOption() {
94
+ var _a;
95
+ const filterByTkOption = (_a = this.options) == null ? void 0 : _a.filterByTk;
96
+ if (!filterByTkOption) {
97
+ return {};
98
+ }
99
+ if (import_lodash.default.isPlainObject(this.options.filterByTk)) {
100
+ const where = {};
101
+ for (const [key, value] of Object.entries(filterByTkOption)) {
102
+ where[key] = value;
103
+ }
104
+ return where;
105
+ }
106
+ const filterTargetKey = this.context.targetKey || this.collection.filterTargetKey;
107
+ if (Array.isArray(filterTargetKey)) {
108
+ throw new Error("multi filter target key value must be object");
109
+ }
110
+ return {
111
+ [filterTargetKey]: filterByTkOption
112
+ };
113
+ }
93
114
  toSequelizeParams() {
94
115
  var _a, _b;
95
116
  const queryParams = this.filterParser.toSequelizeParams();
96
117
  if ((_a = this.options) == null ? void 0 : _a.filterByTk) {
118
+ const filterByTkWhere = this.filterByTkToWhereOption();
97
119
  queryParams.where = {
98
- [import_sequelize.Op.and]: [
99
- queryParams.where,
100
- {
101
- [this.context.targetKey || this.collection.filterTargetKey]: this.options.filterByTk
102
- }
103
- ]
120
+ [import_sequelize.Op.and]: [queryParams.where, filterByTkWhere]
104
121
  };
105
122
  }
106
123
  if ((_b = this.options) == null ? void 0 : _b.include) {
@@ -123,12 +140,18 @@ const _OptionsParser = class _OptionsParser {
123
140
  sort = sort.split(",");
124
141
  }
125
142
  let defaultSortField = this.model.primaryKeyAttribute;
126
- if (!defaultSortField && this.collection.filterTargetKey) {
143
+ if (Array.isArray(this.collection.filterTargetKey)) {
144
+ defaultSortField = this.collection.filterTargetKey;
145
+ }
146
+ if (!defaultSortField && this.collection.filterTargetKey && !Array.isArray(this.collection.filterTargetKey)) {
127
147
  defaultSortField = this.collection.filterTargetKey;
128
148
  }
129
149
  if (defaultSortField && !((_b = this.options) == null ? void 0 : _b.group)) {
130
- if (!sort.includes(defaultSortField)) {
131
- sort.push(defaultSortField);
150
+ defaultSortField = import_lodash.default.castArray(defaultSortField);
151
+ for (const key of defaultSortField) {
152
+ if (!sort.includes(key)) {
153
+ sort.push(key);
154
+ }
132
155
  }
133
156
  }
134
157
  const orderParams = [];
@@ -50,6 +50,9 @@ function buildQueryInterface(db) {
50
50
  postgres: import_postgres_query_interface.default,
51
51
  sqlite: import_sqlite_query_interface.default
52
52
  };
53
+ if (db.isPostgresCompatibleDialect()) {
54
+ return new import_postgres_query_interface.default(db);
55
+ }
53
56
  const dialect = db.options.dialect;
54
57
  if (!map[dialect]) {
55
58
  return null;
@@ -45,29 +45,26 @@ var import_relation_repository = require("./relation-repository");
45
45
  const _HasManyRepository = class _HasManyRepository extends import_multiple_relation_repository.MultipleRelationRepository {
46
46
  async find(options) {
47
47
  const targetRepository = this.targetCollection.repository;
48
- const addFilter = {
49
- [this.association.foreignKey]: this.sourceKeyValue
50
- };
51
- if (options == null ? void 0 : options.filterByTk) {
52
- addFilter[this.associationField.targetKey] = options.filterByTk;
48
+ const targetFilterOptions = await this.targetRepositoryFilterOptionsBySourceValue();
49
+ const findOptionsOmit = ["where", "values", "attributes"];
50
+ if ((options == null ? void 0 : options.filterByTk) && !this.isMultiTargetKey(options.filterByTk)) {
51
+ targetFilterOptions[this.associationField.targetKey] = options.filterByTk;
52
+ findOptionsOmit.push("filterByTk");
53
53
  }
54
54
  const findOptions = {
55
- ...(0, import_lodash.omit)(options, ["filterByTk", "where", "values", "attributes"]),
55
+ ...(0, import_lodash.omit)(options, findOptionsOmit),
56
56
  filter: {
57
- $and: [options.filter || {}, addFilter]
57
+ $and: [(options == null ? void 0 : options.filter) || {}, targetFilterOptions]
58
58
  }
59
59
  };
60
60
  return await targetRepository.find(findOptions);
61
61
  }
62
62
  async aggregate(options) {
63
63
  const targetRepository = this.targetCollection.repository;
64
- const addFilter = {
65
- [this.association.foreignKey]: this.sourceKeyValue
66
- };
67
64
  const aggOptions = {
68
65
  ...options,
69
66
  filter: {
70
- $and: [options.filter || {}, addFilter]
67
+ $and: [options.filter || {}, await this.targetRepositoryFilterOptionsBySourceValue()]
71
68
  }
72
69
  };
73
70
  return await targetRepository.aggregate(aggOptions);
@@ -14,6 +14,7 @@ export interface AssociatedOptions extends Transactionable {
14
14
  tk?: TK;
15
15
  }
16
16
  export declare abstract class MultipleRelationRepository extends RelationRepository {
17
+ targetRepositoryFilterOptionsBySourceValue(): Promise<any>;
17
18
  find(options?: FindOptions): Promise<any>;
18
19
  findAndCount(options?: FindAndCountOptions): Promise<[any[], number]>;
19
20
  count(options?: CountOptions): Promise<number>;
@@ -55,6 +55,16 @@ var import_update_associations = require("../update-associations");
55
55
  var import_update_guard = require("../update-guard");
56
56
  var import_relation_repository = require("./relation-repository");
57
57
  const _MultipleRelationRepository = class _MultipleRelationRepository extends import_relation_repository.RelationRepository {
58
+ async targetRepositoryFilterOptionsBySourceValue() {
59
+ let filterForeignKeyValue = this.sourceKeyValue;
60
+ if (this.isMultiTargetKey()) {
61
+ const sourceModel = await this.getSourceModel();
62
+ filterForeignKeyValue = sourceModel.get(this.association.sourceKey);
63
+ }
64
+ return {
65
+ [this.association.foreignKey]: filterForeignKeyValue
66
+ };
67
+ }
58
68
  async find(options) {
59
69
  const targetRepository = this.targetCollection.repository;
60
70
  const association = this.association;
@@ -68,9 +78,7 @@ const _MultipleRelationRepository = class _MultipleRelationRepository extends im
68
78
  const appendFilter = {
69
79
  isPivotFilter: true,
70
80
  association: pivotAssoc,
71
- where: {
72
- [association.foreignKey]: this.sourceKeyValue
73
- }
81
+ where: await this.targetRepositoryFilterOptionsBySourceValue()
74
82
  };
75
83
  return targetRepository.find({
76
84
  include: [appendFilter],
@@ -11,7 +11,7 @@ import { Collection } from '../collection';
11
11
  import Database from '../database';
12
12
  import { RelationField } from '../fields/relation-field';
13
13
  import { Model } from '../model';
14
- import { CreateOptions, Filter, FindOptions } from '../repository';
14
+ import { CreateOptions, Filter, FindOptions, TargetKey } from '../repository';
15
15
  export declare const transaction: (transactionInjector?: any) => (target: any, name: any, descriptor: any) => any;
16
16
  export declare abstract class RelationRepository {
17
17
  sourceCollection: Collection;
@@ -20,11 +20,14 @@ export declare abstract class RelationRepository {
20
20
  targetCollection: Collection;
21
21
  associationName: string;
22
22
  associationField: RelationField;
23
- sourceKeyValue: string | number;
23
+ sourceKeyValue: TargetKey;
24
24
  sourceInstance: Model;
25
25
  db: Database;
26
26
  database: Database;
27
- constructor(sourceCollection: Collection, association: string, sourceKeyValue: string | number);
27
+ constructor(sourceCollection: Collection, association: string, sourceKeyValue: TargetKey);
28
+ decodeMultiTargetKey(str: string): any;
29
+ setSourceKeyValue(sourceKeyValue: TargetKey): void;
30
+ isMultiTargetKey(value?: any): boolean;
28
31
  get collection(): Collection<any, any>;
29
32
  abstract find(options?: FindOptions): Promise<any>;
30
33
  chunk(options: FindOptions & {