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
@@ -0,0 +1,23 @@
1
+ import { GenericResponse } from './server/index';
2
+ import { Remult } from './src/context';
3
+ import { SubscriptionServer } from './src/live-query/SubscriptionServer';
4
+ export declare class SseSubscriptionServer implements SubscriptionServer {
5
+ private canUserConnectToChannel?;
6
+ constructor(canUserConnectToChannel?: (channel: string, remult: Remult) => boolean);
7
+ publishMessage<T>(channel: string, message: any): Promise<void>;
8
+ }
9
+ export interface ResponseRequiredForSSE {
10
+ write(data: string): void;
11
+ writeHead(status: number, headers: any): void;
12
+ flush?(): void;
13
+ }
14
+ export declare class clientConnection {
15
+ response: GenericResponse & ResponseRequiredForSSE;
16
+ channels: Record<string, boolean>;
17
+ close(): void;
18
+ closed: boolean;
19
+ write(eventData: string, eventType?: string): void;
20
+ connectionId: any;
21
+ constructor(response: GenericResponse & ResponseRequiredForSSE);
22
+ sendLiveMessage(): void;
23
+ }
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.clientConnection = exports.SseSubscriptionServer = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var uuid_1 = require("uuid");
6
+ var SseSubscriptionClient_1 = require("./src/live-query/SseSubscriptionClient");
7
+ var SseSubscriptionServer = /** @class */ (function () {
8
+ function SseSubscriptionServer(canUserConnectToChannel) {
9
+ this.canUserConnectToChannel = canUserConnectToChannel;
10
+ //@internal
11
+ this.connections = [];
12
+ //@internal
13
+ this.debugMessageFileSaver = function (id, channel, message) { };
14
+ //@internal
15
+ this.debugFileSaver = function () { };
16
+ if (!this.canUserConnectToChannel) {
17
+ this.canUserConnectToChannel = function () { return true; };
18
+ }
19
+ }
20
+ //@internal
21
+ SseSubscriptionServer.prototype.subscribeToChannel = function (_a, res, remult, remove) {
22
+ var e_1, _b;
23
+ var channel = _a.channel, clientId = _a.clientId;
24
+ if (remove === void 0) { remove = false; }
25
+ try {
26
+ for (var _c = tslib_1.__values(this.connections), _d = _c.next(); !_d.done; _d = _c.next()) {
27
+ var c = _d.value;
28
+ if (c.connectionId === clientId) {
29
+ if (this.canUserConnectToChannel(channel, remult)) {
30
+ if (remove)
31
+ delete c.channels[channel];
32
+ else
33
+ c.channels[channel] = true;
34
+ res.success("ok");
35
+ this.debug();
36
+ return;
37
+ }
38
+ else {
39
+ res.forbidden();
40
+ this.debug();
41
+ return;
42
+ }
43
+ }
44
+ }
45
+ }
46
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
47
+ finally {
48
+ try {
49
+ if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
50
+ }
51
+ finally { if (e_1) throw e_1.error; }
52
+ }
53
+ res.success(SseSubscriptionClient_1.ConnectionNotFoundError);
54
+ };
55
+ SseSubscriptionServer.prototype.publishMessage = function (channel, message) {
56
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
57
+ var data, _a, _b, sc;
58
+ var e_2, _c;
59
+ return tslib_1.__generator(this, function (_d) {
60
+ data = JSON.stringify({ channel: channel, data: message });
61
+ try {
62
+ for (_a = tslib_1.__values(this.connections), _b = _a.next(); !_b.done; _b = _a.next()) {
63
+ sc = _b.value;
64
+ if (sc.channels[channel]) {
65
+ this.debugMessageFileSaver(sc.connectionId, channel, message);
66
+ sc.write(data);
67
+ }
68
+ }
69
+ }
70
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
71
+ finally {
72
+ try {
73
+ if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
74
+ }
75
+ finally { if (e_2) throw e_2.error; }
76
+ }
77
+ return [2 /*return*/];
78
+ });
79
+ });
80
+ };
81
+ //@internal
82
+ SseSubscriptionServer.prototype.openHttpServerStream = function (req, res) {
83
+ var _this = this;
84
+ res.writeHead(200, {
85
+ 'Content-Type': 'text/event-stream',
86
+ 'Cache-Control': 'no-cache',
87
+ 'Connection': 'keep-alive'
88
+ });
89
+ var cc = new clientConnection(res);
90
+ //const lastEventId = req.headers['last-event-id'];
91
+ this.connections.push(cc);
92
+ this.debug();
93
+ //@ts-ignore
94
+ req.on("close", function () {
95
+ cc.close();
96
+ _this.connections = _this.connections.filter(function (s) { return s !== cc; });
97
+ _this.debug();
98
+ });
99
+ return cc;
100
+ };
101
+ //@internal
102
+ SseSubscriptionServer.prototype.debug = function () {
103
+ this.debugFileSaver(this.connections.map(function (x) { return ({
104
+ id: x.connectionId,
105
+ channels: x.channels
106
+ }); }));
107
+ };
108
+ return SseSubscriptionServer;
109
+ }());
110
+ exports.SseSubscriptionServer = SseSubscriptionServer;
111
+ var clientConnection = /** @class */ (function () {
112
+ function clientConnection(response) {
113
+ this.response = response;
114
+ this.channels = {};
115
+ this.closed = false;
116
+ this.connectionId = uuid_1.v4();
117
+ this.write(this.connectionId, "connectionId");
118
+ this.sendLiveMessage();
119
+ }
120
+ clientConnection.prototype.close = function () {
121
+ this.closed = true;
122
+ };
123
+ clientConnection.prototype.write = function (eventData, eventType) {
124
+ if (eventType === void 0) { eventType = "message"; }
125
+ var event = "event:" + eventType;
126
+ // if (id != undefined)
127
+ // event += "\nid:" + id;
128
+ this.response.write(event + "\ndata:" + eventData + "\n\n");
129
+ if (this.response.flush)
130
+ this.response.flush();
131
+ };
132
+ clientConnection.prototype.sendLiveMessage = function () {
133
+ var _this = this;
134
+ if (this.closed)
135
+ return;
136
+ this.write("", "keep-alive");
137
+ setTimeout(function () {
138
+ _this.sendLiveMessage();
139
+ }, 45000);
140
+ };
141
+ return clientConnection;
142
+ }());
143
+ exports.clientConnection = clientConnection;
package/ably.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type * as Ably from '../../node_modules/ably';
2
+ import type { SubscriptionServer } from './src/live-query/SubscriptionServer';
3
+ import type { SubscriptionClient, SubscriptionClientConnection } from './src/live-query/SubscriptionChannel';
4
+ export declare class AblySubscriptionClient implements SubscriptionClient {
5
+ private ably;
6
+ constructor(ably: Ably.Types.RealtimePromise);
7
+ openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
8
+ }
9
+ export declare class AblySubscriptionServer implements SubscriptionServer {
10
+ private ably;
11
+ constructor(ably: Ably.Types.RestPromise);
12
+ publishMessage<T>(channel: string, message: T): Promise<void>;
13
+ }
package/ably.js ADDED
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AblySubscriptionServer = exports.AblySubscriptionClient = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var AblySubscriptionClient = /** @class */ (function () {
6
+ function AblySubscriptionClient(ably) {
7
+ this.ably = ably;
8
+ }
9
+ AblySubscriptionClient.prototype.openConnection = function (onReconnect) {
10
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
11
+ var _this = this;
12
+ return tslib_1.__generator(this, function (_a) {
13
+ return [2 /*return*/, {
14
+ close: function () {
15
+ // Since we did not open the connection, we do not close it
16
+ },
17
+ subscribe: function (channel, handler) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
18
+ var myHandler;
19
+ var _this = this;
20
+ return tslib_1.__generator(this, function (_a) {
21
+ switch (_a.label) {
22
+ case 0:
23
+ myHandler = function (y) { return handler(y.data); };
24
+ return [4 /*yield*/, this.ably.channels.get(channel).subscribe(function (y) { return myHandler(y); })];
25
+ case 1:
26
+ _a.sent();
27
+ return [2 /*return*/, function () {
28
+ myHandler = function () { };
29
+ _this.ably.channels.get(channel).unsubscribe();
30
+ }];
31
+ }
32
+ });
33
+ }); }
34
+ }];
35
+ });
36
+ });
37
+ };
38
+ return AblySubscriptionClient;
39
+ }());
40
+ exports.AblySubscriptionClient = AblySubscriptionClient;
41
+ var AblySubscriptionServer = /** @class */ (function () {
42
+ function AblySubscriptionServer(ably) {
43
+ this.ably = ably;
44
+ }
45
+ AblySubscriptionServer.prototype.publishMessage = function (channel, message) {
46
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
47
+ return tslib_1.__generator(this, function (_a) {
48
+ switch (_a.label) {
49
+ case 0: return [4 /*yield*/, this.ably.channels.get(channel).publish({ data: message })];
50
+ case 1:
51
+ _a.sent();
52
+ return [2 /*return*/];
53
+ }
54
+ });
55
+ });
56
+ };
57
+ return AblySubscriptionServer;
58
+ }());
59
+ exports.AblySubscriptionServer = AblySubscriptionServer;
@@ -0,0 +1,23 @@
1
+ import { GenericResponse } from './server/index';
2
+ import { Remult } from './src/context';
3
+ import { SubscriptionServer } from './src/live-query/SubscriptionServer';
4
+ export declare class SseSubscriptionServer implements SubscriptionServer {
5
+ private canUserConnectToChannel?;
6
+ constructor(canUserConnectToChannel?: (channel: string, remult: Remult) => boolean);
7
+ publishMessage<T>(channel: string, message: any): Promise<void>;
8
+ }
9
+ export interface ResponseRequiredForSSE {
10
+ write(data: string): void;
11
+ writeHead(status: number, headers: any): void;
12
+ flush?(): void;
13
+ }
14
+ export declare class clientConnection {
15
+ response: GenericResponse & ResponseRequiredForSSE;
16
+ channels: Record<string, boolean>;
17
+ close(): void;
18
+ closed: boolean;
19
+ write(eventData: string, eventType?: string): void;
20
+ connectionId: any;
21
+ constructor(response: GenericResponse & ResponseRequiredForSSE);
22
+ sendLiveMessage(): void;
23
+ }
@@ -0,0 +1,102 @@
1
+ import { v4 as uuid } from 'uuid';
2
+ import { ConnectionNotFoundError } from './src/live-query/SseSubscriptionClient';
3
+ export class SseSubscriptionServer {
4
+ constructor(canUserConnectToChannel) {
5
+ this.canUserConnectToChannel = canUserConnectToChannel;
6
+ //@internal
7
+ this.connections = [];
8
+ //@internal
9
+ this.debugMessageFileSaver = (id, channel, message) => { };
10
+ //@internal
11
+ this.debugFileSaver = () => { };
12
+ if (!this.canUserConnectToChannel) {
13
+ this.canUserConnectToChannel = () => true;
14
+ }
15
+ }
16
+ //@internal
17
+ subscribeToChannel({ channel, clientId }, res, remult, remove = false) {
18
+ for (const c of this.connections) {
19
+ if (c.connectionId === clientId) {
20
+ if (this.canUserConnectToChannel(channel, remult)) {
21
+ if (remove)
22
+ delete c.channels[channel];
23
+ else
24
+ c.channels[channel] = true;
25
+ res.success("ok");
26
+ this.debug();
27
+ return;
28
+ }
29
+ else {
30
+ res.forbidden();
31
+ this.debug();
32
+ return;
33
+ }
34
+ }
35
+ }
36
+ res.success(ConnectionNotFoundError);
37
+ }
38
+ async publishMessage(channel, message) {
39
+ const data = JSON.stringify({ channel, data: message });
40
+ for (const sc of this.connections) {
41
+ if (sc.channels[channel]) {
42
+ this.debugMessageFileSaver(sc.connectionId, channel, message);
43
+ sc.write(data);
44
+ }
45
+ }
46
+ }
47
+ //@internal
48
+ openHttpServerStream(req, res) {
49
+ res.writeHead(200, {
50
+ 'Content-Type': 'text/event-stream',
51
+ 'Cache-Control': 'no-cache',
52
+ 'Connection': 'keep-alive'
53
+ });
54
+ const cc = new clientConnection(res);
55
+ //const lastEventId = req.headers['last-event-id'];
56
+ this.connections.push(cc);
57
+ this.debug();
58
+ //@ts-ignore
59
+ req.on("close", () => {
60
+ cc.close();
61
+ this.connections = this.connections.filter(s => s !== cc);
62
+ this.debug();
63
+ });
64
+ return cc;
65
+ }
66
+ //@internal
67
+ debug() {
68
+ this.debugFileSaver(this.connections.map(x => ({
69
+ id: x.connectionId,
70
+ channels: x.channels
71
+ })));
72
+ }
73
+ }
74
+ export class clientConnection {
75
+ constructor(response) {
76
+ this.response = response;
77
+ this.channels = {};
78
+ this.closed = false;
79
+ this.connectionId = uuid();
80
+ this.write(this.connectionId, "connectionId");
81
+ this.sendLiveMessage();
82
+ }
83
+ close() {
84
+ this.closed = true;
85
+ }
86
+ write(eventData, eventType = "message") {
87
+ let event = "event:" + eventType;
88
+ // if (id != undefined)
89
+ // event += "\nid:" + id;
90
+ this.response.write(event + "\ndata:" + eventData + "\n\n");
91
+ if (this.response.flush)
92
+ this.response.flush();
93
+ }
94
+ sendLiveMessage() {
95
+ if (this.closed)
96
+ return;
97
+ this.write("", "keep-alive");
98
+ setTimeout(() => {
99
+ this.sendLiveMessage();
100
+ }, 45000);
101
+ }
102
+ }
package/esm/ably.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type * as Ably from '../../node_modules/ably';
2
+ import type { SubscriptionServer } from './src/live-query/SubscriptionServer';
3
+ import type { SubscriptionClient, SubscriptionClientConnection } from './src/live-query/SubscriptionChannel';
4
+ export declare class AblySubscriptionClient implements SubscriptionClient {
5
+ private ably;
6
+ constructor(ably: Ably.Types.RealtimePromise);
7
+ openConnection(onReconnect: VoidFunction): Promise<SubscriptionClientConnection>;
8
+ }
9
+ export declare class AblySubscriptionServer implements SubscriptionServer {
10
+ private ably;
11
+ constructor(ably: Ably.Types.RestPromise);
12
+ publishMessage<T>(channel: string, message: T): Promise<void>;
13
+ }
package/esm/ably.js ADDED
@@ -0,0 +1,28 @@
1
+ export class AblySubscriptionClient {
2
+ constructor(ably) {
3
+ this.ably = ably;
4
+ }
5
+ async openConnection(onReconnect) {
6
+ return {
7
+ close: () => {
8
+ // Since we did not open the connection, we do not close it
9
+ },
10
+ subscribe: async (channel, handler) => {
11
+ let myHandler = (y) => handler(y.data);
12
+ await this.ably.channels.get(channel).subscribe(y => myHandler(y));
13
+ return () => {
14
+ myHandler = () => { };
15
+ this.ably.channels.get(channel).unsubscribe();
16
+ };
17
+ }
18
+ };
19
+ }
20
+ }
21
+ export class AblySubscriptionServer {
22
+ constructor(ably) {
23
+ this.ably = ably;
24
+ }
25
+ async publishMessage(channel, message) {
26
+ await this.ably.channels.get(channel).publish({ data: message });
27
+ }
28
+ }
package/esm/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/esm/index.js CHANGED
@@ -8,7 +8,7 @@ export { InMemoryDataProvider } from './src/data-providers/in-memory-database';
8
8
  export { ArrayEntityDataProvider } from './src/data-providers/array-entity-data-provider'; //V
