remult 0.16.3-exp.1 → 0.16.3-exp.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.
Files changed (54) hide show
  1. package/README.md +3 -5
  2. package/esm/index.d.ts +1 -2
  3. package/esm/index.js +1 -2
  4. package/esm/postgres/postgres-data-provider.d.ts +3 -1
  5. package/esm/postgres/postgres-data-provider.js +11 -1
  6. package/esm/postgres/schema-builder.js +20 -20
  7. package/esm/remult-knex/index.d.ts +4 -28
  8. package/esm/remult-knex/index.js +46 -33
  9. package/esm/remult-mongo.d.ts +8 -2
  10. package/esm/remult-mongo.js +22 -8
  11. package/esm/server/expressBridge.d.ts +1 -0
  12. package/esm/src/backend-tests/my-test.backend-spec.js +66 -2
  13. package/esm/src/context.d.ts +2 -1
  14. package/esm/src/context.js +2 -4
  15. package/esm/src/data-providers/sql-database.d.ts +2 -0
  16. package/esm/src/data-providers/sql-database.js +26 -15
  17. package/esm/src/data-providers/web-sql-data-provider.d.ts +3 -0
  18. package/esm/src/data-providers/web-sql-data-provider.js +16 -8
  19. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +13 -14
  20. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +52 -19
  21. package/esm/src/remult-proxy.js +2 -2
  22. package/esm/src/remult3/RepositoryImplementation.d.ts +1 -2
  23. package/esm/src/remult3/RepositoryImplementation.js +17 -12
  24. package/esm/src/shared-tests/db-tests-setup.js +1 -2
  25. package/esm/src/tests/entityForCustomFilter.js +3 -4
  26. package/esm/src/tests/frontend-database-tests-setup.spec.js +1 -2
  27. package/esm/src/tests/testHelper.spec.js +0 -1
  28. package/index.d.ts +1 -2
  29. package/index.js +3 -3
  30. package/package.json +1 -1
  31. package/postgres/postgres-data-provider.d.ts +3 -1
  32. package/postgres/postgres-data-provider.js +11 -1
  33. package/postgres/schema-builder.js +19 -19
  34. package/remult-knex/index.d.ts +4 -28
  35. package/remult-knex/index.js +68 -38
  36. package/remult-mongo.d.ts +8 -2
  37. package/remult-mongo.js +39 -8
  38. package/server/expressBridge.d.ts +1 -0
  39. package/src/backend-tests/my-test.backend-spec.js +212 -0
  40. package/src/context.d.ts +2 -1
  41. package/src/context.js +6 -9
  42. package/src/data-providers/sql-database.d.ts +2 -0
  43. package/src/data-providers/sql-database.js +25 -14
  44. package/src/data-providers/web-sql-data-provider.d.ts +3 -0
  45. package/src/data-providers/web-sql-data-provider.js +15 -7
  46. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +13 -14
  47. package/src/filter/filter-consumer-bridge-to-sql-request.js +95 -46
  48. package/src/remult-proxy.js +6 -1
  49. package/src/remult3/RepositoryImplementation.d.ts +1 -2
  50. package/src/remult3/RepositoryImplementation.js +31 -16
  51. package/src/shared-tests/db-tests-setup.js +2 -3
  52. package/src/tests/entityForCustomFilter.js +3 -4
  53. package/src/tests/frontend-database-tests-setup.spec.js +4 -5
  54. package/src/tests/testHelper.spec.js +3 -4
