remult 0.16.5 → 0.17.0-exp.2
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.
- package/README.md +5 -27
- package/esm/index.d.ts +2 -1
- package/esm/remult-express.d.ts +32 -0
- package/esm/remult-express.js +130 -2
- package/esm/remult-fastify.js +0 -2
- package/esm/remult-knex/index.js +2 -9
- package/esm/server/expressBridge.d.ts +44 -10
- package/esm/server/expressBridge.js +27 -20
- package/esm/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -1
- package/esm/src/backend-tests/backend-database-test-setup.backend-spec.js +0 -10
- package/esm/src/backend-tests/my-test.backend-spec.js +0 -48
- package/esm/src/column.d.ts +3 -3
- package/esm/src/context.d.ts +2 -0
- package/esm/src/context.js +11 -0
- package/esm/src/data-api.d.ts +6 -2
- package/esm/src/data-api.js +17 -4
- package/esm/src/data-providers/array-entity-data-provider.js +1 -16
- package/esm/src/data-providers/rest-data-provider.d.ts +4 -0
- package/esm/src/data-providers/rest-data-provider.js +11 -7
- package/esm/src/live-query/LiveQuery.js +7 -5
- package/esm/src/live-query/LiveQueryManager.d.ts +1 -2
- package/esm/src/live-query/LiveQueryManager.js +18 -16
- package/esm/src/remult-proxy.d.ts +1 -1
- package/esm/src/remult-proxy.js +11 -9
- package/esm/src/remult3/RepositoryImplementation.d.ts +6 -3
- package/esm/src/remult3/RepositoryImplementation.js +39 -22
- package/esm/src/remult3/getId.d.ts +2 -0
- package/esm/src/remult3/getId.js +7 -0
- package/esm/src/remult3/remult3.d.ts +10 -6
- package/esm/src/server-action.js +4 -3
- package/esm/src/shared-tests/db-tests-setup.d.ts +1 -1
- package/esm/src/shared-tests/db-tests-setup.js +0 -1
- package/esm/src/sort.d.ts +1 -0
- package/esm/src/sort.js +18 -0
- package/esm/src/tests/testHelper.spec.d.ts +2 -0
- package/esm/src/tests/testHelper.spec.js +60 -57
- package/esm/src/valueConverters.js +0 -2
- package/index.d.ts +2 -1
- package/package.json +1 -1
- package/remult-express.d.ts +32 -0
- package/remult-express.js +193 -3
- package/remult-fastify.js +0 -2
- package/remult-knex/index.js +8 -16
- package/server/expressBridge.d.ts +44 -10
- package/server/expressBridge.js +37 -20
- package/src/backend-tests/backend-database-test-setup.backend-spec.d.ts +0 -1
- package/src/backend-tests/backend-database-test-setup.backend-spec.js +1 -11
- package/src/backend-tests/my-test.backend-spec.js +0 -57
- package/src/column.d.ts +3 -3
- package/src/context.d.ts +2 -0
- package/src/context.js +11 -0
- package/src/data-api.d.ts +6 -2
- package/src/data-api.js +23 -15
- package/src/data-providers/array-entity-data-provider.js +1 -16
- package/src/data-providers/rest-data-provider.d.ts +4 -0
- package/src/data-providers/rest-data-provider.js +11 -7
- package/src/live-query/LiveQuery.js +6 -4
- package/src/live-query/LiveQueryManager.d.ts +1 -2
- package/src/live-query/LiveQueryManager.js +64 -62
- package/src/remult-proxy.d.ts +1 -1
- package/src/remult-proxy.js +19 -9
- package/src/remult3/RepositoryImplementation.d.ts +6 -3
- package/src/remult3/RepositoryImplementation.js +69 -42
- package/src/remult3/getId.d.ts +2 -0
- package/src/remult3/getId.js +11 -0
- package/src/remult3/remult3.d.ts +10 -6
- package/src/server-action.js +3 -2
- package/src/shared-tests/db-tests-setup.d.ts +1 -1
- package/src/shared-tests/db-tests-setup.js +0 -1
- package/src/sort.d.ts +1 -0
- package/src/sort.js +18 -0
- package/src/tests/testHelper.spec.d.ts +2 -0
- package/src/tests/testHelper.spec.js +99 -95
- package/src/valueConverters.js +0 -2
package/esm/src/data-api.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { customUrlToken, buildFilterFromRequestParameters } from './filter/filter-interfaces';
|
|
2
2
|
import { Filter } from './filter/filter-interfaces';
|
|
3
3
|
export class DataApi {
|
|
4
|
-
constructor(repository, remult) {
|
|
4
|
+
constructor(repository, remult, liveQueryProvider) {
|
|
5
5
|
this.repository = repository;
|
|
6
6
|
this.remult = remult;
|
|
7
|
+
this.liveQueryProvider = liveQueryProvider;
|
|
7
8
|
}
|
|
8
9
|
httpGet(res, req) {
|
|
9
10
|
if (req.get("__action") == "count") {
|
|
@@ -13,7 +14,10 @@ export class DataApi {
|
|
|
13
14
|
return this.getArray(res, req);
|
|
14
15
|
}
|
|
15
16
|
httpPost(res, req, body) {
|
|
16
|
-
|
|
17
|
+
const action = req?.get("__action");
|
|
18
|
+
if (action?.startsWith("subscribe"))
|
|
19
|
+
return this.getArray(res, req, body);
|
|
20
|
+
switch (action) {
|
|
17
21
|
case "get":
|
|
18
22
|
return this.getArray(res, req, body);
|
|
19
23
|
case "count":
|
|
@@ -89,10 +93,19 @@ export class DataApi {
|
|
|
89
93
|
findOptions.limit = limit;
|
|
90
94
|
findOptions.page = +request.get("_page");
|
|
91
95
|
}
|
|
92
|
-
|
|
96
|
+
const action = request?.get("__action");
|
|
97
|
+
const r = await this.repository.find(findOptions)
|
|
93
98
|
.then(async (r) => {
|
|
94
|
-
|
|
99
|
+
return await Promise.all(r.map(async (y) => this.repository.getEntityRef(y).toApiJson()));
|
|
95
100
|
});
|
|
101
|
+
if (this.liveQueryProvider && action?.startsWith("subscribe")) {
|
|
102
|
+
response.success({
|
|
103
|
+
id: this.liveQueryProvider.subscribe(this.repository, action.split('|')[1], findOptions, this.remult, r.map(y => this.repository.getEntityRef(y).getId())),
|
|
104
|
+
result: r
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
response.success(r);
|
|
96
109
|
}
|
|
97
110
|
catch (err) {
|
|
98
111
|
response.error(err);
|
|
@@ -66,22 +66,7 @@ export class ArrayEntityDataProvider {
|
|
|
66
66
|
}
|
|
67
67
|
if (options.orderBy) {
|
|
68
68
|
rows = rows.sort((a, b) => {
|
|
69
|
-
|
|
70
|
-
for (let i = 0; i < options.orderBy.Segments.length; i++) {
|
|
71
|
-
let seg = options.orderBy.Segments[i];
|
|
72
|
-
let left = a[seg.field.key];
|
|
73
|
-
let right = b[seg.field.key];
|
|
74
|
-
if (left > right)
|
|
75
|
-
r = 1;
|
|
76
|
-
else if (left < right)
|
|
77
|
-
r = -1;
|
|
78
|
-
if (r != 0) {
|
|
79
|
-
if (seg.isDescending)
|
|
80
|
-
r *= -1;
|
|
81
|
-
return r;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return r;
|
|
69
|
+
return options.orderBy.compare(a, b);
|
|
85
70
|
});
|
|
86
71
|
}
|
|
87
72
|
rows = pageArray(rows, options);
|
|
@@ -19,6 +19,10 @@ export declare class RestEntityDataProvider implements EntityDataProvider {
|
|
|
19
19
|
translateToJson(row: any): {};
|
|
20
20
|
count(where: Filter): Promise<number>;
|
|
21
21
|
find(options: EntityDataProviderFindOptions): Promise<Array<any>>;
|
|
22
|
+
buildFindRequest(options: EntityDataProviderFindOptions): {
|
|
23
|
+
filterObject: any;
|
|
24
|
+
url: UrlBuilder;
|
|
25
|
+
};
|
|
22
26
|
update(id: any, data: any): Promise<any>;
|
|
23
27
|
delete(id: any): Promise<void>;
|
|
24
28
|
insert(data: any): Promise<any>;
|
|
@@ -55,6 +55,16 @@ export class RestEntityDataProvider {
|
|
|
55
55
|
return this.http().get(url.url).then(r => +(r.count));
|
|
56
56
|
}
|
|
57
57
|
find(options) {
|
|
58
|
+
let { filterObject, url } = this.buildFindRequest(options);
|
|
59
|
+
if (filterObject) {
|
|
60
|
+
url.add("__action", "get");
|
|
61
|
+
return this.http().post(url.url, filterObject).then(x => x.map(y => this.translateFromJson(y)));
|
|
62
|
+
}
|
|
63
|
+
else
|
|
64
|
+
return this.http().get(url.url).then(x => x.map(y => this.translateFromJson(y)));
|
|
65
|
+
;
|
|
66
|
+
}
|
|
67
|
+
buildFindRequest(options) {
|
|
58
68
|
let url = new UrlBuilder(this.url());
|
|
59
69
|
let filterObject;
|
|
60
70
|
if (options) {
|
|
@@ -82,13 +92,7 @@ export class RestEntityDataProvider {
|
|
|
82
92
|
if (options.page)
|
|
83
93
|
url.add('_page', options.page);
|
|
84
94
|
}
|
|
85
|
-
|
|
86
|
-
url.add("__action", "get");
|
|
87
|
-
return this.http().post(url.url, filterObject).then(x => x.map(y => this.translateFromJson(y)));
|
|
88
|
-
}
|
|
89
|
-
else
|
|
90
|
-
return this.http().get(url.url).then(x => x.map(y => this.translateFromJson(y)));
|
|
91
|
-
;
|
|
95
|
+
return { filterObject, url };
|
|
92
96
|
}
|
|
93
97
|
update(id, data) {
|
|
94
98
|
let result = {};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { remult as defaultRemult, Sort } from '../../index';
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
3
|
import { RestEntityDataProvider } from '../data-providers/rest-data-provider';
|
|
4
4
|
import { buildRestDataProvider } from '../context';
|
|
5
|
+
import { getId } from '../remult3/getId';
|
|
5
6
|
export const streamUrl = 'stream1';
|
|
6
7
|
class LiveQueryOnFrontEnd {
|
|
7
8
|
constructor(repo, query) {
|
|
8
9
|
this.repo = repo;
|
|
9
10
|
this.query = query;
|
|
10
|
-
this.
|
|
11
|
+
this.defaultQueryState = [];
|
|
11
12
|
this.listeners = [];
|
|
12
13
|
}
|
|
13
14
|
async setAllItems(result) {
|
|
@@ -19,6 +20,7 @@ class LiveQueryOnFrontEnd {
|
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
forListeners(what) {
|
|
23
|
+
// what(x => this.defaultQueryState = x(this.defaultQueryState));
|
|
22
24
|
for (const l of this.listeners) {
|
|
23
25
|
what(l);
|
|
24
26
|
}
|
|
@@ -41,7 +43,7 @@ class LiveQueryOnFrontEnd {
|
|
|
41
43
|
listener(items => {
|
|
42
44
|
if (!items)
|
|
43
45
|
items = [];
|
|
44
|
-
return sort(items.map(x => this.repo.
|
|
46
|
+
return sort(items.map(x => getId(this.repo.metadata, x) === message.data.oldId ? item : x));
|
|
45
47
|
});
|
|
46
48
|
});
|
|
47
49
|
break;
|
|
@@ -61,7 +63,7 @@ class LiveQueryOnFrontEnd {
|
|
|
61
63
|
this.forListeners(listener => listener(items => {
|
|
62
64
|
if (!items)
|
|
63
65
|
items = [];
|
|
64
|
-
return
|
|
66
|
+
return items.filter(x => getId(this.repo.metadata, x) !== message.data.id);
|
|
65
67
|
}));
|
|
66
68
|
break;
|
|
67
69
|
}
|
|
@@ -152,7 +154,7 @@ export class LiveQueryClient {
|
|
|
152
154
|
this.runPromise(this.provider.get(url.url).then(thenResult));
|
|
153
155
|
}
|
|
154
156
|
else {
|
|
155
|
-
onResult(x => q.
|
|
157
|
+
onResult(x => [...q.defaultQueryState]);
|
|
156
158
|
}
|
|
157
159
|
q.listeners.push(onResult);
|
|
158
160
|
onUnsubscribe = () => {
|
|
@@ -2,12 +2,11 @@ import { Remult } from '../..';
|
|
|
2
2
|
import { Repository, EntityRef, FindOptions } from '../remult3';
|
|
3
3
|
import { LiveQueryProvider } from '../data-api';
|
|
4
4
|
import { liveQueryMessage } from './LiveQuery';
|
|
5
|
-
export declare class
|
|
5
|
+
export declare class LiveQueryPublisher implements LiveQueryProvider {
|
|
6
6
|
private dispatcher;
|
|
7
7
|
constructor(dispatcher: ServerEventDispatcher);
|
|
8
8
|
subscribe(repo: Repository<any>, clientId: string, findOptions: FindOptions<any>, remult: Remult, ids: any[]): string;
|
|
9
9
|
clients: clientInfo[];
|
|
10
|
-
sendMessage(key: string, message: liveQueryMessage): void;
|
|
11
10
|
hasListeners(ref: EntityRef<any>): boolean;
|
|
12
11
|
runPromise(p: Promise<any>): void;
|
|
13
12
|
saved(ref: EntityRef<any>): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuid } from 'uuid';
|
|
2
|
-
export class
|
|
2
|
+
export class LiveQueryPublisher {
|
|
3
3
|
constructor(dispatcher) {
|
|
4
4
|
this.dispatcher = dispatcher;
|
|
5
5
|
this.clients = [];
|
|
@@ -19,15 +19,6 @@ export class LiveQueryManager {
|
|
|
19
19
|
});
|
|
20
20
|
return id;
|
|
21
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
22
|
hasListeners(ref) {
|
|
32
23
|
for (const c of this.clients) {
|
|
33
24
|
for (const q of c.queries) {
|
|
@@ -87,11 +78,22 @@ export class LiveQueryManager {
|
|
|
87
78
|
}
|
|
88
79
|
}
|
|
89
80
|
deleted(ref) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
81
|
+
const id = ref.getOriginalId();
|
|
82
|
+
for (const c of this.clients) {
|
|
83
|
+
for (const q of c.queries) {
|
|
84
|
+
if (q.repo.metadata.key === ref.metadata.key) {
|
|
85
|
+
if (q.ids.includes(id)) {
|
|
86
|
+
this.dispatcher.sendQueryMessage({
|
|
87
|
+
clientId: c.clientId, queryId: q.id, message: {
|
|
88
|
+
type: "remove",
|
|
89
|
+
data: {
|
|
90
|
+
id: id
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
96
98
|
}
|
|
97
99
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Remult } from "./context";
|
|
1
|
+
import type { Remult } from "./context";
|
|
2
2
|
export declare const remult: Remult;
|
package/esm/src/remult-proxy.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { Remult } from "./context";
|
|
2
|
-
import { RepositoryImplementation } from "./remult3";
|
|
3
|
-
let defaultRemult = new Remult();
|
|
4
1
|
/*@internal*/
|
|
5
2
|
export class RemultProxy {
|
|
6
3
|
constructor() {
|
|
7
4
|
/*@internal*/
|
|
8
|
-
this.remultFactory = () => defaultRemult;
|
|
5
|
+
this.remultFactory = () => RemultProxy.defaultRemult;
|
|
9
6
|
this.repo = (...args) => this.remultFactory().repo(...args);
|
|
10
7
|
}
|
|
8
|
+
get liveQueryProvider() { return this.remultFactory().liveQueryProvider; }
|
|
9
|
+
;
|
|
10
|
+
set liveQueryProvider(val) { this.remultFactory().liveQueryProvider = val; }
|
|
11
|
+
;
|
|
12
|
+
get _changeListener() {
|
|
13
|
+
return this.remultFactory()._changeListener;
|
|
14
|
+
}
|
|
15
|
+
set _changeListener(val) {
|
|
16
|
+
this.remultFactory()._changeListener = val;
|
|
17
|
+
}
|
|
11
18
|
call(backendMethod, self, ...args) {
|
|
12
19
|
return this.remultFactory().call(backendMethod, self, ...args);
|
|
13
20
|
}
|
|
@@ -31,10 +38,6 @@ export class RemultProxy {
|
|
|
31
38
|
clearAllCache() {
|
|
32
39
|
return this.remultFactory().clearAllCache();
|
|
33
40
|
}
|
|
34
|
-
/*@internal*/
|
|
35
|
-
resetFactory() {
|
|
36
|
-
this.remultFactory = () => defaultRemult;
|
|
37
|
-
}
|
|
38
41
|
get user() {
|
|
39
42
|
return this.remultFactory().user;
|
|
40
43
|
}
|
|
@@ -49,4 +52,3 @@ export class RemultProxy {
|
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
export const remult = new RemultProxy();
|
|
52
|
-
RepositoryImplementation.defaultRemult = remult;
|
|
@@ -5,13 +5,12 @@ import { EntityMetadata, FieldRef, FieldsRef, EntityFilter, FindOptions, Reposit
|
|
|
5
5
|
import { ClassType } from "../../classType";
|
|
6
6
|
import { Remult, Unobserve } from "../context";
|
|
7
7
|
import { entityEventListener } from "../__EntityValueProvider";
|
|
8
|
-
import { DataProvider, EntityDataProvider } from "../data-interfaces";
|
|
8
|
+
import { DataProvider, EntityDataProvider, EntityDataProviderFindOptions } from "../data-interfaces";
|
|
9
9
|
import { RefSubscriber } from ".";
|
|
10
10
|
export declare class RepositoryImplementation<entityType> implements Repository<entityType> {
|
|
11
11
|
private entity;
|
|
12
|
-
|
|
12
|
+
remult: Remult;
|
|
13
13
|
private dataProvider;
|
|
14
|
-
static defaultRemult: Remult;
|
|
15
14
|
createAfterFilter(orderBy: EntityOrderBy<entityType>, lastRow: entityType): Promise<EntityFilter<entityType>>;
|
|
16
15
|
private _info;
|
|
17
16
|
private __edp;
|
|
@@ -43,6 +42,7 @@ export declare class RepositoryImplementation<entityType> implements Repository<
|
|
|
43
42
|
save(item: Partial<OmitEB<entityType>>[]): Promise<entityType[]>;
|
|
44
43
|
save(item: Partial<OmitEB<entityType>>): Promise<entityType>;
|
|
45
44
|
find(options: FindOptions<entityType>): Promise<entityType[]>;
|
|
45
|
+
buildEntityDataProviderFindOptions(options: FindOptions<entityType>): Promise<EntityDataProviderFindOptions>;
|
|
46
46
|
private mapRawDataToResult;
|
|
47
47
|
count(where?: EntityFilter<entityType>): Promise<number>;
|
|
48
48
|
private cache;
|
|
@@ -89,6 +89,7 @@ declare abstract class rowHelperBase<T> {
|
|
|
89
89
|
copyDataToObject(): any;
|
|
90
90
|
originalValues: any;
|
|
91
91
|
saveOriginalData(): void;
|
|
92
|
+
saveMoreOriginalData(): void;
|
|
92
93
|
validate(): Promise<boolean>;
|
|
93
94
|
__validateEntity(): Promise<void>;
|
|
94
95
|
__performColumnAndEntityValidations(): Promise<void>;
|
|
@@ -106,6 +107,7 @@ export declare class rowHelperImplementation<T> extends rowHelperBase<T> impleme
|
|
|
106
107
|
get apiInsertAllowed(): boolean;
|
|
107
108
|
metadata: EntityMetadata<T>;
|
|
108
109
|
getId(): any;
|
|
110
|
+
saveMoreOriginalData(): void;
|
|
109
111
|
private _wasDeleted;
|
|
110
112
|
wasDeleted(): boolean;
|
|
111
113
|
undoChanges(): void;
|
|
@@ -118,6 +120,7 @@ export declare class rowHelperImplementation<T> extends rowHelperBase<T> impleme
|
|
|
118
120
|
delete(): Promise<void>;
|
|
119
121
|
loadDataFrom(data: any, loadItems?: FieldMetadata[]): Promise<void>;
|
|
120
122
|
id: any;
|
|
123
|
+
originalId: any;
|
|
121
124
|
getOriginalId(): any;
|
|
122
125
|
private calcServerExpression;
|
|
123
126
|
isNew(): boolean;
|
|
@@ -6,6 +6,8 @@ import { v4 as uuid } from 'uuid';
|
|
|
6
6
|
import { ValueConverters } from "../valueConverters";
|
|
7
7
|
import { filterHelper } from "../filter/filter-interfaces";
|
|
8
8
|
import { assign } from "../../assign";
|
|
9
|
+
import { remult as defaultRemult } from "../remult-proxy";
|
|
10
|
+
import { getId } from "./getId";
|
|
9
11
|
//import { remult } from "../remult-proxy";
|
|
10
12
|
let classValidatorValidate = undefined;
|
|
11
13
|
// import("class-validator".toString())
|
|
@@ -165,8 +167,10 @@ export class RepositoryImplementation {
|
|
|
165
167
|
instance[field.key] = entity[field.key];
|
|
166
168
|
}
|
|
167
169
|
let row = new rowHelperImplementation(this._info, instance, this, this.edp, this.remult, false);
|
|
168
|
-
if (id)
|
|
170
|
+
if (id) {
|
|
169
171
|
row.id = id;
|
|
172
|
+
row.originalId = id;
|
|
173
|
+
}
|
|
170
174
|
else
|
|
171
175
|
row.id = row.getId();
|
|
172
176
|
ref = row;
|
|
@@ -197,17 +201,9 @@ export class RepositoryImplementation {
|
|
|
197
201
|
}
|
|
198
202
|
async find(options) {
|
|
199
203
|
Remult.onFind(this._info, options);
|
|
200
|
-
let opt = {};
|
|
201
204
|
if (!options)
|
|
202
205
|
options = {};
|
|
203
|
-
opt =
|
|
204
|
-
if (!options.orderBy || Object.keys(options.orderBy).length === 0) {
|
|
205
|
-
options.orderBy = this._info.entityInfo.defaultOrderBy;
|
|
206
|
-
}
|
|
207
|
-
opt.where = await this.translateWhereToFilter(options.where);
|
|
208
|
-
opt.orderBy = Sort.translateOrderByToSort(this.metadata, options.orderBy);
|
|
209
|
-
opt.limit = options.limit;
|
|
210
|
-
opt.page = options.page;
|
|
206
|
+
let opt = await this.buildEntityDataProviderFindOptions(options);
|
|
211
207
|
let rawRows = await this.edp.find(opt);
|
|
212
208
|
let loadFields = undefined;
|
|
213
209
|
if (options.load)
|
|
@@ -242,6 +238,18 @@ export class RepositoryImplementation {
|
|
|
242
238
|
}
|
|
243
239
|
}
|
|
244
240
|
}
|
|
241
|
+
async buildEntityDataProviderFindOptions(options) {
|
|
242
|
+
let opt = {};
|
|
243
|
+
opt = {};
|
|
244
|
+
if (!options.orderBy || Object.keys(options.orderBy).length === 0) {
|
|
245
|
+
options.orderBy = this._info.entityInfo.defaultOrderBy;
|
|
246
|
+
}
|
|
247
|
+
opt.where = await this.translateWhereToFilter(options.where);
|
|
248
|
+
opt.orderBy = Sort.translateOrderByToSort(this.metadata, options.orderBy);
|
|
249
|
+
opt.limit = options.limit;
|
|
250
|
+
opt.page = options.page;
|
|
251
|
+
return opt;
|
|
252
|
+
}
|
|
245
253
|
async mapRawDataToResult(r, loadFields) {
|
|
246
254
|
if (!r)
|
|
247
255
|
return undefined;
|
|
@@ -622,6 +630,9 @@ class rowHelperBase {
|
|
|
622
630
|
}
|
|
623
631
|
saveOriginalData() {
|
|
624
632
|
this.originalValues = this.copyDataToObject();
|
|
633
|
+
this.saveMoreOriginalData();
|
|
634
|
+
}
|
|
635
|
+
saveMoreOriginalData() {
|
|
625
636
|
}
|
|
626
637
|
async validate() {
|
|
627
638
|
this.__clearErrorsAndReportChanged();
|
|
@@ -711,10 +722,10 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
711
722
|
get apiDeleteAllowed() { return this.remult.isAllowedForInstance(this.instance, this.metadata.options.allowApiDelete); }
|
|
712
723
|
get apiInsertAllowed() { return this.remult.isAllowedForInstance(this.instance, this.metadata.options.allowApiInsert); }
|
|
713
724
|
getId() {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
725
|
+
return getId(this.info, this.instance);
|
|
726
|
+
}
|
|
727
|
+
saveMoreOriginalData() {
|
|
728
|
+
this.originalId = this.getId();
|
|
718
729
|
}
|
|
719
730
|
wasDeleted() {
|
|
720
731
|
this._subscribers?.reportObserved();
|
|
@@ -805,6 +816,7 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
805
816
|
}
|
|
806
817
|
}
|
|
807
818
|
await this.loadDataFrom(updatedRow);
|
|
819
|
+
this.repository.remult._changeListener.saved(this);
|
|
808
820
|
if (this.info.entityInfo.saved)
|
|
809
821
|
await this.info.entityInfo.saved(this.instance);
|
|
810
822
|
this.saveOriginalData();
|
|
@@ -831,6 +843,7 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
831
843
|
this.__assertValidity();
|
|
832
844
|
try {
|
|
833
845
|
await this.edp.delete(this.id);
|
|
846
|
+
this.repository.remult._changeListener.deleted(this);
|
|
834
847
|
if (this.info.entityInfo.deleted)
|
|
835
848
|
await this.info.entityInfo.deleted(this.instance);
|
|
836
849
|
if (this.repository.listeners)
|
|
@@ -861,14 +874,10 @@ export class rowHelperImplementation extends rowHelperBase {
|
|
|
861
874
|
this.instance[col.key] = data[col.key];
|
|
862
875
|
}
|
|
863
876
|
await this.calcServerExpression();
|
|
864
|
-
|
|
865
|
-
this.id = this.repository.metadata.idMetadata.field.getId(this.instance);
|
|
866
|
-
}
|
|
867
|
-
else
|
|
868
|
-
this.id = data[this.repository.metadata.idMetadata.field.key];
|
|
877
|
+
this.id = getId(this.info, this.instance);
|
|
869
878
|
}
|
|
870
879
|
getOriginalId() {
|
|
871
|
-
return this.
|
|
880
|
+
return this.originalId;
|
|
872
881
|
}
|
|
873
882
|
async calcServerExpression() {
|
|
874
883
|
if (isBackend())
|
|
@@ -913,7 +922,7 @@ export function getFields(container, remult) {
|
|
|
913
922
|
return getControllerRef(container, remult).fields;
|
|
914
923
|
}
|
|
915
924
|
export function getControllerRef(container, remultArg) {
|
|
916
|
-
const remultVar = remultArg ||
|
|
925
|
+
const remultVar = remultArg || defaultRemult;
|
|
917
926
|
let result = container[controllerColumns];
|
|
918
927
|
if (!result)
|
|
919
928
|
result = container[entityMember];
|
|
@@ -1658,7 +1667,7 @@ export class EntityBase {
|
|
|
1658
1667
|
}
|
|
1659
1668
|
export class ControllerBase {
|
|
1660
1669
|
constructor(remult) {
|
|
1661
|
-
this.remult = remult ||
|
|
1670
|
+
this.remult = remult || defaultRemult;
|
|
1662
1671
|
}
|
|
1663
1672
|
assign(values) {
|
|
1664
1673
|
assign(this, values);
|
|
@@ -1678,6 +1687,14 @@ class QueryResultImpl {
|
|
|
1678
1687
|
this.options.pageSize = queryConfig.defaultPageSize;
|
|
1679
1688
|
}
|
|
1680
1689
|
}
|
|
1690
|
+
subscribe(onResult) {
|
|
1691
|
+
return this.repo.remult.liveQueryProvider.subscribe(this.repo, {
|
|
1692
|
+
limit: this.options.pageSize,
|
|
1693
|
+
load: this.options.load,
|
|
1694
|
+
orderBy: this.options.orderBy,
|
|
1695
|
+
where: this.options.where
|
|
1696
|
+
}, onResult);
|
|
1697
|
+
}
|
|
1681
1698
|
async getPage(page) {
|
|
1682
1699
|
if (page < 1)
|
|
1683
1700
|
page = 1;
|
|
@@ -15,7 +15,8 @@ export interface EntityRef<entityType> extends Subscribable {
|
|
|
15
15
|
wasDeleted(): boolean;
|
|
16
16
|
fields: FieldsRef<entityType>;
|
|
17
17
|
error: string;
|
|
18
|
-
getId():
|
|
18
|
+
getId(): idType<entityType>;
|
|
19
|
+
getOriginalId(): idType<entityType>;
|
|
19
20
|
repository: Repository<entityType>;
|
|
20
21
|
metadata: EntityMetadata<entityType>;
|
|
21
22
|
toApiJson(): any;
|
|
@@ -108,6 +109,11 @@ export interface EntityMetadata<entityType = any> {
|
|
|
108
109
|
getDbName(): Promise<string>;
|
|
109
110
|
}
|
|
110
111
|
export declare type OmitEB<T> = Omit<T, keyof import('./RepositoryImplementation').EntityBase>;
|
|
112
|
+
export declare type idType<entityType> = entityType extends {
|
|
113
|
+
id?: number;
|
|
114
|
+
} ? number : entityType extends {
|
|
115
|
+
id?: string;
|
|
116
|
+
} ? string : (string | number);
|
|
111
117
|
/**used to perform CRUD operations on an `entityType` */
|
|
112
118
|
export interface Repository<entityType> {
|
|
113
119
|
/** returns a result array based on the provided options */
|
|
@@ -120,11 +126,7 @@ export interface Repository<entityType> {
|
|
|
120
126
|
* */
|
|
121
127
|
findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>): Promise<entityType>;
|
|
122
128
|
/** returns the items that matches the idm the result is cached unless specified differently in the `options` parameter */
|
|
123
|
-
findId(id: entityType
|
|
124
|
-
id?: number;
|
|
125
|
-
} ? number : entityType extends {
|
|
126
|
-
id?: string;
|
|
127
|
-
} ? string : (string | number), options?: FindFirstOptionsBase<entityType>): Promise<entityType>;
|
|
129
|
+
findId(id: idType<entityType>, options?: FindFirstOptionsBase<entityType>): Promise<entityType>;
|
|
128
130
|
/** An alternative form of fetching data from the API server, which is intended for operating on large numbers of entity objects.
|
|
129
131
|
*
|
|
130
132
|
* It also has it's own paging mechanism that can be used n paging scenarios.
|
|
@@ -298,6 +300,8 @@ export interface QueryResult<entityType> {
|
|
|
298
300
|
getPage(pageNumber?: number): Promise<entityType[]>;
|
|
299
301
|
/** Performs an operation on all the items matching the query criteria */
|
|
300
302
|
forEach(what: (item: entityType) => Promise<any>): Promise<number>;
|
|
303
|
+
/**@Experimental */
|
|
304
|
+
subscribe(onResult: (reducer: (prevState: entityType[]) => entityType[]) => void): VoidFunction;
|
|
301
305
|
}
|
|
302
306
|
/** An interface used to paginating using the `query` method in the `Repository` object */
|
|
303
307
|
export interface Paginator<entityType> {
|
package/esm/src/server-action.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import { Remult, allEntities, classHelpers, ClassHelper, setControllerSettings, buildRestDataProvider } from './context';
|
|
3
3
|
import { SqlDatabase } from './data-providers/sql-database';
|
|
4
|
-
import { getEntityRef, decorateColumnSettings, getEntitySettings, getControllerRef
|
|
4
|
+
import { getEntityRef, decorateColumnSettings, getEntitySettings, getControllerRef } from './remult3';
|
|
5
|
+
import { remult } from './remult-proxy';
|
|
5
6
|
export class Action {
|
|
6
7
|
constructor(actionUrl, queue, allowed) {
|
|
7
8
|
this.actionUrl = actionUrl;
|
|
@@ -10,9 +11,9 @@ export class Action {
|
|
|
10
11
|
}
|
|
11
12
|
async run(pIn, baseUrl, http) {
|
|
12
13
|
if (baseUrl === undefined)
|
|
13
|
-
baseUrl =
|
|
14
|
+
baseUrl = remult.apiClient.url;
|
|
14
15
|
if (!http)
|
|
15
|
-
http = buildRestDataProvider(
|
|
16
|
+
http = buildRestDataProvider(remult.apiClient.httpClient);
|
|
16
17
|
let r = await http.post(baseUrl + '/' + this.actionUrl, pIn);
|
|
17
18
|
let p = r;
|
|
18
19
|
if (p && p.queuedJobId) {
|
|
@@ -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):
|
|
9
|
+
export declare function addDatabaseToTest(tester: dbTestMethodSignature): void;
|
|
10
10
|
export declare function testInMemory(key: string, what: dbTestWhatSignature, focus?: boolean): void;
|
|
11
11
|
export declare type dbTestWhatSignature = (db: {
|
|
12
12
|
db: DataProvider;
|
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;
|
|
@@ -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";
|
|
@@ -32,3 +33,4 @@ export declare class MockRestDataProvider implements DataProvider {
|
|
|
32
33
|
transaction(action: (dataProvider: DataProvider) => Promise<void>): Promise<void>;
|
|
33
34
|
supportsCustomFilter: boolean;
|
|
34
35
|
}
|
|
36
|
+
export declare function createMockHttpDataProvider(dataApi: DataApi<any>): import("c:/Repos/radweb/projects/core/src/data-interfaces").RestDataProviderHttpProvider;
|