@nocobase/database 0.7.6-alpha.2 → 0.8.0-alpha.10

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.
Files changed (72) hide show
  1. package/lib/collection.d.ts +1 -1
  2. package/lib/collection.js +1 -0
  3. package/lib/database.d.ts +17 -2
  4. package/lib/database.js +53 -41
  5. package/lib/decorators/transaction-decorator.js +1 -0
  6. package/lib/features/ReferencesMap.d.ts +15 -0
  7. package/lib/features/ReferencesMap.js +60 -0
  8. package/lib/features/referential-integrity-check.d.ts +8 -0
  9. package/lib/features/referential-integrity-check.js +89 -0
  10. package/lib/fields/belongs-to-field.d.ts +2 -0
  11. package/lib/fields/belongs-to-field.js +17 -2
  12. package/lib/fields/belongs-to-many-field.d.ts +1 -0
  13. package/lib/fields/belongs-to-many-field.js +9 -2
  14. package/lib/fields/context-field.d.ts +2 -1
  15. package/lib/fields/context-field.js +12 -8
  16. package/lib/fields/field.d.ts +2 -1
  17. package/lib/fields/field.js +1 -0
  18. package/lib/fields/formula-field.js +1 -1
  19. package/lib/fields/has-many-field.d.ts +2 -0
  20. package/lib/fields/has-many-field.js +21 -2
  21. package/lib/fields/has-one-field.d.ts +2 -0
  22. package/lib/fields/has-one-field.js +17 -2
  23. package/lib/fields/relation-field.d.ts +1 -0
  24. package/lib/fields/relation-field.js +16 -0
  25. package/lib/fields/sequence-field.d.ts +2 -1
  26. package/lib/fields/sequence-field.js +3 -2
  27. package/lib/filter-parser.js +5 -3
  28. package/lib/model.d.ts +1 -0
  29. package/lib/options-parser.js +3 -2
  30. package/lib/relation-repository/belongs-to-many-repository.d.ts +3 -3
  31. package/lib/relation-repository/hasmany-repository.d.ts +2 -2
  32. package/lib/relation-repository/hasone-repository.d.ts +2 -4
  33. package/lib/relation-repository/multiple-relation-repository.d.ts +2 -5
  34. package/lib/relation-repository/relation-repository.js +2 -2
  35. package/lib/relation-repository/single-relation-repository.d.ts +1 -1
  36. package/lib/repository.d.ts +25 -15
  37. package/lib/repository.js +3 -1
  38. package/lib/types.d.ts +43 -0
  39. package/lib/types.js +5 -0
  40. package/package.json +3 -3
  41. package/src/__tests__/fields/belongs-to-field.test.ts +112 -4
  42. package/src/__tests__/fields/has-many-field.test.ts +83 -0
  43. package/src/__tests__/fields/sequence-field.test.ts +25 -0
  44. package/src/__tests__/relation-repository/hasone-repository.test.ts +3 -3
  45. package/src/__tests__/repository/find.test.ts +10 -0
  46. package/src/collection.ts +3 -1
  47. package/src/database.ts +64 -15
  48. package/src/decorators/transaction-decorator.ts +1 -0
  49. package/src/features/ReferencesMap.ts +64 -0
  50. package/src/features/referential-integrity-check.ts +61 -0
  51. package/src/fields/belongs-to-field.ts +22 -1
  52. package/src/fields/belongs-to-many-field.ts +11 -0
  53. package/src/fields/context-field.ts +5 -7
  54. package/src/fields/field.ts +3 -2
  55. package/src/fields/formula-field.ts +4 -4
  56. package/src/fields/has-many-field.ts +26 -2
  57. package/src/fields/has-one-field.ts +23 -2
  58. package/src/fields/relation-field.ts +16 -0
  59. package/src/fields/sequence-field.ts +4 -2
  60. package/src/filter-parser.ts +5 -1
  61. package/src/model-hook.ts +0 -2
  62. package/src/model.ts +1 -0
  63. package/src/options-parser.ts +4 -2
  64. package/src/relation-repository/belongs-to-many-repository.ts +3 -3
  65. package/src/relation-repository/hasmany-repository.ts +8 -5
  66. package/src/relation-repository/hasone-repository.ts +2 -4
  67. package/src/relation-repository/multiple-relation-repository.ts +3 -4
  68. package/src/relation-repository/relation-repository.ts +1 -1
  69. package/src/relation-repository/single-relation-repository.ts +1 -1
  70. package/src/repository.ts +40 -19
  71. package/src/types.ts +64 -0
  72. package/src/update-associations.ts +2 -1
