remult 0.17.3 → 0.18.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 (163) hide show
  1. package/SseSubscriptionServer.d.ts +23 -0
  2. package/SseSubscriptionServer.js +143 -0
  3. package/ably.d.ts +13 -0
  4. package/ably.js +59 -0
  5. package/esm/SseSubscriptionServer.d.ts +23 -0
  6. package/esm/SseSubscriptionServer.js +102 -0
  7. package/esm/ably.d.ts +13 -0
  8. package/esm/ably.js +28 -0
  9. package/esm/index.d.ts +7 -4
  10. package/esm/index.js +4 -2
  11. package/esm/live-query/data-provider-live-query-storage.d.ts +23 -0
  12. package/esm/live-query/data-provider-live-query-storage.js +78 -0
  13. package/esm/myLog.d.ts +1 -0
  14. package/esm/myLog.js +5 -0
  15. package/esm/postgres/postgres-data-provider.d.ts +4 -2
  16. package/esm/postgres/postgres-data-provider.js +18 -6
  17. package/esm/postgres/schema-builder.d.ts +2 -1
  18. package/esm/postgres/schema-builder.js +49 -29
  19. package/esm/remult-knex/index.d.ts +10 -32
  20. package/esm/remult-knex/index.js +75 -51
  21. package/esm/remult-mongo.d.ts +9 -2
  22. package/esm/remult-mongo.js +24 -8
  23. package/esm/remult-next.d.ts +11 -0
  24. package/esm/remult-next.js +27 -0
  25. package/esm/server/core.d.ts +2 -0
  26. package/esm/server/core.js +2 -0
  27. package/esm/server/expressBridge.d.ts +19 -7
  28. package/esm/server/expressBridge.js +135 -31
  29. package/esm/server/index.d.ts +2 -1
  30. package/esm/server/index.js +2 -1
  31. package/esm/server/initDataProvider.d.ts +2 -0
  32. package/esm/server/initDataProvider.js +14 -0
  33. package/esm/src/buildRestDataProvider.d.ts +31 -0
  34. package/esm/src/buildRestDataProvider.js +110 -0
  35. package/esm/src/column-interfaces.d.ts +44 -8
  36. package/esm/src/column.d.ts +3 -3
  37. package/esm/src/context.d.ts +39 -36
  38. package/esm/src/context.js +87 -117
  39. package/esm/src/data-api.d.ts +9 -3
  40. package/esm/src/data-api.js +130 -63
  41. package/esm/src/data-interfaces.d.ts +5 -1
  42. package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
  43. package/esm/src/data-providers/array-entity-data-provider.js +2 -17
  44. package/esm/src/data-providers/rest-data-provider.d.ts +4 -3
  45. package/esm/src/data-providers/rest-data-provider.js +64 -23
  46. package/esm/src/data-providers/sql-database.d.ts +7 -3
  47. package/esm/src/data-providers/sql-database.js +60 -17
  48. package/esm/src/data-providers/web-sql-data-provider.d.ts +3 -0
  49. package/esm/src/data-providers/web-sql-data-provider.js +23 -9
  50. package/esm/src/entity.d.ts +2 -2
  51. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
  52. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +29 -21
  53. package/esm/src/filter/filter-interfaces.d.ts +5 -5
  54. package/esm/src/filter/filter-interfaces.js +31 -26
  55. package/esm/src/live-query/LiveQueryClient.d.ts +1 -0
  56. package/esm/src/live-query/LiveQueryClient.js +184 -0
  57. package/esm/src/live-query/SseSubscriptionClient.d.ts +5 -0
  58. package/esm/src/live-query/SseSubscriptionClient.js +86 -0
  59. package/esm/src/live-query/SubscriptionChannel.d.ts +41 -0
  60. package/esm/src/live-query/SubscriptionChannel.js +121 -0
  61. package/esm/src/live-query/SubscriptionServer.d.ts +38 -0
  62. package/esm/src/live-query/SubscriptionServer.js +108 -0
  63. package/esm/src/remult-proxy.d.ts +1 -1
  64. package/esm/src/remult-proxy.js +52 -7
  65. package/esm/src/remult3/RepositoryImplementation.d.ts +14 -5
  66. package/esm/src/remult3/RepositoryImplementation.js +124 -44
  67. package/esm/src/remult3/getId.d.ts +2 -0
  68. package/esm/src/remult3/getId.js +7 -0
  69. package/esm/src/remult3/remult3.d.ts +67 -10
  70. package/esm/src/remult3/remult3.js +1 -0
  71. package/esm/src/server-action.d.ts +5 -1
  72. package/esm/src/server-action.js +11 -12
  73. package/esm/src/shared-tests/db-tests-setup.d.ts +12 -5
  74. package/esm/src/shared-tests/db-tests-setup.js +14 -6
  75. package/esm/src/shared-tests/db-tests.db-tests.js +71 -10
  76. package/esm/src/sort.d.ts +1 -0
  77. package/esm/src/sort.js +18 -0
  78. package/esm/src/sql-command.d.ts +5 -2
  79. package/esm/src/tests/entityForCustomFilter.d.ts +6 -6
  80. package/esm/src/tests/entityForCustomFilter.js +20 -21
  81. package/esm/src/tests/frontend-database-tests-setup.spec.js +3 -4
  82. package/esm/src/tests/testHelper.spec.d.ts +3 -1
  83. package/esm/src/tests/testHelper.spec.js +63 -60
  84. package/esm/src/valueConverters.js +15 -7
  85. package/index.d.ts +7 -4
  86. package/index.js +7 -3
  87. package/live-query/data-provider-live-query-storage.d.ts +23 -0
  88. package/live-query/data-provider-live-query-storage.js +236 -0
  89. package/myLog.d.ts +1 -0
  90. package/myLog.js +20 -0
  91. package/package.json +18 -1
  92. package/postgres/postgres-data-provider.d.ts +4 -2
  93. package/postgres/postgres-data-provider.js +54 -39
  94. package/postgres/schema-builder.d.ts +2 -1
  95. package/postgres/schema-builder.js +118 -70
  96. package/remult-express.js +1 -1
  97. package/remult-knex/index.d.ts +10 -32
  98. package/remult-knex/index.js +134 -87
  99. package/remult-mongo.d.ts +9 -2
  100. package/remult-mongo.js +39 -7
  101. package/remult-next.d.ts +11 -0
  102. package/remult-next.js +73 -0
  103. package/server/JsonEntityFileStorage.js +2 -2
  104. package/server/core.d.ts +2 -0
  105. package/server/core.js +5 -1
  106. package/server/expressBridge.d.ts +19 -7
  107. package/server/expressBridge.js +283 -69
  108. package/server/index.d.ts +2 -1
  109. package/server/index.js +3 -1
  110. package/server/initDataProvider.d.ts +2 -0
  111. package/server/initDataProvider.js +26 -0
  112. package/src/buildRestDataProvider.d.ts +31 -0
  113. package/src/buildRestDataProvider.js +162 -0
  114. package/src/column-interfaces.d.ts +44 -8
  115. package/src/column.d.ts +3 -3
  116. package/src/context.d.ts +39 -36
  117. package/src/context.js +171 -166
  118. package/src/data-api.d.ts +9 -3
  119. package/src/data-api.js +233 -88
  120. package/src/data-interfaces.d.ts +5 -1
  121. package/src/data-providers/array-entity-data-provider.d.ts +1 -1
  122. package/src/data-providers/array-entity-data-provider.js +2 -17
  123. package/src/data-providers/rest-data-provider.d.ts +4 -3
  124. package/src/data-providers/rest-data-provider.js +105 -39
  125. package/src/data-providers/sql-database.d.ts +7 -3
  126. package/src/data-providers/sql-database.js +89 -16
  127. package/src/data-providers/web-sql-data-provider.d.ts +3 -0
  128. package/src/data-providers/web-sql-data-provider.js +56 -11
  129. package/src/entity.d.ts +2 -2
  130. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
  131. package/src/filter/filter-consumer-bridge-to-sql-request.js +59 -50
  132. package/src/filter/filter-interfaces.d.ts +5 -5
  133. package/src/filter/filter-interfaces.js +31 -26
  134. package/src/live-query/LiveQueryClient.d.ts +1 -0
  135. package/src/live-query/LiveQueryClient.js +283 -0
  136. package/src/live-query/SseSubscriptionClient.d.ts +5 -0
  137. package/src/live-query/SseSubscriptionClient.js +150 -0
  138. package/src/live-query/SubscriptionChannel.d.ts +41 -0
  139. package/src/live-query/SubscriptionChannel.js +209 -0
  140. package/src/live-query/SubscriptionServer.d.ts +38 -0
  141. package/src/live-query/SubscriptionServer.js +258 -0
  142. package/src/remult-proxy.d.ts +1 -1
  143. package/src/remult-proxy.js +153 -8
  144. package/src/remult3/RepositoryImplementation.d.ts +14 -5
  145. package/src/remult3/RepositoryImplementation.js +200 -85
  146. package/src/remult3/getId.d.ts +2 -0
  147. package/src/remult3/getId.js +11 -0
  148. package/src/remult3/remult3.d.ts +67 -10
  149. package/src/remult3/remult3.js +1 -0
  150. package/src/server-action.d.ts +5 -1
  151. package/src/server-action.js +11 -11
  152. package/src/shared-tests/db-tests-setup.d.ts +12 -5
  153. package/src/shared-tests/db-tests-setup.js +17 -8
  154. package/src/shared-tests/db-tests.db-tests.js +140 -8
  155. package/src/sort.d.ts +1 -0
  156. package/src/sort.js +18 -0
  157. package/src/sql-command.d.ts +5 -2
  158. package/src/tests/entityForCustomFilter.d.ts +6 -6
  159. package/src/tests/entityForCustomFilter.js +30 -31
  160. package/src/tests/frontend-database-tests-setup.spec.js +5 -6
  161. package/src/tests/testHelper.spec.d.ts +3 -1
  162. package/src/tests/testHelper.spec.js +104 -100
  163. package/src/valueConverters.js +15 -7
