remult 0.23.2 → 0.23.3
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/esm/graphql.js +2 -1
- package/esm/remult-knex/index.js +8 -0
- package/esm/remult-mongo.js +10 -4
- package/esm/src/context.js +0 -2
- package/esm/src/data-api.js +1 -0
- package/esm/src/data-providers/array-entity-data-provider.js +14 -0
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.d.ts +1 -0
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +9 -0
- package/esm/src/filter/filter-interfaces.d.ts +2 -0
- package/esm/src/filter/filter-interfaces.js +18 -0
- package/esm/src/live-query/SubscriptionServer.js +0 -1
- package/esm/src/remult3/RepositoryImplementation.js +1 -2
- package/esm/src/remult3/__updateEntityBasedOnWhere.js +1 -0
- package/esm/src/remult3/remult3.d.ts +10 -9
- package/esm/src/remult3/remult3.js +55 -38
- package/graphql.js +2 -1
- package/package.json +1 -1
- package/remult-knex/index.js +13 -0
- package/remult-mongo.js +14 -4
- package/src/context.js +0 -2
- package/src/data-api.js +1 -0
- package/src/data-providers/array-entity-data-provider.js +14 -0
- package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +1 -0
- package/src/filter/filter-consumer-bridge-to-sql-request.js +13 -0
- package/src/filter/filter-interfaces.d.ts +2 -0
- package/src/filter/filter-interfaces.js +21 -0
- package/src/live-query/SubscriptionServer.js +1 -4
- package/src/remult3/RepositoryImplementation.js +1 -2
- package/src/remult3/__updateEntityBasedOnWhere.js +1 -0
- package/src/remult3/remult3.d.ts +10 -9
- package/src/remult3/remult3.js +55 -38
package/esm/graphql.js
CHANGED
|
@@ -88,7 +88,7 @@ export function remultGraphql(options) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
if (whereType === 'String') {
|
|
91
|
-
for (const operator of ['contains']) {
|
|
91
|
+
for (const operator of ['contains', 'notContains']) {
|
|
92
92
|
const field = {
|
|
93
93
|
key: operator,
|
|
94
94
|
value: whereType,
|
|
@@ -820,6 +820,7 @@ export function translateWhereToRestBody(fields, { where }) {
|
|
|
820
820
|
tr('nin', (x) => (result[field.key + '.ne'] = x));
|
|
821
821
|
tr('eq', (x) => (result[field.key] = x));
|
|
822
822
|
tr('contains', (x) => (result[field.key + '.contains'] = x));
|
|
823
|
+
tr('notContains', (x) => (result[field.key + '.notContains'] = x));
|
|
823
824
|
}
|
|
824
825
|
}
|
|
825
826
|
if (where.OR) {
|
package/esm/remult-knex/index.js
CHANGED
|
@@ -296,6 +296,14 @@ class FilterConsumerBridgeToKnexRequest {
|
|
|
296
296
|
"%')"));
|
|
297
297
|
this.promises.push((async () => { })());
|
|
298
298
|
}
|
|
299
|
+
notContainsCaseInsensitive(col, val) {
|
|
300
|
+
this.result.push((b) => b.whereRaw('not lower (' +
|
|
301
|
+
b.client.ref(this.nameProvider.$dbNameOf(col)) +
|
|
302
|
+
") like lower ('%" +
|
|
303
|
+
val.replace(/'/g, "''") +
|
|
304
|
+
"%')"));
|
|
305
|
+
this.promises.push((async () => { })());
|
|
306
|
+
}
|
|
299
307
|
add(col, val, operator) {
|
|
300
308
|
this.result.push((b) => b.where(this.nameProvider.$dbNameOf(col), operator, translateValueAndHandleArrayAndHandleArray(col, val)));
|
|
301
309
|
}
|
package/esm/remult-mongo.js
CHANGED
|
@@ -246,10 +246,16 @@ class FilterConsumerBridgeToMongo {
|
|
|
246
246
|
}
|
|
247
247
|
containsCaseInsensitive(col, val) {
|
|
248
248
|
this.add(col, val, '$regex', { $options: 'i' });
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
}
|
|
250
|
+
notContainsCaseInsensitive(col, val) {
|
|
251
|
+
this.result.push(() => ({
|
|
252
|
+
[this.nameProvider.$dbNameOf(col)]: {
|
|
253
|
+
$not: {
|
|
254
|
+
$regex: isNull(val) ? val : toDb(col, val),
|
|
255
|
+
$options: 'i',
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
}));
|
|
253
259
|
}
|
|
254
260
|
add(col, val, operator, moreOptions) {
|
|
255
261
|
this.result.push(() => ({
|
package/esm/src/context.js
CHANGED
|
@@ -286,5 +286,3 @@ class transactionLiveQueryPublisher {
|
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
|
-
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
290
|
-
//y2 - require filter argument - and perform validation checks for it - site, id etc.. changelog, status changes etc...,
|
package/esm/src/data-api.js
CHANGED
|
@@ -274,4 +274,18 @@ class FilterConsumerBridgeToObject {
|
|
|
274
274
|
if (s.toLowerCase().indexOf(val) < 0)
|
|
275
275
|
this.ok = false;
|
|
276
276
|
}
|
|
277
|
+
notContainsCaseInsensitive(col, val) {
|
|
278
|
+
let v = this.row[this.dbNames.$dbNameOf(col)];
|
|
279
|
+
if (!v) {
|
|
280
|
+
this.ok = false;
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
let s = '' + v;
|
|
284
|
+
if (val)
|
|
285
|
+
val = col.valueConverter.toJson(val);
|
|
286
|
+
if (val)
|
|
287
|
+
val = val.toString().toLowerCase();
|
|
288
|
+
if (s.toLowerCase().indexOf(val) >= 0)
|
|
289
|
+
this.ok = false;
|
|
290
|
+
}
|
|
277
291
|
}
|
|
@@ -23,6 +23,7 @@ export declare class FilterConsumerBridgeToSqlRequest implements FilterConsumer
|
|
|
23
23
|
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
24
24
|
isLessThan(col: FieldMetadata, val: any): void;
|
|
25
25
|
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
26
|
+
notContainsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
26
27
|
private add;
|
|
27
28
|
private addToWhere;
|
|
28
29
|
databaseCustom(databaseCustom: CustomSqlFilterObject): void;
|
|
@@ -93,6 +93,15 @@ export class FilterConsumerBridgeToSqlRequest {
|
|
|
93
93
|
"%')");
|
|
94
94
|
})());
|
|
95
95
|
}
|
|
96
|
+
notContainsCaseInsensitive(col, val) {
|
|
97
|
+
this.promises.push((async () => {
|
|
98
|
+
this.addToWhere('not lower (' +
|
|
99
|
+
this.nameProvider.$dbNameOf(col) +
|
|
100
|
+
") like lower ('%" +
|
|
101
|
+
val.replace(/'/g, "''") +
|
|
102
|
+
"%')");
|
|
103
|
+
})());
|
|
104
|
+
}
|
|
96
105
|
add(col, val, operator) {
|
|
97
106
|
this.promises.push((async () => {
|
|
98
107
|
let x = this.nameProvider.$dbNameOf(col) +
|
|
@@ -25,6 +25,7 @@ export interface FilterConsumer {
|
|
|
25
25
|
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
26
26
|
isLessThan(col: FieldMetadata, val: any): void;
|
|
27
27
|
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
28
|
+
notContainsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
28
29
|
isIn(col: FieldMetadata, val: any[]): void;
|
|
29
30
|
custom(key: string, customItem: any): void;
|
|
30
31
|
databaseCustom(databaseCustom: any): void;
|
|
@@ -58,6 +59,7 @@ export declare class FilterSerializer implements FilterConsumer {
|
|
|
58
59
|
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
59
60
|
isLessThan(col: FieldMetadata, val: any): void;
|
|
60
61
|
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
62
|
+
notContainsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
61
63
|
}
|
|
62
64
|
export declare function entityFilterToJson<T>(entityDefs: EntityMetadata<T>, where: EntityFilter<T>): any;
|
|
63
65
|
export declare function buildFilterFromRequestParameters(entity: EntityMetadata, filterInfo: {
|
|
@@ -101,6 +101,10 @@ export class Filter {
|
|
|
101
101
|
found = true;
|
|
102
102
|
result.push(fh.contains(element));
|
|
103
103
|
break;
|
|
104
|
+
case '$notContains':
|
|
105
|
+
found = true;
|
|
106
|
+
result.push(fh.notContains(element));
|
|
107
|
+
break;
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
110
|
}
|
|
@@ -171,6 +175,9 @@ class filterHelper {
|
|
|
171
175
|
contains(val) {
|
|
172
176
|
return new Filter((add) => add.containsCaseInsensitive(this.metadata, val));
|
|
173
177
|
}
|
|
178
|
+
notContains(val) {
|
|
179
|
+
return new Filter((add) => add.notContainsCaseInsensitive(this.metadata, val));
|
|
180
|
+
}
|
|
174
181
|
isLessThan(val) {
|
|
175
182
|
val = this.processVal(val);
|
|
176
183
|
return new Filter((add) => add.isLessThan(this.metadata, val));
|
|
@@ -237,6 +244,9 @@ class manyToOneFilterHelper {
|
|
|
237
244
|
contains(val) {
|
|
238
245
|
throw new Error('Invalid for Many To One Relation Field');
|
|
239
246
|
}
|
|
247
|
+
notContains(val) {
|
|
248
|
+
throw new Error('Invalid for Many To One Relation Field');
|
|
249
|
+
}
|
|
240
250
|
isLessThan(val) {
|
|
241
251
|
throw new Error('Invalid for Many To One Relation Field');
|
|
242
252
|
}
|
|
@@ -383,6 +393,9 @@ export class FilterSerializer {
|
|
|
383
393
|
containsCaseInsensitive(col, val) {
|
|
384
394
|
this.add(col.key + '.contains', val);
|
|
385
395
|
}
|
|
396
|
+
notContainsCaseInsensitive(col, val) {
|
|
397
|
+
this.add(col.key + '.notContains', val);
|
|
398
|
+
}
|
|
386
399
|
}
|
|
387
400
|
export function entityFilterToJson(entityDefs, where) {
|
|
388
401
|
if (!where)
|
|
@@ -452,6 +465,7 @@ export function buildFilterFromRequestParameters(entity, filterInfo) {
|
|
|
452
465
|
}
|
|
453
466
|
}
|
|
454
467
|
addFilter('.contains', (val) => ({ $contains: val }), false, true);
|
|
468
|
+
addFilter('.notContains', (val) => ({ $notContains: val }), false, true);
|
|
455
469
|
});
|
|
456
470
|
let val = filterInfo.get('OR');
|
|
457
471
|
if (val) {
|
|
@@ -555,6 +569,9 @@ class customTranslator {
|
|
|
555
569
|
containsCaseInsensitive(col, val) {
|
|
556
570
|
this.commands.push((x) => x.containsCaseInsensitive(col, val));
|
|
557
571
|
}
|
|
572
|
+
notContainsCaseInsensitive(col, val) {
|
|
573
|
+
this.commands.push((x) => x.notContainsCaseInsensitive(col, val));
|
|
574
|
+
}
|
|
558
575
|
isIn(col, val) {
|
|
559
576
|
this.commands.push((x) => x.isIn(col, val));
|
|
560
577
|
}
|
|
@@ -587,6 +604,7 @@ export function __updateEntityBasedOnWhere(entityDefs, where, r) {
|
|
|
587
604
|
custom: emptyFunction,
|
|
588
605
|
databaseCustom: emptyFunction,
|
|
589
606
|
containsCaseInsensitive: emptyFunction,
|
|
607
|
+
notContainsCaseInsensitive: emptyFunction,
|
|
590
608
|
isDifferentFrom: emptyFunction,
|
|
591
609
|
isEqualTo: (col, val) => {
|
|
592
610
|
r[col.key] = val;
|
|
@@ -12,7 +12,6 @@ export class LiveQueryPublisher {
|
|
|
12
12
|
runPromise(p) { }
|
|
13
13
|
debugFileSaver = (x) => { };
|
|
14
14
|
async itemChanged(entityKey, changes) {
|
|
15
|
-
//TODO 2 - optimize so that the user will get their messages first. Based on user id
|
|
16
15
|
await this.liveQueryStorage().forEach(entityKey, async ({ query: q, setData }) => {
|
|
17
16
|
let query = { ...q.data };
|
|
18
17
|
await this.performWithContext(query.requestJson, entityKey, async (repo) => {
|
|
@@ -143,7 +143,6 @@ export class RepositoryImplementation {
|
|
|
143
143
|
this.idCache.set(id, row);
|
|
144
144
|
return await row;
|
|
145
145
|
}
|
|
146
|
-
//TODO2 - Used to prevent unnecessary many to one relations
|
|
147
146
|
addToCache(item) {
|
|
148
147
|
if (item)
|
|
149
148
|
this.idCache.set(this.getEntityRef(item).getId() + '', item);
|
|
@@ -1804,7 +1803,7 @@ class EntityFullInfo {
|
|
|
1804
1803
|
}
|
|
1805
1804
|
get apiReadAllowed() {
|
|
1806
1805
|
if (this.options.allowApiRead === undefined)
|
|
1807
|
-
return true;
|
|
1806
|
+
return true;
|
|
1808
1807
|
return this.remult.isAllowed(this.options.allowApiRead);
|
|
1809
1808
|
}
|
|
1810
1809
|
apiDeleteAllowed(item) {
|
|
@@ -7,6 +7,7 @@ export function __updateEntityBasedOnWhere(entityDefs, where, r) {
|
|
|
7
7
|
custom: emptyFunction,
|
|
8
8
|
databaseCustom: emptyFunction,
|
|
9
9
|
containsCaseInsensitive: emptyFunction,
|
|
10
|
+
notContainsCaseInsensitive: emptyFunction,
|
|
10
11
|
isDifferentFrom: emptyFunction,
|
|
11
12
|
isEqualTo: (col, val) => {
|
|
12
13
|
r[col.key] = val;
|
|
@@ -388,6 +388,7 @@ export type ComparisonValueFilter<valueType> = ValueFilter<valueType> & {
|
|
|
388
388
|
};
|
|
389
389
|
export interface ContainsStringValueFilter {
|
|
390
390
|
$contains?: string;
|
|
391
|
+
$notContains?: string;
|
|
391
392
|
}
|
|
392
393
|
export type IdFilter<valueType> = ValueFilter<valueType> | {
|
|
393
394
|
$id: ValueFilter<valueType extends {
|
|
@@ -579,21 +580,21 @@ export type ClassFieldDecorator<entityType, valueType> = (target: any, context:
|
|
|
579
580
|
remult.apiClient.httpClient = (
|
|
580
581
|
input: RequestInfo | URL,
|
|
581
582
|
init?: RequestInit
|
|
582
|
-
) => {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
583
|
+
) => {
|
|
584
|
+
return fetch(input, {
|
|
585
|
+
...init,
|
|
586
|
+
headers: {
|
|
587
|
+
authorization: 'Bearer ' + sessionStorage.sessionId,
|
|
588
|
+
},
|
|
589
|
+
cache: 'no-store',
|
|
590
|
+
})
|
|
590
591
|
}
|
|
591
592
|
|
|
592
593
|
&&
|
|
593
594
|
remult.apiClient.url='localhost:3007/api
|
|
594
595
|
|
|
595
596
|
|
|
596
|
-
|
|
597
|
+
*/
|
|
597
598
|
/**
|
|
598
599
|
* our default is allow null false.
|
|
599
600
|
* for sql databases we add a db default of 0/''/false
|
|
@@ -1,58 +1,73 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
//p1 - not contains - meni request
|
|
3
|
+
//p1 - sql-expression for knex
|
|
4
|
+
//p1 - postgres case sensitive
|
|
5
|
+
//p1 - filterToRaw should get a dbnames of - and we should create a dbnames of that supports an alias
|
|
6
|
+
/*p1 - with remult async for remultexpress
|
|
7
|
+
rename withremultpromise to that withRemultAsync
|
|
8
|
+
expose live query storage in remult
|
|
9
|
+
|
|
10
|
+
request optional - and depends on that run `getUser` & `initRequest`
|
|
11
|
+
*/
|
|
12
|
+
//y1 - consider moving the request to be second parameter of with remult async
|
|
13
|
+
//y1 - Add a with remult promise to Remult!
|
|
14
|
+
//y1 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
15
|
+
//y1 - how to run a transaction as a user
|
|
16
|
+
//p1 - enum column
|
|
17
|
+
//p1 - fix sql log to console to make more sense
|
|
18
|
+
//p1 - add schema option to create postgres data provider
|
|
19
|
+
//p1 - find one i had a question about find first's different syntax from find that confused a user
|
|
20
|
+
//p1 - I think there should be a way to throw a forbidden exception
|
|
21
|
+
//y1 - Write some ctrl g
|
|
22
|
+
//y1 - get backend methods to work when specifying types for date, and entities as poco's
|
|
23
|
+
//y1 - required
|
|
24
|
+
//y1 - reconsider validators
|
|
25
|
+
//y1 - message for invalid valie
|
|
26
|
+
//y1 - message for relation that is missing
|
|
27
|
+
//p1 - more column types
|
|
28
|
+
//p2 - processError in remult express
|
|
29
|
+
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
30
|
+
//p1 - write doc about controlling updates of rows...
|
|
31
|
+
//p1 - need a way to extract the fields from the relation - for generating relation based sql
|
|
32
|
+
//p1 - add docs for apply changes
|
|
33
|
+
//p1 - when subscribe is forbidden - the query still runs after the renew process
|
|
34
|
+
//p1 - JSON FIELD LOST JSON STORAGE WHEN SET INPUT VALUE
|
|
35
|
+
//p1 - 'update tasks set where id = $1
|
|
36
|
+
//y2 - consider multi tenancies
|
|
37
|
+
//y2 - allow api read to also support instance and filter. - problem with promise
|
|
38
|
+
//p1 - doc this:
|
|
10
39
|
/**
|
|
11
40
|
* //p2 - doc this
|
|
12
41
|
remult.apiClient.httpClient = (
|
|
13
42
|
input: RequestInfo | URL,
|
|
14
43
|
init?: RequestInit
|
|
15
|
-
) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
44
|
+
) => {
|
|
45
|
+
return fetch(input, {
|
|
46
|
+
...init,
|
|
47
|
+
headers: {
|
|
48
|
+
authorization: 'Bearer ' + sessionStorage.sessionId,
|
|
49
|
+
},
|
|
50
|
+
cache: 'no-store',
|
|
51
|
+
})
|
|
23
52
|
}
|
|
24
53
|
|
|
25
54
|
&&
|
|
26
55
|
remult.apiClient.url='localhost:3007/api
|
|
27
56
|
|
|
28
57
|
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//p2 - with remult for remultexpress
|
|
36
|
-
//p2 - Add a with remult promise to Remult!
|
|
37
|
-
//p2 - filterToRaw should get a dbnames of - and we should create a dbnames of that supports an alias
|
|
58
|
+
*/
|
|
59
|
+
//y2 - discuss a default date formatter
|
|
60
|
+
//y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
|
|
61
|
+
//y2 - live query refresh of view on table update
|
|
62
|
+
//y2 - Operator '>' cannot be applied to types 'Number' and 'number'.ts(2365) - change fields to <entityType,number> (now it's Number)
|
|
63
|
+
//y2 - Field(()=>String) - doesn't play nice with strict mode - it prevents people from extending basic types
|
|
38
64
|
//y2 - livequery for findfirst (@JY)
|
|
39
65
|
//y2 - #239 - (@JY) add a way to get from fieldMetadata back to entity repo (like we have in fieldRef)
|
|
40
66
|
//p2 - constraints (@JY)
|
|
41
|
-
//p2 - Add ability to process query that comes from the api
|
|
42
|
-
//p2 - too much data by mistake
|
|
43
|
-
//p2 - postgres case sensitive
|
|
44
|
-
//p2 - fix sql log to console to make more sense
|
|
45
67
|
//p2 - type metadata.key - to keyof entity - based on cwis input
|
|
46
|
-
//p2 - processError in remult express
|
|
47
|
-
//y2 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
48
|
-
//p2 - get backend methods to work when specifying types for date, and entities as poco's
|
|
49
|
-
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
50
68
|
//y2 - remove __dirname from tutorials
|
|
51
|
-
//
|
|
52
|
-
//y2 - I tihnk there should be a way to throw a forbidden exception
|
|
69
|
+
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
53
70
|
//p2 - conside law-q db based on schema issue - I think that while running the dataProvider function, we should have a valid remult - maybe even have a valid remult, that will be valid until api is run
|
|
54
|
-
//p2 - allow api read to also support instance and filter.
|
|
55
|
-
//p2 - investigate why did lawq didn't run after build - even though it ran with tsx
|
|
56
71
|
//y2 - we should really reconsider allow null by default to be true - I think that what we're doing is confusing for most . In my case I added a volunteer relation, and didn't set any value to it - and I get an error that null value is not allowed for it
|
|
57
72
|
/**
|
|
58
73
|
* our default is allow null false.
|
|
@@ -61,5 +76,7 @@ remult.apiClient.url='localhost:3007/api
|
|
|
61
76
|
* we do not enforce allow null false (mongo, json it'll get stored)
|
|
62
77
|
|
|
63
78
|
*/
|
|
64
|
-
//y2 - i had a question about find first's different syntax from find that confused a user
|
|
65
79
|
//p2 - allowApiUpdate should be false for include in api false
|
|
80
|
+
//[ ] V2 - what to do about for relations count?
|
|
81
|
+
//[ ] V2 - condition? not to fetch if null etc....
|
|
82
|
+
//[ ] V3 - all these fields will also appear in the where etc... in the typescript api - but we will not enforce them
|
package/graphql.js
CHANGED
|
@@ -118,7 +118,7 @@ function remultGraphql(options) {
|
|
|
118
118
|
}
|
|
119
119
|
if (whereType === 'String') {
|
|
120
120
|
try {
|
|
121
|
-
for (var _p = (e_4 = void 0, tslib_1.__values(['contains'])), _q = _p.next(); !_q.done; _q = _p.next()) {
|
|
121
|
+
for (var _p = (e_4 = void 0, tslib_1.__values(['contains', 'notContains'])), _q = _p.next(); !_q.done; _q = _p.next()) {
|
|
122
122
|
var operator = _q.value;
|
|
123
123
|
var field = {
|
|
124
124
|
key: operator,
|
|
@@ -944,6 +944,7 @@ function translateWhereToRestBody(fields, _a) {
|
|
|
944
944
|
tr('nin', function (x) { return (result[field.key + '.ne'] = x); });
|
|
945
945
|
tr('eq', function (x) { return (result[field.key] = x); });
|
|
946
946
|
tr('contains', function (x) { return (result[field.key + '.contains'] = x); });
|
|
947
|
+
tr('notContains', function (x) { return (result[field.key + '.notContains'] = x); });
|
|
947
948
|
}
|
|
948
949
|
};
|
|
949
950
|
try {
|
package/package.json
CHANGED
package/remult-knex/index.js
CHANGED
|
@@ -575,6 +575,19 @@ var FilterConsumerBridgeToKnexRequest = /** @class */ (function () {
|
|
|
575
575
|
return [2 /*return*/];
|
|
576
576
|
}); }); })());
|
|
577
577
|
};
|
|
578
|
+
FilterConsumerBridgeToKnexRequest.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
579
|
+
var _this = this;
|
|
580
|
+
this.result.push(function (b) {
|
|
581
|
+
return b.whereRaw('not lower (' +
|
|
582
|
+
b.client.ref(_this.nameProvider.$dbNameOf(col)) +
|
|
583
|
+
") like lower ('%" +
|
|
584
|
+
val.replace(/'/g, "''") +
|
|
585
|
+
"%')");
|
|
586
|
+
});
|
|
587
|
+
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) {
|
|
588
|
+
return [2 /*return*/];
|
|
589
|
+
}); }); })());
|
|
590
|
+
};
|
|
578
591
|
FilterConsumerBridgeToKnexRequest.prototype.add = function (col, val, operator) {
|
|
579
592
|
var _this = this;
|
|
580
593
|
this.result.push(function (b) {
|
package/remult-mongo.js
CHANGED
|
@@ -488,10 +488,20 @@ var FilterConsumerBridgeToMongo = /** @class */ (function () {
|
|
|
488
488
|
};
|
|
489
489
|
FilterConsumerBridgeToMongo.prototype.containsCaseInsensitive = function (col, val) {
|
|
490
490
|
this.add(col, val, '$regex', { $options: 'i' });
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
491
|
+
};
|
|
492
|
+
FilterConsumerBridgeToMongo.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
493
|
+
var _this = this;
|
|
494
|
+
this.result.push(function () {
|
|
495
|
+
var _a;
|
|
496
|
+
return (_a = {},
|
|
497
|
+
_a[_this.nameProvider.$dbNameOf(col)] = {
|
|
498
|
+
$not: {
|
|
499
|
+
$regex: isNull(val) ? val : toDb(col, val),
|
|
500
|
+
$options: 'i',
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
_a);
|
|
504
|
+
});
|
|
495
505
|
};
|
|
496
506
|
FilterConsumerBridgeToMongo.prototype.add = function (col, val, operator, moreOptions) {
|
|
497
507
|
var _this = this;
|
package/src/context.js
CHANGED
|
@@ -450,5 +450,3 @@ var transactionLiveQueryPublisher = /** @class */ (function () {
|
|
|
450
450
|
};
|
|
451
451
|
return transactionLiveQueryPublisher;
|
|
452
452
|
}());
|
|
453
|
-
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
454
|
-
//y2 - require filter argument - and perform validation checks for it - site, id etc.. changelog, status changes etc...,
|
package/src/data-api.js
CHANGED
|
@@ -134,6 +134,7 @@ var DataApi = /** @class */ (function () {
|
|
|
134
134
|
if (w) {
|
|
135
135
|
w.__applyToConsumer({
|
|
136
136
|
containsCaseInsensitive: function () { },
|
|
137
|
+
notContainsCaseInsensitive: function () { },
|
|
137
138
|
isDifferentFrom: function () { },
|
|
138
139
|
isEqualTo: function (col, val) {
|
|
139
140
|
if (_this.repository.metadata.idMetadata.isIdField(col))
|
|
@@ -423,5 +423,19 @@ var FilterConsumerBridgeToObject = /** @class */ (function () {
|
|
|
423
423
|
if (s.toLowerCase().indexOf(val) < 0)
|
|
424
424
|
this.ok = false;
|
|
425
425
|
};
|
|
426
|
+
FilterConsumerBridgeToObject.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
427
|
+
var v = this.row[this.dbNames.$dbNameOf(col)];
|
|
428
|
+
if (!v) {
|
|
429
|
+
this.ok = false;
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
var s = '' + v;
|
|
433
|
+
if (val)
|
|
434
|
+
val = col.valueConverter.toJson(val);
|
|
435
|
+
if (val)
|
|
436
|
+
val = val.toString().toLowerCase();
|
|
437
|
+
if (s.toLowerCase().indexOf(val) >= 0)
|
|
438
|
+
this.ok = false;
|
|
439
|
+
};
|
|
426
440
|
return FilterConsumerBridgeToObject;
|
|
427
441
|
}());
|
|
@@ -23,6 +23,7 @@ export declare class FilterConsumerBridgeToSqlRequest implements FilterConsumer
|
|
|
23
23
|
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
24
24
|
isLessThan(col: FieldMetadata, val: any): void;
|
|
25
25
|
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
26
|
+
notContainsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
26
27
|
private add;
|
|
27
28
|
private addToWhere;
|
|
28
29
|
databaseCustom(databaseCustom: CustomSqlFilterObject): void;
|
|
@@ -175,6 +175,19 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
175
175
|
});
|
|
176
176
|
}); })());
|
|
177
177
|
};
|
|
178
|
+
FilterConsumerBridgeToSqlRequest.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
179
|
+
var _this = this;
|
|
180
|
+
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
181
|
+
return tslib_1.__generator(this, function (_a) {
|
|
182
|
+
this.addToWhere('not lower (' +
|
|
183
|
+
this.nameProvider.$dbNameOf(col) +
|
|
184
|
+
") like lower ('%" +
|
|
185
|
+
val.replace(/'/g, "''") +
|
|
186
|
+
"%')");
|
|
187
|
+
return [2 /*return*/];
|
|
188
|
+
});
|
|
189
|
+
}); })());
|
|
190
|
+
};
|
|
178
191
|
FilterConsumerBridgeToSqlRequest.prototype.add = function (col, val, operator) {
|
|
179
192
|
var _this = this;
|
|
180
193
|
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
@@ -25,6 +25,7 @@ export interface FilterConsumer {
|
|
|
25
25
|
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
26
26
|
isLessThan(col: FieldMetadata, val: any): void;
|
|
27
27
|
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
28
|
+
notContainsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
28
29
|
isIn(col: FieldMetadata, val: any[]): void;
|
|
29
30
|
custom(key: string, customItem: any): void;
|
|
30
31
|
databaseCustom(databaseCustom: any): void;
|
|
@@ -58,6 +59,7 @@ export declare class FilterSerializer implements FilterConsumer {
|
|
|
58
59
|
isLessOrEqualTo(col: FieldMetadata, val: any): void;
|
|
59
60
|
isLessThan(col: FieldMetadata, val: any): void;
|
|
60
61
|
containsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
62
|
+
notContainsCaseInsensitive(col: FieldMetadata, val: any): void;
|
|
61
63
|
}
|
|
62
64
|
export declare function entityFilterToJson<T>(entityDefs: EntityMetadata<T>, where: EntityFilter<T>): any;
|
|
63
65
|
export declare function buildFilterFromRequestParameters(entity: EntityMetadata, filterInfo: {
|
|
@@ -114,6 +114,10 @@ var Filter = /** @class */ (function () {
|
|
|
114
114
|
found = true;
|
|
115
115
|
result.push(fh.contains(element));
|
|
116
116
|
break;
|
|
117
|
+
case '$notContains':
|
|
118
|
+
found = true;
|
|
119
|
+
result.push(fh.notContains(element));
|
|
120
|
+
break;
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
}
|
|
@@ -223,6 +227,12 @@ var filterHelper = /** @class */ (function () {
|
|
|
223
227
|
var _this = this;
|
|
224
228
|
return new Filter(function (add) { return add.containsCaseInsensitive(_this.metadata, val); });
|
|
225
229
|
};
|
|
230
|
+
filterHelper.prototype.notContains = function (val) {
|
|
231
|
+
var _this = this;
|
|
232
|
+
return new Filter(function (add) {
|
|
233
|
+
return add.notContainsCaseInsensitive(_this.metadata, val);
|
|
234
|
+
});
|
|
235
|
+
};
|
|
226
236
|
filterHelper.prototype.isLessThan = function (val) {
|
|
227
237
|
var _this = this;
|
|
228
238
|
val = this.processVal(val);
|
|
@@ -311,6 +321,9 @@ var manyToOneFilterHelper = /** @class */ (function () {
|
|
|
311
321
|
manyToOneFilterHelper.prototype.contains = function (val) {
|
|
312
322
|
throw new Error('Invalid for Many To One Relation Field');
|
|
313
323
|
};
|
|
324
|
+
manyToOneFilterHelper.prototype.notContains = function (val) {
|
|
325
|
+
throw new Error('Invalid for Many To One Relation Field');
|
|
326
|
+
};
|
|
314
327
|
manyToOneFilterHelper.prototype.isLessThan = function (val) {
|
|
315
328
|
throw new Error('Invalid for Many To One Relation Field');
|
|
316
329
|
};
|
|
@@ -494,6 +507,9 @@ var FilterSerializer = /** @class */ (function () {
|
|
|
494
507
|
FilterSerializer.prototype.containsCaseInsensitive = function (col, val) {
|
|
495
508
|
this.add(col.key + '.contains', val);
|
|
496
509
|
};
|
|
510
|
+
FilterSerializer.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
511
|
+
this.add(col.key + '.notContains', val);
|
|
512
|
+
};
|
|
497
513
|
return FilterSerializer;
|
|
498
514
|
}());
|
|
499
515
|
exports.FilterSerializer = FilterSerializer;
|
|
@@ -583,6 +599,7 @@ function buildFilterFromRequestParameters(entity, filterInfo) {
|
|
|
583
599
|
}
|
|
584
600
|
}
|
|
585
601
|
addFilter('.contains', function (val) { return ({ $contains: val }); }, false, true);
|
|
602
|
+
addFilter('.notContains', function (val) { return ({ $notContains: val }); }, false, true);
|
|
586
603
|
});
|
|
587
604
|
var val = filterInfo.get('OR');
|
|
588
605
|
if (val) {
|
|
@@ -712,6 +729,9 @@ var customTranslator = /** @class */ (function () {
|
|
|
712
729
|
customTranslator.prototype.containsCaseInsensitive = function (col, val) {
|
|
713
730
|
this.commands.push(function (x) { return x.containsCaseInsensitive(col, val); });
|
|
714
731
|
};
|
|
732
|
+
customTranslator.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
733
|
+
this.commands.push(function (x) { return x.notContainsCaseInsensitive(col, val); });
|
|
734
|
+
};
|
|
715
735
|
customTranslator.prototype.isIn = function (col, val) {
|
|
716
736
|
this.commands.push(function (x) { return x.isIn(col, val); });
|
|
717
737
|
};
|
|
@@ -766,6 +786,7 @@ function __updateEntityBasedOnWhere(entityDefs, where, r) {
|
|
|
766
786
|
custom: emptyFunction,
|
|
767
787
|
databaseCustom: emptyFunction,
|
|
768
788
|
containsCaseInsensitive: emptyFunction,
|
|
789
|
+
notContainsCaseInsensitive: emptyFunction,
|
|
769
790
|
isDifferentFrom: emptyFunction,
|
|
770
791
|
isEqualTo: function (col, val) {
|
|
771
792
|
r[col.key] = val;
|
|
@@ -17,9 +17,7 @@ var LiveQueryPublisher = /** @class */ (function () {
|
|
|
17
17
|
var _this = this;
|
|
18
18
|
return tslib_1.__generator(this, function (_a) {
|
|
19
19
|
switch (_a.label) {
|
|
20
|
-
case 0:
|
|
21
|
-
//TODO 2 - optimize so that the user will get their messages first. Based on user id
|
|
22
|
-
return [4 /*yield*/, this.liveQueryStorage().forEach(entityKey, function (_a) {
|
|
20
|
+
case 0: return [4 /*yield*/, this.liveQueryStorage().forEach(entityKey, function (_a) {
|
|
23
21
|
var q = _a.query, setData = _a.setData;
|
|
24
22
|
return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
25
23
|
var query;
|
|
@@ -123,7 +121,6 @@ var LiveQueryPublisher = /** @class */ (function () {
|
|
|
123
121
|
});
|
|
124
122
|
})];
|
|
125
123
|
case 1:
|
|
126
|
-
//TODO 2 - optimize so that the user will get their messages first. Based on user id
|
|
127
124
|
_a.sent();
|
|
128
125
|
return [2 /*return*/];
|
|
129
126
|
}
|
|
@@ -195,7 +195,6 @@ var RepositoryImplementation = /** @class */ (function () {
|
|
|
195
195
|
});
|
|
196
196
|
});
|
|
197
197
|
};
|
|
198
|
-
//TODO2 - Used to prevent unnecessary many to one relations
|
|
199
198
|
RepositoryImplementation.prototype.addToCache = function (item) {
|
|
200
199
|
if (item)
|
|
201
200
|
this.idCache.set(this.getEntityRef(item).getId() + '', item);
|
|
@@ -2961,7 +2960,7 @@ var EntityFullInfo = /** @class */ (function () {
|
|
|
2961
2960
|
Object.defineProperty(EntityFullInfo.prototype, "apiReadAllowed", {
|
|
2962
2961
|
get: function () {
|
|
2963
2962
|
if (this.options.allowApiRead === undefined)
|
|
2964
|
-
return true;
|
|
2963
|
+
return true;
|
|
2965
2964
|
return this.remult.isAllowed(this.options.allowApiRead);
|
|
2966
2965
|
},
|
|
2967
2966
|
enumerable: false,
|
|
@@ -10,6 +10,7 @@ function __updateEntityBasedOnWhere(entityDefs, where, r) {
|
|
|
10
10
|
custom: emptyFunction,
|
|
11
11
|
databaseCustom: emptyFunction,
|
|
12
12
|
containsCaseInsensitive: emptyFunction,
|
|
13
|
+
notContainsCaseInsensitive: emptyFunction,
|
|
13
14
|
isDifferentFrom: emptyFunction,
|
|
14
15
|
isEqualTo: function (col, val) {
|
|
15
16
|
r[col.key] = val;
|
package/src/remult3/remult3.d.ts
CHANGED
|
@@ -388,6 +388,7 @@ export type ComparisonValueFilter<valueType> = ValueFilter<valueType> & {
|
|
|
388
388
|
};
|
|
389
389
|
export interface ContainsStringValueFilter {
|
|
390
390
|
$contains?: string;
|
|
391
|
+
$notContains?: string;
|
|
391
392
|
}
|
|
392
393
|
export type IdFilter<valueType> = ValueFilter<valueType> | {
|
|
393
394
|
$id: ValueFilter<valueType extends {
|
|
@@ -579,21 +580,21 @@ export type ClassFieldDecorator<entityType, valueType> = (target: any, context:
|
|
|
579
580
|
remult.apiClient.httpClient = (
|
|
580
581
|
input: RequestInfo | URL,
|
|
581
582
|
init?: RequestInit
|
|
582
|
-
) => {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
583
|
+
) => {
|
|
584
|
+
return fetch(input, {
|
|
585
|
+
...init,
|
|
586
|
+
headers: {
|
|
587
|
+
authorization: 'Bearer ' + sessionStorage.sessionId,
|
|
588
|
+
},
|
|
589
|
+
cache: 'no-store',
|
|
590
|
+
})
|
|
590
591
|
}
|
|
591
592
|
|
|
592
593
|
&&
|
|
593
594
|
remult.apiClient.url='localhost:3007/api
|
|
594
595
|
|
|
595
596
|
|
|
596
|
-
|
|
597
|
+
*/
|
|
597
598
|
/**
|
|
598
599
|
* our default is allow null false.
|
|
599
600
|
* for sql databases we add a db default of 0/''/false
|
package/src/remult3/remult3.js
CHANGED
|
@@ -1,59 +1,74 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
//p1 - not contains - meni request
|
|
4
|
+
//p1 - sql-expression for knex
|
|
5
|
+
//p1 - postgres case sensitive
|
|
6
|
+
//p1 - filterToRaw should get a dbnames of - and we should create a dbnames of that supports an alias
|
|
7
|
+
/*p1 - with remult async for remultexpress
|
|
8
|
+
rename withremultpromise to that withRemultAsync
|
|
9
|
+
expose live query storage in remult
|
|
10
|
+
|
|
11
|
+
request optional - and depends on that run `getUser` & `initRequest`
|
|
12
|
+
*/
|
|
13
|
+
//y1 - consider moving the request to be second parameter of with remult async
|
|
14
|
+
//y1 - Add a with remult promise to Remult!
|
|
15
|
+
//y1 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
16
|
+
//y1 - how to run a transaction as a user
|
|
17
|
+
//p1 - enum column
|
|
18
|
+
//p1 - fix sql log to console to make more sense
|
|
19
|
+
//p1 - add schema option to create postgres data provider
|
|
20
|
+
//p1 - find one i had a question about find first's different syntax from find that confused a user
|
|
21
|
+
//p1 - I think there should be a way to throw a forbidden exception
|
|
22
|
+
//y1 - Write some ctrl g
|
|
23
|
+
//y1 - get backend methods to work when specifying types for date, and entities as poco's
|
|
24
|
+
//y1 - required
|
|
25
|
+
//y1 - reconsider validators
|
|
26
|
+
//y1 - message for invalid valie
|
|
27
|
+
//y1 - message for relation that is missing
|
|
28
|
+
//p1 - more column types
|
|
29
|
+
//p2 - processError in remult express
|
|
30
|
+
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
31
|
+
//p1 - write doc about controlling updates of rows...
|
|
32
|
+
//p1 - need a way to extract the fields from the relation - for generating relation based sql
|
|
33
|
+
//p1 - add docs for apply changes
|
|
34
|
+
//p1 - when subscribe is forbidden - the query still runs after the renew process
|
|
35
|
+
//p1 - JSON FIELD LOST JSON STORAGE WHEN SET INPUT VALUE
|
|
36
|
+
//p1 - 'update tasks set where id = $1
|
|
37
|
+
//y2 - consider multi tenancies
|
|
38
|
+
//y2 - allow api read to also support instance and filter. - problem with promise
|
|
39
|
+
//p1 - doc this:
|
|
11
40
|
/**
|
|
12
41
|
* //p2 - doc this
|
|
13
42
|
remult.apiClient.httpClient = (
|
|
14
43
|
input: RequestInfo | URL,
|
|
15
44
|
init?: RequestInit
|
|
16
|
-
) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
45
|
+
) => {
|
|
46
|
+
return fetch(input, {
|
|
47
|
+
...init,
|
|
48
|
+
headers: {
|
|
49
|
+
authorization: 'Bearer ' + sessionStorage.sessionId,
|
|
50
|
+
},
|
|
51
|
+
cache: 'no-store',
|
|
52
|
+
})
|
|
24
53
|
}
|
|
25
54
|
|
|
26
55
|
&&
|
|
27
56
|
remult.apiClient.url='localhost:3007/api
|
|
28
57
|
|
|
29
58
|
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//p2 - with remult for remultexpress
|
|
37
|
-
//p2 - Add a with remult promise to Remult!
|
|
38
|
-
//p2 - filterToRaw should get a dbnames of - and we should create a dbnames of that supports an alias
|
|
59
|
+
*/
|
|
60
|
+
//y2 - discuss a default date formatter
|
|
61
|
+
//y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
|
|
62
|
+
//y2 - live query refresh of view on table update
|
|
63
|
+
//y2 - Operator '>' cannot be applied to types 'Number' and 'number'.ts(2365) - change fields to <entityType,number> (now it's Number)
|
|
64
|
+
//y2 - Field(()=>String) - doesn't play nice with strict mode - it prevents people from extending basic types
|
|
39
65
|
//y2 - livequery for findfirst (@JY)
|
|
40
66
|
//y2 - #239 - (@JY) add a way to get from fieldMetadata back to entity repo (like we have in fieldRef)
|
|
41
67
|
//p2 - constraints (@JY)
|
|
42
|
-
//p2 - Add ability to process query that comes from the api
|
|
43
|
-
//p2 - too much data by mistake
|
|
44
|
-
//p2 - postgres case sensitive
|
|
45
|
-
//p2 - fix sql log to console to make more sense
|
|
46
68
|
//p2 - type metadata.key - to keyof entity - based on cwis input
|
|
47
|
-
//p2 - processError in remult express
|
|
48
|
-
//y2 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
49
|
-
//p2 - get backend methods to work when specifying types for date, and entities as poco's
|
|
50
|
-
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
51
69
|
//y2 - remove __dirname from tutorials
|
|
52
|
-
//
|
|
53
|
-
//y2 - I tihnk there should be a way to throw a forbidden exception
|
|
70
|
+
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
54
71
|
//p2 - conside law-q db based on schema issue - I think that while running the dataProvider function, we should have a valid remult - maybe even have a valid remult, that will be valid until api is run
|
|
55
|
-
//p2 - allow api read to also support instance and filter.
|
|
56
|
-
//p2 - investigate why did lawq didn't run after build - even though it ran with tsx
|
|
57
72
|
//y2 - we should really reconsider allow null by default to be true - I think that what we're doing is confusing for most . In my case I added a volunteer relation, and didn't set any value to it - and I get an error that null value is not allowed for it
|
|
58
73
|
/**
|
|
59
74
|
* our default is allow null false.
|
|
@@ -62,5 +77,7 @@ remult.apiClient.url='localhost:3007/api
|
|
|
62
77
|
* we do not enforce allow null false (mongo, json it'll get stored)
|
|
63
78
|
|
|
64
79
|
*/
|
|
65
|
-
//y2 - i had a question about find first's different syntax from find that confused a user
|
|
66
80
|
//p2 - allowApiUpdate should be false for include in api false
|
|
81
|
+
//[ ] V2 - what to do about for relations count?
|
|
82
|
+
//[ ] V2 - condition? not to fetch if null etc....
|
|
83
|
+
//[ ] V3 - all these fields will also appear in the where etc... in the typescript api - but we will not enforce them
|