remult 3.3.14 → 3.3.15
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/remult-node-sqlite.js +55 -0
- package/esm/src/data-api.js +3 -0
- package/esm/src/remult3/RepositoryImplementation.js +7 -3
- package/package.json +6 -1
- package/remult-node-sqlite.d.ts +19 -0
- package/remult-node-sqlite.js +72 -0
- package/src/data-api.js +14 -11
- package/src/remult3/RepositoryImplementation.js +10 -6
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
|
|
2
|
+
/**
|
|
3
|
+
* A Remult data provider for Node's built-in `node:sqlite` module.
|
|
4
|
+
*
|
|
5
|
+
* `node:sqlite` is available in Node.js 22.5.0 and newer. The database is
|
|
6
|
+
* accepted structurally so importing this adapter does not load a Node-only
|
|
7
|
+
* module until the application creates its `DatabaseSync` instance.
|
|
8
|
+
*/
|
|
9
|
+
export class NodeSqliteDataProvider extends SqliteCoreDataProvider {
|
|
10
|
+
constructor(db) {
|
|
11
|
+
super(() => new NodeSqliteCommand(db), async () => {
|
|
12
|
+
db.close();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class NodeSqliteCommand {
|
|
17
|
+
db;
|
|
18
|
+
values = {};
|
|
19
|
+
i = 0;
|
|
20
|
+
constructor(db) {
|
|
21
|
+
this.db = db;
|
|
22
|
+
}
|
|
23
|
+
async execute(sql) {
|
|
24
|
+
const statement = this.db.prepare(sql);
|
|
25
|
+
statement.setAllowBareNamedParameters(true);
|
|
26
|
+
const rows = Object.keys(this.values).length
|
|
27
|
+
? statement.all(this.values)
|
|
28
|
+
: statement.all();
|
|
29
|
+
return new NodeSqliteResult(rows);
|
|
30
|
+
}
|
|
31
|
+
addParameterAndReturnSqlToken(value) {
|
|
32
|
+
return this.param(value);
|
|
33
|
+
}
|
|
34
|
+
param(value) {
|
|
35
|
+
if (value instanceof Date)
|
|
36
|
+
value = value.valueOf();
|
|
37
|
+
if (typeof value === 'boolean')
|
|
38
|
+
value = value ? 1 : 0;
|
|
39
|
+
if (value === undefined)
|
|
40
|
+
value = null;
|
|
41
|
+
const key = String(this.i++);
|
|
42
|
+
this.values[key] = value;
|
|
43
|
+
return `:${key}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
class NodeSqliteResult {
|
|
47
|
+
rows;
|
|
48
|
+
constructor(rows) {
|
|
49
|
+
this.rows = rows;
|
|
50
|
+
}
|
|
51
|
+
getColumnKeyInResultForIndexInSelect(index) {
|
|
52
|
+
const first = this.rows[0];
|
|
53
|
+
return first ? (Object.keys(first)[index] ?? '') : '';
|
|
54
|
+
}
|
|
55
|
+
}
|
package/esm/src/data-api.js
CHANGED
|
@@ -195,6 +195,9 @@ export class DataApi {
|
|
|
195
195
|
if (body?.orderBy) {
|
|
196
196
|
for (const element of body?.orderBy) {
|
|
197
197
|
const direction = element.isDescending ? 'desc' : 'asc';
|
|
198
|
+
if (element.operation !== 'count' &&
|
|
199
|
+
!this.repository.fields.find(element.field)?.includedInApi())
|
|
200
|
+
continue;
|
|
198
201
|
switch (element.operation) {
|
|
199
202
|
case undefined:
|
|
200
203
|
orderBy[element.field] = direction;
|
|
@@ -3,7 +3,7 @@ import { CompoundIdField } from '../CompoundIdField.js';
|
|
|
3
3
|
import { Remult } from '../context.js';
|
|
4
4
|
import { Filter } from '../filter/filter-interfaces.js';
|
|
5
5
|
import { Sort } from '../sort.js';
|
|
6
|
-
import { GroupByForApiKey, } from './remult3.js';
|
|
6
|
+
import { GroupByCountMember, GroupByForApiKey, } from './remult3.js';
|
|
7
7
|
import { assign } from '../../assign.js';
|
|
8
8
|
import { EntityError, } from '../data-interfaces.js';
|
|
9
9
|
import { ValueConverters } from '../valueConverters.js';
|
|
@@ -185,10 +185,14 @@ export class RepositoryImplementation {
|
|
|
185
185
|
const element = options.orderBy[key];
|
|
186
186
|
if (element)
|
|
187
187
|
if (typeof element === 'string') {
|
|
188
|
+
// ordering by a raw column is only valid for grouped fields -
|
|
189
|
+
// skip others so behavior is consistent across data providers
|
|
190
|
+
if (key !== GroupByCountMember && !options?.group?.includes(key))
|
|
191
|
+
continue;
|
|
188
192
|
dpOptions.orderBy.push({
|
|
189
|
-
field: key ===
|
|
193
|
+
field: key === GroupByCountMember ? undefined : getField(key),
|
|
190
194
|
isDescending: element === 'desc',
|
|
191
|
-
operation: key ===
|
|
195
|
+
operation: key === GroupByCountMember ? 'count' : undefined,
|
|
192
196
|
});
|
|
193
197
|
}
|
|
194
198
|
else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remult",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.15",
|
|
4
4
|
"description": "A CRUD framework for full-stack TypeScript",
|
|
5
5
|
"homepage": "https://remult.dev",
|
|
6
6
|
"repository": {
|
|
@@ -112,6 +112,11 @@
|
|
|
112
112
|
"import": "./esm/remult-sqlite-core.js",
|
|
113
113
|
"types": "./remult-sqlite-core.d.ts"
|
|
114
114
|
},
|
|
115
|
+
"./remult-node-sqlite": {
|
|
116
|
+
"require": "./remult-node-sqlite.js",
|
|
117
|
+
"import": "./esm/remult-node-sqlite.js",
|
|
118
|
+
"types": "./remult-node-sqlite.d.ts"
|
|
119
|
+
},
|
|
115
120
|
"./remult-better-sqlite3": {
|
|
116
121
|
"require": "./remult-better-sqlite3.js",
|
|
117
122
|
"import": "./esm/remult-better-sqlite3.js",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SqliteCoreDataProvider } from './remult-sqlite-core.js';
|
|
2
|
+
export type NodeSqliteStatement = {
|
|
3
|
+
setAllowBareNamedParameters(enabled: boolean): void;
|
|
4
|
+
all(...anonymousParameters: any[]): Record<string, unknown>[];
|
|
5
|
+
};
|
|
6
|
+
export type NodeSqliteDatabase = {
|
|
7
|
+
prepare(sql: string): NodeSqliteStatement;
|
|
8
|
+
close(): void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* A Remult data provider for Node's built-in `node:sqlite` module.
|
|
12
|
+
*
|
|
13
|
+
* `node:sqlite` is available in Node.js 22.5.0 and newer. The database is
|
|
14
|
+
* accepted structurally so importing this adapter does not load a Node-only
|
|
15
|
+
* module until the application creates its `DatabaseSync` instance.
|
|
16
|
+
*/
|
|
17
|
+
export declare class NodeSqliteDataProvider extends SqliteCoreDataProvider {
|
|
18
|
+
constructor(db: NodeSqliteDatabase);
|
|
19
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NodeSqliteDataProvider = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
5
|
+
var remult_sqlite_core_js_1 = require("./remult-sqlite-core.js");
|
|
6
|
+
/**
|
|
7
|
+
* A Remult data provider for Node's built-in `node:sqlite` module.
|
|
8
|
+
*
|
|
9
|
+
* `node:sqlite` is available in Node.js 22.5.0 and newer. The database is
|
|
10
|
+
* accepted structurally so importing this adapter does not load a Node-only
|
|
11
|
+
* module until the application creates its `DatabaseSync` instance.
|
|
12
|
+
*/
|
|
13
|
+
var NodeSqliteDataProvider = /** @class */ (function (_super) {
|
|
14
|
+
tslib_1.__extends(NodeSqliteDataProvider, _super);
|
|
15
|
+
function NodeSqliteDataProvider(db) {
|
|
16
|
+
var _this = _super.call(this, function () { return new NodeSqliteCommand(db); }, function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
|
17
|
+
return tslib_1.__generator(this, function (_a) {
|
|
18
|
+
db.close();
|
|
19
|
+
return [2 /*return*/];
|
|
20
|
+
});
|
|
21
|
+
}); }) || this;
|
|
22
|
+
return _this;
|
|
23
|
+
}
|
|
24
|
+
return NodeSqliteDataProvider;
|
|
25
|
+
}(remult_sqlite_core_js_1.SqliteCoreDataProvider));
|
|
26
|
+
exports.NodeSqliteDataProvider = NodeSqliteDataProvider;
|
|
27
|
+
var NodeSqliteCommand = /** @class */ (function () {
|
|
28
|
+
function NodeSqliteCommand(db) {
|
|
29
|
+
this.db = db;
|
|
30
|
+
this.values = {};
|
|
31
|
+
this.i = 0;
|
|
32
|
+
}
|
|
33
|
+
NodeSqliteCommand.prototype.execute = function (sql) {
|
|
34
|
+
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
35
|
+
var statement, rows;
|
|
36
|
+
return tslib_1.__generator(this, function (_a) {
|
|
37
|
+
statement = this.db.prepare(sql);
|
|
38
|
+
statement.setAllowBareNamedParameters(true);
|
|
39
|
+
rows = Object.keys(this.values).length
|
|
40
|
+
? statement.all(this.values)
|
|
41
|
+
: statement.all();
|
|
42
|
+
return [2 /*return*/, new NodeSqliteResult(rows)];
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
NodeSqliteCommand.prototype.addParameterAndReturnSqlToken = function (value) {
|
|
47
|
+
return this.param(value);
|
|
48
|
+
};
|
|
49
|
+
NodeSqliteCommand.prototype.param = function (value) {
|
|
50
|
+
if (value instanceof Date)
|
|
51
|
+
value = value.valueOf();
|
|
52
|
+
if (typeof value === 'boolean')
|
|
53
|
+
value = value ? 1 : 0;
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
value = null;
|
|
56
|
+
var key = String(this.i++);
|
|
57
|
+
this.values[key] = value;
|
|
58
|
+
return ":".concat(key);
|
|
59
|
+
};
|
|
60
|
+
return NodeSqliteCommand;
|
|
61
|
+
}());
|
|
62
|
+
var NodeSqliteResult = /** @class */ (function () {
|
|
63
|
+
function NodeSqliteResult(rows) {
|
|
64
|
+
this.rows = rows;
|
|
65
|
+
}
|
|
66
|
+
NodeSqliteResult.prototype.getColumnKeyInResultForIndexInSelect = function (index) {
|
|
67
|
+
var _a;
|
|
68
|
+
var first = this.rows[0];
|
|
69
|
+
return first ? ((_a = Object.keys(first)[index]) !== null && _a !== void 0 ? _a : '') : '';
|
|
70
|
+
};
|
|
71
|
+
return NodeSqliteResult;
|
|
72
|
+
}());
|
package/src/data-api.js
CHANGED
|
@@ -378,22 +378,25 @@ var DataApi = /** @class */ (function () {
|
|
|
378
378
|
var findOptions, orderBy, _a, _b, element, direction, group, min, max, result, minMax, _loop_1, _c, _d, element;
|
|
379
379
|
var e_3, _e, _f, _g, e_4, _h;
|
|
380
380
|
var _this = this;
|
|
381
|
-
var _j, _k, _l, _m, _o, _p;
|
|
382
|
-
return tslib_1.__generator(this, function (
|
|
383
|
-
switch (
|
|
381
|
+
var _j, _k, _l, _m, _o, _p, _q;
|
|
382
|
+
return tslib_1.__generator(this, function (_r) {
|
|
383
|
+
switch (_r.label) {
|
|
384
384
|
case 0:
|
|
385
385
|
if (!this.repository.metadata.apiReadAllowed) {
|
|
386
386
|
throw new server_action_js_1.ForbiddenError();
|
|
387
387
|
}
|
|
388
388
|
return [4 /*yield*/, this.findOptionsFromRequest(request, body)];
|
|
389
389
|
case 1:
|
|
390
|
-
findOptions =
|
|
390
|
+
findOptions = _r.sent();
|
|
391
391
|
orderBy = {};
|
|
392
392
|
if (body === null || body === void 0 ? void 0 : body.orderBy) {
|
|
393
393
|
try {
|
|
394
394
|
for (_a = tslib_1.__values(body === null || body === void 0 ? void 0 : body.orderBy), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
395
395
|
element = _b.value;
|
|
396
396
|
direction = element.isDescending ? 'desc' : 'asc';
|
|
397
|
+
if (element.operation !== 'count' &&
|
|
398
|
+
!((_j = this.repository.fields.find(element.field)) === null || _j === void 0 ? void 0 : _j.includedInApi()))
|
|
399
|
+
continue;
|
|
397
400
|
switch (element.operation) {
|
|
398
401
|
case undefined:
|
|
399
402
|
orderBy[element.field] = direction;
|
|
@@ -415,13 +418,13 @@ var DataApi = /** @class */ (function () {
|
|
|
415
418
|
finally { if (e_3) throw e_3.error; }
|
|
416
419
|
}
|
|
417
420
|
}
|
|
418
|
-
group = (
|
|
421
|
+
group = (_k = body === null || body === void 0 ? void 0 : body.groupBy) === null || _k === void 0 ? void 0 : _k.filter(function (x) {
|
|
419
422
|
return _this.repository.fields.find(x).includedInApi();
|
|
420
423
|
});
|
|
421
|
-
min = (
|
|
424
|
+
min = (_l = body === null || body === void 0 ? void 0 : body.min) === null || _l === void 0 ? void 0 : _l.filter(function (x) {
|
|
422
425
|
return _this.repository.fields.find(x).includedInApi();
|
|
423
426
|
});
|
|
424
|
-
max = (
|
|
427
|
+
max = (_m = body === null || body === void 0 ? void 0 : body.max) === null || _m === void 0 ? void 0 : _m.filter(function (x) {
|
|
425
428
|
return _this.repository.fields.find(x).includedInApi();
|
|
426
429
|
});
|
|
427
430
|
return [4 /*yield*/, this.repository.groupBy((_g = {
|
|
@@ -432,21 +435,21 @@ var DataApi = /** @class */ (function () {
|
|
|
432
435
|
//@ts-expect-error internal key
|
|
433
436
|
_g[remult3_js_1.GroupByForApiKey] = true,
|
|
434
437
|
_g.group = group,
|
|
435
|
-
_g.sum = (
|
|
438
|
+
_g.sum = (_o = body === null || body === void 0 ? void 0 : body.sum) === null || _o === void 0 ? void 0 : _o.filter(function (x) {
|
|
436
439
|
return _this.repository.fields.find(x).includedInApi();
|
|
437
440
|
}),
|
|
438
|
-
_g.avg = (
|
|
441
|
+
_g.avg = (_p = body === null || body === void 0 ? void 0 : body.avg) === null || _p === void 0 ? void 0 : _p.filter(function (x) {
|
|
439
442
|
return _this.repository.fields.find(x).includedInApi();
|
|
440
443
|
}),
|
|
441
444
|
_g.min = min,
|
|
442
445
|
_g.max = max,
|
|
443
|
-
_g.distinctCount = (
|
|
446
|
+
_g.distinctCount = (_q = body === null || body === void 0 ? void 0 : body.distinctCount) === null || _q === void 0 ? void 0 : _q.filter(function (x) {
|
|
444
447
|
return _this.repository.fields.find(x).includedInApi();
|
|
445
448
|
}),
|
|
446
449
|
_g.orderBy = orderBy,
|
|
447
450
|
_g))];
|
|
448
451
|
case 2:
|
|
449
|
-
result =
|
|
452
|
+
result = _r.sent();
|
|
450
453
|
if (group)
|
|
451
454
|
result.forEach(function (x) {
|
|
452
455
|
var e_5, _a;
|
|
@@ -243,12 +243,12 @@ var RepositoryImplementation = /** @class */ (function () {
|
|
|
243
243
|
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
|
244
244
|
var findOptions, getField, getFieldNotInGroupBy, dpOptions, key, element, operation, direction;
|
|
245
245
|
var _this = this;
|
|
246
|
-
var _a, _b, _c, _d, _e, _f;
|
|
247
|
-
return tslib_1.__generator(this, function (
|
|
248
|
-
switch (
|
|
246
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
247
|
+
return tslib_1.__generator(this, function (_h) {
|
|
248
|
+
switch (_h.label) {
|
|
249
249
|
case 0: return [4 /*yield*/, this._buildEntityDataProviderFindOptions(tslib_1.__assign({}, options))];
|
|
250
250
|
case 1:
|
|
251
|
-
findOptions =
|
|
251
|
+
findOptions = _h.sent();
|
|
252
252
|
getField = function (key) {
|
|
253
253
|
var r = _this.metadata.fields.find(key);
|
|
254
254
|
if (r === undefined)
|
|
@@ -279,10 +279,14 @@ var RepositoryImplementation = /** @class */ (function () {
|
|
|
279
279
|
element = options.orderBy[key];
|
|
280
280
|
if (element)
|
|
281
281
|
if (typeof element === 'string') {
|
|
282
|
+
// ordering by a raw column is only valid for grouped fields -
|
|
283
|
+
// skip others so behavior is consistent across data providers
|
|
284
|
+
if (key !== remult3_js_1.GroupByCountMember && !((_g = options === null || options === void 0 ? void 0 : options.group) === null || _g === void 0 ? void 0 : _g.includes(key)))
|
|
285
|
+
continue;
|
|
282
286
|
dpOptions.orderBy.push({
|
|
283
|
-
field: key ===
|
|
287
|
+
field: key === remult3_js_1.GroupByCountMember ? undefined : getField(key),
|
|
284
288
|
isDescending: element === 'desc',
|
|
285
|
-
operation: key ===
|
|
289
|
+
operation: key === remult3_js_1.GroupByCountMember ? 'count' : undefined,
|
|
286
290
|
});
|
|
287
291
|
}
|
|
288
292
|
else {
|