@nocobase/database 2.1.0-alpha.15 → 2.1.0-alpha.17

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/database.d.ts CHANGED
@@ -45,6 +45,7 @@ export interface IDatabaseOptions extends Options {
45
45
  migrator?: any;
46
46
  usingBigIntForId?: boolean;
47
47
  underscored?: boolean;
48
+ rawTimezone?: string;
48
49
  logger?: LoggerOptions | Logger;
49
50
  customHooks?: any;
50
51
  instanceId?: string;
@@ -53,23 +53,23 @@ const ALLOWED_ORDER_DIRECTIONS = ["ASC", "DESC"];
53
53
  function createQueryFormatter(database) {
54
54
  switch (database.sequelize.getDialect()) {
55
55
  case "sqlite":
56
- return new import_sqlite.SQLiteQueryFormatter(database.sequelize);
56
+ return new import_sqlite.SQLiteQueryFormatter(database.sequelize, database.options.rawTimezone);
57
57
  case "postgres":
58
- return new import_postgres.PostgresQueryFormatter(database.sequelize);
58
+ return new import_postgres.PostgresQueryFormatter(database.sequelize, database.options.rawTimezone);
59
59
  case "mysql":
60
60
  case "mariadb":
61
- return new import_mysql.MySQLQueryFormatter(database.sequelize);
61
+ return new import_mysql.MySQLQueryFormatter(database.sequelize, database.options.rawTimezone);
62
62
  case "oracle":
63
- return new import_oracle.OracleQueryFormatter(database.sequelize);
63
+ return new import_oracle.OracleQueryFormatter(database.sequelize, database.options.rawTimezone);
64
64
  default:
65
65
  return new class extends import_formatter.QueryFormatter {
66
- formatDate(field, _format, _timezone) {
66
+ formatDate(field, _format, _timezone, _preserveLocalTime) {
67
67
  return field;
68
68
  }
69
69
  formatUnixTimestamp(field, _format, _accuracy, _timezone) {
70
70
  return this.sequelize.col(field);
71
71
  }
72
- }(database.sequelize);
72
+ }(database.sequelize, database.options.rawTimezone);
73
73
  }
74
74
  }
75
75
  __name(createQueryFormatter, "createQueryFormatter");
@@ -166,6 +166,7 @@ function buildQuery(database, collection, options = {}) {
166
166
  let hasAgg = false;
167
167
  const attributes = [];
168
168
  const fieldMap = {};
169
+ const projectedFieldMap = {};
169
170
  measures.forEach((measure) => {
170
171
  const { field, aggregation, alias, distinct } = measure;
171
172
  const col = sequelize.col(field);
@@ -184,6 +185,7 @@ function buildQuery(database, collection, options = {}) {
184
185
  }
185
186
  attributes.push(attribute.length > 1 ? attribute : attribute[0]);
186
187
  fieldMap[alias || field] = measure;
188
+ projectedFieldMap[alias || field] = attribute[0];
187
189
  });
188
190
  const group = [];
189
191
  dimensions.forEach((dimension) => {
@@ -202,11 +204,13 @@ function buildQuery(database, collection, options = {}) {
202
204
  group.push(attribute[0]);
203
205
  }
204
206
  fieldMap[alias || field] = dimension;
207
+ projectedFieldMap[alias || field] = attribute[0];
205
208
  });
206
209
  const order = orders.map((item) => {
207
210
  var _a2;
208
211
  const alias = sequelize.getQueryInterface().quoteIdentifier(item.alias);
209
- const name = hasAgg ? sequelize.literal(alias) : sequelize.col(item.field);
212
+ const projectedField = projectedFieldMap[item.alias] || projectedFieldMap[item.name] || projectedFieldMap[item.field];
213
+ const name = hasAgg ? projectedField || sequelize.literal(alias) : sequelize.col(item.field);
210
214
  let sort = ALLOWED_ORDER_DIRECTIONS.includes((_a2 = item.order) == null ? void 0 : _a2.toUpperCase()) ? item.order.toUpperCase() : "ASC";
211
215
  if (item.nulls === "first") {
212
216
  sort += " NULLS FIRST";
@@ -234,15 +238,23 @@ function buildQuery(database, collection, options = {}) {
234
238
  }
235
239
  __name(buildQuery, "buildQuery");
236
240
  function normalizeQueryResult(data, fieldMap) {
241
+ const dateTimeTypes = ["date", "datetime", "datetimeTz", "datetimeNoTz"];
237
242
  return data.map((record) => {
238
243
  Object.entries(record).forEach(([key, value]) => {
239
- var _a;
240
244
  if (value === null || value === void 0) {
241
245
  return;
242
246
  }
243
- const type = (_a = fieldMap[key]) == null ? void 0 : _a.type;
247
+ const field = fieldMap[key];
248
+ const type = field == null ? void 0 : field.type;
244
249
  if (["bigInt", "integer", "float", "double", "decimal"].includes(type)) {
245
250
  record[key] = Number(value);
251
+ return;
252
+ }
253
+ if (!(field == null ? void 0 : field.format) && dateTimeTypes.includes(type) && !(value instanceof Date)) {
254
+ const dateValue = new Date(value);
255
+ if (!Number.isNaN(dateValue.getTime())) {
256
+ record[key] = dateValue;
257
+ }
246
258
  }
247
259
  });
248
260
  return record;
@@ -1,11 +1,20 @@
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
+ */
1
9
  import { Sequelize } from 'sequelize';
2
10
  export type Col = ReturnType<typeof Sequelize.col>;
3
11
  export type Literal = ReturnType<typeof Sequelize.literal>;
4
12
  export type Fn = ReturnType<typeof Sequelize.fn>;
5
13
  export declare abstract class QueryFormatter {
6
14
  sequelize: Sequelize;
7
- constructor(sequelize: Sequelize);
8
- abstract formatDate(field: Col, format: string, timezone?: string): Fn | Col;
15
+ rawTimezone?: string;
16
+ constructor(sequelize: Sequelize, rawTimezone?: string);
17
+ abstract formatDate(field: Col, format: string, timezone?: string, preserveLocalTime?: boolean): Fn | Col;
9
18
  abstract formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): Fn | Literal | Col;
10
19
  convertFormat(format: string): string;
11
20
  protected getTimezoneByOffset(offset?: string): string;
@@ -43,8 +43,10 @@ module.exports = __toCommonJS(formatter_exports);
43
43
  var import_moment_timezone = __toESM(require("moment-timezone"));
44
44
  const _QueryFormatter = class _QueryFormatter {
45
45
  sequelize;
46
- constructor(sequelize) {
46
+ rawTimezone;
47
+ constructor(sequelize, rawTimezone) {
47
48
  this.sequelize = sequelize;
49
+ this.rawTimezone = rawTimezone;
48
50
  }
49
51
  convertFormat(format) {
50
52
  return format;
@@ -80,6 +82,7 @@ const _QueryFormatter = class _QueryFormatter {
80
82
  case "datetimeTz":
81
83
  return this.formatDate(col, format, timezone);
82
84
  case "datetimeNoTz":
85
+ return this.formatDate(col, format, void 0, true);
83
86
  case "dateOnly":
84
87
  case "time":
85
88
  return this.formatDate(col, format);
@@ -9,6 +9,6 @@
9
9
  import { QueryFormatter, Col } from '../formatter';
10
10
  export declare class MySQLQueryFormatter extends QueryFormatter {
11
11
  convertFormat(format: string): string;
12
- formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
12
+ formatDate(field: Col, format: string, timezone?: string, _preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
13
13
  formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
14
14
  }
@@ -35,7 +35,7 @@ const _MySQLQueryFormatter = class _MySQLQueryFormatter extends import_formatter
35
35
  convertFormat(format) {
36
36
  return format.replace(/YYYY/g, "%Y").replace(/MM/g, "%m").replace(/DD/g, "%d").replace(/hh/g, "%H").replace(/mm/g, "%i").replace(/ss/g, "%S");
37
37
  }
38
- formatDate(field, format, timezone) {
38
+ formatDate(field, format, timezone, _preserveLocalTime) {
39
39
  const fmt = this.convertFormat(format);
40
40
  const resolvedTimezone = this.getTimezoneByOffset(timezone);
41
41
  if (resolvedTimezone) {
@@ -9,6 +9,6 @@
9
9
  import { QueryFormatter, Col } from '../formatter';
10
10
  export declare class OracleQueryFormatter extends QueryFormatter {
11
11
  convertFormat(format: string): string;
12
- formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
12
+ formatDate(field: Col, format: string, timezone?: string, _preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
13
13
  formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
14
14
  }
@@ -35,7 +35,7 @@ const _OracleQueryFormatter = class _OracleQueryFormatter extends import_formatt
35
35
  convertFormat(format) {
36
36
  return format.replace(/hh/g, "HH24").replace(/mm/g, "MI").replace(/ss/g, "SS");
37
37
  }
38
- formatDate(field, format, timezone) {
38
+ formatDate(field, format, timezone, _preserveLocalTime) {
39
39
  const fmt = this.convertFormat(format);
40
40
  const resolvedTimezone = this.getTimezoneByOffset(timezone);
41
41
  if (resolvedTimezone) {
@@ -9,6 +9,6 @@
9
9
  import { QueryFormatter, Col } from '../formatter';
10
10
  export declare class PostgresQueryFormatter extends QueryFormatter {
11
11
  convertFormat(format: string): string;
12
- formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
12
+ formatDate(field: Col, format: string, timezone?: string, _preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
13
13
  formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
14
14
  }
@@ -35,7 +35,7 @@ const _PostgresQueryFormatter = class _PostgresQueryFormatter extends import_for
35
35
  convertFormat(format) {
36
36
  return format.replace(/hh/g, "HH24").replace(/mm/g, "MI").replace(/ss/g, "SS");
37
37
  }
38
- formatDate(field, format, timezone) {
38
+ formatDate(field, format, timezone, _preserveLocalTime) {
39
39
  const fmt = this.convertFormat(format);
40
40
  const resolvedTimezone = this.getTimezoneByOffset(timezone);
41
41
  if (resolvedTimezone) {
@@ -9,6 +9,6 @@
9
9
  import { QueryFormatter, Col } from '../formatter';
10
10
  export declare class SQLiteQueryFormatter extends QueryFormatter {
11
11
  convertFormat(format: string): string;
12
- formatDate(field: Col, format: string, timezone?: string): import("sequelize/types/utils").Fn;
12
+ formatDate(field: Col, format: string, timezone?: string, preserveLocalTime?: boolean): import("sequelize/types/utils").Fn;
13
13
  formatUnixTimestamp(field: string, format: string, accuracy?: 'second' | 'millisecond', timezone?: string): import("sequelize/types/utils").Fn;
14
14
  }
@@ -35,11 +35,14 @@ const _SQLiteQueryFormatter = class _SQLiteQueryFormatter extends import_formatt
35
35
  convertFormat(format) {
36
36
  return format.replace(/YYYY/g, "%Y").replace(/MM/g, "%m").replace(/DD/g, "%d").replace(/hh/g, "%H").replace(/mm/g, "%M").replace(/ss/g, "%S");
37
37
  }
38
- formatDate(field, format, timezone) {
38
+ formatDate(field, format, timezone, preserveLocalTime) {
39
39
  const fmt = this.convertFormat(format);
40
40
  if (timezone && /^[+-]\d{1,2}:\d{2}$/.test(timezone)) {
41
41
  return this.sequelize.fn("strftime", fmt, field, this.getOffsetExpression(timezone));
42
42
  }
43
+ if (preserveLocalTime && this.rawTimezone && /^[+-]\d{1,2}:\d{2}$/.test(this.rawTimezone)) {
44
+ return this.sequelize.fn("strftime", fmt, field, this.getOffsetExpression(this.rawTimezone));
45
+ }
43
46
  return this.sequelize.fn("strftime", fmt, field);
44
47
  }
45
48
  formatUnixTimestamp(field, format, accuracy = "second", timezone) {
package/lib/repository.js CHANGED
@@ -152,12 +152,13 @@ const _Repository = class _Repository {
152
152
  [import_sequelize.Op.and]: [options["where"] || {}, optionParser.filterByTkToWhereOption()]
153
153
  };
154
154
  }
155
+ const hasInclude = Array.isArray(options["include"]) && options["include"].length > 0;
155
156
  const queryOptions = {
156
- ...options,
157
- distinct: Boolean(this.collection.model.primaryKeyAttribute) && !this.collection.isMultiFilterTargetKey()
157
+ ...options
158
158
  };
159
- if (Array.isArray(queryOptions.include) && queryOptions.include.length > 0) {
159
+ if (hasInclude) {
160
160
  queryOptions.include = (0, import_utils2.processIncludes)(queryOptions.include, this.collection.model);
161
+ queryOptions.distinct = Boolean(this.collection.model.primaryKeyAttribute) && !this.collection.isMultiFilterTargetKey();
161
162
  } else {
162
163
  delete queryOptions.include;
163
164
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@nocobase/database",
3
- "version": "2.1.0-alpha.15",
3
+ "version": "2.1.0-alpha.17",
4
4
  "description": "",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
7
7
  "license": "Apache-2.0",
8
8
  "dependencies": {
9
- "@nocobase/logger": "2.1.0-alpha.15",
10
- "@nocobase/utils": "2.1.0-alpha.15",
9
+ "@nocobase/logger": "2.1.0-alpha.17",
10
+ "@nocobase/utils": "2.1.0-alpha.17",
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": "7c86e75b0af4b9f532c8ebf5ef96a7423b0ab60e"
41
+ "gitHead": "586cb00f56557e66168b9720d0e0193a1b752067"
42
42
  }