remult 0.25.8-exp.6 → 0.25.8-exp.8
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/src/isOfType.js +1 -1
- package/esm/src/remult3/Fields.js +66 -0
- package/esm/src/remult3/RepositoryImplementation.js +4 -2
- package/esm/src/remult3/addValidatorKey.js +1 -0
- package/esm/src/remult3/remult3.js +14 -43
- package/esm/src/validators.js +1 -1
- package/package.json +1 -1
- package/src/column-interfaces.d.ts +9 -3
- package/src/isOfType.js +1 -1
- package/src/remult3/Fields.d.ts +36 -0
- package/src/remult3/Fields.js +77 -0
- package/src/remult3/RepositoryImplementation.d.ts +6 -2
- package/src/remult3/RepositoryImplementation.js +54 -50
- package/src/remult3/addValidatorKey.d.ts +1 -0
- package/src/remult3/addValidatorKey.js +4 -0
- package/src/remult3/remult3.d.ts +6 -2
- package/src/remult3/remult3.js +14 -43
- package/src/validators.js +3 -1
package/esm/src/isOfType.js
CHANGED
|
@@ -5,6 +5,7 @@ import { buildOptions } from './RepositoryImplementation.js';
|
|
|
5
5
|
import { Validators } from '../validators.js';
|
|
6
6
|
import { relationInfoMemberInOptions } from './relationInfoMember.js';
|
|
7
7
|
import { remultStatic } from '../remult-static.js';
|
|
8
|
+
import { addValidatorKey } from './addValidatorKey.js';
|
|
8
9
|
export class Fields {
|
|
9
10
|
/**
|
|
10
11
|
* Stored as a JSON.stringify - to store as json use Fields.json
|
|
@@ -76,6 +77,11 @@ export class Fields {
|
|
|
76
77
|
},
|
|
77
78
|
}, ...options);
|
|
78
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* A CUID (Collision Resistant Unique Identifier) field.
|
|
82
|
+
* This id value is determined on the backend on insert, and can't be updated through the API.
|
|
83
|
+
* The CUID is generated using the `@paralleldrive/cuid2` npm package.
|
|
84
|
+
*/
|
|
79
85
|
static cuid(...options) {
|
|
80
86
|
return Field(() => String, {
|
|
81
87
|
allowApiUpdate: false,
|
|
@@ -86,6 +92,63 @@ export class Fields {
|
|
|
86
92
|
},
|
|
87
93
|
}, ...options);
|
|
88
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Defines a field that can hold a value from a specified set of string literals.
|
|
97
|
+
* @param {() => readonly valueType[]} optionalValues - A function that returns an array of allowed string literals.
|
|
98
|
+
* @returns {ClassFieldDecorator<entityType, valueType | undefined>} - A class field decorator.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
|
|
102
|
+
* class MyEntity {
|
|
103
|
+
* .@Fields.literal(() => ['open', 'closed', 'frozen', 'in progress'] as const)
|
|
104
|
+
* status: 'open' | 'closed' | 'frozen' | 'in progress' = 'open';
|
|
105
|
+
* }
|
|
106
|
+
|
|
107
|
+
*
|
|
108
|
+
* // This defines a field `status` in `MyEntity` that can only hold the values 'open', 'closed', 'frozen', or 'in progress'.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* // For better reusability and maintainability:
|
|
112
|
+
|
|
113
|
+
* const statuses = ['open', 'closed', 'frozen', 'in progress'] as const;
|
|
114
|
+
* type StatusType = typeof statuses[number];
|
|
115
|
+
*
|
|
116
|
+
* class MyEntity {
|
|
117
|
+
* .@Fields.literal(() => statuses)
|
|
118
|
+
* status: StatusType = 'open';
|
|
119
|
+
* }
|
|
120
|
+
|
|
121
|
+
*
|
|
122
|
+
* // This approach allows easy management and updates of the allowed values for the `status` field.
|
|
123
|
+
*/
|
|
124
|
+
static literal(optionalValues, ...options) {
|
|
125
|
+
return Fields.string({
|
|
126
|
+
//@ts-ignore
|
|
127
|
+
[addValidatorKey]: (entity, event) => Validators.in(optionalValues())(entity, event)
|
|
128
|
+
}, ...options);
|
|
129
|
+
}
|
|
130
|
+
static enum(enumType, ...options) {
|
|
131
|
+
let valueConverter;
|
|
132
|
+
return Field(() =>
|
|
133
|
+
//@ts-ignore
|
|
134
|
+
enumType(), {
|
|
135
|
+
[addValidatorKey]: (entity, event) => Validators.enum(enumType())(entity, event)
|
|
136
|
+
}, ...options, (options) => {
|
|
137
|
+
if (valueConverter === undefined) {
|
|
138
|
+
let enumObj = enumType();
|
|
139
|
+
let enumValues = Object.values(enumObj)
|
|
140
|
+
.filter((x) => typeof enumObj[x] !== 'number');
|
|
141
|
+
valueConverter = enumValues.find(x => typeof x === "string") ? ValueConverters.String : ValueConverters.Integer;
|
|
142
|
+
}
|
|
143
|
+
if (!options.valueConverter) {
|
|
144
|
+
options.valueConverter = valueConverter;
|
|
145
|
+
}
|
|
146
|
+
else if (!options.valueConverter.fieldTypeInDb) {
|
|
147
|
+
//@ts-ignore
|
|
148
|
+
options.valueConverter.fieldTypeInDb = valueConverter.fieldTypeInDb;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
89
152
|
static string(...options) {
|
|
90
153
|
return Field(() => String, ...options);
|
|
91
154
|
}
|
|
@@ -188,6 +251,9 @@ export function Field(valueType, ...options) {
|
|
|
188
251
|
if (r.required) {
|
|
189
252
|
r.validate = addValidator(r.validate, Validators.required);
|
|
190
253
|
}
|
|
254
|
+
if (r[addValidatorKey]) {
|
|
255
|
+
r.validate = addValidator(r.validate, r[addValidatorKey]);
|
|
256
|
+
}
|
|
191
257
|
if (r.maxLength) {
|
|
192
258
|
r.validate = addValidator(r.validate, Validators.maxLength(r.maxLength));
|
|
193
259
|
}
|
|
@@ -14,6 +14,7 @@ import { RelationLoader } from './relation-loader.js';
|
|
|
14
14
|
import { getInternalKey, } from './repository-internals.js';
|
|
15
15
|
import { entityDbName, fieldDbName, } from '../filter/filter-consumer-bridge-to-sql-request.js';
|
|
16
16
|
import { remultStatic } from '../remult-static.js';
|
|
17
|
+
import { Validators } from '../validators.js';
|
|
17
18
|
//import { remult } from "../remult-proxy";
|
|
18
19
|
let classValidatorValidate = undefined;
|
|
19
20
|
// import ("class-validator".toString())
|
|
@@ -269,7 +270,7 @@ export class RepositoryImplementation {
|
|
|
269
270
|
}
|
|
270
271
|
}
|
|
271
272
|
}
|
|
272
|
-
async updateMany(where, set) {
|
|
273
|
+
async updateMany({ where }, set) {
|
|
273
274
|
Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
|
|
274
275
|
if (this._dataProvider.isProxy) {
|
|
275
276
|
return this._edp.updateMany(await this._translateWhereToFilter(where), set);
|
|
@@ -636,7 +637,7 @@ export class RepositoryImplementation {
|
|
|
636
637
|
async count(where) {
|
|
637
638
|
return this._edp.count(await this._translateWhereToFilter(where));
|
|
638
639
|
}
|
|
639
|
-
async deleteMany(where) {
|
|
640
|
+
async deleteMany({ where }) {
|
|
640
641
|
Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
|
|
641
642
|
if (this._dataProvider.isProxy) {
|
|
642
643
|
return this._edp.deleteMany(await this._translateWhereToFilter(where));
|
|
@@ -1961,6 +1962,7 @@ export function ValueListFieldType(...options) {
|
|
|
1961
1962
|
;
|
|
1962
1963
|
(o.valueConverter = ValueListInfo.get(type)),
|
|
1963
1964
|
(o.displayValue = (item, val) => val?.caption);
|
|
1965
|
+
o.validate = (entity, ref) => Validators.in(ValueListInfo.get(type).getValues())(entity, ref);
|
|
1964
1966
|
}, ...options)(type, context);
|
|
1965
1967
|
};
|
|
1966
1968
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const addValidatorKey = '__addValidator';
|
|
@@ -1,44 +1,27 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//p1 -
|
|
2
|
+
//p1 - `preprocessApiFindOptions`, naming - allow find options preprocessor for api calls, to use for authorization
|
|
3
|
+
//p1 - admin url1 - pocketbase use /_ for the admin //{allowed?:Allowed,url?:string}
|
|
4
|
+
//p1 - Validate for NAN
|
|
5
|
+
//p1 - Make async hooks gracefully handle non async hooks environment
|
|
6
|
+
//p1 - chain validators with options
|
|
7
|
+
//y2 - should we validate relations
|
|
8
|
+
//y1 - consider replacing all errors with error classes that extend the base Error class
|
|
9
|
+
//y2 - consider if field types should include validation in them by default (string,number that it's not NaN etc...) and if so, what message?
|
|
10
|
+
//y2 - should enforce integer - currently we probably round / truncate it
|
|
11
|
+
/*y1 - talk about modules in init express with entities/controllers,initRequest,initApi
|
|
12
|
+
- support get with backend method, with url search params as the first parameter, & url as second parameter
|
|
13
|
+
- support returning redirect, and plain html (For sign in scenarios)
|
|
14
|
+
|
|
15
|
+
*/
|
|
3
16
|
//p1 - in this video I'll use remult to turn a frontend app to a fullstack app
|
|
4
17
|
//y1 - getFields didn't work for kobi in the home component
|
|
5
|
-
//y1 - consider replacing all errors with error classes that extend the base Error class
|
|
6
18
|
//p1 - document offline support
|
|
7
|
-
//p1 - add section to Fields doc, explaining field type in db
|
|
8
|
-
//p1 - add section about union type
|
|
9
|
-
//p1 - add section about value list field type
|
|
10
19
|
/*y1 - Talk JYC - JYC - add some integrity checks on delete
|
|
11
20
|
- soft delete
|
|
12
21
|
- delete restrict (implicit, or user selected - and if so, how) (delete & update of id)
|
|
13
22
|
|
|
14
23
|
*/
|
|
15
|
-
/*y1 currency.ts:10 Uncaught TypeError: Currency_1 is not a constructor
|
|
16
|
-
// - ValueListFieldType - the decorator gives an error in react vite project - see langulage yedidya
|
|
17
|
-
// happens in target 2022, ts<5.1.6
|
|
18
|
-
//typescript 5.1.6
|
|
19
|
-
@ValueListFieldType()
|
|
20
|
-
export class Currency {
|
|
21
|
-
constructor(
|
|
22
|
-
public id: number,
|
|
23
|
-
public caption: string,
|
|
24
|
-
public symbol: string
|
|
25
|
-
) {}
|
|
26
|
-
static shekel = new Currency(1, 'Shekel', '₪');
|
|
27
|
-
static dollar = new Currency(2, 'Dollar', '$');
|
|
28
|
-
static euro = new Currency(3, 'Euro', '€');
|
|
29
|
-
static pound = new Currency(4, 'Pound', '£');
|
|
30
|
-
static yen = new Currency(5, 'Yen', '¥');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
*/
|
|
34
|
-
//y1 - allow api read to also support instance and filter. - problem with promise
|
|
35
|
-
//y1 - admin url1 - pocketbase use /_ for the admin
|
|
36
24
|
//y1 - consider sql expression gets a dbnames of it's own (that already has the "tableName" defined correctly) maybe also the filter translator
|
|
37
|
-
/*y1 - talk about modules in init express with entities/controllers,initRequest,initApi
|
|
38
|
-
- support get with backend method, with url search params as the first parameter, & url as second parameter
|
|
39
|
-
- support returning redirect, and plain html (For sign in scenarios)
|
|
40
|
-
|
|
41
|
-
*/
|
|
42
25
|
//y1 - tried to upgrade vitest, nuxt tests are failing with loading uuid - sounds familiar?
|
|
43
26
|
//y1 - I think that the tests you've setup don't cover next app router - I added to the setup, but not sure where else
|
|
44
27
|
//y1 - talk about the parameter issue with backend methods
|
|
@@ -53,8 +36,6 @@ export class Currency {
|
|
|
53
36
|
})
|
|
54
37
|
Description = ""*/
|
|
55
38
|
//y2 - get backend methods to work when specifying types for date, and entities as poco's
|
|
56
|
-
//y2 - 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
|
|
57
|
-
//y2 - #239 - (@JY) add a way to get from fieldMetadata back to entity repo (like we have in fieldRef)
|
|
58
39
|
//y2 - constraints (@JY)
|
|
59
40
|
/*p2 remult admin
|
|
60
41
|
|
|
@@ -69,11 +50,9 @@ export class Currency {
|
|
|
69
50
|
- remult-admin didn't show a update for a table with a uniqua that is numeric
|
|
70
51
|
*/
|
|
71
52
|
//remult
|
|
72
|
-
//p1 - better support union types (status, etc... so it'll work also in filter etc...)
|
|
73
53
|
//p1 - when a tasks table exists in a different schema - we get many errors
|
|
74
54
|
//p1 - live query with include
|
|
75
55
|
//p1 - adjust angular tutorial starter kit for latest angular (as is in tutorial)
|
|
76
|
-
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
77
56
|
//p2 - when subscribe is forbidden - the query still runs after the renew process
|
|
78
57
|
//p2 - 'update tasks set where id = $1
|
|
79
58
|
//p2 - type metadata.key - to keyof entity - based on cwis input
|
|
@@ -81,23 +60,15 @@ export class Currency {
|
|
|
81
60
|
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
82
61
|
//p2 - allowApiUpdate should be false for include in api false
|
|
83
62
|
//docs
|
|
84
|
-
//p2 - make sure that internal members do not appear in the documentation - try running it on the d.ts instead of the code itself.
|
|
85
63
|
//------
|
|
86
64
|
//y2 - from the crm-demo(https://crm-demo.up.railway.app/deals), after editing a deal: - _updateEntityBasedOnApi
|
|
87
65
|
//y2 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
88
66
|
//y2 - how to run a transaction as a user
|
|
89
|
-
//p2 - enum column
|
|
90
|
-
//y2 - message for invalid value
|
|
91
67
|
//y2 - message for relation that is missing
|
|
92
68
|
//y2 - consider multi tenancies
|
|
93
|
-
//p2 - more column types
|
|
94
|
-
//p2 - document validators
|
|
95
69
|
//p2 - and validators to reference
|
|
96
70
|
//y2 - discuss a default date formatter
|
|
97
71
|
//y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
|
|
98
72
|
//[ ] V2 - what to do about for relations count?
|
|
99
73
|
//[ ] V2 - condition? not to fetch if null etc....
|
|
100
|
-
//[ ] V3 - all these fields will also appear in the where etc... in the typescript api - but we will not enforce them
|
|
101
|
-
//y2 - consider if field types should include validation in them by default (string,number that it's not NaN etc...) and if so, what message?
|
|
102
|
-
//y2 - should enforce integer - currently we probably round / truncate it
|
|
103
74
|
//p1 - adjust react tutorial to esm
|
package/esm/src/validators.js
CHANGED
|
@@ -26,7 +26,7 @@ export class Validators {
|
|
|
26
26
|
static regex = createValueValidatorWithArgs((val, regex) => regex.test(val));
|
|
27
27
|
static email = createValueValidator((val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val), 'Invalid Email');
|
|
28
28
|
static url = createValueValidator((val) => !!new URL(val), 'Invalid Url');
|
|
29
|
-
static in = createValueValidatorWithArgs((val, values) => values.includes(val), (values) => `Value must be one of ${values.join(', ')}`);
|
|
29
|
+
static in = createValueValidatorWithArgs((val, values) => values.includes(val), (values) => `Value must be one of ${values.map(y => typeof y === "object" ? y['id'] !== undefined ? y['id'] : y.toString() : y).join(', ')}`);
|
|
30
30
|
static notNull = createValueValidator((val) => val != null, 'Should not be null');
|
|
31
31
|
static enum = createValueValidatorWithArgs((value, enumObj) => Object.values(enumObj).includes(value), (enumObj) => `Value must be one of ${Object.values(enumObj)
|
|
32
32
|
.filter((x) => typeof enumObj[x] !== 'number')
|
package/package.json
CHANGED
|
@@ -247,17 +247,23 @@ export interface ValueConverter<valueType> {
|
|
|
247
247
|
*/
|
|
248
248
|
displayValue?(val: valueType): string;
|
|
249
249
|
/**
|
|
250
|
-
* Specifies the storage type used in the database for this field.
|
|
250
|
+
* Specifies the storage type used in the database for this field. This can be used to explicitly define the data type and precision of the field in the database.
|
|
251
251
|
*
|
|
252
252
|
* @example
|
|
253
|
-
*
|
|
253
|
+
* // Define a field with a specific decimal precision in the database
|
|
254
|
+
* @Fields.number({
|
|
255
|
+
* valueConverter: {
|
|
256
|
+
* fieldTypeInDb: 'decimal(18,8)'
|
|
257
|
+
* }
|
|
258
|
+
* })
|
|
259
|
+
* price=0;
|
|
254
260
|
*/
|
|
255
261
|
readonly fieldTypeInDb?: string;
|
|
256
262
|
/**
|
|
257
263
|
* Specifies the type of HTML input element suitable for values of valueType.
|
|
258
264
|
*
|
|
259
265
|
* @example
|
|
260
|
-
*
|
|
266
|
+
* inputType = 'date';
|
|
261
267
|
*/
|
|
262
268
|
readonly inputType?: string;
|
|
263
269
|
}
|
package/src/isOfType.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cast = exports.isOfType = void 0;
|
|
4
4
|
function isOfType(obj, checkMethod) {
|
|
5
|
-
return typeof obj[checkMethod]
|
|
5
|
+
return typeof obj[checkMethod] !== 'undefined';
|
|
6
6
|
}
|
|
7
7
|
exports.isOfType = isOfType;
|
|
8
8
|
function cast(obj, checkMethod) {
|
package/src/remult3/Fields.d.ts
CHANGED
|
@@ -16,7 +16,43 @@ export declare class Fields {
|
|
|
16
16
|
static createdAt<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
17
17
|
static updatedAt<entityType = any>(...options: (FieldOptions<entityType, Date> | ((options: FieldOptions<entityType, Date>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, Date | undefined>;
|
|
18
18
|
static uuid<entityType = any>(...options: (FieldOptions<entityType, string> | ((options: FieldOptions<entityType, string>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
19
|
+
/**
|
|
20
|
+
* A CUID (Collision Resistant Unique Identifier) field.
|
|
21
|
+
* This id value is determined on the backend on insert, and can't be updated through the API.
|
|
22
|
+
* The CUID is generated using the `@paralleldrive/cuid2` npm package.
|
|
23
|
+
*/
|
|
19
24
|
static cuid<entityType = any>(...options: (FieldOptions<entityType, string> | ((options: FieldOptions<entityType, string>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, string | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* Defines a field that can hold a value from a specified set of string literals.
|
|
27
|
+
* @param {() => readonly valueType[]} optionalValues - A function that returns an array of allowed string literals.
|
|
28
|
+
* @returns {ClassFieldDecorator<entityType, valueType | undefined>} - A class field decorator.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
|
|
32
|
+
* class MyEntity {
|
|
33
|
+
* .@Fields.literal(() => ['open', 'closed', 'frozen', 'in progress'] as const)
|
|
34
|
+
* status: 'open' | 'closed' | 'frozen' | 'in progress' = 'open';
|
|
35
|
+
* }
|
|
36
|
+
|
|
37
|
+
*
|
|
38
|
+
* // This defines a field `status` in `MyEntity` that can only hold the values 'open', 'closed', 'frozen', or 'in progress'.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // For better reusability and maintainability:
|
|
42
|
+
|
|
43
|
+
* const statuses = ['open', 'closed', 'frozen', 'in progress'] as const;
|
|
44
|
+
* type StatusType = typeof statuses[number];
|
|
45
|
+
*
|
|
46
|
+
* class MyEntity {
|
|
47
|
+
* .@Fields.literal(() => statuses)
|
|
48
|
+
* status: StatusType = 'open';
|
|
49
|
+
* }
|
|
50
|
+
|
|
51
|
+
*
|
|
52
|
+
* // This approach allows easy management and updates of the allowed values for the `status` field.
|
|
53
|
+
*/
|
|
54
|
+
static literal<entityType = any, valueType extends string = any>(optionalValues: () => readonly valueType[], ...options: (StringFieldOptions<entityType, valueType> | ((options: StringFieldOptions<entityType, valueType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, valueType | undefined>;
|
|
55
|
+
static enum<entityType = any, theEnum = any>(enumType: () => theEnum, ...options: (FieldOptions<entityType, theEnum[keyof theEnum]> | ((options: FieldOptions<entityType, theEnum[keyof theEnum]>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, theEnum[keyof theEnum] | undefined>;
|
|
20
56
|
static string<entityType = any, valueType = string>(...options: (StringFieldOptions<entityType, valueType> | ((options: StringFieldOptions<entityType, valueType>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, valueType | undefined>;
|
|
21
57
|
static boolean<entityType = any>(...options: (FieldOptions<entityType, boolean> | ((options: FieldOptions<entityType, boolean>, remult: Remult) => void))[]): ClassFieldDecorator<entityType, boolean | undefined>;
|
|
22
58
|
}
|
package/src/remult3/Fields.js
CHANGED
|
@@ -9,6 +9,7 @@ var RepositoryImplementation_js_1 = require("./RepositoryImplementation.js");
|
|
|
9
9
|
var validators_js_1 = require("../validators.js");
|
|
10
10
|
var relationInfoMember_js_1 = require("./relationInfoMember.js");
|
|
11
11
|
var remult_static_js_1 = require("../remult-static.js");
|
|
12
|
+
var addValidatorKey_js_1 = require("./addValidatorKey.js");
|
|
12
13
|
var Fields = /** @class */ (function () {
|
|
13
14
|
function Fields() {
|
|
14
15
|
}
|
|
@@ -127,6 +128,11 @@ var Fields = /** @class */ (function () {
|
|
|
127
128
|
},
|
|
128
129
|
}], tslib_1.__read(options), false));
|
|
129
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* A CUID (Collision Resistant Unique Identifier) field.
|
|
133
|
+
* This id value is determined on the backend on insert, and can't be updated through the API.
|
|
134
|
+
* The CUID is generated using the `@paralleldrive/cuid2` npm package.
|
|
135
|
+
*/
|
|
130
136
|
Fields.cuid = function () {
|
|
131
137
|
var options = [];
|
|
132
138
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
@@ -142,6 +148,74 @@ var Fields = /** @class */ (function () {
|
|
|
142
148
|
},
|
|
143
149
|
}], tslib_1.__read(options), false));
|
|
144
150
|
};
|
|
151
|
+
/**
|
|
152
|
+
* Defines a field that can hold a value from a specified set of string literals.
|
|
153
|
+
* @param {() => readonly valueType[]} optionalValues - A function that returns an array of allowed string literals.
|
|
154
|
+
* @returns {ClassFieldDecorator<entityType, valueType | undefined>} - A class field decorator.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
|
|
158
|
+
* class MyEntity {
|
|
159
|
+
* .@Fields.literal(() => ['open', 'closed', 'frozen', 'in progress'] as const)
|
|
160
|
+
* status: 'open' | 'closed' | 'frozen' | 'in progress' = 'open';
|
|
161
|
+
* }
|
|
162
|
+
|
|
163
|
+
*
|
|
164
|
+
* // This defines a field `status` in `MyEntity` that can only hold the values 'open', 'closed', 'frozen', or 'in progress'.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* // For better reusability and maintainability:
|
|
168
|
+
|
|
169
|
+
* const statuses = ['open', 'closed', 'frozen', 'in progress'] as const;
|
|
170
|
+
* type StatusType = typeof statuses[number];
|
|
171
|
+
*
|
|
172
|
+
* class MyEntity {
|
|
173
|
+
* .@Fields.literal(() => statuses)
|
|
174
|
+
* status: StatusType = 'open';
|
|
175
|
+
* }
|
|
176
|
+
|
|
177
|
+
*
|
|
178
|
+
* // This approach allows easy management and updates of the allowed values for the `status` field.
|
|
179
|
+
*/
|
|
180
|
+
Fields.literal = function (optionalValues) {
|
|
181
|
+
var _a;
|
|
182
|
+
var options = [];
|
|
183
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
184
|
+
options[_i - 1] = arguments[_i];
|
|
185
|
+
}
|
|
186
|
+
return Fields.string.apply(Fields, tslib_1.__spreadArray([(_a = {},
|
|
187
|
+
//@ts-ignore
|
|
188
|
+
_a[addValidatorKey_js_1.addValidatorKey] = function (entity, event) { return validators_js_1.Validators.in(optionalValues())(entity, event); },
|
|
189
|
+
_a)], tslib_1.__read(options), false));
|
|
190
|
+
};
|
|
191
|
+
Fields.enum = function (enumType) {
|
|
192
|
+
var _a;
|
|
193
|
+
var options = [];
|
|
194
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
195
|
+
options[_i - 1] = arguments[_i];
|
|
196
|
+
}
|
|
197
|
+
var valueConverter;
|
|
198
|
+
return Field.apply(void 0, tslib_1.__spreadArray(tslib_1.__spreadArray([function () {
|
|
199
|
+
//@ts-ignore
|
|
200
|
+
return (enumType());
|
|
201
|
+
}, (_a = {},
|
|
202
|
+
_a[addValidatorKey_js_1.addValidatorKey] = function (entity, event) { return validators_js_1.Validators.enum(enumType())(entity, event); },
|
|
203
|
+
_a)], tslib_1.__read(options), false), [function (options) {
|
|
204
|
+
if (valueConverter === undefined) {
|
|
205
|
+
var enumObj_1 = enumType();
|
|
206
|
+
var enumValues = Object.values(enumObj_1)
|
|
207
|
+
.filter(function (x) { return typeof enumObj_1[x] !== 'number'; });
|
|
208
|
+
valueConverter = enumValues.find(function (x) { return typeof x === "string"; }) ? valueConverters_js_1.ValueConverters.String : valueConverters_js_1.ValueConverters.Integer;
|
|
209
|
+
}
|
|
210
|
+
if (!options.valueConverter) {
|
|
211
|
+
options.valueConverter = valueConverter;
|
|
212
|
+
}
|
|
213
|
+
else if (!options.valueConverter.fieldTypeInDb) {
|
|
214
|
+
//@ts-ignore
|
|
215
|
+
options.valueConverter.fieldTypeInDb = valueConverter.fieldTypeInDb;
|
|
216
|
+
}
|
|
217
|
+
}], false));
|
|
218
|
+
};
|
|
145
219
|
Fields.string = function () {
|
|
146
220
|
var options = [];
|
|
147
221
|
for (var _i = 0; _i < arguments.length; _i++) {
|
|
@@ -251,6 +325,9 @@ function Field(valueType) {
|
|
|
251
325
|
if (r.required) {
|
|
252
326
|
r.validate = addValidator(r.validate, validators_js_1.Validators.required);
|
|
253
327
|
}
|
|
328
|
+
if (r[addValidatorKey_js_1.addValidatorKey]) {
|
|
329
|
+
r.validate = addValidator(r.validate, r[addValidatorKey_js_1.addValidatorKey]);
|
|
330
|
+
}
|
|
254
331
|
if (r.maxLength) {
|
|
255
332
|
r.validate = addValidator(r.validate, validators_js_1.Validators.maxLength(r.maxLength));
|
|
256
333
|
}
|
|
@@ -47,7 +47,9 @@ export declare class RepositoryImplementation<entityType> implements Repository<
|
|
|
47
47
|
insert(item: Partial<MembersOnly<entityType>>): Promise<entityType>;
|
|
48
48
|
get fields(): FieldsMetadata<entityType>;
|
|
49
49
|
validate(entity: Partial<MembersOnly<entityType>>, ...fields: Extract<keyof MembersOnly<entityType>, string>[]): Promise<ErrorInfo<entityType> | undefined>;
|
|
50
|
-
updateMany(where
|
|
50
|
+
updateMany({ where }: {
|
|
51
|
+
where: EntityFilter<entityType>;
|
|
52
|
+
}, set: Partial<MembersOnly<entityType>>): Promise<number>;
|
|
51
53
|
update(id: idType<entityType>, item: Partial<MembersOnly<entityType>>): Promise<entityType>;
|
|
52
54
|
update(originalItem: Partial<MembersOnly<entityType>>, item: Partial<MembersOnly<entityType>>): Promise<entityType>;
|
|
53
55
|
private _getRefForExistingRow;
|
|
@@ -63,7 +65,9 @@ export declare class RepositoryImplementation<entityType> implements Repository<
|
|
|
63
65
|
toJson(item: entityType | entityType[] | Promise<entityType> | Promise<entityType[]>): any;
|
|
64
66
|
fromJson(json: any, newRow?: boolean): any;
|
|
65
67
|
count(where?: EntityFilter<entityType>): Promise<number>;
|
|
66
|
-
deleteMany(where
|
|
68
|
+
deleteMany({ where }: {
|
|
69
|
+
where: EntityFilter<entityType>;
|
|
70
|
+
}): Promise<number>;
|
|
67
71
|
private _cache;
|
|
68
72
|
findOne(options?: FindFirstOptions<entityType>, skipOrderByAndLimit?: boolean): Promise<entityType>;
|
|
69
73
|
findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>, skipOrderByAndLimit?: boolean): Promise<entityType>;
|
|
@@ -18,6 +18,7 @@ var relation_loader_js_1 = require("./relation-loader.js");
|
|
|
18
18
|
var repository_internals_js_1 = require("./repository-internals.js");
|
|
19
19
|
var filter_consumer_bridge_to_sql_request_js_1 = require("../filter/filter-consumer-bridge-to-sql-request.js");
|
|
20
20
|
var remult_static_js_1 = require("../remult-static.js");
|
|
21
|
+
var validators_js_1 = require("../validators.js");
|
|
21
22
|
//import { remult } from "../remult-proxy";
|
|
22
23
|
var classValidatorValidate = undefined;
|
|
23
24
|
// import ("class-validator".toString())
|
|
@@ -435,52 +436,53 @@ var RepositoryImplementation = /** @class */ (function () {
|
|
|
435
436
|
});
|
|
436
437
|
});
|
|
437
438
|
};
|
|
438
|
-
RepositoryImplementation.prototype.updateMany = function (
|
|
439
|
-
var
|
|
439
|
+
RepositoryImplementation.prototype.updateMany = function (_a, set) {
|
|
440
|
+
var _b, e_7, _c, _d;
|
|
441
|
+
var where = _a.where;
|
|
440
442
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
441
|
-
var
|
|
442
|
-
return tslib_1.__generator(this, function (
|
|
443
|
-
switch (
|
|
443
|
+
var _e, _f, updated, _g, _h, _j, item, e_7_1;
|
|
444
|
+
return tslib_1.__generator(this, function (_k) {
|
|
445
|
+
switch (_k.label) {
|
|
444
446
|
case 0:
|
|
445
447
|
filter_interfaces_js_1.Filter.throwErrorIfFilterIsEmpty(where, 'updateMany');
|
|
446
448
|
if (!this._dataProvider.isProxy) return [3 /*break*/, 2];
|
|
447
|
-
|
|
449
|
+
_f = (_e = this._edp).updateMany;
|
|
448
450
|
return [4 /*yield*/, this._translateWhereToFilter(where)];
|
|
449
|
-
case 1: return [2 /*return*/,
|
|
451
|
+
case 1: return [2 /*return*/, _f.apply(_e, [_k.sent(), set])];
|
|
450
452
|
case 2:
|
|
451
453
|
updated = 0;
|
|
452
|
-
|
|
454
|
+
_k.label = 3;
|
|
453
455
|
case 3:
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
case 4: return [4 /*yield*/,
|
|
456
|
+
_k.trys.push([3, 9, 10, 15]);
|
|
457
|
+
_g = true, _h = tslib_1.__asyncValues(this.query({ where: where }));
|
|
458
|
+
_k.label = 4;
|
|
459
|
+
case 4: return [4 /*yield*/, _h.next()];
|
|
458
460
|
case 5:
|
|
459
|
-
if (!(
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
item =
|
|
461
|
+
if (!(_j = _k.sent(), _b = _j.done, !_b)) return [3 /*break*/, 8];
|
|
462
|
+
_d = _j.value;
|
|
463
|
+
_g = false;
|
|
464
|
+
item = _d;
|
|
463
465
|
(0, assign_js_1.assign)(item, set);
|
|
464
466
|
return [4 /*yield*/, (0, getEntityRef_js_1.getEntityRef)(item).save()];
|
|
465
467
|
case 6:
|
|
466
|
-
|
|
468
|
+
_k.sent();
|
|
467
469
|
updated++;
|
|
468
|
-
|
|
470
|
+
_k.label = 7;
|
|
469
471
|
case 7:
|
|
470
|
-
|
|
472
|
+
_g = true;
|
|
471
473
|
return [3 /*break*/, 4];
|
|
472
474
|
case 8: return [3 /*break*/, 15];
|
|
473
475
|
case 9:
|
|
474
|
-
e_7_1 =
|
|
476
|
+
e_7_1 = _k.sent();
|
|
475
477
|
e_7 = { error: e_7_1 };
|
|
476
478
|
return [3 /*break*/, 15];
|
|
477
479
|
case 10:
|
|
478
|
-
|
|
479
|
-
if (!(!
|
|
480
|
-
return [4 /*yield*/,
|
|
480
|
+
_k.trys.push([10, , 13, 14]);
|
|
481
|
+
if (!(!_g && !_b && (_c = _h.return))) return [3 /*break*/, 12];
|
|
482
|
+
return [4 /*yield*/, _c.call(_h)];
|
|
481
483
|
case 11:
|
|
482
|
-
|
|
483
|
-
|
|
484
|
+
_k.sent();
|
|
485
|
+
_k.label = 12;
|
|
484
486
|
case 12: return [3 /*break*/, 14];
|
|
485
487
|
case 13:
|
|
486
488
|
if (e_7) throw e_7.error;
|
|
@@ -1087,51 +1089,52 @@ var RepositoryImplementation = /** @class */ (function () {
|
|
|
1087
1089
|
});
|
|
1088
1090
|
});
|
|
1089
1091
|
};
|
|
1090
|
-
RepositoryImplementation.prototype.deleteMany = function (
|
|
1091
|
-
var
|
|
1092
|
+
RepositoryImplementation.prototype.deleteMany = function (_a) {
|
|
1093
|
+
var _b, e_18, _c, _d;
|
|
1094
|
+
var where = _a.where;
|
|
1092
1095
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
1093
|
-
var
|
|
1094
|
-
return tslib_1.__generator(this, function (
|
|
1095
|
-
switch (
|
|
1096
|
+
var _e, _f, deleted, _g, _h, _j, item, e_18_1;
|
|
1097
|
+
return tslib_1.__generator(this, function (_k) {
|
|
1098
|
+
switch (_k.label) {
|
|
1096
1099
|
case 0:
|
|
1097
1100
|
filter_interfaces_js_1.Filter.throwErrorIfFilterIsEmpty(where, 'deleteMany');
|
|
1098
1101
|
if (!this._dataProvider.isProxy) return [3 /*break*/, 2];
|
|
1099
|
-
|
|
1102
|
+
_f = (_e = this._edp).deleteMany;
|
|
1100
1103
|
return [4 /*yield*/, this._translateWhereToFilter(where)];
|
|
1101
|
-
case 1: return [2 /*return*/,
|
|
1104
|
+
case 1: return [2 /*return*/, _f.apply(_e, [_k.sent()])];
|
|
1102
1105
|
case 2:
|
|
1103
1106
|
deleted = 0;
|
|
1104
|
-
|
|
1107
|
+
_k.label = 3;
|
|
1105
1108
|
case 3:
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
case 4: return [4 /*yield*/,
|
|
1109
|
+
_k.trys.push([3, 9, 10, 15]);
|
|
1110
|
+
_g = true, _h = tslib_1.__asyncValues(this.query({ where: where }));
|
|
1111
|
+
_k.label = 4;
|
|
1112
|
+
case 4: return [4 /*yield*/, _h.next()];
|
|
1110
1113
|
case 5:
|
|
1111
|
-
if (!(
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
item =
|
|
1114
|
+
if (!(_j = _k.sent(), _b = _j.done, !_b)) return [3 /*break*/, 8];
|
|
1115
|
+
_d = _j.value;
|
|
1116
|
+
_g = false;
|
|
1117
|
+
item = _d;
|
|
1115
1118
|
return [4 /*yield*/, (0, getEntityRef_js_1.getEntityRef)(item).delete()];
|
|
1116
1119
|
case 6:
|
|
1117
|
-
|
|
1120
|
+
_k.sent();
|
|
1118
1121
|
deleted++;
|
|
1119
|
-
|
|
1122
|
+
_k.label = 7;
|
|
1120
1123
|
case 7:
|
|
1121
|
-
|
|
1124
|
+
_g = true;
|
|
1122
1125
|
return [3 /*break*/, 4];
|
|
1123
1126
|
case 8: return [3 /*break*/, 15];
|
|
1124
1127
|
case 9:
|
|
1125
|
-
e_18_1 =
|
|
1128
|
+
e_18_1 = _k.sent();
|
|
1126
1129
|
e_18 = { error: e_18_1 };
|
|
1127
1130
|
return [3 /*break*/, 15];
|
|
1128
1131
|
case 10:
|
|
1129
|
-
|
|
1130
|
-
if (!(!
|
|
1131
|
-
return [4 /*yield*/,
|
|
1132
|
+
_k.trys.push([10, , 13, 14]);
|
|
1133
|
+
if (!(!_g && !_b && (_c = _h.return))) return [3 /*break*/, 12];
|
|
1134
|
+
return [4 /*yield*/, _c.call(_h)];
|
|
1132
1135
|
case 11:
|
|
1133
|
-
|
|
1134
|
-
|
|
1136
|
+
_k.sent();
|
|
1137
|
+
_k.label = 12;
|
|
1135
1138
|
case 12: return [3 /*break*/, 14];
|
|
1136
1139
|
case 13:
|
|
1137
1140
|
if (e_18) throw e_18.error;
|
|
@@ -3247,6 +3250,7 @@ function ValueListFieldType() {
|
|
|
3247
3250
|
;
|
|
3248
3251
|
(o.valueConverter = ValueListInfo.get(type)),
|
|
3249
3252
|
(o.displayValue = function (item, val) { return val === null || val === void 0 ? void 0 : val.caption; });
|
|
3253
|
+
o.validate = function (entity, ref) { return validators_js_1.Validators.in(ValueListInfo.get(type).getValues())(entity, ref); };
|
|
3250
3254
|
}], tslib_1.__read(options), false))(type, context);
|
|
3251
3255
|
};
|
|
3252
3256
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const addValidatorKey = "__addValidator";
|
package/src/remult3/remult3.d.ts
CHANGED
|
@@ -315,14 +315,18 @@ export interface Repository<entityType> {
|
|
|
315
315
|
/**
|
|
316
316
|
* Updates all items that match the `where` condition.
|
|
317
317
|
*/
|
|
318
|
-
updateMany(
|
|
318
|
+
updateMany(options: {
|
|
319
|
+
where: EntityFilter<entityType>;
|
|
320
|
+
}, item: Partial<MembersOnly<entityType>>): Promise<number>;
|
|
319
321
|
/** Deletes an Item*/
|
|
320
322
|
delete(id: idType<entityType>): Promise<void>;
|
|
321
323
|
delete(item: Partial<MembersOnly<entityType>>): Promise<void>;
|
|
322
324
|
/**
|
|
323
325
|
* Deletes all items that match the `where` condition.
|
|
324
326
|
*/
|
|
325
|
-
deleteMany(
|
|
327
|
+
deleteMany(options: {
|
|
328
|
+
where: EntityFilter<entityType>;
|
|
329
|
+
}): Promise<number>;
|
|
326
330
|
/** Creates an instance of an item. It'll not be saved to the data source unless `save` or `insert` will be called for that item */
|
|
327
331
|
create(item?: Partial<MembersOnly<entityType>>): entityType;
|
|
328
332
|
toJson(item: Promise<entityType[]>): Promise<any[]>;
|
package/src/remult3/remult3.js
CHANGED
|
@@ -1,45 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//p1 -
|
|
3
|
+
//p1 - `preprocessApiFindOptions`, naming - allow find options preprocessor for api calls, to use for authorization
|
|
4
|
+
//p1 - admin url1 - pocketbase use /_ for the admin //{allowed?:Allowed,url?:string}
|
|
5
|
+
//p1 - Validate for NAN
|
|
6
|
+
//p1 - Make async hooks gracefully handle non async hooks environment
|
|
7
|
+
//p1 - chain validators with options
|
|
8
|
+
//y2 - should we validate relations
|
|
9
|
+
//y1 - consider replacing all errors with error classes that extend the base Error class
|
|
10
|
+
//y2 - consider if field types should include validation in them by default (string,number that it's not NaN etc...) and if so, what message?
|
|
11
|
+
//y2 - should enforce integer - currently we probably round / truncate it
|
|
12
|
+
/*y1 - talk about modules in init express with entities/controllers,initRequest,initApi
|
|
13
|
+
- support get with backend method, with url search params as the first parameter, & url as second parameter
|
|
14
|
+
- support returning redirect, and plain html (For sign in scenarios)
|
|
15
|
+
|
|
16
|
+
*/
|
|
4
17
|
//p1 - in this video I'll use remult to turn a frontend app to a fullstack app
|
|
5
18
|
//y1 - getFields didn't work for kobi in the home component
|
|
6
|
-
//y1 - consider replacing all errors with error classes that extend the base Error class
|
|
7
19
|
//p1 - document offline support
|
|
8
|
-
//p1 - add section to Fields doc, explaining field type in db
|
|
9
|
-
//p1 - add section about union type
|
|
10
|
-
//p1 - add section about value list field type
|
|
11
20
|
/*y1 - Talk JYC - JYC - add some integrity checks on delete
|
|
12
21
|
- soft delete
|
|
13
22
|
- delete restrict (implicit, or user selected - and if so, how) (delete & update of id)
|
|
14
23
|
|
|
15
24
|
*/
|
|
16
|
-
/*y1 currency.ts:10 Uncaught TypeError: Currency_1 is not a constructor
|
|
17
|
-
// - ValueListFieldType - the decorator gives an error in react vite project - see langulage yedidya
|
|
18
|
-
// happens in target 2022, ts<5.1.6
|
|
19
|
-
//typescript 5.1.6
|
|
20
|
-
@ValueListFieldType()
|
|
21
|
-
export class Currency {
|
|
22
|
-
constructor(
|
|
23
|
-
public id: number,
|
|
24
|
-
public caption: string,
|
|
25
|
-
public symbol: string
|
|
26
|
-
) {}
|
|
27
|
-
static shekel = new Currency(1, 'Shekel', '₪');
|
|
28
|
-
static dollar = new Currency(2, 'Dollar', '$');
|
|
29
|
-
static euro = new Currency(3, 'Euro', '€');
|
|
30
|
-
static pound = new Currency(4, 'Pound', '£');
|
|
31
|
-
static yen = new Currency(5, 'Yen', '¥');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
//y1 - allow api read to also support instance and filter. - problem with promise
|
|
36
|
-
//y1 - admin url1 - pocketbase use /_ for the admin
|
|
37
25
|
//y1 - consider sql expression gets a dbnames of it's own (that already has the "tableName" defined correctly) maybe also the filter translator
|
|
38
|
-
/*y1 - talk about modules in init express with entities/controllers,initRequest,initApi
|
|
39
|
-
- support get with backend method, with url search params as the first parameter, & url as second parameter
|
|
40
|
-
- support returning redirect, and plain html (For sign in scenarios)
|
|
41
|
-
|
|
42
|
-
*/
|
|
43
26
|
//y1 - tried to upgrade vitest, nuxt tests are failing with loading uuid - sounds familiar?
|
|
44
27
|
//y1 - I think that the tests you've setup don't cover next app router - I added to the setup, but not sure where else
|
|
45
28
|
//y1 - talk about the parameter issue with backend methods
|
|
@@ -54,8 +37,6 @@ export class Currency {
|
|
|
54
37
|
})
|
|
55
38
|
Description = ""*/
|
|
56
39
|
//y2 - get backend methods to work when specifying types for date, and entities as poco's
|
|
57
|
-
//y2 - 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
|
|
58
|
-
//y2 - #239 - (@JY) add a way to get from fieldMetadata back to entity repo (like we have in fieldRef)
|
|
59
40
|
//y2 - constraints (@JY)
|
|
60
41
|
/*p2 remult admin
|
|
61
42
|
|
|
@@ -70,11 +51,9 @@ export class Currency {
|
|
|
70
51
|
- remult-admin didn't show a update for a table with a uniqua that is numeric
|
|
71
52
|
*/
|
|
72
53
|
//remult
|
|
73
|
-
//p1 - better support union types (status, etc... so it'll work also in filter etc...)
|
|
74
54
|
//p1 - when a tasks table exists in a different schema - we get many errors
|
|
75
55
|
//p1 - live query with include
|
|
76
56
|
//p1 - adjust angular tutorial starter kit for latest angular (as is in tutorial)
|
|
77
|
-
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
78
57
|
//p2 - when subscribe is forbidden - the query still runs after the renew process
|
|
79
58
|
//p2 - 'update tasks set where id = $1
|
|
80
59
|
//p2 - type metadata.key - to keyof entity - based on cwis input
|
|
@@ -82,23 +61,15 @@ export class Currency {
|
|
|
82
61
|
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
83
62
|
//p2 - allowApiUpdate should be false for include in api false
|
|
84
63
|
//docs
|
|
85
|
-
//p2 - make sure that internal members do not appear in the documentation - try running it on the d.ts instead of the code itself.
|
|
86
64
|
//------
|
|
87
65
|
//y2 - from the crm-demo(https://crm-demo.up.railway.app/deals), after editing a deal: - _updateEntityBasedOnApi
|
|
88
66
|
//y2 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
89
67
|
//y2 - how to run a transaction as a user
|
|
90
|
-
//p2 - enum column
|
|
91
|
-
//y2 - message for invalid value
|
|
92
68
|
//y2 - message for relation that is missing
|
|
93
69
|
//y2 - consider multi tenancies
|
|
94
|
-
//p2 - more column types
|
|
95
|
-
//p2 - document validators
|
|
96
70
|
//p2 - and validators to reference
|
|
97
71
|
//y2 - discuss a default date formatter
|
|
98
72
|
//y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
|
|
99
73
|
//[ ] V2 - what to do about for relations count?
|
|
100
74
|
//[ ] V2 - condition? not to fetch if null etc....
|
|
101
|
-
//[ ] V3 - all these fields will also appear in the where etc... in the typescript api - but we will not enforce them
|
|
102
|
-
//y2 - consider if field types should include validation in them by default (string,number that it's not NaN etc...) and if so, what message?
|
|
103
|
-
//y2 - should enforce integer - currently we probably round / truncate it
|
|
104
75
|
//p1 - adjust react tutorial to esm
|
package/src/validators.js
CHANGED
|
@@ -48,7 +48,9 @@ var Validators = /** @class */ (function () {
|
|
|
48
48
|
});
|
|
49
49
|
Validators.email = createValueValidator(function (val) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val); }, 'Invalid Email');
|
|
50
50
|
Validators.url = createValueValidator(function (val) { return !!new URL(val); }, 'Invalid Url');
|
|
51
|
-
Validators.in = createValueValidatorWithArgs(function (val, values) { return values.includes(val); }, function (values) { return "Value must be one of ".concat(values.
|
|
51
|
+
Validators.in = createValueValidatorWithArgs(function (val, values) { return values.includes(val); }, function (values) { return "Value must be one of ".concat(values.map(function (y) {
|
|
52
|
+
return typeof y === "object" ? y['id'] !== undefined ? y['id'] : y.toString() : y;
|
|
53
|
+
}).join(', ')); });
|
|
52
54
|
Validators.notNull = createValueValidator(function (val) { return val != null; }, 'Should not be null');
|
|
53
55
|
Validators.enum = createValueValidatorWithArgs(function (value, enumObj) { return Object.values(enumObj).includes(value); }, function (enumObj) {
|
|
54
56
|
return "Value must be one of ".concat(Object.values(enumObj)
|