9
9
  export { WebSqlDataProvider } from './src/data-providers/web-sql-data-provider'; //V
10
10
  export { SqlDatabase, } from './src/data-providers/sql-database'; //V
11
- export { CustomSqlFilterBuilder } from './src/filter/filter-consumer-bridge-to-sql-request';
11
+ export { CustomSqlFilterBuilder, dbNamesOf } from './src/filter/filter-consumer-bridge-to-sql-request';
12
12
  export { JsonDataProvider } from './src/data-providers/json-data-provider'; //V
13
13
  //export * from './src/data-api'; //reconsider if to make internal
14
14
  export { Controller, BackendMethod, ProgressListener } from './src/server-action';
@@ -17,8 +17,10 @@ export { IdEntity } from './src/id-entity';
17
17
  export { Sort } from './src/sort';
18
18
  export { OneToMany, CompoundIdField } from './src/column';
19
19
  export { Filter } from './src/filter/filter-interfaces';
20
- export { FilterConsumerBridgeToSqlRequest } from './src/filter/filter-consumer-bridge-to-sql-request';
21
20
  export { UrlBuilder } from './urlBuilder';
22
21
  export { Validators } from './src/validators';
23
22
  export { ValueConverters } from './src/valueConverters';
24
23
  export { remult } from './src/remult-proxy';
