@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.
@@ -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
- dumpable: 'required' | 'optional' | 'skip';
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
- getGroups(): CollectionGroup[];
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
- getGroups() {
30
- const collections = [...this.db.collections.values()];
31
- const groups = /* @__PURE__ */ new Map();
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
- const results = [...groups.values()];
80
- const groupCollections = results.map((i) => i.collections).flat();
81
- for (const skipItem of skipped) {
82
- if (groupCollections.includes(skipItem.name)) {
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
- return results;
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");
@@ -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 dumpable = 'required' | 'optional' | 'skip';
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
- registerCollectionType(): void;
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
- namespace: "core.migration",
231
- duplicator: "required",
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
- registerCollectionType() {
254
- this.collectionFactory.registerCollectionType(import_inherited_collection.InheritedCollection, {
255
- condition: (options) => {
256
- return options.inherits && import_lodash.default.castArray(options.inherits).length > 0;
257
- }
258
- });
259
- this.collectionFactory.registerCollectionType(import_view_collection.ViewCollection, {
260
- condition: (options) => {
261
- return options.viewName || options.view;
262
- }
263
- });
264
- this.collectionFactory.registerCollectionType(import_sql_collection.SqlCollection, {
265
- condition: (options) => {
266
- return options.sql;
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(module2);
672
- if (options.from) {
673
- this.importedFrom.set(options.from, [...this.importedFrom.get(options.from) || [], collection.name]);
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
  }
@@ -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.18.0-alpha.9",
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.18.0-alpha.9",
10
- "@nocobase/utils": "0.18.0-alpha.9",
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": "34ca0df4eede2e83fc86297b0fe19eba970e2b1b"
38
+ "gitHead": "cff5b77ecf12ccdb450d50d505b3aa44a68478c8"
39
39
  }