remult 0.17.2 → 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 (165) 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/graphql.js +0 -1
  10. package/esm/index.d.ts +7 -4
  11. package/esm/index.js +4 -2
  12. package/esm/live-query/data-provider-live-query-storage.d.ts +23 -0
  13. package/esm/live-query/data-provider-live-query-storage.js +78 -0
  14. package/esm/myLog.d.ts +1 -0
  15. package/esm/myLog.js +5 -0
  16. package/esm/postgres/postgres-data-provider.d.ts +4 -2
  17. package/esm/postgres/postgres-data-provider.js +18 -6
  18. package/esm/postgres/schema-builder.d.ts +2 -1
  19. package/esm/postgres/schema-builder.js +49 -29
  20. package/esm/remult-knex/index.d.ts +10 -32
  21. package/esm/remult-knex/index.js +75 -51
  22. package/esm/remult-mongo.d.ts +9 -2
  23. package/esm/remult-mongo.js +24 -8
  24. package/esm/remult-next.d.ts +11 -0
  25. package/esm/remult-next.js +27 -0
  26. package/esm/server/core.d.ts +2 -0
  27. package/esm/server/core.js +2 -0
  28. package/esm/server/expressBridge.d.ts +19 -7
  29. package/esm/server/expressBridge.js +135 -31
  30. package/esm/server/index.d.ts +2 -1
  31. package/esm/server/index.js +2 -1
  32. package/esm/server/initDataProvider.d.ts +2 -0
  33. package/esm/server/initDataProvider.js +14 -0
  34. package/esm/src/buildRestDataProvider.d.ts +31 -0
  35. package/esm/src/buildRestDataProvider.js +110 -0
  36. package/esm/src/column-interfaces.d.ts +44 -8
  37. package/esm/src/column.d.ts +3 -3
  38. package/esm/src/context.d.ts +39 -36
  39. package/esm/src/context.js +87 -117
  40. package/esm/src/data-api.d.ts +9 -3
  41. package/esm/src/data-api.js +130 -63
  42. package/esm/src/data-interfaces.d.ts +5 -1
  43. package/esm/src/data-providers/array-entity-data-provider.d.ts +1 -1
  44. package/esm/src/data-providers/array-entity-data-provider.js +2 -17
  45. package/esm/src/data-providers/rest-data-provider.d.ts +4 -3
  46. package/esm/src/data-providers/rest-data-provider.js +64 -23
  47. package/esm/src/data-providers/sql-database.d.ts +7 -3
  48. package/esm/src/data-providers/sql-database.js +60 -17
  49. package/esm/src/data-providers/web-sql-data-provider.d.ts +3 -0
  50. package/esm/src/data-providers/web-sql-data-provider.js +23 -9
  51. package/esm/src/entity.d.ts +2 -2
  52. package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
  53. package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +29 -21
  54. package/esm/src/filter/filter-interfaces.d.ts +5 -5
  55. package/esm/src/filter/filter-interfaces.js +31 -26
  56. package/esm/src/live-query/LiveQueryClient.d.ts +1 -0
  57. package/esm/src/live-query/LiveQueryClient.js +184 -0
  58. package/esm/src/live-query/SseSubscriptionClient.d.ts +5 -0
  59. package/esm/src/live-query/SseSubscriptionClient.js +86 -0
  60. package/esm/src/live-query/SubscriptionChannel.d.ts +41 -0
  61. package/esm/src/live-query/SubscriptionChannel.js +121 -0
  62. package/esm/src/live-query/SubscriptionServer.d.ts +38 -0
  63. package/esm/src/live-query/SubscriptionServer.js +108 -0
  64. package/esm/src/remult-proxy.d.ts +1 -1
  65. package/esm/src/remult-proxy.js +52 -7
  66. package/esm/src/remult3/RepositoryImplementation.d.ts +14 -5
  67. package/esm/src/remult3/RepositoryImplementation.js +124 -44
  68. package/esm/src/remult3/getId.d.ts +2 -0
  69. package/esm/src/remult3/getId.js +7 -0
  70. package/esm/src/remult3/remult3.d.ts +67 -10
  71. package/esm/src/remult3/remult3.js +1 -0
  72. package/esm/src/server-action.d.ts +5 -1
  73. package/esm/src/server-action.js +11 -12
  74. package/esm/src/shared-tests/db-tests-setup.d.ts +12 -5
  75. package/esm/src/shared-tests/db-tests-setup.js +14 -6
  76. package/esm/src/shared-tests/db-tests.db-tests.js +71 -10
  77. package/esm/src/sort.d.ts +1 -0
  78. package/esm/src/sort.js +18 -0
  79. package/esm/src/sql-command.d.ts +5 -2
  80. package/esm/src/tests/entityForCustomFilter.d.ts +6 -6
  81. package/esm/src/tests/entityForCustomFilter.js +20 -21
  82. package/esm/src/tests/frontend-database-tests-setup.spec.js +3 -4
  83. package/esm/src/tests/testHelper.spec.d.ts +3 -1
  84. package/esm/src/tests/testHelper.spec.js +63 -60
  85. package/esm/src/valueConverters.js +15 -7
  86. package/graphql.js +0 -1
  87. package/index.d.ts +7 -4
  88. package/index.js +7 -3
  89. package/live-query/data-provider-live-query-storage.d.ts +23 -0
  90. package/live-query/data-provider-live-query-storage.js +236 -0
  91. package/myLog.d.ts +1 -0
  92. package/myLog.js +20 -0
  93. package/package.json +18 -1
  94. package/postgres/postgres-data-provider.d.ts +4 -2
  95. package/postgres/postgres-data-provider.js +54 -39
  96. package/postgres/schema-builder.d.ts +2 -1
  97. package/postgres/schema-builder.js +118 -70
  98. package/remult-express.js +1 -1
  99. package/remult-knex/index.d.ts +10 -32
  100. package/remult-knex/index.js +134 -87
  101. package/remult-mongo.d.ts +9 -2
  102. package/remult-mongo.js +39 -7
  103. package/remult-next.d.ts +11 -0
  104. package/remult-next.js +73 -0
  105. package/server/JsonEntityFileStorage.js +2 -2
  106. package/server/core.d.ts +2 -0
  107. package/server/core.js +5 -1
  108. package/server/expressBridge.d.ts +19 -7
  109. package/server/expressBridge.js +283 -69
  110. package/server/index.d.ts +2 -1
  111. package/server/index.js +3 -1
  112. package/server/initDataProvider.d.ts +2 -0
  113. package/server/initDataProvider.js +26 -0
  114. package/src/buildRestDataProvider.d.ts +31 -0
  115. package/src/buildRestDataProvider.js +162 -0
  116. package/src/column-interfaces.d.ts +44 -8
  117. package/src/column.d.ts +3 -3
  118. package/src/context.d.ts +39 -36
  119. package/src/context.js +171 -166
  120. package/src/data-api.d.ts +9 -3
  121. package/src/data-api.js +233 -88
  122. package/src/data-interfaces.d.ts +5 -1
  123. package/src/data-providers/array-entity-data-provider.d.ts +1 -1
  124. package/src/data-providers/array-entity-data-provider.js +2 -17
  125. package/src/data-providers/rest-data-provider.d.ts +4 -3
  126. package/src/data-providers/rest-data-provider.js +105 -39
  127. package/src/data-providers/sql-database.d.ts +7 -3
  128. package/src/data-providers/sql-database.js +89 -16
  129. package/src/data-providers/web-sql-data-provider.d.ts +3 -0
  130. package/src/data-providers/web-sql-data-provider.js +56 -11
  131. package/src/entity.d.ts +2 -2
  132. package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +16 -16
  133. package/src/filter/filter-consumer-bridge-to-sql-request.js +59 -50
  134. package/src/filter/filter-interfaces.d.ts +5 -5
  135. package/src/filter/filter-interfaces.js +31 -26
  136. package/src/live-query/LiveQueryClient.d.ts +1 -0
  137. package/src/live-query/LiveQueryClient.js +283 -0
  138. package/src/live-query/SseSubscriptionClient.d.ts +5 -0
  139. package/src/live-query/SseSubscriptionClient.js +150 -0
  140. package/src/live-query/SubscriptionChannel.d.ts +41 -0
  141. package/src/live-query/SubscriptionChannel.js +209 -0
  142. package/src/live-query/SubscriptionServer.d.ts +38 -0
  143. package/src/live-query/SubscriptionServer.js +258 -0
  144. package/src/remult-proxy.d.ts +1 -1
  145. package/src/remult-proxy.js +153 -8
  146. package/src/remult3/RepositoryImplementation.d.ts +14 -5
  147. package/src/remult3/RepositoryImplementation.js +200 -85
  148. package/src/remult3/getId.d.ts +2 -0
  149. package/src/remult3/getId.js +11 -0
  150. package/src/remult3/remult3.d.ts +67 -10
  151. package/src/remult3/remult3.js +1 -0
  152. package/src/server-action.d.ts +5 -1
  153. package/src/server-action.js +11 -11
  154. package/src/shared-tests/db-tests-setup.d.ts +12 -5
  155. package/src/shared-tests/db-tests-setup.js +17 -8
  156. package/src/shared-tests/db-tests.db-tests.js +140 -8
  157. package/src/sort.d.ts +1 -0
  158. package/src/sort.js +18 -0
  159. package/src/sql-command.d.ts +5 -2
  160. package/src/tests/entityForCustomFilter.d.ts +6 -6
  161. package/src/tests/entityForCustomFilter.js +30 -31
  162. package/src/tests/frontend-database-tests-setup.spec.js +5 -6
  163. package/src/tests/testHelper.spec.d.ts +3 -1
  164. package/src/tests/testHelper.spec.js +104 -100
  165. package/src/valueConverters.js +15 -7
