@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.
- package/lib/collection.d.ts +3 -0
- package/lib/collection.js +11 -4
- package/lib/database.d.ts +9 -1
- package/lib/database.js +56 -2
- package/lib/inherited-sync-runner.js +10 -4
- package/package.json +4 -4
package/lib/collection.d.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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 (
|
|
434
|
-
options.underscored
|
|
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
|
|
82
|
-
|
|
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(
|
|
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": "
|
|
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": "
|
|
10
|
-
"@nocobase/utils": "
|
|
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": "
|
|
42
|
+
"gitHead": "8efc23aa78058d871e98a91419f3c4a61762cc15"
|
|
43
43
|
}
|