package/README.md CHANGED
@@ -128,11 +128,9 @@ app.listen(port, () => {
128
128
  ```ts
129
129
  // frontend/code.ts
130
130
 
131
- import { Remult } from "remult";
131
+ import { remult } from "remult";
132
132
  import { Product } from "../shared/product";
133
133
 
134
- const remult = new Remult();
135
-
136
134
  async function increasePriceOfTofu(priceIncrease: number) {
137
135
  const productsRepo = remult.repo(Product);
138
136
 
@@ -146,8 +144,8 @@ async function increasePriceOfTofu(priceIncrease: number) {
146
144
 
147
145
  ```ts
148
146
  @BackendMethod({ allowed: Allow.authenticated })
149
- static async increasePriceOfTofu(priceIncrease: number, remult?: Remult) {
150
- const productsRepo = remult!.repo(Product);
147
+ static async increasePriceOfTofu(priceIncrease: number) {
148
+ const productsRepo = remult.repo(Product);
151
149
 
152
150
  const product = await productsRepo.findFirst({ name: 'Tofu' }); // use Remult in the backend as an ORM
153
151
  product.unitPrice += priceIncrease;
package/esm/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
10
10
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider';
11
11
  export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider';
12
12
  export { SqlDatabase, } from './src/data-providers/sql-database';
13
- export { CustomSqlFilterObject, CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
13
+ export { CustomSqlFilterObject, CustomSqlFilterBuilder, dbNamesOf, sqlCondition } from './src/filter/filter-consumer-bridge-to-sql-request';
14
14
  export { JsonDataProvider, JsonEntityStorage } from './src/data-providers/json-data-provider';
15
15
  export { Controller, BackendMethodOptions, BackendMethod, ProgressListener } from './src/server-action';
16
16
  export { Allowed, Allow, Remult, RemultContext, ApiClient, isBackend, AllowedForInstance, EventDispatcher, EventSource, ExternalHttpProvider, Unobserve, UserInfo } from './src/context';
@@ -18,7 +18,6 @@ export { IdEntity } from './src/id-entity';
18
18
  export { SortSegment, Sort } from './src/sort';
19
19
  export { OneToMany, CompoundIdField } from './src/column';
20
20
  export { Filter } from './src/filter/filter-interfaces';
21
- export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-bridge-to-sql-request';
22
21
  export { UrlBuilder } from './urlBuilder';
23
22
  export { Validators } from './src/validators';
24
23
  export { ValueConverters } from './src/valueConverters';
package/esm/index.js CHANGED
@@ -8,7 +8,7 @@ export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
8
8
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider'; //V
9
9
  export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider'; //V
10
10
  export { SqlDatabase, } from './src/data-providers/sql-database'; //V
11
- export { CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
11
+ export { CustomSqlFilterBuilder, dbNamesOf, sqlCondition } from './src/filter/filter-consumer-bridge-to-sql-request';
12
12
  export { JsonDataProvider } from './src/data-providers/json-data-provider'; //V
13
13
  //export * from './src/data-api'; //reconsider if to make internal
14
14
  export { Controller, BackendMethod, ProgressListener } from './src/server-action';
@@ -17,7 +17,6 @@ export { IdEntity } from './src/id-entity';
17
17
  export { Sort } from './src/sort';
18
18
  export { OneToMany, CompoundIdField } from './src/column';
19
19
  export { Filter } from './src/filter/filter-interfaces';
20
- export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-bridge-to-sql-request';
21
20
  export { UrlBuilder } from './urlBuilder';
22
21
  export { Validators } from './src/validators';
23
22
  export { ValueConverters } from './src/valueConverters';
@@ -1,4 +1,5 @@
1
- import { PoolConfig, QueryResult } from 'pg';
1
+ import { ClientBase, PoolConfig, QueryResult } from 'pg';
2
+ import { Remult } from '../src/context';
2
3
  import { EntityMetadata } from '../src/remult3';
3
4
  import { SqlCommand, SqlImplementation } from '../src/sql-command';
4
5
  import { SqlDatabase } from '../src/data-providers/sql-database';
@@ -10,6 +11,7 @@ export interface PostgresClient extends PostgresCommandSource {
10
11
  }
11
12
  export declare class PostgresDataProvider implements SqlImplementation {
12
13
  private pool;
14
+ static getDb(remult?: Remult): ClientBase;
13
15
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
14
16
  getLimitSqlSyntax(limit: number, offset: number): string;
15
17
  createCommand(): SqlCommand;
@@ -6,6 +6,14 @@ export class PostgresDataProvider {
6
6
  constructor(pool) {
7
7
  this.pool = pool;
8
8
  }
9
+ static getDb(remult) {
10
+ const sql = SqlDatabase.getDb(remult);
11
+ const me = sql._getSourceSql();
12
+ if (!me.pool) {
13
+ throw "the data provider is not a PostgresDataProvider";
14
+ }
15
+ return me.pool;
16
+ }
9
17
  async entityIsUsedForTheFirstTime(entity) {
10
18
  }
11
19
  getLimitSqlSyntax(limit, offset) {
@@ -22,7 +30,9 @@ export class PostgresDataProvider {
22
30
  createCommand: () => new PostgresBridgeToSQLCommand(client),
23
31
  entityIsUsedForTheFirstTime: this.entityIsUsedForTheFirstTime,
24
32
  transaction: () => { throw "nested transactions not allowed"; },
25
- getLimitSqlSyntax: this.getLimitSqlSyntax
33
+ getLimitSqlSyntax: this.getLimitSqlSyntax,
34
+ //@ts-ignore
35
+ pool: client
26
36
  });
27
37
  await client.query('COMMIT');
28
38
  }
@@ -1,5 +1,5 @@
1
1
  import { allEntities } from '../src/context';
2
- import { getDbNameProvider } from '../src/filter/filter-consumer-bridge-to-sql-request';
2
+ import { dbNamesOf, isDbReadonly } from '../src/filter/filter-consumer-bridge-to-sql-request';
3
3
  import { isAutoIncrement } from '../src/remult3';
4
4
  import { ValueConverters } from '../src/valueConverters';
5
5
  export function postgresColumnSyntax(x, dbName) {
@@ -46,57 +46,57 @@ export class PostgresSchemaBuilder {
46
46
  console.log("start verify structure");
47
47
  for (const entityClass of allEntities) {
48
48
  let entity = remult.repo(entityClass).metadata;
49
- let e = await getDbNameProvider(entity);
49
+ let e = await dbNamesOf(entity);
50
50
  try {
51
51
  if (!entity.options.sqlExpression) {
52
- if ((await e.entityName).toLowerCase().indexOf('from ') < 0) {
52
+ if ((await e.$entityName).toLowerCase().indexOf('from ') < 0) {
53
53
  await this.createIfNotExist(entity);
54
54
  await this.verifyAllColumns(entity);
55
55
  }
56
56
  }
57
57
  }
58
58
  catch (err) {
59
- console.log("failed verify structure of " + e.entityName + " ", err);
59
+ console.log("failed verify structure of " + e.$entityName + " ", err);
60
60
  }
61
61
  }
62
62
  }
63
63
  async createIfNotExist(entity) {
64
64
  var c = this.pool.createCommand();
65
- let e = await getDbNameProvider(entity);
66
- await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
65
+ let e = await dbNamesOf(entity);
66
+ await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.$entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
67
67
  if (r.rows.length == 0) {
68
68
  let result = '';
69
69
  for (const x of entity.fields) {
70
- if (!e.isDbReadonly(x) || isAutoIncrement(x)) {
70
+ if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
71
71
  if (result.length != 0)
72
72
  result += ',';
73
73
  result += '\r\n ';
74
74
  if (isAutoIncrement(x))
75
- result += e.nameOf(x) + ' serial';
75
+ result += e.dbNameOf(x) + ' serial';
76
76
  else {
77
- result += postgresColumnSyntax(x, e.nameOf(x));
77
+ result += postgresColumnSyntax(x, e.dbNameOf(x));
78
78
  if (x == entity.idMetadata.field)
79
79
  result += ' primary key';
80
80
  }
81
81
  }
82
82
  }
83
- let sql = 'create table ' + e.entityName + ' (' + result + '\r\n)';
83
+ let sql = 'create table ' + e.$entityName + ' (' + result + '\r\n)';
84
84
  //console.log(sql);
85
85
  await this.pool.execute(sql);
86
86
  }
87
87
  });
88
88
  }
89
89
  async addColumnIfNotExist(entity, c) {
90
- let e = await getDbNameProvider(entity);
91
- if (e.isDbReadonly(c(entity)))
90
+ let e = await dbNamesOf(entity);
91
+ if (isDbReadonly(c(entity), e))
92
92
  return;
93
93
  try {
94
94
  let cmd = this.pool.createCommand();
95
- const colName = e.nameOf(c(entity));
95
+ const colName = e.dbNameOf(c(entity));
96
96
  if ((await cmd.execute(`select 1
97
97
  FROM information_schema.columns
98
- WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
99
- let sql = `alter table ${e.entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
98
+ WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
99
+ let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
100
100
  //console.log(sql);
101
101
  await this.pool.execute(sql);
102
102
  }
@@ -108,14 +108,14 @@ export class PostgresSchemaBuilder {
108
108
  async verifyAllColumns(entity) {
109
109
  try {
110
110
  let cmd = this.pool.createCommand();
111
- let e = await getDbNameProvider(entity);
111
+ let e = await dbNamesOf(entity);
112
112
  let cols = (await cmd.execute(`select column_name
113
113
  FROM information_schema.columns
114
- WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
114
+ WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
115
115
  for (const col of entity.fields) {
116
- if (!e.isDbReadonly(col))
117
- if (!cols.includes(e.nameOf(col).toLocaleLowerCase())) {
118
- let sql = `alter table ${e.entityName} add column ${postgresColumnSyntax(col, e.nameOf(col))}`;
116
+ if (!isDbReadonly(col, e))
117
+ if (!cols.includes(e.dbNameOf(col).toLocaleLowerCase())) {
118
+ let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(col, e.dbNameOf(col))}`;
119
119
  //console.log(sql);
120
120
  await this.pool.execute(sql);
121
121
  }
@@ -1,43 +1,19 @@
1
- import { Knex } from 'knex';
2
- import { Filter, FilterConsumer } from "../src/filter/filter-interfaces";
3
- import { dbNameProvider } from "../src/filter/filter-consumer-bridge-to-sql-request";
1
+ import type { Knex } from 'knex';
4
2
  import { Remult } from "../src/context";
5
- import { EntityFilter, EntityMetadata } from "../src/remult3";
3
+ import { EntityFilter, EntityMetadata, Repository } from "../src/remult3";
6
4
  import { DataProvider, EntityDataProvider } from '../src/data-interfaces';
7
5
  import { FieldMetadata } from '../src/column-interfaces';
8
6
  export declare class KnexDataProvider implements DataProvider {
9
7
  knex: Knex;
10
8
  constructor(knex: Knex);
9
+ static getDb(remult?: Remult): Knex<any, Record<string, any>[]>;
11
10
  getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
12
11
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
13
12
  static customFilter(build: CustomKnexFilterBuilderFunction): EntityFilter<any>;
14
13
  supportsCustomFilter?: boolean;
15
14
  }
16
15
  export declare type CustomKnexFilterBuilderFunction = () => Promise<(builder: Knex.QueryBuilder) => void>;
17
- export declare class FilterConsumerBridgeToKnexRequest implements FilterConsumer {
18
- private nameProvider;
19
- _addWhere: boolean;
20
- promises: Promise<void>[];
21
- result: ((builder: Knex.QueryBuilder) => void)[];
22
- resolveWhere(): Promise<((builder: Knex.QueryBuilder<any, any>) => void)[]>;
23
- constructor(nameProvider: dbNameProvider);
24
- custom(key: string, customItem: any): void;
25
- or(orElements: Filter[]): void;
26
- isNull(col: FieldMetadata): void;
27
- isNotNull(col: FieldMetadata): void;
28
- isIn(col: FieldMetadata, val: any[]): void;
29
- isEqualTo(col: FieldMetadata, val: any): void;
30
- isDifferentFrom(col: FieldMetadata, val: any): void;
31
- isGreaterOrEqualTo(col: FieldMetadata, val: any): void;
32
- isGreaterThan(col: FieldMetadata, val: any): void;
33
- isLessOrEqualTo(col: FieldMetadata, val: any): void;
34
- isLessThan(col: FieldMetadata, val: any): void;
35
- containsCaseInsensitive(col: FieldMetadata, val: any): void;
36
- private add;
37
- databaseCustom(databaseCustom: {
38
- buildKnex: CustomKnexFilterBuilderFunction;
39
- }): void;
40
- }
16
+ export declare function knexCondition<entityType>(repo: Repository<entityType>, condition: EntityFilter<entityType>): Promise<(knex: any) => void>;
41
17
  export declare class KnexSchemaBuilder {
42
18
  private knex;
43
19
  verifyStructureOfAllEntities(remult: Remult): Promise<void>;
@@ -1,15 +1,21 @@
1
- import knex from 'knex';
2
1
  import { customDatabaseFilterToken, Filter } from "../src/filter/filter-interfaces";
3
- import { getDbNameProvider } from "../src/filter/filter-consumer-bridge-to-sql-request";
2
+ import { dbNamesOf, isDbReadonly } from "../src/filter/filter-consumer-bridge-to-sql-request";
4
3
  import { allEntities, Remult } from "../src/context";
5
4
  import { isAutoIncrement } from "../src/remult3";
6
5
  import { ValueConverters } from "../src/valueConverters";
7
6
  import { CompoundIdField } from '../src/column';
8
7
  import { Sort } from '../src/sort';
8
+ import { remult as remultContext } from '../src/remult-proxy';
9
9
  export class KnexDataProvider {
10
10
  constructor(knex) {
11
11
  this.knex = knex;
12
12
  }
13
+ static getDb(remult) {
14
+ const r = (remult || remultContext).dataProvider;
15
+ if (!r.knex)
16
+ throw "the data provider is not an KnexDataProvider";
17
+ return r.knex;
18
+ }
13
19
  getEntityDataProvider(entity) {
14
20
  return new KnexEntityDataProvider(entity, this.knex);
15
21
  }
@@ -42,7 +48,7 @@ class KnexEntityDataProvider {
42
48
  const br = new FilterConsumerBridgeToKnexRequest(e);
43
49
  where.__applyToConsumer(br);
44
50
  let r = await br.resolveWhere();
45
- const result = (await this.knex(e.entityName)
51
+ const result = (await this.knex(e.$entityName)
46
52
  .count().where(b => r.forEach(w => w(b))));
47
53
  var row = result[0];
48
54
  for (const key in row) {
@@ -60,11 +66,11 @@ class KnexEntityDataProvider {
60
66
  if (x.isServerExpression) {
61
67
  }
62
68
  else {
63
- cols.push(e.nameOf(x));
69
+ cols.push(e.dbNameOf(x));
64
70
  colKeys.push(x);
65
71
  }
66
72
  }
67
- let query = this.knex(e.entityName).select(cols);
73
+ let query = this.knex(e.$entityName).select(cols);
68
74
  if (options?.where) {
69
75
  const br = new FilterConsumerBridgeToKnexRequest(e);
70
76
  options.where.__applyToConsumer(br);
@@ -76,7 +82,7 @@ class KnexEntityDataProvider {
76
82
  }
77
83
  if (options.orderBy) {
78
84
  query = query.orderBy(options.orderBy.Segments.map(s => ({
79
- column: e.nameOf(s.field),
85
+ column: e.dbNameOf(s.field),
80
86
  order: s.isDescending ? "desc" : "asc"
81
87
  })));
82
88
  }
@@ -102,7 +108,7 @@ class KnexEntityDataProvider {
102
108
  });
103
109
  }
104
110
  async init() {
105
- return await getDbNameProvider(this.entity);
111
+ return await dbNamesOf(this.entity);
106
112
  }
107
113
  async update(id, data) {
108
114
  const e = await this.init();
@@ -113,17 +119,17 @@ class KnexEntityDataProvider {
113
119
  resultFilter = this.entity.idMetadata.getIdFilter(data.id);
114
120
  let updateObject = {};
115
121
  for (const x of this.entity.fields) {
116
- if (e.isDbReadonly(x)) { }
122
+ if (isDbReadonly(x, e)) { }
117
123
  else if (data[x.key] !== undefined) {
118
124
  let v = x.valueConverter.toDb(data[x.key]);
119
125
  if (v !== undefined) {
120
- let key = await e.nameOf(x);
126
+ let key = await e.dbNameOf(x);
121
127
  updateObject[key] = v;
122
128
  }
123
129
  }
124
130
  }
125
131
  let where = await f.resolveWhere();
126
- await this.knex(e.entityName).update(updateObject).where(b => where.forEach(w => w(b)));
132
+ await this.knex(e.$entityName).update(updateObject).where(b => where.forEach(w => w(b)));
127
133
  return this.find({ where: Filter.fromEntityFilter(this.entity, resultFilter) }).then(y => y[0]);
128
134
  }
129
135
  async delete(id) {
@@ -131,7 +137,7 @@ class KnexEntityDataProvider {
131
137
  let f = new FilterConsumerBridgeToKnexRequest(e);
132
138
  Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
133
139
  let where = await f.resolveWhere();
134
- await this.knex(e.entityName).delete().where(b => where.forEach(w => w(b)));
140
+ await this.knex(e.$entityName).delete().where(b => where.forEach(w => w(b)));
135
141
  }
136
142
  async insert(data) {
137
143
  const e = await this.init();
@@ -142,16 +148,16 @@ class KnexEntityDataProvider {
142
148
  resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
143
149
  let insertObject = {};
144
150
  for (const x of this.entity.fields) {
145
- if (e.isDbReadonly(x)) { }
151
+ if (isDbReadonly(x, e)) { }
146
152
  else {
147
153
  let v = x.valueConverter.toDb(data[x.key]);
148
154
  if (v != undefined) {
149
- let key = await e.nameOf(x);
155
+ let key = await e.dbNameOf(x);
150
156
  insertObject[key] = v;
151
157
  }
152
158
  }
153
159
  }
154
- let insert = this.knex(e.entityName).insert(insertObject);
160
+ let insert = this.knex(e.$entityName).insert(insertObject);
155
161
  if (isAutoIncrement(this.entity.idMetadata.field)) {
156
162
  let result = await insert.returning(this.entity.idMetadata.field.key);
157
163
  let newId = result[0].id;
@@ -164,7 +170,7 @@ class KnexEntityDataProvider {
164
170
  });
165
171
  }
166
172
  }
167
- export class FilterConsumerBridgeToKnexRequest {
173
+ class FilterConsumerBridgeToKnexRequest {
168
174
  constructor(nameProvider) {
169
175
  this.nameProvider = nameProvider;
170
176
  this._addWhere = true;
@@ -208,13 +214,13 @@ export class FilterConsumerBridgeToKnexRequest {
208
214
  })());
209
215
  }
210
216
  isNull(col) {
211
- this.result.push(b => b.whereNull(this.nameProvider.nameOf(col)));
217
+ this.result.push(b => b.whereNull(this.nameProvider.dbNameOf(col)));
212
218
  }
213
219
  isNotNull(col) {
214
- this.result.push(b => b.whereNotNull(this.nameProvider.nameOf(col)));
220
+ this.result.push(b => b.whereNotNull(this.nameProvider.dbNameOf(col)));
215
221
  }
216
222
  isIn(col, val) {
217
- this.result.push(knex => knex.whereIn(this.nameProvider.nameOf(col), val.map(x => col.valueConverter.toDb(x))));
223
+ this.result.push(knex => knex.whereIn(this.nameProvider.dbNameOf(col), val.map(x => col.valueConverter.toDb(x))));
218
224
  }
219
225
  isEqualTo(col, val) {
220
226
  this.add(col, val, "=");
@@ -235,12 +241,12 @@ export class FilterConsumerBridgeToKnexRequest {
235
241
  this.add(col, val, "<");
236
242
  }
237
243
  containsCaseInsensitive(col, val) {
238
- this.result.push(b => b.whereRaw('lower (' + this.nameProvider.nameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')"));
244
+ this.result.push(b => b.whereRaw('lower (' + this.nameProvider.dbNameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')"));
239
245
  this.promises.push((async () => {
240
246
  })());
241
247
  }
242
248
  add(col, val, operator) {
243
- this.result.push(b => b.where(this.nameProvider.nameOf(col), operator, col.valueConverter.toDb(val)));
249
+ this.result.push(b => b.where(this.nameProvider.dbNameOf(col), operator, col.valueConverter.toDb(val)));
244
250
  }
245
251
  databaseCustom(databaseCustom) {
246
252
  this.promises.push((async () => {
@@ -250,6 +256,13 @@ export class FilterConsumerBridgeToKnexRequest {
250
256
  })());
251
257
  }
252
258
  }
259
+ export async function knexCondition(repo, condition) {
260
+ var b = new FilterConsumerBridgeToKnexRequest(await dbNamesOf(repo.metadata));
261
+ b._addWhere = false;
262
+ await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
263
+ let r = await b.resolveWhere();
264
+ return knex => r.forEach(y => y(knex));
265
+ }
253
266
  export class KnexSchemaBuilder {
254
267
  constructor(knex) {
255
268
  this.knex = knex;
@@ -273,16 +286,16 @@ export class KnexSchemaBuilder {
273
286
  }
274
287
  }
275
288
  async createIfNotExist(entity) {
276
- const e = await getDbNameProvider(entity);
277
- if (!await this.knex.schema.hasTable(e.entityName)) {
289
+ const e = await dbNamesOf(entity);
290
+ if (!await this.knex.schema.hasTable(e.$entityName)) {
278
291
  let cols = new Map();
279
292
  for (const f of entity.fields) {
280
293
  cols.set(f, {
281
- name: e.nameOf(f),
282
- readonly: e.isDbReadonly(f)
294
+ name: e.dbNameOf(f),
295
+ readonly: isDbReadonly(f, e)
283
296
  });
284
297
  }
285
- await logSql(this.knex.schema.createTable(e.entityName, b => {
298
+ await logSql(this.knex.schema.createTable(e.$entityName, b => {
286
299
  for (const x of entity.fields) {
287
300
  if (!cols.get(x).readonly || isAutoIncrement(x)) {
288
301
  if (isAutoIncrement(x))
@@ -298,22 +311,22 @@ export class KnexSchemaBuilder {
298
311
  }
299
312
  }
300
313
  async addColumnIfNotExist(entity, c) {
301
- let e = await getDbNameProvider(entity);
302
- if (e.isDbReadonly(c(entity)))
314
+ let e = await dbNamesOf(entity);
315
+ if (isDbReadonly(c(entity), e))
303
316
  return;
304
317
  let col = c(entity);
305
- let colName = e.nameOf(col);
306
- if (!await this.knex.schema.hasColumn(e.entityName, colName)) {
307
- await this.knex.schema.alterTable(e.entityName, b => {
318
+ let colName = e.dbNameOf(col);
319
+ if (!await this.knex.schema.hasColumn(e.$entityName, colName)) {
320
+ await this.knex.schema.alterTable(e.$entityName, b => {
308
321
  buildColumn(col, colName, b);
309
322
  });
310
323
  }
311
324
  }
312
325
  async verifyAllColumns(entity) {
313
- let e = await getDbNameProvider(entity);
326
+ let e = await dbNamesOf(entity);
314
327
  try {
315
328
  for (const col of entity.fields) {
316
- if (!e.isDbReadonly(col)) {
329
+ if (isDbReadonly(col, e)) {
317
330
  await this.addColumnIfNotExist(entity, () => col);
318
331
  }
319
332
  }
@@ -377,7 +390,7 @@ function logSql(who) {
377
390
  return who;
378
391
  }
379
392
  export async function createKnexDataProvider(config, autoCreateTables = true) {
380
- let k = knex(config);
393
+ let k = (await import('knex')).default(config);
381
394
  let result = new KnexDataProvider(k);
382
395
  if (autoCreateTables)
383
396
  await new KnexSchemaBuilder(k).verifyStructureOfAllEntities(new Remult(result));
@@ -1,9 +1,15 @@
1
- import { MongoClient, Db } from 'mongodb';
2
- import { DataProvider, EntityDataProvider, EntityMetadata } from '.';
1
+ import type { MongoClient, Db } from 'mongodb';
2
+ import { DataProvider, EntityDataProvider, EntityFilter, EntityMetadata, Remult, Repository } from '.';
3
3
  export declare class MongoDataProvider implements DataProvider {
4
4
  private db;
5
5
  private client;
6
6
  constructor(db: Db, client: MongoClient);
7
+ static getDb(remult?: Remult): Db;
7
8
  getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
8
9
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
9
10
  }
11
+ export declare function mongoCondition<entityType>(repo: Repository<entityType>, condition: EntityFilter<entityType>): Promise<{
12
+ $and: any[];
13
+ } | {
14
+ $and?: undefined;
15
+ }>;
@@ -1,10 +1,17 @@
1
1
  import { CompoundIdField, Filter } from '.';
2
- import { getDbNameProvider } from './src/filter/filter-consumer-bridge-to-sql-request';
2
+ import { dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
3
+ import { remult as remultContext } from './src/remult-proxy';
3
4
  export class MongoDataProvider {
4
5
  constructor(db, client) {
5
6
  this.db = db;
6
7
  this.client = client;
7
8
  }
9
+ static getDb(remult) {
10
+ const r = (remult || remultContext).dataProvider;
11
+ if (!r.db)
12
+ throw "the data provider is not a MongoDataProvider";
13
+ return r.db;
14
+ }
8
15
  getEntityDataProvider(entity) {
9
16
  return new MongoEntityDataProvider(this.db, entity);
10
17
  }
@@ -33,7 +40,7 @@ class MongoEntityDataProvider {
33
40
  translateFromJson(row, nameProvider) {
34
41
  let result = {};
35
42
  for (const col of this.entity.fields) {
36
- let val = row[nameProvider.nameOf(col)];
43
+ let val = row[nameProvider.dbNameOf(col)];
37
44
  if (isNull(val))
38
45
  val = null;
39
46
  result[col.key] = col.valueConverter.fromDb(val);
@@ -46,7 +53,7 @@ class MongoEntityDataProvider {
46
53
  let val = col.valueConverter.toDb(row[col.key]);
47
54
  if (val === null)
48
55
  val = NULL;
49
- result[nameProvider.nameOf(col)] = val;
56
+ result[nameProvider.dbNameOf(col)] = val;
50
57
  }
51
58
  return result;
52
59
  }
@@ -73,7 +80,7 @@ class MongoEntityDataProvider {
73
80
  if (options.orderBy) {
74
81
  op.sort = {};
75
82
  for (const s of options.orderBy.Segments) {
76
- op.sort[e.nameOf(s.field)] = s.isDescending ? -1 : 1;
83
+ op.sort[e.dbNameOf(s.field)] = s.isDescending ? -1 : 1;
77
84
  }
78
85
  }
79
86
  return await Promise.all(await collection.find(where, op).map(x => this.translateFromJson(x, e)).toArray());
@@ -116,8 +123,8 @@ class MongoEntityDataProvider {
116
123
  return await this.translateFromJson(await collection.findOne({ _id: r.insertedId }), e);
117
124
  }
118
125
  async collection() {
119
- const e = await getDbNameProvider(this.entity);
120
- const collection = this.db.collection(e.entityName);
126
+ const e = await dbNamesOf(this.entity);
127
+ const collection = this.db.collection(e.$entityName);
121
128
  return { e, collection };
122
129
  }
123
130
  }
@@ -171,7 +178,7 @@ class FilterConsumerBridgeToMongo {
171
178
  }
172
179
  isIn(col, val) {
173
180
  this.result.push(() => ({
174
- [this.nameProvider.nameOf(col)]: {
181
+ [this.nameProvider.dbNameOf(col)]: {
175
182
  $in: val.map(x => col.valueConverter.toDb(x))
176
183
  }
177
184
  }));
@@ -203,7 +210,7 @@ class FilterConsumerBridgeToMongo {
203
210
  }
204
211
  add(col, val, operator) {
205
212
  this.result.push(() => ({
206
- [this.nameProvider.nameOf(col)]: { [operator]: isNull(val) ? val : col.valueConverter.toDb(val) }
213
+ [this.nameProvider.dbNameOf(col)]: { [operator]: isNull(val) ? val : col.valueConverter.toDb(val) }
207
214
  }));
208
215
  }
209
216
  databaseCustom(databaseCustom) {
@@ -219,3 +226,10 @@ class FilterConsumerBridgeToMongo {
219
226
  // })());
220
227
  }
221
228
  }
229
+ export async function mongoCondition(repo, condition) {
230
+ var b = new FilterConsumerBridgeToMongo(await dbNamesOf(repo.metadata));
231
+ b._addWhere = false;
232
+ await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
233
+ let r = await b.resolveWhere();
234
+ return r;
235
+ }
@@ -30,6 +30,7 @@ export interface RemultServer {
30
30
  getRemult(req: GenericRequest): Promise<Remult>;
31
31
  openApiDoc(options: {
32
32
  title: string;
33
+ version?: string;
33
34
  }): any;
34
35
  registerRouter(r: GenericRouter): void;
35
36
  handle(req: GenericRequest, gRes?: GenericResponse): Promise<ServerHandleResponse | undefined>;