remult 3.4.0-next.9 → 3.4.1
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/internals.js +1 -0
- package/esm/remult-knex/index.js +46 -73
- package/esm/src/data-api.js +42 -31
- package/esm/src/data-providers/sql-database.js +44 -39
- package/esm/src/filter/filter-consumer-bridge-to-sql-request.js +35 -34
- package/esm/src/filter/walk-filter.js +29 -0
- package/esm/src/valueConverters.js +11 -0
- package/internals.d.ts +1 -0
- package/internals.js +4 -1
- package/package.json +1 -1
- package/remult-knex/index.d.ts +3 -2
- package/remult-knex/index.js +118 -164
- package/src/data-api.d.ts +4 -0
- package/src/data-api.js +51 -48
- package/src/data-providers/sql-database.d.ts +16 -7
- package/src/data-providers/sql-database.js +100 -90
- package/src/filter/filter-consumer-bridge-to-sql-request.d.ts +8 -3
- package/src/filter/filter-consumer-bridge-to-sql-request.js +40 -47
- package/src/filter/walk-filter.d.ts +3 -0
- package/src/filter/walk-filter.js +56 -0
- package/src/sql-command.d.ts +5 -0
- package/src/valueConverters.d.ts +4 -1
- package/src/valueConverters.js +13 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CustomSqlFilterBuilder = exports.FilterConsumerBridgeToSqlRequest = void 0;
|
|
3
|
+
exports.CustomSqlFilterBuilder = exports.FilterConsumerBridgeToSqlRequest = exports.LIKE_ESCAPE_SQL = void 0;
|
|
4
|
+
exports.escapeLike = escapeLike;
|
|
4
5
|
exports.isDbReadonly = isDbReadonly;
|
|
5
6
|
exports.shouldNotCreateField = shouldNotCreateField;
|
|
6
7
|
exports.shouldCreateEntity = shouldCreateEntity;
|
|
@@ -11,12 +12,24 @@ var tslib_1 = require("tslib");
|
|
|
11
12
|
var sql_database_js_1 = require("../data-providers/sql-database.js");
|
|
12
13
|
var remult_proxy_js_1 = require("../remult-proxy.js");
|
|
13
14
|
var RepositoryImplementation_js_1 = require("../remult3/RepositoryImplementation.js");
|
|
15
|
+
var valueConverters_js_1 = require("../valueConverters.js");
|
|
14
16
|
var entityDbName_js_1 = require("./entityDbName.js");
|
|
15
17
|
var fieldDbName_js_1 = require("./fieldDbName.js");
|
|
18
|
+
// `[` starts a character class in sql server's like. `]` on its own is a literal
|
|
19
|
+
// everywhere, so escaping the opening bracket is enough. The other engines treat
|
|
20
|
+
// an escaped non-wildcard as that literal, so one escape set works for all of them.
|
|
21
|
+
var REGEX_LIKE_SPECIAL = /[!%_\[]/g;
|
|
22
|
+
// `!` not `\`: a backslash in a string literal is an escape in mysql and in pg without standard_conforming_strings
|
|
23
|
+
exports.LIKE_ESCAPE_SQL = " escape '!'";
|
|
24
|
+
function escapeLike(val) {
|
|
25
|
+
return val.replace(REGEX_LIKE_SPECIAL, '!$&');
|
|
26
|
+
}
|
|
16
27
|
var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
17
|
-
function FilterConsumerBridgeToSqlRequest(r, nameProvider) {
|
|
28
|
+
function FilterConsumerBridgeToSqlRequest(r, nameProvider, jsonColumnStorage) {
|
|
29
|
+
if (jsonColumnStorage === void 0) { jsonColumnStorage = 'native'; }
|
|
18
30
|
this.r = r;
|
|
19
31
|
this.nameProvider = nameProvider;
|
|
32
|
+
this.jsonColumnStorage = jsonColumnStorage;
|
|
20
33
|
this.where = '';
|
|
21
34
|
this._addWhere = true;
|
|
22
35
|
this.promises = [];
|
|
@@ -81,7 +94,7 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
81
94
|
case 1:
|
|
82
95
|
if (!!orElements_1_1.done) return [3 /*break*/, 4];
|
|
83
96
|
element = orElements_1_1.value;
|
|
84
|
-
f = new FilterConsumerBridgeToSqlRequest(this.r, this.nameProvider);
|
|
97
|
+
f = new FilterConsumerBridgeToSqlRequest(this.r, this.nameProvider, this.jsonColumnStorage);
|
|
85
98
|
f._addWhere = false;
|
|
86
99
|
element.__applyToConsumer(f);
|
|
87
100
|
return [4 /*yield*/, f.resolveWhere()];
|
|
@@ -128,7 +141,7 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
128
141
|
return tslib_1.__generator(this, function (_a) {
|
|
129
142
|
switch (_a.label) {
|
|
130
143
|
case 0:
|
|
131
|
-
f = new FilterConsumerBridgeToSqlRequest(this.r, this.nameProvider);
|
|
144
|
+
f = new FilterConsumerBridgeToSqlRequest(this.r, this.nameProvider, this.jsonColumnStorage);
|
|
132
145
|
f._addWhere = false;
|
|
133
146
|
element.__applyToConsumer(f);
|
|
134
147
|
return [4 /*yield*/, f.resolveWhere()];
|
|
@@ -163,7 +176,9 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
163
176
|
this.addToWhere(this.nameProvider.$dbNameOf(col) +
|
|
164
177
|
' in (' +
|
|
165
178
|
val
|
|
166
|
-
.map(function (x) {
|
|
179
|
+
.map(function (x) {
|
|
180
|
+
return toDbSql(_this.r, col, (0, valueConverters_js_1.toDbColumn)(col, x, _this.jsonColumnStorage));
|
|
181
|
+
})
|
|
167
182
|
.join(',') +
|
|
168
183
|
')');
|
|
169
184
|
else
|
|
@@ -191,53 +206,29 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
191
206
|
this.add(col, val, '<');
|
|
192
207
|
};
|
|
193
208
|
FilterConsumerBridgeToSqlRequest.prototype.containsCaseInsensitive = function (col, val) {
|
|
194
|
-
|
|
195
|
-
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
196
|
-
return tslib_1.__generator(this, function (_a) {
|
|
197
|
-
this.addToWhere('lower (' +
|
|
198
|
-
this.nameProvider.$dbNameOf(col) +
|
|
199
|
-
") like lower ('%" +
|
|
200
|
-
val.replace(/'/g, "''") +
|
|
201
|
-
"%')");
|
|
202
|
-
return [2 /*return*/];
|
|
203
|
-
});
|
|
204
|
-
}); })());
|
|
209
|
+
this.like(col, '%' + escapeLike(val) + '%');
|
|
205
210
|
};
|
|
206
211
|
FilterConsumerBridgeToSqlRequest.prototype.notContainsCaseInsensitive = function (col, val) {
|
|
207
|
-
|
|
208
|
-
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
209
|
-
return tslib_1.__generator(this, function (_a) {
|
|
210
|
-
this.addToWhere('not lower (' +
|
|
211
|
-
this.nameProvider.$dbNameOf(col) +
|
|
212
|
-
") like lower ('%" +
|
|
213
|
-
val.replace(/'/g, "''") +
|
|
214
|
-
"%')");
|
|
215
|
-
return [2 /*return*/];
|
|
216
|
-
});
|
|
217
|
-
}); })());
|
|
212
|
+
this.like(col, '%' + escapeLike(val) + '%', 'not ');
|
|
218
213
|
};
|
|
219
214
|
FilterConsumerBridgeToSqlRequest.prototype.startsWithCaseInsensitive = function (col, val) {
|
|
220
|
-
|
|
221
|
-
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
222
|
-
return tslib_1.__generator(this, function (_a) {
|
|
223
|
-
this.addToWhere('lower (' +
|
|
224
|
-
this.nameProvider.$dbNameOf(col) +
|
|
225
|
-
") like lower ('" +
|
|
226
|
-
val.replace(/'/g, "''") +
|
|
227
|
-
"%')");
|
|
228
|
-
return [2 /*return*/];
|
|
229
|
-
});
|
|
230
|
-
}); })());
|
|
215
|
+
this.like(col, escapeLike(val) + '%');
|
|
231
216
|
};
|
|
232
217
|
FilterConsumerBridgeToSqlRequest.prototype.endsWithCaseInsensitive = function (col, val) {
|
|
218
|
+
this.like(col, '%' + escapeLike(val));
|
|
219
|
+
};
|
|
220
|
+
FilterConsumerBridgeToSqlRequest.prototype.like = function (col, pattern, not) {
|
|
233
221
|
var _this = this;
|
|
222
|
+
if (not === void 0) { not = ''; }
|
|
234
223
|
this.promises.push((function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
235
224
|
return tslib_1.__generator(this, function (_a) {
|
|
236
|
-
this.addToWhere(
|
|
225
|
+
this.addToWhere(not +
|
|
226
|
+
'lower (' +
|
|
237
227
|
this.nameProvider.$dbNameOf(col) +
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
228
|
+
') like lower (' +
|
|
229
|
+
this.r.param(pattern) +
|
|
230
|
+
')' +
|
|
231
|
+
exports.LIKE_ESCAPE_SQL);
|
|
241
232
|
return [2 /*return*/];
|
|
242
233
|
});
|
|
243
234
|
}); })());
|
|
@@ -251,7 +242,7 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
251
242
|
' ' +
|
|
252
243
|
operator +
|
|
253
244
|
' ' +
|
|
254
|
-
toDbSql(this.r, col,
|
|
245
|
+
toDbSql(this.r, col, (0, valueConverters_js_1.toDbColumn)(col, val, this.jsonColumnStorage));
|
|
255
246
|
this.addToWhere(x);
|
|
256
247
|
return [2 /*return*/];
|
|
257
248
|
});
|
|
@@ -274,7 +265,7 @@ var FilterConsumerBridgeToSqlRequest = /** @class */ (function () {
|
|
|
274
265
|
switch (_a.label) {
|
|
275
266
|
case 0:
|
|
276
267
|
if (!(databaseCustom === null || databaseCustom === void 0 ? void 0 : databaseCustom.buildSql)) return [3 /*break*/, 2];
|
|
277
|
-
item = new CustomSqlFilterBuilder(this.r, this.nameProvider.wrapIdentifier);
|
|
268
|
+
item = new CustomSqlFilterBuilder(this.r, this.nameProvider.wrapIdentifier, this.jsonColumnStorage);
|
|
278
269
|
return [4 /*yield*/, databaseCustom.buildSql(item)];
|
|
279
270
|
case 1:
|
|
280
271
|
sql = _a.sent();
|
|
@@ -296,10 +287,12 @@ exports.FilterConsumerBridgeToSqlRequest = FilterConsumerBridgeToSqlRequest;
|
|
|
296
287
|
* Represents a custom SQL filter builder.
|
|
297
288
|
*/
|
|
298
289
|
var CustomSqlFilterBuilder = /** @class */ (function () {
|
|
299
|
-
function CustomSqlFilterBuilder(r, wrapIdentifier) {
|
|
290
|
+
function CustomSqlFilterBuilder(r, wrapIdentifier, jsonColumnStorage) {
|
|
291
|
+
if (jsonColumnStorage === void 0) { jsonColumnStorage = 'native'; }
|
|
300
292
|
var _this = this;
|
|
301
293
|
this.r = r;
|
|
302
294
|
this.wrapIdentifier = wrapIdentifier;
|
|
295
|
+
this.jsonColumnStorage = jsonColumnStorage;
|
|
303
296
|
this.sql = '';
|
|
304
297
|
/**
|
|
305
298
|
* Adds a parameter value.
|
|
@@ -308,8 +301,8 @@ var CustomSqlFilterBuilder = /** @class */ (function () {
|
|
|
308
301
|
* @returns {string} - The SQL token.
|
|
309
302
|
*/
|
|
310
303
|
this.param = function (val, field) {
|
|
311
|
-
if (
|
|
312
|
-
val =
|
|
304
|
+
if (field) {
|
|
305
|
+
val = (0, valueConverters_js_1.toDbColumn)(field, val, _this.jsonColumnStorage);
|
|
313
306
|
}
|
|
314
307
|
return _this.r.param(val);
|
|
315
308
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.omitFilterField = void 0;
|
|
4
|
+
exports.walkFilter = walkFilter;
|
|
5
|
+
var tslib_1 = require("tslib");
|
|
6
|
+
/** Return this from {@link walkFilter}'s visitor to drop that field key. */
|
|
7
|
+
exports.omitFilterField = Symbol('omitFilterField');
|
|
8
|
+
function isCompoundFilterKey(key) {
|
|
9
|
+
return key === '$and' || key === '$or' || key === '$not';
|
|
10
|
+
}
|
|
11
|
+
// `$and`, `$or`, and `$not` are entered. Every other key is a field, passed to `visit`.
|
|
12
|
+
// `visit` returns the value to keep, or `omitFilterField` to drop the key.
|
|
13
|
+
function walkFilter(filter, visit) {
|
|
14
|
+
var e_1, _a, e_2, _b;
|
|
15
|
+
if (Array.isArray(filter)) {
|
|
16
|
+
var result_1 = [];
|
|
17
|
+
try {
|
|
18
|
+
for (var filter_1 = tslib_1.__values(filter), filter_1_1 = filter_1.next(); !filter_1_1.done; filter_1_1 = filter_1.next()) {
|
|
19
|
+
var item = filter_1_1.value;
|
|
20
|
+
result_1.push(walkFilter(item, visit));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
24
|
+
finally {
|
|
25
|
+
try {
|
|
26
|
+
if (filter_1_1 && !filter_1_1.done && (_a = filter_1.return)) _a.call(filter_1);
|
|
27
|
+
}
|
|
28
|
+
finally { if (e_1) throw e_1.error; }
|
|
29
|
+
}
|
|
30
|
+
return result_1;
|
|
31
|
+
}
|
|
32
|
+
if (!filter || typeof filter !== 'object')
|
|
33
|
+
return filter;
|
|
34
|
+
var result = {};
|
|
35
|
+
try {
|
|
36
|
+
for (var _c = tslib_1.__values(Object.keys(filter)), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
37
|
+
var key = _d.value;
|
|
38
|
+
var value = filter[key];
|
|
39
|
+
if (isCompoundFilterKey(key)) {
|
|
40
|
+
result[key] = walkFilter(value, visit);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
var next = visit(key, value);
|
|
44
|
+
if (next !== exports.omitFilterField)
|
|
45
|
+
result[key] = next;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
49
|
+
finally {
|
|
50
|
+
try {
|
|
51
|
+
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
|
|
52
|
+
}
|
|
53
|
+
finally { if (e_2) throw e_2.error; }
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
package/src/sql-command.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export interface SqlImplementation extends HasWrapIdentifier {
|
|
|
18
18
|
export interface HasWrapIdentifier {
|
|
19
19
|
wrapIdentifier?(name: string): string;
|
|
20
20
|
}
|
|
21
|
+
/** How a provider stores `Fields.json`: a real json column, a text column, or text only on write (mysql2 parses on read). */
|
|
22
|
+
export type JsonColumnStorage = 'native' | 'text' | 'textOnWrite';
|
|
23
|
+
export interface HasJsonColumnStorage {
|
|
24
|
+
jsonColumnStorage: JsonColumnStorage;
|
|
25
|
+
}
|
|
21
26
|
export interface SqlCommandFactory extends HasWrapIdentifier {
|
|
22
27
|
createCommand(): SqlCommand;
|
|
23
28
|
execute(sql: string): Promise<SqlResult>;
|
package/src/valueConverters.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ValueConverter } from './column-interfaces.js';
|
|
1
|
+
import type { FieldMetadata, ValueConverter } from './column-interfaces.js';
|
|
2
|
+
import type { JsonColumnStorage } from './sql-command.js';
|
|
2
3
|
export declare class ValueConverters {
|
|
3
4
|
static readonly Date: ValueConverter<Date>;
|
|
4
5
|
static readonly DateOnly: ValueConverter<Date>;
|
|
@@ -13,3 +14,5 @@ export declare class ValueConverters {
|
|
|
13
14
|
static readonly JsonString: ValueConverter<any>;
|
|
14
15
|
static readonly JsonValue: ValueConverter<any>;
|
|
15
16
|
}
|
|
17
|
+
export declare function fromDbColumn(field: FieldMetadata, value: any, storage: JsonColumnStorage): any;
|
|
18
|
+
export declare function toDbColumn(field: FieldMetadata, value: any, storage: JsonColumnStorage): any;
|
package/src/valueConverters.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ValueConverters = void 0;
|
|
4
|
+
exports.fromDbColumn = fromDbColumn;
|
|
5
|
+
exports.toDbColumn = toDbColumn;
|
|
4
6
|
var tslib_1 = require("tslib");
|
|
5
7
|
var inputTypes_js_1 = require("../inputTypes.js");
|
|
6
8
|
var zeroDate = new Date('0000-01-01');
|
|
@@ -213,6 +215,17 @@ var ValueConverters = /** @class */ (function () {
|
|
|
213
215
|
return ValueConverters;
|
|
214
216
|
}());
|
|
215
217
|
exports.ValueConverters = ValueConverters;
|
|
218
|
+
function fromDbColumn(field, value, storage) {
|
|
219
|
+
if (storage === 'text' && field.valueConverter.fieldTypeInDb === 'json')
|
|
220
|
+
return ValueConverters.JsonString.fromDb(value);
|
|
221
|
+
return field.valueConverter.fromDb(value);
|
|
222
|
+
}
|
|
223
|
+
function toDbColumn(field, value, storage) {
|
|
224
|
+
if ((storage === 'text' || storage === 'textOnWrite') &&
|
|
225
|
+
field.valueConverter.fieldTypeInDb === 'json')
|
|
226
|
+
return ValueConverters.JsonString.toDb(value);
|
|
227
|
+
return field.valueConverter.toDb(value);
|
|
228
|
+
}
|
|
216
229
|
function enforceString(value) {
|
|
217
230
|
if (value === null || value === undefined)
|
|
218
231
|
return value;
|