@nocobase/database 1.9.0-beta.9 → 2.0.0-alpha.3

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.
@@ -81,10 +81,12 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
81
81
  model: ModelStatic<Model>;
82
82
  repository: Repository<TModelAttributes, TCreationAttributes>;
83
83
  constructor(options: CollectionOptions, context: CollectionContext);
84
+ get underscored(): boolean;
84
85
  get filterTargetKey(): string | string[];
85
86
  get name(): string;
86
87
  get origin(): string;
87
88
  get titleField(): string;
89
+ get titleFieldInstance(): Field;
88
90
  get db(): Database;
89
91
  get treeParentField(): BelongsToField | null;
90
92
  get treeChildrenField(): HasManyField | null;
@@ -155,6 +157,7 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
155
157
  modelName: string;
156
158
  sequelize: import("sequelize").Sequelize;
157
159
  tableName: any;
160
+ underscored: boolean;
158
161
  };
159
162
  protected bindFieldEventListener(): void;
160
163
  private checkOptions;
package/lib/collection.js CHANGED
@@ -111,6 +111,9 @@ const _Collection = class _Collection extends import_events.EventEmitter {
111
111
  this.setRepository(options.repository);
112
112
  this.setSortable(options.sortable);
113
113
  }
114
+ get underscored() {
115
+ return this.options.underscored;
116
+ }
114
117
  get filterTargetKey() {
115
118
  var _a;
116
119
  const targetKey = (_a = this.options) == null ? void 0 : _a.filterTargetKey;
@@ -137,6 +140,9 @@ const _Collection = class _Collection extends import_events.EventEmitter {
137
140
  get titleField() {
138
141
  return this.options.titleField || this.model.primaryKeyAttribute;
139
142
  }
143
+ get titleFieldInstance() {
144
+ return this.getField(this.titleField);
145
+ }
140
146
  get db() {
141
147
  return this.context.database;
142
148
  }
@@ -225,7 +231,7 @@ const _Collection = class _Collection extends import_events.EventEmitter {
225
231
  tableName() {
226
232
  const { name, tableName } = this.options;
227
233
  const tName = tableName || name;
228
- return this.options.underscored ? (0, import_utils.snakeCase)(tName) : tName;
234
+ return this.underscored ? (0, import_utils.snakeCase)(tName) : tName;
229
235
  }
230
236
  /**
231
237
  * @internal
@@ -338,7 +344,7 @@ const _Collection = class _Collection extends import_events.EventEmitter {
338
344
  return this.setField(name, options);
339
345
  }
340
346
  checkFieldType(name, options) {
341
- if (!this.options.underscored) {
347
+ if (!this.underscored) {
342
348
  return;
343
349
  }
344
350
  const fieldName = options.field || (0, import_utils.snakeCase)(name);
@@ -483,7 +489,7 @@ const _Collection = class _Collection extends import_events.EventEmitter {
483
489
  }
484
490
  if (this.model.options.timestamps !== false) {
485
491
  let timestampsFields = ["createdAt", "updatedAt", "deletedAt"];
486
- if (this.db.options.underscored) {
492
+ if (this.underscored) {
487
493
  timestampsFields = timestampsFields.map((fieldName) => (0, import_utils.snakeCase)(fieldName));
488
494
  }
489
495
  if (timestampsFields.includes(field.columnName())) {
@@ -776,7 +782,8 @@ const _Collection = class _Collection extends import_events.EventEmitter {
776
782
  ...import_lodash.default.omit(this.options, ["name", "fields", "model", "targetKey"]),
777
783
  modelName: name,
778
784
  sequelize: this.context.database.sequelize,
779
- tableName: this.tableName()
785
+ tableName: this.tableName(),
786
+ underscored: this.underscored
780
787
  };
781
788
  return attr;
782
789
  }
package/lib/database.d.ts CHANGED
@@ -17,6 +17,7 @@ import { Collection, CollectionOptions, RepositoryType } from './collection';
17
17
  import { CollectionFactory } from './collection-factory';
18
18
  import { ImportFileExtension } from './collection-importer';
19
19
  import DatabaseUtils from './database-utils';
20
+ import { BaseDialect } from './dialects/base-dialect';
20
21
  import ReferencesMap from './features/references-map';
21
22
  import { ArrayFieldRepository } from './field-repository/array-field-repository';
22
23
  import * as FieldTypes from './fields';
@@ -31,7 +32,6 @@ import { RelationRepository } from './relation-repository/relation-repository';
31
32
  import { Repository, TargetKey } from './repository';
32
33
  import { AfterDefineCollectionListener, BeforeDefineCollectionListener, CreateListener, CreateWithAssociationsListener, DatabaseAfterDefineCollectionEventType, DatabaseAfterRemoveCollectionEventType, DatabaseBeforeDefineCollectionEventType, DatabaseBeforeRemoveCollectionEventType, DestroyListener, EventType, ModelCreateEventTypes, ModelCreateWithAssociationsEventTypes, ModelDestroyEventTypes, ModelSaveEventTypes, ModelSaveWithAssociationsEventTypes, ModelUpdateEventTypes, ModelUpdateWithAssociationsEventTypes, ModelValidateEventTypes, RemoveCollectionListener, SaveListener, SaveWithAssociationsListener, SyncListener, UpdateListener, UpdateWithAssociationsListener, ValidateListener } from './types';
33
34
  import { BaseValueParser } from './value-parsers';
34
- import { BaseDialect } from './dialects/base-dialect';
35
35
  export type MergeOptions = merge.Options;
36
36
  export interface PendingOptions {
37
37
  field: RelationField;
@@ -67,6 +67,11 @@ export type AddMigrationsOptions = {
67
67
  directory: string;
68
68
  };
69
69
  type OperatorFunc = (value: any, ctx?: RegisterOperatorsContext) => any;
70
+ type RunSQLOptions = {
71
+ filter?: Record<string, any>;
72
+ bind?: Record<string, any> | Array<any>;
73
+ type?: 'selectVar' | 'selectRow' | 'selectRows';
74
+ } & Transactionable;
70
75
  export declare class Database extends EventEmitter implements AsyncEmitter {
71
76
  static dialects: Map<string, typeof BaseDialect>;
72
77
  sequelize: Sequelize;
@@ -208,6 +213,9 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
208
213
  extensions?: ImportFileExtension[];
209
214
  }): Promise<Map<string, Collection>>;
210
215
  private registerCollectionType;
216
+ quoteIdentifier(identifier: string): string;
217
+ quoteTable(tableName: string): string;
218
+ runSQL(sql: string, options?: RunSQLOptions): Promise<any>;
211
219
  }
212
220
  export declare function extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): {
213
221
  collectionOptions: CollectionOptions;
package/lib/database.js CHANGED
@@ -58,6 +58,7 @@ var import_path = require("path");
58
58
  var import_safe_json_stringify = __toESM(require("safe-json-stringify"));
59
59
  var import_sequelize = require("sequelize");
60
60
  var import_umzug = require("umzug");
61
+ var import_collection = require("./collection");
61
62
  var import_collection_factory = require("./collection-factory");
62
63
  var import_collection_importer = require("./collection-importer");
63
64
  var import_database_utils = __toESM(require("./database-utils"));
@@ -430,8 +431,10 @@ const _Database = class _Database extends import_events.EventEmitter {
430
431
  */
431
432
  collection(options) {
432
433
  options = import_lodash.default.cloneDeep(options);
433
- if (this.options.underscored) {
434
- options.underscored = true;
434
+ if (typeof options.underscored !== "boolean") {
435
+ if (this.options.underscored) {
436
+ options.underscored = true;
437
+ }
435
438
  }
436
439
  this.logger.trace(`beforeDefineCollection: ${(0, import_safe_json_stringify.default)(options)}`, {
437
440
  databaseInstanceId: this.instanceId
@@ -781,6 +784,57 @@ const _Database = class _Database extends import_events.EventEmitter {
781
784
  }
782
785
  });
783
786
  }
787
+ // 如果需要手动引用标识符,可以添加辅助方法
788
+ quoteIdentifier(identifier) {
789
+ return this.sequelize.getQueryInterface().queryGenerator["quoteIdentifier"](identifier);
790
+ }
791
+ quoteTable(tableName) {
792
+ return this.sequelize.getQueryInterface().quoteIdentifiers(tableName);
793
+ }
794
+ async runSQL(sql, options = {}) {
795
+ const { filter, bind, type, transaction } = options;
796
+ let finalSQL = sql;
797
+ if (!finalSQL.replace(/\s+/g, " ").trim()) {
798
+ throw new Error("SQL cannot be empty");
799
+ }
800
+ if (filter) {
801
+ let where = {};
802
+ const tmpCollection = new import_collection.Collection({ name: "tmp", underscored: false }, { database: this });
803
+ const r = tmpCollection.repository;
804
+ where = r.buildQueryOptions({ filter }).where;
805
+ const queryGenerator = this.sequelize.getQueryInterface().queryGenerator;
806
+ const wSQL = queryGenerator.getWhereConditions(where, null, null, { bindParam: true });
807
+ if (wSQL) {
808
+ let normalizedSQL = sql.replace(/\s+/g, " ").trim();
809
+ if (normalizedSQL.endsWith(";")) {
810
+ normalizedSQL = normalizedSQL.slice(0, -1).trim();
811
+ }
812
+ finalSQL = `SELECT * FROM (${normalizedSQL}) AS tmp WHERE ${wSQL}`;
813
+ }
814
+ }
815
+ this.logger.debug("runSQL", { finalSQL });
816
+ const result = await this.sequelize.query(finalSQL, { bind, transaction });
817
+ let data = result[0];
818
+ if (type === "selectVar") {
819
+ if (Array.isArray(data)) {
820
+ data = data[0];
821
+ }
822
+ return Object.values(data || {}).shift();
823
+ }
824
+ if (type === "selectRow") {
825
+ if (Array.isArray(data)) {
826
+ data = data[0];
827
+ }
828
+ return data || null;
829
+ }
830
+ if (type === "selectRows") {
831
+ if (!Array.isArray(data)) {
832
+ return [data].filter(Boolean);
833
+ }
834
+ return data;
835
+ }
836
+ return data;
837
+ }
784
838
  };
785
839
  __name(_Database, "Database");
786
840
  __publicField(_Database, "dialects", /* @__PURE__ */ new Map());
@@ -43,7 +43,6 @@ module.exports = __toCommonJS(inherited_sync_runner_exports);
43
43
  var import_lodash = __toESM(require("lodash"));
44
44
  const _InheritedSyncRunner = class _InheritedSyncRunner {
45
45
  static async syncInheritModel(model, options) {
46
- var _a;
47
46
  const { transaction } = options;
48
47
  options.hooks = options.hooks === void 0 ? true : !!options.hooks;
49
48
  const inheritedCollection = model.collection;
@@ -78,8 +77,9 @@ const _InheritedSyncRunner = class _InheritedSyncRunner {
78
77
  let maxSequenceName;
79
78
  if (childAttributes.id && childAttributes.id.autoIncrement) {
80
79
  for (const parent of parents) {
81
- const parentIdField = parent.getField("id");
82
- if (!((_a = parentIdField == null ? void 0 : parentIdField.options) == null ? void 0 : _a.autoIncrement)) {
80
+ const attributes2 = parent.model.getAttributes();
81
+ const parentIdField = attributes2["id"];
82
+ if (!(parentIdField == null ? void 0 : parentIdField.autoIncrement)) {
83
83
  continue;
84
84
  }
85
85
  const sequenceNameResult = await queryInterface.sequelize.query(
@@ -151,8 +151,14 @@ const _InheritedSyncRunner = class _InheritedSyncRunner {
151
151
  const columns = await queryInterface.describeTable(tableName, options);
152
152
  for (const attribute in childAttributes) {
153
153
  const columnName = childAttributes[attribute].field;
154
+ const fieldName = childAttributes[attribute].fieldName;
154
155
  if (!columns[columnName]) {
155
- await queryInterface.addColumn(tableName, columnName, childAttributes[columnName], options);
156
+ await queryInterface.addColumn(
157
+ tableName,
158
+ columnName,
159
+ childAttributes[columnName] || childAttributes[fieldName],
160
+ options
161
+ );
156
162
  }
157
163
  }
158
164
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@nocobase/database",
3
- "version": "1.9.0-beta.9",
3
+ "version": "2.0.0-alpha.3",
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.9.0-beta.9",
10
- "@nocobase/utils": "1.9.0-beta.9",
9
+ "@nocobase/logger": "2.0.0-alpha.3",
10
+ "@nocobase/utils": "2.0.0-alpha.3",
11
11
  "async-mutex": "^0.3.2",
12
12
  "chalk": "^4.1.1",
13
13
  "cron-parser": "4.4.0",
@@ -39,5 +39,5 @@
39
39
  "url": "git+https://github.com/nocobase/nocobase.git",
40
40
  "directory": "packages/database"
41
41
  },
42
- "gitHead": "b44464f1d1bbc96022d0f622e0a2f1d7e8d7142f"
42
+ "gitHead": "8efc23aa78058d871e98a91419f3c4a61762cc15"
43
43
  }