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
@@ -1,14 +1,17 @@
1
1
  import { __RowsOfDataForTesting } from "../__RowsOfDataForTesting";
2
2
  import { SqlCommand, SqlImplementation } from "../sql-command";
3
3
  import { EntityMetadata } from "../remult3";
4
+ import { Remult } from "../context";
4
5
  export declare class WebSqlDataProvider implements SqlImplementation, __RowsOfDataForTesting {
5
6
  private databaseName;
6
7
  rows: {
7
8
  [tableName: string]: any;
8
9
  };
9
10
  constructor(databaseName: string, databaseSize?: number);
11
+ static getDb(remult?: Remult): any;
10
12
  getLimitSqlSyntax(limit: number, offset: number): string;
11
13
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
14
+ ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
12
15
  dropTable(entity: EntityMetadata): Promise<void>;
13
16
  createTable(entity: EntityMetadata<any>): Promise<void>;
14
17
  createCommand(): SqlCommand;
@@ -1,6 +1,6 @@
1
1
  import { isAutoIncrement } from "../remult3";
2
2
  import { SqlDatabase } from "./sql-database";
3
- import { getDbNameProvider } from "../filter/filter-consumer-bridge-to-sql-request";
3
+ import { dbNamesOf, isDbReadonly } from "../filter/filter-consumer-bridge-to-sql-request";
4
4
  //SqlDatabase.LogToConsole = true;
5
5
  export class WebSqlDataProvider {
6
6
  constructor(databaseName, databaseSize = 2 * 1024 * 1024) {
@@ -8,41 +8,55 @@ export class WebSqlDataProvider {
8
8
  //@ts-ignore
9
9
  this.db = window.openDatabase(databaseName, '1.0', databaseName, databaseSize);
10
10
  }
11
+ // return instance of websql.Database class - see @types/websql
12
+ static getDb(remult) {
13
+ const sql = SqlDatabase.getDb(remult);
14
+ const me = sql._getSourceSql();
15
+ if (!me.db) {
16
+ throw "the data provider is not a WebSqlDataProvider";
17
+ }
18
+ return me.db;
19
+ }
11
20
  getLimitSqlSyntax(limit, offset) {
12
21
  return ' limit ' + limit + ' offset ' + offset;
13
22
  }
14
23
  async entityIsUsedForTheFirstTime(entity) {
15
24
  await this.createTable(entity);
16
25
  }
26
+ async ensureSchema(entities) {
27
+ for (const entity of entities) {
28
+ await this.createTable(entity);
29
+ }
30
+ }
17
31
  async dropTable(entity) {
18
- let e = await getDbNameProvider(entity);
19
- let sql = 'drop table if exists ' + e.entityName;
32
+ let e = await dbNamesOf(entity);
33
+ let sql = 'drop table if exists ' + e.$entityName;
20
34
  if (SqlDatabase.LogToConsole)
21
- console.log(sql);
35
+ console.info(sql);
22
36
  await this.createCommand().execute(sql);
23
37
  }
24
38
  async createTable(entity) {
25
39
  let result = '';
26
- let e = await getDbNameProvider(entity);
40
+ let e = await dbNamesOf(entity);
27
41
  for (const x of entity.fields) {
28
- if (!e.isDbReadonly(x) || isAutoIncrement(x)) {
42
+ if (!isDbReadonly(x, e) || isAutoIncrement(x)) {
29
43
  if (result.length != 0)
30
44
  result += ',';
31
45
  result += '\r\n ';
32
46
  if (isAutoIncrement(x)) {
33
47
  if (x.key != entity.idMetadata.field.key)
34
48
  throw "in web sql, autoincrement is only allowed for primary key";
35
- result += e.nameOf(x) + ' integer primary key autoincrement';
49
+ result += e.$dbNameOf(x) + ' integer primary key autoincrement';
36
50
  }
37
51
  else {
38
- result += this.addColumnSqlSyntax(x, e.nameOf(x));
52
+ result += this.addColumnSqlSyntax(x, e.$dbNameOf(x));
39
53
  if (x.key == entity.idMetadata.field.key) {
40
54
  result += ' primary key';
41
55
  }
42
56
  }
43
57
  }
44
58
  }
45
- let sql = 'create table if not exists ' + e.entityName + ' (' + result + '\r\n)';
59
+ let sql = 'create table if not exists ' + e.$entityName + ' (' + result + '\r\n)';
46
60
  if (SqlDatabase.LogToConsole)
47
61
  console.log(sql);
48
62
  await this.createCommand().execute(sql);
@@ -1,6 +1,6 @@
1
1
  import { Allowed, AllowedForInstance } from "./context";
2
2
  import { FieldMetadata as FieldMetadata } from './column-interfaces';
3
- import { EntityOrderBy, FieldsMetadata, EntityFilter, EntityRef } from "./remult3";
3
+ import { EntityOrderBy, FieldsMetadata, EntityFilter, EntityRef, EntityMetadata } from "./remult3";
4
4
  export interface EntityOptions<entityType = any> {
5
5
  /**A human readable name for the entity */
6
6
  caption?: string;
@@ -67,7 +67,7 @@ export interface EntityOptions<entityType = any> {
67
67
  */
68
68
  dbName?: string;
69
69
  /** For entities that are based on SQL expressions instead of a physical table or view*/
70
- sqlExpression?: string | ((entity: FieldsMetadata<entityType>) => string | Promise<string>);
70
+ sqlExpression?: string | ((entity: EntityMetadata<entityType>) => string | Promise<string>);
71
71
  /** An arrow function that identifies the `id` column to use for this entity
72
72
  * @example
73
73
  * //Single column id
@@ -1,7 +1,8 @@
1
- import { SqlCommand } from "../sql-command";
1
+ import { SqlCommandWithParameters } from "../sql-command";
2
2
  import { Filter, FilterConsumer } from './filter-interfaces';
3
3
  import { FieldMetadata } from "../column-interfaces";
4
- import { EntityMetadata } from "../remult3/remult3";
4
+ import { EntityFilter, OmitEB } from "../remult3/remult3";
5
+ import { EntityMetadataOverloads, RepositoryOverloads } from "../remult3";
5
6
  export declare class FilterConsumerBridgeToSqlRequest implements FilterConsumer {
6
7
  private r;
7
8
  private nameProvider;
@@ -9,7 +10,7 @@ export declare class FilterConsumerBridgeToSqlRequest implements FilterConsumer
9
10
  _addWhere: boolean;
10
11
  promises: Promise<void>[];
11
12
  resolveWhere(): Promise<string>;
12
- constructor(r: SqlCommand, nameProvider: dbNameProvider);
13
+ constructor(r: SqlCommandWithParameters, nameProvider: EntityDbNamesBase);
13
14
  custom(key: string, customItem: any): void;
14
15
  or(orElements: Filter[]): void;
15
16
  isNull(col: FieldMetadata): void;
@@ -32,19 +33,18 @@ export interface CustomSqlFilterObject {
32
33
  }
33
34
  export declare class CustomSqlFilterBuilder {
34
35
  private r;
35
- constructor(r: SqlCommand);
36
+ constructor(r: SqlCommandWithParameters);
36
37
  sql: string;
37
38
  addParameterAndReturnSqlToken<valueType>(val: valueType, field?: FieldMetadata<valueType>): string;
39
+ filterToRaw<entityType>(repo: RepositoryOverloads<entityType>, condition: EntityFilter<entityType>): Promise<string>;
38
40
  }
39
- export declare function getDbNameProvider(meta: EntityMetadata): Promise<dbNameProvider>;
40
- export declare class dbNameProviderImpl {
41
- map: Map<string, string>;
42
- nameOf(field: FieldMetadata<any>): string;
43
- entityName: string;
44
- isDbReadonly(x: FieldMetadata): boolean;
45
- }
46
- export interface dbNameProvider {
47
- nameOf(field: FieldMetadata<any>): string;
48
- entityName: string;
49
- isDbReadonly(x: FieldMetadata): boolean;
50
- }
41
+ export declare function isDbReadonly<entityType>(field: FieldMetadata, dbNames: EntityDbNames<entityType>): boolean;
42
+ export declare type EntityDbNamesBase = {
43
+ $entityName: string;
44
+ $dbNameOf(field: FieldMetadata<any> | string): string;
45
+ toString(): string;
46
+ };
47
+ export declare type EntityDbNames<entityType> = {
48
+ [Properties in keyof Required<OmitEB<entityType>>]: string;
49
+ } & EntityDbNamesBase;
50
+ export declare function dbNamesOf<entityType>(repo: EntityMetadataOverloads<entityType>): Promise<EntityDbNames<entityType>>;
@@ -1,3 +1,5 @@
1
+ import { getEntityMetadata } from "../remult3";
2
+ import { SqlDatabase } from "../data-providers/sql-database";
1
3
  export class FilterConsumerBridgeToSqlRequest {
2
4
  constructor(r, nameProvider) {
3
5
  this.r = r;
@@ -44,15 +46,15 @@ export class FilterConsumerBridgeToSqlRequest {
44
46
  })());
45
47
  }
46
48
  isNull(col) {
47
- this.promises.push((async () => this.addToWhere(this.nameProvider.nameOf(col) + ' is null'))());
49
+ this.promises.push((async () => this.addToWhere(this.nameProvider.$dbNameOf(col) + ' is null'))());
48
50
  }
49
51
  isNotNull(col) {
50
- this.promises.push((async () => this.addToWhere(this.nameProvider.nameOf(col) + ' is not null'))());
52
+ this.promises.push((async () => this.addToWhere(this.nameProvider.$dbNameOf(col) + ' is not null'))());
51
53
  }
52
54
  isIn(col, val) {
53
55
  this.promises.push((async () => {
54
56
  if (val && val.length > 0)
55
- this.addToWhere(this.nameProvider.nameOf(col) + " in (" + val.map(x => this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(x))).join(",") + ")");
57
+ this.addToWhere(this.nameProvider.$dbNameOf(col) + " in (" + val.map(x => this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(x))).join(",") + ")");
56
58
  else
57
59
  this.addToWhere('1 = 0 /*isIn with no values*/');
58
60
  })());
@@ -77,12 +79,12 @@ export class FilterConsumerBridgeToSqlRequest {
77
79
  }
78
80
  containsCaseInsensitive(col, val) {
79
81
  this.promises.push((async () => {
80
- this.addToWhere('lower (' + this.nameProvider.nameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')");
82
+ this.addToWhere('lower (' + this.nameProvider.$dbNameOf(col) + ") like lower ('%" + val.replace(/'/g, '\'\'') + "%')");
81
83
  })());
82
84
  }
83
85
  add(col, val, operator) {
84
86
  this.promises.push((async () => {
85
- let x = this.nameProvider.nameOf(col) + ' ' + operator + ' ' + this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(val));
87
+ let x = this.nameProvider.$dbNameOf(col) + ' ' + operator + ' ' + this.r.addParameterAndReturnSqlToken(col.valueConverter.toDb(val));
86
88
  this.addToWhere(x);
87
89
  })());
88
90
  }
@@ -117,23 +119,29 @@ export class CustomSqlFilterBuilder {
117
119
  val = field.valueConverter.toDb(val);
118
120
  return this.r.addParameterAndReturnSqlToken(val);
119
121
  }
120
- }
121
- export async function getDbNameProvider(meta) {
122
- var result = new dbNameProviderImpl();
123
- for (const f of meta.fields) {
124
- result.map.set(f.key, await f.getDbName());
122
+ async filterToRaw(repo, condition) {
123
+ return SqlDatabase.filterToRaw(repo, condition, this);
125
124
  }
126
- result.entityName = await meta.getDbName();
127
- return result;
128
125
  }
129
- export class dbNameProviderImpl {
130
- constructor() {
131
- this.map = new Map();
132
- }
133
- nameOf(field) {
134
- return this.map.get(field.key);
135
- }
136
- isDbReadonly(x) {
137
- return (x.dbReadOnly || x.isServerExpression || this.nameOf(x) != x.options.dbName);
126
+ export function isDbReadonly(field, dbNames) {
127
+ return (field.dbReadOnly || field.isServerExpression || dbNames.$dbNameOf(field) != field.options.dbName);
128
+ }
129
+ export async function dbNamesOf(repo) {
130
+ var meta = getEntityMetadata(repo);
131
+ const result = {
132
+ $entityName: await meta.getDbName(),
133
+ toString: () => result.$entityName,
134
+ $dbNameOf: (field) => {
135
+ var key;
136
+ if (typeof field === "string")
137
+ key = field;
138
+ else
139
+ key = field.key;
140
+ return result[key];
141
+ }
142
+ };
143
+ for (const field of meta.fields) {
144
+ result[field.key] = await field.getDbName();
138
145
  }
146
+ return result;
139
147
  }
@@ -6,8 +6,8 @@ export declare class Filter {
6
6
  constructor(apply?: (add: FilterConsumer) => void);
7
7
  __applyToConsumer(add: FilterConsumer): void;
8
8
  static resolve<entityType>(filter: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>)): Promise<EntityFilter<entityType>>;
9
- static createCustom<entityType>(customFilterTranslator: (r: Remult) => EntityFilter<entityType> | Promise<EntityFilter<entityType>>, key?: string): (() => EntityFilter<entityType>) & customFilterInfo<entityType>;
10
- static createCustom<entityType, argsType>(customFilterTranslator: (r: Remult, args: argsType) => EntityFilter<entityType> | Promise<EntityFilter<entityType>>, key?: string): ((y: argsType) => EntityFilter<entityType>) & customFilterInfo<entityType>;
9
+ static createCustom<entityType>(rawFilterTranslator: (unused: never, r: Remult) => EntityFilter<entityType> | Promise<EntityFilter<entityType>>, key?: string): (() => EntityFilter<entityType>) & rawFilterInfo<entityType>;
10
+ static createCustom<entityType, argsType>(rawFilterTranslator: (args: argsType, r: Remult) => EntityFilter<entityType> | Promise<EntityFilter<entityType>>, key?: string): ((y: argsType) => EntityFilter<entityType>) & rawFilterInfo<entityType>;
11
11
  static fromEntityFilter<T>(entity: EntityMetadata<T>, whereItem: EntityFilter<T>): Filter;
12
12
  toJson(): any;
13
13
  static entityFilterToJson<T>(entityDefs: EntityMetadata<T>, where: EntityFilter<T>): any;
@@ -77,9 +77,9 @@ export declare function entityFilterToJson<T>(entityDefs: EntityMetadata<T>, whe
77
77
  export declare function buildFilterFromRequestParameters(entity: EntityMetadata, filterInfo: {
78
78
  get: (key: string) => any;
79
79
  }): EntityFilter<any>;
80
- export interface customFilterInfo<entityType> {
81
- customFilterInfo: {
80
+ export interface rawFilterInfo<entityType> {
81
+ rawFilterInfo: {
82
82
  key: string;
83
- customFilterTranslator: (r: Remult, args: any) => (EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
83
+ rawFilterTranslator: (args: any, r: Remult) => (EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
84
84
  };
85
85
  }
@@ -14,18 +14,18 @@ export class Filter {
14
14
  return await filter();
15
15
  return filter;
16
16
  }
17
- static createCustom(customFilterTranslator, key = '') {
18
- let customFilterInfo = { key: key, customFilterTranslator };
17
+ static createCustom(rawFilterTranslator, key = '') {
18
+ let rawFilterInfo = { key: key, rawFilterTranslator };
19
19
  return Object.assign((x) => {
20
20
  let z = {};
21
21
  if (x == undefined)
22
22
  x = {};
23
- if (!customFilterInfo.key)
23
+ if (!rawFilterInfo.key)
24
24
  throw "Usage of custom filter before a key was assigned to it";
25
25
  return {
26
- [customUrlToken + customFilterInfo.key]: x
26
+ [customUrlToken + rawFilterInfo.key]: x
27
27
  };
28
- }, { customFilterInfo });
28
+ }, { rawFilterInfo });
29
29
  }
30
30
  static fromEntityFilter(entity, whereItem) {
31
31
  let result = [];
@@ -79,6 +79,7 @@ export class Filter {
79
79
  break;
80
80
  case "$ne":
81
81
  case "!=":
82
+ case "$nin":
82
83
  found = true;
83
84
  if (Array.isArray(element)) {
84
85
  result.push(fh.isNotIn(element));
@@ -86,6 +87,10 @@ export class Filter {
86
87
  else
87
88
  result.push(fh.isDifferentFrom(element));
88
89
  break;
90
+ case "$in":
91
+ found = true;
92
+ result.push(fh.isIn(element));
93
+ break;
89
94
  case "$contains":
90
95
  found = true;
91
96
  result.push(fh.contains(element));
@@ -123,9 +128,9 @@ export class Filter {
123
128
  let r = [];
124
129
  for (const key in entity.entityType) {
125
130
  const element = entity.entityType[key];
126
- if (element && element.customFilterInfo && element.customFilterInfo.customFilterTranslator) {
127
- if (element.customFilterInfo.key == filterKey) {
128
- r.push(await Filter.fromEntityFilter(entity, await element.customFilterInfo.customFilterTranslator(remult, custom)));
131
+ if (element && element.rawFilterInfo && element.rawFilterInfo.rawFilterTranslator) {
132
+ if (element.rawFilterInfo.key == filterKey) {
133
+ r.push(await Filter.fromEntityFilter(entity, await element.rawFilterInfo.rawFilterTranslator(custom, remult)));
129
134
  }
130
135
  }
131
136
  }
@@ -259,34 +264,34 @@ export class FilterSerializer {
259
264
  }));
260
265
  }
261
266
  isNull(col) {
262
- this.add(col.key + "_null", true);
267
+ this.add(col.key + ".null", true);
263
268
  }
264
269
  isNotNull(col) {
265
- this.add(col.key + "_null", false);
270
+ this.add(col.key + ".null", false);
266
271
  }
267
272
  isIn(col, val) {
268
- this.add(col.key + "_in", val.map(x => col.valueConverter.toJson(x)));
273
+ this.add(col.key + ".in", val.map(x => col.valueConverter.toJson(x)));
269
274
  }
270
275
  isEqualTo(col, val) {
271
276
  this.add(col.key, col.valueConverter.toJson(val));
272
277
  }
273
278
  isDifferentFrom(col, val) {
274
- this.add(col.key + '_ne', col.valueConverter.toJson(val));
279
+ this.add(col.key + '.ne', col.valueConverter.toJson(val));
275
280
  }
276
281
  isGreaterOrEqualTo(col, val) {
277
- this.add(col.key + '_gte', col.valueConverter.toJson(val));
282
+ this.add(col.key + '.gte', col.valueConverter.toJson(val));
278
283
  }
279
284
  isGreaterThan(col, val) {
280
- this.add(col.key + '_gt', col.valueConverter.toJson(val));
285
+ this.add(col.key + '.gt', col.valueConverter.toJson(val));
281
286
  }
282
287
  isLessOrEqualTo(col, val) {
283
- this.add(col.key + '_lte', col.valueConverter.toJson(val));
288
+ this.add(col.key + '.lte', col.valueConverter.toJson(val));
284
289
  }
285
290
  isLessThan(col, val) {
286
- this.add(col.key + '_lt', col.valueConverter.toJson(val));
291
+ this.add(col.key + '.lt', col.valueConverter.toJson(val));
287
292
  }
288
293
  containsCaseInsensitive(col, val) {
289
- this.add(col.key + "_contains", val);
294
+ this.add(col.key + ".contains", val);
290
295
  }
291
296
  }
292
297
  export function entityFilterToJson(entityDefs, where) {
@@ -337,13 +342,13 @@ export function buildFilterFromRequestParameters(entity, filterInfo) {
337
342
  }
338
343
  let c = new filterHelper(col);
339
344
  addFilter('', val => val);
340
- addFilter('_gt', val => ({ "$gt": val }));
341
- addFilter('_gte', val => ({ "$gte": val }));
342
- addFilter('_lt', val => ({ "$lt": val }));
343
- addFilter('_lte', val => ({ "$lte": val }));
344
- addFilter('_ne', val => ({ "$ne": val }));
345
- addFilter('_in', val => val, true);
346
- var nullFilter = filterInfo.get(col.key + "_null");
345
+ addFilter('.gt', val => ({ "$gt": val }));
346
+ addFilter('.gte', val => ({ "$gte": val }));
347
+ addFilter('.lt', val => ({ "$lt": val }));
348
+ addFilter('.lte', val => ({ "$lte": val }));
349
+ addFilter('.ne', val => ({ "$ne": val }));
350
+ addFilter('.in', val => val, true);
351
+ var nullFilter = filterInfo.get(col.key + ".null");
347
352
  if (nullFilter) {
348
353
  nullFilter = nullFilter.toString().trim().toLowerCase();
349
354
  switch (nullFilter) {
@@ -357,7 +362,7 @@ export function buildFilterFromRequestParameters(entity, filterInfo) {
357
362
  break;
358
363
  }
359
364
  }
360
- addFilter('_contains', val => ({ $contains: val }), false, true);
365
+ addFilter('.contains', val => ({ $contains: val }), false, true);
361
366
  });
362
367
  let val = filterInfo.get('OR');
363
368
  if (val) {
@@ -370,7 +375,7 @@ export function buildFilterFromRequestParameters(entity, filterInfo) {
370
375
  }
371
376
  for (const key in entity.entityType) {
372
377
  const element = entity.entityType[key];
373
- if (element && element.customFilterInfo && element.customFilterInfo.customFilterTranslator) {
378
+ if (element && element.rawFilterInfo && element.rawFilterInfo.rawFilterTranslator) {
374
379
  let custom = filterInfo.get(customUrlToken + key);
375
380
  if (custom !== undefined) {
376
381
  where.push({ [customUrlToken + key]: custom });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,184 @@
1
+ import { RestDataProvider } from '../data-providers/rest-data-provider';
2
+ import { buildRestDataProvider } from "../buildRestDataProvider";
3
+ import { LiveQuerySubscriber, liveQueryKeepAliveRoute } from './SubscriptionChannel';
4
+ /* @internal*/
5
+ export class LiveQueryClient {
6
+ constructor(apiProvider, getUserId) {
7
+ this.apiProvider = apiProvider;
8
+ this.getUserId = getUserId;
9
+ this.queries = new Map();
10
+ this.channels = new Map();
11
+ }
12
+ wrapMessageHandling(handleMessage) {
13
+ var x = this.apiProvider().wrapMessageHandling;
14
+ if (x)
15
+ x(handleMessage);
16
+ else
17
+ handleMessage();
18
+ }
19
+ ;
20
+ runPromise(p) {
21
+ return p;
22
+ }
23
+ close() {
24
+ this.queries.clear();
25
+ this.channels.clear();
26
+ this.closeIfNoListeners();
27
+ }
28
+ async subscribeChannel(key, onResult) {
29
+ let onUnsubscribe = () => { };
30
+ const client = await this.openIfNoOpened();
31
+ try {
32
+ let q = this.channels.get(key);
33
+ if (!q) {
34
+ this.channels.set(key, q = new MessageChannel());
35
+ try {
36
+ q.unsubscribe = await client.subscribe(key, value => this.wrapMessageHandling(() => q.handle(value)), err => {
37
+ onResult.error(err);
38
+ });
39
+ }
40
+ catch (err) {
41
+ onResult.error(err);
42
+ throw err;
43
+ }
44
+ }
45
+ q.listeners.push(onResult);
46
+ onUnsubscribe = () => {
47
+ q.listeners.splice(q.listeners.indexOf(onResult), 1);
48
+ if (q.listeners.length == 0) {
49
+ this.channels.delete(key);
50
+ q.unsubscribe();
51
+ }
52
+ this.closeIfNoListeners();
53
+ };
54
+ }
55
+ catch (err) {
56
+ onResult.error(err);
57
+ throw err;
58
+ }
59
+ return () => {
60
+ onUnsubscribe();
61
+ onUnsubscribe = () => { };
62
+ };
63
+ }
64
+ closeIfNoListeners() {
65
+ if (this.client)
66
+ if (this.queries.size === 0 && this.channels.size === 0) {
67
+ this.runPromise(this.client.then(x => x.close()));
68
+ this.client = undefined;
69
+ clearInterval(this.interval);
70
+ this.interval = undefined;
71
+ }
72
+ }
73
+ subscribe(repo, options, listener) {
74
+ let alive = true;
75
+ let onUnsubscribe = () => { alive = false; };
76
+ this.runPromise(repo.buildEntityDataProviderFindOptions(options)
77
+ .then(opts => {
78
+ if (!alive)
79
+ return;
80
+ const { createKey, subscribe } = new RestDataProvider(this.apiProvider).getEntityDataProvider(repo.metadata).buildFindRequest(opts);
81
+ const eventTypeKey = createKey();
82
+ let q = this.queries.get(eventTypeKey);
83
+ if (!q) {
84
+ this.queries.set(eventTypeKey, q = new LiveQuerySubscriber(repo, { entityKey: repo.metadata.key, orderBy: options.orderBy }, this.getUserId()));
85
+ q.subscribeCode = () => {
86
+ if (q.unsubscribe) {
87
+ q.unsubscribe();
88
+ q.unsubscribe = () => { };
89
+ }
90
+ this.runPromise(this.subscribeChannel(q.queryChannel, {
91
+ next: (value) => this.runPromise(q.handle(value)),
92
+ complete: () => { },
93
+ error: er => {
94
+ q.listeners.forEach(l => l.error(er));
95
+ }
96
+ }).then(unsubscribeToChannel => {
97
+ if (q.listeners.length == 0) {
98
+ unsubscribeToChannel();
99
+ return;
100
+ }
101
+ this.runPromise(subscribe(q.id)
102
+ .then(r => {
103
+ if (q.listeners.length === 0) {
104
+ r.unsubscribe();
105
+ unsubscribeToChannel();
106
+ return;
107
+ }
108
+ this.runPromise(q.setAllItems(r.result));
109
+ q.unsubscribe = () => {
110
+ q.unsubscribe = () => { };
111
+ unsubscribeToChannel();
112
+ this.runPromise(r.unsubscribe());
113
+ };
114
+ })
115
+ .catch(err => {
116
+ listener.error(err);
117
+ }));
118
+ })).catch(err => {
119
+ q.listeners.forEach(l => l.error(err));
120
+ });
121
+ };
122
+ q.subscribeCode();
123
+ }
124
+ else {
125
+ q.sendDefaultState(listener.next);
126
+ }
127
+ q.listeners.push(listener);
128
+ onUnsubscribe = () => {
129
+ q.listeners.splice(q.listeners.indexOf(listener), 1);
130
+ listener.complete();
131
+ if (q.listeners.length == 0) {
132
+ this.queries.delete(eventTypeKey);
133
+ q.unsubscribe();
134
+ }
135
+ this.closeIfNoListeners();
136
+ };
137
+ })
138
+ .catch(err => {
139
+ listener.error(err);
140
+ }));
141
+ return () => {
142
+ onUnsubscribe();
143
+ };
144
+ }
145
+ openIfNoOpened() {
146
+ if (!this.client) {
147
+ this.interval = setInterval(async () => {
148
+ const ids = [];
149
+ for (const q of this.queries.values()) {
150
+ ids.push(q.queryChannel);
151
+ }
152
+ if (ids.length > 0) {
153
+ let p = this.apiProvider();
154
+ let { actionInfo } = await import('../server-action');
155
+ const invalidIds = await this.runPromise(await actionInfo.runActionWithoutBlockingUI(() => buildRestDataProvider(p.httpClient).post(p.url + '/' + liveQueryKeepAliveRoute, ids)));
156
+ for (const id of invalidIds) {
157
+ for (const q of this.queries.values()) {
158
+ if (q.queryChannel === id)
159
+ q.subscribeCode();
160
+ }
161
+ }
162
+ }
163
+ }, 30000);
164
+ return this.runPromise(this.client =
165
+ this.apiProvider().subscriptionClient.openConnection(() => {
166
+ for (const q of this.queries.values()) {
167
+ q.subscribeCode();
168
+ }
169
+ }));
170
+ }
171
+ return this.client;
172
+ }
173
+ }
174
+ class MessageChannel {
175
+ constructor() {
176
+ this.unsubscribe = () => { };
177
+ this.listeners = [];
178
+ }
179
+ async handle(message) {
180
+ for (const l of this.listeners) {
181
+ l.next(message);
182
+ }
183
+ }
184
+ }
@@ -0,0 +1,5 @@
1
+ import { SubscriptionClient, SubscriptionClientConnection } from "./SubscriptionChannel";
2
+ export declare class SseSubscriptionClient implements SubscriptionClient {
3
+ openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
4
+ }
5
+ export declare const ConnectionNotFoundError = "client connection not found";