24
+ //export { getId } from './src/remult3/getId';
25
+ export { InMemoryLiveQueryStorage } from "./src/live-query/SubscriptionServer";
26
+ export { SubscriptionChannel } from './src/live-query/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 {};
@@ -0,0 +1,78 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { initDataProvider } from "../server/initDataProvider";
3
+ import { Remult } from "../src/context";
4
+ import { Entity, EntityBase, Fields } from "../src/remult3";
5
+ export class DataProviderLiveQueryStorage {
6
+ constructor(dataProvider) {
7
+ this.dataProvider = initDataProvider(dataProvider);
8
+ this.repo = this.dataProvider.then(dp => new Remult(dp).repo(LiveQueryStorageEntity));
9
+ }
10
+ async ensureSchema() {
11
+ await (await this.dataProvider).ensureSchema([(await this.repo).metadata]);
12
+ }
13
+ async add({ id, entityKey, data }) {
14
+ await this.repo.then(async (repo) => {
15
+ const q = await repo.findId(id, { createIfNotFound: true });
16
+ await q.assign({ entityKey, data }).save();
17
+ });
18
+ }
19
+ async remove(queryId) {
20
+ await this.repo.then(repo => repo.delete(queryId)).catch(() => { });
21
+ }
22
+ async forEach(entityKey, callback) {
23
+ const repo = await this.repo;
24
+ let d = new Date();
25
+ d.setMinutes(d.getMinutes() - 5);
26
+ const iso = d.toISOString();
27
+ for (const query of await repo.find({ where: { entityKey } })) {
28
+ if (query.lastUsedIso < iso)
29
+ await repo.delete(query);
30
+ else {
31
+ await callback({
32
+ query, setData: async (data) => {
33
+ query.data = data;
34
+ await repo.save(query);
35
+ },
36
+ });
37
+ }
38
+ }
39
+ }
40
+ async keepAliveAndReturnUnknownQueryIds(queryIds) {
41
+ const repo = await this.repo;
42
+ for (const query of await repo.find({ where: { id: queryIds } })) {
43
+ query.lastUsedIso = new Date().toISOString();
44
+ await repo.save(query);
45
+ queryIds = queryIds.filter(x => x !== query.id);
46
+ }
47
+ return queryIds;
48
+ }
49
+ }
50
+ let LiveQueryStorageEntity = class LiveQueryStorageEntity extends EntityBase {
51
+ constructor() {
52
+ super(...arguments);
53
+ this.id = '';
54
+ this.entityKey = '';
55
+ this.lastUsedIso = new Date().toISOString();
56
+ }
57
+ };
58
+ __decorate([
59
+ Fields.string(),
60
+ __metadata("design:type", Object)
61
+ ], LiveQueryStorageEntity.prototype, "id", void 0);
62
+ __decorate([
63
+ Fields.string(),
64
+ __metadata("design:type", Object)
65
+ ], LiveQueryStorageEntity.prototype, "entityKey", void 0);
66
+ __decorate([
67
+ Fields.object(),
68
+ __metadata("design:type", Object)
69
+ ], LiveQueryStorageEntity.prototype, "data", void 0);
70
+ __decorate([
71
+ Fields.string(),
72
+ __metadata("design:type", Object)
73
+ ], LiveQueryStorageEntity.prototype, "lastUsedIso", void 0);
74
+ LiveQueryStorageEntity = __decorate([
75
+ Entity(undefined, {
76
+ dbName: 'remult_live_query_storage'
77
+ })
78
+ ], LiveQueryStorageEntity);
package/esm/myLog.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function writeToLog(what: any): Promise<void>;
package/esm/myLog.js ADDED
@@ -0,0 +1,5 @@
1
+ export async function writeToLog(what) {
2
+ if (typeof what !== "string")
3
+ what = JSON.stringify(what, undefined, 2);
4
+ (await (import('fs'))).appendFileSync('./tmp/test.log', what + '\n');
5
+ }
@@ -1,4 +1,5 @@
1
- import { PoolConfig, QueryResult } from 'pg';
1
+ import { ClientBase, PoolConfig, QueryResult } from 'pg';
2
+ import { Remult } from '../src/context';
2
3
  import { EntityMetadata } from '../src/remult3';