@@ -6,7 +6,8 @@ export declare function postgresColumnSyntax(x: FieldMetadata, dbName: string):
6
6
  export declare function verifyStructureOfAllEntities(db: SqlDatabase, remult: Remult): Promise<void>;
7
7
  export declare class PostgresSchemaBuilder {
8
8
  private pool;
9
- verifyStructureOfAllEntities(remult: Remult): Promise<void>;
9
+ verifyStructureOfAllEntities(remult?: Remult): Promise<void>;
10
+ ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
10
11
  createIfNotExist(entity: EntityMetadata): Promise<void>;
11
12
  addColumnIfNotExist<T extends EntityMetadata>(entity: T, c: ((e: T) => FieldMetadata)): Promise<void>;
12
13
  verifyAllColumns<T extends EntityMetadata>(entity: T): Promise<void>;
@@ -1,5 +1,6 @@
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
+ import { RemultProxy } from '../src/remult-proxy';
3
4
  import { isAutoIncrement } from '../src/remult3';
4
5
  import { ValueConverters } from '../src/valueConverters';
5
6
  export function postgresColumnSyntax(x, dbName) {
@@ -43,86 +44,105 @@ export class PostgresSchemaBuilder {
43
44
  }
44
45
  }
45
46
  async verifyStructureOfAllEntities(remult) {
46
- console.log("start verify structure");
47
- for (const entityClass of allEntities) {
47
+ if (!remult) {
48
+ remult = RemultProxy.defaultRemult;
49
+ }
50
+ const completed = new Set();
51
+ const entities = [];
52
+ for (const entityClass of [...allEntities].reverse()) {
48
53
  let entity = remult.repo(entityClass).metadata;
49
- let e = await getDbNameProvider(entity);
54
+ let e = await dbNamesOf(entity);
55
+ if (completed.has(e.$entityName))
56
+ continue;
57
+ completed.add(e.$entityName);
58
+ entities.push(entity);
59
+ }
60
+ await this.ensureSchema(entities);
61
+ }
62
+ async ensureSchema(entities) {
63
+ for (const entity of entities) {
64
+ let e = await dbNamesOf(entity);
50
65
  try {
51
66
  if (!entity.options.sqlExpression) {
52
- if ((await e.entityName).toLowerCase().indexOf('from ') < 0) {
67
+ if (e.$entityName.toLowerCase().indexOf('from ') < 0) {
53
68
  await this.createIfNotExist(entity);
54
69
  await this.verifyAllColumns(entity);
55
70
  }
56
71
  }
57
72
  }
58
73
  catch (err) {
59
- console.log("failed verify structure of " + e.entityName + " ", err);
74
+ console.error("failed verify structure of " + e.$entityName + " ", err);
60
75
  }
61
76
  }
62
77
  }
63
78
  async createIfNotExist(entity) {
64
79
  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) => {
80
+ let e = await dbNamesOf(entity);
81
+ await c.execute("select 1 from information_Schema.tables where table_name=" + c.addParameterAndReturnSqlToken((e.$entityName).toLowerCase()) + this.additionalWhere).then(async (r) => {
67
82
  if (r.rows.length == 0) {
68
83
  let result = '';
69
84
  for (const x of entity.fields) {
70
- if (!e.isDbReadonly(x) || isAutoIncrement(x)) {
85
+ if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
71
86
  if (result.length != 0)
72
87
  result += ',';
73
88
  result += '\r\n ';
74
89
  if (isAutoIncrement(x))
75
- result += e.nameOf(x) + ' serial';
90
+ result += e.$dbNameOf(x) + ' serial';
76
91
  else {
77
- result += postgresColumnSyntax(x, e.nameOf(x));
78
- if (x == entity.idMetadata.field)
79
- result += ' primary key';
92
+ result += postgresColumnSyntax(x, e.$dbNameOf(x));
80
93
  }
94
+ if (x == entity.idMetadata.field)
95
+ result += ' primary key';
81
96
  }
82
97
  }
83
- let sql = 'create table ' + e.entityName + ' (' + result + '\r\n)';
84
- //console.log(sql);
98
+ let sql = 'create table ' + e.$entityName + ' (' + result + '\r\n)';
99
+ if (PostgresSchemaBuilder.logToConsole)
100
+ console.info(sql);
85
101
  await this.pool.execute(sql);
86
102
  }
87
103
  });
88
104
  }
89
105
  async addColumnIfNotExist(entity, c) {
90
- let e = await getDbNameProvider(entity);
91
- if (e.isDbReadonly(c(entity)))
106
+ let e = await dbNamesOf(entity);
107
+ if (isDbReadonly(c(entity), e))
92
108
  return;
93
109
  try {
94
110
  let cmd = this.pool.createCommand();
95
- const colName = e.nameOf(c(entity));
111
+ const colName = e.$dbNameOf(c(entity));
96
112
  if ((await cmd.execute(`select 1
97
113
  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)}`;
100
- //console.log(sql);
114
+ WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} and column_name=${cmd.addParameterAndReturnSqlToken((colName).toLocaleLowerCase())}` + this.additionalWhere)).rows.length == 0) {
115
+ let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(c(entity), colName)}`;
116
+ if (PostgresSchemaBuilder.logToConsole)
117
+ console.info(sql);
101
118
  await this.pool.execute(sql);
102
119
  }
103
120
  }
104
121
  catch (err) {
105
- console.log(err);
122
+ console.error(err);
106
123
  }
107
124
  }
108
125
  async verifyAllColumns(entity) {
109
126
  try {
110
127
  let cmd = this.pool.createCommand();
111
- let e = await getDbNameProvider(entity);
128
+ let e = await dbNamesOf(entity);
112
129
  let cols = (await cmd.execute(`select column_name
113
130
  FROM information_schema.columns
114
- WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
131
+ WHERE table_name=${cmd.addParameterAndReturnSqlToken((e.$entityName).toLocaleLowerCase())} ` + this.additionalWhere)).rows.map(x => x.column_name);
115
132
  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))}`;
119
- //console.log(sql);
133
+ if (!isDbReadonly(col, e))
134
+ if (!cols.includes(e.$dbNameOf(col).toLocaleLowerCase())) {
135
+ let sql = `alter table ${e.$entityName} add column ${postgresColumnSyntax(col, e.$dbNameOf(col))}`;
136
+ if (PostgresSchemaBuilder.logToConsole)
137
+ console.info(sql);
120
138
  await this.pool.execute(sql);
121
139
  }
122
140
  }
123
141
  }
124
142
  catch (err) {
125
- console.log(err);
143
+ console.error(err);
126
144
  }
127
145
  }
128
146
  }
147
+ //@internal
148
+ PostgresSchemaBuilder.logToConsole = true;
@@ -1,46 +1,24 @@
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, RepositoryOverloads } 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, any[]>;
11
10
  getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
12
11
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
13
- static customFilter(build: CustomKnexFilterBuilderFunction): EntityFilter<any>;
14
- supportsCustomFilter?: boolean;
12
+ static rawFilter(build: CustomKnexFilterBuilderFunction): EntityFilter<any>;
13
+ static filterToRaw<entityType>(entity: RepositoryOverloads<entityType>, condition: EntityFilter<entityType>): Promise<(knex: any) => void>;
14
+ supportsRawFilter?: boolean;
15
+ ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
15
16
  }
16
17
  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
- }
41
18
  export declare class KnexSchemaBuilder {
42
19
  private knex;
43
- verifyStructureOfAllEntities(remult: Remult): Promise<void>;
20
+ verifyStructureOfAllEntities(remult?: Remult): Promise<void>;
21
+ ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
44
22
  createIfNotExist(entity: EntityMetadata): Promise<void>;
45
23
  addColumnIfNotExist<T extends EntityMetadata>(entity: T, c: ((e: T) => FieldMetadata)): Promise<void>;
46
24
  verifyAllColumns<T extends EntityMetadata>(entity: T): Promise<void>;
@@ -48,4 +26,4 @@ export declare class KnexSchemaBuilder {
48
26
  constructor(knex: Knex);
49
27
  }
50
28
  export declare function buildColumn(x: FieldMetadata, dbName: string, b: Knex.CreateTableBuilder): void;
51
- export declare function createKnexDataProvider(config: Knex.Config, autoCreateTables?: boolean): Promise<KnexDataProvider>;
29
+ export declare function createKnexDataProvider(config: Knex.Config): Promise<KnexDataProvider>;
@@ -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";
4
- import { allEntities, Remult } from "../src/context";
5
- import { isAutoIncrement } from "../src/remult3";
2
+ import { dbNamesOf, isDbReadonly } from "../src/filter/filter-consumer-bridge-to-sql-request";
3
+ import { allEntities } from "../src/context";
4
+ import { isAutoIncrement, getRepository } 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, RemultProxy } 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
  }
@@ -24,13 +30,25 @@ export class KnexDataProvider {
24
30
  throw err;
25
31
  }
26
32
  }
27
- static customFilter(build) {
33
+ static rawFilter(build) {
28
34
  return {
29
35
  [customDatabaseFilterToken]: {
30
36
  buildKnex: build
31
37
  }
32
38
  };
33
39
  }
40
+ static async filterToRaw(entity, condition) {
41
+ const repo = getRepository(entity);
42
+ var b = new FilterConsumerBridgeToKnexRequest(await dbNamesOf(repo.metadata));
43
+ b._addWhere = false;
44
+ await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
45
+ let r = await b.resolveWhere();
46
+ return knex => r.forEach(y => y(knex));
47
+ }
48
+ async ensureSchema(entities) {
49
+ var sb = new KnexSchemaBuilder(this.knex);
50
+ await sb.ensureSchema(entities);
51
+ }
34
52
  }
35
53
  class KnexEntityDataProvider {
36
54
  constructor(entity, knex) {
@@ -42,7 +60,7 @@ class KnexEntityDataProvider {
42
60
  const br = new FilterConsumerBridgeToKnexRequest(e);
43
61
  where.__applyToConsumer(br);
44
62
  let r = await br.resolveWhere();
45
- const result = (await this.knex(e.entityName)
63
+ const result = (await this.knex(e.$entityName)
46
64
  .count().where(b => r.forEach(w => w(b))));
47
65
  var row = result[0];
48
66
  for (const key in row) {
@@ -60,11 +78,11 @@ class KnexEntityDataProvider {
60
78
  if (x.isServerExpression) {
61
79
  }
62
80
  else {
63
- cols.push(e.nameOf(x));
81
+ cols.push(e.$dbNameOf(x));
64
82
  colKeys.push(x);
65
83
  }
66
84
  }
67
- let query = this.knex(e.entityName).select(cols);
85
+ let query = this.knex(e.$entityName).select(cols);
68
86
  if (options?.where) {
69
87
  const br = new FilterConsumerBridgeToKnexRequest(e);
70
88
  options.where.__applyToConsumer(br);
@@ -76,7 +94,7 @@ class KnexEntityDataProvider {
76
94
  }
77
95
  if (options.orderBy) {
78
96
  query = query.orderBy(options.orderBy.Segments.map(s => ({
79
- column: e.nameOf(s.field),
97
+ column: e.$dbNameOf(s.field),
80
98
  order: s.isDescending ? "desc" : "asc"
81
99
  })));
82
100
  }
@@ -102,7 +120,7 @@ class KnexEntityDataProvider {
102
120
  });
103
121
  }
104
122
  async init() {
105
- return await getDbNameProvider(this.entity);
123
+ return await dbNamesOf(this.entity);
106
124
  }
107
125
  async update(id, data) {
108
126
  const e = await this.init();
@@ -113,17 +131,17 @@ class KnexEntityDataProvider {
113
131
  resultFilter = this.entity.idMetadata.getIdFilter(data.id);
114
132
  let updateObject = {};
115
133
  for (const x of this.entity.fields) {
116
- if (e.isDbReadonly(x)) { }
134
+ if (isDbReadonly(x, e)) { }
117
135
  else if (data[x.key] !== undefined) {
118
136
  let v = x.valueConverter.toDb(data[x.key]);
119
137
  if (v !== undefined) {
120
- let key = await e.nameOf(x);
138
+ let key = await e.$dbNameOf(x);
121
139
  updateObject[key] = v;
122
140
  }
123
141
  }
124
142
  }
125
143
  let where = await f.resolveWhere();
126
- await this.knex(e.entityName).update(updateObject).where(b => where.forEach(w => w(b)));
144
+ await this.knex(e.$entityName).update(updateObject).where(b => where.forEach(w => w(b)));
127
145
  return this.find({ where: Filter.fromEntityFilter(this.entity, resultFilter) }).then(y => y[0]);
128
146
  }
129
147
  async delete(id) {
@@ -131,7 +149,7 @@ class KnexEntityDataProvider {
131
149
  let f = new FilterConsumerBridgeToKnexRequest(e);
132
150
  Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(id)).__applyToConsumer(f);
133
151
  let where = await f.resolveWhere();
134
- await this.knex(e.entityName).delete().where(b => where.forEach(w => w(b)));
152
+ await this.knex(e.$entityName).delete().where(b => where.forEach(w => w(b)));
135
153
  }
136
154
  async insert(data) {
137
155
  const e = await this.init();
@@ -142,16 +160,16 @@ class KnexEntityDataProvider {
142
160
  resultFilter = Filter.fromEntityFilter(this.entity, this.entity.idMetadata.getIdFilter(data[this.entity.idMetadata.field.key]));
143
161
  let insertObject = {};
144
162
  for (const x of this.entity.fields) {
145
- if (e.isDbReadonly(x)) { }
163
+ if (isDbReadonly(x, e)) { }
146
164
  else {
147
165
  let v = x.valueConverter.toDb(data[x.key]);
148
166
  if (v != undefined) {
149
- let key = await e.nameOf(x);
167
+ let key = await e.$dbNameOf(x);
150
168
  insertObject[key] = v;
151
169
  }
152
170
  }
153
171
  }
154
- let insert = this.knex(e.entityName).insert(insertObject);
172
+ let insert = this.knex(e.$entityName).insert(insertObject);
155
173
  if (isAutoIncrement(this.entity.idMetadata.field)) {
156
174
  let newId;
157
175
  if (this.knex.client.config.client === 'mysql2') {
@@ -171,7 +189,7 @@ class KnexEntityDataProvider {
171
189
  });
172
190
  }
173
191
  }
174
- export class FilterConsumerBridgeToKnexRequest {
192
+ class FilterConsumerBridgeToKnexRequest {
175
193
  constructor(nameProvider) {
176
194
  this.nameProvider = nameProvider;
177
195
  this._addWhere = true;
@@ -215,13 +233,13 @@ export class FilterConsumerBridgeToKnexRequest {
215
233
  })());
216
234
  }
217
235
  isNull(col) {
218
- this.result.push(b => b.whereNull(this.nameProvider.nameOf(col)));
236
+ this.result.push(b => b.whereNull(this.nameProvider.$dbNameOf(col)));
219
237
  }
220
238
  isNotNull(col) {
221
- this.result.push(b => b.whereNotNull(this.nameProvider.nameOf(col)));
239
+ this.result.push(b => b.whereNotNull(this.nameProvider.$dbNameOf(col)));
222
240
  }
223
241
  isIn(col, val) {
224
- this.result.push(knex => knex.whereIn(this.nameProvider.nameOf(col), val.map(x => col.valueConverter.toDb(x))));
242
+ this.result.push(knex => knex.whereIn(this.nameProvider.$dbNameOf(col), val.map(x => col.valueConverter.toDb(x))));
225
243
  }
226
244
  isEqualTo(col, val) {
227
245
  this.add(col, val, "=");
@@ -242,12 +260,12 @@ export class FilterConsumerBridgeToKnexRequest {
242
260
  this.add(col, val, "<");
243
261
  }
244
262
  containsCaseInsensitive(col, val) {
245
- this.result.push(b => b.whereRaw('lower (' + this.nameProvider.nameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')"));
263
+ this.result.push(b => b.whereRaw('lower (' + this.nameProvider.$dbNameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')"));
246
264
  this.promises.push((async () => {
247
265
  })());
248
266
  }
249
267
  add(col, val, operator) {
250
- this.result.push(b => b.where(this.nameProvider.nameOf(col), operator, col.valueConverter.toDb(val)));
268
+ this.result.push(b => b.where(this.nameProvider.$dbNameOf(col), operator, col.valueConverter.toDb(val)));
251
269
  }
252
270
  databaseCustom(databaseCustom) {
253
271
  this.promises.push((async () => {
@@ -263,33 +281,38 @@ export class KnexSchemaBuilder {
263
281
  this.additionalWhere = '';
264
282
  }
265
283
  async verifyStructureOfAllEntities(remult) {
266
- console.log("start verify structure");
267
- for (const entity of allEntities) {
268
- let metadata = remult.repo(entity).metadata;
284
+ if (!remult)
285
+ remult = RemultProxy.defaultRemult;
286
+ const entities = allEntities.map(x => remult.repo(x).metadata);
287
+ this.ensureSchema(entities);
288
+ }
289
+ async ensureSchema(entities) {
290
+ for (const entity of entities) {
291
+ let e = await dbNamesOf(entity);
269
292
  try {
270
- if (!metadata.options.sqlExpression) {
271
- if ((await metadata.getDbName()).toLowerCase().indexOf('from ') < 0) {
272
- await this.createIfNotExist(metadata);
273
- await this.verifyAllColumns(metadata);
293
+ if (!entity.options.sqlExpression) {
294
+ if (e.$entityName.toLowerCase().indexOf('from ') < 0) {
295
+ await this.createIfNotExist(entity);
296
+ await this.verifyAllColumns(entity);
274
297
  }
275
298
  }
276
299
  }
277
300
  catch (err) {
278
- console.log("failed verify structure of " + await metadata.getDbName() + " ", err);
301
+ console.error("failed ensure schema of " + e.$entityName + " ", err);
279
302
  }
280
303
  }
281
304
  }
282
305
  async createIfNotExist(entity) {
283
- const e = await getDbNameProvider(entity);
284
- if (!await this.knex.schema.hasTable(e.entityName)) {
306
+ const e = await dbNamesOf(entity);
307
+ if (!await this.knex.schema.hasTable(e.$entityName)) {
285
308
  let cols = new Map();
286
309
  for (const f of entity.fields) {
287
310
  cols.set(f, {
288
- name: e.nameOf(f),
289
- readonly: e.isDbReadonly(f)
311
+ name: e.$dbNameOf(f),
312
+ readonly: isDbReadonly(f, e)
290
313
  });
291
314
  }
292
- await logSql(this.knex.schema.createTable(e.entityName, b => {
315
+ await logSql(this.knex.schema.createTable(e.$entityName, b => {
293
316
  for (const x of entity.fields) {
294
317
  if (!cols.get(x).readonly || isAutoIncrement(x)) {
295
318
  if (isAutoIncrement(x))
@@ -305,31 +328,33 @@ export class KnexSchemaBuilder {
305
328
  }
306
329
  }
307
330
  async addColumnIfNotExist(entity, c) {
308
- let e = await getDbNameProvider(entity);
309
- if (e.isDbReadonly(c(entity)))
331
+ let e = await dbNamesOf(entity);
332
+ if (isDbReadonly(c(entity), e))
310
333
  return;
311
334
  let col = c(entity);
312
- let colName = e.nameOf(col);
313
- if (!await this.knex.schema.hasColumn(e.entityName, colName)) {
314
- await this.knex.schema.alterTable(e.entityName, b => {
335
+ let colName = e.$dbNameOf(col);
336
+ if (!await this.knex.schema.hasColumn(e.$entityName, colName)) {
337
+ await logSql(this.knex.schema.alterTable(e.$entityName, b => {
315
338
  buildColumn(col, colName, b);
316
- });
339
+ }));
317
340
  }
318
341
  }
319
342
  async verifyAllColumns(entity) {
320
- let e = await getDbNameProvider(entity);
343
+ let e = await dbNamesOf(entity);
321
344
  try {
322
- for (const col of entity.fields) {
323
- if (!e.isDbReadonly(col)) {
345
+ for (const col of entity.fields.toArray()) {
346
+ if (!isDbReadonly(col, e)) {
324
347
  await this.addColumnIfNotExist(entity, () => col);
325
348
  }
326
349
  }
327
350
  }
328
351
  catch (err) {
329
- console.log(err);
352
+ console.error(err);
330
353
  }
331
354
  }
332
355
  }
356
+ //@internal
357
+ KnexSchemaBuilder.logToConsole = true;
333
358
  export function buildColumn(x, dbName, b) {
334
359
  if (x.valueType == Number) {
335
360
  if (!x.valueConverter.fieldTypeInDb) {
@@ -380,13 +405,12 @@ export function buildColumn(x, dbName, b) {
380
405
  }
381
406
  }
382
407
  function logSql(who) {
383
- //console.log(who.toSQL().sql);
408
+ if (KnexSchemaBuilder.logToConsole)
409
+ console.info(who.toSQL());
384
410
  return who;
385
411
  }
386
- export async function createKnexDataProvider(config, autoCreateTables = true) {
387
- let k = knex(config);
412
+ export async function createKnexDataProvider(config) {
413
+ let k = (await import('knex')).default(config);
388
414
  let result = new KnexDataProvider(k);
389
- if (autoCreateTables)
390
- await new KnexSchemaBuilder(k).verifyStructureOfAllEntities(new Remult(result));
391
415
  return result;
392
416
  }
@@ -1,9 +1,16 @@
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 } from '.';
3
+ import { RepositoryOverloads } from './src/remult3';
3
4
  export declare class MongoDataProvider implements DataProvider {
4
5
  private db;
5
6
  private client;
6
7
  constructor(db: Db, client: MongoClient);
8
+ static getDb(remult?: Remult): Db;
7
9
  getEntityDataProvider(entity: EntityMetadata<any>): EntityDataProvider;
8
10
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
11
+ static filterToRaw<entityType>(entity: RepositoryOverloads<entityType>, condition: EntityFilter<entityType>): Promise<{
12
+ $and: any[];
13
+ } | {
14
+ $and?: undefined;
15
+ }>;
9
16
  }
@@ -1,10 +1,18 @@
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 { getRepository } from './src/remult3';
4
+ import { remult as remultContext } from './src/remult-proxy';
3
5
  export class MongoDataProvider {
4
6
  constructor(db, client) {
5
7
  this.db = db;
6
8
  this.client = client;
7
9
  }
10
+ static getDb(remult) {
11
+ const r = (remult || remultContext).dataProvider;
12
+ if (!r.db)
13
+ throw "the data provider is not a MongoDataProvider";
14
+ return r.db;
15
+ }
8
16
  getEntityDataProvider(entity) {
9
17
  return new MongoEntityDataProvider(this.db, entity);
10
18
  }
@@ -20,6 +28,14 @@ export class MongoDataProvider {
20
28
  throw err;
21
29
  }
22
30
  }
31
+ static async filterToRaw(entity, condition) {
32
+ const repo = getRepository(entity);
33
+ var b = new FilterConsumerBridgeToMongo(await dbNamesOf(repo.metadata));
34
+ b._addWhere = false;
35
+ await (await (repo.translateWhereToFilter(condition))).__applyToConsumer(b);
36
+ let r = await b.resolveWhere();
37
+ return r;
38
+ }
23
39
  }
24
40
  const NULL = { $null: "$null" };
25
41
  function isNull(x) {
@@ -33,7 +49,7 @@ class MongoEntityDataProvider {
33
49
  translateFromJson(row, nameProvider) {
34
50
  let result = {};
35
51
  for (const col of this.entity.fields) {
36
- let val = row[nameProvider.nameOf(col)];
52
+ let val = row[nameProvider.$dbNameOf(col)];
37
53
  if (isNull(val))
38
54
  val = null;
39
55
  result[col.key] = col.valueConverter.fromDb(val);
@@ -46,7 +62,7 @@ class MongoEntityDataProvider {
46
62
  let val = col.valueConverter.toDb(row[col.key]);
47
63
  if (val === null)
48
64
  val = NULL;
49
- result[nameProvider.nameOf(col)] = val;
65
+ result[nameProvider.$dbNameOf(col)] = val;
50
66
  }
51
67
  return result;
52
68
  }
@@ -73,7 +89,7 @@ class MongoEntityDataProvider {
73
89
  if (options.orderBy) {
74
90
  op.sort = {};
75
91
  for (const s of options.orderBy.Segments) {
76
- op.sort[e.nameOf(s.field)] = s.isDescending ? -1 : 1;
92
+ op.sort[e.$dbNameOf(s.field)] = s.isDescending ? -1 : 1;
77
93
  }
78
94
  }
79
95
  return await Promise.all(await collection.find(where, op).map(x => this.translateFromJson(x, e)).toArray());
@@ -116,8 +132,8 @@ class MongoEntityDataProvider {
116
132
  return await this.translateFromJson(await collection.findOne({ _id: r.insertedId }), e);
117
133
  }
118
134
  async collection() {
119
- const e = await getDbNameProvider(this.entity);
120
- const collection = this.db.collection(e.entityName);
135
+ const e = await dbNamesOf(this.entity);
136
+ const collection = this.db.collection(e.$entityName);
121
137
  return { e, collection };
122
138
  }
123
139
  }
@@ -171,7 +187,7 @@ class FilterConsumerBridgeToMongo {
171
187
  }
172
188
  isIn(col, val) {
173
189
  this.result.push(() => ({
174
- [this.nameProvider.nameOf(col)]: {
190
+ [this.nameProvider.$dbNameOf(col)]: {
175
191
  $in: val.map(x => col.valueConverter.toDb(x))
176
192
  }
177
193
  }));
@@ -203,7 +219,7 @@ class FilterConsumerBridgeToMongo {
203
219
  }
204
220
  add(col, val, operator) {
205
221
  this.result.push(() => ({
206
- [this.nameProvider.nameOf(col)]: { [operator]: isNull(val) ? val : col.valueConverter.toDb(val) }
222
+ [this.nameProvider.$dbNameOf(col)]: { [operator]: isNull(val) ? val : col.valueConverter.toDb(val) }
207
223
  }));
208
224
  }
209
225
  databaseCustom(databaseCustom) {
@@ -0,0 +1,11 @@
1
+ /// <reference types="node" />
2
+ import type { GetServerSideProps, NextApiRequest, PreviewData, NextApiHandler } from "next";
3
+ import type { ParsedUrlQuery } from "querystring";
4
+ import { RemultServer, RemultServerOptions } from "./server";
5
+ export declare function remultNext(options?: RemultServerOptions<NextApiRequest>): RemultServer & NextApiHandler & {
6
+ getServerSideProps<P extends {
7
+ [key: string]: any;
8
+ } = {
9
+ [key: string]: any;
10
+ }, Q extends ParsedUrlQuery = ParsedUrlQuery, D extends PreviewData = PreviewData>(getServerPropsFunction: GetServerSideProps<P, Q, D>): GetServerSideProps<P, Q, D>;
11
+ };
@@ -0,0 +1,27 @@
1
+ import { createRemultServer } from "./server";
2
+ export function remultNext(options) {
3
+ let result = createRemultServer(options);
4
+ return Object.assign((req, res) => result.handle(req, res), result, {
5
+ getRemult: (...args) => result.getRemult(...args),
6
+ handle: (...args) => result.handle(...args),
7
+ openApiDoc: (...args) => result.openApiDoc(...args),
8
+ registerRouter: (...args) => result.registerRouter(...args),
9
+ withRemult: (...args) => result.withRemult(...args),
10
+ }, {
11
+ getServerSideProps: (getServerPropsFunction) => {
12
+ return (context) => {
13
+ return new Promise((res, err) => {
14
+ result.withRemult(context, undefined, async () => {
15
+ try {
16
+ let r = await getServerPropsFunction(context);
17
+ res(JSON.parse(JSON.stringify(r)));
18
+ }
19
+ catch (e) {
20
+ err(e);
21
+ }
22
+ });
23
+ });
24
+ };
25
+ }
26
+ });
27
+ }