remult 0.25.8-exp.7 → 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 +2 -0
- package/esm/src/remult3/addValidatorKey.js +1 -0
- package/esm/src/remult3/remult3.js +14 -45
- 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.js +2 -0
- package/src/remult3/addValidatorKey.d.ts +1 -0
- package/src/remult3/addValidatorKey.js +4 -0
- package/src/remult3/remult3.js +14 -45
- 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())
|
|
@@ -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,46 +1,27 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//p1 -
|
|
3
|
-
//p1 -
|
|
4
|
-
//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
|
+
*/
|
|
5
16
|
//p1 - in this video I'll use remult to turn a frontend app to a fullstack app
|
|
6
17
|
//y1 - getFields didn't work for kobi in the home component
|
|
7
|
-
//y1 - consider replacing all errors with error classes that extend the base Error class
|
|
8
18
|
//p1 - document offline support
|
|
9
|
-
//p1 - add section to Fields doc, explaining field type in db
|
|
10
|
-
//p1 - add section about union type
|
|
11
|
-
//p1 - add section about value list field type
|
|
12
19
|
/*y1 - Talk JYC - JYC - add some integrity checks on delete
|
|
13
20
|
- soft delete
|
|
14
21
|
- delete restrict (implicit, or user selected - and if so, how) (delete & update of id)
|
|
15
22
|
|
|
16
23
|
*/
|
|
17
|
-
/*y1 currency.ts:10 Uncaught TypeError: Currency_1 is not a constructor
|
|
18
|
-
// - ValueListFieldType - the decorator gives an error in react vite project - see langulage yedidya
|
|
19
|
-
// happens in target 2022, ts<5.1.6
|
|
20
|
-
//typescript 5.1.6
|
|
21
|
-
@ValueListFieldType()
|
|
22
|
-
export class Currency {
|
|
23
|
-
constructor(
|
|
24
|
-
public id: number,
|
|
25
|
-
public caption: string,
|
|
26
|
-
public symbol: string
|
|
27
|
-
) {}
|
|
28
|
-
static shekel = new Currency(1, 'Shekel', '₪');
|
|
29
|
-
static dollar = new Currency(2, 'Dollar', '$');
|
|
30
|
-
static euro = new Currency(3, 'Euro', '€');
|
|
31
|
-
static pound = new Currency(4, 'Pound', '£');
|
|
32
|
-
static yen = new Currency(5, 'Yen', '¥');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
*/
|
|
36
|
-
//y1 - allow api read to also support instance and filter. - problem with promise
|
|
37
|
-
//y1 - admin url1 - pocketbase use /_ for the admin
|
|
38
24
|
//y1 - consider sql expression gets a dbnames of it's own (that already has the "tableName" defined correctly) maybe also the filter translator
|
|
39
|
-
/*y1 - talk about modules in init express with entities/controllers,initRequest,initApi
|
|
40
|
-
- support get with backend method, with url search params as the first parameter, & url as second parameter
|
|
41
|
-
- support returning redirect, and plain html (For sign in scenarios)
|
|
42
|
-
|
|
43
|
-
*/
|
|
44
25
|
//y1 - tried to upgrade vitest, nuxt tests are failing with loading uuid - sounds familiar?
|
|
45
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
|
|
46
27
|
//y1 - talk about the parameter issue with backend methods
|
|
@@ -55,8 +36,6 @@ export class Currency {
|
|
|
55
36
|
})
|
|
56
37
|
Description = ""*/
|
|
57
38
|
//y2 - get backend methods to work when specifying types for date, and entities as poco's
|
|
58
|
-
//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
|
|
59
|
-
//y2 - #239 - (@JY) add a way to get from fieldMetadata back to entity repo (like we have in fieldRef)
|
|
60
39
|
//y2 - constraints (@JY)
|
|
61
40
|
/*p2 remult admin
|
|
62
41
|
|
|
@@ -71,11 +50,9 @@ export class Currency {
|
|
|
71
50
|
- remult-admin didn't show a update for a table with a uniqua that is numeric
|
|
72
51
|
*/
|
|
73
52
|
//remult
|
|
74
|
-
//p1 - better support union types (status, etc... so it'll work also in filter etc...)
|
|
75
53
|
//p1 - when a tasks table exists in a different schema - we get many errors
|
|
76
54
|
//p1 - live query with include
|
|
77
55
|
//p1 - adjust angular tutorial starter kit for latest angular (as is in tutorial)
|
|
78
|
-
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
79
56
|
//p2 - when subscribe is forbidden - the query still runs after the renew process
|
|
80
57
|
//p2 - 'update tasks set where id = $1
|
|
81
58
|
//p2 - type metadata.key - to keyof entity - based on cwis input
|
|
@@ -83,23 +60,15 @@ export class Currency {
|
|
|
83
60
|
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
84
61
|
//p2 - allowApiUpdate should be false for include in api false
|
|
85
62
|
//docs
|
|
86
|
-
//p2 - make sure that internal members do not appear in the documentation - try running it on the d.ts instead of the code itself.
|
|
87
63
|
//------
|
|
88
64
|
//y2 - from the crm-demo(https://crm-demo.up.railway.app/deals), after editing a deal: - _updateEntityBasedOnApi
|
|
89
65
|
//y2 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
90
66
|
//y2 - how to run a transaction as a user
|
|
91
|
-
//p2 - enum column
|
|
92
|
-
//y2 - message for invalid value
|
|
93
67
|
//y2 - message for relation that is missing
|
|
94
68
|
//y2 - consider multi tenancies
|
|
95
|
-
//p2 - more column types
|
|
96
|
-
//p2 - document validators
|
|
97
69
|
//p2 - and validators to reference
|
|
98
70
|
//y2 - discuss a default date formatter
|
|
99
71
|
//y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
|
|
100
72
|
//[ ] V2 - what to do about for relations count?
|
|
101
73
|
//[ ] V2 - condition? not to fetch if null etc....
|
|
102
|
-
//[ ] V3 - all these fields will also appear in the where etc... in the typescript api - but we will not enforce them
|
|
103
|
-
//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?
|
|
104
|
-
//y2 - should enforce integer - currently we probably round / truncate it
|
|
105
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
|
}
|
|
@@ -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())
|
|
@@ -3249,6 +3250,7 @@ function ValueListFieldType() {
|
|
|
3249
3250
|
;
|
|
3250
3251
|
(o.valueConverter = ValueListInfo.get(type)),
|
|
3251
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); };
|
|
3252
3254
|
}], tslib_1.__read(options), false))(type, context);
|
|
3253
3255
|
};
|
|
3254
3256
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const addValidatorKey = "__addValidator";
|
package/src/remult3/remult3.js
CHANGED
|
@@ -1,47 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//p1 -
|
|
4
|
-
//p1 -
|
|
5
|
-
//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
|
+
*/
|
|
6
17
|
//p1 - in this video I'll use remult to turn a frontend app to a fullstack app
|
|
7
18
|
//y1 - getFields didn't work for kobi in the home component
|
|
8
|
-
//y1 - consider replacing all errors with error classes that extend the base Error class
|
|
9
19
|
//p1 - document offline support
|
|
10
|
-
//p1 - add section to Fields doc, explaining field type in db
|
|
11
|
-
//p1 - add section about union type
|
|
12
|
-
//p1 - add section about value list field type
|
|
13
20
|
/*y1 - Talk JYC - JYC - add some integrity checks on delete
|
|
14
21
|
- soft delete
|
|
15
22
|
- delete restrict (implicit, or user selected - and if so, how) (delete & update of id)
|
|
16
23
|
|
|
17
24
|
*/
|
|
18
|
-
/*y1 currency.ts:10 Uncaught TypeError: Currency_1 is not a constructor
|
|
19
|
-
// - ValueListFieldType - the decorator gives an error in react vite project - see langulage yedidya
|
|
20
|
-
// happens in target 2022, ts<5.1.6
|
|
21
|
-
//typescript 5.1.6
|
|
22
|
-
@ValueListFieldType()
|
|
23
|
-
export class Currency {
|
|
24
|
-
constructor(
|
|
25
|
-
public id: number,
|
|
26
|
-
public caption: string,
|
|
27
|
-
public symbol: string
|
|
28
|
-
) {}
|
|
29
|
-
static shekel = new Currency(1, 'Shekel', '₪');
|
|
30
|
-
static dollar = new Currency(2, 'Dollar', '$');
|
|
31
|
-
static euro = new Currency(3, 'Euro', '€');
|
|
32
|
-
static pound = new Currency(4, 'Pound', '£');
|
|
33
|
-
static yen = new Currency(5, 'Yen', '¥');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
*/
|
|
37
|
-
//y1 - allow api read to also support instance and filter. - problem with promise
|
|
38
|
-
//y1 - admin url1 - pocketbase use /_ for the admin
|
|
39
25
|
//y1 - consider sql expression gets a dbnames of it's own (that already has the "tableName" defined correctly) maybe also the filter translator
|
|
40
|
-
/*y1 - talk about modules in init express with entities/controllers,initRequest,initApi
|
|
41
|
-
- support get with backend method, with url search params as the first parameter, & url as second parameter
|
|
42
|
-
- support returning redirect, and plain html (For sign in scenarios)
|
|
43
|
-
|
|
44
|
-
*/
|
|
45
26
|
//y1 - tried to upgrade vitest, nuxt tests are failing with loading uuid - sounds familiar?
|
|
46
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
|
|
47
28
|
//y1 - talk about the parameter issue with backend methods
|
|
@@ -56,8 +37,6 @@ export class Currency {
|
|
|
56
37
|
})
|
|
57
38
|
Description = ""*/
|
|
58
39
|
//y2 - get backend methods to work when specifying types for date, and entities as poco's
|
|
59
|
-
//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
|
|
60
|
-
//y2 - #239 - (@JY) add a way to get from fieldMetadata back to entity repo (like we have in fieldRef)
|
|
61
40
|
//y2 - constraints (@JY)
|
|
62
41
|
/*p2 remult admin
|
|
63
42
|
|
|
@@ -72,11 +51,9 @@ export class Currency {
|
|
|
72
51
|
- remult-admin didn't show a update for a table with a uniqua that is numeric
|
|
73
52
|
*/
|
|
74
53
|
//remult
|
|
75
|
-
//p1 - better support union types (status, etc... so it'll work also in filter etc...)
|
|
76
54
|
//p1 - when a tasks table exists in a different schema - we get many errors
|
|
77
55
|
//p1 - live query with include
|
|
78
56
|
//p1 - adjust angular tutorial starter kit for latest angular (as is in tutorial)
|
|
79
|
-
//p2 - allow find options preprocessor for api calls, to use for authorization
|
|
80
57
|
//p2 - when subscribe is forbidden - the query still runs after the renew process
|
|
81
58
|
//p2 - 'update tasks set where id = $1
|
|
82
59
|
//p2 - type metadata.key - to keyof entity - based on cwis input
|
|
@@ -84,23 +61,15 @@ export class Currency {
|
|
|
84
61
|
//p2 - when value changes for field with error, clear error - so the user will feel comfortable
|
|
85
62
|
//p2 - allowApiUpdate should be false for include in api false
|
|
86
63
|
//docs
|
|
87
|
-
//p2 - make sure that internal members do not appear in the documentation - try running it on the d.ts instead of the code itself.
|
|
88
64
|
//------
|
|
89
65
|
//y2 - from the crm-demo(https://crm-demo.up.railway.app/deals), after editing a deal: - _updateEntityBasedOnApi
|
|
90
66
|
//y2 - Backend methods are transactions, it's not intuitive and maybe should be optional / opt in
|
|
91
67
|
//y2 - how to run a transaction as a user
|
|
92
|
-
//p2 - enum column
|
|
93
|
-
//y2 - message for invalid value
|
|
94
68
|
//y2 - message for relation that is missing
|
|
95
69
|
//y2 - consider multi tenancies
|
|
96
|
-
//p2 - more column types
|
|
97
|
-
//p2 - document validators
|
|
98
70
|
//p2 - and validators to reference
|
|
99
71
|
//y2 - discuss a default date formatter
|
|
100
72
|
//y2 - add some api testing framework for user unit tests (will help with codesandbox based discussions)
|
|
101
73
|
//[ ] V2 - what to do about for relations count?
|
|
102
74
|
//[ ] V2 - condition? not to fetch if null etc....
|
|
103
|
-
//[ ] V3 - all these fields will also appear in the where etc... in the typescript api - but we will not enforce them
|
|
104
|
-
//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?
|
|
105
|
-
//y2 - should enforce integer - currently we probably round / truncate it
|
|
106
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)
|