3
4
  import { SqlCommand, SqlImplementation } from '../src/sql-command';
4
5
  import { SqlDatabase } from '../src/data-providers/sql-database';
@@ -10,10 +11,12 @@ export interface PostgresClient extends PostgresCommandSource {
10
11
  }
11
12
  export declare class PostgresDataProvider implements SqlImplementation {
12
13
  private pool;
14
+ static getDb(remult?: Remult): ClientBase;
13
15
  entityIsUsedForTheFirstTime(entity: EntityMetadata): Promise<void>;
14
16
  getLimitSqlSyntax(limit: number, offset: number): string;
15
17
  createCommand(): SqlCommand;
16
18
  constructor(pool: PostgresPool);
19
+ ensureSchema(entities: EntityMetadata<any>[]): Promise<void>;
17
20
  transaction(action: (dataProvider: SqlImplementation) => Promise<void>): Promise<void>;
18
21
  }
19
22
  export interface PostgresCommandSource {
@@ -23,6 +26,5 @@ export declare function createPostgresConnection(options?: {
23
26
  connectionString?: string;
24
27
  sslInDev?: boolean;
25
28
  configuration?: "heroku" | PoolConfig;
26
- autoCreateTables?: boolean;
27
29
  }): Promise<SqlDatabase>;
28
30
  export declare function preparePostgresQueueStorage(sql: SqlDatabase): Promise<import("../server/expressBridge").EntityQueueStorage>;
@@ -1,11 +1,19 @@
1
1
  import { Pool } from 'pg';
2
2
  import { Remult } from '../src/context';
3
- import { PostgresSchemaBuilder, verifyStructureOfAllEntities } from './schema-builder';
3
+ import { PostgresSchemaBuilder } from './schema-builder';
4
4
  import { SqlDatabase } from '../src/data-providers/sql-database';
5
5
  export class PostgresDataProvider {
6
6
  constructor(pool) {
7
7
  this.pool = pool;
8
8
  }
9
+ static getDb(remult) {
10
+ const sql = SqlDatabase.getDb(remult);
11
+ const me = sql._getSourceSql();
12
+ if (!me.pool) {
13
+ throw "the data provider is not a PostgresDataProvider";
14
+ }
15
+ return me.pool;
16
+ }
9
17
  async entityIsUsedForTheFirstTime(entity) {
10
18
  }
11
19
  getLimitSqlSyntax(limit, offset) {
@@ -14,6 +22,11 @@ export class PostgresDataProvider {
14
22
  createCommand() {
15
23
  return new PostgresBridgeToSQLCommand(this.pool);
16
24
  }
25
+ async ensureSchema(entities) {
26
+ var db = new SqlDatabase(this);
27
+ var sb = new PostgresSchemaBuilder(db);
28
+ await sb.ensureSchema(entities);
29
+ }
17
30
  async transaction(action) {
18
31
  let client = await this.pool.connect();
19
32
  try {
@@ -22,7 +35,9 @@ export class PostgresDataProvider {
22
35
  createCommand: () => new PostgresBridgeToSQLCommand(client),
23
36
  entityIsUsedForTheFirstTime: this.entityIsUsedForTheFirstTime,
24
37
  transaction: () => { throw "nested transactions not allowed"; },
25
- getLimitSqlSyntax: this.getLimitSqlSyntax
38
+ getLimitSqlSyntax: this.getLimitSqlSyntax,
39
+ //@ts-ignore
40
+ pool: client
26
41
  });
27
42
  await client.query('COMMIT');
28
43
  }
@@ -82,8 +97,6 @@ export async function createPostgresConnection(options) {
82
97
  const db = new SqlDatabase(new PostgresDataProvider(new Pool(config)));
83
98
  let remult = new Remult();
84
99
  remult.dataProvider = (db);
85
- if (options.autoCreateTables === undefined || options.autoCreateTables)
86
- await verifyStructureOfAllEntities(db, remult);
87
100
  return db;
88
101
  }
89
102
  export async function preparePostgresQueueStorage(sql) {
@@ -91,7 +104,6 @@ export async function preparePostgresQueueStorage(sql) {
91
104
  c.dataProvider = (sql);
92
105
  let JobsInQueueEntity = (await import('../server/expressBridge')).JobsInQueueEntity;
93
106
  let e = c.repo(JobsInQueueEntity);
94
- await new PostgresSchemaBuilder(sql).createIfNotExist(e.metadata);
95
- await new PostgresSchemaBuilder(sql).verifyAllColumns(e.metadata);
107
+ await sql.ensureSchema([e.metadata]);
96
108
  return new (await import('../server/expressBridge')).EntityQueueStorage(c.repo(JobsInQueueEntity));
97
109
  }