remult 0.16.3 → 0.16.4

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 (49) hide show
  1. package/esm/remult-knex/index.js +9 -2
  2. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +1 -0
  3. package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +10 -0
  4. package/esm/src/live-query/EventSourceLiveQuery.d.ts +5 -0
  5. package/esm/src/live-query/EventSourceLiveQuery.js +48 -0
  6. package/esm/src/live-query/EventSourceLiveQueryProvider.d.ts +6 -0
  7. package/esm/src/live-query/EventSourceLiveQueryProvider.js +24 -0
  8. package/esm/src/live-query/LiveQuery.d.ts +67 -0
  9. package/esm/src/live-query/LiveQuery.js +222 -0
  10. package/esm/src/live-query/LiveQueryManager.d.ts +33 -0
  11. package/esm/src/live-query/LiveQueryManager.js +97 -0
  12. package/esm/src/shared-tests/db-tests-setup.d.ts +1 -1
  13. package/esm/src/shared-tests/db-tests-setup.js +1 -0
  14. package/esm/src/valueConverters.js +2 -0
  15. package/package.json +1 -1
  16. package/remult-knex/index.js +16 -8
  17. package/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +1 -0
  18. package/src/backend-tests/backend-database-test-setup.backend-spec.js +11 -1
  19. package/src/live-query/EventSourceLiveQuery.d.ts +5 -0
  20. package/src/live-query/EventSourceLiveQuery.js +62 -0
  21. package/src/live-query/EventSourceLiveQueryProvider.d.ts +6 -0
  22. package/src/live-query/EventSourceLiveQueryProvider.js +32 -0
  23. package/src/live-query/LiveQuery.d.ts +67 -0
  24. package/src/live-query/LiveQuery.js +305 -0
  25. package/src/live-query/LiveQueryManager.d.ts +33 -0
  26. package/src/live-query/LiveQueryManager.js +196 -0
  27. package/src/shared-tests/db-tests-setup.d.ts +1 -1
  28. package/src/shared-tests/db-tests-setup.js +1 -0
  29. package/src/valueConverters.js +2 -0
  30. package/esm/postgres/postgresColumnSyntax.d.ts +0 -2
  31. package/esm/postgres/postgresColumnSyntax.js +0 -30
  32. package/esm/remult-middleware.d.ts +0 -2
  33. package/esm/remult-middleware.js +0 -65
  34. package/esm/server/register-actions-on-server.d.ts +0 -3
  35. package/esm/server/register-actions-on-server.js +0 -24
  36. package/esm/server/register-entities-on-server.d.ts +0 -3
  37. package/esm/server/register-entities-on-server.js +0 -15
  38. package/esm/valueConverters.d.ts +0 -12
  39. package/esm/valueConverters.js +0 -169
  40. package/postgres/postgresColumnSyntax.d.ts +0 -2
  41. package/postgres/postgresColumnSyntax.js +0 -34
  42. package/remult-middleware.d.ts +0 -2
  43. package/remult-middleware.js +0 -70
  44. package/server/register-actions-on-server.d.ts +0 -3
  45. package/server/register-actions-on-server.js +0 -50
  46. package/server/register-entities-on-server.d.ts +0 -3
  47. package/server/register-entities-on-server.js +0 -19
  48. package/valueConverters.d.ts +0 -12
  49. package/valueConverters.js +0 -168
@@ -153,8 +153,15 @@ class KnexEntityDataProvider {
153
153
  }
154
154
  let insert = this.knex(e.entityName).insert(insertObject);
155
155
  if (isAutoIncrement(this.entity.idMetadata.field)) {
156
- let result = await insert.returning(this.entity.idMetadata.field.key);
157
- let newId = result[0].id;
156
+ let newId;
157
+ if (this.knex.client.config.client === 'mysql2') {
158
+ let result = await this.knex(e.entityName).insert(insertObject, this.entity.idMetadata.field.key);
159
+ newId = result[0];
160
+ }
161
+ else {
162
+ let result = await insert.returning(this.entity.idMetadata.field.key);
163
+ newId = result[0].id;
164
+ }
158
165
  resultFilter = new Filter(x => x.isEqualTo(this.entity.idMetadata.field, newId));
159
166
  }