@@ -7,17 +7,20 @@ import { h } from "../tests/h";
7
7
  import { Categories as newCategories } from "../tests/remult-3-entities";
8
8
  import { tasks } from "../tests/tasks";
9
9
  import { TestDataApiResponse } from "../tests/TestDataApiResponse";
10
- import { testAll, testAllDbs } from "./db-tests-setup";
10
+ import { testAll, testAllDbs, TestDbs } from "./db-tests-setup";
11
11
  import { entityWithValidations, testConfiguration } from "./entityWithValidations";
12
12
  import { Remult } from "../context";
13
13
  import { dWithPrefilter } from "../tests/dWithPrefilter";
14
14
  import { entityFilterToJson, Filter } from "../filter/filter-interfaces";
15
15
  import { d } from "../tests/d";
16
- import { entityForCustomFilter1 } from "../tests/entityForCustomFilter";
16
+ import { entityForrawFilter1 } from "../tests/entityForCustomFilter";
17
17
  import { entityWithValidationsOnColumn } from "../tests/entityWithValidationsOnColumn";
18
18
  import { Validators } from "../validators";
19
19
  import { Status } from "../tests/testModel/models";
20
20
  import { IdEntity } from "../id-entity";
21
+ import { describeClass } from "../remult3/DecoratorReplacer";
22
+ import { DataProviderLiveQueryStorage } from "../../live-query/data-provider-live-query-storage";
23
+ import { v4 as uuid } from 'uuid';
21
24
  testAll("what", async ({ remult, createEntity }) => {
22
25
  await (await createEntity(stam)).create({ id: 1, title: 'noam' }).save();
23
26
  expect(await remult.repo(stam).count()).toBe(1);
@@ -124,13 +127,37 @@ testAll("put with validations on entity fails", async ({ remult, createEntity })
124
127
  x = await s.find({ where: { myId: 1 } });
125
128
  expect(x[0].name).toBe('noam');
126
129
  });
127
- testAll("test date with null works", async ({ createEntity }) => {
130
+ testAll("test date only with null works", async ({ createEntity }) => {
128
131
  let repo = await createEntity(testDateWithNull);
129
132
  let r = repo.create({ id: 0 });
130
133
  await r.save();
131
134
  r = await repo.findFirst();
132
135
  expect(r.d).toBeNull();
133
136
  expect(await repo.count({ d: null })).toBe(1);
137
+ r.d = new Date(1976, 5, 16);
138
+ await r.save();
139
+ expect(r.d.getFullYear()).toBe(1976);
140
+ r = await repo.findFirst();
141
+ expect(r.d.getFullYear()).toBe(1976);
142
+ r.d = null;
143
+ await r.save();
144
+ expect(r.d).toBeNull();
145
+ }, false);
146
+ testAll("test date with null works", async ({ createEntity }) => {
147
+ let repo = await createEntity(testDateWithNull);
148
+ let r = repo.create({ id: 0 });
149
+ await r.save();
150
+ r = await repo.findFirst();
151
+ expect(r.fullDate).toBeNull("expected null after");
152
+ expect(await repo.count({ fullDate: null })).toBe(1);
153
+ r.fullDate = new Date(1976, 5, 16);
154
+ await r.save();
155
+ expect(r.fullDate.getFullYear()).toBe(1976);
156
+ r = await repo.findFirst();
157
+ expect(r.fullDate.getFullYear()).toBe(1976);
158
+ r.fullDate = null;
159
+ await r.save();
160
+ expect(r.fullDate).toBeNull();
134
161
  }, false);
135
162
  testAll("test original value of date", async ({ createEntity }) => {
136
163
  let r = await (await createEntity(testDateWithNull)).create({ id: 1, d: new Date(1976, 6, 16) }).save();
@@ -140,6 +167,7 @@ let testDateWithNull = class testDateWithNull extends EntityBase {
140
167
  constructor() {
141
168
  super(...arguments);
142
169
  this.id = 0;
170
+ this.fullDate = null;
143
171
  }
144
172
  };
145
173
  __decorate([
@@ -150,6 +178,10 @@ __decorate([
150
178
  Fields.dateOnly({ allowNull: true }),
151
179
  __metadata("design:type", Date)
152
180
  ], testDateWithNull.prototype, "d", void 0);
181
+ __decorate([
182
+ Fields.date({ allowNull: true }),
183
+ __metadata("design:type", Date)
184
+ ], testDateWithNull.prototype, "fullDate", void 0);
153
185
  testDateWithNull = __decorate([
154
186
  Entity('testDateWithNull', { allowApiCrud: true })
155
187
  ], testDateWithNull);
@@ -204,7 +236,7 @@ testAll("test paging with complex object", async ({ remult, createEntity }) => {
204
236
  i++;
205
237
  }
206
238
  expect(i).toBe(5);
207
- });
239
+ }, false);
208
240
  testAll("test paging with complex object_2", async ({ remult, createEntity }) => {
209
241
  let c1 = await (await createEntity(c)).create({ id: 1, name: 'c1' }).save();
210
242
  await (await createEntity(p)).create({ id: 1, name: 'p1', c: c1 }).save();
@@ -237,13 +269,13 @@ testAll("test filter doesn't collapse", async ({ createEntity }) => {
237
269
  expect((await repo.find({ where: f })).length).toBe(2);
238
270
  });
239
271
  testAll("test that it works with inheritance", async ({ createEntity }) => {
240
- let c = await createEntity(entityForCustomFilter1);
272
+ let c = await createEntity(entityForrawFilter1);
241
273
  for (let id = 0; id < 5; id++) {
242
274
  await c.create({ id }).save();
243
275
  }
244
- expect(await (c.count(entityForCustomFilter1.oneAndThree()))).toBe(2);
245
- expect((await (c.findFirst(entityForCustomFilter1.testNumericValue(2)))).id).toBe(2);
246
- expect((await (c.findFirst(entityForCustomFilter1.testObjectValue({ val: 2 })))).id).toBe(2);
276
+ expect(await (c.count(entityForrawFilter1.oneAndThree()))).toBe(2);
277
+ expect((await (c.findFirst(entityForrawFilter1.testNumericValue(2)))).id).toBe(2);
278
+ expect((await (c.findFirst(entityForrawFilter1.testObjectValue({ val: 2 })))).id).toBe(2);
247
279
  });
248
280
  testAll("put with validations on column fails", async ({ remult, createEntity }) => {
249
281
  var s = await createEntity(entityWithValidationsOnColumn);
@@ -412,7 +444,7 @@ testAllDbs("get array works with filter in body", async ({ createData, remult })
412
444
  return undefined;
413
445
  }
414
446
  }, {
415
- status_in: '[1, 2]'
447
+ "status.in": '[1, 2]'
416
448
  });
417
449
  d.test();
418
450
  }, false);
@@ -537,7 +569,7 @@ let testFilter = class testFilter {
537
569
  this.c = '';
538
570
  }
539
571
  };
540
- testFilter.search = Filter.createCustom((remult, str) => ({
572
+ testFilter.search = Filter.createCustom((str, remult) => ({
541
573
  $and: [{
542
574
  $or: [
543
575
  { a: 'a' },
@@ -721,3 +753,32 @@ testAll("test transaction rollback", async ({ db }) => {
721
753
  }
722
754
  expect(fail).toBe(true);
723
755
  });
756
+ testAll("test date", async ({ createEntity }) => {
757
+ const e = class {
758
+ constructor() {
759
+ this.a = 0;
760
+ this.d = new Date();
761
+ }
762
+ };
763
+ describeClass(e, Entity("tdate", { allowApiCrud: true }), {
764
+ a: Fields.number(),
765
+ d: Fields.date()
766
+ });
767
+ const r = await createEntity(e);
768
+ await r.insert({ a: 1, d: new Date(1976, 5, 16) });
769
+ let item = await r.findFirst();
770
+ expect(item.d.getFullYear()).toBe(1976);
771
+ }, false);
772
+ testAll("test live query storage", async ({ db, remult }) => {
773
+ var x = new DataProviderLiveQueryStorage(db);
774
+ if (db.ensureSchema)
775
+ await x.ensureSchema();
776
+ const id = uuid();
777
+ await x.add({ id, entityKey: 'x', data: "noam" });
778
+ await x.forEach("x", async (args) => {
779
+ expect(args.query.data).toBe("noam");
780
+ });
781
+ expect((await x.keepAliveAndReturnUnknownQueryIds([id]))).toEqual([]);
782
+ }, false, {
783
+ exclude: [TestDbs.restDataProvider]
784
+ });
package/esm/src/sort.d.ts CHANGED
@@ -5,6 +5,7 @@ export declare class Sort {
5
5
  constructor(...segments: SortSegment[]);
6
6
  Segments: SortSegment[];
7
7
  reverse(): Sort;
8
+ compare(a: any, b: any): number;
8
9
  static translateOrderByToSort<T>(entityDefs: EntityMetadata<T>, orderBy: EntityOrderBy<T>): Sort;
9
10
  static createUniqueSort<T>(entityMetadata: EntityMetadata<T>, orderBy: Sort): Sort;
10
11
  static createUniqueEntityOrderBy<T>(entityMetadata: EntityMetadata<T>, orderBy: EntityOrderBy<T>): EntityOrderBy<T>;
package/esm/src/sort.js CHANGED
@@ -21,6 +21,24 @@ export class Sort {
21
21
  }
22
22
  return r;
23
23
  }
24
+ compare(a, b) {
25
+ let r = 0;
26
+ for (let i = 0; i < this.Segments.length; i++) {
27
+ let seg = this.Segments[i];
28
+ let left = a[seg.field.key];
29
+ let right = b[seg.field.key];
30
+ if (left > right)
31
+ r = 1;
32
+ else if (left < right)
33
+ r = -1;
34
+ if (r != 0) {
35
+ if (seg.isDescending)
36
+ r *= -1;
37
+ return r;
38
+ }
39
+ }
40
+ return r;
41
+ }
24
42
  static translateOrderByToSort(entityDefs, orderBy) {
25
43
  if (!orderBy)
26
44
  return undefined;
@@ -4,11 +4,14 @@ export interface SqlImplementation {
4
4
  createCommand(): SqlCommand;
5
5
  transaction(action: (sql: SqlImplementation) => Promise<void>): Promise<void>;
6
6
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
7
+ ensureSchema?(entities: EntityMetadata[]): Promise<void>;
7
8
  }
8
- export interface SqlCommand {
9
- addParameterAndReturnSqlToken(val: any): string;
9
+ export interface SqlCommand extends SqlCommandWithParameters {
10
10
  execute(sql: string): Promise<SqlResult>;
11
11
  }
12
+ export interface SqlCommandWithParameters {
13
+ addParameterAndReturnSqlToken(val: any): string;
14
+ }
12
15
  export interface SqlResult {
13
16
  rows: any[];
14
17
  getColumnKeyInResultForIndexInSelect(index: number): string;
@@ -1,16 +1,16 @@
1
1
  import { EntityBase, EntityFilter } from '../remult3';
2
- export declare class entityForCustomFilter extends EntityBase {
2
+ export declare class entityForrawFilter extends EntityBase {
3
3
  id: number;
4
4
  static filter: ((y: {
5
5
  oneAndThree?: boolean;
6
6
  dbOneOrThree?: boolean;
7
7
  two?: boolean;
8
- }) => EntityFilter<entityForCustomFilter>) & import("../filter/filter-interfaces").customFilterInfo<entityForCustomFilter>;
9
- static oneAndThree: (() => EntityFilter<entityForCustomFilter>) & import("../filter/filter-interfaces").customFilterInfo<entityForCustomFilter>;
10
- static testNumericValue: ((y: number) => EntityFilter<entityForCustomFilter>) & import("../filter/filter-interfaces").customFilterInfo<entityForCustomFilter>;
8
+ }) => EntityFilter<entityForrawFilter>) & import("../filter/filter-interfaces").rawFilterInfo<entityForrawFilter>;
9
+ static oneAndThree: (() => EntityFilter<entityForrawFilter>) & import("../filter/filter-interfaces").rawFilterInfo<entityForrawFilter>;
10
+ static testNumericValue: ((y: number) => EntityFilter<entityForrawFilter>) & import("../filter/filter-interfaces").rawFilterInfo<entityForrawFilter>;
11
11
  static testObjectValue: ((y: {
12
12
  val: number;
13
- }) => EntityFilter<entityForCustomFilter>) & import("../filter/filter-interfaces").customFilterInfo<entityForCustomFilter>;
13
+ }) => EntityFilter<entityForrawFilter>) & import("../filter/filter-interfaces").rawFilterInfo<entityForrawFilter>;
14
14
  }
15
- export declare class entityForCustomFilter1 extends entityForCustomFilter {
15
+ export declare class entityForrawFilter1 extends entityForrawFilter {
16
16
  }
@@ -1,44 +1,43 @@
1
- var entityForCustomFilter_1;
1
+ var entityForrawFilter_1;
2
2
  import { __decorate, __metadata } from "tslib";
3
3
  import { SqlDatabase } from '../data-providers/sql-database';
4
4
  import { Entity, EntityBase, Fields } from '../remult3';
5
5
  import { Filter } from '../filter/filter-interfaces';
6
6
  import { ArrayEntityDataProvider } from '../data-providers/array-entity-data-provider';
7
- import { getDbNameProvider } from '../filter/filter-consumer-bridge-to-sql-request';
8
- let entityForCustomFilter = entityForCustomFilter_1 = class entityForCustomFilter extends EntityBase {
7
+ import { dbNamesOf } from '../filter/filter-consumer-bridge-to-sql-request';
8
+ let entityForrawFilter = entityForrawFilter_1 = class entityForrawFilter extends EntityBase {
9
9
  };
10
- entityForCustomFilter.filter = Filter.createCustom(async (remult, c) => {
10
+ entityForrawFilter.filter = Filter.createCustom(async (c, remult) => {
11
11
  let r = [];
12
12
  if (c.oneAndThree)
13
13
  r.push({ id: [1, 3] });
14
14
  if (c.two)
15
15
  r.push({ id: 2 });
16
16
  if (c.dbOneOrThree) {
17
- let meta = remult.repo(entityForCustomFilter_1).metadata;
18
- const e = await getDbNameProvider(meta);
17
+ const e = await dbNamesOf(remult.repo(entityForrawFilter_1));
19
18
  r.push({
20
19
  $and: [
21
- SqlDatabase.customFilter(async (x) => x.sql = e.nameOf(meta.fields.id) + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3) + ")"),
22
- ArrayEntityDataProvider.customFilter(x => x.id == 1 || x.id == 3)
20
+ SqlDatabase.rawFilter(async (x) => x.sql = e.id + ' in (' + x.addParameterAndReturnSqlToken(1) + "," + x.addParameterAndReturnSqlToken(3) + ")"),
21
+ ArrayEntityDataProvider.rawFilter(x => x.id == 1 || x.id == 3)
23
22
  ]
24
23
  });
25
24
  }
26
25
  return { $and: r };
27
26
  });
28
- entityForCustomFilter.oneAndThree = Filter.createCustom(() => ({ id: [1, 3] }));
29
- entityForCustomFilter.testNumericValue = Filter.createCustom((r, val) => ({ id: val }));
30
- entityForCustomFilter.testObjectValue = Filter.createCustom((r, val) => ({ id: val.val }));
27
+ entityForrawFilter.oneAndThree = Filter.createCustom(() => ({ id: [1, 3] }));
28
+ entityForrawFilter.testNumericValue = Filter.createCustom((val) => ({ id: val }));
29
+ entityForrawFilter.testObjectValue = Filter.createCustom((val) => ({ id: val.val }));
31
30
  __decorate([
32
31
  Fields.integer(),
33
32
  __metadata("design:type", Number)
34
- ], entityForCustomFilter.prototype, "id", void 0);
35
- entityForCustomFilter = entityForCustomFilter_1 = __decorate([
36
- Entity('entityForCustomFilter', { allowApiCrud: true })
37
- ], entityForCustomFilter);
38
- export { entityForCustomFilter };
39
- let entityForCustomFilter1 = class entityForCustomFilter1 extends entityForCustomFilter {
33
+ ], entityForrawFilter.prototype, "id", void 0);
34
+ entityForrawFilter = entityForrawFilter_1 = __decorate([
35
+ Entity('entityForrawFilter', { allowApiCrud: true })
36
+ ], entityForrawFilter);
37
+ export { entityForrawFilter };
38
+ let entityForrawFilter1 = class entityForrawFilter1 extends entityForrawFilter {
40
39
  };
41
- entityForCustomFilter1 = __decorate([
42
- Entity('entityForCustomFilter1', { allowApiCrud: true })
43
- ], entityForCustomFilter1);
44
- export { entityForCustomFilter1 };
40
+ entityForrawFilter1 = __decorate([
41
+ Entity('entityForrawFilter1', { allowApiCrud: true })
42
+ ], entityForrawFilter1);
43
+ export { entityForrawFilter1 };
@@ -1,5 +1,5 @@
1
- import { addDatabaseToTest, itWithFocus } from "../shared-tests/db-tests-setup";
2
- import { InMemoryDataProvider } from "../..";
1
+ import { addDatabaseToTest, itWithFocus, TestDbs } from "../shared-tests/db-tests-setup";
2
+ import { InMemoryDataProvider, remult } from "../..";
3
3
  import { Remult } from "../context";
4
4
  import { SqlDatabase } from "../data-providers/sql-database";
5
5
  import { WebSqlDataProvider } from "../data-providers/web-sql-data-provider";
@@ -28,11 +28,10 @@ export function testRest(key, what, focus = false) {
28
28
  itWithFocus(key + " - Rest Provider", async () => {
29
29
  let r = new Remult();
30
30
  r.dataProvider = (new InMemoryDataProvider());
31
- let remult = new Remult();
32
31
  let db = new MockRestDataProvider(r);
33
32
  remult.dataProvider = (db);
34
33
  await what({ db, remult, createEntity: async (x) => remult.repo(x) });
35
34
  }, focus);
36
35
  }
37
- addDatabaseToTest(testRest);
36
+ addDatabaseToTest(testRest, TestDbs.restDataProvider);
38
37
  import '../shared-tests/';
@@ -1,5 +1,6 @@
1
1
  import './frontend-database-tests-setup.spec';
2
2
  import { Remult } from "../context";
3
+ import { DataApi } from "../data-api";
3
4
  import { DataProvider, EntityDataProvider } from "../data-interfaces";
4
5
  import { InMemoryDataProvider } from "../data-providers/in-memory-database";
5
6
  import { EntityMetadata } from "../remult3";
@@ -30,5 +31,6 @@ export declare class MockRestDataProvider implements DataProvider {
30
31
  constructor(remult: Remult);
31
32
  getEntityDataProvider(metadata: EntityMetadata<any>): EntityDataProvider;
32
33
  transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
33
- supportsCustomFilter: boolean;
34
+ supportsRawFilter: boolean;
34
35
  }
36
+ export declare function createMockHttpDataProvider(dataApi: DataApi<any>): import("../data-interfaces").RestDataProviderHttpProvider;
@@ -1,5 +1,5 @@
1
1
  import './frontend-database-tests-setup.spec';
2
- import { HttpProviderBridgeToRestDataProviderHttpProvider, Remult } from "../context";
2
+ import { Remult } from "../context";
3
3
  import { DataApi, serializeError } from "../data-api";
4
4
  import { InMemoryDataProvider } from "../data-providers/in-memory-database";
5
5
  import { RestEntityDataProvider } from "../data-providers/rest-data-provider";
@@ -9,6 +9,7 @@ import { actionInfo, serverActionField } from "../server-action";
9
9
  import { testConfiguration } from '../shared-tests/entityWithValidations';
10
10
  import { TestDataApiResponse } from './TestDataApiResponse';
11
11
  import { remult } from '../remult-proxy';
12
+ import { HttpProviderBridgeToRestDataProviderHttpProvider } from '../buildRestDataProvider';
12
13
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 999999;
13
14
  //actionInfo.runningOnServer = false;
14
15
  export function itForEach(name, arrayOfT, runAsync) {
@@ -103,7 +104,6 @@ export async function testSql(runAsync) {
103
104
  await runAsync({ db: sql, remult });
104
105
  }
105
106
  export async function testInMemoryDb(runAsync) {
106
- let remult = new Remult();
107
107
  let db = new InMemoryDataProvider();
108
108
  remult.dataProvider = (db);
109
109
  await runAsync({ db, remult });
@@ -154,69 +154,72 @@ function urlToReq(url) {
154
154
  export class MockRestDataProvider {
155
155
  constructor(remult) {
156
156
  this.remult = remult;
157
- this.supportsCustomFilter = true;
157
+ this.supportsRawFilter = true;
158
158
  }
159
159
  getEntityDataProvider(metadata) {
160
160
  let dataApi = new DataApi(this.remult.repo(metadata.entityType), this.remult);
161
- return new RestEntityDataProvider(() => "", () => new HttpProviderBridgeToRestDataProviderHttpProvider({
162
- delete: async (url) => {
163
- let urlSplit = url.split('/');
164
- let r = new TestDataApiResponse();
165
- let result;
166
- r.deleted = () => { };
167
- try {
168
- testConfiguration.restDbRunningOnServer = true;
169
- await dataApi.delete(r, urlSplit[urlSplit.length - 1]);
170
- }
171
- finally {
172
- testConfiguration.restDbRunningOnServer = false;
173
- }
174
- return result;
175
- },
176
- get: async (url) => {
177
- let r = new TestDataApiResponse();
178
- let result;
179
- r.success = data => { result = data; };
180
- try {
181
- testConfiguration.restDbRunningOnServer = true;
182
- await dataApi.httpGet(r, urlToReq(url));
183
- }
184
- finally {
185
- testConfiguration.restDbRunningOnServer = false;
186
- }
187
- return result;
188
- },
189
- post: async (url, data) => {
190
- let r = new TestDataApiResponse();
191
- let result;
192
- r.created = data => { result = data; };
193
- r.success = data => { result = data; };
194
- try {
195
- testConfiguration.restDbRunningOnServer = true;
196
- await dataApi.httpPost(r, urlToReq(url), data);
197
- }
198
- finally {
199
- testConfiguration.restDbRunningOnServer = false;
200
- }
201
- return result;
202
- },
203
- put: async (url, data) => {
204
- let urlSplit = url.split('/');
205
- let r = new TestDataApiResponse();
206
- let result;
207
- r.success = data => { result = data; };
208
- try {
209
- testConfiguration.restDbRunningOnServer = true;
210
- await dataApi.put(r, urlSplit[urlSplit.length - 1], data);
211
- }
212
- finally {
213
- testConfiguration.restDbRunningOnServer = false;
214
- }
215
- return result;
216
- }
217
- }), metadata);
161
+ return new RestEntityDataProvider(() => "", () => createMockHttpDataProvider(dataApi), metadata);
218
162
  }
219
163
  transaction(action) {
220
164
  throw new Error('Method not implemented.');
221
165
  }
222
166
  }
167
+ export function createMockHttpDataProvider(dataApi) {
168
+ return new HttpProviderBridgeToRestDataProviderHttpProvider({
169
+ delete: async (url) => {
170
+ let urlSplit = url.split('/');
171
+ let r = new TestDataApiResponse();
172
+ let result;
173
+ r.deleted = () => { };
174
+ try {
175
+ testConfiguration.restDbRunningOnServer = true;
176
+ await dataApi.delete(r, urlSplit[urlSplit.length - 1]);
177
+ }
178
+ finally {
179
+ testConfiguration.restDbRunningOnServer = false;
180
+ }
181
+ return result;
182
+ },
183
+ get: async (url) => {
184
+ let r = new TestDataApiResponse();
185
+ let result;
186
+ r.success = data => { result = data; };
187
+ try {
188
+ testConfiguration.restDbRunningOnServer = true;
189
+ await dataApi.httpGet(r, urlToReq(url), () => "");
190
+ }
191
+ finally {
192
+ testConfiguration.restDbRunningOnServer = false;
193
+ }
194
+ return result;
195
+ },
196
+ post: async (url, data) => {
197
+ let r = new TestDataApiResponse();
198
+ let result;
199
+ r.created = data => { result = data; };
200
+ r.success = data => { result = data; };
201
+ try {
202
+ testConfiguration.restDbRunningOnServer = true;
203
+ await dataApi.httpPost(r, urlToReq(url), data, () => ({}));
204
+ }
205
+ finally {
206
+ testConfiguration.restDbRunningOnServer = false;
207
+ }
208
+ return result;
209
+ },
210
+ put: async (url, data) => {
211
+ let urlSplit = url.split('/');
212
+ let r = new TestDataApiResponse();
213
+ let result;
214
+ r.success = data => { result = data; };
215
+ try {
216
+ testConfiguration.restDbRunningOnServer = true;
217
+ await dataApi.put(r, urlSplit[urlSplit.length - 1], data);
218
+ }
219
+ finally {
220
+ testConfiguration.restDbRunningOnServer = false;
221
+ }
222
+ return result;
223
+ }
224
+ });
225
+ }
@@ -3,6 +3,8 @@ export class ValueConverters {
3
3
  }
4
4
  ValueConverters.Date = {
5
5
  toJson: (val) => {
6
+ if (val === null)
7
+ return null;
6
8
  if (!val)
7
9
  return '';
8
10
  if (typeof (val) === "string")
@@ -11,11 +13,12 @@ ValueConverters.Date = {
11
13
  return val.toISOString();
12
14
  }
13
15
  else {
14
- console.log("ToJsonError", val);
15
- throw new Error("Expected date but got val");
16
+ throw new Error("Expected date but got " + val);
16
17
  }
17
18
  },
18
19
  fromJson: (val) => {
20
+ if (val === null)
21
+ return null;
19
22
  if (val == undefined)
20
23
  return undefined;
21
24
  if (val == '')
@@ -25,7 +28,15 @@ ValueConverters.Date = {
25
28
  return new Date(Date.parse(val));
26
29
  },
27
30
  toDb: x => x,
28
- fromDb: x => x,
31
+ fromDb: val => {
32
+ if (typeof val === "number")
33
+ val = new Date(val);
34
+ if (typeof (val) === "string")
35
+ val = new Date(val);
36
+ if (val && !(val instanceof Date))
37
+ throw "expected date but got " + val;
38
+ return val;
39
+ },
29
40
  fromInput: x => ValueConverters.Date.fromJson(x),
30
41
  toInput: x => ValueConverters.Date.toJson(x),
31
42
  displayValue: (val) => {
@@ -63,10 +74,7 @@ ValueConverters.DateOnly = {
63
74
  } //when using date storage, the database expects and returns a date local and every where else we reflect on date iso
64
75
  ,
65
76
  fromDb: (val) => {
66
- var d = val;
67
- if (!d)
68
- return null;
69
- return val;
77
+ return ValueConverters.Date.fromDb(val);
70
78
  },
71
79
  fieldTypeInDb: 'date',
72
80
  displayValue: (value) => {
package/graphql.js CHANGED
@@ -147,7 +147,6 @@ function remultGraphql(api) {
147
147
  return tslib_1.__awaiter(_this, void 0, void 0, function () {
148
148
  var _this = this;
149
149
  return tslib_1.__generator(this, function (_b) {
150
- console.log(tslib_1.__assign({}, a.fieldNodes));
151
150
  return [2 /*return*/, new Promise(function (res, error) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
152
151
  var _this = this;
153
152
  return tslib_1.__generator(this, function (_a) {
package/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { Field, Fields, StringFieldOptions, FieldsMetadata, Entity, EntityBase, ControllerBase, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FieldType, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, getFields, EntityRef, getEntityRef, SortSegments, ValueListFieldType, getValueList, ValueListFieldOptions, ValueListInfo, OmitEB, Paginator, CaptionTransformer } from './src/remult3';
1
+ export { Field, Fields, FieldsMetadata, Entity, EntityBase, ControllerBase, FieldRef, IdFieldRef, FieldsRef, EntityMetadata, EntityOrderBy, EntityFilter, FindOptions, QueryResult, QueryOptions, Repository, FieldType, FindFirstOptions, ComparisonValueFilter, ValueFilter, IdFilter, ContainsStringValueFilter, getFields, EntityRef, getEntityRef, SortSegments, ValueListFieldType, getValueList, ValueListFieldOptions, ValueListInfo, OmitEB, Paginator, CaptionTransformer, LiveQuery, LiveQueryChangeInfo } from './src/remult3';
2
+ export { StringFieldOptions } from './src/remult3/RepositoryImplementation';
2
3
  export { describeClass } from './src/remult3/DecoratorReplacer';
3
4
  export { EntityOptions } from './src/entity';
4
5
  export { DataProvider, EntityDataProvider, EntityDataProviderFindOptions, ErrorInfo, RestDataProviderHttpProvider } from './src/data-interfaces';
@@ -10,16 +11,18 @@ export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
10
11
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider';
11
12
  export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider';
12
13
  export { SqlDatabase, } from './src/data-providers/sql-database';
13
- export { CustomSqlFilterObject, CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
14
+ export { CustomSqlFilterObject, CustomSqlFilterBuilder, dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
14
15
  export { JsonDataProvider, JsonEntityStorage } from './src/data-providers/json-data-provider';
15
16
  export { Controller, BackendMethodOptions, BackendMethod, ProgressListener } from './src/server-action';
16
- export { Allowed, Allow, Remult, RemultContext, ApiClient, isBackend, AllowedForInstance, EventDispatcher, EventSource, ExternalHttpProvider, Unobserve, UserInfo } from './src/context';
17
+ export { Allowed, Allow, Remult, RemultContext, ApiClient, isBackend, AllowedForInstance, EventDispatcher, EventSource, Unobserve, UserInfo } from './src/context';
18
+ export { ExternalHttpProvider } from './src/buildRestDataProvider';
17
19
  export { IdEntity } from './src/id-entity';
18
20
  export { SortSegment, Sort } from './src/sort';
19
21
  export { OneToMany, CompoundIdField } from './src/column';
20
22
  export { Filter } from './src/filter/filter-interfaces';
21
- export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-bridge-to-sql-request';
22
23
  export { UrlBuilder } from './urlBuilder';
23
24
  export { Validators } from './src/validators';
24
25
  export { ValueConverters } from './src/valueConverters';
25
26
  export { remult } from './src/remult-proxy';
27
+ export { SubscriptionServer, LiveQueryStorage, StoredQuery, InMemoryLiveQueryStorage } from "./src/live-query/SubscriptionServer";
28
+ export { SubscriptionListener, SubscriptionClientConnection, SubscriptionClient, SubscriptionChannel, LiveQueryChange, Unsubscribe } from './src/live-query/SubscriptionChannel';
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.remult = exports.ValueConverters = exports.Validators = exports.UrlBuilder = exports.FilterConsumerBridgeToSqlRequest = exports.Filter = exports.CompoundIdField = exports.OneToMany = exports.Sort = exports.IdEntity = exports.EventSource = exports.isBackend = exports.Remult = exports.Allow = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonDataProvider = exports.CustomSqlFilterBuilder = exports.SqlDatabase = exports.WebSqlDataProvider = exports.ArrayEntityDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.describeClass = exports.CaptionTransformer = exports.ValueListInfo = exports.getValueList = exports.ValueListFieldType = exports.getEntityRef = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = exports.Entity = exports.Fields = exports.Field = void 0;
3
+ exports.SubscriptionChannel = exports.InMemoryLiveQueryStorage = exports.remult = exports.ValueConverters = exports.Validators = exports.UrlBuilder = exports.Filter = exports.CompoundIdField = exports.OneToMany = exports.Sort = exports.IdEntity = exports.EventSource = exports.isBackend = exports.Remult = exports.Allow = exports.ProgressListener = exports.BackendMethod = exports.Controller = exports.JsonDataProvider = exports.dbNamesOf = exports.CustomSqlFilterBuilder = exports.SqlDatabase = exports.WebSqlDataProvider = exports.ArrayEntityDataProvider = exports.InMemoryDataProvider = exports.RestDataProvider = exports.describeClass = exports.CaptionTransformer = exports.ValueListInfo = exports.getValueList = exports.ValueListFieldType = exports.getEntityRef = exports.getFields = exports.FieldType = exports.ControllerBase = exports.EntityBase = exports.Entity = exports.Fields = exports.Field = void 0;
4
4
  /*
5
5
  * Public API Surface of remult
6
6
  */
@@ -31,6 +31,7 @@ var sql_database_1 = require("./src/data-providers/sql-database"); //V
31
31
  Object.defineProperty(exports, "SqlDatabase", { enumerable: true, get: function () { return sql_database_1.SqlDatabase; } });
32
32
  var filter_consumer_bridge_to_sql_request_1 = require("./src/filter/filter-consumer-bridge-to-sql-request");
33
33
  Object.defineProperty(exports, "CustomSqlFilterBuilder", { enumerable: true, get: function () { return filter_consumer_bridge_to_sql_request_1.CustomSqlFilterBuilder; } });
34
+ Object.defineProperty(exports, "dbNamesOf", { enumerable: true, get: function () { return filter_consumer_bridge_to_sql_request_1.dbNamesOf; } });
34
35
  var json_data_provider_1 = require("./src/data-providers/json-data-provider"); //V
35
36
  Object.defineProperty(exports, "JsonDataProvider", { enumerable: true, get: function () { return json_data_provider_1.JsonDataProvider; } });
36
37
  //export * from './src/data-api'; //reconsider if to make internal
@@ -52,8 +53,6 @@ Object.defineProperty(exports, "OneToMany", { enumerable: true, get: function ()
52
53
  Object.defineProperty(exports, "CompoundIdField", { enumerable: true, get: function () { return column_1.CompoundIdField; } });
53
54
  var filter_interfaces_1 = require("./src/filter/filter-interfaces");
54
55
  Object.defineProperty(exports, "Filter", { enumerable: true, get: function () { return filter_interfaces_1.Filter; } });
55
- var filter_consumer_bridge_to_sql_request_2 = require("./src/filter/filter-consumer-bridge-to-sql-request");
56
- Object.defineProperty(exports, "FilterConsumerBridgeToSqlRequest", { enumerable: true, get: function () { return filter_consumer_bridge_to_sql_request_2.FilterConsumerBridgeToSqlRequest; } });
57
56
  var urlBuilder_1 = require("./urlBuilder");
58
57
  Object.defineProperty(exports, "UrlBuilder", { enumerable: true, get: function () { return urlBuilder_1.UrlBuilder; } });
59
58
  var validators_1 = require("./src/validators");
@@ -62,3 +61,8 @@ var valueConverters_1 = require("./src/valueConverters");
62
61
  Object.defineProperty(exports, "ValueConverters", { enumerable: true, get: function () { return valueConverters_1.ValueConverters; } });
63
62
  var remult_proxy_1 = require("./src/remult-proxy");
64
63
  Object.defineProperty(exports, "remult", { enumerable: true, get: function () { return remult_proxy_1.remult; } });
64
+ //export { getId } from './src/remult3/getId';
65
+ var SubscriptionServer_1 = require("./src/live-query/SubscriptionServer");
66
+ Object.defineProperty(exports, "InMemoryLiveQueryStorage", { enumerable: true, get: function () { return SubscriptionServer_1.InMemoryLiveQueryStorage; } });
67
+ var SubscriptionChannel_1 = require("./src/live-query/SubscriptionChannel");
68
+ Object.defineProperty(exports, "SubscriptionChannel", { enumerable: true, get: function () { return SubscriptionChannel_1.SubscriptionChannel; } });
@@ -0,0 +1,23 @@
1
+ import { Storage, DataProvider } from "../src/data-interfaces";
2
+ import { LiveQueryStorage, StoredQuery } from "../src/live-query/SubscriptionServer";
3
+ import { EntityBase, Repository } from "../src/remult3";
4
+ export declare class DataProviderLiveQueryStorage implements LiveQueryStorage, Storage {
5
+ repo: Promise<Repository<LiveQueryStorageEntity>>;
6
+ dataProvider: Promise<DataProvider>;
7
+ constructor(dataProvider: DataProvider | Promise<DataProvider> | (() => Promise<DataProvider | undefined>));
8
+ ensureSchema(): Promise<void>;
9
+ add({ id, entityKey, data }: StoredQuery): Promise<void>;
10
+ remove(queryId: string): Promise<void>;
11
+ forEach(entityKey: string, callback: (args: {
12
+ query: StoredQuery;
13
+ setData(data: any): Promise<void>;
14
+ }) => Promise<void>): Promise<void>;
15
+ keepAliveAndReturnUnknownQueryIds(queryIds: string[]): Promise<string[]>;
16
+ }
17
+ declare class LiveQueryStorageEntity extends EntityBase {
18
+ id: string;
19
+ entityKey: string;
20
+ data: any;
21
+ lastUsedIso: string;
22
+ }
23
+ export {};