remult 0.13.29 → 0.13.31
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/package.json +1 -1
- package/remult-middleware.d.ts +2 -0
- package/remult-middleware.js +64 -0
- package/server/expressBridge.d.ts +1 -0
- package/server/expressBridge.js +18 -16
- package/src/column-interfaces.d.ts +3 -3
- package/src/data-providers/web-sql-data-provider.js +4 -3
- package/src/entity.d.ts +11 -4
- package/src/remult3/RepositoryImplementation.d.ts +6 -5
- package/src/remult3/RepositoryImplementation.js +17 -8
- package/src/remult3/remult3.d.ts +8 -3
- package/src/shared-tests/test-update-with-null.spec.js +38 -0
- package/valueConverters.js +4 -0
package/package.json
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { remultMiddlewareBase } from './server/expressBridge';
|
|
2
|
+
export function remultMiddleware(options) {
|
|
3
|
+
const m = new middleware();
|
|
4
|
+
let app = Object.assign(m, (req, res, next) => m.handleRequest(req, res, next));
|
|
5
|
+
return remultMiddlewareBase(app, options);
|
|
6
|
+
}
|
|
7
|
+
class middleware {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.map = new Map();
|
|
10
|
+
}
|
|
11
|
+
route(path) {
|
|
12
|
+
//consider using:
|
|
13
|
+
//* https://raw.githubusercontent.com/cmorten/opine/main/src/utils/pathToRegex.ts
|
|
14
|
+
//* https://github.com/pillarjs/path-to-regexp
|
|
15
|
+
let r = path.toLowerCase();
|
|
16
|
+
let m = new Map();
|
|
17
|
+
this.map.set(r, m);
|
|
18
|
+
const route = {
|
|
19
|
+
get: (h) => {
|
|
20
|
+
m.set("get", h);
|
|
21
|
+
return route;
|
|
22
|
+
},
|
|
23
|
+
put: (h) => {
|
|
24
|
+
m.set("put", h);
|
|
25
|
+
return route;
|
|
26
|
+
},
|
|
27
|
+
post: (h) => {
|
|
28
|
+
m.set("post", h);
|
|
29
|
+
return route;
|
|
30
|
+
},
|
|
31
|
+
delete: (h) => {
|
|
32
|
+
m.set("delete", h);
|
|
33
|
+
return route;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return route;
|
|
37
|
+
}
|
|
38
|
+
handleRequest(req, res, next) {
|
|
39
|
+
let lowerPath = req.path.toLowerCase();
|
|
40
|
+
let m = this.map.get(lowerPath);
|
|
41
|
+
if (m) {
|
|
42
|
+
let h = m.get(req.method.toLowerCase());
|
|
43
|
+
if (h) {
|
|
44
|
+
h(req, res, next);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
let idPosition = req.path.lastIndexOf('/');
|
|
49
|
+
if (idPosition >= 0) {
|
|
50
|
+
lowerPath = req.path.substring(0, idPosition) + '/:id';
|
|
51
|
+
m = this.map.get(lowerPath);
|
|
52
|
+
if (m) {
|
|
53
|
+
let h = m.get(req.method.toLowerCase());
|
|
54
|
+
if (h) {
|
|
55
|
+
req.params.id = req.path.substring(idPosition + 1);
|
|
56
|
+
h(req, res, next);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
console.log(req.path);
|
|
62
|
+
next();
|
|
63
|
+
}
|
|
64
|
+
}
|
package/server/expressBridge.js
CHANGED
|
@@ -93,11 +93,14 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
93
93
|
ExpressBridge.prototype.openApiDoc = function (options) {
|
|
94
94
|
var e_1, _a, e_2, _b;
|
|
95
95
|
var r = new __1.Remult();
|
|
96
|
+
if (!options.version)
|
|
97
|
+
options.version = "1.0.0";
|
|
96
98
|
var spec = {
|
|
97
|
-
info: { title: options.title },
|
|
99
|
+
info: { title: options.title, version: options.version },
|
|
98
100
|
openapi: "3.0.0",
|
|
99
101
|
//swagger: "2.0",
|
|
100
102
|
"components": {
|
|
103
|
+
"schemas": {},
|
|
101
104
|
"securitySchemes": {
|
|
102
105
|
"bearerAuth": {
|
|
103
106
|
"scheme": "bearer",
|
|
@@ -106,8 +109,7 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
},
|
|
109
|
-
paths: {}
|
|
110
|
-
definitions: {}
|
|
112
|
+
paths: {}
|
|
111
113
|
};
|
|
112
114
|
var validationError = {
|
|
113
115
|
"400": {
|
|
@@ -115,7 +117,7 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
115
117
|
"content": {
|
|
116
118
|
"application/json": {
|
|
117
119
|
"schema": {
|
|
118
|
-
"$ref": "#/
|
|
120
|
+
"$ref": "#/components/schemas/InvalidResponse"
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
}
|
|
@@ -182,12 +184,12 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
182
184
|
}
|
|
183
185
|
finally { if (e_3) throw e_3.error; }
|
|
184
186
|
}
|
|
185
|
-
spec.
|
|
187
|
+
spec.components.schemas[key] = {
|
|
186
188
|
type: "object",
|
|
187
189
|
properties: properties
|
|
188
190
|
};
|
|
189
191
|
var definition = {
|
|
190
|
-
"$ref": "#/
|
|
192
|
+
"$ref": "#/components/schemas/" + key
|
|
191
193
|
};
|
|
192
194
|
var secure = function (condition, def, item) {
|
|
193
195
|
item.tags = [meta.key];
|
|
@@ -206,28 +208,28 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
206
208
|
"description": "limit the number of returned rows, default 100",
|
|
207
209
|
"required": false,
|
|
208
210
|
"style": "simple",
|
|
209
|
-
"type": "
|
|
211
|
+
"schema": { "type": "integer" }
|
|
210
212
|
},
|
|
211
213
|
{
|
|
212
214
|
"name": "_page",
|
|
213
215
|
"in": "query",
|
|
214
216
|
"description": "to be used for paging",
|
|
215
217
|
"required": false,
|
|
216
|
-
"type": "
|
|
218
|
+
"schema": { "type": "integer" }
|
|
217
219
|
},
|
|
218
220
|
{
|
|
219
221
|
"name": "_sort",
|
|
220
222
|
"in": "query",
|
|
221
223
|
"description": "the columns to sort on",
|
|
222
224
|
"required": false,
|
|
223
|
-
"type": "string"
|
|
225
|
+
"schema": { "type": "string" }
|
|
224
226
|
},
|
|
225
227
|
{
|
|
226
228
|
"name": "_order",
|
|
227
229
|
"in": "query",
|
|
228
230
|
"description": "the sort order to user for the columns in `_sort`",
|
|
229
231
|
"required": false,
|
|
230
|
-
"type": "string"
|
|
232
|
+
"schema": { "type": "string" }
|
|
231
233
|
}], parameters),
|
|
232
234
|
responses: {
|
|
233
235
|
"200": {
|
|
@@ -248,14 +250,14 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
248
250
|
"in": "path",
|
|
249
251
|
"description": "id of " + key,
|
|
250
252
|
"required": true,
|
|
251
|
-
"type": "string"
|
|
253
|
+
"schema": { "type": "string" },
|
|
252
254
|
};
|
|
253
255
|
var itemInBody = {
|
|
254
256
|
"requestBody": {
|
|
255
257
|
"content": {
|
|
256
258
|
"application/json": {
|
|
257
259
|
"schema": {
|
|
258
|
-
"$ref": "#/
|
|
260
|
+
"$ref": "#/components/schemas/" + key
|
|
259
261
|
}
|
|
260
262
|
}
|
|
261
263
|
}
|
|
@@ -269,7 +271,7 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
269
271
|
"content": {
|
|
270
272
|
"application/json": {
|
|
271
273
|
"schema": {
|
|
272
|
-
"$ref": "#/
|
|
274
|
+
"$ref": "#/components/schemas/" + key
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
}
|
|
@@ -282,7 +284,7 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
282
284
|
"content": {
|
|
283
285
|
"application/json": {
|
|
284
286
|
"schema": {
|
|
285
|
-
"$ref": "#/
|
|
287
|
+
"$ref": "#/components/schemas/" + key
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
290
|
}
|
|
@@ -299,7 +301,7 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
299
301
|
"content": {
|
|
300
302
|
"application/json": {
|
|
301
303
|
"schema": {
|
|
302
|
-
"$ref": "#/
|
|
304
|
+
"$ref": "#/components/schemas/" + key
|
|
303
305
|
}
|
|
304
306
|
}
|
|
305
307
|
}
|
|
@@ -378,7 +380,7 @@ var ExpressBridge = /** @class */ (function () {
|
|
|
378
380
|
}
|
|
379
381
|
finally { if (e_2) throw e_2.error; }
|
|
380
382
|
}
|
|
381
|
-
spec.
|
|
383
|
+
spec.components.schemas["InvalidResponse"] = {
|
|
382
384
|
"type": "object",
|
|
383
385
|
properties: {
|
|
384
386
|
"message": {
|
|
@@ -14,18 +14,18 @@ export interface FieldOptions<entityType = any, valueType = any> {
|
|
|
14
14
|
allowApiUpdate?: AllowedForInstance<entityType>;
|
|
15
15
|
/** An arrow function that'll be used to perform validations on it
|
|
16
16
|
* @example
|
|
17
|
-
*
|
|
17
|
+
* @Fields.string({
|
|
18
18
|
* validate: Validators.required
|
|
19
19
|
* })
|
|
20
20
|
* @example
|
|
21
|
-
*
|
|
21
|
+
* @Fields.string<Task>({
|
|
22
22
|
* validate: task=>{
|
|
23
23
|
* if (task.title.length<3)
|
|
24
24
|
* throw "Too Short";
|
|
25
25
|
* }
|
|
26
26
|
* })
|
|
27
27
|
* @example
|
|
28
|
-
*
|
|
28
|
+
* @Fields.string({
|
|
29
29
|
* validate: (_, fieldRef)=>{
|
|
30
30
|
* if (fieldRef.value.length<3)
|
|
31
31
|
* fieldRef.error = "Too Short";
|
|
@@ -109,15 +109,16 @@ var WebSqlDataProvider = /** @class */ (function () {
|
|
|
109
109
|
};
|
|
110
110
|
WebSqlDataProvider.prototype.addColumnSqlSyntax = function (x, dbName) {
|
|
111
111
|
var result = dbName;
|
|
112
|
+
var nullNumber = x.allowNull ? "" : " default 0 not null";
|
|
112
113
|
if (x.valueType == Date)
|
|
113
114
|
result += " integer";
|
|
114
115
|
else if (x.valueType == Boolean)
|
|
115
|
-
result += " integer
|
|
116
|
+
result += " integer " + nullNumber;
|
|
116
117
|
else if (x.valueType == Number) {
|
|
117
118
|
if (!x.valueConverter.fieldTypeInDb)
|
|
118
|
-
result += ' real
|
|
119
|
+
result += ' real ' + nullNumber;
|
|
119
120
|
else
|
|
120
|
-
result += ' ' + x.valueConverter.fieldTypeInDb + '
|
|
121
|
+
result += ' ' + x.valueConverter.fieldTypeInDb + ' ' + nullNumber;
|
|
121
122
|
}
|
|
122
123
|
else
|
|
123
124
|
result += " text" + (x.allowNull ? " " : " default '' not null ");
|
package/src/entity.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface EntityOptions<entityType = any> {
|
|
|
29
29
|
apiPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
|
|
30
30
|
/** A filter that will be used for all queries from this entity both from the API and from within the backend.
|
|
31
31
|
* @example
|
|
32
|
-
*
|
|
32
|
+
* backendPrefilter: { archive:false }
|
|
33
33
|
* @see [EntityFilter](http://remult.dev/docs/entityFilter.html)
|
|
34
34
|
*/
|
|
35
35
|
backendPrefilter?: EntityFilter<entityType> | (() => EntityFilter<entityType> | Promise<EntityFilter<entityType>>);
|
|
@@ -45,7 +45,7 @@ export interface EntityOptions<entityType = any> {
|
|
|
45
45
|
* If the `error` property of the entity's ref or any of it's fields will be set, the save will be aborted and an exception will be thrown.
|
|
46
46
|
* this is the place to run logic that we want to run in any case before an entity is saved.
|
|
47
47
|
* @example
|
|
48
|
-
*
|
|
48
|
+
* @Entity<Task>("tasks", {
|
|
49
49
|
* saving: async task => {
|
|
50
50
|
* task.lastUpdated = new Date()
|
|
51
51
|
* }
|
|
@@ -68,8 +68,15 @@ export interface EntityOptions<entityType = any> {
|
|
|
68
68
|
dbName?: string;
|
|
69
69
|
/** For entities that are based on SQL expressions instead of a physical table or view*/
|
|
70
70
|
sqlExpression?: string | ((entity: FieldsMetadata<entityType>) => string | Promise<string>);
|
|
71
|
-
/** An arrow function that identifies the `id` column to use for this entity
|
|
72
|
-
|
|
71
|
+
/** An arrow function that identifies the `id` column to use for this entity
|
|
72
|
+
* @example
|
|
73
|
+
* //Single column id
|
|
74
|
+
* @Entity<Products>("products", { id:p=>p.productCode })
|
|
75
|
+
* @example
|
|
76
|
+
* //Multiple columns id
|
|
77
|
+
* @Entity<OrderDetails>("orderDetails", { id:od=> [od.orderId, od.productCode] })
|
|
78
|
+
*/
|
|
79
|
+
id?: (entity: FieldsMetadata<entityType>) => FieldMetadata | FieldMetadata[];
|
|
73
80
|
entityRefInit?: (ref: EntityRef<entityType>, row: entityType) => void;
|
|
74
81
|
apiRequireId?: Allowed;
|
|
75
82
|
}
|
|
@@ -256,11 +256,11 @@ export declare function getValueList<T>(type: ClassType<T>): T[];
|
|
|
256
256
|
* FieldOptions can be set in two ways:
|
|
257
257
|
* @example
|
|
258
258
|
* // as an object
|
|
259
|
-
*
|
|
259
|
+
* @Fields.string({ includeInApi:false })
|
|
260
260
|
* title='';
|
|
261
261
|
* @example
|
|
262
262
|
* // as an arrow function that receives `remult` as a parameter
|
|
263
|
-
*
|
|
263
|
+
* @Fields.string((options,remult) => options.includeInApi = true)
|
|
264
264
|
* title='';
|
|
265
265
|
*/
|
|
266
266
|
export declare function Field<entityType = any, valueType = any>(valueType: () => ClassType<valueType>, ...options: (FieldOptions<entityType, valueType> | ((options: FieldOptions<entityType, valueType>, remult: Remult) => void))[]): (target: any, key: any, c?: any) => void;
|
|
@@ -289,13 +289,14 @@ export declare function BuildEntity<entityType>(c: ClassType<entityType>, key: s
|
|
|
289
289
|
* @Fields.boolean()
|
|
290
290
|
* completed = false;
|
|
291
291
|
* }
|
|
292
|
-
*
|
|
292
|
+
* @note
|
|
293
|
+
* EntityOptions can be set in two ways:
|
|
293
294
|
* @example
|
|
294
295
|
* // as an object
|
|
295
|
-
*
|
|
296
|
+
* @Entity("tasks",{ allowApiCrud:true })
|
|
296
297
|
* @example
|
|
297
298
|
* // as an arrow function that receives `remult` as a parameter
|
|
298
|
-
*
|
|
299
|
+
* @Entity("tasks", (options,remult) => options.allowApiCrud = true)
|
|
299
300
|
*/
|
|
300
301
|
export declare function Entity<entityType>(key: string, ...options: (EntityOptions<entityType> | ((options: EntityOptions<entityType>, remult: Remult) => void))[]): (target: any) => any;
|
|
301
302
|
export declare class EntityBase {
|
|
@@ -2181,7 +2181,15 @@ var EntityFullInfo = /** @class */ (function () {
|
|
|
2181
2181
|
this.fields = r;
|
|
2182
2182
|
this.caption = buildCaption(entityInfo.caption, this.key, remult);
|
|
2183
2183
|
if (entityInfo.id) {
|
|
2184
|
-
|
|
2184
|
+
var r_2 = entityInfo.id(this.fields);
|
|
2185
|
+
if (Array.isArray(r_2)) {
|
|
2186
|
+
if (r_2.length > 1)
|
|
2187
|
+
this.idMetadata.field = new (column_1.CompoundIdField.bind.apply(column_1.CompoundIdField, tslib_1.__spread([void 0], r_2)))();
|
|
2188
|
+
else if (r_2.length == 1)
|
|
2189
|
+
this.idMetadata.field = r_2[0];
|
|
2190
|
+
}
|
|
2191
|
+
else
|
|
2192
|
+
this.idMetadata.field = r_2;
|
|
2185
2193
|
}
|
|
2186
2194
|
else {
|
|
2187
2195
|
if (this.fields["id"])
|
|
@@ -2331,8 +2339,8 @@ var Fields = /** @class */ (function () {
|
|
|
2331
2339
|
}());
|
|
2332
2340
|
exports.Fields = Fields;
|
|
2333
2341
|
function isAutoIncrement(f) {
|
|
2334
|
-
var _a;
|
|
2335
|
-
return ((_a = f.options
|
|
2342
|
+
var _a, _b;
|
|
2343
|
+
return ((_b = (_a = f.options) === null || _a === void 0 ? void 0 : _a.valueConverter) === null || _b === void 0 ? void 0 : _b.fieldTypeInDb) === 'autoincrement';
|
|
2336
2344
|
}
|
|
2337
2345
|
exports.isAutoIncrement = isAutoIncrement;
|
|
2338
2346
|
function ValueListFieldType() {
|
|
@@ -2467,11 +2475,11 @@ exports.getValueList = getValueList;
|
|
|
2467
2475
|
* FieldOptions can be set in two ways:
|
|
2468
2476
|
* @example
|
|
2469
2477
|
* // as an object
|
|
2470
|
-
*
|
|
2478
|
+
* @Fields.string({ includeInApi:false })
|
|
2471
2479
|
* title='';
|
|
2472
2480
|
* @example
|
|
2473
2481
|
* // as an arrow function that receives `remult` as a parameter
|
|
2474
|
-
*
|
|
2482
|
+
* @Fields.string((options,remult) => options.includeInApi = true)
|
|
2475
2483
|
* title='';
|
|
2476
2484
|
*/
|
|
2477
2485
|
function Field(valueType) {
|
|
@@ -2637,13 +2645,14 @@ exports.BuildEntity = BuildEntity;
|
|
|
2637
2645
|
* @Fields.boolean()
|
|
2638
2646
|
* completed = false;
|
|
2639
2647
|
* }
|
|
2640
|
-
*
|
|
2648
|
+
* @note
|
|
2649
|
+
* EntityOptions can be set in two ways:
|
|
2641
2650
|
* @example
|
|
2642
2651
|
* // as an object
|
|
2643
|
-
*
|
|
2652
|
+
* @Entity("tasks",{ allowApiCrud:true })
|
|
2644
2653
|
* @example
|
|
2645
2654
|
* // as an arrow function that receives `remult` as a parameter
|
|
2646
|
-
*
|
|
2655
|
+
* @Entity("tasks", (options,remult) => options.allowApiCrud = true)
|
|
2647
2656
|
*/
|
|
2648
2657
|
function Entity(key) {
|
|
2649
2658
|
var options = [];
|
package/src/remult3/remult3.d.ts
CHANGED
|
@@ -112,7 +112,12 @@ export declare type OmitEB<T> = Omit<T, keyof import('./RepositoryImplementation
|
|
|
112
112
|
export interface Repository<entityType> {
|
|
113
113
|
/** returns a result array based on the provided options */
|
|
114
114
|
find(options?: FindOptions<entityType>): Promise<entityType[]>;
|
|
115
|
-
/** returns the first item that matchers the `where` condition
|
|
115
|
+
/** returns the first item that matchers the `where` condition
|
|
116
|
+
* @example
|
|
117
|
+
* await taskRepo.findFirst({ completed:false })
|
|
118
|
+
* @example
|
|
119
|
+
* await taskRepo.findFirst({ completed:false },{ createIfNotFound: true })
|
|
120
|
+
* */
|
|
116
121
|
findFirst(where?: EntityFilter<entityType>, options?: FindFirstOptions<entityType>): Promise<entityType>;
|
|
117
122
|
/** returns the items that matches the idm the result is cached unless specified differently in the `options` parameter */
|
|
118
123
|
findId(id: entityType extends {
|
|
@@ -285,7 +290,7 @@ export interface QueryResult<entityType> {
|
|
|
285
290
|
[Symbol.asyncIterator](): {
|
|
286
291
|
next: () => Promise<IteratorResult<entityType, entityType>>;
|
|
287
292
|
};
|
|
288
|
-
/** returns the number of rows that match the query
|
|
293
|
+
/** returns the number of rows that match the query criteria */
|
|
289
294
|
count(): Promise<number>;
|
|
290
295
|
/** Returns a `Paginator` object that is used for efficient paging */
|
|
291
296
|
paginator(): Promise<Paginator<entityType>>;
|
|
@@ -300,7 +305,7 @@ export interface Paginator<entityType> {
|
|
|
300
305
|
items: entityType[];
|
|
301
306
|
/** True if next page exists */
|
|
302
307
|
hasNextPage: boolean;
|
|
303
|
-
/**
|
|
308
|
+
/** Gets the next page in the `query`'s result set */
|
|
304
309
|
nextPage(): Promise<Paginator<entityType>>;
|
|
305
310
|
/** the count of the total items in the `query`'s result */
|
|
306
311
|
count(): Promise<number>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
var tslib_1 = require("tslib");
|
|
4
|
+
var sql_database_1 = require("../data-providers/sql-database");
|
|
4
5
|
var remult3_1 = require("../remult3");
|
|
5
6
|
var db_tests_setup_1 = require("./db-tests-setup");
|
|
6
7
|
var testNull = /** @class */ (function (_super) {
|
|
@@ -8,6 +9,7 @@ var testNull = /** @class */ (function (_super) {
|
|
|
8
9
|
function testNull() {
|
|
9
10
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
10
11
|
_this.id = 0;
|
|
12
|
+
_this.numberWithNull = null;
|
|
11
13
|
return _this;
|
|
12
14
|
}
|
|
13
15
|
tslib_1.__decorate([
|
|
@@ -18,6 +20,10 @@ var testNull = /** @class */ (function (_super) {
|
|
|
18
20
|
remult3_1.Field(undefined, { allowNull: true }),
|
|
19
21
|
tslib_1.__metadata("design:type", Object)
|
|
20
22
|
], testNull.prototype, "myCol", void 0);
|
|
23
|
+
tslib_1.__decorate([
|
|
24
|
+
remult3_1.Fields.integer({ allowNull: true }),
|
|
25
|
+
tslib_1.__metadata("design:type", Number)
|
|
26
|
+
], testNull.prototype, "numberWithNull", void 0);
|
|
21
27
|
testNull = tslib_1.__decorate([
|
|
22
28
|
remult3_1.Entity('testNull', { allowApiCrud: true })
|
|
23
29
|
], testNull);
|
|
@@ -49,3 +55,35 @@ db_tests_setup_1.testAll("test that update null works", function (_a) {
|
|
|
49
55
|
});
|
|
50
56
|
});
|
|
51
57
|
}, false);
|
|
58
|
+
db_tests_setup_1.testAll("test number with null", function (_a) {
|
|
59
|
+
var createEntity = _a.createEntity;
|
|
60
|
+
return tslib_1.__awaiter(void 0, void 0, void 0, function () {
|
|
61
|
+
var r, i, _b, _c;
|
|
62
|
+
return tslib_1.__generator(this, function (_d) {
|
|
63
|
+
switch (_d.label) {
|
|
64
|
+
case 0: return [4 /*yield*/, createEntity(testNull)];
|
|
65
|
+
case 1:
|
|
66
|
+
r = _d.sent();
|
|
67
|
+
return [4 /*yield*/, r.insert({ id: 1, myCol: { value: 'abc' }, numberWithNull: null })];
|
|
68
|
+
case 2:
|
|
69
|
+
i = _d.sent();
|
|
70
|
+
expect(i.numberWithNull).toBe(null);
|
|
71
|
+
_b = expect;
|
|
72
|
+
return [4 /*yield*/, r.count({ numberWithNull: null })];
|
|
73
|
+
case 3:
|
|
74
|
+
_b.apply(void 0, [_d.sent()]).toBe(1);
|
|
75
|
+
i.numberWithNull = 0;
|
|
76
|
+
return [4 /*yield*/, i.save()];
|
|
77
|
+
case 4:
|
|
78
|
+
_d.sent();
|
|
79
|
+
expect(i.numberWithNull).toBe(0);
|
|
80
|
+
sql_database_1.SqlDatabase.LogToConsole = true;
|
|
81
|
+
_c = expect;
|
|
82
|
+
return [4 /*yield*/, r.count({ numberWithNull: null })];
|
|
83
|
+
case 5:
|
|
84
|
+
_c.apply(void 0, [_d.sent()]).toBe(0);
|
|
85
|
+
return [2 /*return*/];
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}, false);
|
package/valueConverters.js
CHANGED
|
@@ -86,6 +86,8 @@ var ValueConverters = /** @class */ (function () {
|
|
|
86
86
|
return undefined;
|
|
87
87
|
return val.replace(/-/g, '');
|
|
88
88
|
}, fromDb: function (val) {
|
|
89
|
+
if (val === null)
|
|
90
|
+
return null;
|
|
89
91
|
if (!val)
|
|
90
92
|
return undefined;
|
|
91
93
|
return new Date(val.substring(0, 4) + '-' + val.substring(4, 6) + '-' + val.substring(6, 8));
|
|
@@ -110,6 +112,8 @@ var ValueConverters = /** @class */ (function () {
|
|
|
110
112
|
};
|
|
111
113
|
ValueConverters.Number = {
|
|
112
114
|
fromDb: function (value) {
|
|
115
|
+
if (value === null)
|
|
116
|
+
return null;
|
|
113
117
|
if (value !== undefined)
|
|
114
118
|
return +value;
|
|
115
119
|
return undefined;
|