160
167
  else
@@ -1,5 +1,6 @@
1
1
  import { dbTestWhatSignature } from "../shared-tests/db-tests-setup";
2
2
  export declare const testKnexPGSqlImpl: (key: string, what: dbTestWhatSignature, focus?: boolean) => void;
3
+ export declare const mySqlTest: import("../shared-tests/db-tests-setup").dbTestMethodSignature;
3
4
  export declare function testPostgresImplementation(key: string, what: dbTestWhatSignature, focus?: boolean): void;
4
5
  export declare function testMongo(key: string, what: dbTestWhatSignature, focus?: boolean): void;
5
6
  import '../shared-tests';
@@ -53,6 +53,16 @@ if (true)
53
53
  filename: ":memory:"
54
54
  },
55
55
  }), "sqlite3"));
56
+ export const mySqlTest = addDatabaseToTest(testKnexSqlImpl(Knex.default({
57
+ client: 'mysql2',
58
+ connection: {
59
+ user: 'root',
60
+ password: 'MASTERKEY',
61
+ host: '127.0.0.1',
62
+ database: 'test'
63
+ }
64
+ //debug: true
65
+ }), "mysql2"));
56
66
  let pg = createPostgresConnection({
57
67
  autoCreateTables: false
58
68
  });
@@ -0,0 +1,5 @@
1
+ import { LiveQueryClient } from './LiveQuery';
2
+ export declare class EventSourceLiveQuery extends LiveQueryClient {
3
+ private wrapMessage?;
4
+ constructor(wrapMessage?: (what: () => void) => void);
5
+ }
@@ -0,0 +1,48 @@
1
+ import { LiveQueryClient, streamUrl } from './LiveQuery';
2
+ import { fetchEventSource } from '@microsoft/fetch-event-source';
3
+ import { remult } from '../remult-proxy';
4
+ export class EventSourceLiveQuery extends LiveQueryClient {
5
+ constructor(wrapMessage) {
6
+ super(new EventSourceLiveQueryProvider(wrapMessage));
7
+ this.wrapMessage = wrapMessage;
8
+ }
9
+ }
10
+ class EventSourceLiveQueryProvider {
11
+ constructor(wrapMessage, url = undefined, jwtToken) {
12
+ this.wrapMessage = wrapMessage;
13
+ this.url = url;
14
+ this.jwtToken = jwtToken;
15
+ this.lastId = 0;
16
+ if (!this.wrapMessage)
17
+ this.wrapMessage = x => x();
18
+ if (!this.url) {
19
+ this.url = remult.apiClient.url + '/' + streamUrl;
20
+ }
21
+ }
22
+ openStreamAndReturnCloseFunction(clientId, onMessage) {
23
+ const ctrl = new AbortController();
24
+ const headers = {
25
+ "client-id": clientId
26
+ };
27
+ if (this.jwtToken) {
28
+ headers["Authorization"] = "Bearer " + this.jwtToken;
29
+ }
30
+ fetchEventSource(this.url, {
31
+ headers,
32
+ onmessage: message => {
33
+ const mid = +message.id;
34
+ if (mid <= this.lastId && this.lastId - mid < 10)
35
+ return;
36
+ this.lastId = mid;
37
+ console.log(message.data);
38
+ if (message.event !== 'keep-alive') {
39
+ this.wrapMessage(() => onMessage(message));
40
+ }
41
+ },
42
+ onopen: async () => {
43
+ },
44
+ signal: ctrl.signal,
45
+ });
46
+ return () => ctrl.abort();
47
+ }
48
+ }
@@ -0,0 +1,6 @@
1
+ import { LiveQueryProvider, MessageHandler } from "./LiveQuery";
2
+ export declare class EventSourceLiveQueryProvider implements LiveQueryProvider {
3
+ private wrapMessage?;
4
+ constructor(wrapMessage?: (what: () => void) => void);
5
+ openStreamAndReturnCloseFunction(clientId: string, onMessage: MessageHandler): Promise<VoidFunction>;
6
+ }
@@ -0,0 +1,24 @@
1
+ import { remult } from "../remult-proxy";
2
+ import { streamUrl } from "./LiveQuery";
3
+ export class EventSourceLiveQueryProvider {
4
+ constructor(wrapMessage) {
5
+ this.wrapMessage = wrapMessage;
6
+ if (!this.wrapMessage)
7
+ this.wrapMessage = x => x();
8
+ }
9
+ openStreamAndReturnCloseFunction(clientId, onMessage) {
10
+ const source = new EventSource(remult.apiClient.url + '/' + streamUrl + "?id=" + clientId, {
11
+ withCredentials: true
12
+ });
13
+ source.onmessage = e => {
14
+ this.wrapMessage(() => onMessage(JSON.parse(e.data)));
15
+ };
16
+ return new Promise((res) => {
17
+ source.onopen = e => {
18
+ res(() => {
19
+ source.close();
20
+ });
21
+ };
22
+ });
23
+ }
24
+ }
@@ -0,0 +1,67 @@
1
+ import { EntityOrderBy, FindOptions, Remult, Repository, RestDataProviderHttpProvider } from '../../index';
2
+ import { Allowed } from '../context';
3
+ import { ServerEventDispatcher } from './LiveQueryManager';
4
+ export declare const streamUrl = "stream1";
5
+ export interface LiveQueryProvider {
6
+ openStreamAndReturnCloseFunction(clientId: string, onMessage: MessageHandler): Promise<VoidFunction>;
7
+ }
8
+ export declare type MessageHandler = (message: {
9
+ data: any;
10
+ event: string;
11
+ }) => void;
12
+ export declare class LiveQueryClient {
13
+ lqp: LiveQueryProvider;
14
+ private provider?;
15
+ clientId: any;
16
+ private queries;
17
+ private channels;
18
+ constructor(lqp: LiveQueryProvider, provider?: RestDataProviderHttpProvider);
19
+ runPromise(p: Promise<any>): Promise<any>;
20
+ close(): void;
21
+ subscribeChannel<T>(key: string, onResult: (item: T) => void): () => void;
22
+ private closeIfNoListeners;
23
+ subscribe<entityType>(repo: Repository<entityType>, options: FindOptions<entityType>, onResult: (reducer: (prevState: entityType[]) => entityType[]) => void): () => void;
24
+ closeListener: Promise<VoidFunction>;
25
+ private openIfNoOpened;
26
+ }
27
+ export declare type listener = (message: any) => void;
28
+ export interface SubscribeToQueryArgs<entityType = any> {
29
+ entityKey: string;
30
+ orderBy?: EntityOrderBy<entityType>;
31
+ }
32
+ export declare type liveQueryMessage = {
33
+ type: "all";
34
+ data: any[];
35
+ } | {
36
+ type: "add";
37
+ data: any;
38
+ } | {
39
+ type: 'replace';
40
+ data: {
41
+ oldId: any;
42
+ item: any;
43
+ };
44
+ } | {
45
+ type: "remove";
46
+ data: {
47
+ id: any;
48
+ };
49
+ };
50
+ export interface SubscribeResult {
51
+ result: [];
52
+ id: string;
53
+ }
54
+ export interface ChannelSubscribe {
55
+ clientId: string;
56
+ channel: string;
57
+ remove: boolean;
58
+ }
59
+ export declare class AMessageChannel<messageType> {
60
+ private subscribedAllowed;
61
+ userCanSubscribe(channel: string, remult: Remult): boolean;
62
+ private key;
63
+ constructor(key: (string | ((remult: Remult) => string)), subscribedAllowed: Allowed);
64
+ send(what: messageType, remult?: Remult): void;
65
+ subscribe(client: LiveQueryClient, onValue: (value: messageType) => void, remult?: Remult): void;
66
+ dispatcher: ServerEventDispatcher;
67
+ }
@@ -0,0 +1,222 @@
1
+ import { getEntityRef, remult as defaultRemult, Sort } from '../../index';
2
+ import { v4 as uuid } from 'uuid';
3
+ import { RestEntityDataProvider } from '../data-providers/rest-data-provider';
4
+ import { buildRestDataProvider } from '../context';
5
+ export const streamUrl = 'stream1';
6
+ class LiveQueryOnFrontEnd {
7
+ constructor(repo, query) {
8
+ this.repo = repo;
9
+ this.query = query;
10
+ this.items = [];
11
+ this.listeners = [];
12
+ }
13
+ async setAllItems(result) {
14
+ const items = await Promise.all(result.map(item => this.repo.fromJson(item)));
15
+ this.forListeners(listener => {
16
+ listener(x => {
17
+ return items;
18
+ });
19
+ });
20
+ }
21
+ forListeners(what) {
22
+ for (const l of this.listeners) {
23
+ what(l);
24
+ }
25
+ }
26
+ async handle(message) {
27
+ const sort = (items) => {
28
+ if (this.query.orderBy) {
29
+ const o = Sort.translateOrderByToSort(this.repo.metadata, this.query.orderBy);
30
+ items.sort((a, b) => o.compare(a, b));
31
+ }
32
+ return items;
33
+ };
34
+ switch (message.type) {
35
+ case "all":
36
+ this.setAllItems(message.data);
37
+ break;
38
+ case "replace": {
39
+ const item = await this.repo.fromJson(message.data.item);
40
+ this.forListeners(listener => {
41
+ listener(items => {
42
+ if (!items)
43
+ items = [];
44
+ return sort(items.map(x => this.repo.getEntityRef(x).getId() === message.data.oldId ? item : x));
45
+ });
46
+ });
47
+ break;
48
+ }
49
+ case "add":
50
+ {
51
+ const item = await this.repo.fromJson(message.data.item);
52
+ this.forListeners(listener => listener(items => {
53
+ if (!items)
54
+ items = [];
55
+ items.push(item);
56
+ return sort(items);
57
+ }));
58
+ break;
59
+ }
60
+ case "remove":
61
+ this.forListeners(listener => listener(items => {
62
+ if (!items)
63
+ items = [];
64
+ return this.items.filter(x => getEntityRef(x).getId() !== message.data.id);
65
+ }));
66
+ break;
67
+ }
68
+ ;
69
+ }
70
+ }
71
+ class MessageChannel {
72
+ constructor() {
73
+ this.listeners = [];
74
+ }
75
+ async handle(message) {
76
+ for (const l of this.listeners) {
77
+ l(message);
78
+ }
79
+ }
80
+ }
81
+ export class LiveQueryClient {
82
+ constructor(lqp, provider) {
83
+ this.lqp = lqp;
84
+ this.provider = provider;
85
+ this.clientId = uuid();
86
+ this.queries = new Map();
87
+ this.channels = new Map();
88
+ }
89
+ runPromise(p) {
90
+ return p;
91
+ }
92
+ close() {
93
+ this.queries.clear();
94
+ this.channels.clear();
95
+ this.closeIfNoListeners();
96
+ }
97
+ subscribeChannel(key, onResult) {
98
+ let onUnsubscribe = () => { };
99
+ this.openIfNoOpened().then(() => {
100
+ let q = this.channels.get(key);
101
+ if (!q) {
102
+ this.channels.set(key, q = new MessageChannel());
103
+ this.provider.post(defaultRemult.apiClient.url + '/' + streamUrl, {
104
+ channel: key,
105
+ clientId: this.clientId,
106
+ remove: false
107
+ });
108
+ }
109
+ else {
110
+ }
111
+ q.listeners.push(onResult);
112
+ onUnsubscribe = () => {
113
+ q.listeners.splice(q.listeners.indexOf(onResult), 1);
114
+ if (q.listeners.length == 0) {
115
+ this.channels.delete(key);
116
+ }
117
+ this.closeIfNoListeners();
118
+ };
119
+ });
120
+ return () => {
121
+ onUnsubscribe();
122
+ };
123
+ }
124
+ closeIfNoListeners() {
125
+ if (this.queries.size === 0 && this.channels.size === 0) {
126
+ this.runPromise(this.closeListener.then(x => x()));
127
+ this.closeListener = undefined;
128
+ }
129
+ }
130
+ subscribe(repo, options, onResult) {
131
+ let alive = true;
132
+ let onUnsubscribe = () => { };
133
+ this.runPromise(this.openIfNoOpened().then(() => repo.buildEntityDataProviderFindOptions(options)
134
+ .then(opts => {
135
+ if (!alive)
136
+ return;
137
+ const { url, filterObject } = new RestEntityDataProvider(() => defaultRemult.apiClient.url + '/' + repo.metadata.key, () => this.provider, repo.metadata)
138
+ .buildFindRequest(opts);
139
+ const eventTypeKey = JSON.stringify({ url, filterObject });
140
+ let q = this.queries.get(eventTypeKey);
141
+ if (!q) {
142
+ this.queries.set(eventTypeKey, q = new LiveQueryOnFrontEnd(repo, { entityKey: repo.metadata.key, orderBy: options.orderBy }));
143
+ url.add("__action", 'subscribe|' + this.clientId);
144
+ const thenResult = (r) => {
145
+ this.runPromise(q.setAllItems(r.result));
146
+ q.id = r.id;
147
+ };
148
+ if (filterObject) {
149
+ this.runPromise(this.provider.post(url.url, filterObject).then(thenResult));
150
+ }
151
+ else
152
+ this.runPromise(this.provider.get(url.url).then(thenResult));
153
+ }
154
+ else {
155
+ onResult(x => q.items);
156
+ }
157
+ q.listeners.push(onResult);
158
+ onUnsubscribe = () => {
159
+ q.listeners.splice(q.listeners.indexOf(onResult), 1);
160
+ if (q.listeners.length == 0) {
161
+ this.queries.delete(eventTypeKey);
162
+ }
163
+ this.closeIfNoListeners();
164
+ };
165
+ })));
166
+ return () => {
167
+ alive = false;
168
+ onUnsubscribe();
169
+ };
170
+ }
171
+ openIfNoOpened() {
172
+ if (!this.provider) {
173
+ this.provider = buildRestDataProvider(defaultRemult.apiClient.httpClient);
174
+ }
175
+ if (!this.closeListener)
176
+ return this.runPromise(this.closeListener = this.lqp.openStreamAndReturnCloseFunction(this.clientId, message => {
177
+ for (const q of this.queries.values()) {
178
+ if (q.id === message.event) {
179
+ this.runPromise(q.handle(message.data));
180
+ }
181
+ }
182
+ const channel = this.channels.get(message.event);
183
+ if (channel) {
184
+ channel.handle(message.data);
185
+ }
186
+ }));
187
+ return this.closeListener;
188
+ }
189
+ }
190
+ export class AMessageChannel {
191
+ constructor(key, subscribedAllowed) {
192
+ this.subscribedAllowed = subscribedAllowed;
193
+ if (typeof key === "string")
194
+ this.key = () => key;
195
+ else
196
+ this.key = key;
197
+ }
198
+ userCanSubscribe(channel, remult) {
199
+ if (!remult)
200
+ remult = defaultRemult;
201
+ if (channel == this.key(remult) && remult.isAllowed(this.subscribedAllowed))
202
+ return true;
203
+ return false;
204
+ }
205
+ send(what, remult) {
206
+ if (!this.dispatcher)
207
+ throw new Error("Message couldn't be send since no dispatcher was set");
208
+ this.dispatcher.sendChannelMessage(this.key(remult || defaultRemult), what);
209
+ }
210
+ subscribe(client, onValue, remult) {
211
+ client.subscribeChannel(this.key(remult || defaultRemult), onValue);
212
+ }
213
+ }
214
+ /*
215
+ [V] use entity normal http route for this - with __action.
216
+ [] move id from header to url in stream registration.
217
+ [] transaction accumulates messages.
218
+ [] on unsubscribe, also unsubscribe on server
219
+ [] consolidate channel & query
220
+ [] fix stream api url on server
221
+ [] remove client id from header
222
+ */
@@ -0,0 +1,33 @@
1
+ import { Remult } from '../..';
2
+ import { Repository, EntityRef, FindOptions } from '../remult3';
3
+ import { LiveQueryProvider } from '../data-api';
4
+ import { liveQueryMessage } from './LiveQuery';
5
+ export declare class LiveQueryManager implements LiveQueryProvider {
6
+ private dispatcher;
7
+ constructor(dispatcher: ServerEventDispatcher);
8
+ subscribe(repo: Repository<any>, clientId: string, findOptions: FindOptions<any>, remult: Remult, ids: any[]): string;
9
+ clients: clientInfo[];
10
+ sendMessage(key: string, message: liveQueryMessage): void;
11
+ hasListeners(ref: EntityRef<any>): boolean;
12
+ runPromise(p: Promise<any>): void;
13
+ saved(ref: EntityRef<any>): void;
14
+ deleted(ref: EntityRef<any>): void;
15
+ }
16
+ export interface clientInfo {
17
+ clientId: string;
18
+ queries: ({
19
+ id: string;
20
+ repo: Repository<any>;
21
+ findOptions: FindOptions<any>;
22
+ ids: any[];
23
+ })[];
24
+ }
25
+ export interface ServerEventDispatcher {
26
+ sendQueryMessage(message: ServerEventMessage): void;
27
+ sendChannelMessage<T>(channel: string, message: any): void;
28
+ }
29
+ export interface ServerEventMessage {
30
+ clientId: string;
31
+ queryId: string;
32
+ message: liveQueryMessage;
33
+ }
@@ -0,0 +1,97 @@
1
+ import { v4 as uuid } from 'uuid';
2
+ export class LiveQueryManager {
3
+ constructor(dispatcher) {
4
+ this.dispatcher = dispatcher;
5
+ this.clients = [];
6
+ }
7
+ subscribe(repo, clientId, findOptions, remult, ids) {
8
+ let client = this.clients.find(c => c.clientId === clientId);
9
+ if (!client) {
10
+ this.clients.push(client = { clientId: clientId, queries: [] });
11
+ }
12
+ const id = uuid();
13
+ console.log({ ids });
14
+ client.queries.push({
15
+ id,
16
+ findOptions: findOptions,
17
+ repo,
18
+ ids
19
+ });
20
+ return id;
21
+ }
22
+ sendMessage(key, message) {
23
+ for (const c of this.clients) {
24
+ for (const q of c.queries) {
25
+ if (q.repo.metadata.key === key) {
26
+ this.dispatcher.sendQueryMessage({ clientId: c.clientId, queryId: q.id, message });
27
+ }
28
+ }
29
+ }
30
+ }
31
+ hasListeners(ref) {
32
+ for (const c of this.clients) {
33
+ for (const q of c.queries) {
34
+ if (q.repo.metadata.key === ref.metadata.key)
35
+ return true;
36
+ }
37
+ }
38
+ return false;
39
+ }
40
+ runPromise(p) {
41
+ }
42
+ //TODO - reconsider usage of zone
43
+ saved(ref) {
44
+ const isNew = ref.isNew();
45
+ const origId = isNew ? ref.getId() : ref.getOriginalId();
46
+ for (const c of this.clients) {
47
+ for (const q of c.queries) {
48
+ if (q.repo.metadata.key === ref.metadata.key) {
49
+ this.runPromise(q.repo.find(q.findOptions).then(currentItems => {
50
+ const currentIds = currentItems.map(x => q.repo.getEntityRef(x).getId());
51
+ const sendMessage = (message) => {
52
+ console.log({ message: message.type });
53
+ this.dispatcher.sendQueryMessage({ clientId: c.clientId, queryId: q.id, message });
54
+ };
55
+ console.log({ ids: q.ids, currentIds });
56
+ for (const id of q.ids.filter(y => !currentIds.includes(y))) {
57
+ if (id != origId || !currentIds.includes(ref.getId()))
58
+ sendMessage({
59
+ type: "remove",
60
+ data: {
61
+ id: id
62
+ }
63
+ });
64
+ }
65
+ for (const item of currentItems) {
66
+ const itemRef = q.repo.getEntityRef(item);
67
+ if (itemRef.getId() == ref.getId() && q.ids.includes(origId)) {
68
+ sendMessage({
69
+ type: "replace",
70
+ data: {
71
+ oldId: origId,
72
+ item: itemRef.toApiJson()
73
+ }
74
+ });
75
+ }
76
+ else if (!q.ids.includes(itemRef.getId())) {
77
+ sendMessage({
78
+ type: "add",
79
+ data: { item: itemRef.toApiJson() }
80
+ });
81
+ }
82
+ }
83
+ q.ids = currentIds;
84
+ }));
85
+ }
86
+ }
87
+ }
88
+ }
89
+ deleted(ref) {
90
+ if (!this.hasListeners(ref))
91
+ return;
92
+ this.sendMessage(ref.metadata.key, {
93
+ type: "remove",
94
+ data: { id: ref.getId() }
95
+ });
96
+ }
97
+ }
@@ -6,7 +6,7 @@ import { CategoriesForTesting } from "../tests/remult-3-entities";
6
6
  import { Status } from "../tests/testModel/models";
