@nocobase/database 0.18.0-alpha.9 → 0.19.0-alpha.2
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-factory.d.ts +1 -0
- package/lib/collection-group-manager.d.ts +16 -3
- package/lib/collection-group-manager.js +20 -58
- package/lib/collection.d.ts +22 -15
- package/lib/collection.js +3 -0
- package/lib/database.d.ts +6 -3
- package/lib/database.js +66 -24
- package/lib/fields/belongs-to-many-field.js +3 -0
- package/lib/fields/field.js +1 -1
- package/lib/query-interface/mysql-query-interface.d.ts +15 -1
- package/lib/query-interface/mysql-query-interface.js +23 -0
- package/lib/query-interface/postgres-query-interface.d.ts +15 -0
- package/lib/query-interface/postgres-query-interface.js +45 -0
- package/lib/query-interface/query-interface.d.ts +15 -1
- package/lib/query-interface/sqlite-query-interface.d.ts +15 -0
- package/lib/query-interface/sqlite-query-interface.js +25 -0
- package/lib/value-parsers/date-value-parser.js +8 -0
- package/package.json +6 -6
|
@@ -4,6 +4,7 @@ import { Model } from './model';
|
|
|
4
4
|
type CollectionTypeOptions = {
|
|
5
5
|
condition: (options: CollectionOptions) => boolean;
|
|
6
6
|
onSync?: (model: typeof Model, options: any) => Promise<void>;
|
|
7
|
+
onDump?: (dumper: any, collection: Collection) => Promise<void>;
|
|
7
8
|
};
|
|
8
9
|
export declare class CollectionFactory {
|
|
9
10
|
private database;
|
|
@@ -1,13 +1,26 @@
|
|
|
1
|
+
import { BaseDumpRules, DumpRules } from './collection';
|
|
1
2
|
import Database from './database';
|
|
3
|
+
type RequiredGroup = 'required';
|
|
4
|
+
type SkippedGroup = 'skipped';
|
|
5
|
+
export type BuiltInGroup = RequiredGroup | SkippedGroup;
|
|
6
|
+
export type DumpRulesGroupType = BuiltInGroup | string;
|
|
2
7
|
export interface CollectionGroup {
|
|
3
|
-
namespace: string;
|
|
4
8
|
collections: string[];
|
|
5
9
|
function: string;
|
|
6
|
-
|
|
10
|
+
dataType: DumpRulesGroupType;
|
|
7
11
|
delayRestore?: any;
|
|
8
12
|
}
|
|
13
|
+
export interface CollectionGroupWithCollectionTitle extends Omit<CollectionGroup, 'collections'> {
|
|
14
|
+
collections: Array<{
|
|
15
|
+
name: string;
|
|
16
|
+
title: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
9
19
|
export declare class CollectionGroupManager {
|
|
10
20
|
db: Database;
|
|
11
21
|
constructor(db: Database);
|
|
12
|
-
|
|
22
|
+
static unifyDumpRules(dumpRules: DumpRules): (BaseDumpRules & {
|
|
23
|
+
group: DumpRulesGroupType;
|
|
24
|
+
}) | undefined;
|
|
13
25
|
}
|
|
26
|
+
export {};
|
|
@@ -21,70 +21,32 @@ __export(collection_group_manager_exports, {
|
|
|
21
21
|
CollectionGroupManager: () => CollectionGroupManager
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(collection_group_manager_exports);
|
|
24
|
-
var import_lodash = require("lodash");
|
|
25
24
|
const _CollectionGroupManager = class _CollectionGroupManager {
|
|
26
25
|
constructor(db) {
|
|
27
26
|
this.db = db;
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const skipped = [];
|
|
33
|
-
for (const collection of collections) {
|
|
34
|
-
const groupKey = collection.options.namespace;
|
|
35
|
-
if (!groupKey) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
const [namespace, groupFunc] = groupKey.split(".");
|
|
39
|
-
if (!groupFunc) {
|
|
40
|
-
skipped.push({
|
|
41
|
-
name: collection.name,
|
|
42
|
-
reason: "no-group-function"
|
|
43
|
-
});
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
if (!groups.has(groupKey)) {
|
|
47
|
-
const dumpable = (() => {
|
|
48
|
-
if (!collection.options.duplicator) {
|
|
49
|
-
return void 0;
|
|
50
|
-
}
|
|
51
|
-
if ((0, import_lodash.isString)(collection.options.duplicator)) {
|
|
52
|
-
return {
|
|
53
|
-
dumpable: collection.options.duplicator
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
return collection.options.duplicator;
|
|
57
|
-
})();
|
|
58
|
-
if (!dumpable) {
|
|
59
|
-
skipped.push({
|
|
60
|
-
name: collection.name,
|
|
61
|
-
reason: "no-dumpable"
|
|
62
|
-
});
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const group2 = {
|
|
66
|
-
namespace,
|
|
67
|
-
function: groupFunc,
|
|
68
|
-
collections: dumpable.with ? (0, import_lodash.castArray)(dumpable.with) : [],
|
|
69
|
-
dumpable: dumpable.dumpable
|
|
70
|
-
};
|
|
71
|
-
if (dumpable.delayRestore) {
|
|
72
|
-
group2.delayRestore = dumpable.delayRestore;
|
|
73
|
-
}
|
|
74
|
-
groups.set(groupKey, group2);
|
|
75
|
-
}
|
|
76
|
-
const group = groups.get(groupKey);
|
|
77
|
-
group.collections.push(collection.name);
|
|
28
|
+
static unifyDumpRules(dumpRules) {
|
|
29
|
+
if (!dumpRules) {
|
|
30
|
+
return void 0;
|
|
78
31
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
this.db.logger.warn(`collection ${skipItem.name} is not in any collection group, reason: ${skipItem.reason}.`);
|
|
32
|
+
if (typeof dumpRules === "string") {
|
|
33
|
+
return {
|
|
34
|
+
group: dumpRules
|
|
35
|
+
};
|
|
86
36
|
}
|
|
87
|
-
|
|
37
|
+
if ("required" in dumpRules && dumpRules.required) {
|
|
38
|
+
return {
|
|
39
|
+
...dumpRules,
|
|
40
|
+
group: "required"
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if ("skipped" in dumpRules && dumpRules.skipped) {
|
|
44
|
+
return {
|
|
45
|
+
...dumpRules,
|
|
46
|
+
group: "skipped"
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return dumpRules;
|
|
88
50
|
}
|
|
89
51
|
};
|
|
90
52
|
__name(_CollectionGroupManager, "CollectionGroupManager");
|
package/lib/collection.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { ModelOptions, ModelStatic, QueryInterfaceDropTableOptions, QueryInterfaceOptions, SyncOptions, Transactionable } from 'sequelize';
|
|
4
|
+
import { BuiltInGroup } from './collection-group-manager';
|
|
4
5
|
import { Database } from './database';
|
|
5
6
|
import { BelongsToField, Field, FieldOptions, HasManyField } from './fields';
|
|
6
7
|
import { Model } from './model';
|
|
@@ -10,24 +11,21 @@ export type CollectionSortable = string | boolean | {
|
|
|
10
11
|
name?: string;
|
|
11
12
|
scopeKey?: string;
|
|
12
13
|
};
|
|
13
|
-
type
|
|
14
|
+
export type BaseDumpRules = {
|
|
15
|
+
delayRestore?: any;
|
|
16
|
+
};
|
|
17
|
+
export type DumpRules = BuiltInGroup | ({
|
|
18
|
+
required: true;
|
|
19
|
+
} & BaseDumpRules) | ({
|
|
20
|
+
skipped: true;
|
|
21
|
+
} & BaseDumpRules) | ({
|
|
22
|
+
group: BuiltInGroup | string;
|
|
23
|
+
} & BaseDumpRules);
|
|
14
24
|
export interface CollectionOptions extends Omit<ModelOptions, 'name' | 'hooks'> {
|
|
15
25
|
name: string;
|
|
16
26
|
title?: string;
|
|
17
27
|
namespace?: string;
|
|
18
|
-
|
|
19
|
-
* Used for @nocobase/plugin-duplicator
|
|
20
|
-
* @see packages/core/database/src/collection-group-manager.tss
|
|
21
|
-
*
|
|
22
|
-
* @prop {'required' | 'optional' | 'skip'} dumpable - Determine whether the collection is dumped
|
|
23
|
-
* @prop {string[] | string} [with] - Collections dumped with this collection
|
|
24
|
-
* @prop {any} [delayRestore] - A function to execute after all collections are restored
|
|
25
|
-
*/
|
|
26
|
-
duplicator?: dumpable | {
|
|
27
|
-
dumpable: dumpable;
|
|
28
|
-
with?: string[] | string;
|
|
29
|
-
delayRestore?: any;
|
|
30
|
-
};
|
|
28
|
+
dumpRules?: DumpRules;
|
|
31
29
|
tableName?: string;
|
|
32
30
|
inherits?: string[] | string;
|
|
33
31
|
viewName?: string;
|
|
@@ -47,6 +45,15 @@ export interface CollectionOptions extends Omit<ModelOptions, 'name' | 'hooks'>
|
|
|
47
45
|
magicAttribute?: string;
|
|
48
46
|
tree?: string;
|
|
49
47
|
template?: string;
|
|
48
|
+
/**
|
|
49
|
+
* where is the collection from
|
|
50
|
+
*
|
|
51
|
+
* values
|
|
52
|
+
* - 'plugin' - collection is from plugin
|
|
53
|
+
* - 'core' - collection is from core
|
|
54
|
+
* - 'user' - collection is from user
|
|
55
|
+
*/
|
|
56
|
+
origin?: string;
|
|
50
57
|
[key: string]: any;
|
|
51
58
|
}
|
|
52
59
|
export interface CollectionContext {
|
|
@@ -62,6 +69,7 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
|
|
|
62
69
|
constructor(options: CollectionOptions, context: CollectionContext);
|
|
63
70
|
get filterTargetKey(): string;
|
|
64
71
|
get name(): string;
|
|
72
|
+
get origin(): string;
|
|
65
73
|
get titleField(): string;
|
|
66
74
|
get db(): Database;
|
|
67
75
|
get treeParentField(): BelongsToField | null;
|
|
@@ -125,4 +133,3 @@ export declare class Collection<TModelAttributes extends {} = any, TCreationAttr
|
|
|
125
133
|
private checkOptions;
|
|
126
134
|
private checkTableName;
|
|
127
135
|
}
|
|
128
|
-
export {};
|
package/lib/collection.js
CHANGED
|
@@ -105,6 +105,9 @@ const _Collection = class _Collection extends import_events.EventEmitter {
|
|
|
105
105
|
get name() {
|
|
106
106
|
return this.options.name;
|
|
107
107
|
}
|
|
108
|
+
get origin() {
|
|
109
|
+
return this.options.origin || "core";
|
|
110
|
+
}
|
|
108
111
|
get titleField() {
|
|
109
112
|
return this.options.titleField || this.model.primaryKeyAttribute;
|
|
110
113
|
}
|
package/lib/database.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { EventEmitter } from 'events';
|
|
|
6
6
|
import { ModelStatic, Options, QueryInterfaceDropAllTablesOptions, QueryOptions, Sequelize, SyncOptions, Transactionable } from 'sequelize';
|
|
7
7
|
import { Umzug } from 'umzug';
|
|
8
8
|
import { Collection, CollectionOptions, RepositoryType } from './collection';
|
|
9
|
+
import { CollectionFactory } from './collection-factory';
|
|
9
10
|
import { CollectionGroupManager } from './collection-group-manager';
|
|
10
11
|
import { ImportFileExtension } from './collection-importer';
|
|
11
12
|
import DatabaseUtils from './database-utils';
|
|
@@ -22,7 +23,6 @@ import { RelationRepository } from './relation-repository/relation-repository';
|
|
|
22
23
|
import { Repository } from './repository';
|
|
23
24
|
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';
|
|
24
25
|
import { BaseValueParser } from './value-parsers';
|
|
25
|
-
import { CollectionFactory } from './collection-factory';
|
|
26
26
|
export type MergeOptions = merge.Options;
|
|
27
27
|
export interface PendingOptions {
|
|
28
28
|
field: RelationField;
|
|
@@ -99,7 +99,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
|
|
|
99
99
|
utils: DatabaseUtils;
|
|
100
100
|
referenceMap: ReferencesMap;
|
|
101
101
|
inheritanceMap: InheritanceMap;
|
|
102
|
-
importedFrom: Map<string, string
|
|
102
|
+
importedFrom: Map<string, Set<string>>;
|
|
103
103
|
modelHook: ModelHook;
|
|
104
104
|
version: DatabaseVersion;
|
|
105
105
|
delayCollectionExtend: Map<string, {
|
|
@@ -113,7 +113,9 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
|
|
|
113
113
|
constructor(options: DatabaseOptions);
|
|
114
114
|
_instanceId: string;
|
|
115
115
|
get instanceId(): string;
|
|
116
|
-
|
|
116
|
+
createMigrator({ migrations }: {
|
|
117
|
+
migrations: any;
|
|
118
|
+
}): Umzug<any>;
|
|
117
119
|
setContext(context: any): void;
|
|
118
120
|
sequelizeOptions(options: any): any;
|
|
119
121
|
initListener(): void;
|
|
@@ -180,6 +182,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
|
|
|
180
182
|
from?: string;
|
|
181
183
|
extensions?: ImportFileExtension[];
|
|
182
184
|
}): Promise<Map<string, Collection>>;
|
|
185
|
+
private registerCollectionType;
|
|
183
186
|
}
|
|
184
187
|
export declare function extendCollection(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions): {
|
|
185
188
|
collectionOptions: CollectionOptions;
|
package/lib/database.js
CHANGED
|
@@ -38,6 +38,7 @@ __export(database_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(database_exports);
|
|
39
39
|
var import_logger = require("@nocobase/logger");
|
|
40
40
|
var import_utils = require("@nocobase/utils");
|
|
41
|
+
var import_chalk = __toESM(require("chalk"));
|
|
41
42
|
var import_events = require("events");
|
|
42
43
|
var import_exponential_backoff = require("exponential-backoff");
|
|
43
44
|
var import_glob = __toESM(require("glob"));
|
|
@@ -47,12 +48,14 @@ var import_path = require("path");
|
|
|
47
48
|
var import_semver = __toESM(require("semver"));
|
|
48
49
|
var import_sequelize = require("sequelize");
|
|
49
50
|
var import_umzug = require("umzug");
|
|
51
|
+
var import_collection_factory = require("./collection-factory");
|
|
50
52
|
var import_collection_group_manager = require("./collection-group-manager");
|
|
51
53
|
var import_collection_importer = require("./collection-importer");
|
|
52
54
|
var import_database_utils = __toESM(require("./database-utils"));
|
|
53
55
|
var import_ReferencesMap = __toESM(require("./features/ReferencesMap"));
|
|
54
56
|
var import_referential_integrity_check = require("./features/referential-integrity-check");
|
|
55
57
|
var FieldTypes = __toESM(require("./fields"));
|
|
58
|
+
var import_helpers = require("./helpers");
|
|
56
59
|
var import_inherited_collection = require("./inherited-collection");
|
|
57
60
|
var import_inherited_map = __toESM(require("./inherited-map"));
|
|
58
61
|
var import_listeners = require("./listeners");
|
|
@@ -64,9 +67,6 @@ var import_sql_collection = require("./sql-collection/sql-collection");
|
|
|
64
67
|
var import_utils2 = require("./utils");
|
|
65
68
|
var import_value_parsers = require("./value-parsers");
|
|
66
69
|
var import_view_collection = require("./view-collection");
|
|
67
|
-
var import_collection_factory = require("./collection-factory");
|
|
68
|
-
var import_chalk = __toESM(require("chalk"));
|
|
69
|
-
var import_helpers = require("./helpers");
|
|
70
70
|
const DialectVersionAccessors = {
|
|
71
71
|
sqlite: {
|
|
72
72
|
sql: "select sqlite_version() as version",
|
|
@@ -227,8 +227,8 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
227
227
|
name: "migrations",
|
|
228
228
|
autoGenId: false,
|
|
229
229
|
timestamps: false,
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
dumpRules: "required",
|
|
231
|
+
origin: "@nocobase/database",
|
|
232
232
|
fields: [{ type: "string", name: "name", primaryKey: true }]
|
|
233
233
|
});
|
|
234
234
|
this.migrator = new import_umzug.Umzug({
|
|
@@ -250,21 +250,24 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
250
250
|
get instanceId() {
|
|
251
251
|
return this._instanceId;
|
|
252
252
|
}
|
|
253
|
-
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
253
|
+
createMigrator({ migrations }) {
|
|
254
|
+
const migratorOptions = this.options.migrator || {};
|
|
255
|
+
const context = {
|
|
256
|
+
db: this,
|
|
257
|
+
sequelize: this.sequelize,
|
|
258
|
+
queryInterface: this.sequelize.getQueryInterface(),
|
|
259
|
+
...migratorOptions.context
|
|
260
|
+
};
|
|
261
|
+
return new import_umzug.Umzug({
|
|
262
|
+
logger: migratorOptions.logger || console,
|
|
263
|
+
migrations: Array.isArray(migrations) ? import_lodash.default.sortBy(migrations, (m) => m.name) : migrations,
|
|
264
|
+
context,
|
|
265
|
+
storage: new import_umzug.SequelizeStorage({
|
|
266
|
+
tableName: `${this.options.tablePrefix || ""}migrations`,
|
|
267
|
+
modelName: "migrations",
|
|
268
|
+
...migratorOptions.storage,
|
|
269
|
+
sequelize: this.sequelize
|
|
270
|
+
})
|
|
268
271
|
});
|
|
269
272
|
}
|
|
270
273
|
setContext(context) {
|
|
@@ -353,6 +356,14 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
353
356
|
options.schema = this.options.schema;
|
|
354
357
|
}
|
|
355
358
|
});
|
|
359
|
+
this.on("afterDefineCollection", async (collection) => {
|
|
360
|
+
const options = collection.options;
|
|
361
|
+
if (options.origin) {
|
|
362
|
+
const existsSet = this.importedFrom.get(options.origin) || /* @__PURE__ */ new Set();
|
|
363
|
+
existsSet.add(collection.name);
|
|
364
|
+
this.importedFrom.set(options.origin, existsSet);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
356
367
|
(0, import_listeners.registerBuiltInListeners)(this);
|
|
357
368
|
}
|
|
358
369
|
addMigration(item) {
|
|
@@ -668,15 +679,46 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
668
679
|
if (module2.extend) {
|
|
669
680
|
this.extendCollection(module2.collectionOptions, module2.mergeOptions);
|
|
670
681
|
} else {
|
|
671
|
-
const collection = this.collection(
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
682
|
+
const collection = this.collection({
|
|
683
|
+
...module2,
|
|
684
|
+
origin: options.from
|
|
685
|
+
});
|
|
675
686
|
result.set(collection.name, collection);
|
|
676
687
|
}
|
|
677
688
|
}
|
|
678
689
|
return result;
|
|
679
690
|
}
|
|
691
|
+
registerCollectionType() {
|
|
692
|
+
this.collectionFactory.registerCollectionType(import_inherited_collection.InheritedCollection, {
|
|
693
|
+
condition: (options) => {
|
|
694
|
+
return options.inherits && import_lodash.default.castArray(options.inherits).length > 0;
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
this.collectionFactory.registerCollectionType(import_view_collection.ViewCollection, {
|
|
698
|
+
condition: (options) => {
|
|
699
|
+
return options.viewName || options.view;
|
|
700
|
+
},
|
|
701
|
+
async onSync() {
|
|
702
|
+
return;
|
|
703
|
+
},
|
|
704
|
+
async onDump(dumper, collection) {
|
|
705
|
+
const viewDef = await collection.db.queryInterface.viewDef(collection.getTableNameWithSchemaAsString());
|
|
706
|
+
dumper.writeSQLContent(`view-${collection.name}`, {
|
|
707
|
+
sql: [
|
|
708
|
+
`DROP VIEW IF EXISTS ${collection.getTableNameWithSchemaAsString()}`,
|
|
709
|
+
`CREATE VIEW ${collection.getTableNameWithSchemaAsString()} AS ${viewDef}`
|
|
710
|
+
],
|
|
711
|
+
group: "required"
|
|
712
|
+
});
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
this.collectionFactory.registerCollectionType(import_sql_collection.SqlCollection, {
|
|
717
|
+
condition: (options) => {
|
|
718
|
+
return options.sql;
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
}
|
|
680
722
|
};
|
|
681
723
|
__name(_Database, "Database");
|
|
682
724
|
let Database = _Database;
|
|
@@ -69,6 +69,9 @@ const _BelongsToManyField = class _BelongsToManyField extends import_relation_fi
|
|
|
69
69
|
const throughCollectionOptions = {
|
|
70
70
|
name: through
|
|
71
71
|
};
|
|
72
|
+
if (this.collection.options.dumpRules) {
|
|
73
|
+
throughCollectionOptions["dumpRules"] = this.collection.options.dumpRules;
|
|
74
|
+
}
|
|
72
75
|
if (this.collection.collectionSchema()) {
|
|
73
76
|
throughCollectionOptions["schema"] = this.collection.collectionSchema();
|
|
74
77
|
}
|
package/lib/fields/field.js
CHANGED
|
@@ -137,7 +137,7 @@ const _Field = class _Field {
|
|
|
137
137
|
toSequelize() {
|
|
138
138
|
const opts = import_lodash.default.omit(this.options, ["name"]);
|
|
139
139
|
if (this.dataType) {
|
|
140
|
-
Object.assign(opts, { type: this.dataType });
|
|
140
|
+
Object.assign(opts, { type: this.database.sequelize.normalizeDataType(this.dataType) });
|
|
141
141
|
}
|
|
142
142
|
return opts;
|
|
143
143
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transactionable } from 'sequelize';
|
|
1
|
+
import { Transaction, Transactionable } from 'sequelize';
|
|
2
2
|
import { Collection } from '../collection';
|
|
3
3
|
import QueryInterface, { TableInfo } from './query-interface';
|
|
4
4
|
export default class MysqlQueryInterface extends QueryInterface {
|
|
@@ -18,4 +18,18 @@ export default class MysqlQueryInterface extends QueryInterface {
|
|
|
18
18
|
parseSQL(sql: string): any;
|
|
19
19
|
viewDef(viewName: string): Promise<string>;
|
|
20
20
|
showTableDefinition(tableInfo: TableInfo): Promise<any>;
|
|
21
|
+
getAutoIncrementInfo(options: {
|
|
22
|
+
tableInfo: TableInfo;
|
|
23
|
+
fieldName: string;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
seqName?: string;
|
|
26
|
+
currentVal: number;
|
|
27
|
+
}>;
|
|
28
|
+
setAutoIncrementVal(options: {
|
|
29
|
+
tableInfo: TableInfo;
|
|
30
|
+
columnName: string;
|
|
31
|
+
seqName?: string;
|
|
32
|
+
currentVal: number;
|
|
33
|
+
transaction?: Transaction;
|
|
34
|
+
}): Promise<void>;
|
|
21
35
|
}
|
|
@@ -94,6 +94,29 @@ const _MysqlQueryInterface = class _MysqlQueryInterface extends import_query_int
|
|
|
94
94
|
const results = await this.db.sequelize.query(sql, { type: "SELECT" });
|
|
95
95
|
return results[0]["Create Table"];
|
|
96
96
|
}
|
|
97
|
+
async getAutoIncrementInfo(options) {
|
|
98
|
+
const { tableInfo, fieldName } = options;
|
|
99
|
+
const sql = `SELECT AUTO_INCREMENT as currentVal
|
|
100
|
+
FROM information_schema.tables
|
|
101
|
+
WHERE table_schema = DATABASE()
|
|
102
|
+
AND table_name = '${tableInfo.tableName}';`;
|
|
103
|
+
const results = await this.db.sequelize.query(sql, { type: "SELECT" });
|
|
104
|
+
let currentVal = results[0]["currentVal"];
|
|
105
|
+
if (currentVal === null) {
|
|
106
|
+
const maxSql = `SELECT MAX(${fieldName}) as currentVal
|
|
107
|
+
FROM ${tableInfo.tableName};`;
|
|
108
|
+
const maxResults = await this.db.sequelize.query(maxSql, { type: "SELECT" });
|
|
109
|
+
currentVal = maxResults[0]["currentVal"];
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
currentVal
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async setAutoIncrementVal(options) {
|
|
116
|
+
const { tableInfo, columnName, seqName, currentVal, transaction } = options;
|
|
117
|
+
const sql = `ALTER TABLE ${tableInfo.tableName} AUTO_INCREMENT = ${currentVal};`;
|
|
118
|
+
await this.db.sequelize.query(sql, { transaction });
|
|
119
|
+
}
|
|
97
120
|
};
|
|
98
121
|
__name(_MysqlQueryInterface, "MysqlQueryInterface");
|
|
99
122
|
let MysqlQueryInterface = _MysqlQueryInterface;
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import { Collection } from '../collection';
|
|
2
2
|
import QueryInterface, { TableInfo } from './query-interface';
|
|
3
|
+
import { Transaction } from 'sequelize';
|
|
3
4
|
export default class PostgresQueryInterface extends QueryInterface {
|
|
4
5
|
constructor(db: any);
|
|
6
|
+
setAutoIncrementVal(options: {
|
|
7
|
+
tableInfo: TableInfo;
|
|
8
|
+
columnName: string;
|
|
9
|
+
seqName?: string;
|
|
10
|
+
currentVal?: number;
|
|
11
|
+
transaction?: Transaction;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
getAutoIncrementInfo(options: {
|
|
14
|
+
tableInfo: TableInfo;
|
|
15
|
+
fieldName: string;
|
|
16
|
+
}): Promise<{
|
|
17
|
+
seqName?: string;
|
|
18
|
+
currentVal: number;
|
|
19
|
+
}>;
|
|
5
20
|
collectionTableExists(collection: Collection, options?: any): Promise<any>;
|
|
6
21
|
listViews(): Promise<[unknown[], unknown]>;
|
|
7
22
|
viewDef(viewName: string): Promise<string>;
|
|
@@ -38,6 +38,51 @@ const _PostgresQueryInterface = class _PostgresQueryInterface extends import_que
|
|
|
38
38
|
constructor(db) {
|
|
39
39
|
super(db);
|
|
40
40
|
}
|
|
41
|
+
async setAutoIncrementVal(options) {
|
|
42
|
+
const { tableInfo, columnName, seqName, currentVal, transaction } = options;
|
|
43
|
+
if (!seqName) {
|
|
44
|
+
throw new Error("seqName is required to set auto increment val in postgres");
|
|
45
|
+
}
|
|
46
|
+
await this.db.sequelize.query(
|
|
47
|
+
`alter table ${this.db.utils.quoteTable({
|
|
48
|
+
tableName: tableInfo.tableName,
|
|
49
|
+
schema: tableInfo.schema
|
|
50
|
+
})}
|
|
51
|
+
alter column "${columnName}" set default nextval('${seqName}')`,
|
|
52
|
+
{
|
|
53
|
+
transaction
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
if (currentVal) {
|
|
57
|
+
await this.db.sequelize.query(`select setval('${seqName}', ${currentVal})`, {
|
|
58
|
+
transaction
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async getAutoIncrementInfo(options) {
|
|
63
|
+
const fieldName = options.fieldName || "id";
|
|
64
|
+
const tableInfo = options.tableInfo;
|
|
65
|
+
const sequenceNameResult = await this.db.sequelize.query(
|
|
66
|
+
`SELECT column_default
|
|
67
|
+
FROM information_schema.columns
|
|
68
|
+
WHERE table_name = '${tableInfo.tableName}'
|
|
69
|
+
and table_schema = '${tableInfo.schema || "public"}'
|
|
70
|
+
and "column_name" = '${fieldName}';`
|
|
71
|
+
);
|
|
72
|
+
const columnDefault = sequenceNameResult[0][0]["column_default"];
|
|
73
|
+
const regex = new RegExp(/nextval\('(.*)'::regclass\)/);
|
|
74
|
+
const match = regex.exec(columnDefault);
|
|
75
|
+
const sequenceName = match[1];
|
|
76
|
+
const sequenceCurrentValResult = await this.db.sequelize.query(
|
|
77
|
+
`select last_value
|
|
78
|
+
from ${sequenceName}`
|
|
79
|
+
);
|
|
80
|
+
const sequenceCurrentVal = parseInt(sequenceCurrentValResult[0][0]["last_value"]);
|
|
81
|
+
return {
|
|
82
|
+
seqName: sequenceName,
|
|
83
|
+
currentVal: sequenceCurrentVal
|
|
84
|
+
};
|
|
85
|
+
}
|
|
41
86
|
async collectionTableExists(collection, options) {
|
|
42
87
|
const transaction = options == null ? void 0 : options.transaction;
|
|
43
88
|
const tableName = collection.model.tableName;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { QueryInterface as SequelizeQueryInterface, Transactionable } from 'sequelize';
|
|
1
|
+
import { QueryInterface as SequelizeQueryInterface, Transaction, Transactionable } from 'sequelize';
|
|
2
2
|
import { Collection } from '../collection';
|
|
3
3
|
import Database from '../database';
|
|
4
4
|
export type TableInfo = {
|
|
@@ -25,4 +25,18 @@ export default abstract class QueryInterface {
|
|
|
25
25
|
abstract parseSQL(sql: string): any;
|
|
26
26
|
abstract showTableDefinition(tableInfo: TableInfo): Promise<any>;
|
|
27
27
|
dropAll(options: any): Promise<void>;
|
|
28
|
+
abstract getAutoIncrementInfo(options: {
|
|
29
|
+
tableInfo: TableInfo;
|
|
30
|
+
fieldName: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
seqName?: string;
|
|
33
|
+
currentVal: number;
|
|
34
|
+
}>;
|
|
35
|
+
abstract setAutoIncrementVal(options: {
|
|
36
|
+
tableInfo: TableInfo;
|
|
37
|
+
columnName: string;
|
|
38
|
+
seqName?: string;
|
|
39
|
+
currentVal: number;
|
|
40
|
+
transaction?: Transaction;
|
|
41
|
+
}): Promise<void>;
|
|
28
42
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Collection } from '../collection';
|
|
2
2
|
import QueryInterface, { TableInfo } from './query-interface';
|
|
3
|
+
import { Transaction } from 'sequelize';
|
|
3
4
|
export default class SqliteQueryInterface extends QueryInterface {
|
|
4
5
|
constructor(db: any);
|
|
5
6
|
collectionTableExists(collection: Collection, options?: any): Promise<boolean>;
|
|
@@ -17,4 +18,18 @@ export default class SqliteQueryInterface extends QueryInterface {
|
|
|
17
18
|
parseSQL(sql: string): any;
|
|
18
19
|
viewDef(viewName: string): Promise<string>;
|
|
19
20
|
showTableDefinition(tableInfo: TableInfo): Promise<any>;
|
|
21
|
+
getAutoIncrementInfo(options: {
|
|
22
|
+
tableInfo: TableInfo;
|
|
23
|
+
fieldName: string;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
seqName?: string;
|
|
26
|
+
currentVal: number;
|
|
27
|
+
}>;
|
|
28
|
+
setAutoIncrementVal(options: {
|
|
29
|
+
tableInfo: TableInfo;
|
|
30
|
+
columnName: string;
|
|
31
|
+
seqName?: string;
|
|
32
|
+
currentVal: number;
|
|
33
|
+
transaction?: Transaction;
|
|
34
|
+
}): Promise<void>;
|
|
20
35
|
}
|
|
@@ -101,6 +101,31 @@ const _SqliteQueryInterface = class _SqliteQueryInterface extends import_query_i
|
|
|
101
101
|
showTableDefinition(tableInfo) {
|
|
102
102
|
return Promise.resolve(void 0);
|
|
103
103
|
}
|
|
104
|
+
async getAutoIncrementInfo(options) {
|
|
105
|
+
const { tableInfo } = options;
|
|
106
|
+
const tableName = tableInfo.tableName;
|
|
107
|
+
const sql = `SELECT seq
|
|
108
|
+
FROM sqlite_sequence
|
|
109
|
+
WHERE name = '${tableName}';`;
|
|
110
|
+
const results = await this.db.sequelize.query(sql, { type: "SELECT" });
|
|
111
|
+
const row = results[0];
|
|
112
|
+
if (!row) {
|
|
113
|
+
return {
|
|
114
|
+
currentVal: 0
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
currentVal: row["seq"]
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async setAutoIncrementVal(options) {
|
|
122
|
+
const { tableInfo, columnName, seqName, currentVal, transaction } = options;
|
|
123
|
+
const tableName = tableInfo.tableName;
|
|
124
|
+
const sql = `UPDATE sqlite_sequence
|
|
125
|
+
SET seq = ${currentVal}
|
|
126
|
+
WHERE name = '${tableName}';`;
|
|
127
|
+
await this.db.sequelize.query(sql, { transaction });
|
|
128
|
+
}
|
|
104
129
|
};
|
|
105
130
|
__name(_SqliteQueryInterface, "SqliteQueryInterface");
|
|
106
131
|
let SqliteQueryInterface = _SqliteQueryInterface;
|
|
@@ -45,6 +45,14 @@ function isNumeric(str) {
|
|
|
45
45
|
__name(isNumeric, "isNumeric");
|
|
46
46
|
const _DateValueParser = class _DateValueParser extends import_base_value_parser.BaseValueParser {
|
|
47
47
|
async setValue(value) {
|
|
48
|
+
if (typeof value === "string") {
|
|
49
|
+
const match = /^(\d{4})[-/]?(\d{2})[-/]?(\d{2})$/.exec(value);
|
|
50
|
+
if (match) {
|
|
51
|
+
const m = (0, import_dayjs.default)(`${match[1]}-${match[2]}-${match[3]} 00:00:00.000`);
|
|
52
|
+
this.value = m.toISOString();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
48
56
|
if (import_dayjs.default.isDayjs(value)) {
|
|
49
57
|
this.value = value;
|
|
50
58
|
} else if (isDate(value)) {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0-alpha.2",
|
|
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": "0.
|
|
10
|
-
"@nocobase/utils": "0.
|
|
9
|
+
"@nocobase/logger": "0.19.0-alpha.2",
|
|
10
|
+
"@nocobase/utils": "0.19.0-alpha.2",
|
|
11
11
|
"async-mutex": "^0.3.2",
|
|
12
12
|
"chalk": "^4.1.1",
|
|
13
13
|
"cron-parser": "4.4.0",
|
|
@@ -21,19 +21,19 @@
|
|
|
21
21
|
"lodash": "^4.17.21",
|
|
22
22
|
"mathjs": "^10.6.1",
|
|
23
23
|
"nanoid": "^3.3.6",
|
|
24
|
+
"node-fetch": "^2.6.7",
|
|
24
25
|
"qs": "^6.11.2",
|
|
25
26
|
"semver": "^7.3.7",
|
|
26
27
|
"sequelize": "^6.26.0",
|
|
27
28
|
"umzug": "^3.1.1"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
|
-
"@types/glob": "^7.2.0"
|
|
31
|
-
"node-fetch": "^2.6.7"
|
|
31
|
+
"@types/glob": "^7.2.0"
|
|
32
32
|
},
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
|
35
35
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
36
36
|
"directory": "packages/database"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "cff5b77ecf12ccdb450d50d505b3aa44a68478c8"
|
|
39
39
|
}
|