@@ -9,14 +9,12 @@ export class ContextField extends Field {
9
9
  return DataTypes[type.toUpperCase()] || DataTypes.STRING;
10
10
  }
11
11
 
12
- init() {
12
+ listener = async (model: Model, options) => {
13
13
  const { name, dataIndex } = this.options;
14
- this.listener = async (model: Model, options) => {
15
- const { context } = options;
16
- model.set(name, lodash.get(context, dataIndex));
17
- model.changed(name, true);
18
- };
19
- }
14
+ const { context } = options;
15
+ model.set(name, lodash.get(context, dataIndex));
16
+ model.changed(name, true);
17
+ };
20
18
 
21
19
  bind() {
22
20
  super.bind();
@@ -9,7 +9,7 @@ import {
9
9
  } from 'sequelize';
10
10
  import { Collection } from '../collection';
11
11
  import { Database } from '../database';
12
- import { checkIdentifier } from '../utils';
12
+ import { ModelEventTypes } from '../types';
13
13
 
14
14
  export interface FieldContext {
15
15
  database: Database;
@@ -68,7 +68,7 @@ export abstract class Field {
68
68
  // code
69
69
  }
70
70
 
71
- on(eventName: string, listener: (...args: any[]) => void) {
71
+ on(eventName: ModelEventTypes, listener: (...args: any[]) => void) {
72
72
  this.database.on(`${this.collection.name}.${eventName}`, listener);
73
73
  return this;
74
74
  }
@@ -83,6 +83,7 @@ export abstract class Field {
83
83
  }
84
84
 
85
85
  remove() {
86
+ this.collection.removeIndex([this.name]);
86
87
  return this.collection.removeField(this.name);
87
88
  }
88
89
 
@@ -40,7 +40,7 @@ export class FormulaField extends Field {
40
40
  );
41
41
  }
42
42
  }
43
- }
43
+ };
44
44
 
45
45
  caculateField = async (instance) => {
46
46
  const { expression, name } = this.options;
@@ -50,10 +50,10 @@ export class FormulaField extends Field {
50
50
  result = math.evaluate(expression, scope);
51
51
  result = math.round(result, 9);
52
52
  } catch {}
53
- if (result) {
53
+ if (result === 0 || result) {
54
54
  instance.set(name, result);
55
55
  }
56
- }
56
+ };
57
57
 
58
58
  updateFieldData = async (instance, { transaction }) => {
59
59
  if (this.collection.name === instance.collectionName && instance.name === this.options.name) {
@@ -80,7 +80,7 @@ export class FormulaField extends Field {
80
80
  );
81
81
  }
82
82
  }
83
- }
83
+ };
84
84
 
