@strapi/database 4.0.0-next.6 → 4.0.0

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 (44) hide show
  1. package/lib/dialects/dialect.js +45 -0
  2. package/lib/dialects/index.js +6 -112
  3. package/lib/dialects/mysql/index.js +51 -0
  4. package/lib/dialects/mysql/schema-inspector.js +199 -0
  5. package/lib/dialects/postgresql/index.js +49 -0
  6. package/lib/dialects/postgresql/schema-inspector.js +232 -0
  7. package/lib/dialects/sqlite/index.js +74 -0
  8. package/lib/dialects/sqlite/schema-inspector.js +151 -0
  9. package/lib/entity-manager.js +18 -14
  10. package/lib/entity-repository.js +2 -3
  11. package/lib/errors.js +45 -3
  12. package/lib/fields.d.ts +2 -3
  13. package/lib/fields.js +7 -16
  14. package/lib/index.d.ts +67 -22
  15. package/lib/index.js +44 -27
  16. package/lib/lifecycles/index.d.ts +50 -0
  17. package/lib/{lifecycles.js → lifecycles/index.js} +25 -14
  18. package/lib/lifecycles/subscribers/index.d.ts +9 -0
  19. package/lib/lifecycles/subscribers/models-lifecycles.js +19 -0
  20. package/lib/lifecycles/subscribers/timestamps.js +65 -0
  21. package/lib/metadata/index.js +84 -95
  22. package/lib/metadata/relations.js +16 -0
  23. package/lib/migrations/index.d.ts +9 -0
  24. package/lib/migrations/index.js +69 -0
  25. package/lib/migrations/storage.js +51 -0
  26. package/lib/query/helpers/join.js +3 -5
  27. package/lib/query/helpers/order-by.js +21 -11
  28. package/lib/query/helpers/populate.js +35 -10
  29. package/lib/query/helpers/search.js +26 -12
  30. package/lib/query/helpers/transform.js +42 -14
  31. package/lib/query/helpers/where.js +92 -57
  32. package/lib/query/query-builder.js +116 -34
  33. package/lib/schema/__tests__/schema-diff.test.js +14 -1
  34. package/lib/schema/builder.js +315 -284
  35. package/lib/schema/diff.js +376 -0
  36. package/lib/schema/index.d.ts +49 -0
  37. package/lib/schema/index.js +47 -50
  38. package/lib/schema/schema.js +21 -18
  39. package/lib/schema/storage.js +79 -0
  40. package/lib/utils/content-types.js +1 -2
  41. package/package.json +26 -21
  42. package/lib/configuration.js +0 -49
  43. package/lib/schema/schema-diff.js +0 -337
  44. package/lib/schema/schema-storage.js +0 -44
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fse = require('fs-extra');
5
+
6
+ const errors = require('../../errors');
7
+ const { Dialect } = require('../dialect');
8
+ const SqliteSchmeaInspector = require('./schema-inspector');
9
+
10
+ class SqliteDialect extends Dialect {
11
+ constructor(db) {
12
+ super(db);
13
+
14
+ this.schemaInspector = new SqliteSchmeaInspector(db);
15
+ }
16
+
17
+ configure() {
18
+ this.db.config.connection.connection.filename = path.resolve(
19
+ this.db.config.connection.connection.filename
20
+ );
21
+
22
+ const dbDir = path.dirname(this.db.config.connection.connection.filename);
23
+
24
+ fse.ensureDirSync(dbDir);
25
+ }
26
+
27
+ async initialize() {
28
+ await this.db.connection.raw('pragma foreign_keys = on');
29
+ }
30
+
31
+ canAlterConstraints() {
32
+ return false;
33
+ }
34
+
35
+ getSqlType(type) {
36
+ switch (type) {
37
+ // FIXME: enum must be dealt separately
38
+ case 'enum': {
39
+ return 'text';
40
+ }
41
+ case 'double':
42
+ case 'decimal': {
43
+ return 'float';
44
+ }
45
+ case 'timestamp': {
46
+ return 'datetime';
47
+ }
48
+ default: {
49
+ return type;
50
+ }
51
+ }
52
+ }
53
+
54
+ async startSchemaUpdate() {
55
+ await this.db.connection.raw(`pragma foreign_keys = off`);
56
+ }
57
+
58
+ async endSchemaUpdate() {
59
+ await this.db.connection.raw(`pragma foreign_keys = on`);
60
+ }
61
+
62
+ transformErrors(error) {
63
+ switch (error.errno) {
64
+ case 19: {
65
+ throw new errors.NotNullConstraint(); // TODO: extract column name
66
+ }
67
+ default: {
68
+ super.transformErrors(error);
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ module.exports = SqliteDialect;
@@ -0,0 +1,151 @@
1
+ 'use strict';
2
+
3
+ const SQL_QUERIES = {
4
+ TABLE_LIST: `select name from sqlite_master where type = 'table' and name NOT LIKE 'sqlite%'`,
5
+ TABLE_INFO: `pragma table_info(??)`,
6
+ INDEX_LIST: 'pragma index_list(??)',
7
+ INDEX_INFO: 'pragma index_info(??)',
8
+ FOREIGN_KEY_LIST: 'pragma foreign_key_list(??)',
9
+ };
10
+
11
+ const toStrapiType = column => {
12
+ const { type } = column;
13
+
14
+ const rootType = type.toLowerCase().match(/[^(), ]+/)[0];
15
+
16
+ switch (rootType) {
17
+ case 'integer': {
18
+ if (column.pk) {
19
+ return { type: 'increments', args: [{ primary: true }] };
20
+ }
21
+
22
+ return { type: 'integer' };
23
+ }
24
+ case 'float': {
25
+ return { type: 'float', args: [10, 2] };
26
+ }
27
+ case 'bigint': {
28
+ return { type: 'bigInteger' };
29
+ }
30
+ case 'varchar': {
31
+ const length = type.slice(8, type.length - 1);
32
+
33
+ return { type: 'string', args: [Number(length)] };
34
+ }
35
+ case 'text': {
36
+ return { type: 'text', args: ['longtext'] };
37
+ }
38
+ case 'json': {
39
+ return { type: 'jsonb' };
40
+ }
41
+ case 'boolean': {
42
+ return { type: 'boolean' };
43
+ }
44
+ case 'datetime': {
45
+ return { type: 'datetime', args: [{ useTz: false, precision: 6 }] };
46
+ }
47
+ case 'date': {
48
+ return { type: 'date' };
49
+ }
50
+ case 'time': {
51
+ return { type: 'time', args: [{ precision: 3 }] };
52
+ }
53
+ default: {
54
+ return { type: 'specificType', args: [column.data_type] };
55
+ }
56
+ }
57
+ };
58
+
59
+ class SqliteSchemaInspector {
60
+ constructor(db) {
61
+ this.db = db;
62
+ }
63
+
64
+ async getSchema() {
65
+ const schema = { tables: [] };
66
+ const tables = await this.getTables();
67
+
68
+ for (const tableName of tables) {
69
+ const columns = await this.getColumns(tableName);
70
+ const indexes = await this.getIndexes(tableName);
71
+ const foreignKeys = await this.getForeignKeys(tableName);
72
+
73
+ schema.tables.push({
74
+ name: tableName,
75
+ columns,
76
+ indexes,
77
+ foreignKeys,
78
+ });
79
+ }
80
+
81
+ return schema;
82
+ }
83
+
84
+ async getTables() {
85
+ const rows = await this.db.connection.raw(SQL_QUERIES.TABLE_LIST);
86
+
87
+ return rows.map(row => row.name);
88
+ }
89
+
90
+ async getColumns(tableName) {
91
+ const rows = await this.db.connection.raw(SQL_QUERIES.TABLE_INFO, [tableName]);
92
+
93
+ return rows.map(row => {
94
+ const { type, args = [], ...rest } = toStrapiType(row);
95
+
96
+ return {
97
+ type,
98
+ args,
99
+ name: row.name,
100
+ defaultTo: row.dflt_value,
101
+ notNullable: row.notnull !== null ? Boolean(row.notnull) : null,
102
+ unsigned: false,
103
+ ...rest,
104
+ };
105
+ });
106
+ }
107
+
108
+ async getIndexes(tableName) {
109
+ const indexes = await this.db.connection.raw(SQL_QUERIES.INDEX_LIST, [tableName]);
110
+
111
+ const ret = [];
112
+
113
+ for (const index of indexes.filter(index => !index.name.startsWith('sqlite_'))) {
114
+ const res = await this.db.connection.raw(SQL_QUERIES.INDEX_INFO, [index.name]);
115
+
116
+ ret.push({
117
+ columns: res.map(row => row.name),
118
+ name: index.name,
119
+ type: index.unique ? 'unique' : null,
120
+ });
121
+ }
122
+
123
+ return ret;
124
+ }
125
+
126
+ async getForeignKeys(tableName) {
127
+ const fks = await this.db.connection.raw(SQL_QUERIES.FOREIGN_KEY_LIST, [tableName]);
128
+
129
+ const ret = {};
130
+
131
+ for (const fk of fks) {
132
+ if (!ret[fk.id]) {
133
+ ret[fk.id] = {
134
+ // TODO: name, // find name
135
+ columns: [fk.from],
136
+ referencedColumns: [fk.to],
137
+ referencedTable: fk.table,
138
+ onUpdate: fk.on_update.toUpperCase(),
139
+ onDelete: fk.on_delete.toUpperCase(),
140
+ };
141
+ } else {
142
+ ret[fk.id].columns.push(fk.from);
143
+ ret[fk.id].referencedColumns.push(fk.to);
144
+ }
145
+ }
146
+
147
+ return Object.values(ret);
148
+ }
149
+ }
150
+
151
+ module.exports = SqliteSchemaInspector;
@@ -29,8 +29,7 @@ const toAssocs = data => {
29
29
  });
30
30
  };
31
31
 
32
- // TODO: handle programmatic defaults
33
- const toRow = (metadata, data = {}, { withDefaults = false } = {}) => {
32
+ const processData = (metadata, data = {}, { withDefaults = false } = {}) => {
34
33
  const { attributes } = metadata;
35
34
 
36
35
  const obj = {};
@@ -38,7 +37,6 @@ const toRow = (metadata, data = {}, { withDefaults = false } = {}) => {
38
37
  for (const attributeName in attributes) {
39
38
  const attribute = attributes[attributeName];
40
39
 
41
- // TODO: convert to column name
42
40
  if (types.isScalar(attribute.type)) {
43
41
  const field = createField(attribute);
44
42
 
@@ -65,7 +63,6 @@ const toRow = (metadata, data = {}, { withDefaults = false } = {}) => {
65
63
  if (types.isRelation(attribute.type)) {
66
64
  // oneToOne & manyToOne
67
65
  if (attribute.joinColumn && attribute.owner) {
68
- // TODO: ensure joinColumn name respect convention ?
69
66
  const joinColumnName = attribute.joinColumn.name;
70
67
 
71
68
  // allow setting to null
@@ -145,7 +142,7 @@ const createEntityManager = db => {
145
142
  await db.lifecycles.run('beforeCount', uid, { params });
146
143
 
147
144
  const res = await this.createQueryBuilder(uid)
148
- .init(_.pick(['_q', 'where'], params))
145
+ .init(_.pick(['_q', 'where', 'filters'], params))
149
146
  .count()
150
147
  .first()
151
148
  .execute();
@@ -167,7 +164,7 @@ const createEntityManager = db => {
167
164
  throw new Error('Create expects a data object');
168
165
  }
169
166
 
170
- const dataToInsert = toRow(metadata, data, { withDefaults: true });
167
+ const dataToInsert = processData(metadata, data, { withDefaults: true });
171
168
 
172
169
  const [id] = await this.createQueryBuilder(uid)
173
170
  .insert(dataToInsert)
@@ -175,7 +172,7 @@ const createEntityManager = db => {
175
172
 
176
173
  await this.attachRelations(uid, id, data);
177
174
 
178
- // TODO: in case there is not select or populate specified return the inserted data ?
175
+ // TODO: in case there is no select or populate specified return the inserted data ?
179
176
  // TODO: do not trigger the findOne lifecycles ?
180
177
  const result = await this.findOne(uid, {
181
178
  where: { id },
@@ -199,7 +196,7 @@ const createEntityManager = db => {
199
196
  throw new Error('CreateMany expects data to be an array');
200
197
  }
201
198
 
202
- const dataToInsert = data.map(datum => toRow(metadata, datum, { withDefaults: true }));
199
+ const dataToInsert = data.map(datum => processData(metadata, datum, { withDefaults: true }));
203
200
 
204
201
  if (_.isEmpty(dataToInsert)) {
205
202
  throw new Error('Nothing to insert');
@@ -242,7 +239,7 @@ const createEntityManager = db => {
242
239
 
243
240
  const { id } = entity;
244
241
 
245
- const dataToUpdate = toRow(metadata, data);
242
+ const dataToUpdate = processData(metadata, data);
246
243
 
247
244
  if (!_.isEmpty(dataToUpdate)) {
248
245
  await this.createQueryBuilder(uid)
@@ -272,7 +269,7 @@ const createEntityManager = db => {
272
269
  const metadata = db.metadata.get(uid);
273
270
  const { where, data } = params;
274
271
 
275
- const dataToUpdate = toRow(metadata, data);
272
+ const dataToUpdate = processData(metadata, data);
276
273
 
277
274
  if (_.isEmpty(dataToUpdate)) {
278
275
  throw new Error('Update requires data');
@@ -299,7 +296,7 @@ const createEntityManager = db => {
299
296
  throw new Error('Delete requires a where parameter');
300
297
  }
301
298
 
302
- // TODO: avoid trigger the findOne lifecycles in the case ?
299
+ // TODO: do not trigger the findOne lifecycles ?
303
300
  const entity = await this.findOne(uid, {
304
301
  select: select && ['id'].concat(select),
305
302
  where,
@@ -472,7 +469,6 @@ const createEntityManager = db => {
472
469
  const { joinTable } = attribute;
473
470
  const { joinColumn, inverseJoinColumn } = joinTable;
474
471
 
475
- // TODO: validate logic of delete
476
472
  if (isOneToAny(attribute) && isBidirectional(attribute)) {
477
473
  await this.createQueryBuilder(joinTable.name)
478
474
  .delete()
@@ -654,7 +650,10 @@ const createEntityManager = db => {
654
650
  .where(joinTable.on || {})
655
651
  .execute();
656
652
 
657
- if (['oneToOne', 'oneToMany'].includes(attribute.relation)) {
653
+ if (
654
+ isBidirectional(attribute) &&
655
+ ['oneToOne', 'oneToMany'].includes(attribute.relation)
656
+ ) {
658
657
  await this.createQueryBuilder(joinTable.name)
659
658
  .delete()
660
659
  .where({ [inverseJoinColumn.name]: toIds(data[attributeName]) })
@@ -772,6 +771,7 @@ const createEntityManager = db => {
772
771
  continue;
773
772
  }
774
773
 
774
+ // do not need to delete links when using foreign keys
775
775
  if (db.dialect.usesForeignKeys()) {
776
776
  return;
777
777
  }
@@ -812,7 +812,7 @@ const createEntityManager = db => {
812
812
  const entry = await this.findOne(uid, {
813
813
  select: ['id'],
814
814
  where: { id: entity.id },
815
- populate: populate,
815
+ populate,
816
816
  });
817
817
 
818
818
  return Object.assign({}, entity, entry);
@@ -837,6 +837,10 @@ const createEntityManager = db => {
837
837
  },
838
838
  });
839
839
 
840
+ if (!entry) {
841
+ return null;
842
+ }
843
+
840
844
  return entry[field];
841
845
  },
842
846
 
@@ -95,9 +95,8 @@ const createRepository = (uid, db) => {
95
95
  return db.entityManager.deleteRelations(uid, id);
96
96
  },
97
97
 
98
- // TODO: add relation API
99
- populate(entity, field, params) {
100
- return db.entityManager.populate(uid, entity, field, params);
98
+ populate(entity, populate) {
99
+ return db.entityManager.populate(uid, entity, populate);
101
100
  },
102
101
 
103
102
  load(entity, field, params) {
package/lib/errors.js CHANGED
@@ -1,14 +1,56 @@
1
1
  'use strict';
2
2
 
3
- class NotNullConstraint extends Error {
3
+ /* DatabaseError */
4
+ class DatabaseError extends Error {
5
+ constructor(message, details = {}) {
6
+ super();
7
+ this.name = 'DatabaseError';
8
+ this.message = message || 'A database error occured';
9
+ this.details = details;
10
+ }
11
+ }
12
+
13
+ class NotNullConstraint extends DatabaseError {
4
14
  constructor({ column = '' } = {}) {
5
15
  super();
6
16
  this.name = 'NotNullConstraint';
7
- this.message = `Not null constraint violation${column ? `on on column ${column}` : ''}.`;
8
- this.stack = null;
17
+ this.message = `Not null constraint violation${column ? ` on column ${column}` : ''}.`;
18
+ this.details = { column };
19
+ this.stack = '';
20
+ }
21
+ }
22
+
23
+ class InvalidTimeError extends DatabaseError {
24
+ constructor(message) {
25
+ super();
26
+ this.name = 'InvalidTimeFormat';
27
+ this.message = message || 'Invalid time format, expected HH:mm:ss.SSS';
28
+ this.details = {};
29
+ }
30
+ }
31
+
32
+ class InvalidDateError extends DatabaseError {
33
+ constructor(message) {
34
+ super();
35
+ this.name = 'InvalidTimeFormat';
36
+ this.message = message || 'Invalid date format, expected YYYY-MM-DD';
37
+ this.details = {};
38
+ }
39
+ }
40
+
41
+ class InvalidDateTimeError extends DatabaseError {
42
+ constructor(message) {
43
+ super();
44
+ this.name = 'InvalidTimeFormat';
45
+ this.message = message || 'Invalid datetime format, expected a timestamp or an ISO date';
46
+ this.details = {};
9
47
  }
10
48
  }
11
49
 
12
50
  module.exports = {
51
+ DatabaseError,
13
52
  NotNullConstraint,
53
+ InvalidTimeError,
54
+ InvalidDateError,
55
+ InvalidDateTimeError,
14
56
  };
package/lib/fields.d.ts CHANGED
@@ -1,10 +1,9 @@
1
+ import { Attribute } from './schema';
2
+
1
3
  interface Field {
2
4
  config: {};
3
5
  toDB(value: any): any;
4
6
  fromDB(value: any): any;
5
7
  }
6
8
 
7
- interface Attribute {
8
- type: string
9
- }
10
9
  export function createField(attribute: Attribute): Field;
package/lib/fields.js CHANGED
@@ -2,22 +2,13 @@
2
2
 
3
3
  const _ = require('lodash/fp');
4
4
  const dateFns = require('date-fns');
5
+ const { InvalidTimeError, InvalidDateError, InvalidDateTimeError } = require('./errors');
5
6
 
6
7
  class Field {
7
8
  constructor(config) {
8
9
  this.config = config;
9
10
  }
10
11
 
11
- // TODO: impl
12
- validate() {
13
- // // use config validators directly
14
- // if (this.config.validators) {
15
- // this.config.validators.forEach(validator => {
16
- // validator(value)
17
- // })
18
- // }
19
- }
20
-
21
12
  toDB(value) {
22
13
  return value;
23
14
  }
@@ -112,12 +103,12 @@ const parseTime = value => {
112
103
  if (dateFns.isDate(value)) return dateFns.format(value, 'HH:mm:ss.SSS');
113
104
 
114
105
  if (typeof value !== 'string') {
115
- throw new Error(`Expected a string, got a ${typeof value}`);
106
+ throw new InvalidTimeError(`Expected a string, got a ${typeof value}`);
116
107
  }
117
108
  const result = value.match(timeRegex);
118
109
 
119
110
  if (result === null) {
120
- throw new Error('Invalid time format, expected HH:mm:ss.SSS');
111
+ throw new InvalidTimeError('Invalid time format, expected HH:mm:ss.SSS');
121
112
  }
122
113
 
123
114
  const [, hours, minutes, seconds, fraction = '.000'] = result;
@@ -133,9 +124,9 @@ const parseDate = value => {
133
124
 
134
125
  if (dateFns.isValid(date)) return dateFns.format(date, 'yyyy-MM-dd');
135
126
 
136
- throw new Error(`Invalid format, expected an ISO compatible date`);
127
+ throw new InvalidDateError(`Invalid format, expected an ISO compatible date`);
137
128
  } catch (error) {
138
- throw new Error(`Invalid format, expected an ISO compatible date`);
129
+ throw new InvalidDateError(`Invalid format, expected an ISO compatible date`);
139
130
  }
140
131
  };
141
132
 
@@ -148,9 +139,9 @@ const parseDateTimeOrTimestamp = value => {
148
139
  const milliUnixDate = dateFns.parse(value, 'T', new Date());
149
140
  if (dateFns.isValid(milliUnixDate)) return milliUnixDate;
150
141
 
151
- throw new Error(`Invalid format, expected a timestamp or an ISO date`);
142
+ throw new InvalidDateTimeError(`Invalid format, expected a timestamp or an ISO date`);
152
143
  } catch (error) {
153
- throw new Error(`Invalid format, expected a timestamp or an ISO date`);
144
+ throw new InvalidDateTimeError(`Invalid format, expected a timestamp or an ISO date`);
154
145
  }
155
146
  };
156
147
 
package/lib/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import { LifecycleProvider } from './lifecycles';
2
+ import { MigrationProvider } from './migrations';
3
+ import { SchemaProvideer } from './schema';
4
+
1
5
  type BooleanWhere<T> = {
2
6
  $and?: WhereParams<T>[];
3
7
  $or?: WhereParams<T>[];
@@ -50,26 +54,71 @@ interface Pagination {
50
54
  total: number;
51
55
  }
52
56
 
57
+ interface PopulateParams {}
58
+ interface EntityManager {
59
+ findOne<K extends keyof AllTypes>(uid: K, params: FindParams<AllTypes[K]>): Promise<any>;
60
+ findMany<K extends keyof AllTypes>(uid: K, params: FindParams<AllTypes[K]>): Promise<any[]>;
61
+
62
+ create<K extends keyof AllTypes>(uid: K, params: CreateParams<AllTypes[K]>): Promise<any>;
63
+ createMany<K extends keyof AllTypes>(
64
+ uid: K,
65
+ params: CreateManyParams<AllTypes[K]>
66
+ ): Promise<{ count: number }>;
67
+
68
+ update<K extends keyof AllTypes>(uid: K, params: any): Promise<any>;
69
+ updateMany<K extends keyof AllTypes>(uid: K, params: any): Promise<{ count: number }>;
70
+
71
+ delete<K extends keyof AllTypes>(uid: K, params: any): Promise<any>;
72
+ deleteMany<K extends keyof AllTypes>(uid: K, params: any): Promise<{ count: number }>;
73
+
74
+ count<K extends keyof AllTypes>(uid: K, params: any): Promise<number>;
75
+
76
+ attachRelations<K extends keyof AllTypes>(uid: K, id: ID, data: any): Promise<any>;
77
+ updateRelations<K extends keyof AllTypes>(uid: K, id: ID, data: any): Promise<any>;
78
+ deleteRelations<K extends keyof AllTypes>(uid: K, id: ID): Promise<any>;
79
+
80
+ populate<K extends keyof AllTypes, T extends AllTypes[K]>(
81
+ uid: K,
82
+ entity: T,
83
+ populate: PopulateParams
84
+ ): Promise<T>;
85
+
86
+ load<K extends keyof AllTypes, T extends AllTypes[K], SK extends keyof T>(
87
+ uid: K,
88
+ entity: T,
89
+ field: SK,
90
+ populate: PopulateParams
91
+ ): Promise<T[SK]>;
92
+ }
93
+
53
94
  interface QueryFromContentType<T extends keyof AllTypes> {
54
- findOne(params: FindParams<AllTypes[T]>): any;
55
- findMany(params: FindParams<AllTypes[T]>): any[];
56
- findWithCount(params: FindParams<AllTypes[T]>): [any[], number];
57
- findPage(params: FindParams<AllTypes[T]>): { results: any[]; pagination: Pagination };
95
+ findOne(params: FindParams<AllTypes[T]>): Promise<any>;
96
+ findMany(params: FindParams<AllTypes[T]>): Promise<any[]>;
97
+ findWithCount(params: FindParams<AllTypes[T]>): Promise<[any[], number]>;
98
+ findPage(params: FindParams<AllTypes[T]>): Promise<{ results: any[]; pagination: Pagination }>;
99
+
100
+ create(params: CreateParams<AllTypes[T]>): Promise<any>;
101
+ createMany(params: CreateManyParams<AllTypes[T]>): Promise<{ count: number }>;
58
102
 
59
- create(params: CreateParams<AllTypes[T]>): any;
60
- createMany(params: CreateManyParams<AllTypes[T]>): { count: number };
103
+ update(params: any): Promise<any>;
104
+ updateMany(params: any): Promise<{ count: number }>;
61
105
 
62
- update(params: any): any;
63
- updateMany(params: any): { count: number };
106
+ delete(params: any): Promise<any>;
107
+ deleteMany(params: any): Promise<{ count: number }>;
64
108
 
65
- delete(params: any): any;
66
- deleteMany(params: any): { count: number };
109
+ count(params: any): Promise<number>;
67
110
 
68
- count(params: any): number;
111
+ attachRelations(id: ID, data: any): Promise<any>;
112
+ updateRelations(id: ID, data: any): Promise<any>;
113
+ deleteRelations(id: ID): Promise<any>;
69
114
 
70
- attachRelations(id: ID, data: any): any;
71
- updateRelations(id: ID, data: any): any;
72
- deleteRelations(id: ID): any;
115
+ populate<S extends AllTypes[T]>(entity: S, populate: PopulateParams): Promise<S>;
116
+
117
+ load<S extends AllTypes[T], K extends keyof S>(
118
+ entity: S,
119
+ field: K,
120
+ populate: PopulateParams
121
+ ): Promise<S[K]>;
73
122
  }
74
123
 
75
124
  interface ModelConfig {
@@ -83,15 +132,11 @@ interface DatabaseConfig {
83
132
  connection: ConnectionConfig;
84
133
  models: ModelConfig[];
85
134
  }
86
-
87
- interface DatabaseSchema {
88
- sync(): Promise<void>;
89
- reset(): Promise<void>;
90
- create(): Promise<void>;
91
- drop(): Promise<void>;
92
- }
93
135
  export interface Database {
94
- schema: DatabaseSchema;
136
+ schema: SchemaProvideer;
137
+ lifecycles: LifecycleProvider;
138
+ migrations: MigrationProvider;
139
+ entityManager: EntityManager;
95
140
 
96
141
  query<T extends keyof AllTypes>(uid: T): QueryFromContentType<T>;
97
142
  }