7
7
  export declare function itWithFocus(key: string, what: () => Promise<void>, focus?: boolean): void;
8
8
  export declare function testAll(key: string, what: dbTestWhatSignature, focus?: boolean): void;
9
- export declare function addDatabaseToTest(tester: dbTestMethodSignature): void;
9
+ export declare function addDatabaseToTest(tester: dbTestMethodSignature): dbTestMethodSignature;
10
10
  export declare function testInMemory(key: string, what: dbTestWhatSignature, focus?: boolean): void;
11
11
  export declare type dbTestWhatSignature = (db: {
12
12
  db: DataProvider;
@@ -22,6 +22,7 @@ export function addDatabaseToTest(tester) {
22
22
  test(tester);
23
23
  }
24
24
  databasesTesters.push(tester);
25
+ return tester;
25
26
  }
26
27
  export function testInMemory(key, what, focus = false) {
27
28
  itWithFocus(key + " - in memory", async () => {
@@ -100,6 +100,8 @@ ValueConverters.Boolean = {
100
100
  fromJson: value => {
101
101
  if (typeof value === "boolean")
102
102
  return value;
103
+ if (value === 1)
104
+ return true;
103
105
  if (value !== undefined && value !== null) {
104
106
  return value.toString().trim().toLowerCase() == 'true';
105
107
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "remult",
3
- "version": "0.16.3",
3
+ "version": "0.16.4",
4
4
  "description": "A CRUD framework for full-stack TypeScript",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -257,7 +257,7 @@ var KnexEntityDataProvider = /** @class */ (function () {
257
257
  };
258
258
  KnexEntityDataProvider.prototype.insert = function (data) {
259
259
  return tslib_1.__awaiter(this, void 0, void 0, function () {
260
- var e, resultFilter, insertObject, _a, _b, x, v, key, e_3_1, insert, result, newId_1;
260
+ var e, resultFilter, insertObject, _a, _b, x, v, key, e_3_1, insert, newId_1, result, result;
261
261
  var e_3, _c;
262
262
  var _this = this;
263
263
  return tslib_1.__generator(this, function (_d) {
@@ -304,18 +304,26 @@ var KnexEntityDataProvider = /** @class */ (function () {
304
304
  return [7 /*endfinally*/];
305
305
  case 10:
306
306
  insert = this.knex(e.entityName).insert(insertObject);
307
- if (!remult3_1.isAutoIncrement(this.entity.idMetadata.field)) return [3 /*break*/, 12];
308
- return [4 /*yield*/, insert.returning(this.entity.idMetadata.field.key)];
307
+ if (!remult3_1.isAutoIncrement(this.entity.idMetadata.field)) return [3 /*break*/, 15];
308
+ if (!(this.knex.client.config.client === 'mysql2')) return [3 /*break*/, 12];
309
+ return [4 /*yield*/, this.knex(e.entityName).insert(insertObject, this.entity.idMetadata.field.key)];
309
310
  case 11:
310
311
  result = _d.sent();
311
- newId_1 = result[0].id;
312
- resultFilter = new filter_interfaces_1.Filter(function (x) { return x.isEqualTo(_this.entity.idMetadata.field, newId_1); });
312
+ newId_1 = result[0];
313
313
  return [3 /*break*/, 14];
314
- case 12: return [4 /*yield*/, insert];
314
+ case 12: return [4 /*yield*/, insert.returning(this.entity.idMetadata.field.key)];
315
315
  case 13:
316
- _d.sent();
316
+ result = _d.sent();
317
+ newId_1 = result[0].id;
317
318
  _d.label = 14;
318
- case 14: return [2 /*return*/, this.find({ where: resultFilter }).then(function (y) {
319
+ case 14:
320
+ resultFilter = new filter_interfaces_1.Filter(function (x) { return x.isEqualTo(_this.entity.idMetadata.field, newId_1); });
321
+ return [3 /*break*/, 17];
322
+ case 15: return [4 /*yield*/, insert];
323
+ case 16:
324
+ _d.sent();
325
+ _d.label = 17;
326
+ case 17: return [2 /*return*/, this.find({ where: resultFilter }).then(function (y) {
319
327
  return y[0];
320
328
  })];
321
329
  }
@@ -1,5 +1,6 @@
1
1
  import { dbTestWhatSignature } from "../shared-tests/db-tests-setup";
2
2
  export declare const testKnexPGSqlImpl: (key: string, what: dbTestWhatSignature, focus?: boolean) => void;
3
+ export declare const mySqlTest: import("../shared-tests/db-tests-setup").dbTestMethodSignature;
3
4
  export declare function testPostgresImplementation(key: string, what: dbTestWhatSignature, focus?: boolean): void;
4
5
  export declare function testMongo(key: string, what: dbTestWhatSignature, focus?: boolean): void;
5
6
  import '../shared-tests';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.testMongo = exports.testPostgresImplementation = exports.testKnexPGSqlImpl = void 0;
3
+ exports.testMongo = exports.testPostgresImplementation = exports.mySqlTest = exports.testKnexPGSqlImpl = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var context_1 = require("../context");
6
6
  var remult_knex_1 = require("../../remult-knex");
@@ -87,6 +87,16 @@ if (true)
87
87
  filename: ":memory:"
88
88
  },
89
89
  }), "sqlite3"));
90
+ exports.mySqlTest = db_tests_setup_1.addDatabaseToTest(testKnexSqlImpl(Knex.default({
91
+ client: 'mysql2',
92
+ connection: {
93
+ user: 'root',
94
+ password: 'MASTERKEY',
95
+ host: '127.0.0.1',
96
+ database: 'test'
97
+ }
98
+ //debug: true
99
+ }), "mysql2"));
90
100
  var pg = postgres_1.createPostgresConnection({
91
101
  autoCreateTables: false
92
102
  });
@@ -0,0 +1,5 @@
1
+ import { LiveQueryClient } from './LiveQuery';
2
+ export declare class EventSourceLiveQuery extends LiveQueryClient {
3
+ private wrapMessage?;
4
+ constructor(wrapMessage?: (what: () => void) => void);
5
+ }