85
85
  bind() {
86
86
  super.bind();
@@ -5,11 +5,12 @@ import {
5
5
  ForeignKeyOptions,
6
6
  HasManyOptions,
7
7
  HasManyOptions as SequelizeHasManyOptions,
8
- Utils
8
+ Utils,
9
9
  } from 'sequelize';
10
10
  import { Collection } from '../collection';
11
11
  import { checkIdentifier } from '../utils';
12
12
  import { MultipleRelationFieldOptions, RelationField } from './relation-field';
13
+ import { Reference } from '../features/ReferencesMap';
13
14
 
14
15
  export interface HasManyFieldOptions extends HasManyOptions {
15
16
  /**
@@ -81,6 +82,18 @@ export class HasManyField extends RelationField {
81
82
  return Utils.camelize([model.options.name.singular, this.sourceKey || model.primaryKeyAttribute].join('_'));
82
83
  }
83
84
 
85
+ reference(association): Reference {
86
+ const sourceKey = association.sourceKey;
87
+
88
+ return {
89
+ sourceCollectionName: this.database.modelCollection.get(association.target).name,
90
+ sourceField: association.foreignKey,
91
+ targetField: sourceKey,
92
+ targetCollectionName: this.database.modelCollection.get(association.source).name,
93
+ onDelete: this.options.onDelete,
94
+ };
95
+ }
96
+
84
97
  bind() {
85
98
  const { database, collection } = this.context;
86
99
  const Target = this.TargetModel;
@@ -95,7 +108,7 @@ export class HasManyField extends RelationField {
95
108
 
96
109
  const association = collection.model.hasMany(Target, {
97
110
  constraints: false,
98
- ...omit(this.options, ['name', 'type', 'target']),
111
+ ...omit(this.options, ['name', 'type', 'target', 'onDelete']),
99
112
  as: this.name,
100
113
  foreignKey: this.foreignKey,
101
114
  });
@@ -130,6 +143,9 @@ export class HasManyField extends RelationField {
130
143
  if (tcoll) {
131
144
  tcoll.addIndex([this.options.foreignKey]);
132
145
  }
146
+
147
+ this.database.referenceMap.addReference(this.reference(association));
148
+
133
149
  return true;
134
150
  }
135
151
 
@@ -149,6 +165,14 @@ export class HasManyField extends RelationField {
149
165
  if (!field) {
150
166
  tcoll.model.removeAttribute(foreignKey);
151
167
  }
168
+
169
+ const association = collection.model.associations[this.name];
170
+
171
+ if (association) {
172
+ this.database.referenceMap.removeReference(this.reference(association));
173
+ }
174
+
175
+ this.clearAccessors();
152
176
  // 删掉 model 的关联字段
153
177
  delete collection.model.associations[this.name];
154
178
  // @ts-ignore
@@ -5,11 +5,12 @@ import {
5
5
  ForeignKeyOptions,
6
6
  HasOneOptions,
7
7
  HasOneOptions as SequelizeHasOneOptions,
8
- Utils
8
+ Utils,
9
9
  } from 'sequelize';
10
10
  import { Collection } from '../collection';
11
11
  import { checkIdentifier } from '../utils';
12
12
  import { BaseRelationFieldOptions, RelationField } from './relation-field';
13
+ import { Reference } from '../features/ReferencesMap';
13
14
 
14
15
  export interface HasOneFieldOptions extends HasOneOptions {
15
16
  /**
@@ -86,9 +87,22 @@ export class HasOneField extends RelationField {
86
87
  return Utils.camelize([model.options.name.singular, model.primaryKeyAttribute].join('_'));
87
88
  }
88
89
 
90
+ reference(association): Reference {
91
+ const sourceKey = association.sourceKey;
92
+
93
+ return {
94
+ sourceCollectionName: this.database.modelCollection.get(association.target).name,
95
+ sourceField: association.foreignKey,
96
+ targetField: sourceKey,
97
+ targetCollectionName: this.database.modelCollection.get(association.source).name,
98
+ onDelete: this.options.onDelete,
99
+ };
100
+ }
101
+
89
102
  bind() {
90
103
  const { database, collection } = this.context;
91
104
  const Target = this.TargetModel;
105
+
92
106
  if (!Target) {
93
107
  database.addPendingField(this);
94
108
  return false;
@@ -96,7 +110,7 @@ export class HasOneField extends RelationField {
96
110
 
97
111
  const association = collection.model.hasOne(Target, {
98
112
  constraints: false,
99
- ...omit(this.options, ['name', 'type', 'target']),
113
+ ...omit(this.options, ['name', 'type', 'target', 'onDelete']),
100
114
  as: this.name,
101
115
  foreignKey: this.foreignKey,
102
116
  });
@@ -129,6 +143,8 @@ export class HasOneField extends RelationField {
129
143
  if (tcoll) {
130
144
  tcoll.addIndex([this.options.foreignKey]);
131
145
  }
146
+
147
+ this.database.referenceMap.addReference(this.reference(association));
132
148
  return true;
133
149
  }
134
150
 
@@ -148,6 +164,11 @@ export class HasOneField extends RelationField {
148
164
  if (!field) {
149
165
  tcoll.model.removeAttribute(foreignKey);
150
166
  }
167
+
168
+ const association = collection.model.associations[this.name];
169
+ this.database.referenceMap.removeReference(this.reference(association));
170
+
171
+ this.clearAccessors();
151
172
  // 删掉 model 的关联字段
152
173
  delete collection.model.associations[this.name];
153
174
  // @ts-ignore
@@ -34,4 +34,20 @@ export abstract class RelationField extends Field {
34
34
  get TargetModel() {
35
35
  return this.context.database.sequelize.models[this.target];
36
36
  }
37
+
38
+ protected clearAccessors() {
39
+ const { collection } = this.context;
40
+ const association = collection.model.associations[this.name];
41
+ if (!association) {
42
+ return;
43
+ }
44
+
45
+ // @ts-ignore
46
+ const accessors = Object.values(association.accessors);
47
+
48
+ accessors.forEach((accessor) => {
49
+ // @ts-ignore
50
+ delete collection.model.prototype[accessor];
51
+ });
52
+ }
37
53
  }
@@ -44,7 +44,7 @@ sequencePatterns.register('integer', {
44
44
  const { lastRecord = null } = this.options;
45
45
 
46
46
  if (typeof options.current === 'undefined') {
47
- if (lastRecord) {
47
+ if (lastRecord && lastRecord.get(this.options.name)) {
48
48
  // if match current pattern
49
49
  const matcher = this.match(lastRecord.get(this.options.name));
50
50
  if (matcher) {
@@ -115,6 +115,8 @@ export interface SequenceFieldOptions extends BaseColumnFieldOptions {
115
115
  }
116
116
 
117
117
  export class SequenceField extends Field {
118
+ matcher: RegExp;
119
+
118
120
  get dataType() {
119
121
  return DataTypes.STRING;
120
122
  }
@@ -170,7 +172,7 @@ export class SequenceField extends Field {
170
172
  };
171
173
 
172
174
  match(value) {
173
- return value.match(this.matcher);
175
+ return typeof value === 'string' ? value.match(this.matcher) : null;
174
176
  }
175
177
 
176
178
  parse(value: string, patternIndex: number): string {
@@ -78,7 +78,6 @@ export default class FilterParser {
78
78
 
79
79
  const include = {};
80
80
  const where = {};
81
- const filter2 = lodash.cloneDeep(flattenedFilter);
82
81
 
83
82
  let skipPrefix = null;
84
83
  const associations = model.associations;
@@ -91,6 +90,11 @@ export default class FilterParser {
91
90
  continue;
92
91
  }
93
92
 
93
+ // skip empty logic operator value
94
+ if ((key == '$or' || key == '$and') && Array.isArray(value) && value.length == 0) {
95
+ continue;
96
+ }
97
+
94
98
  debug('handle filter key "%s: "%s"', key, value);
95
99
  let keys = key.split('.');
96
100
 
package/src/model-hook.ts CHANGED
@@ -5,8 +5,6 @@ import { Model } from './model';
5
5
 
6
6
  const { hooks } = require('sequelize/lib/hooks');
7
7
 
8
-
9
-
10
8
  export class ModelHook {
11
9
  database: Database;
12
10
 
package/src/model.ts CHANGED
@@ -23,6 +23,7 @@ export class Model<TModelAttributes extends {} = any, TCreationAttributes extend
23
23
  public static database: Database;
24
24
  public static collection: Collection;
25
25
 
26
+ [key: string]: any;
26
27
  protected _changedWithAssociations = new Set();
27
28
  protected _previousDataValuesWithAssociations = {};
28
29
 
@@ -70,6 +70,7 @@ export class OptionsParser {
70
70
  if (typeof sort === 'string') {
71
71
  sort = sort.split(',');
72
72
  }
73
+
73
74
  const orderParams = [];
74
75
  for (const sortKey of sort) {
75
76
  let direction = sortKey.startsWith('-') ? 'DESC' : 'ASC';
@@ -191,8 +192,9 @@ export class OptionsParser {
191
192
 
192
193
  /**
193
194
  * set include params
194
- * @param includeRoot
195
- * @param appends
195
+ * @param model
196
+ * @param queryParams
197
+ * @param append
196
198
  */
197
199
  const setInclude = (model: ModelCtor<any>, queryParams: any, append: string) => {
198
200
  const appendFields = append.split('.');
@@ -1,9 +1,9 @@
1
1
  import lodash from 'lodash';
2
2
  import { BelongsToMany, Op, Transaction } from 'sequelize';
3
3
  import { Model } from '../model';
4
- import { CreateOptions, DestroyOptions, FindOptions, TargetKey, UpdateOptions } from '../repository';
4
+ import { CreateOptions, DestroyOptions, FindOneOptions, FindOptions, TargetKey, UpdateOptions } from '../repository';
5
5
  import { updateThroughTableValue } from '../update-associations';
6
- import { FindAndCountOptions, FindOneOptions, MultipleRelationRepository } from './multiple-relation-repository';
6
+ import { FindAndCountOptions, MultipleRelationRepository } from './multiple-relation-repository';
7
7
  import { transaction } from './relation-repository';
8
8
  import { AssociatedOptions, PrimaryKeyWithThroughValues } from './types';
9
9
 
@@ -14,7 +14,7 @@ interface IBelongsToManyRepository<M extends Model> {
14
14
  findAndCount(options?: FindAndCountOptions): Promise<[M[], number]>;
15
15
  findOne(options?: FindOneOptions): Promise<M>;
16
16
  // 新增并关联,存在中间表数据
17
- create(options?: CreateBelongsToManyOptions): Promise<M>;
17
+ create(options?: CreateOptions): Promise<M>;
18
18
  // 更新,存在中间表数据
19
19
  update(options?: UpdateOptions): Promise<M>;
20
20
  // 删除
@@ -1,13 +1,16 @@
1
1
  import { omit } from 'lodash';
2
2
  import { HasMany, Op } from 'sequelize';
3
3
  import { Model } from '../model';
4
- import { CreateOptions, DestroyOptions, FindOptions, TargetKey, TK, UpdateOptions } from '../repository';
5
4
  import {
6
- AssociatedOptions,
7
- FindAndCountOptions,
5
+ CreateOptions,
6
+ DestroyOptions,
8
7
  FindOneOptions,
9
- MultipleRelationRepository
10
- } from './multiple-relation-repository';
8
+ FindOptions,
9
+ TargetKey,
10
+ TK,
11
+ UpdateOptions,
12
+ } from '../repository';
13
+ import { AssociatedOptions, FindAndCountOptions, MultipleRelationRepository } from './multiple-relation-repository';
11
14
  import { transaction } from './relation-repository';
12
15
 
13
16
  interface IHasManyRepository<M extends Model> {
@@ -2,12 +2,10 @@ import { Model } from '../model';
2
2
  import { CreateOptions } from '../repository';
3
3
  import { SingleRelationFindOption, SingleRelationRepository } from './single-relation-repository';
4
4
 
5
- interface HasOneFindOptions extends SingleRelationFindOption {}
6
-
7
5
  interface IHasOneRepository<M extends Model> {
8
6
  // 不需要 findOne,find 就是 findOne
9
- find(options?: HasOneFindOptions): Promise<M>;
10
- findOne(options?: HasOneFindOptions): Promise<M>;
7
+ find(options?: SingleRelationFindOption): Promise<M>;
8
+ findOne(options?: SingleRelationFindOption): Promise<M>;
11
9
  // 新增并关联,如果存在关联,解除之后,与新数据建立关联
12
10
  create(options?: CreateOptions): Promise<M>;
13
11
  // 更新
@@ -5,7 +5,7 @@ import {
5
5
  CountOptions,
6
6
  DestroyOptions,
7
7
  Filter,
8
- FilterByTk,
8
+ FindOneOptions,
9
9
  FindOptions,
10
10
  TargetKey,
11
11
  TK,
@@ -16,9 +16,7 @@ import { UpdateGuard } from '../update-guard';
16
16
  import { RelationRepository, transaction } from './relation-repository';
17
17
  import { handleAppendsQuery } from '../utils';
18
18
 
19
- export interface FindAndCountOptions extends CommonFindOptions {}
20
-
21
- export interface FindOneOptions extends CommonFindOptions, FilterByTk {}
19
+ export type FindAndCountOptions = CommonFindOptions;
22
20
 
23
21
  export interface AssociatedOptions extends Transactionable {
24
22
  tk?: TK;
@@ -88,6 +86,7 @@ export abstract class MultipleRelationRepository extends RelationRepository {
88
86
 
89
87
  async findAndCount(options?: FindAndCountOptions): Promise<[any[], number]> {
90
88
  const transaction = await this.getTransaction(options, false);
89
+
91
90
  return [
92
91
  await this.find({
93
92
  ...options,
@@ -2,12 +2,12 @@ import lodash from 'lodash';
2
2
  import { Association, BelongsTo, BelongsToMany, HasMany, HasOne, ModelCtor, Transaction } from 'sequelize';
3
3
  import { Collection } from '../collection';
4
4
  import Database from '../database';
5
+ import { transactionWrapperBuilder } from '../decorators/transaction-decorator';
5
6
  import { RelationField } from '../fields/relation-field';
6
7
  import FilterParser from '../filter-parser';
7
8
  import { Model } from '../model';
8
9
  import { OptionsParser } from '../options-parser';
9
10
  import { CreateOptions, Filter, FindOptions } from '../repository';
10
- import { transactionWrapperBuilder } from '../decorators/transaction-decorator';
11
11
  import { updateAssociations } from '../update-associations';
12
12
  import { UpdateGuard } from '../update-guard';
13
13
 
@@ -44,7 +44,7 @@ export abstract class SingleRelationRepository extends RelationRepository {
44
44
  });
45
45
  }
46
46
 
47
- async find(options?: SingleRelationFindOption): Promise<Model<any>> {
47
+ async find(options?: SingleRelationFindOption): Promise<Model<any> | null> {
48
48
  const transaction = await this.getTransaction(options);
49
49
 
50
50
  const findOptions = this.buildQueryOptions({
package/src/repository.ts CHANGED
@@ -2,6 +2,7 @@ import lodash, { omit } from 'lodash';
2
2
  import {
3
3
  Association,
4
4
  BulkCreateOptions,
5
+ CountOptions as SequelizeCountOptions,
5
6
  CreateOptions as SequelizeCreateOptions,
6
7
  DestroyOptions as SequelizeDestroyOptions,
7
8
  FindAndCountOptions as SequelizeAndCountOptions,
@@ -9,8 +10,9 @@ import {
9
10
  ModelCtor,
10
11
  Op,
11
12
  Transactionable,
12
- UpdateOptions as SequelizeUpdateOptions
13
+ UpdateOptions as SequelizeUpdateOptions,
13
14
  } from 'sequelize';
15
+ import { WhereOperators } from 'sequelize/types/lib/model';
14
16
  import { Collection } from './collection';
15
17
  import { Database } from './database';
16
18
  import mustHaveFilter from './decorators/must-have-filter-decorator';
@@ -18,6 +20,7 @@ import { transactionWrapperBuilder } from './decorators/transaction-decorator';
18
20
  import { RelationField } from './fields';
19
21
  import FilterParser from './filter-parser';
20
22
  import { Model } from './model';
23
+ import operators from './operators';
21
24
  import { OptionsParser } from './options-parser';
22
25
  import { BelongsToManyRepository } from './relation-repository/belongs-to-many-repository';
23
26
  import { BelongsToRepository } from './relation-repository/belongs-to-repository';
@@ -45,7 +48,32 @@ export interface FilterAble {
45
48
  export type TargetKey = string | number;
46
49
  export type TK = TargetKey | TargetKey[];
47
50
 
48
- export type Filter = any;
51
+ type FieldValue = string | number | bigint | boolean | Date | Buffer | null | FieldValue[] | FilterWithOperator;
52
+
53
+ type Operators = keyof typeof operators & keyof WhereOperators;
54
+
55
+ export type FilterWithOperator = {
56
+ [key: string]:
57
+ | {
58
+ [K in Operators]: FieldValue;
59
+ }
60
+ | FieldValue;
61
+ };
62
+
63
+ export type FilterWithValue = {
64
+ [key: string]: FieldValue;
65
+ };
66
+
67
+ type FilterAnd = {
68
+ $and: Filter[];
69
+ };
70
+
71
+ type FilterOr = {
72
+ $or: Filter[];
73
+ };
74
+
75
+ export type Filter = FilterWithOperator | FilterWithValue | FilterAnd | FilterOr;
76
+
49
77
  export type Appends = string[];
50
78
  export type Except = string[];
51
79
  export type Fields = string[];
@@ -53,12 +81,12 @@ export type Sort = string[] | string;
53
81
 
54
82
  export type WhiteList = string[];
55
83
  export type BlackList = string[];
84
+
56
85
  export type AssociationKeysToBeUpdate = string[];
57
86
 
58
87
  export type Values = any;
59
88
 
60
- export interface CountOptions extends Omit<SequelizeCreateOptions, 'distinct' | 'where' | 'include'>, Transactionable {
61
- fields?: Fields;
89
+ export interface CountOptions extends Omit<SequelizeCountOptions, 'distinct' | 'where' | 'include'>, Transactionable {
62
90
  filter?: Filter;
63
91
  context?: any;
64
92
  }
@@ -67,7 +95,7 @@ export interface FilterByTk {
67
95
  filterByTk?: TargetKey;
68
96
  }
69
97
 
70
- export interface FindOptions extends SequelizeFindOptions, CommonFindOptions, FilterByTk {}
98
+ export type FindOptions = SequelizeFindOptions & CommonFindOptions & FilterByTk;
71
99
 
72
100
  export interface CommonFindOptions extends Transactionable {
73
101
  filter?: Filter;
@@ -78,7 +106,7 @@ export interface CommonFindOptions extends Transactionable {
78
106
  context?: any;
79
107
  }
80
108
 
81
- interface FindOneOptions extends FindOptions {}
109
+ export type FindOneOptions = Omit<FindOptions, 'limit'>;
82
110
 
83
111
  export interface DestroyOptions extends SequelizeDestroyOptions {
84
112
  filter?: Filter;
@@ -87,18 +115,7 @@ export interface DestroyOptions extends SequelizeDestroyOptions {
87
115
  context?: any;
88
116
  }
89
117
 
90
- interface FindAndCountOptions extends Omit<SequelizeAndCountOptions, 'where' | 'include' | 'order'> {
91
- // 数据过滤
92
- filter?: Filter;
93
- // 输出结果显示哪些字段
94
- fields?: Fields;
95
- // 输出结果不显示哪些字段
96
- except?: Except;
97
- // 附加字段,用于控制关系字段的输出
98
- appends?: Appends;
99
- // 排序,字段前面加上 “-” 表示降序
100
- sort?: Sort;
101
- }
118
+ type FindAndCountOptions = Omit<SequelizeAndCountOptions, 'where' | 'include' | 'order'> & CommonFindOptions;
102
119
 
103
120
  export interface CreateOptions extends SequelizeCreateOptions {
104
121
  values?: Values | Values[];
@@ -275,7 +292,10 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
275
292
  transaction,
276
293
  };
277
294
 
278
- return [await this.find(options), await this.count(options)];
295
+ const count = await this.count(options);
296
+ const results = count ? await this.find(options) : [];
297
+
298
+ return [results, count];
279
299
  }
280
300
 
281
301
  /**
@@ -358,6 +378,7 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
358
378
  const transaction = await this.getTransaction(options);
359
379
  const { records } = options;
360
380
  const instances = [];
381
+
361
382
  for (const values of records) {
362
383
  const instance = await this.create({ values, transaction });
363
384
  instances.push(instance);
package/src/types.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type { Model } from './model';
2
+ import type { ValidationOptions } from 'sequelize/types/lib/instance-validator';
3
+ import type { HookReturn } from 'sequelize/types/lib/hooks';
4
+ import type { CreateOptions, DestroyOptions, SaveOptions, SyncOptions, UpdateOptions } from 'sequelize/types';
5
+ import { Collection, CollectionOptions } from './collection';
6
+
7
+ export type CollectionNameType = string;
8
+
9
+ export type ModelSyncEventType = 'beforeSync' | 'afterSync';
10
+ export type ModelValidateEventType = 'beforeValidate' | 'afterValidate';
11
+ export type ModelCreateEventType = 'beforeCreate' | 'afterCreate';
12
+ export type ModelUpdateEventType = 'beforeUpdate' | 'afterUpdate';
13
+ export type ModelSaveEventType = 'beforeSave' | 'afterSave';
14
+ export type ModelDestroyEventType = 'beforeDestroy' | 'afterDestroy';
15
+ export type ModelCreateWithAssociationsEventType = 'afterCreateWithAssociations';
16
+ export type ModelUpdateWithAssociationsEventType = 'afterUpdateWithAssociations';
17
+ export type ModelSaveWithAssociationsEventType = 'afterSaveWithAssociations';
18
+
19
+ export type ModelValidateEventTypes = ModelValidateEventType | `${CollectionNameType}.${ModelValidateEventType}`;
20
+ export type ModelCreateEventTypes = ModelCreateEventType | `${CollectionNameType}.${ModelCreateEventType}`;
21
+ export type ModelUpdateEventTypes = ModelUpdateEventType | `${CollectionNameType}.${ModelUpdateEventType}`;
22
+ export type ModelSaveEventTypes = ModelSaveEventType | `${CollectionNameType}.${ModelSaveEventType}`;
23
+ export type ModelDestroyEventTypes = ModelDestroyEventType | `${CollectionNameType}.${ModelDestroyEventType}`;
24
+ export type ModelCreateWithAssociationsEventTypes = ModelCreateWithAssociationsEventType | `${CollectionNameType}.${ModelCreateWithAssociationsEventType}`;
25
+ export type ModelUpdateWithAssociationsEventTypes = ModelUpdateWithAssociationsEventType | `${CollectionNameType}.${ModelUpdateWithAssociationsEventType}`;
26
+ export type ModelSaveWithAssociationsEventTypes = ModelSaveWithAssociationsEventType | `${CollectionNameType}.${ModelSaveWithAssociationsEventType}`;
27
+
28
+ export type ModelEventTypes = ModelSyncEventType
29
+ | ModelValidateEventTypes
30
+ | ModelCreateEventTypes
31
+ | ModelUpdateEventTypes
32
+ | ModelSaveEventTypes
33
+ | ModelDestroyEventTypes
34
+ | ModelCreateWithAssociationsEventTypes
35
+ | ModelUpdateWithAssociationsEventTypes
36
+ | ModelSaveWithAssociationsEventTypes;
37
+
38
+ export type DatabaseBeforeDefineCollectionEventType = 'beforeDefineCollection';
39
+ export type DatabaseAfterDefineCollectionEventType = 'afterDefineCollection';
40
+ export type DatabaseBeforeRemoveCollectionEventType = 'beforeRemoveCollection';
41
+ export type DatabaseAfterRemoveCollectionEventType = 'afterRemoveCollection';
42
+
43
+ export type DatabaseEventTypes = DatabaseBeforeDefineCollectionEventType
44
+ | DatabaseAfterDefineCollectionEventType
45
+ | DatabaseBeforeRemoveCollectionEventType
46
+ | DatabaseAfterRemoveCollectionEventType;
47
+
48
+ export type EventType = ModelEventTypes | DatabaseEventTypes | string;
49
+
50
+ export type { HookReturn };
51
+
52
+ export type SyncListener = (options?: SyncOptions) => HookReturn;
53
+ export type ValidateListener = (model: Model, options?: ValidationOptions) => HookReturn;
54
+ export type CreateListener = (model: Model, options?: CreateOptions) => HookReturn;
55
+ export type UpdateListener = (model: Model, options?: UpdateOptions) => HookReturn;
56
+ export type SaveListener = (model: Model, options?: SaveOptions) => HookReturn;
57
+ export type DestroyListener = (model: Model, options?: DestroyOptions) => HookReturn;
58
+ export type CreateWithAssociationsListener = (model: Model, options?: CreateOptions) => HookReturn;
59
+ export type UpdateWithAssociationsListener = (model: Model, options?: UpdateOptions) => HookReturn;
60
+ export type SaveWithAssociationsListener = (model: Model, options?: SaveOptions) => HookReturn;
61
+
62
+ export type BeforeDefineCollectionListener = (options: CollectionOptions) => void;
63
+ export type AfterDefineCollectionListener = (collection: Collection) => void;
64
+ export type RemoveCollectionListener = (collection: Collection) => void;
@@ -6,7 +6,7 @@ import {
6
6
  HasOne,
7
7
  Hookable,
8
8
  ModelCtor,
9
- Transactionable
9
+ Transactionable,
10
10
  } from 'sequelize';
11
11
  import { Model } from './model';
12
12
  import { UpdateGuard } from './update-guard';
@@ -375,6 +375,7 @@ export async function updateMultipleAssociation(
375
375
  const setAccessor = association.accessors.set;
376
376
 
377
377
  const createAccessor = association.accessors.create;
378
+
378
379
  if (isUndefinedOrNull(value)) {
379
380
  await model[setAccessor](null, { transaction, context });
380
381
  model.setDataValue(key, null);